From 08141024b1ac4b5a807700722302653395b731db Mon Sep 17 00:00:00 2001 From: oxomi Date: Mon, 28 Jul 2025 23:18:55 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=98=A8=EB=8F=84=20=EC=83=81?= =?UTF-8?q?=EC=8A=B9=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?feat:=20=ED=86=B5=EC=A6=9D=20=EB=B6=80=EC=9C=84,=20=EC=9A=B4?= =?UTF-8?q?=EB=8F=99=20=EC=8B=9C=EA=B0=84=20=EA=B8=B0=EB=A1=9D&=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=EC=97=90=20=EC=98=A8=EB=8F=84=20=EC=83=81?= =?UTF-8?q?=EC=8A=B9=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/HealthRecordController.java | 45 ++++- .../health/service/HealthRecordService.java | 16 +- ...FamilyTemperatureContributionResponse.java | 2 +- .../ongi/temperature/entity/Temperature.java | 3 + .../repository/TemperatureRepository.java | 8 +- .../service/TemperatureService.java | 183 ++++++++++++++++-- .../java/ongi/HealthRecordControllerTest.java | 131 ------------- 7 files changed, 223 insertions(+), 165 deletions(-) diff --git a/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java b/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java index bfd0626..1604c98 100644 --- a/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java +++ b/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java @@ -15,12 +15,17 @@ import java.util.UUID; import ongi.health.dto.PainRecordResponse; import ongi.health.dto.ExerciseRecordResponse; +import ongi.family.service.FamilyService; +import ongi.family.dto.FamilyInfo; +import ongi.temperature.service.TemperatureService; @RestController @RequestMapping("/health") @RequiredArgsConstructor public class HealthRecordController { private final HealthRecordService healthRecordService; + private final FamilyService familyService; + private final TemperatureService temperatureService; // 통증 기록 추가 @PostMapping("/pain") @@ -30,7 +35,15 @@ public ResponseEntity addPainRecord( @RequestParam PainRecord.PainArea area, @RequestParam PainRecord.PainLevel level ) { + + FamilyInfo familyInfo = familyService.getFamily(userDetails.getUser()); + String familyId = familyInfo.code(); + PainRecord record = healthRecordService.addPainRecord(userDetails.getUser().getUuid(), date, area, level); + + // 온도 상승 + temperatureService.increaseTemperatureForParentPainInput(userDetails.getUser().getUuid(), familyId); + PainRecordResponse response = new PainRecordResponse(record); return ResponseEntity.ok(response); } @@ -42,7 +55,15 @@ public ResponseEntity addExerciseRecord( @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, @RequestParam int duration ) { + + FamilyInfo familyInfo = familyService.getFamily(userDetails.getUser()); + String familyId = familyInfo.code(); + ExerciseRecord record = healthRecordService.addExerciseRecord(userDetails.getUser().getUuid(), date, duration); + + // 온도 상승 + temperatureService.increaseTemperatureForParentExerciseInput(userDetails.getUser().getUuid(), familyId); + ExerciseRecordResponse response = new ExerciseRecordResponse(record); return ResponseEntity.ok(response); } @@ -50,9 +71,17 @@ public ResponseEntity addExerciseRecord( // 최근 7일간 통증 기록 조회 @GetMapping("/pain/view") public ResponseEntity> getParentPainRecordsForLast7Days( - @RequestParam UUID parentId + @RequestParam UUID parentId, + @AuthenticationPrincipal CustomUserDetails userDetails ) { - List response = healthRecordService.getPainRecordsForLast7Days(parentId).stream() + + FamilyInfo familyInfo = familyService.getFamily(userDetails.getUser()); + String familyId = familyInfo.code(); + + // 온도 상승 + temperatureService.increaseTemperatureForChildPainView(userDetails.getUser().getUuid(), familyId); + + List response = healthRecordService.getParentPainRecordsForLast7Days(parentId).stream() .map(PainRecordResponse::new) .toList(); return ResponseEntity.ok(response); @@ -61,9 +90,17 @@ public ResponseEntity> getParentPainRecordsForLast7Days // 최근 7일간 운동 기록 조회 @GetMapping("/exercise/view") public ResponseEntity> getParentExerciseRecordsForLast7Days( - @RequestParam UUID parentId + @RequestParam UUID parentId, + @AuthenticationPrincipal CustomUserDetails userDetails ) { - List response = healthRecordService.getExerciseRecordsForLast7Days(parentId).stream() + + FamilyInfo familyInfo = familyService.getFamily(userDetails.getUser()); + String familyId = familyInfo.code(); + + // 온도 상승 + temperatureService.increaseTemperatureForChildExerciseView(userDetails.getUser().getUuid(), familyId); + + List response = healthRecordService.getParentExerciseRecordsForLast7Days(parentId).stream() .map(ExerciseRecordResponse::new) .toList(); return ResponseEntity.ok(response); diff --git a/backend/ongi/src/main/java/ongi/health/service/HealthRecordService.java b/backend/ongi/src/main/java/ongi/health/service/HealthRecordService.java index b304c95..dd51c73 100644 --- a/backend/ongi/src/main/java/ongi/health/service/HealthRecordService.java +++ b/backend/ongi/src/main/java/ongi/health/service/HealthRecordService.java @@ -30,13 +30,6 @@ public PainRecord addPainRecord(UUID parentId, LocalDate date, PainRecord.PainAr return painRecordRepository.save(record); } - // 최근 7일간 통증 기록 조회 - public List getPainRecordsForLast7Days(UUID parentId) { - LocalDate endDate = LocalDate.now(); - LocalDate startDate = endDate.minusDays(6); // 오늘 포함 7일 - return painRecordRepository.findByParentIdAndDateBetweenOrderByDateDesc(parentId, startDate, endDate); - } - // 운동 기록 추가 @Transactional public ExerciseRecord addExerciseRecord(UUID parentId, LocalDate date, int duration) { @@ -48,8 +41,15 @@ public ExerciseRecord addExerciseRecord(UUID parentId, LocalDate date, int durat return exerciseRecordRepository.save(record); } + // 최근 7일간 통증 기록 조회 + public List getParentPainRecordsForLast7Days(UUID parentId) { + LocalDate endDate = LocalDate.now(); + LocalDate startDate = endDate.minusDays(6); // 오늘 포함 7일 + return painRecordRepository.findByParentIdAndDateBetweenOrderByDateDesc(parentId, startDate, endDate); + } + // 최근 7일간 운동 기록 조회 - public List getExerciseRecordsForLast7Days(UUID parentId) { + public List getParentExerciseRecordsForLast7Days(UUID parentId) { LocalDate endDate = LocalDate.now(); LocalDate startDate = endDate.minusDays(6); // 오늘 포함 7일 return exerciseRecordRepository.findByParentIdAndDateBetweenOrderByDateDesc(parentId, startDate, endDate); diff --git a/backend/ongi/src/main/java/ongi/temperature/dto/FamilyTemperatureContributionResponse.java b/backend/ongi/src/main/java/ongi/temperature/dto/FamilyTemperatureContributionResponse.java index f0b6368..aca30ee 100644 --- a/backend/ongi/src/main/java/ongi/temperature/dto/FamilyTemperatureContributionResponse.java +++ b/backend/ongi/src/main/java/ongi/temperature/dto/FamilyTemperatureContributionResponse.java @@ -15,7 +15,7 @@ public class FamilyTemperatureContributionResponse { @AllArgsConstructor public static class Contribution { private LocalDate date; - private UUID userId; + private String userName; private Double contributed; } } \ No newline at end of file diff --git a/backend/ongi/src/main/java/ongi/temperature/entity/Temperature.java b/backend/ongi/src/main/java/ongi/temperature/entity/Temperature.java index 03b8c5a..60ae697 100644 --- a/backend/ongi/src/main/java/ongi/temperature/entity/Temperature.java +++ b/backend/ongi/src/main/java/ongi/temperature/entity/Temperature.java @@ -36,6 +36,9 @@ @Column(nullable = false) private Double temperature; + @Column(nullable = false, length = 30) + private String reason; + @CreatedDate @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime createdAt; diff --git a/backend/ongi/src/main/java/ongi/temperature/repository/TemperatureRepository.java b/backend/ongi/src/main/java/ongi/temperature/repository/TemperatureRepository.java index 52db80e..c96f2e2 100644 --- a/backend/ongi/src/main/java/ongi/temperature/repository/TemperatureRepository.java +++ b/backend/ongi/src/main/java/ongi/temperature/repository/TemperatureRepository.java @@ -16,15 +16,19 @@ public interface TemperatureRepository extends JpaRepository @Query("SELECT SUM(t.temperature) FROM Temperature t WHERE t.familyId = :familyId") Double getTotalTemperatureByFamilyId(@Param("familyId") String familyId); - // 최근 5일간 가족 온도 총합 (날짜별) - Object[]로 반환 + // 최근 5일간 가족 온도 총합 (날짜별) @Query("SELECT CAST(t.createdAt AS date), SUM(t.temperature) " + "FROM Temperature t WHERE t.familyId = :familyId AND t.createdAt >= :fromDate " + "GROUP BY CAST(t.createdAt AS date) ORDER BY CAST(t.createdAt AS date) DESC") List getFamilyTemperatureDailyRaw(@Param("familyId") String familyId, @Param("fromDate") java.time.LocalDateTime fromDate); - // 최근 5일간 가족 구성원별 온도 기여 내역 - Object[]로 반환 + // 최근 5일간 가족 구성원별 온도 기여 내역 @Query("SELECT CAST(t.createdAt AS date), t.userId, SUM(t.temperature) " + "FROM Temperature t WHERE t.familyId = :familyId AND t.createdAt >= :fromDate " + "GROUP BY CAST(t.createdAt AS date), t.userId ORDER BY CAST(t.createdAt AS date) DESC") List getFamilyTemperatureContributionsRaw(@Param("familyId") String familyId, @Param("fromDate") java.time.LocalDateTime fromDate); + + // 오늘 해당 유저가 특정 활동(reason)으로 온도 기록을 남겼는지 확인 (날짜 기준) + @Query("SELECT COUNT(t) > 0 FROM Temperature t WHERE t.userId = :userId AND t.familyId = :familyId AND t.reason = :reason AND FUNCTION('DATE', t.createdAt) = :date") + boolean existsByUserIdAndFamilyIdAndReasonAndDate(@Param("userId") java.util.UUID userId, @Param("familyId") String familyId, @Param("reason") String reason, @Param("date") java.time.LocalDate date); } \ No newline at end of file diff --git a/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java b/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java index 9dec710..a8354a4 100644 --- a/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java +++ b/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java @@ -15,6 +15,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; +import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @@ -27,7 +28,7 @@ public class TemperatureService { private final UserRepository userRepository; private static final double BASE_TEMPERATURE = 36.5; - // 가족 온도 그래프 및 기여도 조회 + //// 가족 온도 그래프 및 기여도 조회 public FamilyTemperatureResponse getFamilyTemperatureSummary(String familyId) { familyRepository.findById(familyId) @@ -80,7 +81,7 @@ public FamilyTemperatureResponse getFamilyTemperatureSummary(String familyId) { .build(); } - // 최근 5일간 가족 온도 총합 조회 + //// 최근 5일간 가족 온도 총합 조회 public FamilyTemperatureDailyResponse getFamilyTemperatureDaily(String familyId) { familyRepository.findById(familyId) .orElseThrow(() -> new EntityNotFoundException("가족을 찾을 수 없습니다.")); @@ -95,18 +96,32 @@ public FamilyTemperatureDailyResponse getFamilyTemperatureDaily(String familyId) return new FamilyTemperatureDailyResponse(dailyList); } - // 최근 5일간 가족 구성원별 온도 기여 내역 조회 + //// 최근 5일간 가족 구성원별 온도 기여 내역 조회 public FamilyTemperatureContributionResponse getFamilyTemperatureContributions(String familyId) { familyRepository.findById(familyId) .orElseThrow(() -> new EntityNotFoundException("가족을 찾을 수 없습니다.")); java.time.LocalDateTime fromDate = java.time.LocalDate.now().minusDays(4).atStartOfDay(); // 최근 5일 List rawList = temperatureRepository.getFamilyTemperatureContributionsRaw(familyId, fromDate); + + Set userIds = rawList.stream() + .map(arr -> (UUID) arr[1]) + .collect(Collectors.toSet()); + Map userMap = userRepository.findAllById(userIds).stream() + .collect(Collectors.toMap(User::getUuid, user -> user)); + List contributions = rawList.stream() - .map(arr -> new FamilyTemperatureContributionResponse.Contribution( - (java.time.LocalDate) arr[0], - (java.util.UUID) arr[1], - (Double) arr[2] - )) + .map(arr -> { + LocalDate date = (LocalDate) arr[0]; + UUID userId = (UUID) arr[1]; + Double contributed = (Double) arr[2]; + String userName; + if (userId == null) { + userName = "우리 가족"; + } else { + userName = userMap.get(userId) != null ? userMap.get(userId).getName() : ""; + } + return new FamilyTemperatureContributionResponse.Contribution(date, userName, contributed); + }) .toList(); return new FamilyTemperatureContributionResponse(contributions); } @@ -114,33 +129,163 @@ public FamilyTemperatureContributionResponse getFamilyTemperatureContributions(S - // 온도 상승 메서드 + //// 온도 상승 메서드 + + // 활동별 reason 상수 정의 + private static final String REASON_EMOTION_UPLOAD = "EMOTION_UPLOAD"; + private static final String REASON_ALL_EMOTION_UPLOAD = "ALL_EMOTION_UPLOAD"; + private static final String REASON_STEP_GOAL = "STEP_GOAL"; + private static final String REASON_PARENT_PAIN_INPUT = "PARENT_PAIN_INPUT"; + private static final String REASON_PARENT_MED_INPUT = "PARENT_MED_INPUT"; + private static final String REASON_PARENT_EXERCISE_INPUT = "PARENT_EXERCISE_INPUT"; + private static final String REASON_CHILD_PAIN_VIEW = "CHILD_PAIN_VIEW"; + private static final String REASON_CHILD_MED_VIEW = "CHILD_MED_VIEW"; + private static final String REASON_CHILD_EXERCISE_VIEW = "CHILD_EXERCISE_VIEW"; + + private java.time.LocalDate getToday() { + return java.time.LocalDate.now(); + } + // 감정기록 업로드 시 온도 상승 (하루 1회만 적용) public void increaseTemperatureForEmotionUpload(UUID userId, String familyId) { - // TODO: 하루 1회 제한 및 온도 상승(+0.1도) 로직 구현 + java.time.LocalDate today = getToday(); + boolean alreadyIncreased = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_EMOTION_UPLOAD, today); + if (!alreadyIncreased) { + Temperature temp = Temperature.builder() + .userId(userId) + .familyId(familyId) + .temperature(0.1) + .reason(REASON_EMOTION_UPLOAD) + .build(); + temperatureRepository.save(temp); + } } // 가족 모두 감정기록 업로드 시 온도 추가 상승 public void increaseTemperatureForAllEmotionUpload(String familyId) { - // TODO: 가족 모두 업로드 확인 및 온도 추가 상승(+0.5도) 로직 구현 + var family = familyRepository.findById(familyId) + .orElseThrow(() -> new EntityNotFoundException("가족을 찾을 수 없습니다.")); + var members = family.getMembers(); + java.time.LocalDate today = getToday(); + boolean allUploaded = members.stream().allMatch( + userId -> temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_EMOTION_UPLOAD, today) + ); + boolean alreadyIncreased = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_ALL_EMOTION_UPLOAD, today); + if (allUploaded && !alreadyIncreased) { + Temperature temp = Temperature.builder() + .userId(null) + .familyId(familyId) + .temperature(0.5) + .reason(REASON_ALL_EMOTION_UPLOAD) + .build(); + temperatureRepository.save(temp); + } } - // 부모 건강 정보 입력 시 온도 상승 (최대 0.6도) - public void increaseTemperatureForParentHealthInput(UUID userId, String familyId) { - // TODO: 하루 최대 0.6도까지 온도 상승(+0.2도씩) 로직 구현 + // 부모 통증 부위 입력 오늘 1회만 온도 상승 + public void increaseTemperatureForParentPainInput(UUID userId, String familyId) { + java.time.LocalDate today = getToday(); + boolean already = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_PARENT_PAIN_INPUT, today); + if (!already) { + Temperature temp = Temperature.builder() + .userId(userId) + .familyId(familyId) + .temperature(0.2) + .reason(REASON_PARENT_PAIN_INPUT) + .build(); + temperatureRepository.save(temp); + } } - - // 자녀가 부모 건강 정보 열람 시 온도 상승 (최대 0.9도) - public void increaseTemperatureForChildHealthView(UUID userId, String familyId) { - // TODO: 하루 최대 0.9도까지 온도 상승(+0.3도씩) 로직 구현 + // 부모 약 복용 입력 오늘 1회만 온도 상승 + public void increaseTemperatureForParentMedInput(UUID userId, String familyId) { + java.time.LocalDate today = getToday(); + boolean already = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_PARENT_MED_INPUT, today); + if (!already) { + Temperature temp = Temperature.builder() + .userId(userId) + .familyId(familyId) + .temperature(0.2) + .reason(REASON_PARENT_MED_INPUT) + .build(); + temperatureRepository.save(temp); + } + } + // 부모 운동 시간 입력 오늘 1회만 온도 상승 + public void increaseTemperatureForParentExerciseInput(UUID userId, String familyId) { + java.time.LocalDate today = getToday(); + boolean already = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_PARENT_EXERCISE_INPUT, today); + if (!already) { + Temperature temp = Temperature.builder() + .userId(userId) + .familyId(familyId) + .temperature(0.2) + .reason(REASON_PARENT_EXERCISE_INPUT) + .build(); + temperatureRepository.save(temp); + } + } + // 자녀 통증 부위 확인 오늘 1회만 온도 상승 + public void increaseTemperatureForChildPainView(UUID userId, String familyId) { + java.time.LocalDate today = getToday(); + boolean already = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_CHILD_PAIN_VIEW, today); + if (!already) { + Temperature temp = Temperature.builder() + .userId(userId) + .familyId(familyId) + .temperature(0.3) + .reason(REASON_CHILD_PAIN_VIEW) + .build(); + temperatureRepository.save(temp); + } + } + // 자녀 약 복용 확인 오늘 1회만 온도 상승 + public void increaseTemperatureForChildMedView(UUID userId, String familyId) { + java.time.LocalDate today = getToday(); + boolean already = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_CHILD_MED_VIEW, today); + if (!already) { + Temperature temp = Temperature.builder() + .userId(userId) + .familyId(familyId) + .temperature(0.3) + .reason(REASON_CHILD_MED_VIEW) + .build(); + temperatureRepository.save(temp); + } + } + // 자녀 운동 시간 확인 오늘 1회만 온도 상승 + public void increaseTemperatureForChildExerciseView(UUID userId, String familyId) { + java.time.LocalDate today = getToday(); + boolean already = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_CHILD_EXERCISE_VIEW, today); + if (!already) { + Temperature temp = Temperature.builder() + .userId(userId) + .familyId(familyId) + .temperature(0.3) + .reason(REASON_CHILD_EXERCISE_VIEW) + .build(); + temperatureRepository.save(temp); + } } // 가족 만보기 걸음수 충족 시 온도 상승 + // 메서드 적용 시 가족 만보기 총 걸음수가 하루 {(부모 수) x 7,000 + (자녀 수) x 10,000}보 이상인지 검사 필요 public void increaseTemperatureForStepGoal(String familyId) { - // TODO: 걸음수 충족 시 온도 상승(+0.2도) 로직 구현 + java.time.LocalDate today = getToday(); + boolean alreadyIncreased = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_STEP_GOAL, today); + if (!alreadyIncreased) { + Temperature temp = Temperature.builder() + .userId(null) + .familyId(familyId) + .temperature(0.2) + .reason(REASON_STEP_GOAL) + .build(); + temperatureRepository.save(temp); + } } + + // 온도 하락 메서드 // 부모 1명 이상 일주일 미접속 시 온도 하락 public void decreaseTemperatureForInactiveParent(String familyId) { diff --git a/backend/ongi/src/test/java/ongi/HealthRecordControllerTest.java b/backend/ongi/src/test/java/ongi/HealthRecordControllerTest.java index 431222e..e69de29 100644 --- a/backend/ongi/src/test/java/ongi/HealthRecordControllerTest.java +++ b/backend/ongi/src/test/java/ongi/HealthRecordControllerTest.java @@ -1,131 +0,0 @@ -package ongi; - -import ongi.health.controller.HealthRecordController; -import ongi.health.entity.PainRecord; -import ongi.health.entity.ExerciseRecord; -import ongi.health.service.HealthRecordService; -import ongi.health.dto.PainRecordResponse; -import ongi.health.dto.ExerciseRecordResponse; -import ongi.security.CustomUserDetails; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; -import java.time.LocalDate; -import java.util.List; -import java.util.UUID; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.BDDMockito.given; - -@ExtendWith(MockitoExtension.class) -class HealthRecordControllerTest { - - @Mock - private HealthRecordService healthRecordService; - - @InjectMocks - private HealthRecordController healthRecordController; - - private UUID parentId; - private CustomUserDetails userDetails; - - @BeforeEach - void setUp() { - parentId = UUID.randomUUID(); - userDetails = Mockito.mock(CustomUserDetails.class, Mockito.RETURNS_DEEP_STUBS); - Mockito.when(userDetails.getUser().getUuid()).thenReturn(parentId); - } - - @Test - @DisplayName("통증 기록 추가 성공") - void addPainRecord() { - PainRecord record = PainRecord.builder() - .id(1L) - .parentId(parentId) - .date(LocalDate.of(2024, 7, 18)) - .painArea(PainRecord.PainArea.HEAD) - .painLevel(PainRecord.PainLevel.STRONG) - .build(); - given(healthRecordService.addPainRecord(any(), any(), any(), any())).willReturn(record); - - PainRecordResponse response = healthRecordController.addPainRecord( - userDetails, - LocalDate.of(2024, 7, 18), - PainRecord.PainArea.HEAD, - PainRecord.PainLevel.STRONG - ).getBody(); - - assertNotNull(response); - assertEquals(1L, response.id()); - assertEquals("HEAD", response.painArea()); - assertEquals("STRONG", response.painLevel()); - } - - @Test - @DisplayName("운동 기록 추가 성공") - void addExerciseRecord() { - ExerciseRecord record = ExerciseRecord.builder() - .id(1L) - .parentId(parentId) - .date(LocalDate.of(2024, 7, 18)) - .duration(60) - .build(); - given(healthRecordService.addExerciseRecord(any(), any(), anyInt())).willReturn(record); - - ExerciseRecordResponse response = healthRecordController.addExerciseRecord( - userDetails, - LocalDate.of(2024, 7, 18), - 60 - ).getBody(); - - assertNotNull(response); - assertEquals(1L, response.id()); - assertEquals(60, response.duration()); - } - - @Test - @DisplayName("통증 기록 최근 7일 조회") - void getPainRecordsForLast7Days() { - List records = List.of( - PainRecord.builder() - .id(1L) - .parentId(parentId) - .date(LocalDate.of(2024, 7, 18)) - .painArea(PainRecord.PainArea.HEAD) - .painLevel(PainRecord.PainLevel.STRONG) - .build() - ); - given(healthRecordService.getPainRecordsForLast7Days(any())).willReturn(records); - - List response = healthRecordController.getParentPainRecordsForLast7Days(parentId).getBody(); - - assertNotNull(response); - assertEquals(1, response.size()); - assertEquals("HEAD", response.get(0).painArea()); - } - - @Test - @DisplayName("운동 기록 최근 7일 조회") - void getExerciseRecordsForLast7Days() { - List records = List.of( - ExerciseRecord.builder() - .id(1L) - .parentId(parentId) - .date(LocalDate.of(2024, 7, 18)) - .duration(60) - .build() - ); - given(healthRecordService.getExerciseRecordsForLast7Days(any())).willReturn(records); - - List response = healthRecordController.getParentExerciseRecordsForLast7Days(parentId).getBody(); - - assertNotNull(response); - assertEquals(1, response.size()); - assertEquals(60, response.get(0).duration()); - } -} \ No newline at end of file From 1ad9bb280a854ad99415abe06cc50e735f0f17a6 Mon Sep 17 00:00:00 2001 From: oxomi Date: Tue, 29 Jul 2025 00:00:41 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=98=A8=EB=8F=84=20=EC=83=81=EC=8A=B9=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=8A=A4=EC=BC=80=EC=A4=84=EB=9F=AC=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20feat:=20=EC=98=A8=EB=8F=84=20=ED=95=98=EB=9D=BD=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=8A=A4=EC=BC=80=EC=A4=84?= =?UTF-8?q?=EB=9F=AC=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TemperatureService.java | 123 ++++++++----- .../ongi/TemperatureControllerUnitTest.java | 161 ------------------ 2 files changed, 84 insertions(+), 200 deletions(-) diff --git a/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java b/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java index a8354a4..e1c8071 100644 --- a/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java +++ b/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java @@ -12,6 +12,7 @@ import ongi.user.repository.UserRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.scheduling.annotation.Scheduled; import java.math.BigDecimal; import java.math.RoundingMode; @@ -161,27 +162,6 @@ public void increaseTemperatureForEmotionUpload(UUID userId, String familyId) { } } - // 가족 모두 감정기록 업로드 시 온도 추가 상승 - public void increaseTemperatureForAllEmotionUpload(String familyId) { - var family = familyRepository.findById(familyId) - .orElseThrow(() -> new EntityNotFoundException("가족을 찾을 수 없습니다.")); - var members = family.getMembers(); - java.time.LocalDate today = getToday(); - boolean allUploaded = members.stream().allMatch( - userId -> temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_EMOTION_UPLOAD, today) - ); - boolean alreadyIncreased = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_ALL_EMOTION_UPLOAD, today); - if (allUploaded && !alreadyIncreased) { - Temperature temp = Temperature.builder() - .userId(null) - .familyId(familyId) - .temperature(0.5) - .reason(REASON_ALL_EMOTION_UPLOAD) - .build(); - temperatureRepository.save(temp); - } - } - // 부모 통증 부위 입력 오늘 1회만 온도 상승 public void increaseTemperatureForParentPainInput(UUID userId, String familyId) { java.time.LocalDate today = getToday(); @@ -267,38 +247,103 @@ public void increaseTemperatureForChildExerciseView(UUID userId, String familyId } } - // 가족 만보기 걸음수 충족 시 온도 상승 - // 메서드 적용 시 가족 만보기 총 걸음수가 하루 {(부모 수) x 7,000 + (자녀 수) x 10,000}보 이상인지 검사 필요 - public void increaseTemperatureForStepGoal(String familyId) { - java.time.LocalDate today = getToday(); - boolean alreadyIncreased = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_STEP_GOAL, today); - if (!alreadyIncreased) { - Temperature temp = Temperature.builder() - .userId(null) - .familyId(familyId) - .temperature(0.2) - .reason(REASON_STEP_GOAL) - .build(); - temperatureRepository.save(temp); + + // 매일 23:59:59에 당일의 가족별 보너스 온도 상승 처리 + @Scheduled(cron = "59 59 23 * * *") + @Transactional + public void processFamilyBonusTemperature() { + var families = familyRepository.findAll(); + java.time.LocalDate targetDate = getToday(); // 오늘 날짜 + for (var family : families) { + String familyId = family.getCode(); + var members = family.getMembers(); + + // 전체 가족 구성원이 감정기록 업로드 시 보너스 + boolean allEmotionUploaded = members.stream().allMatch( + userId -> temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_EMOTION_UPLOAD, targetDate) + ); + boolean alreadyEmotionBonus = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_ALL_EMOTION_UPLOAD, targetDate); + if (allEmotionUploaded && !alreadyEmotionBonus) { + Temperature temp = Temperature.builder() + .userId(null) + .familyId(familyId) + .temperature(0.5) + .reason(REASON_ALL_EMOTION_UPLOAD) + .build(); + temperatureRepository.save(temp); + } + // 만보기 걸음 수 충족 시 보너스 + boolean alreadyStepBonus = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_STEP_GOAL, targetDate); + // TODO: 가족 만보기 총 걸음수가 하루 {(부모 수) x 7,000 + (자녀 수) x 10,000}보 이상인지 검사 필요 + boolean stepGoalMet = false; // 실제 조건으로 대체 필요 + if (stepGoalMet && !alreadyStepBonus) { + Temperature temp = Temperature.builder() + .userId(null) + .familyId(familyId) + .temperature(0.2) + .reason(REASON_STEP_GOAL) + .build(); + temperatureRepository.save(temp); + } } } + // 매일 23:59:59에 당일의 가족별 온도 하락 처리 + @Scheduled(cron = "59 59 23 * * *") + @Transactional + public void processFamilyTemperatureDecrease() { + var families = familyRepository.findAll(); + for (var family : families) { + String familyId = family.getCode(); + decreaseTemperatureForInactiveParent(familyId); + decreaseTemperatureForInactiveChild(familyId); + decreaseTemperatureForNoLogin(familyId); + } + } - - // 온도 하락 메서드 // 부모 1명 이상 일주일 미접속 시 온도 하락 public void decreaseTemperatureForInactiveParent(String familyId) { - // TODO: 부모 미접속 시 온도 하락(-15도) 로직 구현 + // TODO: 부모 미접속 판별 로직 필요 + boolean parentInactive = false; // 실제 판별로 대체 + if (parentInactive) { + Temperature temp = Temperature.builder() + .userId(null) + .familyId(familyId) + .temperature(-15.0) + .reason("INACTIVE_PARENT") + .build(); + temperatureRepository.save(temp); + } } // 자녀 1명 이상 일주일 미접속 시 온도 하락 public void decreaseTemperatureForInactiveChild(String familyId) { - // TODO: 자녀 미접속 시 온도 하락(-15도) 로직 구현 + // TODO: 자녀 미접속 판별 로직 필요 + boolean childInactive = false; // 실제 판별로 대체 + if (childInactive) { + Temperature temp = Temperature.builder() + .userId(null) + .familyId(familyId) + .temperature(-15.0) + .reason("INACTIVE_CHILD") + .build(); + temperatureRepository.save(temp); + } } // 하루 동안 아무도 미접속 시 온도 하락 public void decreaseTemperatureForNoLogin(String familyId) { - // TODO: 하루 미접속 시 온도 하락(-1도) 로직 구현 + // TODO: 전체 미접속 판별 로직 필요 + boolean noLogin = false; // 실제 판별로 대체 + if (noLogin) { + Temperature temp = Temperature.builder() + .userId(null) + .familyId(familyId) + .temperature(-1.0) + .reason("NO_LOGIN") + .build(); + temperatureRepository.save(temp); + } } } \ No newline at end of file diff --git a/backend/ongi/src/test/java/ongi/TemperatureControllerUnitTest.java b/backend/ongi/src/test/java/ongi/TemperatureControllerUnitTest.java index 30be9a3..e69de29 100644 --- a/backend/ongi/src/test/java/ongi/TemperatureControllerUnitTest.java +++ b/backend/ongi/src/test/java/ongi/TemperatureControllerUnitTest.java @@ -1,161 +0,0 @@ -package ongi; - -import ongi.exception.EntityNotFoundException; -import ongi.temperature.controller.TemperatureController; -import ongi.temperature.dto.FamilyTemperatureDailyResponse; -import ongi.temperature.dto.FamilyTemperatureContributionResponse; -import ongi.temperature.service.TemperatureService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.context.ActiveProfiles; - -import java.util.UUID; -import ongi.temperature.dto.FamilyTemperatureResponse; -import static org.mockito.BDDMockito.given; -import static org.junit.jupiter.api.Assertions.*; - -@ExtendWith(MockitoExtension.class) -@ActiveProfiles("test") -class TemperatureControllerUnitTest { - - @Mock - private TemperatureService temperatureService; - - @InjectMocks - private TemperatureController temperatureController; - - private String testFamilyId; - - @BeforeEach - void setUp() { - testFamilyId = "FAM123"; - } - - @Test - @DisplayName("가족 온도 요약 - 여러 가족, 구성원, 기여도 포함 성공") - void getFamilyTemperatureSummary_MultipleFamiliesAndMembers_Success() { - // given - UUID userId1 = UUID.randomUUID(); - UUID userId2 = UUID.randomUUID(); - UUID userId3 = UUID.randomUUID(); - FamilyTemperatureResponse.MemberTemperatureInfo m1 = FamilyTemperatureResponse.MemberTemperatureInfo.builder() - .userId(userId1).userName("홍길동").contributedTemperature(1.2).percentage(30.0).build(); - FamilyTemperatureResponse.MemberTemperatureInfo m2 = FamilyTemperatureResponse.MemberTemperatureInfo.builder() - .userId(userId2).userName("김철수").contributedTemperature(2.8).percentage(70.0).build(); - FamilyTemperatureResponse.MemberTemperatureInfo m3 = FamilyTemperatureResponse.MemberTemperatureInfo.builder() - .userId(userId3).userName("이영희").contributedTemperature(0.0).percentage(0.0).build(); - FamilyTemperatureResponse response = FamilyTemperatureResponse.builder() - .familyTemperature(36.5) - .totalContributedTemperature(4.0) - .memberTemperatures(java.util.Arrays.asList(m1, m2, m3)) - .build(); - given(temperatureService.getFamilyTemperatureSummary(testFamilyId)).willReturn(response); - - // when - FamilyTemperatureResponse result = temperatureController.getFamilyTemperatureSummary(testFamilyId).getBody(); - - // then - assertNotNull(result); - assertEquals(36.5, result.getFamilyTemperature()); - assertEquals(4.0, result.getTotalContributedTemperature()); - assertEquals("홍길동", result.getMemberTemperatures().get(0).getUserName()); - assertEquals("김철수", result.getMemberTemperatures().get(1).getUserName()); - assertEquals("이영희", result.getMemberTemperatures().get(2).getUserName()); - } - - @Test - @DisplayName("가족 온도 요약 - 존재하지 않는 가족") - void getFamilyTemperatureSummary_FamilyNotFound() { - // given - given(temperatureService.getFamilyTemperatureSummary(testFamilyId)) - .willThrow(new EntityNotFoundException("가족을 찾을 수 없습니다.")); - - // when & then - assertThrows(EntityNotFoundException.class, () -> - temperatureController.getFamilyTemperatureSummary(testFamilyId) - ); - } - - @Test - @DisplayName("가족 온도 일별 로그 - 여러 가족, 여러 일자 온도 로그 포함 성공") - void getFamilyTemperatureDaily_MultipleFamiliesAndLogs_Success() { - // given - FamilyTemperatureDailyResponse.DailyTemperature daily1 = new FamilyTemperatureDailyResponse.DailyTemperature( - java.time.LocalDate.now().minusDays(2), 36.6); - FamilyTemperatureDailyResponse.DailyTemperature daily2 = new FamilyTemperatureDailyResponse.DailyTemperature( - java.time.LocalDate.now().minusDays(1), 36.7); - FamilyTemperatureDailyResponse.DailyTemperature daily3 = new FamilyTemperatureDailyResponse.DailyTemperature( - java.time.LocalDate.now(), 36.8); - FamilyTemperatureDailyResponse response = new FamilyTemperatureDailyResponse( - java.util.Arrays.asList(daily1, daily2, daily3)); - given(temperatureService.getFamilyTemperatureDaily(testFamilyId)).willReturn(response); - - // when - FamilyTemperatureDailyResponse result = temperatureController.getFamilyTemperatureDaily(testFamilyId).getBody(); - - // then - assertNotNull(result); - assertEquals(3, result.getDailyTemperatures().size()); - assertEquals(36.6, result.getDailyTemperatures().get(0).getTotalTemperature()); - assertEquals(36.7, result.getDailyTemperatures().get(1).getTotalTemperature()); - assertEquals(36.8, result.getDailyTemperatures().get(2).getTotalTemperature()); - } - - @Test - @DisplayName("가족 온도 일별 로그 - 존재하지 않는 가족") - void getFamilyTemperatureDaily_FamilyNotFound() { - // given - given(temperatureService.getFamilyTemperatureDaily(testFamilyId)) - .willThrow(new EntityNotFoundException("가족을 찾을 수 없습니다.")); - - // when & then - assertThrows(EntityNotFoundException.class, () -> - temperatureController.getFamilyTemperatureDaily(testFamilyId) - ); - } - - @Test - @DisplayName("가족 온도 기여도 - 여러 가족, 여러 구성원, 여러 일자 기여도 포함 성공") - void getFamilyTemperatureContributions_MultipleFamiliesMembersLogs_Success() { - // given - java.util.UUID userId1 = java.util.UUID.randomUUID(); - java.util.UUID userId2 = java.util.UUID.randomUUID(); - FamilyTemperatureContributionResponse.Contribution c1 = new FamilyTemperatureContributionResponse.Contribution( - java.time.LocalDate.now().minusDays(2), userId1, 1.1); - FamilyTemperatureContributionResponse.Contribution c2 = new FamilyTemperatureContributionResponse.Contribution( - java.time.LocalDate.now().minusDays(1), userId2, 2.2); - FamilyTemperatureContributionResponse.Contribution c3 = new FamilyTemperatureContributionResponse.Contribution( - java.time.LocalDate.now(), userId1, 3.3); - FamilyTemperatureContributionResponse response = new FamilyTemperatureContributionResponse( - java.util.Arrays.asList(c1, c2, c3)); - given(temperatureService.getFamilyTemperatureContributions(testFamilyId)).willReturn(response); - - // when - FamilyTemperatureContributionResponse result = temperatureController.getFamilyTemperatureContributions(testFamilyId).getBody(); - - // then - assertNotNull(result); - assertEquals(3, result.getContributions().size()); - assertEquals(1.1, result.getContributions().get(0).getContributed()); - assertEquals(2.2, result.getContributions().get(1).getContributed()); - assertEquals(3.3, result.getContributions().get(2).getContributed()); - } - - @Test - @DisplayName("가족 온도 기여도 - 존재하지 않는 가족") - void getFamilyTemperatureContributions_FamilyNotFound() { - // given - given(temperatureService.getFamilyTemperatureContributions(testFamilyId)) - .willThrow(new EntityNotFoundException("가족을 찾을 수 없습니다.")); - - // when & then - assertThrows(EntityNotFoundException.class, () -> - temperatureController.getFamilyTemperatureContributions(testFamilyId) - ); - } -} From 69659e864bdbc0f11c0207c78db32cdb5a81d60d Mon Sep 17 00:00:00 2001 From: oxomi Date: Thu, 31 Jul 2025 00:11:24 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EC=98=A8=EB=8F=84=20=EC=83=81?= =?UTF-8?q?=EC=8A=B9=20=EC=88=98=EC=B9=98=20=EC=A1=B0=EC=A0=95=20feat:=20?= =?UTF-8?q?=ED=86=B5=EC=A6=9D,=20=EC=9A=B4=EB=8F=99=20API=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/HealthRecordController.java | 28 +++++++++------ .../health/dto/ExerciseRecordRequest.java | 8 +++++ .../ongi/health/dto/PainRecordRequest.java | 9 +++++ .../service/TemperatureService.java | 34 +++++++++++-------- 4 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 backend/ongi/src/main/java/ongi/health/dto/ExerciseRecordRequest.java create mode 100644 backend/ongi/src/main/java/ongi/health/dto/PainRecordRequest.java diff --git a/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java b/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java index 1604c98..5df2874 100644 --- a/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java +++ b/backend/ongi/src/main/java/ongi/health/controller/HealthRecordController.java @@ -5,12 +5,10 @@ import ongi.health.entity.ExerciseRecord; import ongi.health.service.HealthRecordService; import ongi.security.CustomUserDetails; -import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; -import java.time.LocalDate; import java.util.List; import java.util.UUID; import ongi.health.dto.PainRecordResponse; @@ -18,6 +16,8 @@ import ongi.family.service.FamilyService; import ongi.family.dto.FamilyInfo; import ongi.temperature.service.TemperatureService; +import ongi.health.dto.PainRecordRequest; +import ongi.health.dto.ExerciseRecordRequest; @RestController @RequestMapping("/health") @@ -28,18 +28,21 @@ public class HealthRecordController { private final TemperatureService temperatureService; // 통증 기록 추가 - @PostMapping("/pain") + @PostMapping("/pain/record") public ResponseEntity addPainRecord( @AuthenticationPrincipal CustomUserDetails userDetails, - @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, - @RequestParam PainRecord.PainArea area, - @RequestParam PainRecord.PainLevel level + @RequestBody PainRecordRequest request ) { FamilyInfo familyInfo = familyService.getFamily(userDetails.getUser()); String familyId = familyInfo.code(); - PainRecord record = healthRecordService.addPainRecord(userDetails.getUser().getUuid(), date, area, level); + PainRecord record = healthRecordService.addPainRecord( + userDetails.getUser().getUuid(), + request.date(), + PainRecord.PainArea.valueOf(request.painArea()), + PainRecord.PainLevel.valueOf(request.painLevel()) + ); // 온도 상승 temperatureService.increaseTemperatureForParentPainInput(userDetails.getUser().getUuid(), familyId); @@ -49,17 +52,20 @@ public ResponseEntity addPainRecord( } // 운동 기록 추가 - @PostMapping("/exercise") + @PostMapping("/exercise/record") public ResponseEntity addExerciseRecord( @AuthenticationPrincipal CustomUserDetails userDetails, - @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, - @RequestParam int duration + @RequestBody ExerciseRecordRequest request ) { FamilyInfo familyInfo = familyService.getFamily(userDetails.getUser()); String familyId = familyInfo.code(); - ExerciseRecord record = healthRecordService.addExerciseRecord(userDetails.getUser().getUuid(), date, duration); + ExerciseRecord record = healthRecordService.addExerciseRecord( + userDetails.getUser().getUuid(), + request.date(), + request.duration() + ); // 온도 상승 temperatureService.increaseTemperatureForParentExerciseInput(userDetails.getUser().getUuid(), familyId); diff --git a/backend/ongi/src/main/java/ongi/health/dto/ExerciseRecordRequest.java b/backend/ongi/src/main/java/ongi/health/dto/ExerciseRecordRequest.java new file mode 100644 index 0000000..be34559 --- /dev/null +++ b/backend/ongi/src/main/java/ongi/health/dto/ExerciseRecordRequest.java @@ -0,0 +1,8 @@ +package ongi.health.dto; + +import java.time.LocalDate; + +public record ExerciseRecordRequest( + LocalDate date, + int duration +) {} \ No newline at end of file diff --git a/backend/ongi/src/main/java/ongi/health/dto/PainRecordRequest.java b/backend/ongi/src/main/java/ongi/health/dto/PainRecordRequest.java new file mode 100644 index 0000000..de167ab --- /dev/null +++ b/backend/ongi/src/main/java/ongi/health/dto/PainRecordRequest.java @@ -0,0 +1,9 @@ +package ongi.health.dto; + +import java.time.LocalDate; + +public record PainRecordRequest( + LocalDate date, + String painArea, + String painLevel +) {} \ No newline at end of file diff --git a/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java b/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java index e1c8071..b5dba39 100644 --- a/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java +++ b/backend/ongi/src/main/java/ongi/temperature/service/TemperatureService.java @@ -22,7 +22,7 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) +@Transactional public class TemperatureService { private final TemperatureRepository temperatureRepository; private final FamilyRepository familyRepository; @@ -170,7 +170,7 @@ public void increaseTemperatureForParentPainInput(UUID userId, String familyId) Temperature temp = Temperature.builder() .userId(userId) .familyId(familyId) - .temperature(0.2) + .temperature(0.1) .reason(REASON_PARENT_PAIN_INPUT) .build(); temperatureRepository.save(temp); @@ -184,7 +184,7 @@ public void increaseTemperatureForParentMedInput(UUID userId, String familyId) { Temperature temp = Temperature.builder() .userId(userId) .familyId(familyId) - .temperature(0.2) + .temperature(0.1) .reason(REASON_PARENT_MED_INPUT) .build(); temperatureRepository.save(temp); @@ -198,7 +198,7 @@ public void increaseTemperatureForParentExerciseInput(UUID userId, String family Temperature temp = Temperature.builder() .userId(userId) .familyId(familyId) - .temperature(0.2) + .temperature(0.1) .reason(REASON_PARENT_EXERCISE_INPUT) .build(); temperatureRepository.save(temp); @@ -212,7 +212,7 @@ public void increaseTemperatureForChildPainView(UUID userId, String familyId) { Temperature temp = Temperature.builder() .userId(userId) .familyId(familyId) - .temperature(0.3) + .temperature(0.1) .reason(REASON_CHILD_PAIN_VIEW) .build(); temperatureRepository.save(temp); @@ -226,7 +226,7 @@ public void increaseTemperatureForChildMedView(UUID userId, String familyId) { Temperature temp = Temperature.builder() .userId(userId) .familyId(familyId) - .temperature(0.3) + .temperature(0.1) .reason(REASON_CHILD_MED_VIEW) .build(); temperatureRepository.save(temp); @@ -240,7 +240,7 @@ public void increaseTemperatureForChildExerciseView(UUID userId, String familyId Temperature temp = Temperature.builder() .userId(userId) .familyId(familyId) - .temperature(0.3) + .temperature(0.1) .reason(REASON_CHILD_EXERCISE_VIEW) .build(); temperatureRepository.save(temp); @@ -267,11 +267,12 @@ public void processFamilyBonusTemperature() { Temperature temp = Temperature.builder() .userId(null) .familyId(familyId) - .temperature(0.5) + .temperature(0.1) .reason(REASON_ALL_EMOTION_UPLOAD) .build(); temperatureRepository.save(temp); } + // 만보기 걸음 수 충족 시 보너스 boolean alreadyStepBonus = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_STEP_GOAL, targetDate); // TODO: 가족 만보기 총 걸음수가 하루 {(부모 수) x 7,000 + (자녀 수) x 10,000}보 이상인지 검사 필요 @@ -288,6 +289,11 @@ public void processFamilyBonusTemperature() { } } + // 매주 일요일 23:59:59 에 만보기 경쟁 결과 보너스 온도 상승 처리 (후순위! 일단 안만들어도 됨) + // TODO: 만보기 전체 경쟁 상위 10% -> +3도 + // TODO: 만보기 전체 경쟁 상위 20% -> +1도 + + // 매일 23:59:59에 당일의 가족별 온도 하락 처리 @Scheduled(cron = "59 59 23 * * *") @@ -302,7 +308,7 @@ public void processFamilyTemperatureDecrease() { } } - // 부모 1명 이상 일주일 미접속 시 온도 하락 + // 부모 1명 이상 일주일 아무 활동 없을 시 온도 하락 public void decreaseTemperatureForInactiveParent(String familyId) { // TODO: 부모 미접속 판별 로직 필요 boolean parentInactive = false; // 실제 판별로 대체 @@ -310,14 +316,14 @@ public void decreaseTemperatureForInactiveParent(String familyId) { Temperature temp = Temperature.builder() .userId(null) .familyId(familyId) - .temperature(-15.0) + .temperature(-10.0) .reason("INACTIVE_PARENT") .build(); temperatureRepository.save(temp); } } - // 자녀 1명 이상 일주일 미접속 시 온도 하락 + // 자녀 1명 이상 일주일 아무 활동 없을 시 온도 하락 public void decreaseTemperatureForInactiveChild(String familyId) { // TODO: 자녀 미접속 판별 로직 필요 boolean childInactive = false; // 실제 판별로 대체 @@ -325,14 +331,14 @@ public void decreaseTemperatureForInactiveChild(String familyId) { Temperature temp = Temperature.builder() .userId(null) .familyId(familyId) - .temperature(-15.0) + .temperature(-10.0) .reason("INACTIVE_CHILD") .build(); temperatureRepository.save(temp); } } - // 하루 동안 아무도 미접속 시 온도 하락 + // 하루 동안 아무도 활동 없을 시 시 온도 하락 public void decreaseTemperatureForNoLogin(String familyId) { // TODO: 전체 미접속 판별 로직 필요 boolean noLogin = false; // 실제 판별로 대체 @@ -340,7 +346,7 @@ public void decreaseTemperatureForNoLogin(String familyId) { Temperature temp = Temperature.builder() .userId(null) .familyId(familyId) - .temperature(-1.0) + .temperature(-0.5) .reason("NO_LOGIN") .build(); temperatureRepository.save(temp);