diff --git a/src/main/java/dopamine/backend/backoffice/controller/ChallengeBackofficeController.java b/src/main/java/dopamine/backend/backoffice/controller/ChallengeBackofficeController.java index 1913aab..12f0f69 100644 --- a/src/main/java/dopamine/backend/backoffice/controller/ChallengeBackofficeController.java +++ b/src/main/java/dopamine/backend/backoffice/controller/ChallengeBackofficeController.java @@ -59,9 +59,7 @@ public String createForm(Model model){ public String createChallenge(ChallengeRequestDTO challengeRequestDTO, @RequestPart(value = "file", required = false) MultipartFile file){ - if(!file.isEmpty()){ - challengeRequestDTO.setImage(imageService.updateImage(file, "challenge", "image")); - } + challengeRequestDTO.setImage(imageService.updateImage(file, "challenge", "image")); challengeService.createChallenge(challengeRequestDTO); return "redirect:/backoffice/challenge"; @@ -104,9 +102,8 @@ public String editLevel(@PathVariable("challengeId") Long challengeId, ChallengeEditDTO challengeEditDTO, @RequestPart("file") MultipartFile file) { // 이미지 업로드 - if (!file.isEmpty()) { - challengeEditDTO.setImage(imageService.updateImage(file, "level", "badge")); - } + challengeEditDTO.setImage(imageService.updateImage(file, "level", "badge")); + // 레벨 수정 challengeService.editChallenge(challengeId, challengeEditDTO); return "redirect:/backoffice/challenge"; diff --git a/src/main/java/dopamine/backend/backoffice/controller/FeedBackofficeController.java b/src/main/java/dopamine/backend/backoffice/controller/FeedBackofficeController.java index b316f35..7abb351 100644 --- a/src/main/java/dopamine/backend/backoffice/controller/FeedBackofficeController.java +++ b/src/main/java/dopamine/backend/backoffice/controller/FeedBackofficeController.java @@ -34,10 +34,8 @@ public String feed(Model model) { @GetMapping("/{feedId}/delete") public String feedDelete(@PathVariable("feedId") Long feedId) { Feed feed = feedService.verifiedFeed(feedId); - feedService.deleteFeedHard(feedId); - if (feed.getFulfillYn()) { - memberService.minusMemberExp(feed.getMember(), feed.getChallenge().getChallengeLevel().getExp()); - } + feedService.deleteFeedHard(feed); + memberService.setMemberExpAndLevel(feed.getMember()); return "redirect:/backoffice/feed"; } @@ -47,11 +45,10 @@ public String feedFullfill(@PathVariable("feedId") Long feedId) { if (feedService.verifiedFeed(feedId).getFulfillYn()) { feedService.patchFeedFulfill(feedId, false); - memberService.minusMemberExp(feed.getMember(), feed.getChallenge().getChallengeLevel().getExp()); } else { feedService.patchFeedFulfill(feedId, true); - memberService.plusMemberExp(feed.getMember(), feed.getChallenge().getChallengeLevel().getExp()); } + memberService.setMemberExpAndLevel(feed.getMember()); return "redirect:/backoffice/feed"; } diff --git a/src/main/java/dopamine/backend/backoffice/controller/LevelBackofficeController.java b/src/main/java/dopamine/backend/backoffice/controller/LevelBackofficeController.java index 4fd4860..c49e390 100644 --- a/src/main/java/dopamine/backend/backoffice/controller/LevelBackofficeController.java +++ b/src/main/java/dopamine/backend/backoffice/controller/LevelBackofficeController.java @@ -78,9 +78,8 @@ public String editLevel(@PathVariable("levelId") Long levelId, LevelEditDto levelEditDto, @RequestPart("file") MultipartFile file) { // 이미지 업로드 - if (!file.isEmpty()) { - levelEditDto.setBadge(imageService.updateImage(file, "level", "badge")); - } + levelEditDto.setBadge(imageService.updateImage(file, "level", "badge")); + // 레벨 수정 levelService.editLevel(levelId, levelEditDto); return "redirect:/backoffice/level"; @@ -110,9 +109,7 @@ public String levelCreate(Model model) { public String levelCreate(LevelRequestDto levelRequestDto, @RequestPart("file") MultipartFile file) { // 이미지 업로드 - if (!file.isEmpty()) { - levelRequestDto.setBadge(imageService.updateImage(file, "level", "badge")); - } + levelRequestDto.setBadge(imageService.updateImage(file, "level", "badge")); // 레벨 생성 Level level = levelService.createLevel(levelRequestDto); diff --git a/src/main/java/dopamine/backend/backoffice/form/LevelForm.java b/src/main/java/dopamine/backend/backoffice/form/LevelForm.java deleted file mode 100644 index ab7fe0e..0000000 --- a/src/main/java/dopamine/backend/backoffice/form/LevelForm.java +++ /dev/null @@ -1,9 +0,0 @@ -package dopamine.backend.backoffice.form; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class LevelForm { -} diff --git a/src/main/java/dopamine/backend/domain/challenge/controller/ChallengeController.java b/src/main/java/dopamine/backend/domain/challenge/controller/ChallengeController.java index e1812fa..6bbb029 100644 --- a/src/main/java/dopamine/backend/domain/challenge/controller/ChallengeController.java +++ b/src/main/java/dopamine/backend/domain/challenge/controller/ChallengeController.java @@ -31,9 +31,7 @@ public class ChallengeController { @PostMapping(value = "/challenges", consumes={MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) public void createChallenge(@Valid @RequestPart(value = "request") ChallengeRequestDTO challengeRequestDTO, @RequestPart(value = "image", required = false) MultipartFile file){ - if(file != null){ - challengeRequestDTO.setImage(imageService.updateImage(file, "challenge", "image")); - } + challengeRequestDTO.setImage(imageService.updateImage(file, "challenge", "image")); challengeService.createChallenge(challengeRequestDTO); } @@ -74,9 +72,8 @@ public ChallengeResponseDTO getChallenge(@PathVariable("challengeId") Long chall @PutMapping(value = "/challenges/{challengeId}", consumes={MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) public void editChallenge(@PathVariable Long challengeId, @RequestPart(value = "request") ChallengeEditDTO challengeEditDTO, @RequestPart(value = "image", required = false) MultipartFile file){ - if(file != null){ - challengeEditDTO.setImage(imageService.updateImage(file, "challenge", "image")); - } + + challengeEditDTO.setImage(imageService.updateImage(file, "challenge", "image")); challengeService.editChallenge(challengeId, challengeEditDTO); } diff --git a/src/main/java/dopamine/backend/domain/challenge/entity/Challenge.java b/src/main/java/dopamine/backend/domain/challenge/entity/Challenge.java index 9bc8d5a..8572aae 100644 --- a/src/main/java/dopamine/backend/domain/challenge/entity/Challenge.java +++ b/src/main/java/dopamine/backend/domain/challenge/entity/Challenge.java @@ -49,7 +49,7 @@ public Challenge(String title, String subtitle, String image, String challengeGu this.challengeLevel = challengeLevel; } - public void changeChallenge(ChallengeEditDTO challengeEditDTO){ + public void changeChallenge(ChallengeEditDTO challengeEditDTO) { this.title = challengeEditDTO.getTitle(); this.subtitle = challengeEditDTO.getSubtitle(); this.image = challengeEditDTO.getImage(); diff --git a/src/main/java/dopamine/backend/domain/feed/controller/FeedController.java b/src/main/java/dopamine/backend/domain/feed/controller/FeedController.java index 4aba832..01d7f1f 100644 --- a/src/main/java/dopamine/backend/domain/feed/controller/FeedController.java +++ b/src/main/java/dopamine/backend/domain/feed/controller/FeedController.java @@ -1,11 +1,13 @@ package dopamine.backend.domain.feed.controller; +import dopamine.backend.domain.feed.entity.Feed; import dopamine.backend.domain.feed.request.FeedEditDTO; import dopamine.backend.domain.feed.request.FeedRequestDTO; import dopamine.backend.domain.feed.response.FeedResponseDTO; import dopamine.backend.domain.feed.response.FeedYearResponseDto; import dopamine.backend.domain.feed.service.FeedService; import dopamine.backend.domain.member.entity.Member; +import dopamine.backend.domain.member.service.MemberService; import dopamine.backend.global.exception.BusinessLogicException; import dopamine.backend.global.exception.ExceptionCode; import dopamine.backend.global.jwt.service.JwtService; @@ -30,6 +32,7 @@ public class FeedController { private final FeedService feedService; private final ImageService imageService; private final JwtService jwtService; + private final MemberService memberService; /** * 피드 조회 @@ -217,6 +220,8 @@ public void deleteFeed(@PathVariable Long feedId) { */ @DeleteMapping("/feeds/{feedId}/hard") public void deleteFeedHard(@PathVariable Long feedId) { - feedService.deleteFeedHard(feedId); + Feed feed = feedService.verifiedFeed(feedId); + feedService.deleteFeedHard(feed); + memberService.setMemberExpAndLevel(feed.getMember()); } } \ No newline at end of file diff --git a/src/main/java/dopamine/backend/domain/feed/repository/FeedRepository.java b/src/main/java/dopamine/backend/domain/feed/repository/FeedRepository.java index 75e4678..9216128 100644 --- a/src/main/java/dopamine/backend/domain/feed/repository/FeedRepository.java +++ b/src/main/java/dopamine/backend/domain/feed/repository/FeedRepository.java @@ -9,7 +9,7 @@ import java.util.Optional; public interface FeedRepository extends JpaRepository { - List findFeedByMemberAndDelYn(Member member, Boolean delYn); + List findFeedByMemberAndDelYnAndFulfillYn(Member member, Boolean delYn, Boolean fulfillYn); public List findFeedByMemberAndDelYnAndCreatedDateBetweenOrderByCreatedDate(Member member, Boolean delYn, LocalDateTime startDate, LocalDateTime finishDate); } diff --git a/src/main/java/dopamine/backend/domain/feed/service/FeedService.java b/src/main/java/dopamine/backend/domain/feed/service/FeedService.java index 173e45f..169fc94 100644 --- a/src/main/java/dopamine/backend/domain/feed/service/FeedService.java +++ b/src/main/java/dopamine/backend/domain/feed/service/FeedService.java @@ -97,8 +97,7 @@ public void postFeed(Member member, FeedRequestDTO feedRequestDTO) { feed.setChallenge(challenge); feed.setMember(member); setCertification(member, challenge); - int exp = feed.getChallenge().getChallengeLevel().getExp(); - memberService.plusMemberExp(member, exp); + memberService.setMemberExpAndLevel(member); feedRepository.save(feed); } @@ -141,14 +140,10 @@ public void deleteFeed(Long feedId) { /** * 피드 완전 삭제 (DB) - * - * @param feedId + * @param feed */ - public void deleteFeedHard(Long feedId) { - Feed feed = verifiedFeed(feedId); - + public void deleteFeedHard(Feed feed) { feed.deleteFromChallenge(); - feedRepository.delete(feed); } @@ -272,7 +267,7 @@ public List feedListByMemberAndYear(Member member, List members = memberRepository.findAllByLevel(level); - for(Member member : members) { - member.changeMember(null, null, null, 0, findLevelByLevelNum(1)); - } + Level levelOne = findLevelByLevelNum(1); + + // 1레벨 삭제 불가(모든 회원의 default) + if (level == levelOne) throw new BusinessLogicException(ExceptionCode.LEVEL_1_CANNOT_DELETE); + + // 레벨에 포함된 회원을 1레벨로 변경 후 삭제 + level.getMembers().forEach(member -> member.setLevel(levelOne)); levelRepository.delete(level); - orderLevelNum(); + + // levelNum 정렬 & 관련 멤버의 레벨 변경 + sortLevelNum(); allMemberLevelChange(); } @@ -85,6 +93,27 @@ public LevelResponseDto getLevel(Long levelId) { return levelResponseDto; } + /** + * GET : 레벨 디테일하게 조회 + * @param member + * @return + */ + @Transactional(readOnly = true) + public LevelDetailResponseDto getMemberDetailLevel(Member member) { + int expRange = levelRepository.findLevelByLevelNum(member.getLevel().getLevelNum() + 1).map(Level::getExp).orElse(INF) - member.getLevel().getExp(); + int expMember = levelRepository.findLevelByLevelNum(member.getLevel().getLevelNum() + 1).map(Level::getExp).orElse(INF) - member.getExp() - 1; + int expPercent = (int)Math.round((double) expMember/expRange * 100); + + return LevelDetailResponseDto.builder() + .levelId(member.getLevel().getLevelId()) + .levelNum(member.getLevel().getLevelNum()) + .name(member.getLevel().getName()) + .badge(member.getLevel().getBadge()) + .expRange(expRange) + .expMember(expMember) + .expPercent(expPercent).build(); + } + /** * UPDATE : 수정 (name, exp, badge설정 가능) * @@ -107,15 +136,22 @@ public LevelResponseDto editLevel(Long levelId, LevelEditDto levelEditDto) { } /** - * 검증 -> levelId 입력하면 관련 ChallengeMember Entity가 있는지 확인 + * 검증 -> levelId 입력하면 관련 Level Entity가 있는지 확인 * @param levelId * @return level */ + @Transactional(readOnly = true) public Level verifiedLevel(Long levelId) { Optional level = levelRepository.findById(levelId); return level.orElseThrow(() -> new BusinessLogicException(ExceptionCode.LEVEL_NOT_FOUND)); } + /** + * levelNum을 기준으로 Level Entity 찾기 + * @param levelNum + * @return Level + */ + @Transactional(readOnly = true) public Level findLevelByLevelNum(int levelNum) { Optional level = levelRepository.findLevelByLevelNum(levelNum); return level.orElseThrow(() -> new BusinessLogicException(ExceptionCode.LEVEL_NOT_FOUND)); @@ -124,6 +160,7 @@ public Level findLevelByLevelNum(int levelNum) { /** * DB에서 가장 큰 levelNum 조회 + 1 (순차적으로) */ + @Transactional(readOnly = true) public int createLevelNum(){ return levelRepository.findTopByOrderByLevelNumDesc() .map(level -> level.getLevelNum() + 1) @@ -135,6 +172,7 @@ public int createLevelNum(){ * @param levelNum * @param exp */ + @Transactional(readOnly = true) public void verifiedExp(int levelNum, int exp) { // 이전 기준 경험치보다 큰지 검증 int preExp = levelRepository.findLevelByLevelNum(levelNum - 1).map(Level::getExp).orElse(-1); @@ -152,35 +190,28 @@ public void verifiedExp(int levelNum, int exp) { /** * levelNum연속으로 이어지도록 설정(삭제시 levelNum한칸씩 앞으로) */ - public void orderLevelNum() { - List levels = levelRepository.findAllByOrderByLevelNumAsc(); - for (int i=0; i < levels.size() ; i++) { - levels.get(i).changeLevel(i+1, null, null, 0); + private void sortLevelNum() { + int levelNum = 0; + for (Level level : levelRepository.findAllByOrderByLevelNumAsc()) { + level.changeLevelNum(++levelNum); } } - public LevelDetailResponseDto memberDetailLevel(Member member) { - int expRange = levelRepository.findLevelByLevelNum(member.getLevel().getLevelNum() + 1).map(Level::getExp).orElse(INF) - member.getLevel().getExp(); - int expMember = levelRepository.findLevelByLevelNum(member.getLevel().getLevelNum() + 1).map(Level::getExp).orElse(INF) - member.getExp() - 1; - int expPercent = (int)Math.round((double) expMember/expRange * 100); - - return LevelDetailResponseDto.builder() - .levelId(member.getLevel().getLevelId()) - .levelNum(member.getLevel().getLevelNum()) - .name(member.getLevel().getName()) - .badge(member.getLevel().getBadge()) - .expRange(expRange) - .expMember(expMember) - .expPercent(expPercent).build(); + /** + * Level 변경시 모든 멤버의 레벨에 반영 + */ + private void allMemberLevelChange(){ + memberRepository.findAll().forEach(member -> member.setLevel(getMemberLevel(member.getExp()))); } - // Level 변경시 모든 멤버의 레벨에 반영 - private void allMemberLevelChange(){ - List members = memberRepository.findAll(); - for (Member member : members) { - Level level = memberService.getMemberLevel(member.getExp()); - member.changeMember(null, null, null, 0, level); - } + /** + * 경험치에 속하는 Level 반환 + * @param exp + * @return Level + */ + @Transactional(readOnly = true) + public Level getMemberLevel(int exp) { + return levelRepository.findTopByExpLessThanEqualOrderByExpDesc(exp); } } diff --git a/src/main/java/dopamine/backend/domain/member/controller/MemberController.java b/src/main/java/dopamine/backend/domain/member/controller/MemberController.java index 515c19e..c3bbc98 100644 --- a/src/main/java/dopamine/backend/domain/member/controller/MemberController.java +++ b/src/main/java/dopamine/backend/domain/member/controller/MemberController.java @@ -25,7 +25,6 @@ @RequestMapping("/api/members") @Api(tags = "멤버 API") @RequiredArgsConstructor -@Slf4j public class MemberController { private final MemberService memberService; private final MemberMapper memberMapper; @@ -33,15 +32,11 @@ public class MemberController { private final LevelService levelService; private final FeedRepository feedRepository; - - // CREATE : 생성 @PostMapping public ResponseEntity createMember(@Valid @RequestBody MemberRequestDto memberRequestDto) { Member member = memberService.createMember(memberRequestDto); MemberResponseDto memberResponseDto = memberMapper.memberToMemberResponseDto(member); - log.info("임시 accessToken"); - log.info(jwtService.getAccessToken(member)); return new ResponseEntity<>(memberResponseDto, HttpStatus.CREATED); } @@ -56,19 +51,17 @@ public void deleteMember(@RequestHeader("Authorization") String accessToken) { @GetMapping public ResponseEntity getMember(@RequestHeader("Authorization") String accessToken) { - Member member = jwtService.getMemberFromAccessToken(accessToken); // member 찾기 - - LevelDetailResponseDto levelDetailResponseDto = levelService.memberDetailLevel(member); - - int successCnt = feedRepository.findFeedByMemberAndDelYn(member, false).size(); // todo : fullfillyn default값 추가되면 수정해야함 + // member 찾기 + Member member = jwtService.getMemberFromAccessToken(accessToken); + // Response MemberDetailResponseDto response = MemberDetailResponseDto.builder() .memberId(member.getMemberId()) .kakaoId(member.getKakaoId()) .nickname(member.getNickname()) - .successCnt(successCnt) + .successCnt(feedRepository.findFeedByMemberAndDelYnAndFulfillYn(member, false, true).size()) .exp(member.getExp()) - .level(levelDetailResponseDto) + .level(levelService.getMemberDetailLevel(member)) .build(); return new ResponseEntity<>(response, HttpStatus.OK); @@ -85,11 +78,4 @@ public ResponseEntity editMember(@RequestHeader("Authorization") String accessTo return new ResponseEntity<>(response, HttpStatus.OK); } - - @GetMapping("/mypage") - public ResponseEntity returnMemberDetail(@RequestHeader("Authorization") String accessToken) { - Member member = jwtService.getMemberFromAccessToken(accessToken); - MemberResponseDto response = memberMapper.memberToMemberResponseDto(member); - return new ResponseEntity<>(response, HttpStatus.OK); - } } diff --git a/src/main/java/dopamine/backend/domain/member/entity/Member.java b/src/main/java/dopamine/backend/domain/member/entity/Member.java index d21b448..196f694 100644 --- a/src/main/java/dopamine/backend/domain/member/entity/Member.java +++ b/src/main/java/dopamine/backend/domain/member/entity/Member.java @@ -5,10 +5,7 @@ import dopamine.backend.domain.feed.entity.Feed; import dopamine.backend.domain.feedLike.entity.FeedLike; import dopamine.backend.domain.level.entity.Level; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import javax.persistence.*; import java.time.LocalDateTime; @@ -60,12 +57,8 @@ public class Member extends BaseEntity { */ @Builder - public Member(String kakaoId, String nickname, String refreshToken, int exp, Level level) { + public Member(String kakaoId) { this.kakaoId = kakaoId; - this.nickname = nickname; - this.refreshToken = refreshToken; - this.exp = exp; - setLevel(level); } /** @@ -76,16 +69,33 @@ public Member(String kakaoId, String nickname, String refreshToken, int exp, Lev * @param exp * @param level */ - public void changeMember(String kakaoId, String nickname, String refreshToken, int exp, Level level) { + public void changeMember(String kakaoId, String nickname, String refreshToken) { this.kakaoId = Optional.ofNullable(kakaoId).orElse(this.kakaoId); this.nickname = Optional.ofNullable(nickname).orElse(this.nickname); this.refreshToken = Optional.ofNullable(refreshToken).orElse(this.refreshToken); - this.exp = (exp != 0) ? exp : this.exp; + } + + // == 비즈니스 로직 == // + /** + * exp와 level 변경 + * @param exp + * @param level + */ + public void setExpAndLevel(int exp, Level level) { + this.exp = exp; setLevel(level); } + /** + * RefreshDate 변경 + * @param localDateTime + */ + public void setChallengeRefreshDate(LocalDateTime localDateTime){ + challengeRefreshDate = localDateTime; + } + // == 연관관계 편의 메소드 == // - private void setLevel(Level level) { + public void setLevel(Level level) { if (this.level != null) { if (this.level.getMembers().contains(this)) { this.level.getMembers().remove(this); @@ -94,8 +104,4 @@ private void setLevel(Level level) { this.level = Optional.ofNullable(level).orElse(this.level); this.level.getMembers().add(this); } - - public void setChallengeRefreshDate(LocalDateTime localDateTime){ - challengeRefreshDate = localDateTime; - } } \ No newline at end of file diff --git a/src/main/java/dopamine/backend/domain/member/request/MemberRequestDto.java b/src/main/java/dopamine/backend/domain/member/request/MemberRequestDto.java index 6e2f2ee..5901631 100644 --- a/src/main/java/dopamine/backend/domain/member/request/MemberRequestDto.java +++ b/src/main/java/dopamine/backend/domain/member/request/MemberRequestDto.java @@ -10,14 +10,5 @@ @NoArgsConstructor @AllArgsConstructor public class MemberRequestDto { - private String kakaoId; - - @Pattern(regexp = "^[ㄱ-ㅎ가-힣a-zA-Z0-9-_ ]{2,10}$", message = "닉네임은 특수문자를 제외한 2~10자리여야 합니다.") - private String nickname; - - private String refreshToken; - - private int exp; - } diff --git a/src/main/java/dopamine/backend/domain/member/service/MemberService.java b/src/main/java/dopamine/backend/domain/member/service/MemberService.java index 16df097..9e619d2 100644 --- a/src/main/java/dopamine/backend/domain/member/service/MemberService.java +++ b/src/main/java/dopamine/backend/domain/member/service/MemberService.java @@ -1,5 +1,6 @@ package dopamine.backend.domain.member.service; +import dopamine.backend.domain.feed.entity.Feed; import dopamine.backend.global.exception.BusinessLogicException; import dopamine.backend.global.exception.ExceptionCode; import dopamine.backend.domain.level.repository.LevelRepository; @@ -20,57 +21,33 @@ @Service @AllArgsConstructor @Transactional -@Slf4j public class MemberService { private final MemberRepository memberRepository; - private final MemberMapper memberMapper; private final LevelRepository levelRepository; /** - * CREATE : 생성 + * kakaoId를 가진 Member가 없으면 새로운 Member생성, 아니면 기존 Member반환 * - * @param memberRequestDto + * @param kakaoId + * @return */ - public Member createMember(MemberRequestDto memberRequestDto) { - // 닉네임 중복 검사 - checkNicknameDuplication(null, memberRequestDto.getNickname()); - - // exp에 해당하는 레벨 생성 - Level level = getMemberLevel(memberRequestDto.getExp()); - - // member 생성 - Member member = Member.builder() - .kakaoId(memberRequestDto.getKakaoId()) // kakaoId - .nickname(memberRequestDto.getNickname()) // nickname - .refreshToken(memberRequestDto.getRefreshToken()) // refreshToken - .level(level) // level - .exp(memberRequestDto.getExp()).build(); // exp - - memberRepository.save(member); - - return member; + public Member findMemberByKakaoId(String kakaoId) { + return memberRepository.findMemberByKakaoId(kakaoId).orElseGet(() -> createMember(MemberRequestDto.builder() + .kakaoId(kakaoId) + .build())); } /** - * DELETE : 삭제 + * CREATE : 생성 * - * @param member + * @param memberRequestDto */ - public void deleteMember(Member member) { - memberRepository.delete(member); - } + public Member createMember(MemberRequestDto memberRequestDto) { - /** - * GET : 조회 - * - * @param memberId - * @return memberResponseDto - */ - @Transactional(readOnly = true) - public MemberResponseDto getMember(Long memberId) { - Member member = verifiedMember(memberId); - MemberResponseDto memberResponseDto = memberMapper.memberToMemberResponseDto(member); - return memberResponseDto; + Member member = Member.builder().kakaoId(memberRequestDto.getKakaoId()).build(); // member 생성 + setMemberExpAndLevel(member); // 경험치 설정 + + return memberRepository.save(member); } /** @@ -85,65 +62,38 @@ public Member editMember(Member member, MemberEditDto memberEditDto) { // 닉네임 중복 검사 checkNicknameDuplication(member, memberEditDto.getNickname()); - // exp에 해당하는 레벨 생성 - Level level = member.getLevel(); - if (memberEditDto.getExp() != 0) { - level = getMemberLevel(memberEditDto.getExp()); - } - // member 수정 - member.changeMember( - memberEditDto.getKakaoId(), // kakaoId - memberEditDto.getNickname(), // nickname - memberEditDto.getRefreshToken(), // refreshToken - memberEditDto.getExp(), // exp - level // level - ); + member.changeMember(memberEditDto.getKakaoId(), memberEditDto.getNickname(), memberEditDto.getRefreshToken()); + setMemberExpAndLevel(member); return member; } /** - * 검증 -> memberId 입력하면 관련 Member Entity가 있는지 확인 + * DELETE : 삭제 * - * @param memberId - * @return member + * @param member */ - - public Member verifiedMember(Long memberId) { - Optional member = memberRepository.findById(memberId); - return member.orElseThrow(() -> new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND)); + public void deleteMember(Member member) { + memberRepository.delete(member); } - //== jwt 인증 부분==// /** - * kakaoId를 가진 Member가 없으면 새로운 Member생성, 아니면 기존 Member반환 - * - * @param kakaoId - * @return - */ - public Member findMemberByKakaoId(String kakaoId) { - return memberRepository.findMemberByKakaoId(kakaoId).orElseGet(() -> createMember(MemberRequestDto.builder() - .kakaoId(kakaoId) - .build())); - } - - /** - * 닉네임 중복 검사

- * 1. 기존 사용자 정보이면, 중복 검사 진행 X

- * 2. nickname 값이 입력되어 있으면, 중복 검사 진행 + * 닉네임 중복 검사 * * @param member * @param nickname */ + @Transactional(readOnly = true) public void checkNicknameDuplication(Member member, String nickname) { + // 기존 사용자 정보이면 중복 검사 진행x if (member != null && member.getNickname() != null) { if (member.getNickname().equals(nickname)) { return; } } - + // nickname 값이 입력되어 있으면, 중복 검사 진행 if (nickname != null) { memberRepository.findMemberByNickname(nickname).ifPresent(a -> { throw new BusinessLogicException(ExceptionCode.NICKNAME_DUPLICATE); @@ -152,39 +102,32 @@ public void checkNicknameDuplication(Member member, String nickname) { } /** - * exp에 해당하는 Level 반환 - * - * @param exp - * @return Level + * member의 Feed에 따라 exp와 Level변경 + * @param member */ - public Level getMemberLevel(int exp) { - return levelRepository.findTopByExpLessThanEqualOrderByExpDesc(exp); - } + public void setMemberExpAndLevel(Member member) { + int exp = 0; + // 사용자의 Feed를 기준으로 exp 계산 + for (Feed f : member.getFeeds()) { + if (!f.getFulfillYn()) continue; + exp += f.getChallenge().getChallengeLevel().getExp(); + } - /** - * Member의 exp 증가 - * - * @param member - * @param exp - */ - public void plusMemberExp(Member member, int exp) { - exp = member.getExp() + exp; - Level level = getMemberLevel(exp); - member.changeMember(null, null, null, exp, level); + // exp와 level 변경 + member.setExpAndLevel(exp, levelRepository.findTopByExpLessThanEqualOrderByExpDesc(exp)); } + /** - * Member의 exp 감소 + * 검증 -> memberId 입력하면 관련 Member Entity가 있는지 확인 * - * @param member - * @param exp + * @param memberId + * @return member */ - public void minusMemberExp(Member member, int exp) { - if (member.getExp() >= exp) { - exp = member.getExp() - exp; - Level level = getMemberLevel(exp); - member.changeMember(null, null, null, exp, level); - } + @Transactional(readOnly = true) + public Member verifiedMember(Long memberId) { + Optional member = memberRepository.findById(memberId); + return member.orElseThrow(() -> new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND)); } } \ No newline at end of file diff --git a/src/main/java/dopamine/backend/global/exception/ExceptionCode.java b/src/main/java/dopamine/backend/global/exception/ExceptionCode.java index 6702939..fa3895f 100644 --- a/src/main/java/dopamine/backend/global/exception/ExceptionCode.java +++ b/src/main/java/dopamine/backend/global/exception/ExceptionCode.java @@ -16,7 +16,7 @@ public enum ExceptionCode { MISSING_YEAR_REQUEST_PARAM(400, "필수 파라미터(year)를 작성해야 합니다."), MISSING_REDIRECT_REQUEST_PARAM(400, "필수 파라미터(redirect_url)를 작성해야 합니다."), CHALLENGE_ALREADY_CERTIFIED(400, "이미 완료한 챌린지입니다."), - + LEVEL_1_CANNOT_DELETE(400, "1레벨은 삭제할 수 없습니다."), EXP_MIN_NOT_VALID(400, "레벨 경험치는 이전 레벨보다 높은 기준으로 설정해주세요."), EXP_MAX_NOT_VALID(400, "레벨 경험치는 이후 레벨보다 낮은 기준으로 설정해주세요."), LOGOUT_MEMBER(400, "이미 로그아웃한 유저입니다."), diff --git a/src/main/java/dopamine/backend/global/s3/service/ImageService.java b/src/main/java/dopamine/backend/global/s3/service/ImageService.java index d9bf047..75e1acf 100644 --- a/src/main/java/dopamine/backend/global/s3/service/ImageService.java +++ b/src/main/java/dopamine/backend/global/s3/service/ImageService.java @@ -29,6 +29,8 @@ public class ImageService { public String updateImage(MultipartFile file, String entityName, String columnName) { + if (file.isEmpty()) return null; + // File Path 설정 String uploadFilePath = entityName + "/" + columnName; // 엔티티명.컬럼명 폴더가 만들어짐