docs(gift): 선물 요구사항 변경을 기록한다
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
| 작성일 | 2026-09-29 |
|
||||
| 요구사항 기준 | `docs/20260929_크리에이터_선물하기/prd.md` |
|
||||
| API 기준 | `docs/20260929_크리에이터_선물하기/prd.md`의 `8. API 계약` |
|
||||
| 현재 Phase | Phase 7 완료 |
|
||||
| 현재 Phase | Phase 9 완료 |
|
||||
| 현재 활성 Goal | 완료 |
|
||||
|
||||
## 목표
|
||||
@@ -38,6 +38,8 @@
|
||||
| 5 | 완료 | `3/3` | 완료 | 없음 |
|
||||
| 6 | 완료 | `2/2` | 완료 | 없음 |
|
||||
| 7 | 완료 | `3/3` | 완료 | 없음 |
|
||||
| 8 | 완료 | `1/1` | 완료 | 없음 |
|
||||
| 9 | 완료 | `3/3` | 완료 | 없음 |
|
||||
|
||||
- 동시에 하나의 미완료 goal만 운용한다.
|
||||
- 구현 중 요구사항이 바뀌면 이 문서의 체크박스와 범위를 먼저 갱신한 뒤 코드를 수정한다.
|
||||
@@ -655,6 +657,57 @@
|
||||
|
||||
**Expected:** 모든 명령 exit 0. PRD `GIFT-001`~`GIFT-013`이 구현·검증·문서 추적으로 연결된다.
|
||||
|
||||
## Phase 9: 카테고리 확장과 신청번호 정책 변경
|
||||
|
||||
**Phase 결과:** 카테고리는 분류번호, 내부 범용코드, 분류명, 접수코드, 대표품목, 파손면책 조건을 관리하고, 신청번호는 카테고리+날짜별 sequence로 발급된다.
|
||||
|
||||
**선행조건:** Phase 8 완료, 사용자 확정 요구사항 반영.
|
||||
|
||||
**Phase 완료 조건:** `P9-T1`~`P9-T3`와 `P9-GATE` 완료, 검증 기록 누적.
|
||||
|
||||
### 구현 항목
|
||||
|
||||
#### Task 9.1 문서와 DDL 계약 갱신
|
||||
|
||||
**Goal 실행 `P9-T1`:** PRD, 구현 계획, DDL에 확정된 카테고리 필드와 신청번호 정책을 반영한다.
|
||||
|
||||
- **Files:** Modify `prd.md`, `plan-task.md`, `gift-schema.sql`.
|
||||
- [x] **RED:** 문서/DDL의 기존 `G{yyyyMMdd}{dailySequence6}`와 기존 카테고리 필드 계약을 확인한다.
|
||||
- [x] **GREEN:** `classificationNumber`, `categoryCode`, `name`, `receiptCode`, `representativeItem`, `requiresDamageWaiver`, `isActive`와 새 신청번호 형식을 반영한다.
|
||||
- [x] **검증:** 세 문서가 같은 제약과 응답 정책을 설명하는지 대조한다.
|
||||
|
||||
#### Task 9.2 카테고리 persistence/API 계약 변경
|
||||
|
||||
**Goal 실행 `P9-T2`:** 관리자 API는 새 카테고리 필드를 각각 관리하고, 사용자 폼 옵션은 `분류명/대표품목` 조합 name만 내려준다.
|
||||
|
||||
- **Files:** Modify `GiftCategory.kt`, `GiftAdminService.kt`, `AdminGiftRequest.kt`, `AdminGiftResponse.kt`, `GiftQueryService.kt`, `GiftResponse.kt` if needed.
|
||||
- **Tests:** Modify `GiftEntityMappingTest.kt`, `GiftAdminServiceTest.kt`, `GiftQueryServiceTest.kt`, `AdminGiftControllerTest.kt`, `GiftControllerTest.kt`.
|
||||
- [x] **RED:** 새 필드 저장/조회, 관리자 request/response 분리, 사용자 폼 옵션 name 조합, validation 실패 테스트를 작성하고 실패를 확인한다.
|
||||
- [x] **GREEN:** 엔티티, DTO, service mapping, validation을 최소 구현한다.
|
||||
- [x] **검증:** 카테고리 관련 focused test를 실행한다.
|
||||
|
||||
#### Task 9.3 신청번호 채번 정책 변경
|
||||
|
||||
**Goal 실행 `P9-T3`:** `receiptCode-classificationNumberYYMMDDSequenceNo` 형식과 카테고리+날짜별 sequence를 구현한다.
|
||||
|
||||
- **Files:** Modify `GiftApplicationNoSequence.kt`, `GiftApplicationNoSequenceRepository.kt`, `GiftApplicationNoGenerator.kt`, `GiftCommandService.kt`.
|
||||
- **Tests:** Modify `GiftApplicationNoGeneratorTest.kt`, `GiftCommandServiceTest.kt`, `GiftEntityMappingTest.kt` if needed.
|
||||
- [x] **RED:** 형식, 카테고리별 독립 sequence, 날짜별 독립 sequence, `9999` 초과, 병렬 unique 테스트를 작성하고 실패를 확인한다.
|
||||
- [x] **GREEN:** 기존 transaction/locking 방식을 유지해 최소 구현한다.
|
||||
- [x] **검증:** 신청번호 focused test와 직접 영향 테스트를 실행한다.
|
||||
|
||||
### Phase 9 Gate
|
||||
|
||||
```bash
|
||||
./gradlew test --tests "kr.co.vividnext.sodalive.v2.gift.application.GiftApplicationNoGeneratorTest" --tests "kr.co.vividnext.sodalive.v2.gift.application.GiftAdminServiceTest" --tests "kr.co.vividnext.sodalive.v2.gift.application.GiftQueryServiceTest" --tests "kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.GiftEntityMappingTest" --tests "kr.co.vividnext.sodalive.v2.api.admin.gift.adapter.in.web.AdminGiftControllerTest" --tests "kr.co.vividnext.sodalive.v2.api.gift.adapter.in.web.GiftControllerTest"
|
||||
./gradlew ktlintCheck
|
||||
git diff --check
|
||||
```
|
||||
|
||||
**Expected:** 모든 명령 exit 0. 기존 datetime UTC ISO 문자열 변경은 유지된다.
|
||||
|
||||
**결과:** 완료. 2026-09-30 기준 Phase 9 Gate 명령 3개 모두 성공.
|
||||
|
||||
## 실행 순서와 의존성
|
||||
|
||||
| 순서 | Goal | 선행조건 | 병행 가능 | 차단 시 다음 행동 |
|
||||
@@ -1147,6 +1200,65 @@ P7은 FCM 확장 후 전체 상태 전이를 연결하고 최종 회귀로 종
|
||||
- 검증: focused gift/API/scheduler/admin test 실행 결과 `BUILD SUCCESSFUL`, `./gradlew ktlintCheck` 실행 결과 `BUILD SUCCESSFUL`
|
||||
- 남은 항목: 없음
|
||||
|
||||
## Phase 8: 선물 응답 시각 UTC ISO 문자열화
|
||||
|
||||
**Phase 결과:** 선물 사용자/관리자 API가 모든 응답 시각을 클라이언트가 안전하게 해석할 수 있는 UTC ISO 문자열로 반환한다.
|
||||
|
||||
**선행조건:** `P7-GATE` 완료와 PRD `DEC-013` 확정.
|
||||
|
||||
**Phase 완료 조건:** `P8-T1` 완료와 focused/controller 회귀, gift 회귀, lint 검증 기록 누적.
|
||||
|
||||
### 구현 항목
|
||||
|
||||
#### Task 8.1 선물 response datetime 계약 수정
|
||||
|
||||
**Goal 실행 `P8-T1`:** `GiftResponse.kt`와 `AdminGiftResponse.kt`의 응답 시각 필드를 UTC ISO `String`으로 변환한다.
|
||||
|
||||
- **시작 조건:** PRD `DEC-013` 확인.
|
||||
- **완료 증거:** RED/GREEN/REFACTOR 체크박스, focused controller test, gift 회귀 test, `ktlintCheck` 통과.
|
||||
- **범위 밖:** 전역 Jackson 설정 변경, 선물 외 API datetime 마이그레이션, DB 저장 timezone 변경.
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/gift/dto/GiftResponse.kt`
|
||||
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/v2/api/admin/gift/dto/AdminGiftResponse.kt`
|
||||
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/gift/adapter/in/web/GiftControllerTest.kt`
|
||||
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/admin/gift/adapter/in/web/AdminGiftControllerTest.kt`
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Produces: 선물 사용자/관리자 API의 모든 populated datetime JSON 값은 `2026-09-30T12:00:00Z` 같은 UTC ISO 문자열이다.
|
||||
|
||||
- [x] **RED:** controller test의 선물 날짜/시간 응답 기대값을 `Z` 포함 UTC ISO 문자열로 변경한다.
|
||||
- [x] **RED 확인:** `./gradlew test --tests "kr.co.vividnext.sodalive.v2.api.gift.adapter.in.web.GiftControllerTest" --tests "kr.co.vividnext.sodalive.v2.api.admin.gift.adapter.in.web.AdminGiftControllerTest"`를 실행해 기존 `LocalDateTime` 직렬화가 `Z`를 포함하지 않아 실패함을 확인한다.
|
||||
- [x] **GREEN:** response DTO의 `LocalDateTime` 필드를 `String`, `LocalDateTime?` 필드를 `String?`로 바꾸고 기존 `LocalDateTime.toUtcIso()` extension으로 변환한다.
|
||||
- [x] **GREEN 확인:** 같은 focused controller test가 통과하는지 확인한다.
|
||||
- [x] **REFACTOR:** 불필요한 import를 제거하고 `./gradlew test --tests "kr.co.vividnext.sodalive.v2.gift.*"`, `./gradlew ktlintCheck`, `git diff --check` 결과를 Progress에 기록한다.
|
||||
|
||||
### P8-T1 선물 response datetime 계약 수정 — 2026-09-30
|
||||
|
||||
- 상태: 완료
|
||||
- 무엇을: 선물 사용자/관리자 response DTO의 날짜/시간 필드를 `String`으로 바꾸고 `toUtcIso()`로 변환했다. 클라이언트 요약 문서도 UTC ISO 문자열 계약으로 동기화했다.
|
||||
- 왜: Jackson 기본 `LocalDateTime` 직렬화는 `2026-09-30T12:00:00`처럼 offset이 없어 클라이언트가 UTC로 안전하게 해석할 수 없기 때문이다.
|
||||
- 어떻게:
|
||||
- RED test: controller test 기대값을 `Z` 포함 문자열로 변경 후 focused test 실행 결과 11개 assertion 실패 확인.
|
||||
- GREEN 구현: `GiftResponse.kt`, `AdminGiftResponse.kt`에서 응답 시각 필드를 `String`/`String?`로 변경하고 기존 `LocalDateTime.toUtcIso()` extension 재사용.
|
||||
- 검증: focused controller test 실행 결과 `BUILD SUCCESSFUL`, `./gradlew test --tests "kr.co.vividnext.sodalive.v2.gift.*"` 실행 결과 `BUILD SUCCESSFUL`, `./gradlew ktlintCheck` 실행 결과 `BUILD SUCCESSFUL`, `git diff --check` 출력 없음, `rg -n -- "LocalDateTime"` 대상 response DTO/클라이언트 요약 문서 출력 없음, `./gradlew tasks --all` 실행 결과 `BUILD SUCCESSFUL`.
|
||||
- 남은 항목: 없음
|
||||
|
||||
### Phase 9 카테고리 확장과 신청번호 정책 변경 — 2026-09-30
|
||||
|
||||
- 상태: 완료
|
||||
- 무엇을: 카테고리에 분류번호, 접수코드, 대표품목을 추가하고 사용자 폼 옵션의 카테고리명은 `분류명/대표품목`으로 조합했다. 신청번호는 `receiptCode-classificationNumberYYMMDDSequenceNo` 형식으로 변경하고 sequence는 카테고리+날짜별로 분리했다.
|
||||
- 왜: `categoryCode`는 내부 범용코드로 유지하고, 운영용 분류번호/접수코드/대표품목을 별도 관리해야 하기 때문이다.
|
||||
- 어떻게:
|
||||
- RED 확인 1: 카테고리 추가 필드 테스트 작성 후 `compileTestKotlin`에서 `classificationNumber`, `receiptCode`, `representativeItem` 미구현 실패 확인
|
||||
- GREEN 확인 1: 카테고리 focused suite 실행 결과 `BUILD SUCCESSFUL`
|
||||
- RED 확인 2: 신청번호 generator 테스트 작성 후 기존 `generate(now)`와 sequence entity가 새 시그니처/필드를 지원하지 않아 `compileTestKotlin` 실패 확인
|
||||
- GREEN 확인 2: 신청번호 focused suite 실행 결과 `BUILD SUCCESSFUL`
|
||||
- Gate 확인: Phase 9 focused suite, `./gradlew ktlintCheck`, `git diff --check` 모두 성공
|
||||
- 남은 항목: 없음
|
||||
|
||||
## Decision Log
|
||||
|
||||
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 Goal/문서 |
|
||||
@@ -1156,6 +1268,8 @@ P7은 FCM 확장 후 전체 상태 전이를 연결하고 최종 회귀로 종
|
||||
| 2026-09-29 | `PLAN-DEC-003` | 확정 | 최종 Gate에서는 전체 `./gradlew test`를 실행한다 | 캔 결제, FCM, 스케줄러 등 공통 경계를 변경함 | `P7-GATE` |
|
||||
| 2026-09-29 | `PLAN-DEC-004` | 확정 | 신규 선물 구현은 v2 신규 도메인 관례대로 `domain`, `application`, `port`, `adapter` 구조를 사용한다 | 사용자 지시: v2 아래 구현된 관례만 확인하고 처리 | 전체 구현 |
|
||||
| 2026-09-30 | `PLAN-DEC-005` | 확정 | 운영 반영용 DDL에는 선물 도메인 FK를 명시하고, 선물 신청 건에는 최종 결제 금액 스냅샷만 저장한다 | 사용자 결정: 제대로 가는 방향 선호, `basePriceCan`은 신청 건에 불필요 | `gift-schema.sql`, `Gift` |
|
||||
| 2026-09-30 | `PLAN-DEC-006` | 확정 | 선물 API response datetime은 전역 Jackson 설정이 아니라 DTO response boundary에서 UTC ISO 문자열로 변환한다 | 선물 API만의 공개 계약 보강이며 전역 변경은 기존 API 영향이 큼 | `P8-T1`, `client-api-summary.md` |
|
||||
| 2026-09-30 | `PLAN-DEC-007` | 확정 | 기존 `categoryCode`는 내부 범용코드로 유지하고 분류번호/접수코드/대표품목을 추가하며, 신청번호는 카테고리+날짜별 sequence로 발급한다 | 사용자 확정: 카테고리 필드 의미와 사용자 폼 옵션 표시 규칙 분리 | `P9-T1`~`P9-T3` |
|
||||
|
||||
## 발견된 문제
|
||||
|
||||
|
||||
Reference in New Issue
Block a user