From 148df92c4102b472d3e919795f565bb5468bac28 Mon Sep 17 00:00:00 2001 From: Park Yun Chan Date: Sun, 25 Aug 2024 23:35:35 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EA=B8=B0=EB=A1=9D=20N?= =?UTF-8?q?OT=5FCOMPLETED=20=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=9F=AC=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EA=B8=B0=EC=A4=80=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: LocalDateTime을 기준으로 반영 * fix: endOfYesterday 변수 설정 --- .../missionRecord/application/MissionRecordService.java | 3 +-- .../missionRecord/dao/MissionRecordRepositoryImpl.java | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordService.java b/src/main/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordService.java index 3d8cf3e9..979056b1 100644 --- a/src/main/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordService.java +++ b/src/main/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordService.java @@ -47,8 +47,6 @@ public class MissionRecordService { private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - private static final LocalDateTime endOfYesterday = - LocalDate.now().minusDays(1).atTime(23, 59, 59); public MissionRecordIdResponse startMission(Long missionId) { final Member member = memberUtil.getCurrentMember(); @@ -232,6 +230,7 @@ public MissionRecordCompleteTotal getTotalMissionRecords(Long memberId) { } public void expiredMissionsToNotCompletedUpdate() { + LocalDateTime endOfYesterday = LocalDate.now().minusDays(1).atTime(23, 59, 59); missionRecordRepository.updateExpiredMissionsToNotCompleted(endOfYesterday); } } diff --git a/src/main/java/com/depromeet/stonebed/domain/missionRecord/dao/MissionRecordRepositoryImpl.java b/src/main/java/com/depromeet/stonebed/domain/missionRecord/dao/MissionRecordRepositoryImpl.java index ed40c633..5b08e206 100644 --- a/src/main/java/com/depromeet/stonebed/domain/missionRecord/dao/MissionRecordRepositoryImpl.java +++ b/src/main/java/com/depromeet/stonebed/domain/missionRecord/dao/MissionRecordRepositoryImpl.java @@ -42,15 +42,16 @@ public List findByMemberIdAndCreatedAtFromWithPagination( } @Override - public void updateExpiredMissionsToNotCompleted(LocalDateTime endOfYesterday) { + public void updateExpiredMissionsToNotCompleted(LocalDateTime currentTime) { queryFactory .update(missionRecord) .set(missionRecord.status, MissionRecordStatus.NOT_COMPLETED) + .set(missionRecord.updatedAt, LocalDateTime.now()) .where( missionRecord .status .eq(MissionRecordStatus.IN_PROGRESS) - .and(missionRecord.createdAt.before(endOfYesterday))) + .and(missionRecord.createdAt.before(currentTime))) .execute(); } From d69767a6fa2efea8e1fa68d44cfb5203819bd0e4 Mon Sep 17 00:00:00 2001 From: Park Yun Chan Date: Sun, 25 Aug 2024 23:38:20 +0900 Subject: [PATCH 2/3] =?UTF-8?q?test:=20=EB=AF=B8=EC=85=98=20=ED=83=AD?= =?UTF-8?q?=EB=B0=94=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20(#224)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MissionRecordServiceTest.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/test/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordServiceTest.java b/src/test/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordServiceTest.java index 14321952..19a2cce0 100644 --- a/src/test/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordServiceTest.java +++ b/src/test/java/com/depromeet/stonebed/domain/missionRecord/application/MissionRecordServiceTest.java @@ -7,7 +7,9 @@ import com.depromeet.stonebed.domain.fcm.application.FcmNotificationService; import com.depromeet.stonebed.domain.member.domain.Member; import com.depromeet.stonebed.domain.mission.dao.MissionRepository; +import com.depromeet.stonebed.domain.mission.domain.Mission; import com.depromeet.stonebed.domain.missionHistory.dao.MissionHistoryRepository; +import com.depromeet.stonebed.domain.missionHistory.domain.MissionHistory; import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordBoostRepository; import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordRepository; import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord; @@ -15,6 +17,7 @@ import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecordStatus; import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCalendarResponse; import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCompleteTotal; +import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionTabResponse; import com.depromeet.stonebed.global.error.ErrorCode; import com.depromeet.stonebed.global.error.exception.CustomException; import com.depromeet.stonebed.global.util.MemberUtil; @@ -259,4 +262,96 @@ class MissionRecordServiceTest extends FixtureMonkeySetUp { verify(missionRecordRepository).findById(missionRecord.getId()); verify(missionRecordBoostRepository).save(any(MissionRecordBoost.class)); } + + @Test + void 미션탭_상태_미션_완료() { + // Given + Long missionId = 1L; + Member member = fixtureMonkey.giveMeOne(Member.class); + Mission mission = fixtureMonkey.giveMeBuilder(Mission.class).set("id", missionId).sample(); + MissionHistory missionHistory = + fixtureMonkey.giveMeBuilder(MissionHistory.class).set("mission", mission).sample(); + MissionRecord missionRecord = + fixtureMonkey + .giveMeBuilder(MissionRecord.class) + .set("member", member) + .set("missionHistory", missionHistory) + .set("status", MissionRecordStatus.COMPLETED) + .sample(); + + when(memberUtil.getCurrentMember()).thenReturn(member); + when(missionRepository.findById(missionId)).thenReturn(Optional.of(mission)); + when(missionHistoryRepository.findLatestOneByMissionIdRaisePet( + missionId, mission.getRaisePet())) + .thenReturn(Optional.of(missionHistory)); + when(missionRecordRepository.findByMemberAndMissionHistory(member, missionHistory)) + .thenReturn(Optional.of(missionRecord)); + + // When + MissionTabResponse response = missionRecordService.getMissionTabStatus(missionId); + + // Then + then(response).isNotNull(); + then(response.imageUrl()).isEqualTo(missionRecord.getImageUrl()); + then(response.status()).isEqualTo(MissionRecordStatus.COMPLETED); + + verify(memberUtil).getCurrentMember(); + verify(missionRepository).findById(missionId); + verify(missionHistoryRepository) + .findLatestOneByMissionIdRaisePet(missionId, mission.getRaisePet()); + verify(missionRecordRepository).findByMemberAndMissionHistory(member, missionHistory); + } + + @Test + void 미션탭_상태_미션_진행중() { + // Given + Long missionId = 1L; + Member member = fixtureMonkey.giveMeOne(Member.class); + Mission mission = fixtureMonkey.giveMeBuilder(Mission.class).set("id", missionId).sample(); + MissionHistory missionHistory = + fixtureMonkey.giveMeBuilder(MissionHistory.class).set("mission", mission).sample(); + + when(memberUtil.getCurrentMember()).thenReturn(member); + when(missionRepository.findById(missionId)).thenReturn(Optional.of(mission)); + when(missionHistoryRepository.findLatestOneByMissionIdRaisePet( + missionId, mission.getRaisePet())) + .thenReturn(Optional.of(missionHistory)); + when(missionRecordRepository.findByMemberAndMissionHistory(member, missionHistory)) + .thenReturn(Optional.empty()); + + // When + MissionTabResponse response = missionRecordService.getMissionTabStatus(missionId); + + // Then + then(response).isNotNull(); + then(response.imageUrl()).isNull(); + then(response.status()).isEqualTo(MissionRecordStatus.NOT_COMPLETED); + + verify(memberUtil).getCurrentMember(); + verify(missionRepository).findById(missionId); + verify(missionHistoryRepository) + .findLatestOneByMissionIdRaisePet(missionId, mission.getRaisePet()); + verify(missionRecordRepository).findByMemberAndMissionHistory(member, missionHistory); + } + + @Test + void 미션탭_상태_미션_시작안함() { + // Given + Long missionId = 1L; + + when(missionRepository.findById(missionId)).thenReturn(Optional.empty()); + + // When & Then + CustomException exception = + org.junit.jupiter.api.Assertions.assertThrows( + CustomException.class, + () -> missionRecordService.getMissionTabStatus(missionId)); + + then(exception.getErrorCode()).isEqualTo(ErrorCode.MISSION_NOT_FOUND); + + verify(missionRepository).findById(missionId); + verify(missionHistoryRepository, never()) + .findLatestOneByMissionIdRaisePet(anyLong(), any()); + verify(missionRecordRepository, never()).findByMemberAndMissionHistory(any(), any()); + } } From 78d6bb79dbec07173ff44cb125a5561047827c7d Mon Sep 17 00:00:00 2001 From: yb__char <68099546+char-yb@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:20:31 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20API=20(#226)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 회원 정보 조회 API * fix: oauth Id -> oauth email로 조회 조건 변경 * fix: 테스트 코드 수정 * fix: oauth 로직 수정 --- .gitignore | 3 +++ .../domain/auth/application/AuthService.java | 9 +++++---- .../domain/auth/application/kakao/KakaoClient.java | 2 +- .../stonebed/domain/member/api/MemberController.java | 11 +++++++++-- .../domain/member/application/MemberService.java | 8 +++++++- .../stonebed/domain/member/dao/MemberRepository.java | 12 ++++++++++-- .../stonebed/domain/member/domain/Member.java | 6 ++++-- .../stonebed/domain/member/domain/OauthInfo.java | 2 +- .../domain/auth/application/AuthServiceTest.java | 9 +++------ .../domain/member/application/MemberServiceTest.java | 2 +- 10 files changed, 44 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index b5a33fa0..f9d5d2fd 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,6 @@ logs *.DS_Store /src/main/generated .*-database + +### 멀티모듈 임시 주석 ### +walwal-* diff --git a/src/main/java/com/depromeet/stonebed/domain/auth/application/AuthService.java b/src/main/java/com/depromeet/stonebed/domain/auth/application/AuthService.java index ec2e7987..5361c98f 100644 --- a/src/main/java/com/depromeet/stonebed/domain/auth/application/AuthService.java +++ b/src/main/java/com/depromeet/stonebed/domain/auth/application/AuthService.java @@ -55,8 +55,7 @@ public SocialClientResponse authenticateFromProvider(OAuthProvider provider, Str public AuthTokenResponse socialLogin( OAuthProvider oAuthProvider, String oauthId, String email) { Optional memberOptional = - memberRepository.findByOauthInfoOauthProviderAndOauthInfoOauthId( - oAuthProvider.getValue(), oauthId); + memberRepository.findByMemberOauthInfo(oAuthProvider.getValue(), email); return memberOptional .map( @@ -67,7 +66,8 @@ public AuthTokenResponse socialLogin( ? getTemporaryLoginResponse(member) : getLoginResponse(member); member.updateLastLoginAt(); - updateMemberStatus(member); + member.updateOauthId(oauthId); + updateMemberNormalStatus(member); return AuthTokenResponse.of( tokenPair, member.getRole() == MemberRole.TEMPORARY); }) @@ -132,6 +132,7 @@ public void withdraw() { validateMemberStatusDelete(member.getStatus()); member.updateMemberRole(MemberRole.TEMPORARY); member.updateProfile(Profile.createProfile("", "")); + member.updateOauthId(""); memberRepository.flush(); withdrawMemberRelationByMemberId(member.getId()); @@ -156,7 +157,7 @@ private Member registerMember(Member member, CreateMemberRequest request) { return member; } - private void updateMemberStatus(Member member) { + private void updateMemberNormalStatus(Member member) { if (member.getStatus() == MemberStatus.DELETED) { member.updateStatus(MemberStatus.NORMAL); } diff --git a/src/main/java/com/depromeet/stonebed/domain/auth/application/kakao/KakaoClient.java b/src/main/java/com/depromeet/stonebed/domain/auth/application/kakao/KakaoClient.java index 0734a876..56e09737 100644 --- a/src/main/java/com/depromeet/stonebed/domain/auth/application/kakao/KakaoClient.java +++ b/src/main/java/com/depromeet/stonebed/domain/auth/application/kakao/KakaoClient.java @@ -26,7 +26,7 @@ public SocialClientResponse authenticateFromKakao(String token) { (request, response) -> { if (!response.getStatusCode().is2xxSuccessful()) { throw new CustomException( - ErrorCode.APPLE_TOKEN_CLIENT_FAILED); + ErrorCode.KAKAO_TOKEN_CLIENT_FAILED); } return Objects.requireNonNull( response.bodyTo(KakaoAuthResponse.class)); diff --git a/src/main/java/com/depromeet/stonebed/domain/member/api/MemberController.java b/src/main/java/com/depromeet/stonebed/domain/member/api/MemberController.java index e73f5c5d..2abf384f 100644 --- a/src/main/java/com/depromeet/stonebed/domain/member/api/MemberController.java +++ b/src/main/java/com/depromeet/stonebed/domain/member/api/MemberController.java @@ -10,6 +10,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -26,8 +27,14 @@ public class MemberController { @Operation(summary = "내 정보 조회", description = "내 정보를 조회하는 API입니다.") @GetMapping("/me") - public MemberInfoResponse memberInfo() { - return memberService.findMemberInfo(); + public MemberInfoResponse memberMyInfo() { + return memberService.findMemberMyInfo(); + } + + @Operation(summary = "회원 정보 조회", description = "회원 정보를 조회하는 API입니다.") + @GetMapping("/{memberId}") + public MemberInfoResponse memberInfo(@PathVariable("memberId") Long memberId) { + return memberService.findMemberInfo(memberId); } @Operation(summary = "회원 프로필 변경", description = "회원 프로필을 변경합니다.") diff --git a/src/main/java/com/depromeet/stonebed/domain/member/application/MemberService.java b/src/main/java/com/depromeet/stonebed/domain/member/application/MemberService.java index b2d05a78..b008e4f2 100644 --- a/src/main/java/com/depromeet/stonebed/domain/member/application/MemberService.java +++ b/src/main/java/com/depromeet/stonebed/domain/member/application/MemberService.java @@ -18,11 +18,17 @@ public class MemberService { private final MemberUtil memberUtil; @Transactional(readOnly = true) - public MemberInfoResponse findMemberInfo() { + public MemberInfoResponse findMemberMyInfo() { Member currentMember = memberUtil.getCurrentMember(); return MemberInfoResponse.from(currentMember); } + @Transactional(readOnly = true) + public MemberInfoResponse findMemberInfo(Long memberId) { + Member member = memberUtil.getMemberByMemberId(memberId); + return MemberInfoResponse.from(member); + } + @Transactional(readOnly = true) public void checkNickname(NicknameCheckRequest request) { memberUtil.checkNickname(request); diff --git a/src/main/java/com/depromeet/stonebed/domain/member/dao/MemberRepository.java b/src/main/java/com/depromeet/stonebed/domain/member/dao/MemberRepository.java index b30050ca..e20ca0d0 100644 --- a/src/main/java/com/depromeet/stonebed/domain/member/dao/MemberRepository.java +++ b/src/main/java/com/depromeet/stonebed/domain/member/dao/MemberRepository.java @@ -3,8 +3,16 @@ import com.depromeet.stonebed.domain.member.domain.Member; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface MemberRepository extends JpaRepository, MemberRepositoryCustom { - Optional findByOauthInfoOauthProviderAndOauthInfoOauthId( - String oauthProvider, String oauthId); + + @Query( + "SELECT m FROM Member m WHERE m.oauthInfo.oauthProvider = :provider AND m.oauthInfo.oauthEmail = :email") + Optional findByMemberOauthInfo( + @Param("provider") String oauthProvider, @Param("email") String email); + + Optional findByOauthInfoOauthProviderAndOauthInfoOauthEmail( + String oauthProvider, String email); } diff --git a/src/main/java/com/depromeet/stonebed/domain/member/domain/Member.java b/src/main/java/com/depromeet/stonebed/domain/member/domain/Member.java index a6611c17..ab417b0e 100644 --- a/src/main/java/com/depromeet/stonebed/domain/member/domain/Member.java +++ b/src/main/java/com/depromeet/stonebed/domain/member/domain/Member.java @@ -23,13 +23,11 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.SQLRestriction; @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @SQLDelete(sql = "UPDATE member SET status = 'DELETED' WHERE member_id = ?") -@SQLRestriction("status != 'DELETED'") public class Member extends BaseTimeEntity { @Id @@ -121,4 +119,8 @@ public void updateMemberRole(MemberRole memberRole) { public void updateStatus(MemberStatus status) { this.status = status; } + + public void updateOauthId(String oauthId) { + this.oauthInfo.oauthId = oauthId; + } } diff --git a/src/main/java/com/depromeet/stonebed/domain/member/domain/OauthInfo.java b/src/main/java/com/depromeet/stonebed/domain/member/domain/OauthInfo.java index e0666410..ed5d1883 100644 --- a/src/main/java/com/depromeet/stonebed/domain/member/domain/OauthInfo.java +++ b/src/main/java/com/depromeet/stonebed/domain/member/domain/OauthInfo.java @@ -14,7 +14,7 @@ public class OauthInfo { @Schema(description = "소셜 ID", example = "123487892") - private String oauthId; + public String oauthId; @Schema(description = "소셜 제공자", example = "APPLE") private String oauthProvider; diff --git a/src/test/java/com/depromeet/stonebed/domain/auth/application/AuthServiceTest.java b/src/test/java/com/depromeet/stonebed/domain/auth/application/AuthServiceTest.java index c92f2213..66ec85c0 100644 --- a/src/test/java/com/depromeet/stonebed/domain/auth/application/AuthServiceTest.java +++ b/src/test/java/com/depromeet/stonebed/domain/auth/application/AuthServiceTest.java @@ -57,8 +57,7 @@ void setUp() { // given OAuthProvider provider = OAuthProvider.KAKAO; - when(memberRepository.findByOauthInfoOauthProviderAndOauthInfoOauthId( - provider.getValue(), oauthId)) + when(memberRepository.findByMemberOauthInfo(provider.getValue(), email)) .thenReturn(Optional.of(member)); when(jwtTokenService.generateTokenPair(member.getId(), MemberRole.USER)) .thenReturn(new TokenPairResponse("accessToken", "refreshToken")); @@ -75,8 +74,7 @@ void setUp() { // given OAuthProvider provider = OAuthProvider.APPLE; - when(memberRepository.findByOauthInfoOauthProviderAndOauthInfoOauthId( - provider.getValue(), oauthId)) + when(memberRepository.findByMemberOauthInfo(provider.getValue(), email)) .thenReturn(Optional.of(member)); when(jwtTokenService.generateTokenPair(member.getId(), MemberRole.USER)) .thenReturn(new TokenPairResponse("accessToken", "refreshToken")); @@ -95,8 +93,7 @@ void setUp() { TokenPairResponse temporaryTokenPair = new TokenPairResponse("accessToken", "refreshToken"); Member newMember = Member.createOAuthMember(provider, oauthId, email); - when(memberRepository.findByOauthInfoOauthProviderAndOauthInfoOauthId( - provider.getValue(), oauthId)) + when(memberRepository.findByMemberOauthInfo(provider.getValue(), email)) .thenReturn(Optional.empty()); when(memberRepository.save(any(Member.class))).thenReturn(newMember); when(jwtTokenService.generateTemporaryTokenPair(any(Member.class))) diff --git a/src/test/java/com/depromeet/stonebed/domain/member/application/MemberServiceTest.java b/src/test/java/com/depromeet/stonebed/domain/member/application/MemberServiceTest.java index 4253250f..7f4e8899 100644 --- a/src/test/java/com/depromeet/stonebed/domain/member/application/MemberServiceTest.java +++ b/src/test/java/com/depromeet/stonebed/domain/member/application/MemberServiceTest.java @@ -32,7 +32,7 @@ class MemberServiceTest extends FixtureMonkeySetUp { when(memberUtil.getCurrentMember()).thenReturn(member); // when - MemberInfoResponse result = memberService.findMemberInfo(); + MemberInfoResponse result = memberService.findMemberMyInfo(); // then assertNotNull(result);