Skip to content

Fix/mission-popup-timer - #32

Merged
chaeyylee merged 1 commit into
mainfrom
fix/mission-popup-timer
Jul 10, 2026
Merged

Fix/mission-popup-timer#32
chaeyylee merged 1 commit into
mainfrom
fix/mission-popup-timer

Conversation

@chaeyylee

@chaeyylee chaeyylee commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • 버그 수정

    • 오늘의 미션 팝업이 현재 시간, 미션 상태 및 진행 가능 시간에 따라 정확히 표시됩니다.
    • 단기 디톡스 설정 시 미션 타이머가 실제 종료 시각에 맞춰 짧게 설정됩니다.
    • 자정을 넘기는 디톡스 종료 시간도 올바르게 반영됩니다.
  • 테스트

    • 10분 미만의 단기 디톡스 미션 타이머 동작을 검증하는 테스트를 추가했습니다.

@chaeyylee chaeyylee self-assigned this Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

오늘 미션의 데드라인이 디톡스 종료 시각을 반영하도록 변경되었고, 팝업 필요 여부가 현재 시간과 미션 상태를 기준으로 계산됩니다. 단기 디톡스의 데드라인 단축을 검증하는 테스트가 추가되었습니다.

Changes

미션 시간 처리

Layer / File(s) Summary
디톡스 종료 시각 기반 데드라인 계산
src/main/java/com/example/hackathon/domain/mission/service/MissionService.java, src/test/java/com/example/hackathon/domain/mission/service/MissionTimerTest.java
디톡스 종료 시각이 자정을 넘기는 경우를 보정하고, 기본 데드라인보다 이르면 종료 시각으로 단축합니다. 1분 디톡스의 데드라인 단축 동작을 테스트합니다.
현재 시간 기반 팝업 판정
src/main/java/com/example/hackathon/domain/mission/dto/response/MissionTodayResponse.java
서울 시간 기준 현재 시각이 미션 시간 범위에 있고 상태가 ASSIGNED 또는 CONFIRMED일 때 팝업이 필요하도록 계산합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 미션 팝업 타이머 관련 수정 내용을 잘 요약하고 있어 변경사항과 관련성이 높습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mission-popup-timer

Comment @coderabbitai help to get the list of available commands.

@chaeyylee
chaeyylee merged commit 5d87e7e into main Jul 10, 2026
2 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/example/hackathon/domain/mission/dto/response/MissionTodayResponse.java`:
- Around line 23-28: MissionTodayResponse.from currently bypasses the injected
Clock and duplicates MissionService.isPopupRequired. Change from to accept a
LocalDateTime now parameter and use it for popup evaluation, update all
MissionService callers—including getOrCreateTodayMission and
getTodayMissionStatus—to compute now via LocalDateTime.now(clock) and pass the
same value, and centralize the shared popup condition in one reusable method
such as UserMissionLog or a common utility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c795125-4a90-457a-947a-3d1194c398d7

📥 Commits

Reviewing files that changed from the base of the PR and between 821c382 and fdd108c.

📒 Files selected for processing (3)
  • src/main/java/com/example/hackathon/domain/mission/dto/response/MissionTodayResponse.java
  • src/main/java/com/example/hackathon/domain/mission/service/MissionService.java
  • src/test/java/com/example/hackathon/domain/mission/service/MissionTimerTest.java

Comment on lines +23 to +28
java.time.LocalDateTime now = java.time.LocalDateTime.now(java.time.ZoneId.of("Asia/Seoul"));
boolean popupRequired = !now.isBefore(log.getAssignedAt())
&& now.isBefore(log.getDeadlineAt())
&& (log.getStatus() == com.example.hackathon.domain.mission.entity.MissionStatus.ASSIGNED
|| log.getStatus() == com.example.hackathon.domain.mission.entity.MissionStatus.CONFIRMED);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Clock 주입을 무시하고 시스템 시각을 직접 사용 + isPopupRequired 로직 중복.

MissionServiceClock clock을 주입받아 모든 시간 계산에 LocalDateTime.now(clock)을 사용하고, 테스트에서도 setClockTime()으로 이를 모킹해 결정론적 테스트를 보장합니다. 하지만 이 from() 메서드는 LocalDateTime.now(ZoneId.of("Asia/Seoul"))을 직접 호출해 Clock을 완전히 우회하며, MissionService.isPopupRequired(log, now)(Line 265-269)와 동일한 조건식을 재구현하고 있습니다.

이로 인해 getTodayMissionStatusgetOrCreateTodayMission 두 API의 popupRequired 판정 로직이 서로 다른 시각 소스를 사용하게 되고, 한쪽만 수정될 경우 판정이 갈라질 위험이 있습니다. 또한 이 경로는 Clock 모킹이 불가능해 결정론적 테스트 작성이 어렵습니다(실제로 새로 추가된 shortDetoxTimeShortensDeadlineAt 테스트도 popupRequired를 검증하지 않습니다).

now를 서비스에서 전달받도록 시그니처를 변경하고, 가능하면 판정 로직을 한 곳(예: UserMissionLog 엔티티 또는 공용 유틸)으로 통합하는 것을 권장합니다.

♻️ 제안하는 수정
-    public static MissionTodayResponse from(UserMissionLog log) {
-        java.time.LocalDateTime now = java.time.LocalDateTime.now(java.time.ZoneId.of("Asia/Seoul"));
-        boolean popupRequired = !now.isBefore(log.getAssignedAt())
-                && now.isBefore(log.getDeadlineAt())
-                && (log.getStatus() == com.example.hackathon.domain.mission.entity.MissionStatus.ASSIGNED
-                    || log.getStatus() == com.example.hackathon.domain.mission.entity.MissionStatus.CONFIRMED);
+    public static MissionTodayResponse from(UserMissionLog log, LocalDateTime now) {
+        boolean popupRequired = !now.isBefore(log.getAssignedAt())
+                && now.isBefore(log.getDeadlineAt())
+                && (log.getStatus() == MissionStatus.ASSIGNED
+                    || log.getStatus() == MissionStatus.CONFIRMED);

         return new MissionTodayResponse(

MissionService.java 쪽 호출부도 동일한 now를 전달하도록 함께 수정이 필요합니다(현재 44-47행은 변경 범위 밖이라 diff 대신 코드블록으로 표기):

`@Transactional`
public MissionTodayResponse getOrCreateTodayMission(String deviceId) {
    LocalDateTime now = LocalDateTime.now(clock);
    return MissionTodayResponse.from(getOrCreateTodayMissionLog(deviceId, now), now);
}

Also applies to: 39-39

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/example/hackathon/domain/mission/dto/response/MissionTodayResponse.java`
around lines 23 - 28, MissionTodayResponse.from currently bypasses the injected
Clock and duplicates MissionService.isPopupRequired. Change from to accept a
LocalDateTime now parameter and use it for popup evaluation, update all
MissionService callers—including getOrCreateTodayMission and
getTodayMissionStatus—to compute now via LocalDateTime.now(clock) and pass the
same value, and centralize the shared popup condition in one reusable method
such as UserMissionLog or a common utility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant