[v1.2.0] 미션 및 레벨 프로덕션 적용#266
Conversation
…sMessage, active 필드 추가 - BadgeCondition VO로 조건을 (conditionType + threshold + params JSON)으로 데이터화 - BadgeConditionType 7종, BadgeCategory 4종(CONSISTENCY/PROJECT/PATTERN/ACCESS)으로 재정의 - BadgeResponse 응답 스키마 확장 (category, threshold, iconUrl, congrats 필드) - V34: badges 컬럼 확장 - V36: 배지 10종 재시드 (꾸준함 3·프로젝트 3·패턴 3·접속 1). 폐기 배지(STREAK_3_DAYS/DEEP_QUESTION)는 DELETE 후 재시드, user_badges orphan은 mapNotNull로 안전 처리
develop의 V34(alter_tags)와 #263(V34/V35)과의 버전 중복을 피하기 위해 배지/스트릭 마이그레이션을 V37~V40으로 재넘버링. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
develop의 V34(alter_tags) 및 #262(배지/스트릭) 마이그레이션과의 버전 중복을 피하기 위해 미션 테이블 마이그레이션을 V35/V36으로 재넘버링. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Lv.2 만료 배치 네이티브 쿼리 테이블명 오타 수정 (user_mission/mission → user_missions/missions) - 연속주차(Lv.3·5·7·9) 진행률을 회고 건 단위가 아닌 주 단위로 증가하도록 수정 - 실패 미션(WAIT_CONFIRM)을 현재 미션 조회에 포함시켜 실패 팝업 노출·재도전 가능하도록 수정 - 재도전 시 상태를 IN_PROGRESS로 복구 (UserMission.retry) - Lv.2 만료 lazy 처리를 FAILED→WAIT_CONFIRM으로 통일 - 실패 팝업 노출 조건을 WAIT_CONFIRM 상태로 한정 (정상 진행 미션의 오노출 방지) - 스케줄러 지난주 계산 off-by-one 수정 - 미사용 dead code(checkAndHandleWeeklyReset) 제거 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
[DIT-209] 미션/레벨 시스템 구현
Dit 213 streak system dev
- 배지 생성/수정/활성토글 API (POST/PUT/PATCH) + 감사로그 - 배지 상세 조회, condition-types 메타(조건타입 7종/카테고리 4종 + param 스키마) API - 레벨 분포/미션 달성/배지 획득 운영 통계 API (/admin/stats/levels·missions·badges) - Badge 도메인에 update/changeActive 추가, 편집 필드 var 전환 - BadgeRepository.findById, UserLevel/UserMission 집계 쿼리 추가 - 미션/레벨은 통계 조회만 (닫힌 사다리, CRUD 미제공) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
프론트엔드 숫자 변환 규칙(type==number/integer)과 일치시켜 weeklyMinCount가 문자열이 아닌 숫자로 전송되도록 함. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 홈 V2 응답에 hasUnreadNotification(boolean) 추가 — 알림 전체 목록 호출 대신 exists 쿼리로 새 알림 유무만 경량 반환 - 프로필 V2 응답에 currentLevel 추가 (UserLevelFinder 경량 조회, 기본 1) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
[home/profile] 홈 안읽은 알림 플래그 + 프로필 레벨 응답 추가
V39 배지 재정의 이후 새 badge_id로 갈아끼우면서 보존된 구 스트릭 시절 획득 기록(orphan)을 삭제. 현재 badges에 없는 badge_id의 user_badges 제거. 배포 시점부터 신규 배지는 다음 트리거 이벤트부터 평가/부여(소급 없음). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aa664cb036
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| val from = LocalDateTime.of(weekStartDate, LocalTime.MIDNIGHT) | ||
| val to = LocalDateTime.of(weekEndDate, LocalTime.of(23, 59, 59)) | ||
|
|
||
| val completedRetros = retrospectiveRepository.findCompletedByUserIdAndPeriod(userId, from, to) | ||
| val completedDates = completedRetros.map { it.completedAt?.toLocalDate() }.toSet() |
There was a problem hiding this comment.
Convert weekly mission status dates through ServiceTime
This weekly-status query builds raw LocalDateTime bounds and then calls completedAt?.toLocalDate(), whereas the rest of the retrospective date APIs convert service dates with ServiceTime before querying/displaying. For retros completed between 00:00 and 08:59 KST, the stored UTC timestamp falls on the previous UTC date, so the current-week range/day set can omit the user's actual KST completion and show an incomplete day after they saved a retro.
Useful? React with 👍 / 👎.
[db] 구 배지 획득 기록(orphan user_badges) 정리 V42
코드리뷰(#266) 반영: - MissionScheduler 연속주차 실패 판정: LocalDate.now()/raw 경계 → ServiceTime.today() KST 주차 + startOfDayUtc 배타적 경계로 쿼리 - MissionQueryService 주간 현황: from/to를 ServiceTime UTC로, completedAt은 toServiceDate(KST)로 변환해 00:00~08:59 KST 완료분 누락 방지 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
[fix] 주간 미션 KST 주차 경계 ServiceTime 변환 (#266 리뷰 반영)
회고 전(레벨 행 없는) 유저가 /api/v1/missions/current 호출 시 UserLevelNotFound로 500 나던 문제 수정. ensureInitialized로 UserLevel(Lv.1)+ Lv.1 미션을 자가 생성 후 조회하도록 변경(소급/마이그레이션 불필요). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
[fix] /missions/current 신규 유저 500(USER_LEVEL_NOT_FOUND) 해결
홈 진입 시 home/mission/profile 3콜 중 mission을 /home에 합침. - HomeV2Response에 mission(CurrentMissionResponse) 추가 - getHomeV2가 ensureInitialized 후 getCurrentMission 포함 반환 (신규 유저 500 방지) - 마이페이지의 /api/v2/users/profile 단독 호출은 유지 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- UserLevel 기본값 0, 프로필 기본 레벨 0 - 현재 미션 = findByLevel(currentLevel+1), 미션 정의(Lv.1~10)는 유지 - awardNextLevel: 다음 미션레벨=currentLevel+1, Lv.10 완료 시 종료 - 운영 통계 레벨 분포 0~10, 행 없는 유저=Lv.0 - V43: 기존 user_levels 1-base→0-base 보정 + 기본값 0 - 배지/스트릭은 변경 없음 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
[level] 레벨을 0부터 시작 (currentLevel=완료 미션 수)
[home] /api/v2/home에 현재 미션 포함(홈 집계, 3콜→1콜)
이전(launch 전) 회고가 누적/주간 배지 조건에 소급 반영되던 문제 수정. achievement.feature-launched-at(설정, env 오버라이드) 이후 completedAt 회고만 countCompletedRetros / 주간 카운트에 반영. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
첫 미션 완료(Lv.1 도달)는 '첫 기록' 배지로 처리되고 레벨업 팝업/레벨 이미지가 없으므로(lv-1.svg 부재), Lv.1 도달 시 levelUpPopupShown=true로 두어 팝업을 띄우지 않음. 레벨업 팝업은 Lv.2부터. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
[badge] 배지 카운트 비소급 (launch 이후 회고만)
[fix] 레벨 1 도달 시 레벨업 팝업 미노출 (배지로 처리)
TIME_LIMITED·CUMULATIVE 미션 progress를 startedAt.toLocalDate()(자정) 기준 날짜 범위로 세어, 레벨업을 발생시킨 같은 날 회고까지 중복 카운트되던 버그 수정. countRetrosAfter(completedAt > startedAt 타임스탬프)로 레벨업 시점 이후 회고만 집계. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
No description provided.