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 33d4e218..ff5aa92e 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 @@ -21,6 +21,7 @@ import com.coniverse.dangjang.domain.auth.mapper.AuthMapper; import com.coniverse.dangjang.domain.auth.repository.BlackTokenRepository; import com.coniverse.dangjang.domain.auth.repository.RefreshTokenRepository; +import com.coniverse.dangjang.domain.healthmetric.enums.HealthConnect; import com.coniverse.dangjang.domain.infrastructure.auth.client.OAuthClient; import com.coniverse.dangjang.domain.infrastructure.auth.dto.OAuthInfoResponse; import com.coniverse.dangjang.domain.notification.service.NotificationService; @@ -82,8 +83,9 @@ public LoginResponse login(OauthLoginRequest params, String fcmToken) { 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, false); + return new LoginResponse(user.getNickname(), false, healthConnect.isConnecting()); } /** 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 cbf7342b..02cc2f09 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 @@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.coniverse.dangjang.domain.healthmetric.dto.HealthMetricLastDateResponse; import com.coniverse.dangjang.domain.healthmetric.dto.request.HealthMetricPatchRequest; import com.coniverse.dangjang.domain.healthmetric.dto.request.HealthMetricPostRequest; import com.coniverse.dangjang.domain.healthmetric.dto.response.HealthMetricChartResponse; @@ -22,6 +23,7 @@ import com.coniverse.dangjang.domain.healthmetric.exception.SameTypeException; 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.global.dto.SuccessSingleResponse; import com.coniverse.dangjang.global.validator.ValidLocalDate; @@ -41,6 +43,7 @@ public class HealthMetricController { private final HealthMetricRegisterService healthMetricRegisterService; private final HealthMetricChartSearchService healthMetricChartSearchService; + private final HealthMetricSearchService healthMetricSearchService; /** * HTTP POST METHOD @@ -85,4 +88,19 @@ public ResponseEntity> getHealt LocalDate.parse(endDate)); return ResponseEntity.ok().body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), response)); } + + /** + * 마지막 건강지표 생성일을 조회한다 + * + * @param principal 유저 정보 + * @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)); + } } diff --git a/src/main/java/com/coniverse/dangjang/domain/healthmetric/dto/HealthMetricLastDateResponse.java b/src/main/java/com/coniverse/dangjang/domain/healthmetric/dto/HealthMetricLastDateResponse.java new file mode 100644 index 00000000..ec3b589c --- /dev/null +++ b/src/main/java/com/coniverse/dangjang/domain/healthmetric/dto/HealthMetricLastDateResponse.java @@ -0,0 +1,12 @@ +package com.coniverse.dangjang.domain.healthmetric.dto; + +import java.time.LocalDate; + +/** + * health metric last Date + * + * @author EVE + * @since 1.1.0 + */ +public record HealthMetricLastDateResponse(LocalDate date) { +} diff --git a/src/main/java/com/coniverse/dangjang/domain/healthmetric/enums/HealthConnect.java b/src/main/java/com/coniverse/dangjang/domain/healthmetric/enums/HealthConnect.java index c8a7fe9d..339da121 100644 --- a/src/main/java/com/coniverse/dangjang/domain/healthmetric/enums/HealthConnect.java +++ b/src/main/java/com/coniverse/dangjang/domain/healthmetric/enums/HealthConnect.java @@ -1,5 +1,8 @@ package com.coniverse.dangjang.domain.healthmetric.enums; +import lombok.AllArgsConstructor; +import lombok.Getter; + /** * health connect 연동여부 Enum *

@@ -8,8 +11,12 @@ * @author EVE * @since 1.0.0 */ +@AllArgsConstructor +@Getter public enum HealthConnect { - NEVER_CONNECTED, - CONNECTING, - DISCONNECTED + NEVER_CONNECTED(false), + CONNECTING(true), + DISCONNECTED(false); + + boolean isConnecting; } diff --git a/src/main/java/com/coniverse/dangjang/domain/healthmetric/repository/HealthMetricRepository.java b/src/main/java/com/coniverse/dangjang/domain/healthmetric/repository/HealthMetricRepository.java index b1cc7bdd..15251db9 100644 --- a/src/main/java/com/coniverse/dangjang/domain/healthmetric/repository/HealthMetricRepository.java +++ b/src/main/java/com/coniverse/dangjang/domain/healthmetric/repository/HealthMetricRepository.java @@ -67,4 +67,14 @@ public interface HealthMetricRepository extends JpaRepository findLastWeekByGroupCodeAndCreatedAt(String oauthId, GroupCode groupCode, LocalDate startDate, LocalDate endDate); + + /** + * 사용자의 health metrics 마지막 생성일 조회 + * + * @param oauthId 사용자 ID + * @return CreatedAt + * @since 1.1.0 + */ + @Query("SELECT h.healthMetricId.createdAt FROM HealthMetric h WHERE h.healthMetricId.oauthId = ?1 ORDER BY h.healthMetricId.createdAt DESC LIMIT 1") + Optional findCreatedAtByOauthId(String oauthId); } diff --git a/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchService.java b/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchService.java index 8596a7a9..9137d0b2 100644 --- a/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchService.java +++ b/src/main/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchService.java @@ -8,6 +8,7 @@ import com.coniverse.dangjang.domain.code.enums.CommonCode; import com.coniverse.dangjang.domain.code.enums.GroupCode; +import com.coniverse.dangjang.domain.healthmetric.dto.HealthMetricLastDateResponse; import com.coniverse.dangjang.domain.healthmetric.entity.HealthMetric; import com.coniverse.dangjang.domain.healthmetric.exception.HealthMetricNotFoundException; import com.coniverse.dangjang.domain.healthmetric.repository.HealthMetricRepository; @@ -76,4 +77,17 @@ public List findWeeklyHealthMetricById(String oauthId, CommonCode public List findWeeklyHealthMetricByGroupCode(String oauthId, GroupCode code, LocalDate startDate, LocalDate endDate) { return healthMetricRepository.findLastWeekByGroupCodeAndCreatedAt(oauthId, code, startDate, endDate); } + + /** + * 유저의 마지막 건강 지표 생성일을 조회한다. + * + * @param oauthId 유저 아이디 + * @return HealthMetricLastDateResponse 유저의 마지막 건강 지표 생성일 + * @throws HealthMetricNotFoundException 유저의 건강 지표를 찾을 수 없을 경우 발생한다. + * @since 1.1.0 + */ + public HealthMetricLastDateResponse findHealthMetricLastDate(String oauthId) { + LocalDate lastDate = healthMetricRepository.findCreatedAtByOauthId(oauthId).orElseThrow(HealthMetricNotFoundException::new); + return new HealthMetricLastDateResponse(lastDate); + } } 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 aec468a4..ba57f4a6 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 @@ -46,7 +46,7 @@ public class UserController { // TODO 전체 수정 (위치: signup, 이름: dup */ @GetMapping("/duplicateNickname") public ResponseEntity> checkDuplicateNickname( - @RequestParam @Pattern(regexp = "^[ㄱ-ㅎ가-힣a-zA-Z0-9]{1,8}$", message = "닉네임은 영어,한글,숫자 1~8글자 이내로 이루어져있어야 합니다.") @NotBlank(message = "닉네임은 1~8글자 이내여야 합니다.") String nickname) { + @RequestParam @Pattern(regexp = "^[가-힣ㄱ-ㅎㅏ-ㅣa-zA-Z0-9]{1,8}$", message = "닉네임은 영어,한글,숫자 1~8글자 이내로 이루어져있어야 합니다.") @NotBlank(message = "닉네임은 1~8글자 이내여야 합니다.") String nickname) { DuplicateNicknameResponse duplicateNicknameResponse = userSignupService.checkDuplicatedNickname(nickname); return ResponseEntity.ok().body(new SuccessSingleResponse<>(HttpStatus.OK.getReasonPhrase(), duplicateNicknameResponse)); } diff --git a/src/main/java/com/coniverse/dangjang/domain/user/dto/request/SignUpRequest.java b/src/main/java/com/coniverse/dangjang/domain/user/dto/request/SignUpRequest.java index 3e09668d..3bd8d25c 100644 --- a/src/main/java/com/coniverse/dangjang/domain/user/dto/request/SignUpRequest.java +++ b/src/main/java/com/coniverse/dangjang/domain/user/dto/request/SignUpRequest.java @@ -18,7 +18,7 @@ public record SignUpRequest(@NotBlank(message = "oauth 접근 토큰은 필수로 입력해야 합니다.") String accessToken, @Pattern(regexp = "^[a-z]*$", message = "provider는 소문자여야 합니다.") @NotBlank(message = "oauth provider는 필수로 입력해야 합니다.") String provider, - @Pattern(regexp = "^[ㄱ-ㅎ가-힣a-zA-Z0-9]{1,8}$", message = "닉네임은 영어,한글,숫자 1~8글자 이내로 이루어져있어야 합니다.") String nickname, + @Pattern(regexp = "^[가-힣ㄱ-ㅎㅏ-ㅣa-zA-Z0-9]{1,8}$", message = "닉네임은 영어,한글,숫자 1~8글자 이내로 이루어져있어야 합니다.") String nickname, @NotNull(message = "성별은 필수로 입력해야 합니다.") Boolean gender, @NotNull(message = "생년월일은 필수로 입력해야 합니다.") @Past(message = "생년월일은 현재보다 과거이어야 합니다.") LocalDate birthday, diff --git a/src/main/java/com/coniverse/dangjang/domain/user/repository/UserRepository.java b/src/main/java/com/coniverse/dangjang/domain/user/repository/UserRepository.java index 7fca50a2..7e00e61c 100644 --- a/src/main/java/com/coniverse/dangjang/domain/user/repository/UserRepository.java +++ b/src/main/java/com/coniverse/dangjang/domain/user/repository/UserRepository.java @@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import com.coniverse.dangjang.domain.healthmetric.enums.HealthConnect; import com.coniverse.dangjang.domain.user.entity.User; /** @@ -29,4 +30,14 @@ public interface UserRepository extends JpaRepository { */ @Query("SELECT u FROM users u left join fetch u.userPoint up where u.oauthId = :oauthId") Optional findJoinUserPoint(@Param("oauthId") String oauthId); + + /** + * health connect 연동 여부 조회 + * + * @param oauthId 사용자 pk + * @return HealthConnect 연동여부 + * @since 1.1.0 + */ + @Query("SELECT u.healthConnect FROM users u WHERE u.oauthId = :oauthId") + HealthConnect findHealthConnectByOauthId(String oauthId); } diff --git a/src/main/java/com/coniverse/dangjang/domain/user/service/UserSearchService.java b/src/main/java/com/coniverse/dangjang/domain/user/service/UserSearchService.java index c5932c01..93263f25 100644 --- a/src/main/java/com/coniverse/dangjang/domain/user/service/UserSearchService.java +++ b/src/main/java/com/coniverse/dangjang/domain/user/service/UserSearchService.java @@ -5,6 +5,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.coniverse.dangjang.domain.healthmetric.enums.HealthConnect; import com.coniverse.dangjang.domain.user.entity.User; import com.coniverse.dangjang.domain.user.exception.NonExistentUserException; import com.coniverse.dangjang.domain.user.repository.UserRepository; @@ -56,4 +57,14 @@ public Optional findNickname(String nickname) { public User findJoinUserPoint(String oauthId) { return userRepository.findJoinUserPoint(oauthId).orElseThrow(NonExistentUserException::new); } + + /** + * 헬스커넥트 연동 여부를 조회한다. + * + * @param oauthId 사용자 PK + * @return boolean 헬스커넥트 연동 여부 + */ + public HealthConnect findInterlockHealthConnect(String oauthId) { + return userRepository.findHealthConnectByOauthId(oauthId); + } } 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 595cc28d..b2c5bfe6 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 @@ -66,7 +66,7 @@ public LoginResponse signUp(SignUpRequest signUpRequest, String fcmToken) { registerWeight(savedUser, signUpRequest.weight()); pointService.addSignupPoint(savedUser.getOauthId()); notificationService.saveFcmToken(fcmToken, savedUser.getOauthId()); - return authMapper.toLoginResponse(savedUser.getNickname(), false, false); + return authMapper.toLoginResponse(savedUser.getNickname(), false, savedUser.getHealthConnect().isConnecting()); } /** 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 4a2dc42a..5919ac96 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 @@ -89,6 +89,26 @@ void tearDown() { ); } + @Order(250) + @Test + void 헬스커넥트를_연동한_유저면_로그인시_healthConnect를_true로_반환한다() { + //given + User 이브 = userRepository.save(유저_이브()); + 이브.connectToHealthConnect(); + entityManager.flush(); + KakaoLoginRequest request = 카카오_로그인_요청(); + int tokenCount = 0; + //when + LoginResponse response = oauthLoginService.login(request, fcmToken); + + //then + assertAll( + () -> assertThat(response.nickname()).isEqualTo(이브.getNickname()), + () -> assertThat(response.dangjangClub()).isFalse(), + () -> assertThat(response.healthConnect()).isTrue() + ); + } + @Order(300) @Test void 존재하는_사용자라면_auth토큰을_발급해준다() { diff --git a/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthConnectControllerTest.java b/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthConnectControllerTest.java index c44aa9a9..428e901a 100644 --- a/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthConnectControllerTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/healthmetric/controller/HealthConnectControllerTest.java @@ -41,7 +41,7 @@ class HealthConnectControllerTest extends ControllerTest { } @Test - void 헬스_커넥를_연동하면_성공_메시지를_반환한다() throws Exception { + void 헬스_커넥트를_연동하면_성공_메시지를_반환한다() throws Exception { // given HealthConnectRegisterRequest request = 헬스_커넥트_연동_요청(true); String content = objectMapper.writeValueAsString(request); @@ -56,4 +56,5 @@ class HealthConnectControllerTest extends ControllerTest { jsonPath("$.data").doesNotExist() ); } + } \ No newline at end of file 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 27a62b07..1a9db23b 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 @@ -23,6 +23,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import com.coniverse.dangjang.domain.healthmetric.dto.HealthMetricLastDateResponse; import com.coniverse.dangjang.domain.healthmetric.dto.request.HealthMetricPatchRequest; import com.coniverse.dangjang.domain.healthmetric.dto.request.HealthMetricPostRequest; import com.coniverse.dangjang.domain.healthmetric.dto.response.BloodSugarMinMax; @@ -30,6 +31,7 @@ import com.coniverse.dangjang.domain.healthmetric.dto.response.HealthMetricResponse; 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.support.ControllerTest; import com.coniverse.dangjang.support.annotation.WithDangjangUser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -50,6 +52,8 @@ class HealthMetricControllerTest extends ControllerTest { private HealthMetricRegisterService healthMetricRegisterService; @Autowired 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); @@ -247,4 +251,24 @@ void setUp() throws JsonProcessingException { jsonPath("$.errorCode").value(400) ); } + + @Order(700) + @Test + void 건강지표_마지막_생성일을_전달한다() throws Exception { + //given + String subUrl = URL + "/last-date"; + LocalDate lastDate = LocalDate.now(); + HealthMetricLastDateResponse response = new HealthMetricLastDateResponse(lastDate); + given(healthMetricSearchService.findHealthMetricLastDate(any())).willReturn(response); + + //when + ResultActions resultActions = get(mockMvc, subUrl); + + //then + resultActions.andExpectAll( + status().isOk(), + jsonPath("$.message").value("OK"), + jsonPath("$.data.date").value(response.date().toString()) + ); + } } diff --git a/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchServiceTest.java b/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchServiceTest.java index 09e17757..86bf0d6b 100644 --- a/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchServiceTest.java +++ b/src/test/java/com/coniverse/dangjang/domain/healthmetric/service/HealthMetricSearchServiceTest.java @@ -17,6 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import com.coniverse.dangjang.domain.code.enums.CommonCode; +import com.coniverse.dangjang.domain.healthmetric.dto.HealthMetricLastDateResponse; import com.coniverse.dangjang.domain.healthmetric.entity.HealthMetric; import com.coniverse.dangjang.domain.healthmetric.exception.HealthMetricNotFoundException; import com.coniverse.dangjang.domain.healthmetric.repository.HealthMetricRepository; @@ -40,6 +41,7 @@ class HealthMetricSearchServiceTest { @Autowired private UserRepository userRepository; private String oauthId; + private LocalDate 마지막_생성일 = 조회_날짜.plusDays(10); @BeforeEach void setUpUser() { @@ -50,6 +52,7 @@ void setUpUser() { .mapToObj(i -> 건강지표_엔티티(user, 조회_타입, 조회_날짜.plusDays(i))) .toList() ); + healthMetricRepository.save(건강지표_엔티티(user, 조회_타입, 마지막_생성일)); } @Test @@ -93,7 +96,7 @@ void setUpUser() { // then assertAll( () -> assertThat(조회된_건강지표.getType()).isEqualTo(조회_타입), - () -> assertThat(조회된_건강지표.getCreatedAt()).isEqualTo(조회_날짜.plusDays(9)), + () -> assertThat(조회된_건강지표.getCreatedAt()).isEqualTo(마지막_생성일), () -> assertThat(조회된_건강지표.getOauthId()).isEqualTo(oauthId) ); } @@ -126,4 +129,14 @@ void setUpUser() { && 조회된_건강지표_리스트.get(i - 1).getCreatedAt().equals(조회_날짜.plusDays(i))) ); } + + @Test + void 건강지표_마지막_생성일을_조회한다() { + // when + HealthMetricLastDateResponse 조회된_마지막_생성일 = healthMetricSearchService.findHealthMetricLastDate(oauthId); + + // then + assertThat(조회된_마지막_생성일.date()).isEqualTo(마지막_생성일); + } + } diff --git a/src/test/java/com/coniverse/dangjang/support/ControllerTest.java b/src/test/java/com/coniverse/dangjang/support/ControllerTest.java index cdda10bf..aa08052e 100644 --- a/src/test/java/com/coniverse/dangjang/support/ControllerTest.java +++ b/src/test/java/com/coniverse/dangjang/support/ControllerTest.java @@ -24,12 +24,11 @@ import com.coniverse.dangjang.domain.healthmetric.service.HealthConnectService; 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.log.controller.AppLogController; -import com.coniverse.dangjang.domain.log.service.LogService; import com.coniverse.dangjang.domain.notification.controller.NotificationController; import com.coniverse.dangjang.domain.notification.service.NotificationService; import com.coniverse.dangjang.domain.point.controller.PointController; @@ -109,5 +108,7 @@ public class ControllerTest { private UserWithdrawalService userWithdrawalService; @MockBean private NotificationService notificationService; + @MockBean + private HealthMetricSearchService healthMetricSearchService; }