From a9281ab026c87069c8cb2452ec770fbc13967b41 Mon Sep 17 00:00:00 2001 From: NAM GIBEOM Date: Wed, 1 Nov 2023 00:36:56 +0900 Subject: [PATCH] Revert "hotfix v1.3.0" --- src/lombok.config | 1 + .../auth/controller/LoginController.java | 22 +-- .../dto/request/LogoutFcmTokenRequest.java | 10 ++ .../service/DefaultOauthLoginService.java | 6 +- .../auth/service/OauthLoginService.java | 2 +- .../bloodsugar/document/BloodSugarGuide.java | 22 +++ .../BloodSugarGuideGenerateService.java | 45 ++++- .../common/service/GuideGenerateService.java | 4 + .../guide/common/service/GuideService.java | 23 ++- .../exercise/document/ExerciseGuide.java | 28 ++- .../service/ExerciseGuideGenerateService.java | 33 +++- .../service/WeightGuideGenerateService.java | 17 ++ .../controller/HealthMetricController.java | 19 +- .../service/HealthMetricRegisterService.java | 18 +- .../intro/controller/IntroController.java | 16 -- .../intro/controller/ProdIntroController.java | 28 --- .../intro/controller/TestIntroController.java | 29 --- .../domain/intro/dto/IntroResponse.java | 14 -- .../dangjang/domain/intro/dto/Version.java | 13 -- .../domain/intro/service/IntroService.java | 48 ----- .../domain/notification/entity/FcmId.java | 29 +++ .../notification/entity/UserFcmToken.java | 46 +++-- .../mapper/NotificationMapper.java | 9 +- .../repository/UserFcmTokenRepository.java | 22 ++- .../service/NotificationService.java | 41 ++++- .../user/controller/SignupController.java | 9 +- .../user/controller/UserController.java | 16 +- .../user/dto/request/PostFcmTokenRequest.java | 13 ++ .../user/service/UserSignupService.java | 6 +- .../version/controller/VersionController.java | 52 ++++++ .../version/dto/request/VersionRequest.java | 14 ++ .../version/dto/response/VersionResponse.java | 18 ++ .../domain/version/entity/Version.java | 38 ++++ .../version/repository/VersionRepository.java | 22 +++ .../version/service/VersionService.java | 69 ++++++++ src/main/resources/config | 2 +- src/main/resources/data-dev.sql | 17 +- src/main/resources/schema-dev.sql | 34 ++-- .../auth/controller/LoginControllerTest.java | 10 +- .../auth/service/OauthLoginServiceTest.java | 11 +- .../BloodSugarGuideGenerateServiceTest.java | 39 ++++ .../ExerciseGuideGenerateServiceTest.java | 60 ++++++- .../WeightGuideGenerateServiceTest.java | 20 +++ .../HealthMetricControllerTest.java | 68 ++++++- .../HealthMetricRegisterServiceTest.java | 53 ++++-- .../intro/controller/IntroControllerTest.java | 87 --------- .../intro/service/IntroServiceTest.java | 54 ------ .../service/NotificationServiceTest.java | 29 ++- .../service/SchedulerServiceTest.java | 3 +- .../user/controller/SignupControllerTest.java | 30 ++-- .../user/controller/UserControllerTest.java | 14 -- .../user/service/UserSignupServiceTest.java | 9 +- .../controller/VersionControllerTest.java | 124 +++++++++++++ .../repository/VersionRepositoryTest.java | 43 +++++ .../version/service/VersionServiceTest.java | 72 ++++++++ .../dangjang/fixture/GuideFixture.java | 13 +- .../dangjang/fixture/NotificationFixture.java | 11 +- .../dangjang/fixture/VersionFixture.java | 42 +++++ .../dangjang/support/ControllerTest.java | 9 +- .../dangjang/support/SimpleMockMvc.java | 9 + src/test/resources/config/application.yml | 9 +- src/test/resources/schema.sql | 167 +----------------- 62 files changed, 1196 insertions(+), 645 deletions(-) create mode 100644 src/lombok.config create mode 100644 src/main/java/com/coniverse/dangjang/domain/auth/dto/request/LogoutFcmTokenRequest.java delete mode 100644 src/main/java/com/coniverse/dangjang/domain/intro/controller/IntroController.java delete mode 100644 src/main/java/com/coniverse/dangjang/domain/intro/controller/ProdIntroController.java delete mode 100644 src/main/java/com/coniverse/dangjang/domain/intro/controller/TestIntroController.java delete mode 100644 src/main/java/com/coniverse/dangjang/domain/intro/dto/IntroResponse.java delete mode 100644 src/main/java/com/coniverse/dangjang/domain/intro/dto/Version.java delete mode 100644 src/main/java/com/coniverse/dangjang/domain/intro/service/IntroService.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/notification/entity/FcmId.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/user/dto/request/PostFcmTokenRequest.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/version/controller/VersionController.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/version/dto/request/VersionRequest.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/version/dto/response/VersionResponse.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/version/entity/Version.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/version/repository/VersionRepository.java create mode 100644 src/main/java/com/coniverse/dangjang/domain/version/service/VersionService.java delete mode 100644 src/test/java/com/coniverse/dangjang/domain/intro/controller/IntroControllerTest.java delete mode 100644 src/test/java/com/coniverse/dangjang/domain/intro/service/IntroServiceTest.java create mode 100644 src/test/java/com/coniverse/dangjang/domain/version/controller/VersionControllerTest.java create mode 100644 src/test/java/com/coniverse/dangjang/domain/version/repository/VersionRepositoryTest.java create mode 100644 src/test/java/com/coniverse/dangjang/domain/version/service/VersionServiceTest.java create mode 100644 src/test/java/com/coniverse/dangjang/fixture/VersionFixture.java mode change 100644 => 120000 src/test/resources/schema.sql diff --git a/src/lombok.config b/src/lombok.config new file mode 100644 index 00000000..2c6905d7 --- /dev/null +++ b/src/lombok.config @@ -0,0 +1 @@ +lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Value diff --git a/src/main/java/com/coniverse/dangjang/domain/auth/controller/LoginController.java b/src/main/java/com/coniverse/dangjang/domain/auth/controller/LoginController.java index ddd3cd8a..57b4ea4e 100644 --- a/src/main/java/com/coniverse/dangjang/domain/auth/controller/LoginController.java +++ b/src/main/java/com/coniverse/dangjang/domain/auth/controller/LoginController.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.RestController; import com.coniverse.dangjang.domain.auth.dto.request.KakaoLoginRequest; +import com.coniverse.dangjang.domain.auth.dto.request.LogoutFcmTokenRequest; import com.coniverse.dangjang.domain.auth.dto.request.NaverLoginRequest; import com.coniverse.dangjang.domain.auth.dto.response.LoginResponse; import com.coniverse.dangjang.domain.auth.service.OauthLoginService; @@ -34,14 +35,13 @@ public class LoginController { private static String headerKeyAuthorization = "Authorization"; /** - * @param params 카카오 accessToken - * @param request request에서 fcmToken header가 필요 + * @param params 카카오 accessToken * @return ResponseEntity 로그인을 성공하면, JWT TOKEN과 사용자 정보(nickname, auth id)를 전달한다. * @since 1.0.0 */ @PostMapping("/kakao") - public ResponseEntity> loginKakao(@Valid @RequestBody KakaoLoginRequest params, HttpServletRequest request) { - LoginResponse loginResponse = oauthLoginService.login(params, request.getHeader(headerKeyFcmToken)); + public ResponseEntity> loginKakao(@Valid @RequestBody KakaoLoginRequest params) { + LoginResponse loginResponse = oauthLoginService.login(params); String accessToken = oauthLoginService.getAuthToken(loginResponse.nickname()); return ResponseEntity.ok() .header(headerKeyAccessToken.toString(), accessToken) @@ -49,14 +49,13 @@ public ResponseEntity> loginKakao(@Valid @R } /** - * @param params 네이버 accessToken - * @param request request에서 fcmToken header가 필요 + * @param params 네이버 accessToken * @return ResponseEntity 로그인을 성공하면, JWT TOKEN과 사용자 정보(nickname, auth id)를 전달한다. * @since 1.0.0 */ @PostMapping("/naver") - public ResponseEntity> loginNaver(@Valid @RequestBody NaverLoginRequest params, HttpServletRequest request) { - LoginResponse loginResponse = oauthLoginService.login(params, request.getHeader(headerKeyFcmToken)); + public ResponseEntity> loginNaver(@Valid @RequestBody NaverLoginRequest params) { + LoginResponse loginResponse = oauthLoginService.login(params); String accessToken = oauthLoginService.getAuthToken(loginResponse.nickname()); return ResponseEntity.ok() .header(headerKeyAccessToken, accessToken) @@ -81,12 +80,13 @@ public ResponseEntity> reissue(HttpServletRequest reque /** * 로그아웃 * - * @param request 요청 + * @param request HttpServletRequest oauthId + * @param logoutFcmTokenRequest fcmToken * @since 1.1.0 */ @PostMapping("/logout") - public ResponseEntity logout(HttpServletRequest request) { - oauthLoginService.logout(request.getHeader(headerKeyAuthorization), request.getHeader(headerKeyFcmToken)); + public ResponseEntity logout(HttpServletRequest request, @RequestBody LogoutFcmTokenRequest logoutFcmTokenRequest) { + oauthLoginService.logout(request.getHeader(headerKeyAuthorization), logoutFcmTokenRequest.fcmToken()); return ResponseEntity.ok() .body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), null)); } diff --git a/src/main/java/com/coniverse/dangjang/domain/auth/dto/request/LogoutFcmTokenRequest.java b/src/main/java/com/coniverse/dangjang/domain/auth/dto/request/LogoutFcmTokenRequest.java new file mode 100644 index 00000000..4ac4c4ee --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/auth/dto/request/LogoutFcmTokenRequest.java @@ -0,0 +1,10 @@ +package com.coniverse.dangjang.domain.auth.dto.request; + +/** + * fcmToken을 받아오는 DTO + * + * @author EVE + * @since 1.3.0 + */ +public record LogoutFcmTokenRequest(String fcmToken) { +} diff --git a/src/main/java/com/coniverse/dangjang/domain/auth/service/DefaultOauthLoginService.java b/src/main/java/com/coniverse/dangjang/domain/auth/service/DefaultOauthLoginService.java index ff5aa92e..f96f178f 100644 --- a/src/main/java/com/coniverse/dangjang/domain/auth/service/DefaultOauthLoginService.java +++ b/src/main/java/com/coniverse/dangjang/domain/auth/service/DefaultOauthLoginService.java @@ -73,16 +73,14 @@ public DefaultOauthLoginService(AuthTokenGenerator authTokenGenerator, UserSearc } /** - * @param params 카카오,네이버 accessToken - * @param fcmToken notifiaction 디바이스 토큰 + * @param params 카카오,네이버 accessToken * @return Content 로그인을 성공하면, JWT TOKEN과 사용자 정보(nickname, authID)를 전달한다. * @since 1.0.0 */ @Override - public LoginResponse login(OauthLoginRequest params, String fcmToken) { + public LoginResponse login(OauthLoginRequest params) { OAuthInfoResponse oAuthInfoResponse = request(params); User user = userSearchService.findUserByOauthId(oAuthInfoResponse.getOauthId()); - notificationService.saveFcmToken(fcmToken, user.getOauthId()); HealthConnect healthConnect = userSearchService.findInterlockHealthConnect(user.getOauthId()); user.verifyActiveUser(); return new LoginResponse(user.getNickname(), false, healthConnect.isConnecting()); diff --git a/src/main/java/com/coniverse/dangjang/domain/auth/service/OauthLoginService.java b/src/main/java/com/coniverse/dangjang/domain/auth/service/OauthLoginService.java index 3dea0c02..4e9ce9f0 100644 --- a/src/main/java/com/coniverse/dangjang/domain/auth/service/OauthLoginService.java +++ b/src/main/java/com/coniverse/dangjang/domain/auth/service/OauthLoginService.java @@ -9,7 +9,7 @@ * @since 1.0.0 */ public interface OauthLoginService { - LoginResponse login(OauthLoginRequest params, String fcmToken); + LoginResponse login(OauthLoginRequest params); String getAuthToken(String nickname); diff --git a/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/document/BloodSugarGuide.java b/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/document/BloodSugarGuide.java index 9530448c..00b02fa0 100644 --- a/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/document/BloodSugarGuide.java +++ b/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/document/BloodSugarGuide.java @@ -166,4 +166,26 @@ private void minusAlertCount(String alert) { .findFirst() .ifPresent(TodayGuide::minusCount); } + + /** + * 서브 가이드를 삭제한다. + * + * @param type 서브 가이드 타입 + * @since 1.3.0 + */ + public void removeSubGuide(CommonCode type) { + SubGuide subGuide = getSubGuide(type); + this.subGuides.remove(subGuide); + minusAlertCount(subGuide.getAlert()); + } + + /** + * 서브 가이드가 존재하는지 확인한다. + * + * @return 서브 가이드가 존재하면 true, 존재하지 않으면 false + * @since 1.3.0 + */ + public boolean existsSubGuide() { + return !this.subGuides.isEmpty(); + } } diff --git a/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateService.java b/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateService.java index b06571d6..b212da5b 100644 --- a/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateService.java +++ b/src/main/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateService.java @@ -1,5 +1,7 @@ package com.coniverse.dangjang.domain.guide.bloodsugar.service; +import java.time.LocalDate; + import org.springframework.stereotype.Service; import com.coniverse.dangjang.domain.analysis.dto.AnalysisData; @@ -34,8 +36,6 @@ public class BloodSugarGuideGenerateService implements GuideGenerateService { /** * 서브 가이드를 생성해서 혈당 가이드에 저장한다. - *

- * 혈당 가이드가 존재하면 새로운 서브 가이드를 추가하고, 존재하지 않으면 혈당 가이드를 생성하여 서브 가이드를 추가한다. * * @param analysisData 혈당 분석 데이터 * @return 서브 가이드 응답 @@ -44,12 +44,7 @@ public class BloodSugarGuideGenerateService implements GuideGenerateService { @Override public GuideResponse createGuide(AnalysisData analysisData) { BloodSugarAnalysisData data = (BloodSugarAnalysisData)analysisData; - BloodSugarGuide guide; - try { - guide = bloodSugarGuideSearchService.findByUserIdAndCreatedAt(data.getOauthId(), data.getCreatedAt()); - } catch (GuideNotFoundException e) { - guide = mapper.toDocument(data); - } + BloodSugarGuide guide = getGuide(data); GuideFormat guideFormat = bloodSugarGuideFormatFactory.createGuideFormat(data); SubGuide subGuide = mapper.toSubGuide(data, guideFormat); guide.addSubGuide(subGuide); @@ -57,6 +52,21 @@ public GuideResponse createGuide(AnalysisData analysisData) { return mapper.toSubGuideResponse(subGuide, guide.getTodayGuides()); } + /** + * 혈당 가이드가 존재하면 그대로 반환하고, 존재하지 않으면 새로 생성해서 반환한다. + * + * @param data 혈당 분석 데이터 + * @return 혈당 가이드 + * @since 1.3.0 + */ + private BloodSugarGuide getGuide(BloodSugarAnalysisData data) { + try { + return bloodSugarGuideSearchService.findByUserIdAndCreatedAt(data.getOauthId(), data.getCreatedAt()); + } catch (GuideNotFoundException e) { + return mapper.toDocument(data); + } + } + /** * 단위가 변경된 서브 가이드를 업데이트해서 혈당 가이드에 저장한다. * @@ -97,6 +107,25 @@ public GuideResponse updateGuideWithType(AnalysisData analysisData, CommonCode p return mapper.toSubGuideResponse(subGuide, guide.getTodayGuides()); } + /** + * 서브 가이드를 삭제한다. 서브 가이드가 존재하지 않으면 혈당 가이드를 삭제한다. + * + * @param oauthId 유저 PK + * @param createdAt 생성일자 + * @param type 타입 + * @since 1.3.0 + */ + @Override + public void removeGuide(String oauthId, LocalDate createdAt, CommonCode type) { + BloodSugarGuide guide = bloodSugarGuideSearchService.findByUserIdAndCreatedAt(oauthId, createdAt); + guide.removeSubGuide(type); + if (guide.existsSubGuide()) { + bloodSugarGuideRepository.save(guide); + return; + } + bloodSugarGuideRepository.delete(guide); + } + @Override public GroupCode getGroupCode() { return GroupCode.BLOOD_SUGAR; diff --git a/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideGenerateService.java b/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideGenerateService.java index 80f3ee86..c5f6e4ba 100644 --- a/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideGenerateService.java +++ b/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideGenerateService.java @@ -1,5 +1,7 @@ package com.coniverse.dangjang.domain.guide.common.service; +import java.time.LocalDate; + import com.coniverse.dangjang.domain.analysis.dto.AnalysisData; import com.coniverse.dangjang.domain.code.enums.CommonCode; import com.coniverse.dangjang.domain.code.enums.GroupCode; @@ -20,5 +22,7 @@ default GuideResponse updateGuideWithType(AnalysisData analysisData, CommonCode throw new UnsupportedOperationException("잘못된 메서드 호출입니다."); } + void removeGuide(String oauthId, LocalDate createdAt, CommonCode type); + GroupCode getGroupCode(); } diff --git a/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideService.java b/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideService.java index 3cfcb608..7708061a 100644 --- a/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideService.java +++ b/src/main/java/com/coniverse/dangjang/domain/guide/common/service/GuideService.java @@ -1,5 +1,6 @@ package com.coniverse.dangjang.domain.guide.common.service; +import java.time.LocalDate; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -34,8 +35,7 @@ public GuideService(List guideGenerateServiceMap) { * @since 1.0.0 */ public GuideResponse createGuide(AnalysisData analysisData) { - GroupCode groupCode = GroupCode.findByCode(analysisData.getType()); - GuideGenerateService guideGenerateService = findGuideGenerateService(groupCode); + GuideGenerateService guideGenerateService = findGuideGenerateService(analysisData.getType()); return guideGenerateService.createGuide(analysisData); } @@ -45,8 +45,7 @@ public GuideResponse createGuide(AnalysisData analysisData) { * @since 1.0.0 */ public GuideResponse updateGuide(AnalysisData analysisData) { - GroupCode groupCode = GroupCode.findByCode(analysisData.getType()); - GuideGenerateService guideGenerateService = findGuideGenerateService(groupCode); + GuideGenerateService guideGenerateService = findGuideGenerateService(analysisData.getType()); return guideGenerateService.updateGuide(analysisData); } @@ -56,18 +55,28 @@ public GuideResponse updateGuide(AnalysisData analysisData) { * @since 1.0.0 */ public GuideResponse updateGuideWithType(AnalysisData analysisData, CommonCode prevType) { - GroupCode groupCode = GroupCode.findByCode(analysisData.getType()); - GuideGenerateService guideGenerateService = findGuideGenerateService(groupCode); + GuideGenerateService guideGenerateService = findGuideGenerateService(analysisData.getType()); return guideGenerateService.updateGuideWithType(analysisData, prevType); } + /** + * 가이드를 삭제한다. + * + * @since 1.3.0 + */ + public void removeGuide(String oauthId, LocalDate createdAt, CommonCode type) { + GuideGenerateService guideGenerateService = findGuideGenerateService(type); + guideGenerateService.removeGuide(oauthId, createdAt, type); + } + /** * 그룹코드로 가이드 생성 서비스를 찾는다. * * @see GroupCode * @since 1.0.0 */ - private GuideGenerateService findGuideGenerateService(GroupCode groupCode) { + private GuideGenerateService findGuideGenerateService(CommonCode type) { + GroupCode groupCode = GroupCode.findByCode(type); return guideGenerateServiceMap.get(groupCode); } } diff --git a/src/main/java/com/coniverse/dangjang/domain/guide/exercise/document/ExerciseGuide.java b/src/main/java/com/coniverse/dangjang/domain/guide/exercise/document/ExerciseGuide.java index d1d7d8ec..5492d969 100644 --- a/src/main/java/com/coniverse/dangjang/domain/guide/exercise/document/ExerciseGuide.java +++ b/src/main/java/com/coniverse/dangjang/domain/guide/exercise/document/ExerciseGuide.java @@ -6,11 +6,12 @@ import org.springframework.data.mongodb.core.mapping.Document; +import com.coniverse.dangjang.domain.code.enums.CommonCode; + import jakarta.persistence.Id; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; /** * 운동 가이드 Document @@ -18,15 +19,14 @@ * @author EVE * @since 1.0.0 */ -@Setter @Getter @Document @NoArgsConstructor -public class ExerciseGuide { +public class ExerciseGuide { // TODO 걸음 가이드, 칼로리 가이드로 분리해서 리팩토링 @Id private String id; private String oauthId; - private int needStepByTTS; + private int needStepByTTS; // TODO 걸음 수 관련 필드 -> 객체로 묶기 private int needStepByLastWeek; private LocalDate createdAt; private String content; @@ -69,14 +69,24 @@ public void changeAboutWalk(int needStepByTTS, int needStepByLastWeek, String co *

* 기존에 존재하는 운동 칼로리를 삭제하고, 새로운 운동 칼로리를 추가한다. * - * @param updateExerciseCalorie 운동칼로리 객체 + * @param updatedExerciseCalorie 운동칼로리 객체 * @since 1.0.0 */ - public void changeExerciseCalories(ExerciseCalorie updateExerciseCalorie) { + public void changeExerciseCalories(ExerciseCalorie updatedExerciseCalorie) { + removeExerciseCalorie(updatedExerciseCalorie.type()); + exerciseCalories.add(updatedExerciseCalorie); + } + + /** + * 운동 칼로리를 삭제한다. + * + * @param type 운동 타입 + * @since 1.3.0 + */ + public void removeExerciseCalorie(CommonCode type) { exerciseCalories.stream() - .filter(existExerciseCalorie -> existExerciseCalorie.type().equals(updateExerciseCalorie.type())) + .filter(exerciseCalorie -> exerciseCalorie.type().equals(type)) .findFirst() - .ifPresent(existExerciseCalorie -> exerciseCalories.remove(existExerciseCalorie)); - exerciseCalories.add(updateExerciseCalorie); + .ifPresent(exerciseCalorie -> exerciseCalories.remove(exerciseCalorie)); } } diff --git a/src/main/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateService.java b/src/main/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateService.java index 9f3feb26..792728c6 100644 --- a/src/main/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateService.java +++ b/src/main/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateService.java @@ -1,5 +1,6 @@ package com.coniverse.dangjang.domain.guide.exercise.service; +import java.time.LocalDate; import java.util.List; import org.springframework.stereotype.Service; @@ -27,7 +28,7 @@ */ @Service @RequiredArgsConstructor -public class ExerciseGuideGenerateService implements GuideGenerateService { +public class ExerciseGuideGenerateService implements GuideGenerateService { // TODO 리팩토링 필수 private final ExerciseGuideSearchService exerciseGuideSearchService; private final ExerciseGuideMapper exerciseGuideMapper; private final ExerciseGuideRepository exerciseGuideRepository; @@ -106,6 +107,36 @@ public GuideResponse updateGuide(AnalysisData analysisData) { return exerciseGuideMapper.toResponse(exerciseGuideRepository.save(updateExerciseGuide)); } + /** + * 걸음 수 가이드 또는 칼로리 가이드를 삭제한다. + * + * @since 1.3.0 + */ + @Override + public void removeGuide(String oauthId, LocalDate createdAt, CommonCode type) { + ExerciseGuide exerciseGuide = exerciseGuideSearchService.findByOauthIdAndCreatedAt(oauthId, createdAt); + if (type.equals(CommonCode.STEP_COUNT)) { + exerciseGuide.changeAboutWalk(0, 0, null, null, 0); + removeEmptyExerciseGuide(exerciseGuide); + return; + } + exerciseGuide.removeExerciseCalorie(type); + removeEmptyExerciseGuide(exerciseGuide); + } + + /** + * 운동 가이드가 비어있으면 삭제한다. + * + * @since 1.3.0 + */ + private void removeEmptyExerciseGuide(ExerciseGuide exerciseGuide) { + if (exerciseGuide.getContent() == null && exerciseGuide.getExerciseCalories().isEmpty()) { + exerciseGuideRepository.delete(exerciseGuide); + return; + } + exerciseGuideRepository.save(exerciseGuide); + } + @Override public GroupCode getGroupCode() { return GroupCode.EXERCISE; diff --git a/src/main/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateService.java b/src/main/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateService.java index b2544c32..52f9f2bf 100644 --- a/src/main/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateService.java +++ b/src/main/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateService.java @@ -1,10 +1,13 @@ package com.coniverse.dangjang.domain.guide.weight.service; +import java.time.LocalDate; + import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.stereotype.Service; import com.coniverse.dangjang.domain.analysis.dto.AnalysisData; import com.coniverse.dangjang.domain.analysis.dto.healthMetric.WeightAnalysisData; +import com.coniverse.dangjang.domain.code.enums.CommonCode; import com.coniverse.dangjang.domain.code.enums.GroupCode; import com.coniverse.dangjang.domain.guide.common.dto.response.GuideResponse; import com.coniverse.dangjang.domain.guide.common.service.GuideGenerateService; @@ -59,6 +62,20 @@ public GuideResponse updateGuide(AnalysisData analysisData) { return weightMapper.toResponse(weightGuideRepository.save(weightGuide)); } + /** + * 체중 가이드를 삭제한다. + * + * @param oauthId 유저 PK + * @param createdAt 생성일자 + * @param type 타입 + * @since 1.3.0 + */ + @Override + public void removeGuide(String oauthId, LocalDate createdAt, CommonCode type) { + WeightGuide weightGuide = weightGuideSearchService.findByUserIdAndCreatedAt(oauthId, createdAt.toString()); + weightGuideRepository.delete(weightGuide); + } + @Override public GroupCode getGroupCode() { return GroupCode.WEIGHT; diff --git a/src/main/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricController.java b/src/main/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricController.java index 02cc2f09..94cda464 100644 --- a/src/main/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricController.java +++ b/src/main/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricController.java @@ -7,6 +7,7 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.userdetails.User; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -28,6 +29,7 @@ import com.coniverse.dangjang.global.validator.ValidLocalDate; import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; /** @@ -96,11 +98,26 @@ public ResponseEntity> getHealt * @return 유저의 마지막 건강지표 생성일 * @since 1.1.0 */ - @GetMapping("/last-date") public ResponseEntity> getHealthMetricLastDate(@AuthenticationPrincipal User principal) { String oauthId = principal.getUsername(); HealthMetricLastDateResponse response = healthMetricSearchService.findHealthMetricLastDate(oauthId); return ResponseEntity.ok(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), response)); } + + /** + * 건강지표를 DELETE 요청한다. + * + * @param date 건강지표 생성일 + * @param type 건강지표 타입 + * @param principal 유저 정보 + * @return 성공 메시지 + * @since 1.3.0 + */ + @DeleteMapping + public ResponseEntity> deleteHealthMetric(@ValidLocalDate @RequestParam String date, @NotBlank @RequestParam String type, + @AuthenticationPrincipal User principal) { + healthMetricRegisterService.remove(date, type, principal.getUsername()); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterService.java b/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterService.java index 943d4766..31d339ff 100644 --- a/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterService.java +++ b/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterService.java @@ -47,7 +47,7 @@ public class HealthMetricRegisterService { */ public HealthMetricResponse register(HealthMetricPostRequest request, String oauthId) { final User user = userSearchService.findUserByOauthId(oauthId); - final HealthMetric healthMetric = healthMetricRepository.save(mapper.toEntity(request, user)); // TODO 가이드보다 insert 쿼리가 먼저 가도록 수정 + final HealthMetric healthMetric = healthMetricRepository.save(mapper.toEntity(request, user)); final GuideResponse guideResponse = guideService.createGuide(analysisService.analyze(healthMetric)); return mapper.toResponse(healthMetric, guideResponse); } @@ -101,4 +101,20 @@ private HealthMetricResponse updateType(HealthMetric prevHealthMetric, HealthMet final GuideResponse guideResponse = guideService.updateGuideWithType(analysisService.analyze(healthMetric), prevHealthMetric.getType()); return mapper.toResponse(healthMetric, guideResponse); } + + /** + * 건강지표를 삭제한다. + * + * @param date 건강지표 생성일 + * @param requestType 건강지표 타입 + * @param oauthId 건강지표 삭제 유저 PK + * @since 1.3.0 + */ + public void remove(String date, String requestType, String oauthId) { + CommonCode type = EnumFindUtil.findByTitle(CommonCode.class, requestType); + LocalDate createdAt = LocalDate.parse(date); + HealthMetric healthMetric = healthMetricSearchService.findByHealthMetricId(oauthId, createdAt, type); + healthMetricRepository.delete(healthMetric); + guideService.removeGuide(oauthId, createdAt, type); + } } diff --git a/src/main/java/com/coniverse/dangjang/domain/intro/controller/IntroController.java b/src/main/java/com/coniverse/dangjang/domain/intro/controller/IntroController.java deleted file mode 100644 index ddb5185a..00000000 --- a/src/main/java/com/coniverse/dangjang/domain/intro/controller/IntroController.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.coniverse.dangjang.domain.intro.controller; - -import org.springframework.http.ResponseEntity; - -import com.coniverse.dangjang.domain.intro.dto.IntroResponse; -import com.coniverse.dangjang.global.dto.SuccessSingleResponse; - -/** - * client에서 앱을 처음 실행할 때, 앱의 버전을 확인하고, 최신 버전이 아니라면 업데이트를 유도하는 역할을 한다. - * - * @author TEO - * @since 1.0.0 - */ -public interface IntroController { - ResponseEntity>> getIntro(); -} diff --git a/src/main/java/com/coniverse/dangjang/domain/intro/controller/ProdIntroController.java b/src/main/java/com/coniverse/dangjang/domain/intro/controller/ProdIntroController.java deleted file mode 100644 index 7c6afa99..00000000 --- a/src/main/java/com/coniverse/dangjang/domain/intro/controller/ProdIntroController.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.coniverse.dangjang.domain.intro.controller; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.coniverse.dangjang.domain.intro.dto.IntroResponse; -import com.coniverse.dangjang.domain.intro.service.IntroService; -import com.coniverse.dangjang.global.dto.SuccessSingleResponse; - -import lombok.RequiredArgsConstructor; - -@RestController -@RequestMapping("/api/intro") -@RequiredArgsConstructor -public class ProdIntroController implements IntroController { - private final IntroService introService; - - // TODO - @Override - @GetMapping("/prod") - public ResponseEntity>> getIntro() { - IntroResponse introResponse = introService.getProdIntroResponse(); - return ResponseEntity.ok().body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), introResponse)); - } -} diff --git a/src/main/java/com/coniverse/dangjang/domain/intro/controller/TestIntroController.java b/src/main/java/com/coniverse/dangjang/domain/intro/controller/TestIntroController.java deleted file mode 100644 index 0dcb48bc..00000000 --- a/src/main/java/com/coniverse/dangjang/domain/intro/controller/TestIntroController.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.coniverse.dangjang.domain.intro.controller; - -import org.springframework.context.annotation.Profile; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.coniverse.dangjang.domain.intro.dto.IntroResponse; -import com.coniverse.dangjang.domain.intro.service.IntroService; -import com.coniverse.dangjang.global.dto.SuccessSingleResponse; - -import lombok.RequiredArgsConstructor; - -@RestController -@RequestMapping("/api/intro") -@RequiredArgsConstructor -@Profile({"dev", "local", "test"}) -public class TestIntroController implements IntroController { - private final IntroService introService; - - @Override - @GetMapping("/test") - public ResponseEntity>> getIntro() { - IntroResponse introResponse = introService.getTestIntroResponse(); - return ResponseEntity.ok().body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), introResponse)); - } -} diff --git a/src/main/java/com/coniverse/dangjang/domain/intro/dto/IntroResponse.java b/src/main/java/com/coniverse/dangjang/domain/intro/dto/IntroResponse.java deleted file mode 100644 index 7e1afbd0..00000000 --- a/src/main/java/com/coniverse/dangjang/domain/intro/dto/IntroResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.coniverse.dangjang.domain.intro.dto; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonInclude; - -/** - * splash screen time때 load할 버전 정보와 데이터를 담는 dto이다. - * - * @author TEO - * @since 1.0.0 - */ -public record IntroResponse(String minVersion, String latestVersion, @JsonInclude(JsonInclude.Include.NON_NULL) List loadData) { -} diff --git a/src/main/java/com/coniverse/dangjang/domain/intro/dto/Version.java b/src/main/java/com/coniverse/dangjang/domain/intro/dto/Version.java deleted file mode 100644 index 9e849e7c..00000000 --- a/src/main/java/com/coniverse/dangjang/domain/intro/dto/Version.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.coniverse.dangjang.domain.intro.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -public enum Version { - MINIMUM("1.0.7"), - LATEST("1.0.7"); - - @Getter - private final String version; -} diff --git a/src/main/java/com/coniverse/dangjang/domain/intro/service/IntroService.java b/src/main/java/com/coniverse/dangjang/domain/intro/service/IntroService.java deleted file mode 100644 index 0861db3a..00000000 --- a/src/main/java/com/coniverse/dangjang/domain/intro/service/IntroService.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.coniverse.dangjang.domain.intro.service; - -import org.springframework.stereotype.Service; - -import com.coniverse.dangjang.domain.intro.dto.IntroResponse; -import com.coniverse.dangjang.domain.intro.dto.Version; -import com.coniverse.dangjang.global.exception.BadRequestException; - -import lombok.RequiredArgsConstructor; - -/** - * @author TEO - * @since 1.0.0 - */ -@Service -@RequiredArgsConstructor -public class IntroService { - private static final String MIN_VERSION = Version.MINIMUM.getVersion(); - private static final String LATEST_VERSION = Version.LATEST.getVersion(); - private int error = -1; - - /** - * response를 성공적으로 반환 또는 예외 발생을 번갈아가며 실행한다. - * - * @return IntroResponse - * @since 1.0.0 - */ - public IntroResponse getTestIntroResponse() { - IntroResponse introResponse = new IntroResponse<>(MIN_VERSION, LATEST_VERSION, null); - error += 1; - if (error % 2 == 0) { - return introResponse; - } - throw new BadRequestException(); - } - - /** - * TODO load data - * - * @return IntroResponse - * @since 1.0.0 - */ - public IntroResponse getProdIntroResponse() { - IntroResponse introResponse = new IntroResponse<>(MIN_VERSION, LATEST_VERSION, null); - - return introResponse; - } -} diff --git a/src/main/java/com/coniverse/dangjang/domain/notification/entity/FcmId.java b/src/main/java/com/coniverse/dangjang/domain/notification/entity/FcmId.java new file mode 100644 index 00000000..18c73bd0 --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/notification/entity/FcmId.java @@ -0,0 +1,29 @@ +package com.coniverse.dangjang.domain.notification.entity; + +import java.io.Serializable; + +import jakarta.persistence.Embeddable; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * UserFcmToken의 PK + * + * @author EVE + * @since 1.3.0 + */ +@Getter +@Embeddable +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EqualsAndHashCode +public class FcmId implements Serializable { + private String oauthId; + private String deviceId; + + public FcmId(String deviceId) { + this.deviceId = deviceId; + } + +} diff --git a/src/main/java/com/coniverse/dangjang/domain/notification/entity/UserFcmToken.java b/src/main/java/com/coniverse/dangjang/domain/notification/entity/UserFcmToken.java index ecef21ac..36be0d83 100644 --- a/src/main/java/com/coniverse/dangjang/domain/notification/entity/UserFcmToken.java +++ b/src/main/java/com/coniverse/dangjang/domain/notification/entity/UserFcmToken.java @@ -1,14 +1,15 @@ package com.coniverse.dangjang.domain.notification.entity; -import java.time.LocalDate; - import com.coniverse.dangjang.domain.user.entity.User; +import com.coniverse.dangjang.global.support.BaseEntity; +import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; -import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -16,7 +17,7 @@ /** * UserFcmToken Entity *

- * 사용자 모바일 기기의 fcmToken을 저장한다 + * 사용자 모바일 기기의 fcmToken 을 저장한다 * * @author EVE * @since 1.1.0 @@ -24,20 +25,43 @@ @Getter @Entity @NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) -public class UserFcmToken { - @Id - private String fcmToken; +public class UserFcmToken extends BaseEntity { + @Getter(AccessLevel.PRIVATE) + @EmbeddedId + private FcmId fcmId; - private LocalDate createdAt; + private String fcmToken; + @MapsId("oauthId") @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "oauthId", referencedColumnName = "oauthId", updatable = false) + @JoinColumn(name = "oauth_id") private User user; @Builder - private UserFcmToken(User user, String fcmToken, LocalDate createdAt) { + private UserFcmToken(User user, String fcmToken, String deviceId) { + this.fcmId = new FcmId(deviceId); this.fcmToken = fcmToken; - this.createdAt = createdAt; this.user = user; } + + /** + * oquthId를 조회한다. + * + * @return oauthId + * @since 1.3.0 + */ + public String getOauthId() { + return fcmId.getOauthId(); + } + + /** + * fcmToken을 업데이트한다. + * + * @param fcmToken 토큰 + * @since 1.3.0 + */ + public void setFcmToken(String fcmToken) { + this.fcmToken = fcmToken; + } + } diff --git a/src/main/java/com/coniverse/dangjang/domain/notification/mapper/NotificationMapper.java b/src/main/java/com/coniverse/dangjang/domain/notification/mapper/NotificationMapper.java index 09c7d35d..61ff55ed 100644 --- a/src/main/java/com/coniverse/dangjang/domain/notification/mapper/NotificationMapper.java +++ b/src/main/java/com/coniverse/dangjang/domain/notification/mapper/NotificationMapper.java @@ -35,17 +35,16 @@ public interface NotificationMapper { /** * UserFcmToken Entity 생성 * - * @param user 사용자 - * @param fcmToken 사용자 fcmToken - * @param createdAt fcmToken 저장 날짜 + * @param user 사용자 + * @param fcmToken 사용자 fcmToken * @return UserFcmToken 사용자 fcmToken Entity * @since 1.1.0 */ @Mappings({ @Mapping(target = "user", source = "user"), - @Mapping(target = "createdAt", source = "createdAt") + @Mapping(target = "deviceId", source = "deviceId") }) - UserFcmToken toEntity(User user, String fcmToken, LocalDate createdAt); + UserFcmToken toEntity(User user, String fcmToken, String deviceId); /** * Notification Entity 생성 diff --git a/src/main/java/com/coniverse/dangjang/domain/notification/repository/UserFcmTokenRepository.java b/src/main/java/com/coniverse/dangjang/domain/notification/repository/UserFcmTokenRepository.java index 83881aa1..e12c5b95 100644 --- a/src/main/java/com/coniverse/dangjang/domain/notification/repository/UserFcmTokenRepository.java +++ b/src/main/java/com/coniverse/dangjang/domain/notification/repository/UserFcmTokenRepository.java @@ -2,11 +2,13 @@ import java.time.LocalDate; import java.util.List; +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; +import com.coniverse.dangjang.domain.notification.entity.FcmId; import com.coniverse.dangjang.domain.notification.entity.UserFcmToken; /** @@ -15,7 +17,7 @@ * @author EVE * @since 1.1.0 */ -public interface UserFcmTokenRepository extends JpaRepository { +public interface UserFcmTokenRepository extends JpaRepository { /** * 접속하지 않은, 유저의 fcmToken을 조회한다. * @@ -24,4 +26,22 @@ public interface UserFcmTokenRepository extends JpaRepository findNotAccessUserFcmToken(@Param("date") LocalDate date); + + /** + * FcmId로 UserFcmToken을 조회한다 + * + * @param oauthId 사용자 아이디 + * @param deviceId 디바이스 아이디 + * @since 1.3.0 + */ + @Query("SELECT utk FROM UserFcmToken utk where utk.fcmId.oauthId = :oauthId and utk.fcmId.deviceId = :deviceId") + Optional findUserFcmTokenByFcmId(@Param("oauthId") String oauthId, @Param("deviceId") String deviceId); + + /** + * UserFcmToken을 제거한다 + * + * @param fcmToken fcmToken + * @since 1.3.0 + */ + void deleteByFcmToken(String fcmToken); } diff --git a/src/main/java/com/coniverse/dangjang/domain/notification/service/NotificationService.java b/src/main/java/com/coniverse/dangjang/domain/notification/service/NotificationService.java index ff142461..408d2a8e 100644 --- a/src/main/java/com/coniverse/dangjang/domain/notification/service/NotificationService.java +++ b/src/main/java/com/coniverse/dangjang/domain/notification/service/NotificationService.java @@ -17,6 +17,7 @@ import com.coniverse.dangjang.domain.notification.mapper.NotificationMapper; import com.coniverse.dangjang.domain.notification.repository.NotificationRepository; import com.coniverse.dangjang.domain.notification.repository.UserFcmTokenRepository; +import com.coniverse.dangjang.domain.user.dto.request.PostFcmTokenRequest; import com.coniverse.dangjang.domain.user.entity.User; import com.coniverse.dangjang.domain.user.service.UserSearchService; @@ -81,14 +82,44 @@ public Boolean isExistsNotReadNotification(String oauthId) { /** * fcmToken 저장 + *

+ * 기존에 있는 fcm 토큰이라면 업데이트하고, 없다면 새로 저장한다. * - * @param fcmToken fcmToken - * @param oauthId 사용자 아이디 + * @param request fcmToken 요청 + * @param oauthId 사용자 아이디 * @since 1.1.0 */ - public void saveFcmToken(String fcmToken, String oauthId) { + public void saveOrUpdateFcmToken(PostFcmTokenRequest request, String oauthId) { + Optional existFcmToken = userFcmTokenRepository.findUserFcmTokenByFcmId(oauthId, request.deviceId()); + if (!existFcmToken.isEmpty()) { + updateFcmToken(existFcmToken.get(), request.fcmToken()); + return; + } + saveFcmToken(request, oauthId); + } + + /** + * fcmToken 업데이트 + * + * @param userFcmToken 기존의 userFcmToken + * @param newFcmToken 새로운 fcmToken + * @since 1.3.0 + */ + private void updateFcmToken(UserFcmToken userFcmToken, String newFcmToken) { + userFcmToken.setFcmToken(newFcmToken); + } + + /** + * fcmToken 저장 + * + * @param request 요청 + * @param oauthId 사용자 아이디 + * @since 1.3.0 + */ + private void saveFcmToken(PostFcmTokenRequest request, String oauthId) { User user = userSearchService.findUserByOauthId(oauthId); - userFcmTokenRepository.save(notificationMapper.toEntity(user, fcmToken, LocalDate.now())); + UserFcmToken userFcmToken = notificationMapper.toEntity(user, request.fcmToken(), request.deviceId()); + userFcmTokenRepository.save(userFcmToken); } /** @@ -99,7 +130,7 @@ public void saveFcmToken(String fcmToken, String oauthId) { * @since 1.1.0 */ public void deleteFcmToken(String fcmToken) { - userFcmTokenRepository.deleteById(fcmToken); + userFcmTokenRepository.deleteByFcmToken(fcmToken); } /** diff --git a/src/main/java/com/coniverse/dangjang/domain/user/controller/SignupController.java b/src/main/java/com/coniverse/dangjang/domain/user/controller/SignupController.java index 61be045a..15285fd0 100644 --- a/src/main/java/com/coniverse/dangjang/domain/user/controller/SignupController.java +++ b/src/main/java/com/coniverse/dangjang/domain/user/controller/SignupController.java @@ -13,7 +13,6 @@ import com.coniverse.dangjang.domain.user.service.UserSignupService; import com.coniverse.dangjang.global.dto.SuccessSingleResponse; -import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -27,18 +26,16 @@ public class SignupController { private final UserSignupService userSignupService; private final OauthLoginService oauthLoginService; - private static String headerKeyFcmToken = "FcmToken"; private static String headerKeyAccessToken = "AccessToken"; /** - * @param params 회원가입에 필요한 정보를 담아온다. - * @param request request에서 fcmToken header 이용 + * @param params 회원가입에 필요한 정보를 담아온다. * @return 회원가입 후 로그인을 시도 , ResponseEntity 로그인을 성공하면, JWT TOKEN과 사용자 정보(nickname, authID)를 전달한다. * @since 1.0 */ @PostMapping - public ResponseEntity> signUp(@Valid @RequestBody SignUpRequest params, HttpServletRequest request) { - LoginResponse loginResponse = userSignupService.signUp(params, request.getHeader(headerKeyFcmToken)); + public ResponseEntity> signUp(@Valid @RequestBody SignUpRequest params) { + LoginResponse loginResponse = userSignupService.signUp(params); String accessToken = oauthLoginService.getAuthToken(loginResponse.nickname()); return ResponseEntity.ok() .header(headerKeyAccessToken, accessToken) diff --git a/src/main/java/com/coniverse/dangjang/domain/user/controller/UserController.java b/src/main/java/com/coniverse/dangjang/domain/user/controller/UserController.java index ba57f4a6..34d26cc9 100644 --- a/src/main/java/com/coniverse/dangjang/domain/user/controller/UserController.java +++ b/src/main/java/com/coniverse/dangjang/domain/user/controller/UserController.java @@ -8,11 +8,13 @@ import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.coniverse.dangjang.domain.notification.service.NotificationService; +import com.coniverse.dangjang.domain.user.dto.request.PostFcmTokenRequest; import com.coniverse.dangjang.domain.user.dto.response.DuplicateNicknameResponse; import com.coniverse.dangjang.domain.user.dto.response.MypageResponse; import com.coniverse.dangjang.domain.user.service.MypageService; @@ -20,7 +22,7 @@ import com.coniverse.dangjang.domain.user.service.UserWithdrawalService; import com.coniverse.dangjang.global.dto.SuccessSingleResponse; -import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import lombok.RequiredArgsConstructor; @@ -69,9 +71,17 @@ public ResponseEntity withdraw(@AuthenticationPrincipal User user) { return ResponseEntity.noContent().build(); } + /** + * fcmToken 저장 및 업데이트 + * + * @param user 사용자 정보 + * @param request fcmToken + * @return MyPageResponse 사용자 닉네임과 포인트 + * @since 1.0.0 + */ @PostMapping("/fcmToken") - public ResponseEntity> registerFcmToken(@AuthenticationPrincipal User user, HttpServletRequest request) { - notificationService.saveFcmToken(request.getHeader("FcmToken"), user.getUsername()); + public ResponseEntity> postFcmToken(@AuthenticationPrincipal User user, @Valid @RequestBody PostFcmTokenRequest request) { + notificationService.saveOrUpdateFcmToken(request, user.getUsername()); return ResponseEntity.ok().body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), null)); } } diff --git a/src/main/java/com/coniverse/dangjang/domain/user/dto/request/PostFcmTokenRequest.java b/src/main/java/com/coniverse/dangjang/domain/user/dto/request/PostFcmTokenRequest.java new file mode 100644 index 00000000..7be3c95e --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/user/dto/request/PostFcmTokenRequest.java @@ -0,0 +1,13 @@ +package com.coniverse.dangjang.domain.user.dto.request; + +import jakarta.validation.constraints.NotBlank; + +/** + * fcmToken 등록 및 업데이트 요청 request + * + * @author EVE + * @since 1.3.0 + */ +public record PostFcmTokenRequest(@NotBlank(message = "FCM Token은 필수로 필요합니다") String fcmToken, @NotBlank(message = "Device ID는 필수로 필요합니다") String deviceId) { + +} diff --git a/src/main/java/com/coniverse/dangjang/domain/user/service/UserSignupService.java b/src/main/java/com/coniverse/dangjang/domain/user/service/UserSignupService.java index b2c5bfe6..776591fd 100644 --- a/src/main/java/com/coniverse/dangjang/domain/user/service/UserSignupService.java +++ b/src/main/java/com/coniverse/dangjang/domain/user/service/UserSignupService.java @@ -16,7 +16,6 @@ import com.coniverse.dangjang.domain.healthmetric.dto.request.HealthMetricPostRequest; import com.coniverse.dangjang.domain.healthmetric.service.HealthMetricRegisterService; import com.coniverse.dangjang.domain.infrastructure.auth.dto.OAuthInfoResponse; -import com.coniverse.dangjang.domain.notification.service.NotificationService; import com.coniverse.dangjang.domain.point.service.PointService; import com.coniverse.dangjang.domain.user.dto.request.SignUpRequest; import com.coniverse.dangjang.domain.user.dto.response.DuplicateNicknameResponse; @@ -45,18 +44,16 @@ public class UserSignupService { private final PointService pointService; private final UserMapper userMapper; private final AuthMapper authMapper; - private final NotificationService notificationService; private final WeightGuideSearchService weightGuideSearchService; /** * 회원가입 * * @param signUpRequest 회원가입 정보 - * @param fcmToken notification 디바이스 토큰 * @return LoginResponse 로그인 응답 * @since 1.0.0 */ - public LoginResponse signUp(SignUpRequest signUpRequest, String fcmToken) { + public LoginResponse signUp(SignUpRequest signUpRequest) { OAuthInfoResponse oAuthInfoResponse = getOauthInfo(OauthProvider.of(signUpRequest.provider()), signUpRequest.accessToken()); ActivityAmount activityAmount = ActivityAmount.of(signUpRequest.activityAmount()); Gender gender = Gender.of(signUpRequest.gender()); @@ -65,7 +62,6 @@ public LoginResponse signUp(SignUpRequest signUpRequest, String fcmToken) { User savedUser = userRepository.save(userMapper.toEntity(oAuthInfoResponse, signUpRequest, activityAmount, gender, recommendedCalorie)); registerWeight(savedUser, signUpRequest.weight()); pointService.addSignupPoint(savedUser.getOauthId()); - notificationService.saveFcmToken(fcmToken, savedUser.getOauthId()); return authMapper.toLoginResponse(savedUser.getNickname(), false, savedUser.getHealthConnect().isConnecting()); } diff --git a/src/main/java/com/coniverse/dangjang/domain/version/controller/VersionController.java b/src/main/java/com/coniverse/dangjang/domain/version/controller/VersionController.java new file mode 100644 index 00000000..fb54a77f --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/version/controller/VersionController.java @@ -0,0 +1,52 @@ +package com.coniverse.dangjang.domain.version.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.coniverse.dangjang.domain.version.dto.request.VersionRequest; +import com.coniverse.dangjang.domain.version.dto.response.VersionResponse; +import com.coniverse.dangjang.domain.version.service.VersionService; +import com.coniverse.dangjang.global.dto.SuccessSingleResponse; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +/** + * 앱 버전 관련 controller + * + * @author TEO + * @since 1.3.0 + */ +@RestController +@RequestMapping("/api/version") +@RequiredArgsConstructor +public class VersionController { + private final VersionService versionService; + + /** + * 버전 정보를 GET 요청한다. + * + * @since 1.3.0 + */ + @GetMapping("/intro") + public ResponseEntity>> getIntro() { + VersionResponse versionResponse = versionService.getVersionResponse(); + return ResponseEntity.ok().body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), versionResponse)); + } + + /** + * 버전 정보를 POST 요청한다. + * + * @since 1.3.0 + */ + @PostMapping + public ResponseEntity>> postVersion(@Valid @RequestBody VersionRequest request) { + VersionResponse versionResponse = versionService.saveVersion(request); + return ResponseEntity.ok().body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), versionResponse)); + } +} diff --git a/src/main/java/com/coniverse/dangjang/domain/version/dto/request/VersionRequest.java b/src/main/java/com/coniverse/dangjang/domain/version/dto/request/VersionRequest.java new file mode 100644 index 00000000..9b711bb5 --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/version/dto/request/VersionRequest.java @@ -0,0 +1,14 @@ +package com.coniverse.dangjang.domain.version.dto.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; + +/** + * 앱 버전 post dto + * + * @author TEO + * @since 1.3.0 + */ +public record VersionRequest(@NotBlank @Pattern(regexp = "^\\d\\.\\d\\.\\d$") String minVersion, + @NotBlank @Pattern(regexp = "^\\d\\.\\d\\.\\d$") String latestVersion, @NotBlank String key) { +} diff --git a/src/main/java/com/coniverse/dangjang/domain/version/dto/response/VersionResponse.java b/src/main/java/com/coniverse/dangjang/domain/version/dto/response/VersionResponse.java new file mode 100644 index 00000000..e2a60ce0 --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/version/dto/response/VersionResponse.java @@ -0,0 +1,18 @@ +package com.coniverse.dangjang.domain.version.dto.response; + +import java.util.List; + +import com.coniverse.dangjang.domain.version.entity.Version; +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * 버전 정보를 반환하는 dto이다. + * + * @author TEO + * @since 1.3.0 + */ +public record VersionResponse(String minVersion, String latestVersion, @JsonInclude(JsonInclude.Include.NON_NULL) List loadData) { + public VersionResponse(Version version, List loadData) { + this(version.getMinVersion(), version.getLatestVersion(), loadData); + } +} diff --git a/src/main/java/com/coniverse/dangjang/domain/version/entity/Version.java b/src/main/java/com/coniverse/dangjang/domain/version/entity/Version.java new file mode 100644 index 00000000..0adae6a0 --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/version/entity/Version.java @@ -0,0 +1,38 @@ +package com.coniverse.dangjang.domain.version.entity; + +import java.time.LocalDateTime; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * app version entity + * + * @author TEO + * @since 1.3.0 + */ +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +public class Version { + @Id + @CreatedDate + private LocalDateTime createdAt; + private String minVersion; + private String latestVersion; + + @Builder + private Version(String minVersion, String latestVersion) { + this.minVersion = minVersion; + this.latestVersion = latestVersion; + } +} diff --git a/src/main/java/com/coniverse/dangjang/domain/version/repository/VersionRepository.java b/src/main/java/com/coniverse/dangjang/domain/version/repository/VersionRepository.java new file mode 100644 index 00000000..577e97c8 --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/version/repository/VersionRepository.java @@ -0,0 +1,22 @@ +package com.coniverse.dangjang.domain.version.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.coniverse.dangjang.domain.version.entity.Version; + +/** + * app version repository + * + * @author TEO + * @since 1.3.0 + */ +public interface VersionRepository extends JpaRepository { + + /** + * 가장 최근의 버전 정보를 반환한다. + * + * @return Version + * @since 1.3.0 + */ + Version findFirstByOrderByCreatedAtDesc(); +} diff --git a/src/main/java/com/coniverse/dangjang/domain/version/service/VersionService.java b/src/main/java/com/coniverse/dangjang/domain/version/service/VersionService.java new file mode 100644 index 00000000..73ffdad8 --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/version/service/VersionService.java @@ -0,0 +1,69 @@ +package com.coniverse.dangjang.domain.version.service; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.coniverse.dangjang.domain.version.dto.request.VersionRequest; +import com.coniverse.dangjang.domain.version.dto.response.VersionResponse; +import com.coniverse.dangjang.domain.version.entity.Version; +import com.coniverse.dangjang.domain.version.repository.VersionRepository; + +import lombok.RequiredArgsConstructor; + +/** + * 앱 버전 관련 service + * + * @author TEO + * @since 1.3.0 + */ +@Service +@RequiredArgsConstructor +@Transactional +public class VersionService { + private final VersionRepository versionRepository; + @Value("${version.key}") + private final String serverKey; + + /** + * 가장 최근의 버전 정보를 반환한다. + * + * @return VersionResponse + * @since 1.0.0 + */ + @Transactional(readOnly = true) + public VersionResponse getVersionResponse() { + Version version = versionRepository.findFirstByOrderByCreatedAtDesc(); + return new VersionResponse<>(version, null); + } + + /** + * 버전 정보를 저장한다. + * + * @param request 버전 정보 + * @return VersionResponse + * @since 1.3.0 + */ + public VersionResponse saveVersion(VersionRequest request) { + validateKey(request.key()); + Version version = Version.builder() + .minVersion(request.minVersion()) + .latestVersion(request.latestVersion()) + .build(); + versionRepository.save(version); + return new VersionResponse<>(version, null); + } + + /** + * 버전 정보의 키 값을 확인한다. + * + * @param key 버전 키 + * @throws IllegalArgumentException 서버 키가 아닐 경우 + * @since 1.3.0 + */ + private void validateKey(String key) { + if (!key.equals(serverKey)) { + throw new IllegalArgumentException("올바르지 않은 키 값입니다."); + } + } +} diff --git a/src/main/resources/config b/src/main/resources/config index 64b96d83..f027d62e 160000 --- a/src/main/resources/config +++ b/src/main/resources/config @@ -1 +1 @@ -Subproject commit 64b96d83da52275f908d1f7599812ca34dd16787 +Subproject commit f027d62e9388d1c8a0bb681a61c3ba1d0b76e2ae diff --git a/src/main/resources/data-dev.sql b/src/main/resources/data-dev.sql index 2ac9cccc..bcc3e929 100644 --- a/src/main/resources/data-dev.sql +++ b/src/main/resources/data-dev.sql @@ -29,13 +29,13 @@ INSERT INTO notification_type (type) VALUES ("접속"), ("기록"); -INSERT INTO user_fcm_token (oauth_id, fcm_token, created_at) -VALUES ("11111111", "fcmToken1", '2023-10-08'), - ("22222222", "fcmToken2", '2023-10-08'), - ("11111111", "fcmToken3", '2023-10-09'), - ("33333333", "fcmToken4", '2023-10-09'), - ("33333333", "fcmToken5", '2023-10-10'), - ("44444444", "fcmToken6", '2023-10-10'); +INSERT INTO user_fcm_token (oauth_id, device_id, fcm_token, created_at, updated_at) +VALUES ("11111111", "device1", "fcmToken1", '2023-10-08', '2023-10-08'), + ("22222222", "device2", "fcmToken2", '2023-10-08', '2023-10-08'), + ("11111111", "device3", "fcmToken3", '2023-10-09', '2023-10-09'), + ("33333333", "device4", "fcmToken4", '2023-10-09', '2023-10-09'), + ("33333333", "device5", "fcmToken5", '2023-10-10', '2023-10-10'), + ("44444444", "device6", "fcmToken6", '2023-10-10', '2023-10-10'); -- INSERT INTO notification(title, content, created_at, type, oauth_id, is_read) -- VALUES ("체중 기록!", "오늘 체중을 기록해보세요 ~ ", '2023-10-08', "기록", "11111111", true), @@ -44,3 +44,6 @@ VALUES ("11111111", "fcmToken1", '2023-10-08'), -- ("체중 기록!", "오늘 체중을 기록해보세요 ~ ", '2023-10-08', "기록", "22222222", true), -- ("접속해주세요!", "오늘은 접속 안하셨네요 ~ 접속해서 포인트 받아가세요", '2023-10-09', "접속", "22222222", false), -- ("운동 기록 !", "오늘 운동을 기록해보세요 ~ ", '2023-10-10', "기록", "11111111", false); + +INSERT INTO version(created_at, min_version, latest_version) +VALUES (now(), "1.0.0", "1.0.0"); \ No newline at end of file diff --git a/src/main/resources/schema-dev.sql b/src/main/resources/schema-dev.sql index 50f2d073..9d9ccc14 100644 --- a/src/main/resources/schema-dev.sql +++ b/src/main/resources/schema-dev.sql @@ -12,6 +12,7 @@ DROP TABLE IF EXISTS POINT_PRODUCT; DROP TABLE IF EXISTS USER_POINT; DROP TABLE IF EXISTS USERS; DROP TABLE IF EXISTS SHEDLOCK; +DROP TABLE IF EXISTS VERSION; CREATE TABLE `USERS` ( @@ -119,7 +120,7 @@ CREATE TABLE `PURCHASE_HISTORY` `CREATED_AT` dateTime NOT NULL, `PHONE` varchar(15) NOT NULL, `NAME` varchar(20) NOT NULL, - `COMMENT` varchar(255), + `COMMENT` varchar(255), `COMPLETED` boolean, PRIMARY KEY (`OAUTH_ID`, `PRODUCT_NAME`, `CREATED_AT`), FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) ON DELETE CASCADE, @@ -131,8 +132,10 @@ CREATE TABLE `USER_FCM_TOKEN` ( `OAUTH_ID` varchar(50) NOT NULL, `FCM_TOKEN` varchar(255) NOT NULL, - `CREATED_AT` dateTime NOT NULL, - PRIMARY KEY (`FCM_TOKEN`), + `DEVICE_ID` varchar(255) NOT NULL, + `CREATED_AT` date NOT NULL, + `UPDATED_AT` date NOT NULL, + PRIMARY KEY (`OAUTH_ID`, `DEVICE_ID`), FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) ON DELETE CASCADE ); @@ -144,7 +147,7 @@ CREATE TABLE `NOTIFICATION_TYPE` CREATE TABLE `NOTIFICATION` ( - `NOTIFICATION_ID` INT NOT NULL AUTO_INCREMENT, + `NOTIFICATION_ID` bigint NOT NULL AUTO_INCREMENT, `TITLE` varchar(255) NOT NULL, `CONTENT` varchar(255) NOT NULL, `OAUTH_ID` varchar(50) NOT NULL, @@ -156,10 +159,19 @@ CREATE TABLE `NOTIFICATION` FOREIGN KEY (`TYPE`) REFERENCES NOTIFICATION_TYPE (`TYPE`) ); -CREATE TABLE `SHEDLOCK` ( - `NAME` VARCHAR(64), - `LOCK_UNTIL` TIMESTAMP(3) NULL, - `LOCKED_AT` TIMESTAMP(3) NULL, - `LOCKED_BY` VARCHAR(255), - PRIMARY KEY (NAME) -) +CREATE TABLE `SHEDLOCK` +( + `NAME` varchar(64) NOT NULL, + `LOCK_UNTIL` timestamp(3) NOT NULL, + `LOCKED_AT` timestamp(3) NOT NULL, + `LOCKED_BY` varchar(255) NOT NULL, + PRIMARY KEY (NAME) +); + +CREATE TABLE `VERSION` +( + `CREATED_AT` datetime NOT NULL, + `MIN_VERSION` varchar(10) NOT NULL, + `LATEST_VERSION` varchar(10) NOT NULL, + PRIMARY KEY (`CREATED_AT`) +); diff --git a/src/test/java/com/coniverse/dangjang/domain/auth/controller/LoginControllerTest.java b/src/test/java/com/coniverse/dangjang/domain/auth/controller/LoginControllerTest.java index f8db2d98..1bfc8f49 100644 --- a/src/test/java/com/coniverse/dangjang/domain/auth/controller/LoginControllerTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/auth/controller/LoginControllerTest.java @@ -12,6 +12,7 @@ import com.coniverse.dangjang.domain.auth.dto.AuthToken; import com.coniverse.dangjang.domain.auth.dto.request.KakaoLoginRequest; +import com.coniverse.dangjang.domain.auth.dto.request.LogoutFcmTokenRequest; import com.coniverse.dangjang.domain.auth.dto.request.NaverLoginRequest; import com.coniverse.dangjang.domain.auth.dto.response.LoginResponse; import com.coniverse.dangjang.domain.auth.service.OauthLoginService; @@ -36,7 +37,7 @@ class LoginControllerTest extends ControllerTest { AuthToken authToken = new AuthToken(); authToken.setAccessToken("accessToken"); authToken.setRefreshToken("refreshToken"); - given(oauthLoginService.login(any(), any())).willReturn(response); + given(oauthLoginService.login(any())).willReturn(response); given(oauthLoginService.getAuthToken(any())).willReturn(authToken.getAccessToken()); // when @@ -77,7 +78,7 @@ class LoginControllerTest extends ControllerTest { AuthToken authToken = new AuthToken(); authToken.setAccessToken("accessToken"); authToken.setRefreshToken("refreshToken"); - given(oauthLoginService.login(any(), any())).willReturn(response); + given(oauthLoginService.login(any())).willReturn(response); given(oauthLoginService.getAuthToken(any())).willReturn(authToken.getAccessToken()); // when @@ -113,9 +114,10 @@ class LoginControllerTest extends ControllerTest { @Test void 로그아웃을_성공한다() throws Exception { String subURL = "/logout"; - + LogoutFcmTokenRequest request = new LogoutFcmTokenRequest("fcmToken"); + String content = objectMapper.writeValueAsString(request); // when - ResultActions resultActions = post(mockMvc, URI + subURL); + ResultActions resultActions = post(mockMvc, URI + subURL, content); // then resultActions.andExpectAll( diff --git a/src/test/java/com/coniverse/dangjang/domain/auth/service/OauthLoginServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/auth/service/OauthLoginServiceTest.java index 5919ac96..bd1bb989 100644 --- a/src/test/java/com/coniverse/dangjang/domain/auth/service/OauthLoginServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/auth/service/OauthLoginServiceTest.java @@ -47,6 +47,7 @@ class OauthLoginServiceTest { @Autowired private BlackTokenRepository blackTokenRepository; private final String fcmToken = "fcmToken"; + private String deviceId = "deviceId"; @Autowired private EntityManager entityManager; @Autowired @@ -66,7 +67,7 @@ void tearDown() { KakaoLoginRequest request = 카카오_로그인_요청(); // when & then - assertThatThrownBy(() -> oauthLoginService.login(request, fcmToken)) + assertThatThrownBy(() -> oauthLoginService.login(request)) .isInstanceOf(NonExistentUserException.class); } @@ -79,7 +80,7 @@ void tearDown() { KakaoLoginRequest request = 카카오_로그인_요청(); int tokenCount = 0; //when - LoginResponse response = oauthLoginService.login(request, fcmToken); + LoginResponse response = oauthLoginService.login(request); //then assertAll( @@ -99,7 +100,7 @@ void tearDown() { KakaoLoginRequest request = 카카오_로그인_요청(); int tokenCount = 0; //when - LoginResponse response = oauthLoginService.login(request, fcmToken); + LoginResponse response = oauthLoginService.login(request); //then assertAll( @@ -171,7 +172,7 @@ void tearDown() { void 로그아웃을_성공한다() { //given User 이브 = userRepository.save(유저_이브()); - userFcmTokenRepository.save(사용자_fcmToken_엔티티(fcmToken, 이브)); + userFcmTokenRepository.save(사용자_fcmToken_엔티티(fcmToken, 이브, deviceId)); String accessToken = oauthLoginService.getAuthToken(이브.getNickname()); String header = "Bearer " + accessToken; //when @@ -200,7 +201,7 @@ void tearDown() { KakaoLoginRequest request = 카카오_로그인_요청(); //when & then - assertThatThrownBy(() -> oauthLoginService.login(request, fcmToken)) + assertThatThrownBy(() -> oauthLoginService.login(request)) .isInstanceOf(WithdrawalUserException.class); } diff --git a/src/test/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateServiceTest.java index 4781c3d9..3478f6e1 100644 --- a/src/test/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/guide/bloodsugar/service/BloodSugarGuideGenerateServiceTest.java @@ -1,10 +1,14 @@ package com.coniverse.dangjang.domain.guide.bloodsugar.service; import static com.coniverse.dangjang.fixture.AnalysisDataFixture.*; +import static com.coniverse.dangjang.fixture.CommonCodeFixture.*; +import static com.coniverse.dangjang.fixture.GuideFixture.*; import static com.coniverse.dangjang.fixture.UserFixture.*; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; +import java.time.LocalDate; + import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -19,6 +23,7 @@ import com.coniverse.dangjang.domain.guide.bloodsugar.document.BloodSugarGuide; import com.coniverse.dangjang.domain.guide.bloodsugar.document.SubGuide; import com.coniverse.dangjang.domain.guide.bloodsugar.dto.SubGuideResponse; +import com.coniverse.dangjang.domain.guide.bloodsugar.repository.BloodSugarGuideRepository; import com.coniverse.dangjang.domain.guide.common.exception.GuideAlreadyExistsException; import com.coniverse.dangjang.domain.guide.common.exception.GuideNotFoundException; import com.coniverse.dangjang.domain.user.entity.User; @@ -38,6 +43,8 @@ class BloodSugarGuideGenerateServiceTest { private BloodSugarAnalysisStrategy bloodSugarAnalysisStrategy; @Autowired private BloodSugarGuideSearchService bloodSugarGuideSearchService; + @Autowired + private BloodSugarGuideRepository bloodSugarGuideRepository; @Order(100) @Test @@ -218,4 +225,36 @@ class BloodSugarGuideGenerateServiceTest { } ); } + + @Test + void 서브_가이드를_정상적으로_삭제한다() { + // given + String oauthId = user.getOauthId(); + String createdAt = "2021-08-01"; + CommonCode type = CommonCode.BEFORE_BREAKFAST; + BloodSugarGuide 혈당_가이드 = 혈당_가이드_도큐먼트(oauthId, createdAt); + bloodSugarGuideRepository.save(혈당_가이드); + + // when + bloodSugarGuideGenerateService.removeGuide(oauthId, LocalDate.parse(createdAt), type); + + // then + BloodSugarGuide 삭제한_가이드 = bloodSugarGuideRepository.findByOauthIdAndCreatedAt(oauthId, createdAt).orElseThrow(); + assertThat(삭제한_가이드.getSubGuides()).hasSize(혈당_가이드.getSubGuides().size() - 1); + } + + @Test + void 서브_가이드를_모두_삭제하면_혈당_가이드도_삭제된다() { + // given + String oauthId = user.getOauthId(); + String createdAt = "2021-08-01"; + BloodSugarGuide 혈당_가이드 = 혈당_가이드_도큐먼트(oauthId, createdAt); + bloodSugarGuideRepository.save(혈당_가이드); + + // when + 혈당_타입().forEach(type -> bloodSugarGuideGenerateService.removeGuide(oauthId, LocalDate.parse(createdAt), type)); + + // then + assertThat(bloodSugarGuideRepository.findByOauthIdAndCreatedAt(oauthId, createdAt)).isEmpty(); + } } diff --git a/src/test/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateServiceTest.java index 78ab31a3..58379f01 100644 --- a/src/test/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/guide/exercise/service/ExerciseGuideGenerateServiceTest.java @@ -5,6 +5,7 @@ import static com.coniverse.dangjang.fixture.HealthMetricFixture.*; import static com.coniverse.dangjang.fixture.UserFixture.*; import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import java.time.LocalDate; @@ -15,6 +16,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.params.ParameterizedTest; @@ -180,6 +182,62 @@ void setUp() { break; } } + } + + @Test + void 걸음_가이드를_성공적으로_삭제한다() { + // given + String oauthId = user.getOauthId(); + LocalDate createdAt = LocalDate.parse("2021-08-02"); + CommonCode type = CommonCode.STEP_COUNT; + ExerciseGuide 운동_가이드 = 걸음수_운동_가이드(oauthId, createdAt); + exerciseGuideRepository.save(운동_가이드); + + // when + exerciseGuideGenerateService.removeGuide(oauthId, createdAt.minusDays(1), type); + + // then + ExerciseGuide 삭제한_가이드 = exerciseGuideRepository.findByOauthIdAndCreatedAt(oauthId, createdAt).orElseThrow(); + assertAll( + () -> assertThat(삭제한_가이드.getContent()).isNull(), + () -> assertThat(삭제한_가이드.getComparedToLastWeek()).isNull(), + () -> assertThat(삭제한_가이드.getNeedStepByLastWeek()).isZero(), + () -> assertThat(삭제한_가이드.getNeedStepByTTS()).isZero(), + () -> assertThat(삭제한_가이드.getStepCount()).isZero() + ); + } + + @Test + void 소모칼로리_가이드를_성공적으로_삭제한다() { + // given + String oauthId = user.getOauthId(); + LocalDate createdAt = LocalDate.parse("2021-08-03"); + CommonCode type = CommonCode.HEALTH; + ExerciseGuide 운동_가이드 = 운동_가이드(oauthId, createdAt); + exerciseGuideRepository.save(운동_가이드); + // when + exerciseGuideGenerateService.removeGuide(oauthId, createdAt.minusDays(1), type); + + // then + ExerciseGuide 삭제한_가이드 = exerciseGuideRepository.findByOauthIdAndCreatedAt(oauthId, createdAt).orElseThrow(); + assertThat(삭제한_가이드.getExerciseCalories()).hasSize(운동_가이드.getExerciseCalories().size() - 1); + } + + @Test + void 걸음수_소모칼로리_가이드가_존재하지_않으면_운동_가이드를_성공적으로_삭제한다() { + // given + String oauthId = user.getOauthId(); + LocalDate createdAt = LocalDate.parse("2021-08-04"); + ExerciseGuide 운동_가이드 = 걸음수_운동_가이드(oauthId, createdAt); + exerciseGuideRepository.save(운동_가이드); + + // when + List.of(CommonCode.STEP_COUNT, CommonCode.HEALTH, CommonCode.RUN) + .forEach(type -> exerciseGuideGenerateService.removeGuide(oauthId, createdAt.minusDays(1), type)); + + // then + assertThatThrownBy(() -> exerciseGuideSearchService.findByOauthIdAndCreatedAt(oauthId, createdAt)) + .isInstanceOf(GuideNotFoundException.class); } -} +} \ No newline at end of file diff --git a/src/test/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateServiceTest.java index 519458a6..9daf0374 100644 --- a/src/test/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/guide/weight/service/WeightGuideGenerateServiceTest.java @@ -1,9 +1,13 @@ package com.coniverse.dangjang.domain.guide.weight.service; import static com.coniverse.dangjang.fixture.AnalysisDataFixture.*; +import static com.coniverse.dangjang.fixture.GuideFixture.*; import static com.coniverse.dangjang.fixture.UserFixture.*; import static org.assertj.core.api.Assertions.*; +import java.time.LocalDate; +import java.util.Optional; + import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; @@ -17,6 +21,7 @@ import com.coniverse.dangjang.domain.analysis.dto.healthMetric.WeightAnalysisData; import com.coniverse.dangjang.domain.analysis.strategy.WeightAnalysisStrategy; +import com.coniverse.dangjang.domain.code.enums.CommonCode; import com.coniverse.dangjang.domain.guide.common.exception.GuideNotFoundException; import com.coniverse.dangjang.domain.guide.weight.document.WeightGuide; import com.coniverse.dangjang.domain.guide.weight.repository.WeightGuideRepository; @@ -75,4 +80,19 @@ void setUp() { WeightGuide 등록된_건강지표 = weightGuideRepository.findByOauthIdAndCreatedAt(테오_아이디, 등록_일자).orElseThrow(GuideNotFoundException::new); assertThat(등록된_건강지표.getContent()).isEqualTo(weightGuideGenerateService.createContent((WeightAnalysisData)data)); } + + @Test + void 체중_가이드를_성공적으로_삭제한다() { + // given + String oauthId = 테오_아이디; + String createdAt = "2023-11-01"; + weightGuideRepository.save(체중_가이드(oauthId, createdAt)); + + // when + weightGuideGenerateService.removeGuide(oauthId, LocalDate.parse(createdAt), CommonCode.MEASUREMENT); + + // then + Optional 삭제된_가이드 = weightGuideRepository.findByOauthIdAndCreatedAt(oauthId, createdAt); + assertThat(삭제된_가이드).isEmpty(); + } } diff --git a/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricControllerTest.java b/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricControllerTest.java index 1a9db23b..a1222c7e 100644 --- a/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricControllerTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthMetricControllerTest.java @@ -45,6 +45,13 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class HealthMetricControllerTest extends ControllerTest { public static final String URL = "/api/health-metric"; + public static LocalDate 시작_날짜 = LocalDate.parse("2023-12-31"); + public static LocalDate 마지막_날짜 = LocalDate.parse("2024-01-06"); + public static LocalDate 생성_날짜 = LocalDate.of(2023, 12, 31); + public static List 혈당차트 = 혈당차트_생성(생성_날짜, 100, 200); + public static List 체중차트 = 체중차트_생성(생성_날짜, 100); + public static List 걸음수차트 = 걸음수차트_생성(생성_날짜, 10000); + public static List 칼로리차트 = 칼로리차트_생성(생성_날짜, 400); private final HealthMetricResponse response = 건강지표_등록_응답(); private String postContent; private String patchContent; @@ -54,13 +61,6 @@ class HealthMetricControllerTest extends ControllerTest { private HealthMetricChartSearchService healthMetricChartSearchService; @Autowired private HealthMetricSearchService healthMetricSearchService; - public static LocalDate 시작_날짜 = LocalDate.parse("2023-12-31"); - public static LocalDate 마지막_날짜 = LocalDate.parse("2024-01-06"); - public static LocalDate 생성_날짜 = LocalDate.of(2023, 12, 31); - public static List 혈당차트 = 혈당차트_생성(생성_날짜, 100, 200); - public static List 체중차트 = 체중차트_생성(생성_날짜, 100); - public static List 걸음수차트 = 걸음수차트_생성(생성_날짜, 10000); - public static List 칼로리차트 = 칼로리차트_생성(생성_날짜, 400); @BeforeAll void setUp() throws JsonProcessingException { @@ -271,4 +271,58 @@ void setUp() throws JsonProcessingException { jsonPath("$.data.date").value(response.date().toString()) ); } + + @Test + void 건강지표를_성공적으로_삭제한다() throws Exception { + // given + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("date", "2021-01-01"); + params.add("type", "아침식전"); + + // when + ResultActions resultActions = delete(mockMvc, URL, params); + + // then + resultActions.andExpectAll( + status().isNoContent() + ); + } + + @ParameterizedTest + @ValueSource(strings = {"2021-01-51", "2021-02-29", "2021-04-31", "2021-06-31", "2021-09-31", "2021-11-31", "2021.01.01", "2021/01/01", "2021-1-1"}) + void 잘못된_날짜_parameter를_전달할_경우_400에러를_반환한다(String date) throws Exception { + // given + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("date", date); + params.add("type", "아침식전"); + + // when + ResultActions resultActions = delete(mockMvc, URL, params); + + // then + resultActions.andExpectAll( + status().isBadRequest(), + jsonPath("$.errorCode").value(400), + jsonPath("$.violationErrors[0].rejectedValue").value(date) + ); + } + + @ParameterizedTest + @ValueSource(strings = {" ", ""}) + void 잘못된_타입_parameter를_전달할_경우_400에러를_반환한다(String type) throws Exception { + // given + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("date", "2021-01-01"); + params.add("type", type); + + // when + ResultActions resultActions = delete(mockMvc, URL, params); + + // then + resultActions.andExpectAll( + status().isBadRequest(), + jsonPath("$.errorCode").value(400), + jsonPath("$.violationErrors[0].rejectedValue").value(type) + ); + } } diff --git a/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterServiceTest.java index d3966c02..60db149d 100644 --- a/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricRegisterServiceTest.java @@ -5,6 +5,8 @@ import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; +import java.time.LocalDate; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.MethodOrderer; @@ -23,7 +25,9 @@ import com.coniverse.dangjang.domain.healthmetric.dto.request.HealthMetricPostRequest; import com.coniverse.dangjang.domain.healthmetric.dto.response.HealthMetricResponse; import com.coniverse.dangjang.domain.healthmetric.entity.HealthMetric; +import com.coniverse.dangjang.domain.healthmetric.exception.HealthMetricNotFoundException; import com.coniverse.dangjang.domain.healthmetric.repository.HealthMetricRepository; +import com.coniverse.dangjang.domain.user.entity.User; import com.coniverse.dangjang.domain.user.repository.UserRepository; import com.coniverse.dangjang.global.util.EnumFindUtil; @@ -45,12 +49,15 @@ class HealthMetricRegisterServiceTest { private AnalysisService analysisService; @MockBean private GuideService guideService; - private String 테오_아이디; + private User user; + private String oauthId; private HealthMetric 등록된_건강지표; + private HealthMetric 수정된_건강지표; @BeforeAll void setUp() { - 테오_아이디 = userRepository.save(유저_테오()).getOauthId(); + user = userRepository.save(유저_테오()); + oauthId = user.getOauthId(); } @AfterAll @@ -66,17 +73,17 @@ void tearDown() { HealthMetricPostRequest request = 건강지표_등록_요청(); // when - HealthMetricResponse response = healthMetricRegisterService.register(request, 테오_아이디); + HealthMetricResponse response = healthMetricRegisterService.register(request, oauthId); // then 등록된_건강지표 = healthMetricRepository - .findByHealthMetricId(테오_아이디, response.createdAt(), EnumFindUtil.findByTitle(CommonCode.class, response.type())).orElseThrow(); + .findByHealthMetricId(oauthId, response.createdAt(), EnumFindUtil.findByTitle(CommonCode.class, response.type())).orElseThrow(); assertAll( () -> assertThat(등록된_건강지표.getType().getTitle()).isEqualTo(request.type()), () -> assertThat(등록된_건강지표.getUnit()).isEqualTo(request.unit()), () -> assertThat(등록된_건강지표.getCreatedAt()).isEqualTo(request.createdAt()), - () -> assertThat(등록된_건강지표.getOauthId()).isEqualTo(테오_아이디) + () -> assertThat(등록된_건강지표.getOauthId()).isEqualTo(oauthId) ); } @@ -87,12 +94,12 @@ void tearDown() { HealthMetricPatchRequest request = 단위_변경한_건강지표_수정_요청(); // when - HealthMetricResponse response = healthMetricRegisterService.update(request, 테오_아이디); + HealthMetricResponse response = healthMetricRegisterService.update(request, oauthId); // then HealthMetric 수정된_건강지표 = healthMetricRepository - .findByHealthMetricId(테오_아이디, response.createdAt(), EnumFindUtil.findByTitle(CommonCode.class, response.type())).orElseThrow(); + .findByHealthMetricId(oauthId, response.createdAt(), EnumFindUtil.findByTitle(CommonCode.class, response.type())).orElseThrow(); assertAll( () -> assertThat(수정된_건강지표.getUnit()).isNotEqualTo(등록된_건강지표.getUnit()), @@ -110,11 +117,11 @@ void tearDown() { HealthMetricPatchRequest request = 타입_변경한_건강지표_수정_요청(); // when - HealthMetricResponse response = healthMetricRegisterService.update(request, 테오_아이디); + HealthMetricResponse response = healthMetricRegisterService.update(request, oauthId); // then - HealthMetric 수정된_건강지표 = healthMetricRepository - .findByHealthMetricId(테오_아이디, response.createdAt(), EnumFindUtil.findByTitle(CommonCode.class, response.type())).orElseThrow(); + 수정된_건강지표 = healthMetricRepository + .findByHealthMetricId(oauthId, response.createdAt(), EnumFindUtil.findByTitle(CommonCode.class, response.type())).orElseThrow(); assertAll( () -> assertThat(수정된_건강지표.getType().getTitle()).isEqualTo(request.newType()), @@ -123,4 +130,30 @@ void tearDown() { () -> assertThat(수정된_건강지표.getType()).isNotEqualTo(등록된_건강지표.getType()) ); } + + @Order(300) + @Test + void 건강지표를_성공적으로_삭제한다() { + // given + CommonCode type = 수정된_건강지표.getType(); + LocalDate createdAt = 수정된_건강지표.getCreatedAt(); + + // when + healthMetricRegisterService.remove(createdAt.toString(), type.getTitle(), oauthId); + + // then + assertThat(healthMetricRepository.findByHealthMetricId(oauthId, createdAt, type)).isEmpty(); + } + + @Order(400) + @Test + void 존재하지_않는_건강지표를_삭제할_경우_예외가_발생한다() { + // given + String type = 수정된_건강지표.getType().getTitle(); + String createdAt = 수정된_건강지표.getCreatedAt().toString(); + + // when & then + assertThatThrownBy(() -> healthMetricRegisterService.remove(createdAt, type, oauthId)) + .isInstanceOf(HealthMetricNotFoundException.class); + } } diff --git a/src/test/java/com/coniverse/dangjang/domain/intro/controller/IntroControllerTest.java b/src/test/java/com/coniverse/dangjang/domain/intro/controller/IntroControllerTest.java deleted file mode 100644 index c54b1586..00000000 --- a/src/test/java/com/coniverse/dangjang/domain/intro/controller/IntroControllerTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.coniverse.dangjang.domain.intro.controller; - -import static com.coniverse.dangjang.support.SimpleMockMvc.*; -import static org.mockito.BDDMockito.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.test.web.servlet.ResultActions; - -import com.coniverse.dangjang.domain.intro.dto.IntroResponse; -import com.coniverse.dangjang.domain.intro.dto.Version; -import com.coniverse.dangjang.domain.intro.service.IntroService; -import com.coniverse.dangjang.global.exception.BadRequestException; -import com.coniverse.dangjang.support.ControllerTest; - -/** - * @author TEO - * @since 1.0.0 - */ -class IntroControllerTest extends ControllerTest { - private static final String URI = "/api/intro"; - private static final String MIN_VERSION = Version.MINIMUM.getVersion(); - private static final String LATEST_VERSION = Version.LATEST.getVersion(); - @Autowired - private IntroService introService; - - @Nested - class Test_Intro_URL에_접근시 { - @Test - void 성공한_응답을_반환한다() throws Exception { - // given - IntroResponse introResponse = new IntroResponse<>(MIN_VERSION, LATEST_VERSION, null); - given(introService.getTestIntroResponse()).willReturn(introResponse); - - // when - ResultActions resultActions = get(mockMvc, URI + "/test"); - - // then - resultActions.andExpectAll( - status().isOk(), - jsonPath("$.message").value(HttpStatus.OK.getReasonPhrase()), - jsonPath("$.data.minVersion").value(introResponse.minVersion()), - jsonPath("$.data.latestVersion").value(introResponse.latestVersion()) - ); - } - - @Test - void 실패한_응답을_반환한다() throws Exception { - // given - given(introService.getTestIntroResponse()).willThrow(new BadRequestException()); - - // when - ResultActions resultActions = get(mockMvc, URI + "/test"); - - // then - resultActions.andExpectAll( - status().isBadRequest(), - jsonPath("$.errorCode").value(400), - jsonPath("$.message").value("잘못된 요청입니다.") - ); - } - } - - @Nested - class Prod_Intro_URL에_접근시 { - @Test - void 성공한_응답을_반환한다() throws Exception { - // given - IntroResponse introResponse = new IntroResponse<>(MIN_VERSION, LATEST_VERSION, null); - given(introService.getProdIntroResponse()).willReturn(introResponse); - - // when - ResultActions resultActions = get(mockMvc, URI + "/prod"); - - // then - resultActions.andExpectAll( - status().isOk(), - jsonPath("$.message").value(HttpStatus.OK.getReasonPhrase()), - jsonPath("$.data.minVersion").value(introResponse.minVersion()), - jsonPath("$.data.latestVersion").value(introResponse.latestVersion()) - ); - } - } -} diff --git a/src/test/java/com/coniverse/dangjang/domain/intro/service/IntroServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/intro/service/IntroServiceTest.java deleted file mode 100644 index fb8733f7..00000000 --- a/src/test/java/com/coniverse/dangjang/domain/intro/service/IntroServiceTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.coniverse.dangjang.domain.intro.service; - -import static org.assertj.core.api.Assertions.*; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import com.coniverse.dangjang.domain.intro.dto.IntroResponse; -import com.coniverse.dangjang.global.exception.BadRequestException; - -/** - * @author TEO - * @since 1.0.0 - */ -@SpringBootTest -class IntroServiceTest { - @Autowired - private IntroService introService; - - @Nested - class TestIntroResponse를 { - @Test - void 한_번_호출하면_IntroResponse가_반환된다() { - // when - IntroResponse introResponse = introService.getTestIntroResponse(); - - // then - assertThat(introResponse).isNotNull(); - } - - @Test - void 두_번_연속_호출하면_BadRequestException이_발생한다() { - // given - introService.getTestIntroResponse(); - - // when & then - assertThatThrownBy(() -> introService.getTestIntroResponse()).isInstanceOf(BadRequestException.class); - } - } - - @Nested - class ProdIntroResponse를 { - @Test - void 호출하면_IntroResponse가_반환된다() { - // when - IntroResponse introResponse = introService.getProdIntroResponse(); - - // then - assertThat(introResponse).isNotNull(); - } - } -} diff --git a/src/test/java/com/coniverse/dangjang/domain/notification/service/NotificationServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/notification/service/NotificationServiceTest.java index 0b53ccec..8a37e302 100644 --- a/src/test/java/com/coniverse/dangjang/domain/notification/service/NotificationServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/notification/service/NotificationServiceTest.java @@ -25,6 +25,7 @@ import com.coniverse.dangjang.domain.notification.repository.NotificationRepository; import com.coniverse.dangjang.domain.notification.repository.NotificationTypeRepository; import com.coniverse.dangjang.domain.notification.repository.UserFcmTokenRepository; +import com.coniverse.dangjang.domain.user.dto.request.PostFcmTokenRequest; import com.coniverse.dangjang.domain.user.entity.User; import com.coniverse.dangjang.domain.user.repository.UserRepository; @@ -50,15 +51,15 @@ class NotificationServiceTest { private UserFcmTokenRepository userFcmTokenRepository; @Autowired private NotificationTypeRepository notificationTypeRepository; - @Autowired - private NotificationSearchService notificationSearchService; private User 테오; private User 이브; private String 테오_아이디; private String 이브_아이디; private String fcmToken = "token"; + private String deviceId = "deviceId"; private String 이브_fcmToken = "token2"; + private PostFcmTokenRequest postFcmTokenRequest = fcm_등록_및_업데이트_요청(fcmToken, deviceId); @Transactional @BeforeAll @@ -69,7 +70,7 @@ void setUp() { 이브 = userRepository.save(유저_이브()); 이브.updateAccessedAt(LocalDate.now().minusDays(1)); userRepository.save(이브); - userFcmTokenRepository.save(사용자_fcmToken_엔티티(이브_fcmToken, 이브)); + userFcmTokenRepository.save(사용자_fcmToken_엔티티(이브_fcmToken, 이브, deviceId)); notificationRepository.saveAll(사용자_알림_엔티티_목록(테오)); } @@ -131,22 +132,36 @@ void tearDown() { @Test void fcmToken을_저장한다() { //when - notificationService.saveFcmToken(fcmToken, 테오_아이디); + notificationService.saveOrUpdateFcmToken(postFcmTokenRequest, 테오_아이디); //then - UserFcmToken 조회_결과 = userFcmTokenRepository.findById(fcmToken).get(); + UserFcmToken 조회_결과 = userFcmTokenRepository.findUserFcmTokenByFcmId(테오_아이디, postFcmTokenRequest.deviceId()).get(); assertThat(조회_결과.getUser().getId()).isEqualTo(테오_아이디); assertThat(조회_결과.getFcmToken()).isEqualTo(fcmToken); } + @Transactional + @Order(450) + @Test + void fcmToken을_수정한다() { + //when + UserFcmToken userFcmToken = userFcmTokenRepository.findUserFcmTokenByFcmId(이브.getOauthId(), deviceId).get(); + String newFcmToken = "새로운_fcmToken"; + notificationService.saveOrUpdateFcmToken(fcm_등록_및_업데이트_요청(newFcmToken, deviceId), 이브.getOauthId()); + //then + UserFcmToken 조회_결과 = userFcmTokenRepository.findUserFcmTokenByFcmId(이브.getOauthId(), deviceId).get(); + assertThat(조회_결과.getUser().getId()).isEqualTo(이브.getOauthId()); + assertThat(조회_결과.getFcmToken()).isEqualTo(newFcmToken); + } + @Order(500) @Test void fcmToken을_제거한다() { //given - notificationService.saveFcmToken(fcmToken, 테오_아이디); + notificationService.saveOrUpdateFcmToken(postFcmTokenRequest, 테오_아이디); //when notificationService.deleteFcmToken(fcmToken); //then - assertThat(userFcmTokenRepository.findById(fcmToken)).isEmpty(); + assertThat(userFcmTokenRepository.findUserFcmTokenByFcmId(테오_아이디, postFcmTokenRequest.deviceId())).isEmpty(); } @Order(700) diff --git a/src/test/java/com/coniverse/dangjang/domain/scheduler/service/SchedulerServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/scheduler/service/SchedulerServiceTest.java index 1557f269..21582ef8 100644 --- a/src/test/java/com/coniverse/dangjang/domain/scheduler/service/SchedulerServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/scheduler/service/SchedulerServiceTest.java @@ -44,6 +44,7 @@ class SchedulerServiceTest { private String 테오_아이디; private String 이브_아이디; private String fcmToken = "token"; + private String deviceId = "deviceId"; private String 이브_fcmToken = "token2"; @BeforeAll @@ -54,7 +55,7 @@ void setUp() { 이브 = userRepository.save(유저_이브()); 이브.updateAccessedAt(LocalDate.now().minusDays(1)); userRepository.save(이브); - userFcmTokenRepository.save(사용자_fcmToken_엔티티(이브_fcmToken, 이브)); + userFcmTokenRepository.save(사용자_fcmToken_엔티티(이브_fcmToken, 이브, deviceId)); notificationRepository.saveAll(사용자_알림_엔티티_목록(테오)); } diff --git a/src/test/java/com/coniverse/dangjang/domain/user/controller/SignupControllerTest.java b/src/test/java/com/coniverse/dangjang/domain/user/controller/SignupControllerTest.java index 3bc84745..7a7b25b2 100644 --- a/src/test/java/com/coniverse/dangjang/domain/user/controller/SignupControllerTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/user/controller/SignupControllerTest.java @@ -48,7 +48,7 @@ class SignupControllerTest extends ControllerTest { AuthToken authToken = new AuthToken(); authToken.setAccessToken("accessToken"); authToken.setRefreshToken("refreshToken"); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); given(oauthLoginService.getAuthToken(loginResponse.nickname())).willReturn(authToken.getAccessToken()); String content = objectMapper.writeValueAsString(signUpRequest); @@ -73,7 +73,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -96,7 +96,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -118,7 +118,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -141,7 +141,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -163,7 +163,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when ResultActions resultActions = post(mockMvc, URI, content); @@ -184,7 +184,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -206,7 +206,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -228,7 +228,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -250,7 +250,7 @@ class SignupControllerTest extends ControllerTest { null, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -272,7 +272,7 @@ class SignupControllerTest extends ControllerTest { false, -1, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -294,7 +294,7 @@ class SignupControllerTest extends ControllerTest { false, 0, null, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -316,7 +316,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, null, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -338,7 +338,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, diseases); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when @@ -358,7 +358,7 @@ class SignupControllerTest extends ControllerTest { false, 0, false, false, null); LoginResponse loginResponse = new LoginResponse("test", false, false); - given(userSignupService.signUp(any(), any())).willReturn(loginResponse); + given(userSignupService.signUp(any())).willReturn(loginResponse); String content = objectMapper.writeValueAsString(signUpRequest); // when diff --git a/src/test/java/com/coniverse/dangjang/domain/user/controller/UserControllerTest.java b/src/test/java/com/coniverse/dangjang/domain/user/controller/UserControllerTest.java index c3d5c001..59bc97d8 100644 --- a/src/test/java/com/coniverse/dangjang/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/user/controller/UserControllerTest.java @@ -85,18 +85,4 @@ class UserControllerTest extends ControllerTest { ); } - @WithDangjangUser - @Test - void fcmToken_등록을_성공한다() throws Exception { - // given - String subUrl = "/fcmToken"; - - // when - ResultActions resultActions = post(mockMvc, URI + subUrl); - - // then - resultActions.andExpectAll( - status().isOk() - ); - } } diff --git a/src/test/java/com/coniverse/dangjang/domain/user/service/UserSignupServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/user/service/UserSignupServiceTest.java index f9bcce96..c0180a90 100644 --- a/src/test/java/com/coniverse/dangjang/domain/user/service/UserSignupServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/user/service/UserSignupServiceTest.java @@ -39,7 +39,6 @@ class UserSignupServiceTest { private UserRepository userRepository; @Autowired private UserFcmTokenRepository userFcmTokenRepository; - private final String fcmToken = "fcmToken"; @AfterEach void tearDown() { @@ -57,7 +56,7 @@ void tearDown() { diseases); // when - LoginResponse loginResponse = userSignupService.signUp(signUpRequest, fcmToken); + LoginResponse loginResponse = userSignupService.signUp(signUpRequest); // that assertThat(loginResponse.nickname()).isEqualTo(signUpRequest.nickname()); @@ -75,7 +74,7 @@ void tearDown() { diseases); // when - LoginResponse loginResponse = userSignupService.signUp(signUpRequest, fcmToken); + LoginResponse loginResponse = userSignupService.signUp(signUpRequest); // that assertThat(loginResponse.nickname()).isEqualTo(signUpRequest.nickname()); @@ -93,7 +92,7 @@ void tearDown() { diseases); //when&that - assertThatThrownBy(() -> userSignupService.signUp(signUpRequest, fcmToken)) + assertThatThrownBy(() -> userSignupService.signUp(signUpRequest)) .isInstanceOf(IllegalArgumentException.class); } @@ -105,7 +104,7 @@ void tearDown() { SignUpRequest signUpRequest = SignUpFixture.getSignUpRequest("287873365589", "test", "naver", true, LocalDate.parse("2021-06-21"), 150, 50, "MEDIUM", false, 0, false, false, diseases); - userSignupService.signUp(signUpRequest, fcmToken); + userSignupService.signUp(signUpRequest); //when DuplicateNicknameResponse isDuplicated = userSignupService.checkDuplicatedNickname(signUpRequest.nickname()); diff --git a/src/test/java/com/coniverse/dangjang/domain/version/controller/VersionControllerTest.java b/src/test/java/com/coniverse/dangjang/domain/version/controller/VersionControllerTest.java new file mode 100644 index 00000000..3aee4994 --- /dev/null +++ b/src/test/java/com/coniverse/dangjang/domain/version/controller/VersionControllerTest.java @@ -0,0 +1,124 @@ +package com.coniverse.dangjang.domain.version.controller; + +import static com.coniverse.dangjang.fixture.VersionFixture.*; +import static com.coniverse.dangjang.support.SimpleMockMvc.*; +import static org.mockito.BDDMockito.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.test.web.servlet.ResultActions; + +import com.coniverse.dangjang.domain.version.dto.request.VersionRequest; +import com.coniverse.dangjang.domain.version.dto.response.VersionResponse; +import com.coniverse.dangjang.domain.version.service.VersionService; +import com.coniverse.dangjang.support.ControllerTest; + +/** + * @author TEO + * @since 1.3.0 + */ +class VersionControllerTest extends ControllerTest { + private static final String URI = "/api/version"; + + @Autowired + private VersionService versionService; + + @Test + void 앱_버전을_GET_요청하면_성공한_응답을_반환한다() throws Exception { + // given + VersionResponse versionResponse = 버전_응답(); + doReturn(versionResponse).when(versionService).getVersionResponse(); + + // when + ResultActions resultActions = get(mockMvc, URI + "/intro"); + + // then + resultActions.andExpectAll( + status().isOk(), + jsonPath("$.message").value(HttpStatus.OK.getReasonPhrase()), + jsonPath("$.data.minVersion").value(versionResponse.minVersion()), + jsonPath("$.data.latestVersion").value(versionResponse.latestVersion()) + ); + } + + @Test + void 앱_버전을_POST_요청하면_성공한_응답을_반환한다() throws Exception { + // given + VersionRequest versionRequest = 버전_요청(); + String content = objectMapper.writeValueAsString(versionRequest); + VersionResponse versionResponse = 버전_응답(); + doReturn(versionResponse).when(versionService).saveVersion(any()); + + // when + ResultActions resultActions = post(mockMvc, URI, content); + + // then + resultActions.andExpectAll( + status().isOk(), + jsonPath("$.message").value(HttpStatus.OK.getReasonPhrase()), + jsonPath("$.data.minVersion").value(versionResponse.minVersion()), + jsonPath("$.data.latestVersion").value(versionResponse.latestVersion()) + ); + } + + @ParameterizedTest + @ValueSource(strings = {"", " ", "1/1/1", "1.1.0 ", " 1.0.1"}) + void RequestBody의_minVersion이_잘못됐을_경우_실패한_응답을_반환한다(String minVersion) throws Exception { + // given + VersionRequest versionRequest = 버전_요청(minVersion, "1.0.1", "1234"); + String content = objectMapper.writeValueAsString(versionRequest); + + // when + ResultActions resultActions = post(mockMvc, URI, content); + + // then + resultActions.andExpectAll( + status().isBadRequest(), + jsonPath("$.errorCode").value(400), + jsonPath("$.fieldErrors[0].field").value("minVersion"), + jsonPath("$.fieldErrors[0].rejectedValue").value(minVersion) + ); + } + + @ParameterizedTest + @ValueSource(strings = {"", " ", "1/1/1", "1.1.0 ", " 1.0.1"}) + void RequestBody의_latestVersion이_잘못됐을_경우_실패한_응답을_반환한다(String latestVersion) throws Exception { + // given + VersionRequest versionRequest = 버전_요청("1.0.1", latestVersion, "1234"); + String content = objectMapper.writeValueAsString(versionRequest); + + // when + ResultActions resultActions = post(mockMvc, URI, content); + + // then + resultActions.andExpectAll( + status().isBadRequest(), + jsonPath("$.errorCode").value(400), + jsonPath("$.fieldErrors[0].field").value("latestVersion"), + jsonPath("$.fieldErrors[0].rejectedValue").value(latestVersion) + ); + } + + @ParameterizedTest + @ValueSource(strings = {"", " ", "\n"}) + void RequestBody의_key가_잘못됐을_경우_실패한_응답을_반환한다(String key) throws Exception { + // given + VersionRequest versionRequest = 버전_요청("1.0.1", "1.0.1", key); + String content = objectMapper.writeValueAsString(versionRequest); + + // when + ResultActions resultActions = post(mockMvc, URI, content); + + // then + resultActions.andExpectAll( + status().isBadRequest(), + jsonPath("$.errorCode").value(400), + jsonPath("$.fieldErrors[0].field").value("key"), + jsonPath("$.fieldErrors[0].rejectedValue").value(key) + ); + } +} diff --git a/src/test/java/com/coniverse/dangjang/domain/version/repository/VersionRepositoryTest.java b/src/test/java/com/coniverse/dangjang/domain/version/repository/VersionRepositoryTest.java new file mode 100644 index 00000000..4b3cf24c --- /dev/null +++ b/src/test/java/com/coniverse/dangjang/domain/version/repository/VersionRepositoryTest.java @@ -0,0 +1,43 @@ +package com.coniverse.dangjang.domain.version.repository; + +import static com.coniverse.dangjang.fixture.VersionFixture.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.coniverse.dangjang.domain.version.entity.Version; +import com.coniverse.dangjang.support.annotation.JpaRepositoryTest; + +/** + * @author TEO + * @since 1.3.0 + */ +@JpaRepositoryTest +class VersionRepositoryTest { + @Autowired + private VersionRepository versionRepository; + + @Test + void 가장_최근의_버전_정보를_반환한다() { + // given + int count = 30; + List versions = IntStream.rangeClosed(1, count) + .mapToObj(i -> 버전_엔티티("1.0." + i, "1.0." + i)) + .toList(); + versionRepository.saveAll(versions); + + // when + Version version = versionRepository.findFirstByOrderByCreatedAtDesc(); + + // then + assertAll( + () -> assertThat(version.getMinVersion()).isEqualTo("1.0." + count), + () -> assertThat(version.getLatestVersion()).isEqualTo("1.0." + count) + ); + } +} diff --git a/src/test/java/com/coniverse/dangjang/domain/version/service/VersionServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/version/service/VersionServiceTest.java new file mode 100644 index 00000000..940fb3f3 --- /dev/null +++ b/src/test/java/com/coniverse/dangjang/domain/version/service/VersionServiceTest.java @@ -0,0 +1,72 @@ +package com.coniverse.dangjang.domain.version.service; + +import static com.coniverse.dangjang.fixture.VersionFixture.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import com.coniverse.dangjang.domain.version.dto.request.VersionRequest; +import com.coniverse.dangjang.domain.version.dto.response.VersionResponse; +import com.coniverse.dangjang.domain.version.entity.Version; +import com.coniverse.dangjang.domain.version.repository.VersionRepository; + +/** + * @author TEO + * @since 1.3.0 + */ +class VersionServiceTest { + private VersionService versionService; + private VersionRepository versionRepository; + private static final String KEY = "1234"; + private static final String MIN_VERSION = "1.3.1"; + private static final String LATEST_VERSION = "1.3.1"; + + @BeforeEach + void setUp() { + versionRepository = Mockito.mock(VersionRepository.class); + versionService = new VersionService(versionRepository, KEY); + } + + @Test + void 버전_응답을_반환한다() { + // given + Version version = 버전_엔티티(MIN_VERSION, LATEST_VERSION); + doReturn(version).when(versionRepository).findFirstByOrderByCreatedAtDesc(); + + // when + VersionResponse versionResponse = versionService.getVersionResponse(); + + // then + assertThat(versionResponse.minVersion()).isEqualTo(MIN_VERSION); + assertThat(versionResponse.latestVersion()).isEqualTo(LATEST_VERSION); + } + + @Test + void 키가_같으면_버전을_성공적으로_저장한다() { + // given + doReturn(null) + .when(versionRepository) + .save(any()); + VersionRequest versionRequest = 버전_요청(MIN_VERSION, LATEST_VERSION, KEY); + + // when + VersionResponse versionResponse = versionService.saveVersion(versionRequest); + + // then + assertThat(versionResponse.minVersion()).isEqualTo(MIN_VERSION); + assertThat(versionResponse.latestVersion()).isEqualTo(LATEST_VERSION); + } + + @Test + void 키가_다르면_버전을_저장할_때_예외가_발생한다() { + // given + VersionRequest versionRequest = 버전_요청(MIN_VERSION, LATEST_VERSION, "wrong key"); + + // when + assertThatThrownBy(() -> versionService.saveVersion(versionRequest)) + .isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/com/coniverse/dangjang/fixture/GuideFixture.java b/src/test/java/com/coniverse/dangjang/fixture/GuideFixture.java index 07f792aa..f6583686 100644 --- a/src/test/java/com/coniverse/dangjang/fixture/GuideFixture.java +++ b/src/test/java/com/coniverse/dangjang/fixture/GuideFixture.java @@ -78,11 +78,7 @@ public class GuideFixture { return ExerciseGuide.builder() .oauthId(oauthId) - .needStepByLastWeek(0) - .comparedToLastWeek("저번주 대비 가이드입니다.") - .content("가이드 내용입니다.") .createdAt(조회_날짜) - .stepCount(0) .exerciseCalories(exerciseCalories) .build(); } @@ -118,8 +114,7 @@ public class GuideFixture { } public static WeightGuideResponse 체중_가이드_응답(String createdAt) { - return new WeightGuideResponse(CommonCode.MEASUREMENT.getTitle(), createdAt, 20, Alert.LEVEL_1_OBESITY.getTitle(), "가이드입니다", 18.0, - "50"); + return new WeightGuideResponse(CommonCode.MEASUREMENT.getTitle(), createdAt, 20, Alert.LEVEL_1_OBESITY.getTitle(), "가이드입니다", 18.0, "50"); } public static ExerciseGuideResponse 운동_가이드_응답(String 조회_날짜) { @@ -133,10 +128,6 @@ public class GuideFixture { return new ExerciseCalorie(type, calorie, unit); } - public static GuideResponse 당화혈색소_가이드_응답() { // TODO return 수정 - return null; - } - public static List 운동가이드_리스트(User user, LocalDate createdAt, int unit, int needCount) { return Stream.iterate(0, i -> i + 1).limit(needCount) .map(n -> ExerciseGuide.builder() @@ -150,7 +141,6 @@ public class GuideFixture { .stepCount(8000) .createdAt(createdAt.plusDays(n)) .build()).collect(Collectors.toList()); - } public static DayGuideResponse 하루_가이드_응답(User user, LocalDate date, List 혈당가이드, WeightDayGuide 체중가이드, ExerciseDayGuide 운동가이드) { @@ -164,5 +154,4 @@ public class GuideFixture { public static ExerciseDayGuide 운동_하루_가이드() { return new ExerciseDayGuide(1400, 11000); } - } diff --git a/src/test/java/com/coniverse/dangjang/fixture/NotificationFixture.java b/src/test/java/com/coniverse/dangjang/fixture/NotificationFixture.java index 60c2baa7..0fec4b4e 100644 --- a/src/test/java/com/coniverse/dangjang/fixture/NotificationFixture.java +++ b/src/test/java/com/coniverse/dangjang/fixture/NotificationFixture.java @@ -10,6 +10,7 @@ import com.coniverse.dangjang.domain.notification.entity.Notification; import com.coniverse.dangjang.domain.notification.entity.NotificationType; import com.coniverse.dangjang.domain.notification.entity.UserFcmToken; +import com.coniverse.dangjang.domain.user.dto.request.PostFcmTokenRequest; import com.coniverse.dangjang.domain.user.entity.User; /** @@ -53,15 +54,19 @@ public class NotificationFixture { } public static List 사용자_fcmToken_엔티티_목록() { - return List.of(사용자_fcmToken_엔티티("fcmToken1", 유저_이브()), 사용자_fcmToken_엔티티("fcmToken2", 유저_테오())); + return List.of(사용자_fcmToken_엔티티("fcmToken1", 유저_이브(), "deviceId1"), 사용자_fcmToken_엔티티("fcmToken2", 유저_테오(), "deviceId2")); } - public static UserFcmToken 사용자_fcmToken_엔티티(String fcmToken, User user) { + public static UserFcmToken 사용자_fcmToken_엔티티(String fcmToken, User user, String deviceId) { return UserFcmToken.builder() .fcmToken(fcmToken) + .deviceId(deviceId) .user(user) - .createdAt(LocalDate.now()) .build(); } + public static PostFcmTokenRequest fcm_등록_및_업데이트_요청(String fcmToken, String deviceId) { + return new PostFcmTokenRequest(fcmToken, deviceId); + } + } diff --git a/src/test/java/com/coniverse/dangjang/fixture/VersionFixture.java b/src/test/java/com/coniverse/dangjang/fixture/VersionFixture.java new file mode 100644 index 00000000..f7b54072 --- /dev/null +++ b/src/test/java/com/coniverse/dangjang/fixture/VersionFixture.java @@ -0,0 +1,42 @@ +package com.coniverse.dangjang.fixture; + +import com.coniverse.dangjang.domain.version.dto.request.VersionRequest; +import com.coniverse.dangjang.domain.version.dto.response.VersionResponse; +import com.coniverse.dangjang.domain.version.entity.Version; + +/** + * @author TEO + * @since 1.3.0 + */ +public class VersionFixture { + public static Version 버전_엔티티() { + return getVersion("1.0.0", "1.0.0"); + } + + public static Version 버전_엔티티(String minVersion, String latestVersion) { + return getVersion(minVersion, latestVersion); + } + + private static Version getVersion(String minVersion, String latestVersion) { + return Version.builder() + .minVersion(minVersion) + .latestVersion(latestVersion) + .build(); + } + + public static VersionRequest 버전_요청() { + return getVersionRequest("1.0.0", "1.0.0", "1234"); + } + + public static VersionRequest 버전_요청(String minVersion, String latestVersion, String key) { + return getVersionRequest(minVersion, latestVersion, key); + } + + private static VersionRequest getVersionRequest(String minVersion, String latestVersion, String key) { + return new VersionRequest(minVersion, latestVersion, key); + } + + public static VersionResponse 버전_응답() { + return new VersionResponse<>("1.0.0", "1.0.0", null); + } +} diff --git a/src/test/java/com/coniverse/dangjang/support/ControllerTest.java b/src/test/java/com/coniverse/dangjang/support/ControllerTest.java index aa08052e..1b762aa6 100644 --- a/src/test/java/com/coniverse/dangjang/support/ControllerTest.java +++ b/src/test/java/com/coniverse/dangjang/support/ControllerTest.java @@ -25,8 +25,6 @@ import com.coniverse.dangjang.domain.healthmetric.service.HealthMetricChartSearchService; import com.coniverse.dangjang.domain.healthmetric.service.HealthMetricRegisterService; import com.coniverse.dangjang.domain.healthmetric.service.HealthMetricSearchService; -import com.coniverse.dangjang.domain.intro.controller.IntroController; -import com.coniverse.dangjang.domain.intro.service.IntroService; import com.coniverse.dangjang.domain.log.controller.AppLogController; import com.coniverse.dangjang.domain.log.service.LogService; import com.coniverse.dangjang.domain.notification.controller.NotificationController; @@ -39,6 +37,8 @@ import com.coniverse.dangjang.domain.user.service.MypageService; import com.coniverse.dangjang.domain.user.service.UserSignupService; import com.coniverse.dangjang.domain.user.service.UserWithdrawalService; +import com.coniverse.dangjang.domain.version.controller.VersionController; +import com.coniverse.dangjang.domain.version.service.VersionService; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -51,7 +51,7 @@ */ @WebMvcTest( controllers = { - IntroController.class, + VersionController.class, HealthMetricController.class, LoginController.class, SignupController.class, @@ -75,7 +75,7 @@ public class ControllerTest { @Autowired protected ObjectMapper objectMapper; @MockBean - private IntroService introService; + private VersionService versionService; @MockBean private OauthLoginService oAuthLoginService; @MockBean @@ -110,5 +110,4 @@ public class ControllerTest { private NotificationService notificationService; @MockBean private HealthMetricSearchService healthMetricSearchService; - } diff --git a/src/test/java/com/coniverse/dangjang/support/SimpleMockMvc.java b/src/test/java/com/coniverse/dangjang/support/SimpleMockMvc.java index 4329d60f..7d5a0596 100644 --- a/src/test/java/com/coniverse/dangjang/support/SimpleMockMvc.java +++ b/src/test/java/com/coniverse/dangjang/support/SimpleMockMvc.java @@ -87,4 +87,13 @@ public static ResultActions delete(final MockMvc mockMvc, final String uri, fina .accept(MediaType.APPLICATION_JSON) ); } + + public static ResultActions delete(final MockMvc mockMvc, final String uri, final MultiValueMap params, + final Object... pathVariables) throws Exception { + return mockMvc.perform( + MockMvcRequestBuilders.delete(uri, pathVariables) + .params(params) + .accept(MediaType.APPLICATION_JSON) + ); + } } diff --git a/src/test/resources/config/application.yml b/src/test/resources/config/application.yml index d9714a2b..43d09e5a 100644 --- a/src/test/resources/config/application.yml +++ b/src/test/resources/config/application.yml @@ -47,9 +47,9 @@ jwt: exp: 3600000 fluentbit: - app-log-url: http://localhost:8888/app.log - server-log-url: http://localhost:8888/server.log - notification-url: http://localhost:8888/notification + app-log-url: http://localhost:1234/app.log + server-log-url: http://localhost:1234/server.log + notification-url: http://localhost:1234/notification cors: allowed-origins: "*" @@ -62,6 +62,9 @@ oauth: url: api: https://openapi.naver.com +version: + key: "1234" + logging: level: org: diff --git a/src/test/resources/schema.sql b/src/test/resources/schema.sql deleted file mode 100644 index 31ad0ca8..00000000 --- a/src/test/resources/schema.sql +++ /dev/null @@ -1,166 +0,0 @@ -DROP TABLE IF EXISTS DISEASE; -DROP TABLE IF EXISTS NOTIFICATION_SETTING; -DROP TABLE IF EXISTS NOTIFICATION; -DROP TABLE IF EXISTS USER_FCM_TOKEN; -DROP TABLE IF EXISTS NOTIFICATION_TYPE; -DROP TABLE IF EXISTS DEVICE; -DROP TABLE IF EXISTS HEALTH_METRIC; --- DROP TABLE IF EXISTS CODE; -DROP TABLE IF EXISTS DANGJANG_CLUB; -DROP TABLE IF EXISTS POINT_HISTORY; -DROP TABLE IF EXISTS PURCHASE_HISTORY; -DROP TABLE IF EXISTS POINT_PRODUCT; -DROP TABLE IF EXISTS USER_POINT; -DROP TABLE IF EXISTS USERS; -DROP TABLE IF EXISTS SHEDLOCK; - -CREATE TABLE `USERS` -( - `OAUTH_ID` varchar(50) NOT NULL, - `NICKNAME` varchar(8) NOT NULL, - `OAUTH_PROVIDER` varchar(10) NOT NULL, - `GENDER` varchar(1) NOT NULL, - `BIRTHDAY` date NOT NULL, - `ACTIVITY_AMOUNT` varchar(10) NOT NULL, - `HEIGHT` int NOT NULL, - `ROLE` varchar(10) NOT NULL, - `RECOMMENDED_CALORIE` int NOT NULL, - `STATUS` varchar(10) NOT NULL, - `CREATED_AT` datetime NOT NULL, - `UPDATED_AT` datetime NOT NULL, - `PROFILE_IMAGE_PATH` varchar(255), - `DIABETIC` boolean NOT NULL, - `DIABETES_YEAR` int, - `MEDICINE` boolean, - `INJECTION` boolean, - `ACCESSED_AT` date NOT NULL, - `HEALTH_CONNECT` varchar(50) NOT NULL, - `INACTIVATED_AT` date, - PRIMARY KEY (`OAUTH_ID`), - UNIQUE (`NICKNAME`) -); - -CREATE TABLE `DANGJANG_CLUB` -( - `OAUTH_ID` varchar(50) NOT NULL, - `START_DATE` date NOT NULL, - PRIMARY KEY (`OAUTH_ID`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) -); - -CREATE TABLE `HEALTH_METRIC` -( - `OAUTH_ID` varchar(50) NOT NULL, - `CREATED_AT` date NOT NULL, - `TYPE` varchar(20) NOT NULL, - `GROUP_CODE` varchar(20) NOT NULL, - `UNIT` varchar(20) NOT NULL, - PRIMARY KEY (`OAUTH_ID`, `CREATED_AT`, `TYPE`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) -); - -CREATE TABLE `DEVICE` -( - `OAUTH_ID` varchar(50) NOT NULL, - `CODE` varchar(20) NOT NULL, - PRIMARY KEY (`OAUTH_ID`, `CODE`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) -); - -CREATE TABLE `NOTIFICATION_SETTING` -( - `OAUTH_ID` varchar(50) NOT NULL, - `CODE` varchar(20) NOT NULL, - PRIMARY KEY (`OAUTH_ID`, `CODE`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) -); - -CREATE TABLE `DISEASE` -( - `OAUTH_ID` varchar(50) NOT NULL, - `CODE` varchar(20) NOT NULL, - PRIMARY KEY (`OAUTH_ID`, `CODE`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) -); - -CREATE TABLE `POINT_PRODUCT` -( - `PRODUCT_NAME` varchar(255) NOT NULL, - `POINT` int, - `TYPE` varchar(20) NOT NULL, - `DESCRIPTION` varchar(255), - PRIMARY KEY (`PRODUCT_NAME`) -); - -CREATE TABLE `POINT_HISTORY` -( - `OAUTH_ID` varchar(50) NOT NULL, - `CREATED_AT` dateTime NOT NULL, - `PRODUCT_NAME` varchar(255) NOT NULL, - `CHANGE_POINT` int, - `BALANCE_POINT` int, - PRIMARY KEY (`OAUTH_ID`, `CREATED_AT`, `PRODUCT_NAME`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`), - FOREIGN KEY (`PRODUCT_NAME`) REFERENCES POINT_PRODUCT (`PRODUCT_NAME`) -); - -CREATE TABLE `USER_POINT` -( - `OAUTH_ID` varchar(50) NOT NULL, - `POINT` int, - `VERSION` bigint, - PRIMARY KEY (`OAUTH_ID`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) -); - -CREATE TABLE `PURCHASE_HISTORY` -( - `OAUTH_ID` varchar(50) NOT NULL, - `PRODUCT_NAME` varchar(255) NOT NULL, - `CREATED_AT` dateTime NOT NULL, - `PHONE` varchar(20) NOT NULL, - `NAME` varchar(20) NOT NULL, - `COMMENT` varchar(255), - `COMPLETED` boolean, - PRIMARY KEY (`OAUTH_ID`, `PRODUCT_NAME`, `CREATED_AT`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`), - FOREIGN KEY (`PRODUCT_NAME`) REFERENCES POINT_PRODUCT (`PRODUCT_NAME`) -); - - - -CREATE TABLE `USER_FCM_TOKEN` -( - `OAUTH_ID` varchar(50) NOT NULL, - `FCM_TOKEN` varchar(255) NOT NULL, - `CREATED_AT` dateTime NOT NULL, - PRIMARY KEY (`FCM_TOKEN`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`) -); - -CREATE TABLE `NOTIFICATION_TYPE` -( - `TYPE` varchar(20) NOT NULL, - PRIMARY KEY (`TYPE`) -); - -CREATE TABLE `NOTIFICATION` -( - `NOTIFICATION_ID` INT NOT NULL AUTO_INCREMENT, - `TITLE` varchar(255) NOT NULL, - `CONTENT` varchar(255) NOT NULL, - `OAUTH_ID` varchar(50) NOT NULL, - `TYPE` varchar(20) NOT NULL, - `CREATED_AT` dateTime NOT NULL, - `IS_READ` boolean NOT NULL, - PRIMARY KEY (`NOTIFICATION_ID`), - FOREIGN KEY (`OAUTH_ID`) REFERENCES USERS (`OAUTH_ID`), - FOREIGN KEY (`TYPE`) REFERENCES NOTIFICATION_TYPE (`TYPE`) -); -CREATE TABLE `SHEDLOCK` ( - `NAME` VARCHAR(64), - `LOCK_UNTIL` TIMESTAMP(3) NULL, - `LOCKED_AT` TIMESTAMP(3) NULL, - `LOCKED_BY` VARCHAR(255), - PRIMARY KEY (NAME) -) \ No newline at end of file diff --git a/src/test/resources/schema.sql b/src/test/resources/schema.sql new file mode 120000 index 00000000..7e7f2325 --- /dev/null +++ b/src/test/resources/schema.sql @@ -0,0 +1 @@ +../../main/resources/schema-dev.sql \ No newline at end of file