From f2f3261195074a0a076f3dc4a5ae28e0de3883ed Mon Sep 17 00:00:00 2001 From: 1Seob Date: Sat, 20 Jun 2026 20:35:18 +0900 Subject: [PATCH 1/6] =?UTF-8?q?docs(global):=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20README=20=EC=98=A8=EB=B3=B4=EB=94=A9=20=EA=B0=80?= =?UTF-8?q?=EC=9D=B4=EB=93=9C=20=EC=A0=95=EB=B9=84=20(#185)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(infra): 로컬 Codex 스킬 추적 제거 * docs(global): 프로젝트 README 온보딩 가이드 정비 * docs(global): README 저장소 clone 경로 수정 * docs(global): README 서비스 링크와 소개 이미지 추가 * docs(global): README 소개 이미지 크기 조정 --- .gitignore | 4 +- README.md | 210 ++++++++++++++++++++++++++--------- docs/images/nadab-banner.png | Bin 0 -> 620086 bytes 3 files changed, 160 insertions(+), 54 deletions(-) create mode 100644 docs/images/nadab-banner.png diff --git a/.gitignore b/.gitignore index 66d84356..044f3c21 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,6 @@ node_modules # 오늘의 리포트 프롬프트 /src/main/resources/secret/ -AGENTS.md \ No newline at end of file +AGENTS.md +.codex/ +PROJECT_LOG.md \ No newline at end of file diff --git a/README.md b/README.md index e87f19a6..09a747b1 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,192 @@ -# ⏳ Nadab BE +# Nadab Backend -### 🔗️ Note -> 이 문서는 [Saerok 프로젝트](https://github.com/DevKor-github/saerok-BE)의 README를 참고하여 구성하였으며, Nadab의 컨벤션에 맞게 수정되었습니다. +

+ Nadab 서비스 소개 +

+ +사용자의 일상 답변을 바탕으로 AI 일간·주간·월간·유형 리포트를 생성하고, 친구·소셜 상호작용과 운영 기능을 제공하는 Spring Boot 백엔드 서버입니다. + +--- + +## 서비스 링크 + +- [App Store](https://apps.apple.com/us/app/%EB%82%98%EB%8B%B5-ai-%EC%9E%90%EA%B8%B0%EC%84%B1%EC%B0%B0-%EA%B8%B0%EB%A1%9D-%EB%B0%8F-%EA%B0%90%EC%A0%95-%EB%B6%84%EC%84%9D-%EC%9D%BC%EA%B8%B0/id6761776437) +- [Google Play](https://play.google.com/store/apps/details?id=com.nadab.app) +- [Web](https://www.nadab.app/) --- -## 🛠️ Stacks +## 기술 스택 -- JAVA 21 -- Spring Boot 3.5.7 -- PostgreSQL -- JPA (Hibernate) -- Gradle -- GitHub Actions + AWS EC2 (CI/CD) +| 구분 | 기술 | +| --- | --- | +| Language | Java 21 | +| Framework | Spring Boot 3.5.7, Spring Security, Spring Data JPA | +| Database | PostgreSQL, Flyway | +| AI | Spring AI, OpenAI, Google Gemini | +| Infrastructure | AWS EC2, S3, KMS, Firebase Cloud Messaging | +| API / View | Swagger/OpenAPI, Thymeleaf | +| Test | JUnit 5, Mockito, AssertJ, Testcontainers | +| Build / CI/CD | Gradle, GitHub Actions | --- -## 🧾 Commit Convention +## 주요 기능 -Nadab은 Conventional Commits 규칙을 기반으로 commitlint를 사용해 커밋 메시지 품질을 관리합니다. +- OAuth 및 이메일 기반 인증, JWT 토큰 관리 +- 오늘의 질문과 답변 기록, 이미지 처리 +- AI 기반 일간·주간·월간·유형 리포트 생성 +- 친구, 피드 공유, 댓글, 좋아요, 신고·차단 +- 푸시 알림, 이메일 인증, 알림 설정 +- 앱 버전, 사용자 통계 등 관리자 기능 +- 사용자 지갑 및 크리스탈 이력 관리 -모든 커밋은 아래와 같이 지정된 type / scope / subject 형식을 따라야 하며, 규칙을 위반하면 커밋이 거부됩니다. +--- + +## 로컬 개발 환경 설정 + +### 1. 저장소 클론 + +```bash +git clone https://github.com/DevKor-github/nadab-BE.git +cd nadab-BE ``` -(): - +커밋 도구를 사용하려면 Node.js를 설치한 뒤 패키지를 설치합니다. + +```bash +npm install ``` +### 2. JDK 설정 + +- JDK 21을 설치합니다. +- IntelliJ에서 프로젝트 루트 또는 `build.gradle`을 프로젝트로 엽니다. +- Project SDK와 Gradle JVM을 JDK 21로 설정합니다. -### 1. type (무엇을 했는가) +### 3. PostgreSQL 준비 -| 타입 | 설명 | -|------|------| -| ✨ `feat` | 새로운 기능 추가 | -| 🐛 `fix` | 버그 수정 | -| 📚 `docs` | 문서 관련 변경 (예: README, 주석) | -| 💎 `style` | 코드 의미에는 영향을 주지 않는 스타일 변경 (포맷, 세미콜론 등) | -| 📦 `refactor` | 리팩토링 (기능 변경 없이 구조 개선) | -| 🚀 `perf` | 성능 개선 | -| 🚨 `test` | 테스트 코드 추가/보완 | -| ⚙️ `ci` | CI 설정 및 관련 스크립트 변경 | -| ♻️ `chore` | 기타 작업 (예: 패키지 설치, 설정 파일 변경, 디렉토리 정리 등) | -| 🗑 `revert` | 이전 커밋 되돌리기 | +로컬 PostgreSQL에 사용할 데이터베이스를 생성합니다. 애플리케이션 시작 시 Flyway가 `src/main/resources/db/migration`의 마이그레이션을 자동 적용하며, Hibernate는 스키마를 `validate` 모드로 검증합니다. --- -### 2. scope (어디를 바꿨는가) +## 테스트 + +단위 테스트는 JUnit 5, Mockito, AssertJ를 사용합니다. 데이터베이스 통합 테스트는 PostgreSQL Testcontainers를 사용하므로 Docker Desktop이 실행 중이어야 합니다. + +```powershell +# 전체 테스트 +.\gradlew.bat test + +# 단일 테스트 클래스 +.\gradlew.bat test --tests "com.devkor.ifive.nadab.domain.auth.application.AuthServiceV2Test" +``` -| Scope | 설명 | -|:-------------|:---------------------------------------------| -| 🔐 `auth` | 인증/인가 도메인 | -| 🙋‍♂️ `user` | 사용자 도메인 | -| 🤖 `ai` | AI 처리 | -| 👥 `friend` | 친구 도메인 | -| 📧 `notify` | 알림/이메일 전송 | -| 🛠️ `infra` | 설정/인프라 | -| 🗄️ `db` | 데이터베이스 및 마이그레이션 | -| 🌎 `global` | 공용 설정 및 전역 리소스 | +`develop` 브랜치 대상 Pull Request에는 GitHub Actions가 전체 테스트를 자동 실행합니다. --- -### 3. subject (무슨 일이 일어났는가) +## 배포 환경 -- 변경된 내용을 한 줄로 간결하게 요약합니다. -- 한국어로 자연스럽게 작성하며, 읽는 사람이 바로 이해할 수 있도록 합니다. -- 문장 끝에는 마침표(.)를 붙이지 않습니다. +- `develop` 브랜치 push: 개발 EC2 자동 배포 +- `main` 브랜치 push: 운영 EC2 자동 배포 +- GitHub Actions에서 JDK 21로 실행 JAR을 빌드합니다. +- 빌드 산출물을 SCP로 EC2에 전송하고 프로필별 환경 변수를 주입해 애플리케이션을 재시작합니다. +- PostgreSQL, S3, KMS, Firebase 및 외부 AI API는 환경별 자격 증명으로 연동합니다. -> 예: 회원 탈퇴 기능 추가, 토큰 재발급 로직 수정, 빌드 스크립트 구조 개선 +배포 관련 secret은 GitHub Environment의 `dev`, `prod` 설정에서 관리하며 저장소에 직접 기록하지 않습니다. --- -### 4. body (왜 그렇게 했는가) +## 브랜치 전략 -- 선택 항목이지만, 기능 수정이나 리팩토링 등 맥락이 필요한 변경이라면 작성합니다. -- “무엇을 바꿨고, 왜 바꿨는지”를 중심으로 구체적으로 설명합니다. -> 예: -사용자 조회 시 불필요한 쿼리가 반복 실행되어 응답 속도가 저하되었습니다. -쿼리 캐싱을 적용하여 데이터 접근 횟수를 줄이고 성능을 개선했습니다. +- `main`: 운영 배포 브랜치 +- `develop`: 개발 통합 및 개발 서버 배포 브랜치 +- 기능 개발 브랜치: `feat/*`, `fix/*`, `refactor/*`, `chore/*` 등 작업 목적에 맞게 생성 + +기능 브랜치는 `develop`을 기준으로 작업하고 Pull Request를 통해 병합합니다. 운영 반영은 `develop`에서 검증된 변경을 `main`으로 병합해 진행합니다. --- -### 설치 및 사용법 +## 프로젝트 구조 + +```text +src +├─ main +│ ├─ java/com/devkor/ifive/nadab +│ │ ├─ domain # 비즈니스 도메인 +│ │ └─ global # 공통 설정, 보안, 예외, 인프라, 유틸리티 +│ └─ resources +│ ├─ db/migration # Flyway 마이그레이션 +│ ├─ templates # 관리자·통계 Thymeleaf 화면 +│ └─ application*.yml +└─ test + └─ java/com/devkor/ifive/nadab + └─ infra # Testcontainers 및 테스트 빌더 +``` + +각 도메인은 기능에 따라 다음 계층을 조합합니다. + +- `api`: Controller와 요청·응답 DTO +- `application`: 유스케이스, 트랜잭션, 이벤트, 스케줄러 +- `core`: Entity, Repository, Domain Service, 내부 모델 +- `infra`: 외부 AI API, 스토리지 등 외부 연동 구현 + +공통 설정과 여러 도메인이 함께 사용하는 기능은 `global`에 둡니다. 데이터베이스 스키마 변경은 JPA 설정에 의존하지 않고 Flyway 마이그레이션으로 관리합니다. + +--- + +## 커밋 컨벤션 + +Conventional Commits 기반의 commitlint, Husky, Commitizen을 사용합니다. + +```text +(): + + +``` + +### Type + +| Type | 설명 | +| --- | --- | +| `feat` | 새로운 기능 추가 | +| `fix` | 버그 수정 | +| `docs` | 문서 변경 | +| `chore` | 빌드·설정 등 기타 작업 | +| `style` | 동작에 영향을 주지 않는 스타일 변경 | +| `refactor` | 기능 변경 없는 구조 개선 | +| `test` | 테스트 추가 또는 보완 | +| `perf` | 성능 개선 | +| `ci` | CI/CD 설정 변경 | +| `revert` | 이전 커밋 되돌리기 | + +### Scope + +허용 scope는 다음과 같습니다. + +```text +admin, auth, user, ai, report, moderation, search, stats, +friend, social, notify, infra, db, global +``` + +- subject는 변경 내용을 한국어로 간결하게 작성합니다. +- subject 끝에 마침표를 붙이지 않습니다. +- 맥락이 필요한 변경은 body에 무엇을 바꿨고 왜 바꿨는지 작성합니다. +- scope는 생략할 수 있지만, 사용할 경우 허용 목록 중 하나를 선택해야 합니다. + +```bash +# 직접 작성 +git commit -m "feat(report): 월간 리포트 조회 기능 추가" + +# Commitizen 프롬프트 사용 +npm run commit +``` + +--- -- 터미널에서 `npm install`을 실행하여 commitlint를 설치합니다. -- 커밋 시 터미널에서 `npm run commit` 입력을 통해 커밋합니다. +## 참고 +- 마이그레이션: `src/main/resources/db/migration` +- CI/CD: `.github/workflows` diff --git a/docs/images/nadab-banner.png b/docs/images/nadab-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..2e6be9de000769eca4f3412307216ef6806cab4e GIT binary patch literal 620086 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 k9vwFk^0|-y)s^uov={8rg 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 NpJpSoYUu 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≫F+*NG^2^g6iuW> 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%0A(f)1rrvUFItd$MdO%XdTh8hl5R0y%F=z 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 literal 0 HcmV?d00001 From 9f8720e2f6a08a578c505a6f73e9c7543f9a76c4 Mon Sep 17 00:00:00 2001 From: 1Seob Date: Tue, 30 Jun 2026 17:50:56 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat(report):=20=EC=9B=94=EA=B0=84=20?= =?UTF-8?q?=EB=A6=AC=ED=8F=AC=ED=8A=B8=20V2=20=EB=B9=84=EA=B5=90=C2=B7?= =?UTF-8?q?=EC=86=8C=EC=85=9C=C2=B7=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=8B=A4?= =?UTF-8?q?=EC=96=91=ED=99=94=20=EB=B0=8F=20=EC=A1=B0=ED=9A=8C=20=EA=B3=84?= =?UTF-8?q?=EC=95=BD=20=ED=99=95=EC=9E=A5=20(#186)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(report): 월간 리포트 V2 비교 대상 확정 로직 추가 현재 월 이전의 가장 최근 COMPLETED V2 리포트 조회 및 previousReportId 이벤트 전달, BASELINE·COMPARISON 분기 단위 테스트 추가 * feat(report): 월간 리포트 V2 비교 입력 조립 직전 리포트의 기간·콘텐츠·감정 통계 수집, 긍정 감정 비율 차이와 주요 감정 변화 계산 및 LLM 입력 전달 * feat(report): 월간 리포트 V2 비교 프롬프트 분기 추가 COMPARISON 프롬프트 로딩과 비교 입력 JSON 치환, 감정 비교 응답 검증 및 dev·prod 배포 환경 변수 설정 추가 * feat(report): 월간 리포트 V2에 감정 비교 결과 저장 및 조회 응답 수정 emotion_comparison JSONB 스냅샷 저장과 조회 응답 확장, LLM segment 정규화 및 V2 길이 검증 에러 코드 세분화 * feat(report): 월간 리포트 V2에 소셜 요약 저장 모델 추가 monthly_reports_v2에 social_summary JSONB 컬럼을 추가하고 기존 리포트의 비노출 기본값을 backfill함 * feat(report): 월간 소셜 반응 집계 쿼리 추가 사용자의 DailyReport에 받은 좋아요와 댓글·대댓글을 월별 친구 단위로 집계함. ACCEPTED 친구 관계를 기준으로 비친구, 탈퇴 사용자, 양방향 차단 관계와 삭제 댓글은 제외함 * feat(report): 월간 소셜 노출 및 랭킹 계산 추가 좋아요와 댓글 합계 및 참여 친구 조건으로 소셜 요약 노출 여부를 계산함. 반응 횟수 내림차순과 한국어 가나다순으로 최대 3명을 선정하고 displayOrder와 topRank를 분리해 공동 1위 강조를 지원함 * feat(report): 월간 소셜 요약 생성 파이프라인 연결 KST 월 범위의 소셜 반응을 집계해 MonthlySocialSummaryContent를 생성하고 confirmMonthlyText에서 기존 분석 결과와 함께 원자적으로 저장함. 소셜 집계 실패 시 리포트 실패 및 크리스탈 환불 흐름을 적용함 * feat(report): 월간 소셜 요약 조회 응답 추가 MonthlyReportResponseV2에 소셜 페이지 노출 정보와 좋아요·댓글 랭킹을 추가함 * refactor(report): 월간 리포트 locator 응답 계약 확장 V1/V2 공통 MonthlyReportLocatorResponse를 도입하고 id를 reportId로 명확화함. 나의 월간 리포트 조회 응답을 report와 previousReport 두 슬롯으로 확장해 버전별 상세 API 라우팅 기반을 마련함 * feat(report): 월간 리포트 현재·이전 locator 조회 추가 지난달은 상태와 무관하게, 지지난달은 COMPLETED 상태만 V2 우선·V1 fallback으로 탐색하는 resolver를 추가함 * fix(report): 월간 리포트 V1 조회 보안과 locator 계약 보완 V1 상세 조회에 인증 사용자 기반 소유권 검증과 403 응답을 추가함. locator API의 null·상태·version별 상세 경로를 문서화하고, 이전 월을 현재 범위에서 파생해 연도 경계를 안정적으로 처리함 * feat(report): 월간 리포트 V2 이미지 화풍 프리셋 선택 기능 추가 이미지 화풍 프리셋과 저장 컬럼을 추가하고, 최근 완료 리포트의 화풍을 제외해 결정적으로 프리셋을 선택·저장하도록 구현. 재시도 시 동일한 화풍을 유지하도록 보장하고 Repository, 선택기, 할당 서비스 테스트 추가. * feat(ai): 월간 이미지 프롬프트 조립기 추가 리포트 내용과 기간, 화풍 프리셋을 MonthlyImagePromptContext로 정규화하고 공통 안전 제약과 8개 화풍별 시각 지침을 합성하는 MonthlyImagePromptComposer 추가. 빈 입력 처리와 프리셋별 프롬프트 분기를 단위 테스트로 검증 * feat(ai): 이미지 클라이언트에 프롬프트 context 연동 OpenAiImageClient가 MonthlyImagePromptContext를 받아 composer로 프롬프트를 조립하도록 확장하고 기존 HTTP 요청 경로를 재사용 * feat(report): 월간 이미지 화풍 생성 파이프라인 연결 MonthlyReportGenerationListenerV2에서 프리셋을 할당하고 MonthlyImagePromptContext를 구성해 context 기반 이미지 생성을 호출하도록 전환 * refactor(ai): 월간 이미지 프롬프트 중복 경로 제거 MonthlyReportPromptLoader의 고정 이미지 템플릿과 OpenAiImageClient의 구형 DTO 기반 진입점을 제거하고, 이미지 프롬프트 생성을 MonthlyImagePromptComposer로 단일화 * feat(report): 월간 이미지 색상 팔레트 선택 기반 추가 8종의 색상 팔레트와 저장 컬럼을 추가하고 최근 완료 리포트의 팔레트를 제외하는 결정적 선택 로직 구현. 화풍과 팔레트를 함께 할당하며 기존 부분 저장 상태에서는 누락된 값만 보완하도록 확장 * feat(ai): 월간 이미지 색상 팔레트 생성 파이프라인 연결 저장된 화풍과 색상 팔레트를 MonthlyImagePromptContext로 전달하고 팔레트별 배경·주조색·강조색 지침을 이미지 프롬프트에 합성. 공통 색감 편향과 기본 파스텔 회귀를 제한하고 listener를 통합 visual preset 계약으로 전환 * test(ai): 월간 이미지 조합 및 팔레트 검증 강화 8개 화풍과 8개 팔레트의 전체 64개 프롬프트 조합이 서로 구분되는지 검증하고, 팔레트별 핵심 색상 표현이 유지되는지 테스트 추가 * refactor(report): 불필요한 월간 리포트 current 조회 제거 GET /api/v2/monthly-report/current와 전용 응답 DTO·query service 메서드·테스트를 제거하고 월간 리포트 locator 조회 경로를 기본 API로 단일화 * chore(global): 개인 Codex 스킬 추적 제거 --- .github/workflows/deploy-to-dev-ec2.yml | 4 + .github/workflows/deploy-to-prod-ec2.yml | 4 + gradle/wrapper/gradle-wrapper.properties | 2 +- .../api/MonthlyReportController.java | 8 +- .../api/MonthlyReportControllerV2.java | 35 ++- .../MonthlyReportLocatorResponse.java | 20 ++ .../dto/response/MonthlyReportResponseV2.java | 15 +- .../MonthlySocialRankingItemResponse.java | 21 ++ .../MonthlySocialSummaryResponse.java | 20 ++ .../response/MyMonthlyReportLookupItemV2.java | 17 -- .../MyMonthlyReportLookupResponseV2.java | 9 +- .../MonthlyImagePresetAssignmentService.java | 88 +++++++ .../MonthlyReportLocatorResolver.java | 61 +++++ .../MonthlyReportQueryService.java | 7 +- .../MonthlyReportQueryServiceV2.java | 70 ++++-- .../application/MonthlyReportTxServiceV2.java | 31 ++- .../MonthlyImageColorPaletteSelector.java | 41 +++ .../helper/MonthlyImagePresetSelector.java | 39 +++ .../helper/MonthlyImagePromptComposer.java | 140 +++++++++++ ...MonthlyReportComparisonInputAssembler.java | 105 ++++++++ .../MonthlySocialSummaryCalculator.java | 104 ++++++++ .../MonthlyReportGenerationListenerV2.java | 69 ++++- .../MonthlyEmotionComparisonContent.java | 45 ++++ .../content/MonthlySocialRankingItem.java | 23 ++ .../content/MonthlySocialSummaryContent.java | 42 ++++ .../core/dto/MonthlyImagePromptContext.java | 55 ++++ .../core/dto/MonthlyImageVisualPreset.java | 16 ++ .../dto/MonthlyReportComparisonInputDto.java | 30 +++ ...lyReportGenerationRequestedEventDtoV2.java | 2 +- .../dto/MonthlySocialInteractionCountDto.java | 12 + .../core/entity/MonthlyImageColorPalette.java | 12 + .../core/entity/MonthlyImageStylePreset.java | 12 + .../core/entity/MonthlyReportV2.java | 37 +++ .../repository/MonthlyReportV2Repository.java | 45 +++- .../MonthlySocialQueryRepository.java | 84 +++++++ .../service/MonthlySocialSummaryService.java | 40 +++ .../infra/MonthlyReportLlmClientV2.java | 203 +++++++++++++-- .../infra/OpenAiImageClient.java | 26 +- .../LocalMonthlyReportPromptLoader.java | 43 ++-- .../monthly/MonthlyReportPromptLoader.java | 2 +- .../SecretMonthlyReportPromptLoader.java | 36 +-- .../nadab/global/core/response/ErrorCode.java | 2 + ...otion_comparison_to_monthly_reports_v2.sql | 2 + ...d_social_summary_to_monthly_reports_v2.sql | 17 ++ ...e_prompt_variant_to_monthly_reports_v2.sql | 2 + ...ge_color_palette_to_monthly_reports_v2.sql | 2 + .../MonthlyReportV2RepositoryTest.java | 235 ++++++++++++++++++ .../MonthlySocialQueryRepositoryTest.java | 165 ++++++++++++ .../api/MonthlyReportControllerV2Test.java | 28 +++ .../MyMonthlyReportLookupResponseV2Test.java | 27 ++ ...nthlyImagePresetAssignmentServiceTest.java | 132 ++++++++++ .../MonthlyReportLocatorResolverTest.java | 109 ++++++++ .../MonthlyReportQueryServiceTest.java | 79 ++++++ .../MonthlyReportQueryServiceV2Test.java | 193 ++++++++++++++ .../MonthlyReportTxServiceV2Test.java | 169 +++++++++++++ .../MonthlyImageColorPaletteSelectorTest.java | 52 ++++ .../MonthlyImagePresetSelectorTest.java | 52 ++++ .../MonthlyImagePromptComposerTest.java | 152 +++++++++++ ...hlyReportComparisonInputAssemblerTest.java | 70 ++++++ .../MonthlySocialSummaryCalculatorTest.java | 93 +++++++ ...MonthlyReportGenerationListenerV2Test.java | 136 ++++++++++ .../MonthlyEmotionComparisonContentTest.java | 52 ++++ .../MonthlySocialSummaryContentTest.java | 31 +++ .../MonthlySocialSummaryServiceTest.java | 58 +++++ .../infra/MonthlyReportLlmClientV2Test.java | 184 ++++++++++++++ .../infra/OpenAiImageClientTest.java | 55 ++++ 66 files changed, 3610 insertions(+), 162 deletions(-) create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportLocatorResponse.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialRankingItemResponse.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialSummaryResponse.java delete mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupItemV2.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentService.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolver.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelector.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelector.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposer.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssembler.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculator.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContent.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialRankingItem.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContent.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImagePromptContext.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImageVisualPreset.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportComparisonInputDto.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlySocialInteractionCountDto.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageColorPalette.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageStylePreset.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlySocialQueryRepository.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryService.java create mode 100644 src/main/resources/db/migration/V20260618_1200__IS_add_emotion_comparison_to_monthly_reports_v2.sql create mode 100644 src/main/resources/db/migration/V20260628_1200__IS_add_social_summary_to_monthly_reports_v2.sql create mode 100644 src/main/resources/db/migration/V20260629_1200__IS_add_image_prompt_variant_to_monthly_reports_v2.sql create mode 100644 src/main/resources/db/migration/V20260629_1700__IS_add_image_color_palette_to_monthly_reports_v2.sql create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlyReportV2RepositoryTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlySocialQueryRepositoryTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2Test.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2Test.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentServiceTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolverTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2Test.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2Test.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelectorTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelectorTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposerTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssemblerTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculatorTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContentTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContentTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryServiceTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2Test.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClientTest.java diff --git a/.github/workflows/deploy-to-dev-ec2.yml b/.github/workflows/deploy-to-dev-ec2.yml index 690bd76f..f01fd6cb 100644 --- a/.github/workflows/deploy-to-dev-ec2.yml +++ b/.github/workflows/deploy-to-dev-ec2.yml @@ -86,6 +86,10 @@ jobs: MONTHLY_V2_BASELINE_PROMPT_B64="${{ secrets.MONTHLY_V2_BASELINE_PROMPT_B64 }}" MONTHLY_V2_BASELINE_PROMPT="$(printf '%s' "$MONTHLY_V2_BASELINE_PROMPT_B64" | base64 -d | tr -d '\r')" export MONTHLY_V2_BASELINE_PROMPT + + MONTHLY_V2_COMPARISON_PROMPT_B64="${{ secrets.MONTHLY_V2_COMPARISON_PROMPT_B64 }}" + MONTHLY_V2_COMPARISON_PROMPT="$(printf '%s' "$MONTHLY_V2_COMPARISON_PROMPT_B64" | base64 -d | tr -d '\r')" + export MONTHLY_V2_COMPARISON_PROMPT EVIDENCE_CARD_PROMPT_B64="${{ secrets.EVIDENCE_CARD_PROMPT_B64 }}" EVIDENCE_CARD_PROMPT="$(printf '%s' "$EVIDENCE_CARD_PROMPT_B64" | base64 -d | tr -d '\r')" diff --git a/.github/workflows/deploy-to-prod-ec2.yml b/.github/workflows/deploy-to-prod-ec2.yml index 75b327a9..b27ad5a1 100644 --- a/.github/workflows/deploy-to-prod-ec2.yml +++ b/.github/workflows/deploy-to-prod-ec2.yml @@ -86,6 +86,10 @@ jobs: MONTHLY_V2_BASELINE_PROMPT_B64="${{ secrets.MONTHLY_V2_BASELINE_PROMPT_B64 }}" MONTHLY_V2_BASELINE_PROMPT="$(printf '%s' "$MONTHLY_V2_BASELINE_PROMPT_B64" | base64 -d | tr -d '\r')" export MONTHLY_V2_BASELINE_PROMPT + + MONTHLY_V2_COMPARISON_PROMPT_B64="${{ secrets.MONTHLY_V2_COMPARISON_PROMPT_B64 }}" + MONTHLY_V2_COMPARISON_PROMPT="$(printf '%s' "$MONTHLY_V2_COMPARISON_PROMPT_B64" | base64 -d | tr -d '\r')" + export MONTHLY_V2_COMPARISON_PROMPT EVIDENCE_CARD_PROMPT_B64="${{ secrets.EVIDENCE_CARD_PROMPT_B64 }}" EVIDENCE_CARD_PROMPT="$(printf '%s' "$EVIDENCE_CARD_PROMPT_B64" | base64 -d | tr -d '\r')" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d4081da4..4f5eb9dc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportController.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportController.java index 3c485cb4..a9fecdb4 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportController.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportController.java @@ -166,6 +166,11 @@ public ResponseEntity> getMyMonthlyRepor description = "월간 리포트 조회 성공", content = @Content(schema = @Schema(implementation = MonthlyReportResponse.class), mediaType = "application/json") ), + @ApiResponse( + responseCode = "403", + description = "- ErrorCode: MONTHLY_REPORT_ACCESS_FORBIDDEN - 본인 월간 리포트만 조회 가능", + content = @Content + ), @ApiResponse( responseCode = "404", description = "- ErrorCode: MONTHLY_REPORT_NOT_FOUND - 월간 리포트를 찾을 수 없음", @@ -174,9 +179,10 @@ public ResponseEntity> getMyMonthlyRepor } ) public ResponseEntity> getMonthlyReportById( + @AuthenticationPrincipal UserPrincipal principal, @PathVariable Long id ) { - MonthlyReportResponse response = monthlyReportQueryService.getMonthlyReportById(id); + MonthlyReportResponse response = monthlyReportQueryService.getMonthlyReportById(principal.getId(), id); return ApiResponseEntity.ok(response); } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2.java index f229dc6f..022d9ed7 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2.java @@ -137,13 +137,18 @@ public ResponseEntity>> getAllRepor @Operation( summary = "나의 월간 리포트 조회 V2", description = """ - 사용자의 (지난 달에 대한) 월간 리포트를 조회합니다.
+ 사용자의 지난달·지지난달 월간 리포트 위치 정보를 조회합니다.
- report: 존재하지 않으면 null, 존재하면 id와 version을 반환합니다.
+ report: 지난달 리포트이며 존재하지 않으면 null입니다.
+ previousReport: 지지난달 완료 리포트이며 존재하지 않으면 null입니다.
+ 두 슬롯은 서로 독립적으로 null일 수 있습니다.
+ 각 항목은 reportId, version, month, status를 반환합니다.
+ report.status: PENDING | IN_PROGRESS | TEXT_COMPLETED | COMPLETED | FAILED
+ previousReport.status: 존재하는 경우 항상 COMPLETED
version 규칙: - - monthly_reports - 1인 경우 : GET /api/v1/monthly-report/{id}로 조회 (기존의 레거시 버전) - - monthly_reports - 2인 경우 : GET /api/v2/monthly-report/{id}로 조회 (새로운 V2 버전) + - version 1인 경우 : GET /api/v1/monthly-report/{reportId}로 조회 (기존의 레거시 버전) + - version 2인 경우 : GET /api/v2/monthly-report/{reportId}로 조회 (새로운 V2 버전) """, security = @SecurityRequirement(name = "bearerAuth"), responses = { @@ -194,7 +199,7 @@ public ResponseEntity> getMyMont 다음은 각 페이지에서 활용되는 필드의 값에 대한 설명입니다.
comparisonType: 최초 생성인지 이전 리포트가 존재하는지 여부입니다.
- 현재는 모두 최초 생성이기 때문에 "BASELINE"으로 고정되어 있고, 이전 리포트가 존재하는 경우에는 "COMPARISON"으로 반환될 예정입니다.
+ 이전에 완료된 V2 월간 리포트가 없으면 "BASELINE", 있으면 "COMPARISON"으로 반환됩니다.
**<페이지 1>**
summary : 월간 기록 요약
@@ -203,15 +208,31 @@ public ResponseEntity> getMyMont **<페이지 2>**
dominantKeyword : 이번 달 요약 단어
+ emotionTrend : BASELINE은 "NOT_SUPPORTED", COMPARISON은 주요 감정의 변동 양상
emotionStats.emotions : 감정에 대한 통계가 빈도 기준 내림차순으로 정렬되어 있습니다.
+ emotionComparison : 직전 월간 리포트 감정 비교 스냅샷이며 BASELINE인 경우 null입니다.
+ - emotionComparison.previousReportId : 비교 대상인 직전 완료 리포트 ID
+ - emotionComparison.previousMonth : 비교 대상 월
+ - emotionComparison.previousEmotionStats : 직전 리포트의 감정 통계
+ - emotionComparison.positivePercentPointChange : 현재와 직전 리포트의 긍정 감정 비율 차이(%p)
+ emotionSummaryContent.styledText.segments : 감정 분석 텍스트
- - emotionTrend : "NOT_SUPPORTED" (현재는 고정. 변동 양상은 최초 생성 월간 리포트에서는 지원되지 않음. 이후 업데이트 예정)
**<페이지 3>**
commentSummary : 나답의 한 마디 요약
comment.segments : 나답의 한 마디 텍스트
interestStats.interests : 카테고리(관심사)에 대한 통계가 빈도 기준 내림차순으로 정렬되어 있습니다.
+ + **<페이지 4>**
+ socialSummary.visible : 월간 소셜 페이지 노출 여부
+ socialSummary.month : 집계 대상 월
+ socialSummary.likeRanking : 내 DailyReport에 좋아요를 많이 누른 친구 최대 3명
+ socialSummary.commentRanking : 내 DailyReport에 댓글·대댓글을 많이 작성한 친구 최대 3명
+ - displayOrder : 화면 표시 순서(1~3)
+ - userId : 친구 사용자 ID
+ - nickname : 친구 닉네임
+ - profileImageUrl : 친구 프로필 이미지 URL
+ - topRank : 공동 1위를 포함한 1위 강조 여부
""", security = @SecurityRequirement(name = "bearerAuth"), responses = { diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportLocatorResponse.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportLocatorResponse.java new file mode 100644 index 00000000..fcef089a --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportLocatorResponse.java @@ -0,0 +1,20 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "버전별 월간 리포트 상세 조회를 위한 위치 정보") +public record MonthlyReportLocatorResponse( + @Schema(description = "월간 리포트 ID") + Long reportId, + + @Schema(description = "월간 리포트 버전", allowableValues = {"1", "2"}, example = "2") + int version, + + @Schema(description = "월간 리포트 대상 월", example = "5") + int month, + + @Schema(description = "월간 리포트 상태", example = "COMPLETED") + MonthlyReportStatus status +) { +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportResponseV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportResponseV2.java index 934a97d4..80a0c1b4 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportResponseV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlyReportResponseV2.java @@ -1,6 +1,7 @@ package com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response; import com.devkor.ifive.nadab.domain.monthlyreport.core.content.InterestStatsContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyEmotionComparisonContent; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportComparisonType; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; @@ -32,15 +33,18 @@ public record MonthlyReportResponseV2( @Schema(description = "핵심 키워드") String dominantKeyword, + @Schema(description = "감정 흐름 요약") + String emotionTrend, + @Schema(description = "감정 통계") TypeEmotionStatsContent emotionStats, + @Schema(description = "직전 월간 리포트 감정 비교 스냅샷. BASELINE인 경우 null", nullable = true) + MonthlyEmotionComparisonContent emotionComparison, + @Schema(description = "감정 요약(styled)") TypeTextContent emotionSummaryContent, - @Schema(description = "감정 흐름 요약") - String emotionTrend, - @Schema(description = "코멘트(styled)") StyledText comment, @@ -48,6 +52,9 @@ public record MonthlyReportResponseV2( String commentSummary, @Schema(description = "관심사 통계") - InterestStatsContent interestStats + InterestStatsContent interestStats, + + @Schema(description = "월간 소셜 반응 요약") + MonthlySocialSummaryResponse socialSummary ) { } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialRankingItemResponse.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialRankingItemResponse.java new file mode 100644 index 00000000..e322a602 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialRankingItemResponse.java @@ -0,0 +1,21 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; + +public record MonthlySocialRankingItemResponse( + @Schema(description = "화면 표시 순서", example = "1") + int displayOrder, + + @Schema(description = "친구 사용자 ID", example = "12") + Long userId, + + @Schema(description = "친구 닉네임", example = "가나다") + String nickname, + + @Schema(description = "친구 프로필 이미지 URL", nullable = true) + String profileImageUrl, + + @Schema(description = "공동 1위를 포함한 1위 강조 여부", example = "true") + boolean topRank +) { +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialSummaryResponse.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialSummaryResponse.java new file mode 100644 index 00000000..bc386ade --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MonthlySocialSummaryResponse.java @@ -0,0 +1,20 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.List; + +public record MonthlySocialSummaryResponse( + @Schema(description = "월간 소셜 페이지 노출 여부", example = "true") + boolean visible, + + @Schema(description = "집계 대상 월", example = "5") + int month, + + @Schema(description = "내 DailyReport에 좋아요를 많이 누른 친구 랭킹") + List likeRanking, + + @Schema(description = "내 DailyReport에 댓글·대댓글을 많이 작성한 친구 랭킹") + List commentRanking +) { +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupItemV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupItemV2.java deleted file mode 100644 index f5df4979..00000000 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupItemV2.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response; - -import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; -import io.swagger.v3.oas.annotations.media.Schema; - -@Schema(description = "나의 월간 리포트 라우팅 정보") -public record MyMonthlyReportLookupItemV2( - @Schema(description = "리포트 ID") - Long id, - @Schema(description = "리포트 버전", example = "2") - int version, - @Schema(description = "리포트 대상 월") - int month, - @Schema(description = "리포트 상태", example = "COMPLETED") - MonthlyReportStatus status -) { -} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2.java index 00328b06..d0e67d49 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2.java @@ -2,9 +2,12 @@ import io.swagger.v3.oas.annotations.media.Schema; -@Schema(description = "나의 월간 리포트 단건 조회 응답") +@Schema(description = "나의 현재·이전 월간 리포트 위치 조회 응답") public record MyMonthlyReportLookupResponseV2( - @Schema(description = "월간 리포트 라우팅 정보. 리포트가 없으면 null", nullable = true) - MyMonthlyReportLookupItemV2 report + @Schema(description = "지난달 월간 리포트 위치 정보. 리포트가 없으면 null", nullable = true) + MonthlyReportLocatorResponse report, + + @Schema(description = "지지난달 완료 월간 리포트 위치 정보. 리포트가 없으면 null", nullable = true) + MonthlyReportLocatorResponse previousReport ) { } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentService.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentService.java new file mode 100644 index 00000000..8a7d4ad9 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentService.java @@ -0,0 +1,88 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application; + +import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlyImageColorPaletteSelector; +import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlyImagePresetSelector; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImageVisualPreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import com.devkor.ifive.nadab.global.core.response.ErrorCode; +import com.devkor.ifive.nadab.global.exception.ForbiddenException; +import com.devkor.ifive.nadab.global.exception.NotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional +public class MonthlyImagePresetAssignmentService { + + private static final int RECENT_PRESET_LIMIT = 3; + + private final MonthlyReportV2Repository monthlyReportV2Repository; + + public MonthlyImageVisualPreset getOrAssignVisualPreset(Long userId, Long reportId) { + MonthlyReportV2 report = monthlyReportV2Repository.findById(reportId) + .orElseThrow(() -> new NotFoundException(ErrorCode.MONTHLY_REPORT_NOT_FOUND)); + if (report.getUser() == null || report.getUser().getId() == null + || !report.getUser().getId().equals(userId)) { + throw new ForbiddenException(ErrorCode.MONTHLY_REPORT_ACCESS_FORBIDDEN); + } + MonthlyImageStylePreset stylePreset = getOrAssignStylePreset(userId, reportId, report); + MonthlyImageColorPalette colorPalette = getOrAssignColorPalette(userId, reportId, report); + return new MonthlyImageVisualPreset(stylePreset, colorPalette); + } + + private MonthlyImageStylePreset getOrAssignStylePreset( + Long userId, + Long reportId, + MonthlyReportV2 report + ) { + if (report.getImagePromptVariant() == null) { + List recentPresets = + monthlyReportV2Repository.findRecentCompletedImagePromptVariants( + userId, + reportId, + PageRequest.of(0, RECENT_PRESET_LIMIT) + ); + MonthlyImageStylePreset selected = MonthlyImagePresetSelector.select( + userId, + reportId, + report.getMonthStartDate(), + recentPresets + ); + report.assignImagePromptVariant(selected); + return selected; + } + return report.getImagePromptVariant(); + } + + private MonthlyImageColorPalette getOrAssignColorPalette( + Long userId, + Long reportId, + MonthlyReportV2 report + ) { + if (report.getImageColorPalette() == null) { + List recentPalettes = + monthlyReportV2Repository.findRecentCompletedImageColorPalettes( + userId, + reportId, + PageRequest.of(0, RECENT_PRESET_LIMIT) + ); + MonthlyImageColorPalette selected = MonthlyImageColorPaletteSelector.select( + userId, + reportId, + report.getMonthStartDate(), + recentPalettes + ); + report.assignImageColorPalette(selected); + return selected; + } + return report.getImageColorPalette(); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolver.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolver.java new file mode 100644 index 00000000..a76ae453 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolver.java @@ -0,0 +1,61 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application; + +import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlyReportLocatorResponse; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReport; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportRepository; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class MonthlyReportLocatorResolver { + + private final MonthlyReportRepository monthlyReportRepository; + private final MonthlyReportV2Repository monthlyReportV2Repository; + + public Optional findByMonth(Long userId, LocalDate monthStartDate) { + return monthlyReportV2Repository.findByUserIdAndMonthStartDate(userId, monthStartDate) + .map(this::toLocatorResponse) + .or(() -> monthlyReportRepository.findByUserIdAndMonthStartDate(userId, monthStartDate) + .map(this::toLocatorResponse)); + } + + public Optional findCompletedByMonth(Long userId, LocalDate monthStartDate) { + return monthlyReportV2Repository.findByUserIdAndMonthStartDateAndStatus( + userId, + monthStartDate, + MonthlyReportStatus.COMPLETED + ) + .map(this::toLocatorResponse) + .or(() -> monthlyReportRepository.findByUserIdAndMonthStartDateAndStatus( + userId, + monthStartDate, + MonthlyReportStatus.COMPLETED + ) + .map(this::toLocatorResponse)); + } + + private MonthlyReportLocatorResponse toLocatorResponse(MonthlyReportV2 report) { + return new MonthlyReportLocatorResponse( + report.getId(), + 2, + report.getMonthStartDate().getMonthValue(), + report.getStatus() == null ? MonthlyReportStatus.PENDING : report.getStatus() + ); + } + + private MonthlyReportLocatorResponse toLocatorResponse(MonthlyReport report) { + return new MonthlyReportLocatorResponse( + report.getId(), + 1, + report.getMonthStartDate().getMonthValue(), + report.getStatus() == null ? MonthlyReportStatus.PENDING : report.getStatus() + ); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryService.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryService.java index 27b3edfc..8042c6ec 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryService.java @@ -9,6 +9,7 @@ import com.devkor.ifive.nadab.domain.user.core.entity.User; import com.devkor.ifive.nadab.domain.user.core.repository.UserRepository; import com.devkor.ifive.nadab.global.core.response.ErrorCode; +import com.devkor.ifive.nadab.global.exception.ForbiddenException; import com.devkor.ifive.nadab.global.exception.NotFoundException; import com.devkor.ifive.nadab.global.shared.util.MonthRangeCalculator; import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; @@ -53,9 +54,13 @@ public MyMonthlyReportResponse getMyMonthlyReport(Long userId) { ); } - public MonthlyReportResponse getMonthlyReportById(Long id) { + public MonthlyReportResponse getMonthlyReportById(Long userId, Long id) { MonthlyReport report = monthlyReportRepository.findById(id) .orElseThrow(() -> new NotFoundException(ErrorCode.MONTHLY_REPORT_NOT_FOUND)); + if (report.getUser() == null || report.getUser().getId() == null + || !report.getUser().getId().equals(userId)) { + throw new ForbiddenException(ErrorCode.MONTHLY_REPORT_ACCESS_FORBIDDEN); + } MonthRangeDto range = MonthRangeCalculator.monthRangeOf(report.getMonthStartDate()); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2.java index c2037c8a..054bb046 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2.java @@ -1,11 +1,15 @@ package com.devkor.ifive.nadab.domain.monthlyreport.application; import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.AllReportItemResponseV2; -import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MyMonthlyReportLookupItemV2; +import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlyReportLocatorResponse; import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MyMonthlyReportLookupResponseV2; import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlyReportResponseV2; +import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlySocialRankingItemResponse; +import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlySocialSummaryResponse; import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.ReportListTypeV2; import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyContentFactory; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialRankingItem; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReport; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; @@ -43,6 +47,7 @@ public class MonthlyReportQueryServiceV2 { private final WeeklyReportRepository weeklyReportRepository; private final UserRepository userRepository; private final ProfileImageUrlBuilder profileImageUrlBuilder; + private final MonthlyReportLocatorResolver monthlyReportLocatorResolver; public List getAllReports(Long userId, ReportListTypeV2 type) { if (!userRepository.existsById(userId)) { @@ -120,11 +125,21 @@ public MyMonthlyReportLookupResponseV2 getMyMonthlyReport(Long userId) { } MonthRangeDto range = MonthRangeCalculator.getLastMonthRange(); - return monthlyReportV2Repository.findByUserIdAndMonthStartDate(userId, range.monthStartDate()) - .map(this::toLookupResponse) - .or(() -> monthlyReportRepository.findByUserIdAndMonthStartDate(userId, range.monthStartDate()) - .map(this::toLookupResponse)) - .orElseGet(() -> new MyMonthlyReportLookupResponseV2(null)); + return getMyMonthlyReport(userId, range); + } + + MyMonthlyReportLookupResponseV2 getMyMonthlyReport(Long userId, MonthRangeDto range) { + MonthlyReportLocatorResponse report = monthlyReportLocatorResolver + .findByMonth(userId, range.monthStartDate()) + .orElse(null); + MonthRangeDto previousRange = MonthRangeCalculator.monthRangeOf( + range.monthStartDate().minusMonths(1) + ); + MonthlyReportLocatorResponse previousReport = monthlyReportLocatorResolver + .findCompletedByMonth(userId, previousRange.monthStartDate()) + .orElse(null); + + return new MyMonthlyReportLookupResponseV2(report, previousReport); } public MonthlyReportResponseV2 getMonthlyReportById(Long userId, Long id) { @@ -151,34 +166,41 @@ private MonthlyReportResponseV2 toResponse(MonthlyReportV2 report) { imageUrl, content.discovered(), content.dominantKeyword(), + content.emotionTrend(), report.getEmotionStats() == null ? TypeContentFactory.emptyEmotionStats() : report.getEmotionStats().normalized(), + report.getEmotionComparison() == null ? null : report.getEmotionComparison().normalized(), report.getEmotionSummaryContent() == null ? TypeContentFactory.emptyText() : report.getEmotionSummaryContent().normalized(), - content.emotionTrend(), content.comment(), content.commentSummary(), - report.getInterestStats() == null ? MonthlyContentFactory.emptyInterestStats() : report.getInterestStats().normalized() + report.getInterestStats() == null ? MonthlyContentFactory.emptyInterestStats() : report.getInterestStats().normalized(), + toSocialSummaryResponse(report) ); } - private MyMonthlyReportLookupResponseV2 toLookupResponse(MonthlyReportV2 report) { - return new MyMonthlyReportLookupResponseV2( - new MyMonthlyReportLookupItemV2( - report.getId(), - 2, - report.getMonthStartDate().getMonthValue(), - report.getStatus() == null ? MonthlyReportStatus.PENDING : report.getStatus() - ) + private MonthlySocialSummaryResponse toSocialSummaryResponse(MonthlyReportV2 report) { + MonthlySocialSummaryContent socialSummary = report.getSocialSummary() == null + ? MonthlySocialSummaryContent.empty(report.getMonthStartDate().getMonthValue()) + : report.getSocialSummary().normalized(); + + return new MonthlySocialSummaryResponse( + socialSummary.visible(), + socialSummary.month(), + socialSummary.likeRanking().stream().map(this::toSocialRankingItemResponse).toList(), + socialSummary.commentRanking().stream().map(this::toSocialRankingItemResponse).toList() ); } - private MyMonthlyReportLookupResponseV2 toLookupResponse(MonthlyReport report) { - return new MyMonthlyReportLookupResponseV2( - new MyMonthlyReportLookupItemV2( - report.getId(), - 1, - report.getMonthStartDate().getMonthValue(), - report.getStatus() == null ? MonthlyReportStatus.PENDING : report.getStatus() - ) + private MonthlySocialRankingItemResponse toSocialRankingItemResponse(MonthlySocialRankingItem item) { + String profileImageUrl = item.profileImageKey() != null + ? profileImageUrlBuilder.buildUrl(item.profileImageKey()) + : profileImageUrlBuilder.buildDefaultUrl(item.defaultProfileType()); + + return new MonthlySocialRankingItemResponse( + item.displayOrder(), + item.userId(), + item.nickname(), + profileImageUrl, + item.topRank() ); } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2.java index be32ae0c..8d30fcaa 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2.java @@ -2,6 +2,8 @@ import com.devkor.ifive.nadab.domain.monthlyreport.core.content.InterestStatsContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyEmotionComparisonContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportGenerationRequestedEventDtoV2; import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReserveResultDto; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.*; @@ -19,6 +21,8 @@ import com.devkor.ifive.nadab.global.exception.NotEnoughCrystalException; import com.devkor.ifive.nadab.global.exception.NotFoundException; import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; +import com.devkor.ifive.nadab.global.shared.util.MonthRangeCalculator; +import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; @@ -79,9 +83,17 @@ public MonthlyReserveResultDto reserveMonthly(User user, boolean exists) { public MonthlyReserveResultDto reserveMonthlyAndPublish(User user) { - boolean exists = monthlyReportV2Repository.existsByUserIdAndStatus(user.getId(), MonthlyReportStatus.COMPLETED); + MonthRangeDto range = MonthRangeCalculator.getLastMonthRange(); + Long previousReportId = monthlyReportV2Repository + .findFirstByUserIdAndStatusAndMonthStartDateBeforeOrderByMonthStartDateDesc( + user.getId(), + MonthlyReportStatus.COMPLETED, + range.monthStartDate() + ) + .map(MonthlyReportV2::getId) + .orElse(null); - MonthlyReserveResultDto reserve = this.reserveMonthly(user, exists); + MonthlyReserveResultDto reserve = this.reserveMonthly(user, previousReportId != null); monthlyReportV2Repository.updateStatus(reserve.reportId(), MonthlyReportStatus.IN_PROGRESS); @@ -90,7 +102,7 @@ public MonthlyReserveResultDto reserveMonthlyAndPublish(User user) { reserve.reportId(), user.getId(), reserve.crystalLogId(), - exists + previousReportId )); return reserve; @@ -113,11 +125,14 @@ public void confirmMonthlyText( MonthlyReportV2Content content, TypeTextContent emotionSummaryContent, TypeEmotionStatsContent emotionStats, - InterestStatsContent interestStats + InterestStatsContent interestStats, + MonthlyEmotionComparisonContent emotionComparison, + MonthlySocialSummaryContent socialSummary ) { MonthlyReportV2Content contentNormalized = content.normalized(); TypeTextContent emotionSummaryContentNormalized = emotionSummaryContent.normalized(); InterestStatsContent interestStatsNormalized = interestStats.normalized(); + MonthlySocialSummaryContent socialSummaryNormalized = socialSummary.normalized(); String summary = contentNormalized.summary(); String commentSummary = contentNormalized.commentSummary(); @@ -127,12 +142,18 @@ public void confirmMonthlyText( String emotionSummaryContentJson; String emotionStatsJson; String interestStatsJson; + String emotionComparisonJson; + String socialSummaryJson; try { contentJson = objectMapper.writeValueAsString(contentNormalized); emotionSummaryContentJson = objectMapper.writeValueAsString(emotionSummaryContentNormalized); emotionStatsJson = objectMapper.writeValueAsString(emotionStats.normalized()); interestStatsJson = objectMapper.writeValueAsString(interestStatsNormalized); + emotionComparisonJson = emotionComparison == null + ? null + : objectMapper.writeValueAsString(emotionComparison.normalized()); + socialSummaryJson = objectMapper.writeValueAsString(socialSummaryNormalized); } catch (Exception e) { throw new AiResponseParseException(ErrorCode.AI_RESPONSE_PARSE_FAILED); } @@ -145,6 +166,8 @@ public void confirmMonthlyText( dominantKeyword, emotionStatsJson, interestStatsJson, + emotionComparisonJson, + socialSummaryJson, MonthlyReportStatus.TEXT_COMPLETED.name() ); } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelector.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelector.java new file mode 100644 index 00000000..32a59d6e --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelector.java @@ -0,0 +1,41 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public final class MonthlyImageColorPaletteSelector { + + private static final String SELECTION_SALT = "monthly-image-color-palette-v1"; + + private MonthlyImageColorPaletteSelector() { + } + + public static MonthlyImageColorPalette select( + Long userId, + Long reportId, + LocalDate monthStartDate, + List recentPalettes + ) { + Set excluded = recentPalettes == null + ? Set.of() + : recentPalettes.stream() + .filter(Objects::nonNull) + .collect(Collectors.toUnmodifiableSet()); + + List candidates = Arrays.stream(MonthlyImageColorPalette.values()) + .filter(palette -> !excluded.contains(palette)) + .toList(); + if (candidates.isEmpty()) { + candidates = List.of(MonthlyImageColorPalette.values()); + } + + int seed = Objects.hash(SELECTION_SALT, userId, reportId, monthStartDate); + return candidates.get(Math.floorMod(seed, candidates.size())); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelector.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelector.java new file mode 100644 index 00000000..8a28e7d6 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelector.java @@ -0,0 +1,39 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public final class MonthlyImagePresetSelector { + + private MonthlyImagePresetSelector() { + } + + public static MonthlyImageStylePreset select( + Long userId, + Long reportId, + LocalDate monthStartDate, + List recentPresets + ) { + Set excluded = recentPresets == null + ? Set.of() + : recentPresets.stream() + .filter(Objects::nonNull) + .collect(Collectors.toUnmodifiableSet()); + + List candidates = Arrays.stream(MonthlyImageStylePreset.values()) + .filter(preset -> !excluded.contains(preset)) + .toList(); + if (candidates.isEmpty()) { + candidates = List.of(MonthlyImageStylePreset.values()); + } + + int seed = Objects.hash(userId, reportId, monthStartDate); + return candidates.get(Math.floorMod(seed, candidates.size())); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposer.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposer.java new file mode 100644 index 00000000..6bf01c02 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposer.java @@ -0,0 +1,140 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImagePromptContext; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import org.springframework.stereotype.Component; + +import java.util.EnumMap; +import java.util.Map; + +@Component +public class MonthlyImagePromptComposer { + + private static final Map STYLE_DIRECTIONS = styleDirections(); + private static final Map COLOR_DIRECTIONS = colorDirections(); + + public String compose(MonthlyImagePromptContext context) { + String styleDirection = STYLE_DIRECTIONS.get(context.stylePreset()); + if (styleDirection == null) { + throw new IllegalArgumentException("Unsupported monthly image style preset: " + context.stylePreset()); + } + String colorDirection = COLOR_DIRECTIONS.get(context.colorPalette()); + if (colorDirection == null) { + throw new IllegalArgumentException("Unsupported monthly image color palette: " + context.colorPalette()); + } + + return """ + Create a premium abstract monthly self-reflection cover image for a Korean journaling app. + + Report context: + - Monthly summary: %s + - Gentle comment summary: %s + - Dominant keyword: %s + - Month: %s to %s + + Visual direction: + %s + + Color direction: + %s + + The specified color direction is mandatory. Use it to control the background, dominant forms, lighting, and accents. Preserve clear hue separation and recognizable palette identity. Do not default to lavender, pink, beige, peach, or a generic pastel gradient unless those colors are explicitly included in the selected color direction. + + Interpret the report context symbolically through the selected visual direction. Vary the objects, color relationships, lighting, spatial rhythm, and composition according to the emotional meaning. Do not fall back to a generic fixed scene. + + The image should feel calm, reflective, comforting, refined, and suitable for a premium mobile app monthly report card. Keep a clear focal point and enough negative space. + + Strict constraints: + No people, no faces, no hands, no body parts. + No readable text, no letters, no Korean characters, no English characters, no numbers, no symbols, no handwriting, no typography. + No UI, no logos, no brand marks, no watermarks. + No medical, therapy, counseling, hospital, or diagnosis-related imagery. + No dark, horror, gloomy, childish, or overly dramatic mood. + """.formatted( + context.summary(), + context.commentSummary(), + context.dominantKeyword(), + context.monthStartDate(), + context.monthEndDate(), + styleDirection, + colorDirection + ); + } + + private static Map styleDirections() { + EnumMap directions = + new EnumMap<>(MonthlyImageStylePreset.class); + directions.put(MonthlyImageStylePreset.BOTANICAL_COLLAGE, """ + Botanical editorial collage using abstract leaves, petals, seeds, and organic silhouettes. + Layer tactile paper textures in the selected color direction with an asymmetrical, airy composition. + """); + directions.put(MonthlyImageStylePreset.PAPER_CUT_LAYERS, """ + Dimensional paper-cut illustration built from softly layered shapes and carefully controlled shadows. + Use depth, openings, and overlapping planes to express the emotional progression without depicting a literal scene. + """); + directions.put(MonthlyImageStylePreset.GLASS_AND_LIGHT, """ + Abstract translucent glass forms with gentle refraction, luminous gradients, and soft reflected light. + Keep the materials elegant and weightless, with subtle depth and no sharp or hazardous appearance. + """); + directions.put(MonthlyImageStylePreset.MINIMAL_GEOMETRY, """ + Minimal geometric editorial composition using circles, arcs, planes, and balanced spatial relationships. + Use the selected color direction with precise rhythm and soft dimensional lighting rather than flat iconography. + """); + directions.put(MonthlyImageStylePreset.INK_WASH, """ + Contemporary abstract ink-wash artwork with diluted pigment, quiet brush diffusion, and generous open space. + Keep the mood light and comforting, varying pigment intensity within the selected colors without calligraphy or written marks. + """); + directions.put(MonthlyImageStylePreset.DREAMLIKE_LANDSCAPE, """ + Dreamlike abstract landscape made of gentle horizons, atmospheric color fields, mist, and ambient light. + Suggest an inner emotional journey without recognizable locations, people, buildings, or dramatic weather. + """); + directions.put(MonthlyImageStylePreset.TEXTILE_PATTERN, """ + Artisanal textile-inspired abstraction using woven rhythm, soft fibers, stitched-like paths, and layered fabric forms. + Keep it sophisticated and editorial, avoiding literal lettering, symbols, decorative text, or busy repetition. + """); + directions.put(MonthlyImageStylePreset.CERAMIC_OBJECTS, """ + Sculptural ceramic still life using abstract vessels, rounded forms, matte glaze, and controlled studio light. + Arrange the objects as an emotional metaphor with an uncluttered composition and no human or household narrative. + """); + return Map.copyOf(directions); + } + + private static Map colorDirections() { + EnumMap directions = + new EnumMap<>(MonthlyImageColorPalette.class); + directions.put(MonthlyImageColorPalette.FOREST_MIST, """ + Forest mist palette: sage green and deep teal as dominant hues, moss green accents, and foggy cream highlights. + Keep the temperature cool and botanical, avoiding pink or purple casts. + """); + directions.put(MonthlyImageColorPalette.OCEAN_LIGHT, """ + Ocean light palette: cobalt blue and clear cyan as dominant hues, turquoise transitions, and crisp silver-white highlights. + Keep the result fresh and luminous, avoiding beige or dusty pink casts. + """); + directions.put(MonthlyImageColorPalette.SUNSET_CLAY, """ + Sunset clay palette: terracotta and burnt orange as dominant hues, apricot midtones, and restrained burgundy accents. + Keep the colors earthy and sunlit rather than pink, lavender, or candy-like. + """); + directions.put(MonthlyImageColorPalette.MOON_VIOLET, """ + Moon violet palette: indigo and violet as dominant hues, periwinkle transitions, and cool pearl highlights. + Keep sufficient luminosity for a comforting mood while preserving a distinctly nocturnal violet identity. + """); + directions.put(MonthlyImageColorPalette.CITRUS_BREEZE, """ + Citrus breeze palette: lemon yellow and fresh mint as dominant hues, lime-tinted transitions, and coral accents. + Keep the colors clear and energetic with a light neutral background, avoiding lavender or muted beige dominance. + """); + directions.put(MonthlyImageColorPalette.EARTH_NEUTRAL, """ + Earth neutral palette: ivory and stone gray as the foundation, taupe and soft charcoal as dominant forms, and subtle bronze accents. + Keep saturation intentionally low and avoid pink, purple, or blue color casts. + """); + directions.put(MonthlyImageColorPalette.JEWEL_GLOW, """ + Jewel glow palette: emerald and sapphire as dominant hues, amethyst accents, and bright crystal-like highlights. + Use rich but balanced saturation against a clean light ground, avoiding a generic pastel treatment. + """); + directions.put(MonthlyImageColorPalette.ROSE_DAWN, """ + Rose dawn palette: rose and peach as dominant hues, soft coral transitions, and pale sky-blue highlights. + Keep the combination airy and sunrise-like while maintaining clear contrast between warm and cool colors. + """); + return Map.copyOf(directions); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssembler.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssembler.java new file mode 100644 index 00000000..dfc9ac87 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssembler.java @@ -0,0 +1,105 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.EmotionCode; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyReportV2ContentFactory; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportComparisonInputDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2Content; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeContentFactory; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeTextContent; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public final class MonthlyReportComparisonInputAssembler { + + private MonthlyReportComparisonInputAssembler() { + } + + public static MonthlyReportComparisonInputDto assemble( + MonthlyReportV2 previousReport, + TypeEmotionStatsContent currentEmotionStats + ) { + MonthlyReportV2Content previousContent = previousReport.getContent() == null + ? MonthlyReportV2ContentFactory.empty() + : previousReport.getContent().normalized(); + TypeTextContent previousEmotionSummaryContent = previousReport.getEmotionSummaryContent() == null + ? TypeContentFactory.emptyText() + : previousReport.getEmotionSummaryContent().normalized(); + TypeEmotionStatsContent previousEmotionStats = previousReport.getEmotionStats() == null + ? TypeContentFactory.emptyEmotionStats() + : previousReport.getEmotionStats().normalized(); + TypeEmotionStatsContent normalizedCurrentEmotionStats = currentEmotionStats == null + ? TypeContentFactory.emptyEmotionStats() + : currentEmotionStats.normalized(); + + int currentPositivePercent = normalizedCurrentEmotionStats.positivePercent(); + int previousPositivePercent = previousEmotionStats.positivePercent(); + + return new MonthlyReportComparisonInputDto( + previousReport.getId(), + previousReport.getMonthStartDate(), + previousReport.getMonthEndDate(), + previousContent, + previousEmotionSummaryContent, + previousEmotionStats, + currentPositivePercent, + previousPositivePercent, + currentPositivePercent - previousPositivePercent, + assembleEmotionChanges(normalizedCurrentEmotionStats, previousEmotionStats) + ); + } + + private static List assembleEmotionChanges( + TypeEmotionStatsContent currentEmotionStats, + TypeEmotionStatsContent previousEmotionStats + ) { + Map currentByCode = byEmotionCode(currentEmotionStats); + Map previousByCode = byEmotionCode(previousEmotionStats); + + return Arrays.stream(EmotionCode.values()) + .map(code -> toEmotionChange(code, currentByCode.get(code.name()), previousByCode.get(code.name()))) + .filter(change -> change.changePercentPoint() != 0) + .sorted((left, right) -> Integer.compare( + Math.abs(right.changePercentPoint()), + Math.abs(left.changePercentPoint()) + )) + .limit(3) + .toList(); + } + + private static Map byEmotionCode( + TypeEmotionStatsContent emotionStats + ) { + return emotionStats.emotions().stream() + .filter(stat -> stat.emotionCode() != null) + .collect(Collectors.toMap( + TypeEmotionStatsContent.EmotionStat::emotionCode, + Function.identity(), + (first, ignored) -> first + )); + } + + private static MonthlyReportComparisonInputDto.EmotionChange toEmotionChange( + EmotionCode code, + TypeEmotionStatsContent.EmotionStat current, + TypeEmotionStatsContent.EmotionStat previous + ) { + int currentPercent = current == null ? 0 : current.percent(); + int previousPercent = previous == null ? 0 : previous.percent(); + String emotionName = current != null ? current.emotionName() + : previous == null ? null : previous.emotionName(); + + return new MonthlyReportComparisonInputDto.EmotionChange( + code.name(), + emotionName, + currentPercent, + previousPercent, + currentPercent - previousPercent + ); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculator.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculator.java new file mode 100644 index 00000000..5a52a7d7 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculator.java @@ -0,0 +1,104 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialRankingItem; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto; + +import java.text.Collator; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; + +public final class MonthlySocialSummaryCalculator { + + private static final long MIN_INTERACTION_COUNT = 10; + private static final int MAX_RANKING_SIZE = 3; + + private MonthlySocialSummaryCalculator() { + } + + public static MonthlySocialSummaryContent calculate( + int month, + List likeCounts, + List commentCounts + ) { + List normalizedLikes = normalize(likeCounts); + List normalizedComments = normalize(commentCounts); + + boolean visible = !normalizedLikes.isEmpty() + && !normalizedComments.isEmpty() + && totalCount(normalizedLikes) + totalCount(normalizedComments) >= MIN_INTERACTION_COUNT; + if (!visible) { + return MonthlySocialSummaryContent.empty(month); + } + + return new MonthlySocialSummaryContent( + true, + month, + toRanking(normalizedLikes), + toRanking(normalizedComments) + ).normalized(); + } + + private static List normalize( + List counts + ) { + if (counts == null || counts.isEmpty()) { + return List.of(); + } + + return counts.stream() + .filter(item -> item != null && item.userId() != null && item.interactionCount() > 0) + .toList(); + } + + private static long totalCount(List counts) { + return counts.stream() + .mapToLong(MonthlySocialInteractionCountDto::interactionCount) + .sum(); + } + + private static List toRanking( + List counts + ) { + Collator koreanCollator = Collator.getInstance(Locale.KOREAN); + Comparator comparator = Comparator + .comparingLong(MonthlySocialInteractionCountDto::interactionCount) + .reversed() + .thenComparing( + item -> normalizeNickname(item.nickname()), + koreanCollator + ) + .thenComparing(item -> normalizeNickname(item.nickname())) + .thenComparing(MonthlySocialInteractionCountDto::userId); + + List sorted = counts.stream() + .sorted(comparator) + .limit(MAX_RANKING_SIZE) + .toList(); + long topCount = sorted.getFirst().interactionCount(); + + return java.util.stream.IntStream.range(0, sorted.size()) + .mapToObj(index -> toRankingItem(sorted.get(index), index + 1, topCount)) + .toList(); + } + + private static MonthlySocialRankingItem toRankingItem( + MonthlySocialInteractionCountDto item, + int displayOrder, + long topCount + ) { + return new MonthlySocialRankingItem( + displayOrder, + item.userId(), + normalizeNickname(item.nickname()), + item.profileImageKey(), + item.defaultProfileType(), + item.interactionCount() == topCount + ); + } + + private static String normalizeNickname(String nickname) { + return nickname == null ? "" : nickname.trim(); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java index df0f33ad..4cd0af15 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java @@ -1,15 +1,24 @@ package com.devkor.ifive.nadab.domain.monthlyreport.application.listener; import com.devkor.ifive.nadab.domain.dailyreport.core.entity.DailyReportStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.application.MonthlyImagePresetAssignmentService; import com.devkor.ifive.nadab.domain.monthlyreport.application.MonthlyReportTxServiceV2; import com.devkor.ifive.nadab.domain.monthlyreport.application.event.MonthlyReportCompletedEvent; import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlyInterestStatsCalculator; +import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlyReportComparisonInputAssembler; import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlyRepresentativePicker; import com.devkor.ifive.nadab.domain.monthlyreport.core.content.InterestStatsContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyEmotionComparisonContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.AiMonthlyReportResultDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImagePromptContext; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImageVisualPreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportComparisonInputDto; import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportGenerationRequestedEventDtoV2; import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyQueryRepository; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; import com.devkor.ifive.nadab.domain.monthlyreport.core.service.MonthlyWeeklySummariesService; +import com.devkor.ifive.nadab.domain.monthlyreport.core.service.MonthlySocialSummaryService; import com.devkor.ifive.nadab.domain.monthlyreport.infra.MonthlyReportImageStorage; import com.devkor.ifive.nadab.domain.monthlyreport.infra.MonthlyReportLlmClientV2; import com.devkor.ifive.nadab.domain.monthlyreport.infra.OpenAiImageClient; @@ -41,13 +50,16 @@ public class MonthlyReportGenerationListenerV2 { private static final String MONTHLY_REPORT_V2_LLM_MODEL = "GEMINI_2_5_FLASH"; private final MonthlyQueryRepository monthlyQueryRepository; + private final MonthlyReportV2Repository monthlyReportV2Repository; private final MonthlyReportLlmClientV2 monthlyReportLlmClientV2; private final OpenAiImageClient openAiImageClient; private final MonthlyReportImageStorage monthlyReportImageStorage; private final MonthlyReportTxServiceV2 monthlyReportTxServiceV2; + private final MonthlyImagePresetAssignmentService monthlyImagePresetAssignmentService; private final MonthlyWeeklySummariesService monthlyWeeklySummariesService; + private final MonthlySocialSummaryService monthlySocialSummaryService; private final ReportGenerationLogRecorder reportGenerationLogRecorder; private final ApplicationEventPublisher eventPublisher; @@ -108,6 +120,43 @@ public void handle(MonthlyReportGenerationRequestedEventDtoV2 event) { return; } + MonthlySocialSummaryContent socialSummary; + try { + socialSummary = monthlySocialSummaryService.buildSocialSummary(event.userId(), range); + } catch (Exception e) { + log.error("[MONTHLY_REPORT][SOCIAL_SUMMARY_FAILED] userId={}, reportId={}", + event.userId(), event.reportId(), e); + monthlyReportTxServiceV2.failAndRefundMonthly( + event.userId(), + event.reportId(), + event.crystalLogId() + ); + return; + } + + MonthlyReportComparisonInputDto comparisonInput = null; + if (event.previousReportId() != null) { + try { + comparisonInput = monthlyReportV2Repository.findById(event.previousReportId()) + .filter(previousReport -> previousReport.getUser() != null + && event.userId().equals(previousReport.getUser().getId())) + .map(previousReport -> MonthlyReportComparisonInputAssembler.assemble( + previousReport, + emotionStats + )) + .orElseThrow(); + } catch (Exception e) { + log.error("[MONTHLY_REPORT][COMPARISON_INPUT_FAILED] userId={}, reportId={}, previousReportId={}", + event.userId(), event.reportId(), event.previousReportId(), e); + monthlyReportTxServiceV2.failAndRefundMonthly( + event.userId(), + event.reportId(), + event.crystalLogId() + ); + return; + } + } + AiMonthlyReportResultDto dto; Long generationLogId = reportGenerationLogRecorder.start( event.userId(), @@ -125,7 +174,7 @@ public void handle(MonthlyReportGenerationRequestedEventDtoV2 event) { weeklySummaries, representativeEntries, emotionStats, - event.exists() + comparisonInput ); reportGenerationLogRecorder.succeed(generationLogId); } catch (Exception e) { @@ -156,7 +205,9 @@ public void handle(MonthlyReportGenerationRequestedEventDtoV2 event) { dto.content(), dto.emotionSummaryContent(), emotionStats, - interestStats + interestStats, + MonthlyEmotionComparisonContent.from(comparisonInput), + socialSummary ); reportGenerationLogRecorder.succeed(textConfirmLogId); @@ -184,7 +235,19 @@ public void handle(MonthlyReportGenerationRequestedEventDtoV2 event) { null ); try { - String base64Image = openAiImageClient.generateBase64Image(event.userId(), dto, range); + MonthlyImageVisualPreset imageVisualPreset = monthlyImagePresetAssignmentService.getOrAssignVisualPreset( + event.userId(), + event.reportId() + ); + MonthlyImagePromptContext imagePromptContext = MonthlyImagePromptContext.from( + dto, + range, + imageVisualPreset + ); + String base64Image = openAiImageClient.generateBase64Image( + event.userId(), + imagePromptContext + ); imageKey = monthlyReportImageStorage.uploadBase64Webp( event.userId(), event.reportId(), diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContent.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContent.java new file mode 100644 index 00000000..70158811 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContent.java @@ -0,0 +1,45 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.content; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportComparisonInputDto; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeContentFactory; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; + +public record MonthlyEmotionComparisonContent( + Long previousReportId, + Integer previousMonth, + TypeEmotionStatsContent previousEmotionStats, + Integer positivePercentPointChange +) { + public static MonthlyEmotionComparisonContent from(MonthlyReportComparisonInputDto input) { + if (input == null) { + return null; + } + + Integer previousMonth = input.previousMonthStartDate() == null + ? null + : input.previousMonthStartDate().getMonthValue(); + + return new MonthlyEmotionComparisonContent( + input.previousReportId(), + previousMonth, + input.previousEmotionStats(), + input.positivePercentPointChange() + ).normalized(); + } + + public MonthlyEmotionComparisonContent normalized() { + TypeEmotionStatsContent normalizedPreviousEmotionStats = previousEmotionStats == null + ? TypeContentFactory.emptyEmotionStats() + : previousEmotionStats.normalized(); + int normalizedPositivePercentPointChange = positivePercentPointChange == null + ? 0 + : Math.max(-100, Math.min(100, positivePercentPointChange)); + + return new MonthlyEmotionComparisonContent( + previousReportId, + previousMonth, + normalizedPreviousEmotionStats, + normalizedPositivePercentPointChange + ); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialRankingItem.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialRankingItem.java new file mode 100644 index 00000000..83fefa0e --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialRankingItem.java @@ -0,0 +1,23 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.content; + +import com.devkor.ifive.nadab.domain.user.core.entity.DefaultProfileType; + +public record MonthlySocialRankingItem( + int displayOrder, + Long userId, + String nickname, + String profileImageKey, + DefaultProfileType defaultProfileType, + boolean topRank +) { + public MonthlySocialRankingItem normalized() { + return new MonthlySocialRankingItem( + Math.max(1, displayOrder), + userId, + nickname == null ? "" : nickname.trim(), + profileImageKey, + defaultProfileType, + topRank + ); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContent.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContent.java new file mode 100644 index 00000000..a732e55f --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContent.java @@ -0,0 +1,42 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.content; + +import java.util.List; + +public record MonthlySocialSummaryContent( + boolean visible, + int month, + List likeRanking, + List commentRanking +) { + private static final int MAX_RANKING_SIZE = 3; + + public static MonthlySocialSummaryContent empty(int month) { + return new MonthlySocialSummaryContent( + false, + month, + List.of(), + List.of() + ); + } + + public MonthlySocialSummaryContent normalized() { + return new MonthlySocialSummaryContent( + visible, + Math.max(1, Math.min(12, month)), + normalizeRanking(likeRanking), + normalizeRanking(commentRanking) + ); + } + + private static List normalizeRanking(List ranking) { + if (ranking == null || ranking.isEmpty()) { + return List.of(); + } + + return ranking.stream() + .filter(item -> item != null) + .limit(MAX_RANKING_SIZE) + .map(MonthlySocialRankingItem::normalized) + .toList(); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImagePromptContext.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImagePromptContext.java new file mode 100644 index 00000000..82cbe0d5 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImagePromptContext.java @@ -0,0 +1,55 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.dto; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2Content; +import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; + +import java.time.LocalDate; +import java.util.Objects; + +public record MonthlyImagePromptContext( + String summary, + String commentSummary, + String dominantKeyword, + LocalDate monthStartDate, + LocalDate monthEndDate, + MonthlyImageStylePreset stylePreset, + MonthlyImageColorPalette colorPalette +) { + + public MonthlyImagePromptContext { + summary = normalize(summary); + commentSummary = normalize(commentSummary); + dominantKeyword = normalize(dominantKeyword); + Objects.requireNonNull(monthStartDate, "monthStartDate must not be null"); + Objects.requireNonNull(monthEndDate, "monthEndDate must not be null"); + Objects.requireNonNull(stylePreset, "stylePreset must not be null"); + Objects.requireNonNull(colorPalette, "colorPalette must not be null"); + } + + public static MonthlyImagePromptContext from( + AiMonthlyReportResultDto result, + MonthRangeDto range, + MonthlyImageVisualPreset visualPreset + ) { + Objects.requireNonNull(result, "result must not be null"); + MonthlyReportV2Content content = Objects.requireNonNull(result.content(), "content must not be null"); + Objects.requireNonNull(range, "range must not be null"); + Objects.requireNonNull(visualPreset, "visualPreset must not be null"); + + return new MonthlyImagePromptContext( + content.summary(), + content.commentSummary(), + content.dominantKeyword(), + range.monthStartDate(), + range.monthEndDate(), + visualPreset.stylePreset(), + visualPreset.colorPalette() + ); + } + + private static String normalize(String value) { + return value == null || value.isBlank() ? "Not provided" : value.trim(); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImageVisualPreset.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImageVisualPreset.java new file mode 100644 index 00000000..1ca71b42 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyImageVisualPreset.java @@ -0,0 +1,16 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.dto; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; + +import java.util.Objects; + +public record MonthlyImageVisualPreset( + MonthlyImageStylePreset stylePreset, + MonthlyImageColorPalette colorPalette +) { + public MonthlyImageVisualPreset { + Objects.requireNonNull(stylePreset, "stylePreset must not be null"); + Objects.requireNonNull(colorPalette, "colorPalette must not be null"); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportComparisonInputDto.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportComparisonInputDto.java new file mode 100644 index 00000000..5d68b484 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportComparisonInputDto.java @@ -0,0 +1,30 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.dto; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2Content; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeTextContent; + +import java.time.LocalDate; +import java.util.List; + +public record MonthlyReportComparisonInputDto( + Long previousReportId, + LocalDate previousMonthStartDate, + LocalDate previousMonthEndDate, + MonthlyReportV2Content previousContent, + TypeTextContent previousEmotionSummaryContent, + TypeEmotionStatsContent previousEmotionStats, + int currentPositivePercent, + int previousPositivePercent, + int positivePercentPointChange, + List emotionChanges +) { + public record EmotionChange( + String emotionCode, + String emotionName, + int currentPercent, + int previousPercent, + int changePercentPoint + ) { + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportGenerationRequestedEventDtoV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportGenerationRequestedEventDtoV2.java index a93f3358..41e702e8 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportGenerationRequestedEventDtoV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlyReportGenerationRequestedEventDtoV2.java @@ -4,6 +4,6 @@ public record MonthlyReportGenerationRequestedEventDtoV2( Long reportId, Long userId, Long crystalLogId, - boolean exists + Long previousReportId ) { } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlySocialInteractionCountDto.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlySocialInteractionCountDto.java new file mode 100644 index 00000000..64e69342 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/dto/MonthlySocialInteractionCountDto.java @@ -0,0 +1,12 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.dto; + +import com.devkor.ifive.nadab.domain.user.core.entity.DefaultProfileType; + +public record MonthlySocialInteractionCountDto( + Long userId, + String nickname, + String profileImageKey, + DefaultProfileType defaultProfileType, + long interactionCount +) { +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageColorPalette.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageColorPalette.java new file mode 100644 index 00000000..d6e1c297 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageColorPalette.java @@ -0,0 +1,12 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.entity; + +public enum MonthlyImageColorPalette { + FOREST_MIST, + OCEAN_LIGHT, + SUNSET_CLAY, + MOON_VIOLET, + CITRUS_BREEZE, + EARTH_NEUTRAL, + JEWEL_GLOW, + ROSE_DAWN +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageStylePreset.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageStylePreset.java new file mode 100644 index 00000000..1cca0d8c --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyImageStylePreset.java @@ -0,0 +1,12 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.entity; + +public enum MonthlyImageStylePreset { + BOTANICAL_COLLAGE, + PAPER_CUT_LAYERS, + GLASS_AND_LIGHT, + MINIMAL_GEOMETRY, + INK_WASH, + DREAMLIKE_LANDSCAPE, + TEXTILE_PATTERN, + CERAMIC_OBJECTS +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyReportV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyReportV2.java index ae717af1..1cb31d47 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyReportV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/entity/MonthlyReportV2.java @@ -1,8 +1,10 @@ package com.devkor.ifive.nadab.domain.monthlyreport.core.entity; import com.devkor.ifive.nadab.domain.monthlyreport.core.content.InterestStatsContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyEmotionComparisonContent; import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyContentFactory; import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyReportV2ContentFactory; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; import com.devkor.ifive.nadab.domain.typereport.core.content.TypeContentFactory; import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; import com.devkor.ifive.nadab.domain.typereport.core.content.TypeTextContent; @@ -52,6 +54,14 @@ public class MonthlyReportV2 extends CreatableEntity { @Column(name = "image_key", length = 255) private String imageKey; + @Enumerated(EnumType.STRING) + @Column(name = "image_prompt_variant", length = 40) + private MonthlyImageStylePreset imagePromptVariant; + + @Enumerated(EnumType.STRING) + @Column(name = "image_color_palette", length = 40) + private MonthlyImageColorPalette imageColorPalette; + @Enumerated(EnumType.STRING) @Column(name = "image_status", nullable = false, length = 16) private MonthlyReportImageStatus imageStatus; @@ -72,6 +82,14 @@ public class MonthlyReportV2 extends CreatableEntity { @Column(name = "interest_stats", columnDefinition = "jsonb", nullable = false) private InterestStatsContent interestStats; + @Type(JsonType.class) + @Column(name = "emotion_comparison", columnDefinition = "jsonb") + private MonthlyEmotionComparisonContent emotionComparison; + + @Type(JsonType.class) + @Column(name = "social_summary", columnDefinition = "jsonb", nullable = false) + private MonthlySocialSummaryContent socialSummary; + @Column(name = "summary", nullable = false, length = 80) private String summary; @@ -114,6 +132,7 @@ public static MonthlyReportV2 create( mr.emotionSummaryContent = TypeContentFactory.emptyText().normalized(); mr.emotionStats = TypeContentFactory.emptyEmotionStats(); mr.interestStats = MonthlyContentFactory.emptyInterestStats(); + mr.socialSummary = MonthlySocialSummaryContent.empty(monthStartDate.getMonthValue()); mr.comparisonType = comparisonType; mr.date = date; @@ -128,4 +147,22 @@ public static MonthlyReportV2 createPending( return create(user, monthStartDate, monthEndDate, MonthlyReportV2ContentFactory.empty(), date, MonthlyReportStatus.PENDING, MonthlyReportImageStatus.PENDING, comparisonType); } + + public void updateSocialSummary(MonthlySocialSummaryContent socialSummary) { + this.socialSummary = socialSummary == null + ? MonthlySocialSummaryContent.empty(monthStartDate.getMonthValue()) + : socialSummary.normalized(); + } + + public void assignImagePromptVariant(MonthlyImageStylePreset imagePromptVariant) { + if (this.imagePromptVariant == null) { + this.imagePromptVariant = imagePromptVariant; + } + } + + public void assignImageColorPalette(MonthlyImageColorPalette imageColorPalette) { + if (this.imageColorPalette == null) { + this.imageColorPalette = imageColorPalette; + } + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlyReportV2Repository.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlyReportV2Repository.java index 9b7e6508..abfc86a5 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlyReportV2Repository.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlyReportV2Repository.java @@ -3,6 +3,9 @@ import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportImageStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -14,8 +17,6 @@ public interface MonthlyReportV2Repository extends JpaRepository { - boolean existsByUserIdAndStatus(Long userId, MonthlyReportStatus status); - Optional findByUserIdAndMonthStartDate(Long userId, LocalDate monthStartDate); Optional findByUserIdAndMonthStartDateAndStatus( @@ -24,8 +25,44 @@ Optional findByUserIdAndMonthStartDateAndStatus( MonthlyReportStatus status ); + Optional findFirstByUserIdAndStatusAndMonthStartDateBeforeOrderByMonthStartDateDesc( + Long userId, + MonthlyReportStatus status, + LocalDate monthStartDate + ); + List findAllByUserIdAndStatus(Long userId, MonthlyReportStatus status); + @Query(""" + select mr.imagePromptVariant + from MonthlyReportV2 mr + where mr.user.id = :userId + and mr.id <> :reportId + and mr.status = com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus.COMPLETED + and mr.imagePromptVariant is not null + order by mr.monthStartDate desc, mr.id desc + """) + List findRecentCompletedImagePromptVariants( + @Param("userId") Long userId, + @Param("reportId") Long reportId, + Pageable pageable + ); + + @Query(""" + select mr.imageColorPalette + from MonthlyReportV2 mr + where mr.user.id = :userId + and mr.id <> :reportId + and mr.status = com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus.COMPLETED + and mr.imageColorPalette is not null + order by mr.monthStartDate desc, mr.id desc + """) + List findRecentCompletedImageColorPalettes( + @Param("userId") Long userId, + @Param("reportId") Long reportId, + Pageable pageable + ); + /** * PENDING -> FAILED 확정 */ @@ -55,6 +92,8 @@ int updateStatus( emotion_summary_content = CAST(:emotionSummaryContentJson AS jsonb), emotion_stats = CAST(:emotionStatsJson AS jsonb), interest_stats = CAST(:interestStatsJson AS jsonb), + emotion_comparison = CAST(:emotionComparisonJson AS jsonb), + social_summary = CAST(:socialSummaryJson AS jsonb), summary = :summary, comment_summary = :commentSummary, dominant_keyword = :dominantKeyword, @@ -71,6 +110,8 @@ int updateContent( @Param("dominantKeyword") String dominantKeyword, @Param("emotionStatsJson") String emotionStatsJson, @Param("interestStatsJson") String interestStatsJson, + @Param("emotionComparisonJson") String emotionComparisonJson, + @Param("socialSummaryJson") String socialSummaryJson, @Param("status") String status ); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlySocialQueryRepository.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlySocialQueryRepository.java new file mode 100644 index 00000000..a8a23ffa --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/repository/MonthlySocialQueryRepository.java @@ -0,0 +1,84 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.repository; + +import com.devkor.ifive.nadab.domain.like.core.entity.DailyReportLike; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.query.Param; + +import java.time.OffsetDateTime; +import java.util.List; + +public interface MonthlySocialQueryRepository extends Repository { + + @Query(""" + select new com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto( + liker.id, + liker.nickname, + liker.profileImageKey, + liker.defaultProfileType, + count(l) + ) + from DailyReportLike l + join l.user liker + where l.dailyReport.answerEntry.user.id = :userId + and l.createdAt >= :startAt + and l.createdAt < :endAt + and liker.deletedAt is null + and exists ( + select 1 + from Friendship f + where f.status = com.devkor.ifive.nadab.domain.friend.core.entity.FriendshipStatus.ACCEPTED + and ((f.user1.id = :userId and f.user2.id = liker.id) + or (f.user2.id = :userId and f.user1.id = liker.id)) + ) + and not exists ( + select 1 + from UserBlock ub + where (ub.blocker.id = :userId and ub.blocked.id = liker.id) + or (ub.blocker.id = liker.id and ub.blocked.id = :userId) + ) + group by liker.id, liker.nickname, liker.profileImageKey, liker.defaultProfileType + """) + List countReceivedLikesByFriend( + @Param("userId") Long userId, + @Param("startAt") OffsetDateTime startAt, + @Param("endAt") OffsetDateTime endAt + ); + + @Query(""" + select new com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto( + author.id, + author.nickname, + author.profileImageKey, + author.defaultProfileType, + count(c) + ) + from Comment c + join c.author author + where c.dailyReport.answerEntry.user.id = :userId + and c.createdAt >= :startAt + and c.createdAt < :endAt + and c.deletedAt is null + and author.deletedAt is null + and exists ( + select 1 + from Friendship f + where f.status = com.devkor.ifive.nadab.domain.friend.core.entity.FriendshipStatus.ACCEPTED + and ((f.user1.id = :userId and f.user2.id = author.id) + or (f.user2.id = :userId and f.user1.id = author.id)) + ) + and not exists ( + select 1 + from UserBlock ub + where (ub.blocker.id = :userId and ub.blocked.id = author.id) + or (ub.blocker.id = author.id and ub.blocked.id = :userId) + ) + group by author.id, author.nickname, author.profileImageKey, author.defaultProfileType + """) + List countReceivedCommentsByFriend( + @Param("userId") Long userId, + @Param("startAt") OffsetDateTime startAt, + @Param("endAt") OffsetDateTime endAt + ); +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryService.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryService.java new file mode 100644 index 00000000..97282665 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryService.java @@ -0,0 +1,40 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.service; + +import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlySocialSummaryCalculator; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlySocialQueryRepository; +import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MonthlySocialSummaryService { + + private static final ZoneId SEOUL = ZoneId.of("Asia/Seoul"); + + private final MonthlySocialQueryRepository monthlySocialQueryRepository; + + public MonthlySocialSummaryContent buildSocialSummary(Long userId, MonthRangeDto range) { + OffsetDateTime startAt = range.monthStartDate().atStartOfDay(SEOUL).toOffsetDateTime(); + OffsetDateTime endAt = range.monthEndDate().plusDays(1).atStartOfDay(SEOUL).toOffsetDateTime(); + + List likeCounts = + monthlySocialQueryRepository.countReceivedLikesByFriend(userId, startAt, endAt); + List commentCounts = + monthlySocialQueryRepository.countReceivedCommentsByFriend(userId, startAt, endAt); + + return MonthlySocialSummaryCalculator.calculate( + range.monthStartDate().getMonthValue(), + likeCounts, + commentCounts + ); + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java index 9b5623ca..4210aeb8 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java @@ -1,6 +1,7 @@ package com.devkor.ifive.nadab.domain.monthlyreport.infra; import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.AiMonthlyReportResultDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportComparisonInputDto; import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2Content; import com.devkor.ifive.nadab.domain.typereport.application.helper.TypeReportInputAssembler; import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; @@ -13,6 +14,7 @@ import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; import com.devkor.ifive.nadab.global.shared.reportcontent.*; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.ai.anthropic.AnthropicChatOptions; @@ -24,6 +26,7 @@ import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.EnumSet; import java.util.List; @@ -41,25 +44,36 @@ public class MonthlyReportLlmClientV2 { private static final int MAX_DISCOVERED = 400; private static final int MIN_DISCOVERED = 150; + private static final int MAX_COMMENT = 400; + private static final int MIN_COMMENT = 150; + private static final int MAX_EMOTION = 200; private static final int MIN_EMOTION = 50; private static final int MIN_SUMMARY = 8; private static final int MAX_SUMMARY = 30; + private static final int MIN_COMPARISON_EMOTION_TREND = 5; + private static final int MAX_COMPARISON_EMOTION_TREND = 80; + private static final int MIN_COMPARISON_EMOTION = 40; + private static final int MAX_COMPARISON_EMOTION = 150; + private static final int MAX_COMPARISON_BOLD_SEGMENTS = 4; + public AiMonthlyReportResultDto generate( String monthStartDate, String monthEndDate, String weeklySummaries, String representativeEntries, TypeEmotionStatsContent emotionStats, - boolean exists) { - String prompt = monthlyReportPromptLoader.loadV2BaselinePrompt() - .replace("{monthStartDate}", monthStartDate) - .replace("{monthEndDate}", monthEndDate) - .replace("{weeklySummaries}", weeklySummaries) - .replace("{representativeEntries}", representativeEntries == null ? "" : representativeEntries) - .replace("{emotionStats}", TypeReportInputAssembler.assembleEmotionStats(emotionStats)); + MonthlyReportComparisonInputDto comparisonInput) { + String prompt = buildPrompt( + monthStartDate, + monthEndDate, + weeklySummaries, + representativeEntries, + emotionStats, + comparisonInput + ); ChatClient client = llmRouter.route(provider); @@ -83,15 +97,15 @@ public AiMonthlyReportResultDto generate( MonthlyReportV2Content monthlyReportContent = result.content(); - StyledText discoveredStyled = monthlyReportContent.discovered(); - StyledText commentStyled = monthlyReportContent.comment(); + StyledText discoveredStyled = normalizeStyledTextSegments(monthlyReportContent.discovered()); + StyledText commentStyled = normalizeStyledTextSegments(monthlyReportContent.comment()); String summary = monthlyReportContent.summary(); String commentSummary = monthlyReportContent.commentSummary(); String dominantKeyword = monthlyReportContent.dominantKeyword(); String emotionTrend = monthlyReportContent.emotionTrend(); TypeTextContent emotionStatsContent = result.emotionSummaryContent(); - StyledText styledText = emotionStatsContent.styledText(); + StyledText styledText = normalizeStyledTextSegments(emotionStatsContent.styledText()); if (discoveredStyled == null || commentStyled == null || styledText == null || isBlank(summary) || isBlank(commentSummary) || isBlank(dominantKeyword) || isBlank(emotionTrend)) { @@ -105,17 +119,33 @@ public AiMonthlyReportResultDto generate( validateStyledText(commentStyled, true); validateStyledText(styledText, false); - String discovered = monthlyReportContent.discovered().plainText(); - String comment = monthlyReportContent.comment().plainText(); - String emotion = emotionStatsContent.styledText().plainText(); + String discovered = discoveredStyled.plainText(); + String comment = commentStyled.plainText(); + String emotion = styledText.plainText(); if (isBlank(discovered) || isBlank(comment) || isBlank(emotion)) { throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_AI_JSON_MISSING_FIELDS); } - validateLength(discovered, comment, emotion); + validateLength(discovered, comment, emotion, comparisonInput != null); + + if (comparisonInput != null) { + validateComparisonEmotionTrend(emotionTrend); + validateComparisonEmotionSummary(styledText, dominantKeyword); + } - return result; + MonthlyReportV2Content normalizedContent = new MonthlyReportV2Content( + summary, + commentSummary, + dominantKeyword, + emotionTrend, + discoveredStyled, + commentStyled + ); + return new AiMonthlyReportResultDto( + normalizedContent, + new TypeTextContent(styledText) + ); } catch (AiResponseParseException e) { throw e; @@ -124,6 +154,40 @@ public AiMonthlyReportResultDto generate( } } + String buildPrompt( + String monthStartDate, + String monthEndDate, + String weeklySummaries, + String representativeEntries, + TypeEmotionStatsContent emotionStats, + MonthlyReportComparisonInputDto comparisonInput + ) { + String template = comparisonInput == null + ? monthlyReportPromptLoader.loadV2BaselinePrompt() + : monthlyReportPromptLoader.loadV2ComparisonPrompt(); + + String prompt = template + .replace("{monthStartDate}", monthStartDate) + .replace("{monthEndDate}", monthEndDate) + .replace("{weeklySummaries}", weeklySummaries) + .replace("{representativeEntries}", representativeEntries == null ? "" : representativeEntries) + .replace("{emotionStats}", TypeReportInputAssembler.assembleEmotionStats(emotionStats)); + + if (comparisonInput != null) { + prompt = prompt.replace("{comparisonInput}", serializeComparisonInput(comparisonInput)); + } + + return prompt; + } + + private String serializeComparisonInput(MonthlyReportComparisonInputDto comparisonInput) { + try { + return objectMapper.writeValueAsString(comparisonInput); + } catch (JsonProcessingException e) { + throw new AiResponseParseException(ErrorCode.AI_RESPONSE_PARSE_FAILED); + } + } + private String callOpenAi(ChatClient client, String prompt) { OpenAiChatOptions options = OpenAiChatOptions.builder() .model(OpenAiApi.ChatModel.GPT_5_MINI) @@ -274,6 +338,46 @@ private boolean isBlank(String s) { return s == null || s.trim().isEmpty(); } + StyledText normalizeStyledTextSegments(StyledText styledText) { + if (styledText == null || styledText.segments() == null) { + return styledText; + } + + List normalized = new ArrayList<>(); + StringBuilder leadingWhitespace = new StringBuilder(); + + for (Segment segment : styledText.segments()) { + if (segment == null || segment.text() == null || segment.text().isEmpty()) { + continue; + } + + String text = segment.text(); + if (text.isBlank()) { + if (normalized.isEmpty()) { + leadingWhitespace.append(text); + } else { + int lastIndex = normalized.size() - 1; + Segment previous = normalized.get(lastIndex); + normalized.set(lastIndex, new Segment( + previous.text() + text, + previous.marks() + )); + } + continue; + } + + if (!leadingWhitespace.isEmpty()) { + text = leadingWhitespace + text; + leadingWhitespace.setLength(0); + } + + List marks = segment.marks() == null ? List.of() : segment.marks(); + normalized.add(new Segment(text, marks)); + } + + return new StyledText(List.copyOf(normalized)); + } + private void validateStyledText(StyledText st, boolean isDiscovered) { if (st.segments() == null || st.segments().isEmpty()) { throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_AI_JSON_MISSING_FIELDS); @@ -308,7 +412,7 @@ private void validateStyledText(StyledText st, boolean isDiscovered) { } } - private void validateLength(String discovered, String comment, String emotion) { + void validateLength(String discovered, String comment, String emotion, boolean comparison) { int dLen = discovered.length(); int cLen = comment.length(); int eLen = emotion.length(); @@ -316,14 +420,67 @@ private void validateLength(String discovered, String comment, String emotion) { if (dLen < MIN_DISCOVERED || dLen > MAX_DISCOVERED) { throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_DISCOVERED_LENGTH_INVALID); } - if (cLen < MIN_DISCOVERED || cLen > MAX_DISCOVERED) { - throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_DISCOVERED_LENGTH_INVALID); + if (cLen < MIN_COMMENT || cLen > MAX_COMMENT) { + throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_COMMENT_LENGTH_INVALID); } - if (eLen < MIN_EMOTION || eLen > MAX_EMOTION) { - throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_IMPROVE_LENGTH_INVALID); + int minEmotion = comparison ? MIN_COMPARISON_EMOTION : MIN_EMOTION; + int maxEmotion = comparison ? MAX_COMPARISON_EMOTION : MAX_EMOTION; + if (eLen < minEmotion || eLen > maxEmotion) { + throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_EMOTION_SUMMARY_LENGTH_INVALID); + } + } + + void validateComparisonEmotionTrend(String emotionTrend) { + String trend = emotionTrend.trim(); + if (trend.length() < MIN_COMPARISON_EMOTION_TREND + || trend.length() > MAX_COMPARISON_EMOTION_TREND + || trend.contains("\n") + || trend.contains("\r") + || containsDigit(trend)) { + throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_SUMMARY_INVALID); } } + void validateComparisonEmotionSummary(StyledText emotionSummary, String dominantKeyword) { + int boldSegments = 0; + + for (Segment segment : emotionSummary.segments()) { + List marks = segment.marks() == null ? List.of() : segment.marks(); + if (marks.contains(Mark.BOLD)) { + boldSegments++; + } + } + + if (boldSegments == 0 + || boldSegments > MAX_COMPARISON_BOLD_SEGMENTS + || countOccurrences(emotionSummary.plainText(), dominantKeyword) == 0) { + throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_AI_SEGMENT_INVALID); + } + } + + private boolean containsDigit(String value) { + for (int i = 0; i < value.length(); i++) { + if (Character.isDigit(value.charAt(i))) { + return true; + } + } + return false; + } + + private int countOccurrences(String value, String target) { + if (isBlank(value) || isBlank(target)) { + return 0; + } + + int count = 0; + int fromIndex = 0; + while ((fromIndex = value.indexOf(target, fromIndex)) >= 0) { + count++; + fromIndex += target.length(); + } + return count; + } + private void validateSummary(String summary) { if (summary == null) { throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_SUMMARY_INVALID); @@ -341,10 +498,8 @@ private void validateSummary(String summary) { throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_SUMMARY_INVALID); } // 숫자 금지(시간/빈도 방지) - for (int k = 0; k < s.length(); k++) { - if (Character.isDigit(s.charAt(k))) { - throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_SUMMARY_INVALID); - } + if (containsDigit(s)) { + throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_SUMMARY_INVALID); } } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClient.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClient.java index f17d7ed3..50057f4f 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClient.java @@ -1,15 +1,13 @@ package com.devkor.ifive.nadab.domain.monthlyreport.infra; -import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.AiMonthlyReportResultDto; +import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlyImagePromptComposer; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImagePromptContext; import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.OpenAiImageGenerateRequestDto; import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.OpenAiImageGenerateResponseDto; -import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2Content; -import com.devkor.ifive.nadab.global.core.prompt.monthly.MonthlyReportPromptLoader; import com.devkor.ifive.nadab.global.core.response.ErrorCode; import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; -import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -25,7 +23,7 @@ public class OpenAiImageClient { private final WebClient.Builder webClientBuilder; - private final MonthlyReportPromptLoader monthlyReportPromptLoader; + private final MonthlyImagePromptComposer monthlyImagePromptComposer; @Value("${openai.api-key}") private String apiKey; @@ -42,17 +40,11 @@ public class OpenAiImageClient { @Value("${openai.image.output-format}") private String outputFormat; - public String generateBase64Image(Long userId, AiMonthlyReportResultDto dto, MonthRangeDto range) { - MonthlyReportV2Content content = dto.content(); + public String generateBase64Image(Long userId, MonthlyImagePromptContext context) { + return generateBase64Image(userId, monthlyImagePromptComposer.compose(context)); + } - String prompt = monthlyReportPromptLoader.loadImagePrompt() - .formatted( - safe(content.summary()), - safe(content.commentSummary()), - safe(content.dominantKeyword()), - range.monthStartDate(), - range.monthEndDate() - ); + private String generateBase64Image(Long userId, String prompt) { OpenAiImageGenerateRequestDto request = new OpenAiImageGenerateRequestDto( model, @@ -110,10 +102,6 @@ public String generateBase64Image(Long userId, AiMonthlyReportResultDto dto, Mon } } - private String safe(String value) { - return value == null || value.isBlank() ? "Not provided" : value; - } - private String truncate(String value) { if (value == null) { return ""; diff --git a/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/LocalMonthlyReportPromptLoader.java b/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/LocalMonthlyReportPromptLoader.java index 12a48576..5b5abeb7 100644 --- a/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/LocalMonthlyReportPromptLoader.java +++ b/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/LocalMonthlyReportPromptLoader.java @@ -17,6 +17,7 @@ public class LocalMonthlyReportPromptLoader implements MonthlyReportPromptLoader private static final String V1_PROMPT_PATH = "secret/monthly-prompt-v1-local.txt"; private static final String V2_BASELINE_PROMPT_PATH = "secret/monthly-prompt-v2-baseline-local.txt"; + private static final String V2_COMPARISON_PROMPT_PATH = "secret/monthly-prompt-v2-comparison-local.txt"; @Override public String loadV1Prompt() { @@ -57,30 +58,22 @@ public String loadV2BaselinePrompt() { } @Override - public String loadImagePrompt() { - return """ - Create a premium abstract monthly self-reflection cover image for a Korean journaling app. - - Report context: - - Monthly summary: %s - - Gentle comment summary: %s - - Dominant keyword: %s - - Month: %s to %s - - Task: - Create a symbolic, abstract cover image that represents the emotional meaning of this monthly report. Do not use a fixed scene. Choose objects, colors, light, space, and composition that naturally match the report's theme. - - The image should feel calm, warm, reflective, comforting, refined, and suitable for a premium mobile app monthly report card. - - Style: - Premium editorial illustration, modern app-friendly aesthetic, soft lighting, subtle texture, refined color palette, clean composition, enough negative space. - - Strict constraints: - No people, no faces, no hands, no body parts. - No readable text, no letters, no Korean characters, no English characters, no numbers, no symbols, no handwriting, no typography. - No UI, no logos, no brand marks, no watermarks. - No medical, therapy, counseling, hospital, or diagnosis-related imagery. - No dark, horror, gloomy, childish, or overly dramatic mood. - """; + public String loadV2ComparisonPrompt() { + try { + ClassPathResource resource = new ClassPathResource(V2_COMPARISON_PROMPT_PATH); + + if (!resource.exists()) { + log.error("월간 리포트 프롬프트 파일이 존재하지 않습니다: {}", V2_COMPARISON_PROMPT_PATH); + throw new BadRequestException(ErrorCode.PROMPT_MONTHLY_FILE_NOT_FOUND); + } + + byte[] bytes = resource.getContentAsByteArray(); + return new String(bytes, StandardCharsets.UTF_8); + + } catch (IOException e) { + log.error("로컬 월간 리포트 프롬프트 파일 읽기 실패: {}", V2_COMPARISON_PROMPT_PATH, e); + throw new BadRequestException(ErrorCode.PROMPT_MONTHLY_FILE_READ_FAILED); + } } + } diff --git a/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/MonthlyReportPromptLoader.java b/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/MonthlyReportPromptLoader.java index 68898a41..f2050b4b 100644 --- a/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/MonthlyReportPromptLoader.java +++ b/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/MonthlyReportPromptLoader.java @@ -5,5 +5,5 @@ public interface MonthlyReportPromptLoader { String loadV2BaselinePrompt(); - String loadImagePrompt(); + String loadV2ComparisonPrompt(); } diff --git a/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/SecretMonthlyReportPromptLoader.java b/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/SecretMonthlyReportPromptLoader.java index 728368a2..e1ee5575 100644 --- a/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/SecretMonthlyReportPromptLoader.java +++ b/src/main/java/com/devkor/ifive/nadab/global/core/prompt/monthly/SecretMonthlyReportPromptLoader.java @@ -20,6 +20,9 @@ public class SecretMonthlyReportPromptLoader implements MonthlyReportPromptLoade @Value("${MONTHLY_V2_BASELINE_PROMPT}") private String monthlyV2BaselinePrompt; + @Value("${MONTHLY_V2_COMPARISON_PROMPT}") + private String monthlyV2ComparisonPrompt; + @Override public String loadV1Prompt() { if (monthlyV1Prompt == null || monthlyV1Prompt.isBlank()) { @@ -41,30 +44,13 @@ public String loadV2BaselinePrompt() { } @Override - public String loadImagePrompt() { - return """ - Create a premium abstract monthly self-reflection cover image for a Korean journaling app. - - Report context: - - Monthly summary: %s - - Gentle comment summary: %s - - Dominant keyword: %s - - Month: %s to %s - - Task: - Create a symbolic, abstract cover image that represents the emotional meaning of this monthly report. Do not use a fixed scene. Choose objects, colors, light, space, and composition that naturally match the report's theme. - - The image should feel calm, warm, reflective, comforting, refined, and suitable for a premium mobile app monthly report card. - - Style: - Premium editorial illustration, modern app-friendly aesthetic, soft lighting, subtle texture, refined color palette, clean composition, enough negative space. - - Strict constraints: - No people, no faces, no hands, no body parts. - No readable text, no letters, no Korean characters, no English characters, no numbers, no symbols, no handwriting, no typography. - No UI, no logos, no brand marks, no watermarks. - No medical, therapy, counseling, hospital, or diagnosis-related imagery. - No dark, horror, gloomy, childish, or overly dramatic mood. - """; + public String loadV2ComparisonPrompt() { + if (monthlyV2ComparisonPrompt == null || monthlyV2ComparisonPrompt.isBlank()) { + log.error("환경 변수 MONTHLY_V2_COMPARISON_PROMPT가 비어있습니다."); + throw new BadRequestException(ErrorCode.PROMPT_MONTHLY_ENV_VAR_NOT_SET); + } + + return monthlyV2ComparisonPrompt; } + } diff --git a/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java b/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java index 398ee556..23bb52ea 100644 --- a/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java +++ b/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java @@ -189,6 +189,8 @@ public enum ErrorCode { MONTHLY_REPORT_DISCOVERED_LENGTH_INVALID(HttpStatus.BAD_GATEWAY, "월간 리포트 discovered 길이가 제한을 만족하지 않습니다"), MONTHLY_REPORT_IMPROVE_LENGTH_INVALID(HttpStatus.BAD_GATEWAY, "월간 리포트 improve 길이가 제한을 만족하지 않습니다"), + MONTHLY_REPORT_COMMENT_LENGTH_INVALID(HttpStatus.BAD_GATEWAY, "월간 리포트 comment 길이가 제한을 만족하지 않습니다"), + MONTHLY_REPORT_EMOTION_SUMMARY_LENGTH_INVALID(HttpStatus.BAD_GATEWAY, "월간 리포트 emotionSummaryContent 길이가 제한을 만족하지 않습니다"), MONTHLY_REPORT_TOTAL_LENGTH_INVALID(HttpStatus.BAD_GATEWAY, "월간 리포트 총 길이가 제한을 만족하지 않습니다"), MONTHLY_REPORT_REWRITE_JSON_MAPPING_FAILED(HttpStatus.BAD_GATEWAY, "월간 리포트 리라이트 응답 JSON을 매핑할 수 없습니다"), diff --git a/src/main/resources/db/migration/V20260618_1200__IS_add_emotion_comparison_to_monthly_reports_v2.sql b/src/main/resources/db/migration/V20260618_1200__IS_add_emotion_comparison_to_monthly_reports_v2.sql new file mode 100644 index 00000000..e880562b --- /dev/null +++ b/src/main/resources/db/migration/V20260618_1200__IS_add_emotion_comparison_to_monthly_reports_v2.sql @@ -0,0 +1,2 @@ +ALTER TABLE monthly_reports_v2 + ADD COLUMN emotion_comparison JSONB; diff --git a/src/main/resources/db/migration/V20260628_1200__IS_add_social_summary_to_monthly_reports_v2.sql b/src/main/resources/db/migration/V20260628_1200__IS_add_social_summary_to_monthly_reports_v2.sql new file mode 100644 index 00000000..a98bdba2 --- /dev/null +++ b/src/main/resources/db/migration/V20260628_1200__IS_add_social_summary_to_monthly_reports_v2.sql @@ -0,0 +1,17 @@ +ALTER TABLE monthly_reports_v2 + ADD COLUMN social_summary JSONB NOT NULL DEFAULT '{ + "visible": false, + "month": 1, + "likeRanking": [], + "commentRanking": [] + }'::jsonb; + +UPDATE monthly_reports_v2 +SET social_summary = jsonb_set( + social_summary, + '{month}', + to_jsonb(EXTRACT(MONTH FROM month_start_date)::int) + ); + +ALTER TABLE monthly_reports_v2 + ALTER COLUMN social_summary DROP DEFAULT; diff --git a/src/main/resources/db/migration/V20260629_1200__IS_add_image_prompt_variant_to_monthly_reports_v2.sql b/src/main/resources/db/migration/V20260629_1200__IS_add_image_prompt_variant_to_monthly_reports_v2.sql new file mode 100644 index 00000000..b63e7fc6 --- /dev/null +++ b/src/main/resources/db/migration/V20260629_1200__IS_add_image_prompt_variant_to_monthly_reports_v2.sql @@ -0,0 +1,2 @@ +ALTER TABLE monthly_reports_v2 + ADD COLUMN image_prompt_variant VARCHAR(40); diff --git a/src/main/resources/db/migration/V20260629_1700__IS_add_image_color_palette_to_monthly_reports_v2.sql b/src/main/resources/db/migration/V20260629_1700__IS_add_image_color_palette_to_monthly_reports_v2.sql new file mode 100644 index 00000000..ad0923c3 --- /dev/null +++ b/src/main/resources/db/migration/V20260629_1700__IS_add_image_color_palette_to_monthly_reports_v2.sql @@ -0,0 +1,2 @@ +ALTER TABLE monthly_reports_v2 + ADD COLUMN image_color_palette VARCHAR(40); diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlyReportV2RepositoryTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlyReportV2RepositoryTest.java new file mode 100644 index 00000000..a30746e9 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlyReportV2RepositoryTest.java @@ -0,0 +1,235 @@ +package com.devkor.ifive.nadab.domain.monthlyreport; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialRankingItem; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyReportV2ContentFactory; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportComparisonType; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportImageStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.infra.builder.UserBuilder; +import com.devkor.ifive.nadab.infra.db.PostgresIntegrationTestSupport; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.context.ActiveProfiles; + +import java.time.LocalDate; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@ActiveProfiles("test") +class MonthlyReportV2RepositoryTest extends PostgresIntegrationTestSupport { + + @Autowired + MonthlyReportV2Repository monthlyReportV2Repository; + + @Autowired + TestEntityManager em; + + @Test + void create_pending_initializes_empty_social_summary_for_report_month() { + User user = new UserBuilder(em).build(); + MonthlyReportV2 report = monthlyReportV2Repository.save(MonthlyReportV2.createPending( + user, + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + LocalDate.of(2026, 6, 1), + MonthlyReportComparisonType.BASELINE + )); + em.flush(); + em.clear(); + + MonthlyReportV2 reloaded = monthlyReportV2Repository.findById(report.getId()).orElseThrow(); + + assertThat(reloaded.getSocialSummary().visible()).isFalse(); + assertThat(reloaded.getSocialSummary().month()).isEqualTo(5); + assertThat(reloaded.getSocialSummary().likeRanking()).isEmpty(); + assertThat(reloaded.getSocialSummary().commentRanking()).isEmpty(); + } + + @Test + void update_social_summary_saves_display_order_and_joint_top_rank() { + User user = new UserBuilder(em).build(); + MonthlyReportV2 report = monthlyReportV2Repository.save(MonthlyReportV2.createPending( + user, + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + LocalDate.of(2026, 6, 1), + MonthlyReportComparisonType.BASELINE + )); + report.updateSocialSummary(new MonthlySocialSummaryContent( + true, + 5, + List.of( + new MonthlySocialRankingItem(1, 10L, "가", null, null, true), + new MonthlySocialRankingItem(2, 11L, "나", null, null, true) + ), + List.of(new MonthlySocialRankingItem(1, 12L, "다", null, null, true)) + )); + em.flush(); + em.clear(); + + MonthlyReportV2 reloaded = monthlyReportV2Repository.findById(report.getId()).orElseThrow(); + + assertThat(reloaded.getSocialSummary().visible()).isTrue(); + assertThat(reloaded.getSocialSummary().likeRanking()) + .extracting(MonthlySocialRankingItem::displayOrder) + .containsExactly(1, 2); + assertThat(reloaded.getSocialSummary().likeRanking()) + .allMatch(MonthlySocialRankingItem::topRank); + } + + @Test + void saves_visual_preset_and_finds_three_most_recent_completed_values() { + User user = new UserBuilder(em).build(); + completedReport(user, LocalDate.of(2026, 2, 1), MonthlyImageStylePreset.INK_WASH, + MonthlyImageColorPalette.FOREST_MIST); + completedReport(user, LocalDate.of(2026, 3, 1), MonthlyImageStylePreset.GLASS_AND_LIGHT, + MonthlyImageColorPalette.OCEAN_LIGHT); + completedReport(user, LocalDate.of(2026, 4, 1), MonthlyImageStylePreset.PAPER_CUT_LAYERS, + MonthlyImageColorPalette.SUNSET_CLAY); + MonthlyReportV2 may = completedReport(user, LocalDate.of(2026, 5, 1), + MonthlyImageStylePreset.BOTANICAL_COLLAGE, MonthlyImageColorPalette.MOON_VIOLET); + MonthlyReportV2 current = monthlyReportV2Repository.save(MonthlyReportV2.createPending( + user, + LocalDate.of(2026, 6, 1), + LocalDate.of(2026, 6, 30), + LocalDate.of(2026, 7, 1), + MonthlyReportComparisonType.COMPARISON + )); + em.flush(); + em.clear(); + + List recent = monthlyReportV2Repository.findRecentCompletedImagePromptVariants( + user.getId(), + current.getId(), + PageRequest.of(0, 3) + ); + List recentPalettes = + monthlyReportV2Repository.findRecentCompletedImageColorPalettes( + user.getId(), + current.getId(), + PageRequest.of(0, 3) + ); + MonthlyReportV2 reloadedMay = monthlyReportV2Repository.findById(may.getId()).orElseThrow(); + + assertThat(recent).containsExactly( + MonthlyImageStylePreset.BOTANICAL_COLLAGE, + MonthlyImageStylePreset.PAPER_CUT_LAYERS, + MonthlyImageStylePreset.GLASS_AND_LIGHT + ); + assertThat(recentPalettes).containsExactly( + MonthlyImageColorPalette.MOON_VIOLET, + MonthlyImageColorPalette.SUNSET_CLAY, + MonthlyImageColorPalette.OCEAN_LIGHT + ); + assertThat(reloadedMay.getImagePromptVariant()).isEqualTo(MonthlyImageStylePreset.BOTANICAL_COLLAGE); + assertThat(reloadedMay.getImageColorPalette()).isEqualTo(MonthlyImageColorPalette.MOON_VIOLET); + } + + @Test + void update_content_saves_emotion_comparison_snapshot() { + User user = new UserBuilder(em).build(); + MonthlyReportV2 report = monthlyReportV2Repository.save(MonthlyReportV2.createPending( + user, + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + LocalDate.of(2026, 6, 1), + MonthlyReportComparisonType.COMPARISON + )); + em.flush(); + em.clear(); + + int updated = updateContent( + report.getId(), + "{\"previousReportId\":10,\"previousMonth\":4,\"previousEmotionStats\":{\"totalCount\":10,\"dominantEmotionCode\":\"ACHIEVEMENT\",\"positivePercent\":57,\"emotions\":[]},\"positivePercentPointChange\":14}" + ); + em.flush(); + em.clear(); + + MonthlyReportV2 reloaded = monthlyReportV2Repository.findById(report.getId()).orElseThrow(); + + assertThat(updated).isEqualTo(1); + assertThat(reloaded.getEmotionComparison()).isNotNull(); + assertThat(reloaded.getEmotionComparison().previousReportId()).isEqualTo(10L); + assertThat(reloaded.getEmotionComparison().previousMonth()).isEqualTo(4); + assertThat(reloaded.getEmotionComparison().previousEmotionStats().positivePercent()).isEqualTo(57); + assertThat(reloaded.getEmotionComparison().positivePercentPointChange()).isEqualTo(14); + assertThat(reloaded.getSocialSummary().visible()).isTrue(); + assertThat(reloaded.getSocialSummary().likeRanking()).singleElement() + .satisfies(item -> { + assertThat(item.displayOrder()).isEqualTo(1); + assertThat(item.nickname()).isEqualTo("가"); + assertThat(item.topRank()).isTrue(); + }); + } + + @Test + void update_content_keeps_emotion_comparison_null_for_baseline() { + User user = new UserBuilder(em).build(); + MonthlyReportV2 report = monthlyReportV2Repository.save(MonthlyReportV2.createPending( + user, + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + LocalDate.of(2026, 6, 1), + MonthlyReportComparisonType.BASELINE + )); + em.flush(); + em.clear(); + + int updated = updateContent(report.getId(), null); + em.flush(); + em.clear(); + + MonthlyReportV2 reloaded = monthlyReportV2Repository.findById(report.getId()).orElseThrow(); + + assertThat(updated).isEqualTo(1); + assertThat(reloaded.getEmotionComparison()).isNull(); + } + + private int updateContent(Long reportId, String emotionComparisonJson) { + return monthlyReportV2Repository.updateContent( + reportId, + "{\"summary\":\"월간 요약\",\"commentSummary\":\"한마디 요약\",\"dominantKeyword\":\"도전\",\"emotionTrend\":\"도전을 중심으로 감정이 변했어요\",\"discovered\":{\"segments\":[]},\"comment\":{\"segments\":[]}}", + "{\"styledText\":{\"segments\":[]}}", + "월간 요약", + "한마디 요약", + "도전", + "{\"totalCount\":10,\"dominantEmotionCode\":\"ACHIEVEMENT\",\"positivePercent\":71,\"emotions\":[]}", + "{\"interests\":[]}", + emotionComparisonJson, + "{\"visible\":true,\"month\":5,\"likeRanking\":[{\"displayOrder\":1,\"userId\":10,\"nickname\":\"가\",\"profileImageKey\":null,\"defaultProfileType\":null,\"topRank\":true}],\"commentRanking\":[{\"displayOrder\":1,\"userId\":11,\"nickname\":\"나\",\"profileImageKey\":null,\"defaultProfileType\":null,\"topRank\":true}]}", + MonthlyReportStatus.TEXT_COMPLETED.name() + ); + } + + private MonthlyReportV2 completedReport( + User user, + LocalDate monthStartDate, + MonthlyImageStylePreset preset, + MonthlyImageColorPalette colorPalette + ) { + MonthlyReportV2 report = MonthlyReportV2.create( + user, + monthStartDate, + monthStartDate.withDayOfMonth(monthStartDate.lengthOfMonth()), + MonthlyReportV2ContentFactory.empty(), + monthStartDate.plusMonths(1), + MonthlyReportStatus.COMPLETED, + MonthlyReportImageStatus.COMPLETED, + MonthlyReportComparisonType.COMPARISON + ); + report.assignImagePromptVariant(preset); + report.assignImageColorPalette(colorPalette); + return monthlyReportV2Repository.save(report); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlySocialQueryRepositoryTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlySocialQueryRepositoryTest.java new file mode 100644 index 00000000..b130409c --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/MonthlySocialQueryRepositoryTest.java @@ -0,0 +1,165 @@ +package com.devkor.ifive.nadab.domain.monthlyreport; + +import com.devkor.ifive.nadab.domain.comment.core.entity.Comment; +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.AnswerEntry; +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.DailyReport; +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.DailyReportStatus; +import com.devkor.ifive.nadab.domain.friend.core.entity.Friendship; +import com.devkor.ifive.nadab.domain.like.core.entity.DailyReportLike; +import com.devkor.ifive.nadab.domain.moderation.core.entity.UserBlock; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlySocialQueryRepository; +import com.devkor.ifive.nadab.domain.question.core.entity.DailyQuestion; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.infra.builder.UserBuilder; +import com.devkor.ifive.nadab.infra.db.PostgresIntegrationTestSupport; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.test.context.ActiveProfiles; + +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@ActiveProfiles("test") +class MonthlySocialQueryRepositoryTest extends PostgresIntegrationTestSupport { + + @Autowired + MonthlySocialQueryRepository monthlySocialQueryRepository; + + @Autowired + TestEntityManager em; + + DailyQuestion question; + OffsetDateTime startAt; + OffsetDateTime endAt; + + @BeforeEach + void setUp() { + question = em.getEntityManager() + .createQuery("select q from DailyQuestion q where q.deletedAt is null", DailyQuestion.class) + .setMaxResults(1) + .getSingleResult(); + startAt = OffsetDateTime.now().minusDays(1); + endAt = OffsetDateTime.now().plusDays(1); + } + + @Test + void counts_only_likes_received_from_current_available_friends() { + User owner = user("owner"); + User friend = user("가나다"); + User blockedFriend = user("blocked"); + User deletedFriend = user("deleted"); + User nonFriend = user("stranger"); + User otherOwner = user("otherOwner"); + acceptFriendship(owner, friend); + acceptFriendship(owner, blockedFriend); + acceptFriendship(owner, deletedFriend); + em.persist(UserBlock.create(blockedFriend, owner)); + + DailyReport firstReport = report(owner, LocalDate.of(2026, 6, 1)); + DailyReport secondReport = report(owner, LocalDate.of(2026, 6, 2)); + DailyReport outsideRangeReport = report(owner, LocalDate.of(2026, 6, 3)); + DailyReport otherReport = report(otherOwner, LocalDate.of(2026, 6, 1)); + + em.persist(DailyReportLike.create(friend, firstReport)); + em.persist(DailyReportLike.create(friend, secondReport)); + DailyReportLike outsideRangeLike = DailyReportLike.create(friend, outsideRangeReport); + em.persist(outsideRangeLike); + em.persist(DailyReportLike.create(friend, otherReport)); + em.persist(DailyReportLike.create(blockedFriend, firstReport)); + em.persist(DailyReportLike.create(deletedFriend, firstReport)); + em.persist(DailyReportLike.create(nonFriend, firstReport)); + deletedFriend.softDelete(); + + em.flush(); + em.getEntityManager().createNativeQuery("UPDATE daily_report_likes SET created_at = :createdAt WHERE id = :id") + .setParameter("createdAt", startAt.minusHours(1)) + .setParameter("id", outsideRangeLike.getId()) + .executeUpdate(); + em.clear(); + + List result = monthlySocialQueryRepository.countReceivedLikesByFriend( + owner.getId(), startAt, endAt + ); + + assertThat(result).singleElement().satisfies(row -> { + assertThat(row.userId()).isEqualTo(friend.getId()); + assertThat(row.nickname()).isEqualTo("가나다"); + assertThat(row.interactionCount()).isEqualTo(2); + }); + } + + @Test + void counts_active_comments_and_subcomments_received_from_current_available_friends() { + User owner = user("owner"); + User friend = user("가나다"); + User blockedFriend = user("blocked"); + User deletedFriend = user("deleted"); + User nonFriend = user("stranger"); + User otherOwner = user("otherOwner"); + acceptFriendship(owner, friend); + acceptFriendship(owner, blockedFriend); + acceptFriendship(owner, deletedFriend); + em.persist(UserBlock.create(owner, blockedFriend)); + + DailyReport report = report(owner, LocalDate.of(2026, 6, 1)); + DailyReport otherReport = report(otherOwner, LocalDate.of(2026, 6, 1)); + Comment topLevel = Comment.createTopLevel(report, friend, "comment", false); + em.persist(topLevel); + em.persist(Comment.createSubComment(friend, topLevel, "subcomment", false)); + Comment deletedComment = Comment.createTopLevel(report, friend, "deleted", false); + em.persist(deletedComment); + deletedComment.softDelete(); + Comment outsideRangeComment = Comment.createTopLevel(report, friend, "old", false); + em.persist(outsideRangeComment); + em.persist(Comment.createTopLevel(otherReport, friend, "other report", false)); + em.persist(Comment.createTopLevel(report, blockedFriend, "blocked", false)); + em.persist(Comment.createTopLevel(report, deletedFriend, "withdrawn", false)); + em.persist(Comment.createTopLevel(report, nonFriend, "stranger", false)); + deletedFriend.softDelete(); + + em.flush(); + em.getEntityManager().createNativeQuery("UPDATE comments SET created_at = :createdAt WHERE id = :id") + .setParameter("createdAt", startAt.minusHours(1)) + .setParameter("id", outsideRangeComment.getId()) + .executeUpdate(); + em.clear(); + + List result = monthlySocialQueryRepository.countReceivedCommentsByFriend( + owner.getId(), startAt, endAt + ); + + assertThat(result).singleElement().satisfies(row -> { + assertThat(row.userId()).isEqualTo(friend.getId()); + assertThat(row.nickname()).isEqualTo("가나다"); + assertThat(row.interactionCount()).isEqualTo(2); + }); + } + + private User user(String nickname) { + User user = new UserBuilder(em).build(); + user.updateNickname(nickname); + return user; + } + + private void acceptFriendship(User first, User second) { + Friendship friendship = Friendship.createPending(first, second); + friendship.accept(); + em.persist(friendship); + } + + private DailyReport report(User owner, LocalDate date) { + AnswerEntry answerEntry = AnswerEntry.create(owner, question, "answer", date, null); + em.persist(answerEntry); + DailyReport report = DailyReport.create(answerEntry, null, "report", date, DailyReportStatus.COMPLETED); + em.persist(report); + return report; + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2Test.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2Test.java new file mode 100644 index 00000000..d78a1098 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/MonthlyReportControllerV2Test.java @@ -0,0 +1,28 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.api; + +import com.devkor.ifive.nadab.global.security.principal.UserPrincipal; +import io.swagger.v3.oas.annotations.Operation; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; + +class MonthlyReportControllerV2Test { + + @Test + void locator_swagger_documents_null_status_and_version_routes() throws Exception { + Method method = MonthlyReportControllerV2.class.getMethod( + "getMyMonthlyReport", + UserPrincipal.class + ); + + String description = method.getAnnotation(Operation.class).description(); + assertThat(description) + .contains("두 슬롯은 서로 독립적으로 null일 수 있습니다") + .contains("report.status: PENDING | IN_PROGRESS | TEXT_COMPLETED | COMPLETED | FAILED") + .contains("previousReport.status: 존재하는 경우 항상 COMPLETED") + .contains("/api/v1/monthly-report/{reportId}") + .contains("/api/v2/monthly-report/{reportId}"); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2Test.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2Test.java new file mode 100644 index 00000000..c982f711 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/api/dto/response/MyMonthlyReportLookupResponseV2Test.java @@ -0,0 +1,27 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class MyMonthlyReportLookupResponseV2Test { + + @Test + void serializes_report_and_previous_report_with_report_id() throws Exception { + MyMonthlyReportLookupResponseV2 response = new MyMonthlyReportLookupResponseV2( + new MonthlyReportLocatorResponse(20L, 2, 5, MonthlyReportStatus.IN_PROGRESS), + new MonthlyReportLocatorResponse(10L, 1, 4, MonthlyReportStatus.COMPLETED) + ); + + JsonNode json = new ObjectMapper().readTree(new ObjectMapper().writeValueAsString(response)); + + assertThat(json.path("report").path("reportId").asLong()).isEqualTo(20L); + assertThat(json.path("report").path("version").asInt()).isEqualTo(2); + assertThat(json.path("previousReport").path("reportId").asLong()).isEqualTo(10L); + assertThat(json.path("previousReport").path("status").asText()).isEqualTo("COMPLETED"); + assertThat(json.path("report").has("id")).isFalse(); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentServiceTest.java new file mode 100644 index 00000000..51abb9b3 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyImagePresetAssignmentServiceTest.java @@ -0,0 +1,132 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImageVisualPreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.global.core.response.ErrorCode; +import com.devkor.ifive.nadab.global.exception.ForbiddenException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageRequest; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlyImagePresetAssignmentServiceTest { + + @Mock + MonthlyReportV2Repository monthlyReportV2Repository; + + MonthlyImagePresetAssignmentService service; + + @BeforeEach + void setUp() { + service = new MonthlyImagePresetAssignmentService(monthlyReportV2Repository); + } + + @Test + void reuses_already_assigned_visual_preset() { + MonthlyReportV2 report = report(1L); + when(report.getImagePromptVariant()).thenReturn(MonthlyImageStylePreset.INK_WASH); + when(report.getImageColorPalette()).thenReturn(MonthlyImageColorPalette.OCEAN_LIGHT); + when(monthlyReportV2Repository.findById(10L)).thenReturn(Optional.of(report)); + + MonthlyImageVisualPreset result = service.getOrAssignVisualPreset(1L, 10L); + + assertThat(result.stylePreset()).isEqualTo(MonthlyImageStylePreset.INK_WASH); + assertThat(result.colorPalette()).isEqualTo(MonthlyImageColorPalette.OCEAN_LIGHT); + verify(monthlyReportV2Repository, never()).findRecentCompletedImagePromptVariants( + 1L, 10L, PageRequest.of(0, 3) + ); + verify(monthlyReportV2Repository, never()).findRecentCompletedImageColorPalettes( + 1L, 10L, PageRequest.of(0, 3) + ); + verify(report, never()).assignImagePromptVariant(org.mockito.ArgumentMatchers.any()); + verify(report, never()).assignImageColorPalette(org.mockito.ArgumentMatchers.any()); + } + + @Test + void assigns_visual_preset_excluding_recent_completed_values() { + MonthlyReportV2 report = report(1L); + when(report.getImagePromptVariant()).thenReturn(null); + when(report.getImageColorPalette()).thenReturn(null); + when(report.getMonthStartDate()).thenReturn(LocalDate.of(2026, 5, 1)); + when(monthlyReportV2Repository.findById(10L)).thenReturn(Optional.of(report)); + List recent = List.of( + MonthlyImageStylePreset.BOTANICAL_COLLAGE, + MonthlyImageStylePreset.GLASS_AND_LIGHT, + MonthlyImageStylePreset.INK_WASH + ); + when(monthlyReportV2Repository.findRecentCompletedImagePromptVariants( + 1L, 10L, PageRequest.of(0, 3) + )).thenReturn(recent); + List recentPalettes = List.of( + MonthlyImageColorPalette.FOREST_MIST, + MonthlyImageColorPalette.OCEAN_LIGHT, + MonthlyImageColorPalette.SUNSET_CLAY + ); + when(monthlyReportV2Repository.findRecentCompletedImageColorPalettes( + 1L, 10L, PageRequest.of(0, 3) + )).thenReturn(recentPalettes); + + MonthlyImageVisualPreset result = service.getOrAssignVisualPreset(1L, 10L); + + assertThat(recent).doesNotContain(result.stylePreset()); + assertThat(recentPalettes).doesNotContain(result.colorPalette()); + verify(report).assignImagePromptVariant(result.stylePreset()); + verify(report).assignImageColorPalette(result.colorPalette()); + } + + @Test + void assigns_only_missing_palette_when_style_is_already_assigned() { + MonthlyReportV2 report = report(1L); + when(report.getImagePromptVariant()).thenReturn(MonthlyImageStylePreset.INK_WASH); + when(report.getImageColorPalette()).thenReturn(null); + when(report.getMonthStartDate()).thenReturn(LocalDate.of(2026, 5, 1)); + when(monthlyReportV2Repository.findById(10L)).thenReturn(Optional.of(report)); + when(monthlyReportV2Repository.findRecentCompletedImageColorPalettes( + 1L, 10L, PageRequest.of(0, 3) + )).thenReturn(List.of(MonthlyImageColorPalette.OCEAN_LIGHT)); + + MonthlyImageVisualPreset result = service.getOrAssignVisualPreset(1L, 10L); + + assertThat(result.stylePreset()).isEqualTo(MonthlyImageStylePreset.INK_WASH); + verify(monthlyReportV2Repository, never()).findRecentCompletedImagePromptVariants( + 1L, 10L, PageRequest.of(0, 3) + ); + verify(report).assignImageColorPalette(org.mockito.ArgumentMatchers.any()); + } + + @Test + void rejects_other_users_report() { + MonthlyReportV2 report = report(2L); + when(monthlyReportV2Repository.findById(10L)).thenReturn(Optional.of(report)); + + assertThatThrownBy(() -> service.getOrAssignVisualPreset(1L, 10L)) + .isInstanceOfSatisfying(ForbiddenException.class, exception -> + assertThat(exception.getErrorCode()).isEqualTo(ErrorCode.MONTHLY_REPORT_ACCESS_FORBIDDEN)); + } + + private MonthlyReportV2 report(Long ownerId) { + User user = mock(User.class); + when(user.getId()).thenReturn(ownerId); + MonthlyReportV2 report = mock(MonthlyReportV2.class); + when(report.getUser()).thenReturn(user); + return report; + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolverTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolverTest.java new file mode 100644 index 00000000..f3f12ba0 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportLocatorResolverTest.java @@ -0,0 +1,109 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application; + +import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlyReportLocatorResponse; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReport; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportRepository; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlyReportLocatorResolverTest { + + @Mock + MonthlyReportRepository monthlyReportRepository; + @Mock + MonthlyReportV2Repository monthlyReportV2Repository; + + MonthlyReportLocatorResolver resolver; + + @BeforeEach + void setUp() { + resolver = new MonthlyReportLocatorResolver(monthlyReportRepository, monthlyReportV2Repository); + } + + @Test + void resolves_v2_report_without_v1_fallback() { + LocalDate monthStartDate = LocalDate.of(2026, 5, 1); + MonthlyReportV2 report = v2Report(20L, monthStartDate, MonthlyReportStatus.IN_PROGRESS); + when(monthlyReportV2Repository.findByUserIdAndMonthStartDate(1L, monthStartDate)) + .thenReturn(Optional.of(report)); + + Optional result = resolver.findByMonth(1L, monthStartDate); + + assertThat(result).contains(new MonthlyReportLocatorResponse( + 20L, 2, 5, MonthlyReportStatus.IN_PROGRESS + )); + verifyNoInteractions(monthlyReportRepository); + } + + @Test + void falls_back_to_v1_when_v2_report_does_not_exist() { + LocalDate monthStartDate = LocalDate.of(2026, 5, 1); + MonthlyReport report = v1Report(10L, monthStartDate, MonthlyReportStatus.COMPLETED); + when(monthlyReportV2Repository.findByUserIdAndMonthStartDate(1L, monthStartDate)) + .thenReturn(Optional.empty()); + when(monthlyReportRepository.findByUserIdAndMonthStartDate(1L, monthStartDate)) + .thenReturn(Optional.of(report)); + + Optional result = resolver.findByMonth(1L, monthStartDate); + + assertThat(result).contains(new MonthlyReportLocatorResponse( + 10L, 1, 5, MonthlyReportStatus.COMPLETED + )); + } + + @Test + void resolves_previous_report_with_completed_status_only() { + LocalDate monthStartDate = LocalDate.of(2026, 4, 1); + MonthlyReport report = v1Report(10L, monthStartDate, MonthlyReportStatus.COMPLETED); + when(monthlyReportV2Repository.findByUserIdAndMonthStartDateAndStatus( + 1L, monthStartDate, MonthlyReportStatus.COMPLETED + )).thenReturn(Optional.empty()); + when(monthlyReportRepository.findByUserIdAndMonthStartDateAndStatus( + 1L, monthStartDate, MonthlyReportStatus.COMPLETED + )).thenReturn(Optional.of(report)); + + Optional result = resolver.findCompletedByMonth(1L, monthStartDate); + + assertThat(result).contains(new MonthlyReportLocatorResponse( + 10L, 1, 4, MonthlyReportStatus.COMPLETED + )); + verify(monthlyReportV2Repository).findByUserIdAndMonthStartDateAndStatus( + 1L, monthStartDate, MonthlyReportStatus.COMPLETED + ); + verify(monthlyReportRepository).findByUserIdAndMonthStartDateAndStatus( + 1L, monthStartDate, MonthlyReportStatus.COMPLETED + ); + } + + private MonthlyReportV2 v2Report(Long id, LocalDate monthStartDate, MonthlyReportStatus status) { + MonthlyReportV2 report = mock(MonthlyReportV2.class); + when(report.getId()).thenReturn(id); + when(report.getMonthStartDate()).thenReturn(monthStartDate); + when(report.getStatus()).thenReturn(status); + return report; + } + + private MonthlyReport v1Report(Long id, LocalDate monthStartDate, MonthlyReportStatus status) { + MonthlyReport report = mock(MonthlyReport.class); + when(report.getId()).thenReturn(id); + when(report.getMonthStartDate()).thenReturn(monthStartDate); + when(report.getStatus()).thenReturn(status); + return report; + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceTest.java new file mode 100644 index 00000000..b03ec7b9 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceTest.java @@ -0,0 +1,79 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReport; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportRepository; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.domain.user.core.repository.UserRepository; +import com.devkor.ifive.nadab.global.core.response.ErrorCode; +import com.devkor.ifive.nadab.global.exception.ForbiddenException; +import com.devkor.ifive.nadab.global.exception.NotFoundException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlyReportQueryServiceTest { + + @Mock + MonthlyReportRepository monthlyReportRepository; + @Mock + UserRepository userRepository; + + MonthlyReportQueryService service; + + @BeforeEach + void setUp() { + service = new MonthlyReportQueryService(monthlyReportRepository, userRepository); + } + + @Test + void returns_owned_monthly_report() { + MonthlyReport report = report(1L); + when(report.getMonthStartDate()).thenReturn(LocalDate.of(2026, 5, 1)); + when(report.getStatus()).thenReturn(MonthlyReportStatus.COMPLETED); + when(monthlyReportRepository.findById(10L)).thenReturn(Optional.of(report)); + + var response = service.getMonthlyReportById(1L, 10L); + + assertThat(response.month()).isEqualTo(5); + assertThat(response.status()).isEqualTo("COMPLETED"); + } + + @Test + void rejects_other_users_monthly_report() { + MonthlyReport report = report(2L); + when(monthlyReportRepository.findById(10L)).thenReturn(Optional.of(report)); + + assertThatThrownBy(() -> service.getMonthlyReportById(1L, 10L)) + .isInstanceOfSatisfying(ForbiddenException.class, exception -> + assertThat(exception.getErrorCode()).isEqualTo(ErrorCode.MONTHLY_REPORT_ACCESS_FORBIDDEN)); + } + + @Test + void rejects_missing_monthly_report() { + when(monthlyReportRepository.findById(10L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> service.getMonthlyReportById(1L, 10L)) + .isInstanceOfSatisfying(NotFoundException.class, exception -> + assertThat(exception.getErrorCode()).isEqualTo(ErrorCode.MONTHLY_REPORT_NOT_FOUND)); + } + + private MonthlyReport report(Long ownerId) { + User owner = mock(User.class); + when(owner.getId()).thenReturn(ownerId); + MonthlyReport report = mock(MonthlyReport.class); + when(report.getUser()).thenReturn(owner); + return report; + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2Test.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2Test.java new file mode 100644 index 00000000..3de766ec --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportQueryServiceV2Test.java @@ -0,0 +1,193 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application; + +import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlyReportResponseV2; +import com.devkor.ifive.nadab.domain.monthlyreport.api.dto.response.MonthlyReportLocatorResponse; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyEmotionComparisonContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialRankingItem; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportComparisonType; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportRepository; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.domain.user.core.entity.DefaultProfileType; +import com.devkor.ifive.nadab.domain.user.core.repository.UserRepository; +import com.devkor.ifive.nadab.domain.user.infra.ProfileImageUrlBuilder; +import com.devkor.ifive.nadab.domain.weeklyreport.core.repository.WeeklyReportRepository; +import com.devkor.ifive.nadab.global.shared.util.MonthRangeCalculator; +import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlyReportQueryServiceV2Test { + + @Mock + private MonthlyReportRepository monthlyReportRepository; + @Mock + private MonthlyReportV2Repository monthlyReportV2Repository; + @Mock + private WeeklyReportRepository weeklyReportRepository; + @Mock + private UserRepository userRepository; + @Mock + private ProfileImageUrlBuilder profileImageUrlBuilder; + @Mock + private MonthlyReportLocatorResolver monthlyReportLocatorResolver; + + private MonthlyReportQueryServiceV2 service; + + @BeforeEach + void setUp() { + service = new MonthlyReportQueryServiceV2( + monthlyReportRepository, + monthlyReportV2Repository, + weeklyReportRepository, + userRepository, + profileImageUrlBuilder, + monthlyReportLocatorResolver + ); + } + + @Test + void 현재와_지지난달_월간_리포트_위치_정보를_반환한다() { + when(userRepository.existsById(1L)).thenReturn(true); + LocalDate currentMonth = MonthRangeCalculator.getLastMonthRange().monthStartDate(); + LocalDate previousMonth = MonthRangeCalculator.getTwoMonthsAgoRange().monthStartDate(); + MonthlyReportLocatorResponse current = new MonthlyReportLocatorResponse( + 20L, 2, currentMonth.getMonthValue(), MonthlyReportStatus.IN_PROGRESS + ); + MonthlyReportLocatorResponse previous = new MonthlyReportLocatorResponse( + 10L, 1, previousMonth.getMonthValue(), MonthlyReportStatus.COMPLETED + ); + when(monthlyReportLocatorResolver.findByMonth(1L, currentMonth)).thenReturn(Optional.of(current)); + when(monthlyReportLocatorResolver.findCompletedByMonth(1L, previousMonth)) + .thenReturn(Optional.of(previous)); + + var response = service.getMyMonthlyReport(1L); + + assertThat(response.report()).isEqualTo(current); + assertThat(response.previousReport()).isEqualTo(previous); + } + + @Test + void 연도_경계에서_1월의_이전_리포트로_전년도_12월을_조회한다() { + MonthRangeDto january = new MonthRangeDto( + LocalDate.of(2026, 1, 1), + LocalDate.of(2026, 1, 31) + ); + MonthlyReportLocatorResponse current = new MonthlyReportLocatorResponse( + 20L, 2, 1, MonthlyReportStatus.COMPLETED + ); + MonthlyReportLocatorResponse previous = new MonthlyReportLocatorResponse( + 10L, 1, 12, MonthlyReportStatus.COMPLETED + ); + when(monthlyReportLocatorResolver.findByMonth(1L, LocalDate.of(2026, 1, 1))) + .thenReturn(Optional.of(current)); + when(monthlyReportLocatorResolver.findCompletedByMonth(1L, LocalDate.of(2025, 12, 1))) + .thenReturn(Optional.of(previous)); + + var response = service.getMyMonthlyReport(1L, january); + + assertThat(response.report()).isEqualTo(current); + assertThat(response.previousReport()).isEqualTo(previous); + } + + @Test + void COMPARISON_리포트는_감정_비교_스냅샷을_반환한다() { + User user = mock(User.class); + when(user.getId()).thenReturn(1L); + + MonthlyEmotionComparisonContent emotionComparison = new MonthlyEmotionComparisonContent( + 10L, + 4, + new TypeEmotionStatsContent(10, "ACHIEVEMENT", 57, List.of()), + 14 + ); + MonthlyReportV2 report = mock(MonthlyReportV2.class); + when(report.getUser()).thenReturn(user); + when(report.getMonthStartDate()).thenReturn(LocalDate.of(2026, 5, 1)); + when(report.getStatus()).thenReturn(MonthlyReportStatus.COMPLETED); + when(report.getComparisonType()).thenReturn(MonthlyReportComparisonType.COMPARISON); + when(report.getEmotionComparison()).thenReturn(emotionComparison); + when(monthlyReportV2Repository.findById(7L)).thenReturn(Optional.of(report)); + + MonthlyReportResponseV2 response = service.getMonthlyReportById(1L, 7L); + + assertThat(response.emotionComparison()).isEqualTo(emotionComparison.normalized()); + } + + @Test + void 소셜_요약의_프로필_식별자를_URL로_변환한다() throws Exception { + User user = mock(User.class); + when(user.getId()).thenReturn(1L); + + MonthlySocialSummaryContent socialSummary = new MonthlySocialSummaryContent( + true, + 5, + List.of(new MonthlySocialRankingItem(1, 2L, "가", "custom-key", null, true)), + List.of(new MonthlySocialRankingItem(1, 3L, "나", null, DefaultProfileType.DEFAULT, true)) + ); + MonthlyReportV2 report = mock(MonthlyReportV2.class); + when(report.getUser()).thenReturn(user); + when(report.getMonthStartDate()).thenReturn(LocalDate.of(2026, 5, 1)); + when(report.getStatus()).thenReturn(MonthlyReportStatus.COMPLETED); + when(report.getComparisonType()).thenReturn(MonthlyReportComparisonType.BASELINE); + when(report.getSocialSummary()).thenReturn(socialSummary); + when(monthlyReportV2Repository.findById(7L)).thenReturn(Optional.of(report)); + when(profileImageUrlBuilder.buildUrl("custom-key")).thenReturn("https://cdn/custom-key"); + when(profileImageUrlBuilder.buildDefaultUrl(DefaultProfileType.DEFAULT)) + .thenReturn("https://cdn/default/DEFAULT.png"); + + MonthlyReportResponseV2 response = service.getMonthlyReportById(1L, 7L); + + assertThat(response.socialSummary().visible()).isTrue(); + assertThat(response.socialSummary().likeRanking()).singleElement().satisfies(item -> { + assertThat(item.displayOrder()).isEqualTo(1); + assertThat(item.userId()).isEqualTo(2L); + assertThat(item.profileImageUrl()).isEqualTo("https://cdn/custom-key"); + assertThat(item.topRank()).isTrue(); + }); + assertThat(response.socialSummary().commentRanking()).singleElement() + .satisfies(item -> assertThat(item.profileImageUrl()) + .isEqualTo("https://cdn/default/DEFAULT.png")); + String responseJson = new ObjectMapper().writeValueAsString(response.socialSummary()); + assertThat(responseJson).contains("profileImageUrl"); + assertThat(responseJson).doesNotContain("profileImageKey", "defaultProfileType"); + } + + @Test + void BASELINE_리포트는_감정_비교_스냅샷을_null로_반환한다() { + User user = mock(User.class); + when(user.getId()).thenReturn(1L); + + MonthlyReportV2 report = mock(MonthlyReportV2.class); + when(report.getUser()).thenReturn(user); + when(report.getMonthStartDate()).thenReturn(LocalDate.of(2026, 5, 1)); + when(report.getStatus()).thenReturn(MonthlyReportStatus.COMPLETED); + when(report.getComparisonType()).thenReturn(MonthlyReportComparisonType.BASELINE); + when(monthlyReportV2Repository.findById(7L)).thenReturn(Optional.of(report)); + + MonthlyReportResponseV2 response = service.getMonthlyReportById(1L, 7L); + + assertThat(response.emotionComparison()).isNull(); + assertThat(response.socialSummary().visible()).isFalse(); + assertThat(response.socialSummary().month()).isEqualTo(5); + assertThat(response.socialSummary().likeRanking()).isEmpty(); + assertThat(response.socialSummary().commentRanking()).isEmpty(); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2Test.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2Test.java new file mode 100644 index 00000000..b551c3dd --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/MonthlyReportTxServiceV2Test.java @@ -0,0 +1,169 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyContentFactory; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlyReportV2ContentFactory; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportGenerationRequestedEventDtoV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportStatus; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import com.devkor.ifive.nadab.domain.monthlyreport.core.service.PendingMonthlyReportServiceV2; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeContentFactory; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.domain.wallet.core.entity.CrystalLog; +import com.devkor.ifive.nadab.domain.wallet.core.entity.UserWallet; +import com.devkor.ifive.nadab.domain.wallet.core.repository.CrystalLogRepository; +import com.devkor.ifive.nadab.domain.wallet.core.repository.UserWalletRepository; +import com.devkor.ifive.nadab.global.shared.util.MonthRangeCalculator; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlyReportTxServiceV2Test { + + @Mock + private PendingMonthlyReportServiceV2 pendingMonthlyReportServiceV2; + @Mock + private MonthlyReportV2Repository monthlyReportV2Repository; + @Mock + private UserWalletRepository userWalletRepository; + @Mock + private CrystalLogRepository crystalLogRepository; + @Mock + private ApplicationEventPublisher eventPublisher; + @Mock + private ObjectMapper objectMapper; + + private MonthlyReportTxServiceV2 service; + + @BeforeEach + void setUp() { + service = new MonthlyReportTxServiceV2( + pendingMonthlyReportServiceV2, + monthlyReportV2Repository, + userWalletRepository, + crystalLogRepository, + eventPublisher, + objectMapper + ); + } + + @Test + void 가장_최근_완료된_V2_리포트를_비교_대상으로_확정한다() { + User user = user(1L); + MonthlyReportV2 previousReport = report(10L); + prepareReservation(user, true); + when(monthlyReportV2Repository + .findFirstByUserIdAndStatusAndMonthStartDateBeforeOrderByMonthStartDateDesc( + 1L, + MonthlyReportStatus.COMPLETED, + MonthRangeCalculator.getLastMonthRange().monthStartDate() + )) + .thenReturn(Optional.of(previousReport)); + + service.reserveMonthlyAndPublish(user); + + verify(pendingMonthlyReportServiceV2).getOrCreatePendingMonthlyReport(user, true); + ArgumentCaptor captor = + ArgumentCaptor.forClass(MonthlyReportGenerationRequestedEventDtoV2.class); + verify(eventPublisher).publishEvent(captor.capture()); + assertThat(captor.getValue().previousReportId()).isEqualTo(10L); + } + + @Test + void 이전에_완료된_V2_리포트가_없으면_BASELINE으로_확정한다() { + User user = user(1L); + prepareReservation(user, false); + when(monthlyReportV2Repository + .findFirstByUserIdAndStatusAndMonthStartDateBeforeOrderByMonthStartDateDesc( + 1L, + MonthlyReportStatus.COMPLETED, + MonthRangeCalculator.getLastMonthRange().monthStartDate() + )) + .thenReturn(Optional.empty()); + + service.reserveMonthlyAndPublish(user); + + verify(pendingMonthlyReportServiceV2).getOrCreatePendingMonthlyReport(user, false); + ArgumentCaptor captor = + ArgumentCaptor.forClass(MonthlyReportGenerationRequestedEventDtoV2.class); + verify(eventPublisher).publishEvent(captor.capture()); + assertThat(captor.getValue().previousReportId()).isNull(); + } + + @Test + void confirm_monthly_text_serializes_social_summary_in_same_update() throws Exception { + when(objectMapper.writeValueAsString(any())) + .thenReturn( + "contentJson", + "emotionSummaryJson", + "emotionStatsJson", + "interestStatsJson", + "socialSummaryJson" + ); + + service.confirmMonthlyText( + 20L, + MonthlyReportV2ContentFactory.empty(), + TypeContentFactory.emptyText(), + TypeContentFactory.emptyEmotionStats(), + MonthlyContentFactory.emptyInterestStats(), + null, + MonthlySocialSummaryContent.empty(5) + ); + + verify(monthlyReportV2Repository).updateContent( + eq(20L), + eq("contentJson"), + eq("emotionSummaryJson"), + eq(""), + eq(""), + eq(""), + eq("emotionStatsJson"), + eq("interestStatsJson"), + eq(null), + eq("socialSummaryJson"), + eq(MonthlyReportStatus.TEXT_COMPLETED.name()) + ); + } + + private void prepareReservation(User user, boolean hasPreviousReport) { + MonthlyReportV2 pendingReport = report(20L); + UserWallet wallet = org.mockito.Mockito.mock(UserWallet.class); + CrystalLog crystalLog = org.mockito.Mockito.mock(CrystalLog.class); + + when(pendingMonthlyReportServiceV2.getOrCreatePendingMonthlyReport(user, hasPreviousReport)) + .thenReturn(pendingReport); + when(userWalletRepository.tryConsume(1L, 40L)).thenReturn(1); + when(userWalletRepository.findByUserId(1L)).thenReturn(Optional.of(wallet)); + when(wallet.getCrystalBalance()).thenReturn(60L); + when(crystalLogRepository.save(any(CrystalLog.class))).thenReturn(crystalLog); + when(crystalLog.getId()).thenReturn(30L); + } + + private User user(Long id) { + User user = org.mockito.Mockito.mock(User.class); + when(user.getId()).thenReturn(id); + return user; + } + + private MonthlyReportV2 report(Long id) { + MonthlyReportV2 report = org.mockito.Mockito.mock(MonthlyReportV2.class); + when(report.getId()).thenReturn(id); + return report; + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelectorTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelectorTest.java new file mode 100644 index 00000000..db4edee4 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImageColorPaletteSelectorTest.java @@ -0,0 +1,52 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class MonthlyImageColorPaletteSelectorTest { + + @Test + void selects_deterministically_for_same_report() { + MonthlyImageColorPalette first = MonthlyImageColorPaletteSelector.select( + 1L, 10L, LocalDate.of(2026, 5, 1), List.of() + ); + MonthlyImageColorPalette second = MonthlyImageColorPaletteSelector.select( + 1L, 10L, LocalDate.of(2026, 5, 1), List.of() + ); + + assertThat(second).isEqualTo(first); + } + + @Test + void excludes_recent_palettes() { + List recent = List.of( + MonthlyImageColorPalette.FOREST_MIST, + MonthlyImageColorPalette.OCEAN_LIGHT, + MonthlyImageColorPalette.SUNSET_CLAY + ); + + MonthlyImageColorPalette selected = MonthlyImageColorPaletteSelector.select( + 1L, 10L, LocalDate.of(2026, 5, 1), recent + ); + + assertThat(recent).doesNotContain(selected); + } + + @Test + void reuses_all_palettes_when_every_candidate_is_excluded() { + MonthlyImageColorPalette selected = MonthlyImageColorPaletteSelector.select( + 1L, + 10L, + LocalDate.of(2026, 5, 1), + List.of(MonthlyImageColorPalette.values()) + ); + + assertThat(Arrays.asList(MonthlyImageColorPalette.values())).contains(selected); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelectorTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelectorTest.java new file mode 100644 index 00000000..4965f049 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePresetSelectorTest.java @@ -0,0 +1,52 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class MonthlyImagePresetSelectorTest { + + @Test + void selects_deterministically_for_same_report() { + MonthlyImageStylePreset first = MonthlyImagePresetSelector.select( + 1L, 10L, LocalDate.of(2026, 5, 1), List.of() + ); + MonthlyImageStylePreset second = MonthlyImagePresetSelector.select( + 1L, 10L, LocalDate.of(2026, 5, 1), List.of() + ); + + assertThat(second).isEqualTo(first); + } + + @Test + void excludes_recent_presets() { + List recent = List.of( + MonthlyImageStylePreset.BOTANICAL_COLLAGE, + MonthlyImageStylePreset.GLASS_AND_LIGHT, + MonthlyImageStylePreset.INK_WASH + ); + + MonthlyImageStylePreset selected = MonthlyImagePresetSelector.select( + 1L, 10L, LocalDate.of(2026, 5, 1), recent + ); + + assertThat(recent).doesNotContain(selected); + } + + @Test + void reuses_all_presets_when_every_candidate_is_excluded() { + MonthlyImageStylePreset selected = MonthlyImagePresetSelector.select( + 1L, + 10L, + LocalDate.of(2026, 5, 1), + List.of(MonthlyImageStylePreset.values()) + ); + + assertThat(Arrays.asList(MonthlyImageStylePreset.values())).contains(selected); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposerTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposerTest.java new file mode 100644 index 00000000..ac4bd0f8 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyImagePromptComposerTest.java @@ -0,0 +1,152 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImagePromptContext; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.time.LocalDate; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class MonthlyImagePromptComposerTest { + + private final MonthlyImagePromptComposer composer = new MonthlyImagePromptComposer(); + + @ParameterizedTest + @EnumSource(MonthlyImageStylePreset.class) + void 모든_프리셋에_대해_공통_문맥과_스타일_지침을_조립한다(MonthlyImageStylePreset preset) { + MonthlyImagePromptContext context = context(preset, "꾸준한 성장", "잠시 쉬어가도 괜찮아요", "성장"); + + String prompt = composer.compose(context); + + assertThat(prompt) + .contains("Monthly summary: 꾸준한 성장") + .contains("Gentle comment summary: 잠시 쉬어가도 괜찮아요") + .contains("Dominant keyword: 성장") + .contains("Month: 2026-05-01 to 2026-05-31") + .contains("Visual direction:") + .contains("No people, no faces, no hands, no body parts.") + .doesNotContain(preset.name()); + } + + @Test + void 프리셋마다_서로_다른_시각_지침을_사용한다() { + String botanical = composer.compose(context( + MonthlyImageStylePreset.BOTANICAL_COLLAGE, "요약", "코멘트", "키워드")); + String glass = composer.compose(context( + MonthlyImageStylePreset.GLASS_AND_LIGHT, "요약", "코멘트", "키워드")); + + assertThat(botanical).contains("Botanical editorial collage"); + assertThat(glass).contains("Abstract translucent glass forms"); + assertThat(botanical).isNotEqualTo(glass); + } + + @Test + void 빈_리포트_문맥은_안전한_대체값으로_정규화한다() { + MonthlyImagePromptContext context = context( + MonthlyImageStylePreset.INK_WASH, null, " ", "\t"); + + String prompt = composer.compose(context); + + assertThat(prompt).contains("Monthly summary: Not provided") + .contains("Gentle comment summary: Not provided") + .contains("Dominant keyword: Not provided"); + } + + @ParameterizedTest + @EnumSource(MonthlyImageColorPalette.class) + void composes_a_distinct_direction_for_every_color_palette(MonthlyImageColorPalette palette) { + MonthlyImagePromptContext context = new MonthlyImagePromptContext( + "summary", + "comment", + "keyword", + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + MonthlyImageStylePreset.MINIMAL_GEOMETRY, + palette + ); + + String prompt = composer.compose(context); + + assertThat(prompt) + .contains("Color direction:") + .contains("The specified color direction is mandatory.") + .contains("Do not default to lavender, pink, beige, peach") + .doesNotContain(palette.name()) + .doesNotContain("feel calm, warm"); + } + + @Test + void all_style_and_palette_combinations_produce_distinct_prompts() { + Set prompts = new HashSet<>(); + + for (MonthlyImageStylePreset style : MonthlyImageStylePreset.values()) { + for (MonthlyImageColorPalette palette : MonthlyImageColorPalette.values()) { + prompts.add(composer.compose(new MonthlyImagePromptContext( + "summary", + "comment", + "keyword", + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + style, + palette + ))); + } + } + + assertThat(prompts).hasSize( + MonthlyImageStylePreset.values().length * MonthlyImageColorPalette.values().length + ); + } + + @Test + void every_palette_contains_recognizable_core_color_tokens() { + Map expectedColors = Map.of( + MonthlyImageColorPalette.FOREST_MIST, new String[]{"sage green", "deep teal"}, + MonthlyImageColorPalette.OCEAN_LIGHT, new String[]{"cobalt blue", "clear cyan"}, + MonthlyImageColorPalette.SUNSET_CLAY, new String[]{"terracotta", "burnt orange"}, + MonthlyImageColorPalette.MOON_VIOLET, new String[]{"indigo", "violet"}, + MonthlyImageColorPalette.CITRUS_BREEZE, new String[]{"lemon yellow", "fresh mint"}, + MonthlyImageColorPalette.EARTH_NEUTRAL, new String[]{"ivory", "stone gray"}, + MonthlyImageColorPalette.JEWEL_GLOW, new String[]{"emerald", "sapphire"}, + MonthlyImageColorPalette.ROSE_DAWN, new String[]{"rose", "peach"} + ); + + expectedColors.forEach((palette, colors) -> { + String prompt = composer.compose(new MonthlyImagePromptContext( + "summary", + "comment", + "keyword", + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + MonthlyImageStylePreset.MINIMAL_GEOMETRY, + palette + )); + + assertThat(prompt).contains(colors); + }); + } + + private MonthlyImagePromptContext context( + MonthlyImageStylePreset preset, + String summary, + String commentSummary, + String dominantKeyword + ) { + return new MonthlyImagePromptContext( + summary, + commentSummary, + dominantKeyword, + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31), + preset, + MonthlyImageColorPalette.OCEAN_LIGHT + ); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssemblerTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssemblerTest.java new file mode 100644 index 00000000..526a0342 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlyReportComparisonInputAssemblerTest.java @@ -0,0 +1,70 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportComparisonInputDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class MonthlyReportComparisonInputAssemblerTest { + + @Test + void 직전_리포트와_현재_감정_통계로_비교_입력을_조립한다() { + MonthlyReportV2 previousReport = mock(MonthlyReportV2.class); + TypeEmotionStatsContent previousEmotionStats = emotionStats(57, List.of( + emotion("ACHIEVEMENT", "성취", 20), + emotion("INTEREST", "흥미", 30), + emotion("DEPRESSION", "우울", 25) + )); + TypeEmotionStatsContent currentEmotionStats = emotionStats(71, List.of( + emotion("ACHIEVEMENT", "성취", 35), + emotion("INTEREST", "흥미", 22), + emotion("DEPRESSION", "우울", 15) + )); + when(previousReport.getId()).thenReturn(10L); + when(previousReport.getMonthStartDate()).thenReturn(LocalDate.of(2026, 4, 1)); + when(previousReport.getMonthEndDate()).thenReturn(LocalDate.of(2026, 4, 30)); + when(previousReport.getEmotionStats()).thenReturn(previousEmotionStats); + + MonthlyReportComparisonInputDto result = MonthlyReportComparisonInputAssembler.assemble( + previousReport, + currentEmotionStats + ); + + assertThat(result.previousReportId()).isEqualTo(10L); + assertThat(result.previousMonthStartDate()).isEqualTo(LocalDate.of(2026, 4, 1)); + assertThat(result.previousMonthEndDate()).isEqualTo(LocalDate.of(2026, 4, 30)); + assertThat(result.currentPositivePercent()).isEqualTo(71); + assertThat(result.previousPositivePercent()).isEqualTo(57); + assertThat(result.positivePercentPointChange()).isEqualTo(14); + assertThat(result.previousContent()).isNotNull(); + assertThat(result.previousEmotionSummaryContent()).isNotNull(); + assertThat(result.emotionChanges()) + .extracting( + MonthlyReportComparisonInputDto.EmotionChange::emotionCode, + MonthlyReportComparisonInputDto.EmotionChange::changePercentPoint + ) + .containsExactly( + org.assertj.core.groups.Tuple.tuple("ACHIEVEMENT", 15), + org.assertj.core.groups.Tuple.tuple("DEPRESSION", -10), + org.assertj.core.groups.Tuple.tuple("INTEREST", -8) + ); + } + + private TypeEmotionStatsContent emotionStats( + int positivePercent, + List emotions + ) { + return new TypeEmotionStatsContent(10, "ACHIEVEMENT", positivePercent, emotions); + } + + private TypeEmotionStatsContent.EmotionStat emotion(String code, String name, int percent) { + return new TypeEmotionStatsContent.EmotionStat(code, name, 1, percent); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculatorTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculatorTest.java new file mode 100644 index 00000000..d716ac54 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/helper/MonthlySocialSummaryCalculatorTest.java @@ -0,0 +1,93 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.helper; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialRankingItem; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class MonthlySocialSummaryCalculatorTest { + + @Test + void hides_summary_when_total_interactions_are_less_than_ten() { + MonthlySocialSummaryContent result = MonthlySocialSummaryCalculator.calculate( + 5, + List.of(count(1L, "가", 5)), + List.of(count(2L, "나", 4)) + ); + + assertThat(result.visible()).isFalse(); + assertThat(result.month()).isEqualTo(5); + assertThat(result.likeRanking()).isEmpty(); + assertThat(result.commentRanking()).isEmpty(); + } + + @Test + void hides_summary_when_either_interaction_has_no_friend() { + MonthlySocialSummaryContent result = MonthlySocialSummaryCalculator.calculate( + 5, + List.of(count(1L, "가", 10)), + List.of() + ); + + assertThat(result.visible()).isFalse(); + assertThat(result.likeRanking()).isEmpty(); + assertThat(result.commentRanking()).isEmpty(); + } + + @Test + void exposes_summary_at_ten_interactions_and_keeps_available_friends() { + MonthlySocialSummaryContent result = MonthlySocialSummaryCalculator.calculate( + 5, + List.of(count(1L, "가", 6)), + List.of(count(2L, "나", 3), count(3L, "다", 1)) + ); + + assertThat(result.visible()).isTrue(); + assertThat(result.likeRanking()).extracting(MonthlySocialRankingItem::nickname) + .containsExactly("가"); + assertThat(result.commentRanking()).extracting(MonthlySocialRankingItem::nickname) + .containsExactly("나", "다"); + assertThat(result.commentRanking()).extracting(MonthlySocialRankingItem::displayOrder) + .containsExactly(1, 2); + assertThat(result.commentRanking()).extracting(MonthlySocialRankingItem::topRank) + .containsExactly(true, false); + } + + @Test + void sorts_by_count_then_korean_name_and_highlights_all_joint_top_friends() { + MonthlySocialSummaryContent result = MonthlySocialSummaryCalculator.calculate( + 5, + List.of( + count(4L, "라", 4), + count(2L, "나", 4), + count(1L, "가", 4), + count(3L, "다", 3) + ), + List.of( + count(6L, "다", 5), + count(5L, "나", 5), + count(7L, "가", 4), + count(8L, "라", 4) + ) + ); + + assertThat(result.likeRanking()).extracting(MonthlySocialRankingItem::nickname) + .containsExactly("가", "나", "라"); + assertThat(result.likeRanking()).extracting(MonthlySocialRankingItem::displayOrder) + .containsExactly(1, 2, 3); + assertThat(result.likeRanking()).allMatch(MonthlySocialRankingItem::topRank); + + assertThat(result.commentRanking()).extracting(MonthlySocialRankingItem::nickname) + .containsExactly("나", "다", "가"); + assertThat(result.commentRanking()).extracting(MonthlySocialRankingItem::topRank) + .containsExactly(true, true, false); + } + + private MonthlySocialInteractionCountDto count(Long userId, String nickname, long count) { + return new MonthlySocialInteractionCountDto(userId, nickname, null, null, count); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java new file mode 100644 index 00000000..0354b70f --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java @@ -0,0 +1,136 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.application.listener; + +import com.devkor.ifive.nadab.domain.monthlyreport.application.MonthlyImagePresetAssignmentService; +import com.devkor.ifive.nadab.domain.monthlyreport.application.MonthlyReportTxServiceV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.AiMonthlyReportResultDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImagePromptContext; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImageVisualPreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportGenerationRequestedEventDtoV2; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyReportV2Content; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyQueryRepository; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlyReportV2Repository; +import com.devkor.ifive.nadab.domain.monthlyreport.core.service.MonthlySocialSummaryService; +import com.devkor.ifive.nadab.domain.monthlyreport.core.service.MonthlyWeeklySummariesService; +import com.devkor.ifive.nadab.domain.monthlyreport.infra.MonthlyReportImageStorage; +import com.devkor.ifive.nadab.domain.monthlyreport.infra.MonthlyReportLlmClientV2; +import com.devkor.ifive.nadab.domain.monthlyreport.infra.OpenAiImageClient; +import com.devkor.ifive.nadab.domain.reportlog.application.ReportGenerationLogRecorder; +import com.devkor.ifive.nadab.global.shared.reportcontent.StyledText; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlyReportGenerationListenerV2Test { + + @Mock MonthlyQueryRepository monthlyQueryRepository; + @Mock MonthlyReportV2Repository monthlyReportV2Repository; + @Mock MonthlyReportLlmClientV2 monthlyReportLlmClientV2; + @Mock OpenAiImageClient openAiImageClient; + @Mock MonthlyReportImageStorage monthlyReportImageStorage; + @Mock MonthlyReportTxServiceV2 monthlyReportTxServiceV2; + @Mock MonthlyImagePresetAssignmentService monthlyImagePresetAssignmentService; + @Mock MonthlyWeeklySummariesService monthlyWeeklySummariesService; + @Mock MonthlySocialSummaryService monthlySocialSummaryService; + @Mock ReportGenerationLogRecorder reportGenerationLogRecorder; + @Mock ApplicationEventPublisher eventPublisher; + + @InjectMocks + MonthlyReportGenerationListenerV2 listener; + + @Test + void 할당된_프리셋으로_이미지_prompt_context를_생성한다() { + MonthlyReportGenerationRequestedEventDtoV2 event = + new MonthlyReportGenerationRequestedEventDtoV2(10L, 1L, 100L, null); + MonthlyReportV2Content content = new MonthlyReportV2Content( + "월간 요약", + "코멘트 요약", + "성장", + "", + new StyledText(List.of()), + new StyledText(List.of()) + ); + AiMonthlyReportResultDto result = new AiMonthlyReportResultDto(content, null); + + when(monthlyQueryRepository.findMonthlyInputs(anyLong(), any(), any())).thenReturn(List.of()); + when(monthlyQueryRepository.countCompletedEmotionStatsByRange(anyLong(), any(), any(), any())) + .thenReturn(List.of()); + when(monthlyQueryRepository.countCompletedInterestStatsByRange(anyLong(), any(), any(), any())) + .thenReturn(List.of()); + when(monthlyWeeklySummariesService.buildWeeklySummaries(anyLong(), any())).thenReturn(""); + when(monthlySocialSummaryService.buildSocialSummary(anyLong(), any())) + .thenReturn(MonthlySocialSummaryContent.empty(1)); + when(monthlyReportLlmClientV2.generate(any(), any(), any(), any(), any(), any())) + .thenReturn(result); + when(monthlyImagePresetAssignmentService.getOrAssignVisualPreset(1L, 10L)) + .thenReturn(new MonthlyImageVisualPreset( + MonthlyImageStylePreset.INK_WASH, + MonthlyImageColorPalette.OCEAN_LIGHT + )); + when(openAiImageClient.generateBase64Image(anyLong(), any(MonthlyImagePromptContext.class))) + .thenReturn("base64-image"); + when(monthlyReportImageStorage.uploadBase64Webp(1L, 10L, "base64-image")) + .thenReturn("monthly/1/10.webp"); + + listener.handle(event); + + ArgumentCaptor contextCaptor = + ArgumentCaptor.forClass(MonthlyImagePromptContext.class); + verify(openAiImageClient).generateBase64Image(anyLong(), contextCaptor.capture()); + MonthlyImagePromptContext context = contextCaptor.getValue(); + assertThat(context.summary()).isEqualTo("월간 요약"); + assertThat(context.commentSummary()).isEqualTo("코멘트 요약"); + assertThat(context.dominantKeyword()).isEqualTo("성장"); + assertThat(context.stylePreset()).isEqualTo(MonthlyImageStylePreset.INK_WASH); + assertThat(context.colorPalette()).isEqualTo(MonthlyImageColorPalette.OCEAN_LIGHT); + verify(monthlyReportTxServiceV2).confirmMonthly(10L, 100L, "monthly/1/10.webp"); + } + + @Test + void 프리셋_할당에_실패하면_이미지_생성을_호출하지_않고_환불한다() { + MonthlyReportGenerationRequestedEventDtoV2 event = + new MonthlyReportGenerationRequestedEventDtoV2(10L, 1L, 100L, null); + MonthlyReportV2Content content = new MonthlyReportV2Content( + "월간 요약", + "코멘트 요약", + "성장", + "", + new StyledText(List.of()), + new StyledText(List.of()) + ); + + when(monthlyQueryRepository.findMonthlyInputs(anyLong(), any(), any())).thenReturn(List.of()); + when(monthlyQueryRepository.countCompletedEmotionStatsByRange(anyLong(), any(), any(), any())) + .thenReturn(List.of()); + when(monthlyQueryRepository.countCompletedInterestStatsByRange(anyLong(), any(), any(), any())) + .thenReturn(List.of()); + when(monthlyWeeklySummariesService.buildWeeklySummaries(anyLong(), any())).thenReturn(""); + when(monthlySocialSummaryService.buildSocialSummary(anyLong(), any())) + .thenReturn(MonthlySocialSummaryContent.empty(1)); + when(monthlyReportLlmClientV2.generate(any(), any(), any(), any(), any(), any())) + .thenReturn(new AiMonthlyReportResultDto(content, null)); + when(monthlyImagePresetAssignmentService.getOrAssignVisualPreset(1L, 10L)) + .thenThrow(new IllegalStateException("preset assignment failed")); + + listener.handle(event); + + verify(monthlyReportTxServiceV2).failAndRefundMonthlyWithImage(1L, 10L, 100L); + verifyNoInteractions(openAiImageClient); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContentTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContentTest.java new file mode 100644 index 00000000..e262fe6f --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlyEmotionComparisonContentTest.java @@ -0,0 +1,52 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.content; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportComparisonInputDto; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class MonthlyEmotionComparisonContentTest { + + @Test + void 비교_입력으로부터_저장용_스냅샷을_생성한다() { + TypeEmotionStatsContent previousEmotionStats = new TypeEmotionStatsContent( + 10, + "ACHIEVEMENT", + 57, + List.of(new TypeEmotionStatsContent.EmotionStat( + "ACHIEVEMENT", + "성취", + 5, + 50 + )) + ); + MonthlyReportComparisonInputDto input = new MonthlyReportComparisonInputDto( + 10L, + LocalDate.of(2026, 4, 1), + LocalDate.of(2026, 4, 30), + null, + null, + previousEmotionStats, + 71, + 57, + 14, + List.of() + ); + + MonthlyEmotionComparisonContent result = MonthlyEmotionComparisonContent.from(input); + + assertThat(result.previousReportId()).isEqualTo(10L); + assertThat(result.previousMonth()).isEqualTo(4); + assertThat(result.previousEmotionStats().positivePercent()).isEqualTo(57); + assertThat(result.positivePercentPointChange()).isEqualTo(14); + } + + @Test + void BASELINE_입력은_비교_스냅샷을_생성하지_않는다() { + assertThat(MonthlyEmotionComparisonContent.from(null)).isNull(); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContentTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContentTest.java new file mode 100644 index 00000000..cd11720f --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/content/MonthlySocialSummaryContentTest.java @@ -0,0 +1,31 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.content; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class MonthlySocialSummaryContentTest { + + @Test + void normalized_limits_rankings_and_sanitizes_month() { + MonthlySocialSummaryContent content = new MonthlySocialSummaryContent( + true, + 13, + List.of(item(1), item(2), item(3), item(4)), + null + ); + + MonthlySocialSummaryContent normalized = content.normalized(); + + assertThat(normalized.month()).isEqualTo(12); + assertThat(normalized.likeRanking()).extracting(MonthlySocialRankingItem::displayOrder) + .containsExactly(1, 2, 3); + assertThat(normalized.commentRanking()).isEmpty(); + } + + private MonthlySocialRankingItem item(int rank) { + return new MonthlySocialRankingItem(rank, (long) rank, "friend" + rank, null, null, rank == 1); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryServiceTest.java new file mode 100644 index 00000000..eb4d92d3 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/core/service/MonthlySocialSummaryServiceTest.java @@ -0,0 +1,58 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.core.service; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.content.MonthlySocialSummaryContent; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlySocialInteractionCountDto; +import com.devkor.ifive.nadab.domain.monthlyreport.core.repository.MonthlySocialQueryRepository; +import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlySocialSummaryServiceTest { + + @Mock + MonthlySocialQueryRepository monthlySocialQueryRepository; + + @Test + void builds_summary_with_seoul_month_boundaries() { + MonthlySocialSummaryService service = new MonthlySocialSummaryService(monthlySocialQueryRepository); + MonthRangeDto range = new MonthRangeDto( + LocalDate.of(2026, 5, 1), + LocalDate.of(2026, 5, 31) + ); + OffsetDateTime startAt = OffsetDateTime.of(2026, 5, 1, 0, 0, 0, 0, ZoneOffset.ofHours(9)); + OffsetDateTime endAt = OffsetDateTime.of(2026, 6, 1, 0, 0, 0, 0, ZoneOffset.ofHours(9)); + List likes = List.of(count(1L, "가", 6)); + List comments = List.of(count(2L, "나", 4)); + when(monthlySocialQueryRepository.countReceivedLikesByFriend(10L, startAt, endAt)) + .thenReturn(likes); + when(monthlySocialQueryRepository.countReceivedCommentsByFriend(10L, startAt, endAt)) + .thenReturn(comments); + + MonthlySocialSummaryContent result = service.buildSocialSummary(10L, range); + + assertThat(result.visible()).isTrue(); + assertThat(result.month()).isEqualTo(5); + assertThat(result.likeRanking()).singleElement() + .satisfies(item -> assertThat(item.nickname()).isEqualTo("가")); + assertThat(result.commentRanking()).singleElement() + .satisfies(item -> assertThat(item.nickname()).isEqualTo("나")); + verify(monthlySocialQueryRepository).countReceivedLikesByFriend(10L, startAt, endAt); + verify(monthlySocialQueryRepository).countReceivedCommentsByFriend(10L, startAt, endAt); + } + + private MonthlySocialInteractionCountDto count(Long userId, String nickname, long count) { + return new MonthlySocialInteractionCountDto(userId, nickname, null, null, count); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2Test.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2Test.java new file mode 100644 index 00000000..ac66f8b5 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2Test.java @@ -0,0 +1,184 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.infra; + +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyReportComparisonInputDto; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; +import com.devkor.ifive.nadab.global.core.prompt.monthly.MonthlyReportPromptLoader; +import com.devkor.ifive.nadab.global.core.response.ErrorCode; +import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; +import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.shared.reportcontent.Mark; +import com.devkor.ifive.nadab.global.shared.reportcontent.Segment; +import com.devkor.ifive.nadab.global.shared.reportcontent.StyledText; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MonthlyReportLlmClientV2Test { + + @Mock + private MonthlyReportPromptLoader promptLoader; + @Mock + private LlmRouter llmRouter; + + private MonthlyReportLlmClientV2 client; + + @BeforeEach + void setUp() { + client = new MonthlyReportLlmClientV2(promptLoader, new ObjectMapper(), llmRouter); + } + + @Test + void 비교_입력이_없으면_BASELINE_프롬프트를_사용한다() { + when(promptLoader.loadV2BaselinePrompt()).thenReturn( + "baseline {monthStartDate} {monthEndDate} {weeklySummaries} {representativeEntries} {emotionStats}" + ); + + String prompt = client.buildPrompt( + "2026-05-01", + "2026-05-31", + "weekly", + "entries", + emptyEmotionStats(), + null + ); + + assertThat(prompt).startsWith("baseline 2026-05-01 2026-05-31 weekly entries"); + verify(promptLoader, never()).loadV2ComparisonPrompt(); + } + + @Test + void 비교_입력이_있으면_COMPARISON_프롬프트에_JSON을_주입한다() { + when(promptLoader.loadV2ComparisonPrompt()).thenReturn("comparison {comparisonInput}"); + MonthlyReportComparisonInputDto comparisonInput = new MonthlyReportComparisonInputDto( + 10L, + null, + null, + null, + null, + null, + 71, + 57, + 14, + List.of() + ); + + String prompt = client.buildPrompt( + "2026-05-01", + "2026-05-31", + "weekly", + "entries", + emptyEmotionStats(), + comparisonInput + ); + + assertThat(prompt) + .startsWith("comparison {") + .contains("\"previousReportId\":10") + .contains("\"positivePercentPointChange\":14") + .doesNotContain("{comparisonInput}"); + verify(promptLoader, never()).loadV2BaselinePrompt(); + } + + @Test + void COMPARISON_emotionTrend는_감정_양상_문장의_길이를_검증한다() { + client.validateComparisonEmotionTrend("성취와 의지가 증가했어요"); + + assertThatThrownBy(() -> client.validateComparisonEmotionTrend("변했어요")) + .isInstanceOf(AiResponseParseException.class); + } + + @Test + void 공백_전용_segment는_직전_segment에_합쳐서_정규화한다() { + StyledText input = new StyledText(List.of( + new Segment("높은 기준과 기대를 가지고", List.of(Mark.BOLD, Mark.HIGHLIGHT)), + new Segment(" ", List.of()), + new Segment("의미 있는 결과를 만들고 싶어 해요.", List.of(Mark.BOLD, Mark.HIGHLIGHT)) + )); + + StyledText result = client.normalizeStyledTextSegments(input); + + assertThat(result.segments()).hasSize(2); + assertThat(result.segments().get(0).text()).isEqualTo("높은 기준과 기대를 가지고 "); + assertThat(result.plainText()).isEqualTo("높은 기준과 기대를 가지고 의미 있는 결과를 만들고 싶어 해요."); + } + + @Test + void 빈_segment는_제거하고_null_marks는_빈_배열로_정규화한다() { + StyledText input = new StyledText(List.of( + new Segment("", List.of()), + new Segment("의미 있는 문장", null) + )); + + StyledText result = client.normalizeStyledTextSegments(input); + + assertThat(result.segments()).containsExactly(new Segment("의미 있는 문장", List.of())); + } + + @Test + void COMPARISON_감정_분석문은_BOLD와_HIGHLIGHT_조합을_허용한다() { + StyledText valid = new StyledText(List.of( + new Segment("직전 기간보다 선택을 망설이는 시간이 줄었고, ", List.of()), + new Segment("도전", List.of(Mark.BOLD, Mark.HIGHLIGHT)), + new Segment("을 행동으로 옮기는 흐름이 여러 상황에서 더 분명하게 이어졌어요.", List.of()) + )); + client.validateComparisonEmotionSummary(valid, "도전"); + + StyledText invalid = new StyledText(List.of( + new Segment("도전", List.of(Mark.HIGHLIGHT)), + new Segment("을 행동으로 옮기는 흐름이 더 분명해졌어요.", List.of()) + )); + assertThatThrownBy(() -> client.validateComparisonEmotionSummary(invalid, "도전")) + .isInstanceOf(AiResponseParseException.class); + } + + @Test + void COMPARISON_감정_분석문은_프롬프트보다_넓은_길이_범위를_허용한다() { + client.validateLength( + "가".repeat(150), + "나".repeat(150), + "다".repeat(130), + true + ); + + assertThatThrownBy(() -> client.validateLength( + "가".repeat(150), + "나".repeat(150), + "다".repeat(151), + true + )).isInstanceOfSatisfying( + AiResponseParseException.class, + exception -> assertThat(exception.getErrorCode()) + .isEqualTo(ErrorCode.MONTHLY_REPORT_EMOTION_SUMMARY_LENGTH_INVALID) + ); + } + + @Test + void comment_길이_오류는_comment_전용_에러_코드를_사용한다() { + assertThatThrownBy(() -> client.validateLength( + "가".repeat(150), + "나".repeat(149), + "다".repeat(50), + true + )).isInstanceOfSatisfying( + AiResponseParseException.class, + exception -> assertThat(exception.getErrorCode()) + .isEqualTo(ErrorCode.MONTHLY_REPORT_COMMENT_LENGTH_INVALID) + ); + } + + private TypeEmotionStatsContent emptyEmotionStats() { + return new TypeEmotionStatsContent(0, null, 0, List.of()); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClientTest.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClientTest.java new file mode 100644 index 00000000..2ac7fc29 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/OpenAiImageClientTest.java @@ -0,0 +1,55 @@ +package com.devkor.ifive.nadab.domain.monthlyreport.infra; + +import com.devkor.ifive.nadab.domain.monthlyreport.application.helper.MonthlyImagePromptComposer; +import com.devkor.ifive.nadab.domain.monthlyreport.core.dto.MonthlyImagePromptContext; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageColorPalette; +import com.devkor.ifive.nadab.domain.monthlyreport.core.entity.MonthlyImageStylePreset; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.ExchangeFunction; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class OpenAiImageClientTest { + + @Test + void context로_조립한_프롬프트를_OpenAI_요청에_사용한다() { + ExchangeFunction exchangeFunction = mock(ExchangeFunction.class); + when(exchangeFunction.exchange(any())).thenReturn(Mono.just( + ClientResponse.create(HttpStatus.OK) + .header("Content-Type", "application/json") + .body("{\"data\":[{\"b64_json\":\"aW1hZ2U=\"}]}") + .build() + )); + WebClient.Builder webClientBuilder = WebClient.builder().exchangeFunction(exchangeFunction); + MonthlyImagePromptComposer composer = mock(MonthlyImagePromptComposer.class); + MonthlyImagePromptContext context = new MonthlyImagePromptContext( + "요약", "코멘트", "키워드", + LocalDate.of(2026, 5, 1), LocalDate.of(2026, 5, 31), + MonthlyImageStylePreset.INK_WASH, + MonthlyImageColorPalette.OCEAN_LIGHT + ); + when(composer.compose(context)).thenReturn("composed-prompt"); + OpenAiImageClient client = new OpenAiImageClient(webClientBuilder, composer); + ReflectionTestUtils.setField(client, "apiKey", "test-key"); + ReflectionTestUtils.setField(client, "model", "test-model"); + ReflectionTestUtils.setField(client, "size", "1024x1024"); + ReflectionTestUtils.setField(client, "quality", "medium"); + ReflectionTestUtils.setField(client, "outputFormat", "webp"); + + String result = client.generateBase64Image(1L, context); + + assertThat(result).isEqualTo("aW1hZ2U="); + verify(composer).compose(context); + } +} From 37a728c936822b17e463b07b5f297b82aa5ad0a6 Mon Sep 17 00:00:00 2001 From: 1Seob Date: Tue, 30 Jun 2026 21:52:02 +0900 Subject: [PATCH 3/6] =?UTF-8?q?chore(infra):=20=EA=B0=9C=EB=B0=9C=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20CORS=20=ED=97=88=EC=9A=A9=20URL=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#187)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-to-dev-ec2.yml | 1 + src/main/resources/application-dev.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/deploy-to-dev-ec2.yml b/.github/workflows/deploy-to-dev-ec2.yml index f01fd6cb..f72227cf 100644 --- a/.github/workflows/deploy-to-dev-ec2.yml +++ b/.github/workflows/deploy-to-dev-ec2.yml @@ -121,6 +121,7 @@ jobs: JWT_SECRET="${{ secrets.JWT_SECRET }}" \ FRONTEND_DEV_URL="${{ secrets.FRONTEND_DEV_URL }}" \ FRONTEND_DEV_URL_2="${{ secrets.FRONTEND_DEV_URL_2 }}" \ + FRONTEND_DEV_URL_3="${{ secrets.FRONTEND_DEV_URL_3 }}" \ SWAGGER_SERVER_URL="${{ secrets.SWAGGER_SERVER_URL }}" \ SWAGGER_ORIGIN_PUBLIC_IP="${{ secrets.SWAGGER_ORIGIN_PUBLIC_IP }}" \ SWAGGER_ORIGIN_DOMAIN="${{ secrets.SWAGGER_ORIGIN_DOMAIN }}" \ diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 3a62b47a..69cd4012 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -63,5 +63,6 @@ cors: - http://localhost:5173 - ${FRONTEND_DEV_URL} - ${FRONTEND_DEV_URL_2} + - ${FRONTEND_DEV_URL_3} - ${SWAGGER_ORIGIN_PUBLIC_IP} - ${SWAGGER_ORIGIN_DOMAIN} From ae0e604c7f1e08365f0f9395ed24d32742f3e089 Mon Sep 17 00:00:00 2001 From: 1Seob Date: Wed, 1 Jul 2026 20:51:26 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix(user):=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=EA=B0=92=20=EB=B3=B4=EC=99=84=20(#188)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 관심 주제를 PREFERENCE로 고정하고 초기 크리스탈 1,000 지급 --- .../test/application/TestUserService.java | 8 +- .../domain/wallet/core/entity/UserWallet.java | 6 +- .../test/application/TestUserServiceTest.java | 84 +++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/test/application/TestUserServiceTest.java diff --git a/src/main/java/com/devkor/ifive/nadab/domain/test/application/TestUserService.java b/src/main/java/com/devkor/ifive/nadab/domain/test/application/TestUserService.java index 1a7e39b9..c1c3dcb1 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/test/application/TestUserService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/test/application/TestUserService.java @@ -3,9 +3,11 @@ import com.devkor.ifive.nadab.domain.terms.application.TermsCommandService; import com.devkor.ifive.nadab.domain.test.api.dto.request.CreateTestUserRequest; import com.devkor.ifive.nadab.domain.test.api.dto.response.CreateTestUserResponse; +import com.devkor.ifive.nadab.domain.user.core.entity.InterestCode; import com.devkor.ifive.nadab.domain.user.core.entity.SignupStatusType; import com.devkor.ifive.nadab.domain.user.core.entity.User; import com.devkor.ifive.nadab.domain.user.core.repository.UserRepository; +import com.devkor.ifive.nadab.domain.user.core.service.UserInterestService; import com.devkor.ifive.nadab.domain.user.core.service.UserProfileUpdateService; import com.devkor.ifive.nadab.domain.wallet.core.entity.UserWallet; import com.devkor.ifive.nadab.domain.wallet.core.repository.UserWalletRepository; @@ -25,9 +27,12 @@ @RequiredArgsConstructor public class TestUserService { + private static final long DEFAULT_CRYSTAL_BALANCE = 1_000L; + private final UserRepository userRepository; private final UserWalletRepository userWalletRepository; private final UserProfileUpdateService userProfileUpdateService; + private final UserInterestService userInterestService; private final TermsCommandService termsCommandService; private final PasswordEncoder passwordEncoder; @@ -47,9 +52,10 @@ public CreateTestUserResponse createTestUser(CreateTestUserRequest request) { userRepository.save(user); userProfileUpdateService.updateNickname(user, request.nickname()); + userInterestService.updateUserInterest(user, InterestCode.PREFERENCE); user.updateSignupStatus(SignupStatusType.COMPLETED); - userWalletRepository.save(UserWallet.create(user)); + userWalletRepository.save(UserWallet.create(user, DEFAULT_CRYSTAL_BALANCE)); termsCommandService.saveConsents(user.getId(), true, true, true, false); return new CreateTestUserResponse( diff --git a/src/main/java/com/devkor/ifive/nadab/domain/wallet/core/entity/UserWallet.java b/src/main/java/com/devkor/ifive/nadab/domain/wallet/core/entity/UserWallet.java index 50c370ea..8eff3889 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/wallet/core/entity/UserWallet.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/wallet/core/entity/UserWallet.java @@ -34,9 +34,13 @@ public class UserWallet extends AuditableEntity { private long version; public static UserWallet create(User user) { + return create(user, 0L); + } + + public static UserWallet create(User user, long initialCrystalBalance) { UserWallet wallet = new UserWallet(); wallet.user = user; - wallet.crystalBalance = 0L; + wallet.crystalBalance = initialCrystalBalance; return wallet; } } diff --git a/src/test/java/com/devkor/ifive/nadab/domain/test/application/TestUserServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/test/application/TestUserServiceTest.java new file mode 100644 index 00000000..69d4d09b --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/test/application/TestUserServiceTest.java @@ -0,0 +1,84 @@ +package com.devkor.ifive.nadab.domain.test.application; + +import com.devkor.ifive.nadab.domain.terms.application.TermsCommandService; +import com.devkor.ifive.nadab.domain.test.api.dto.request.CreateTestUserRequest; +import com.devkor.ifive.nadab.domain.user.core.entity.InterestCode; +import com.devkor.ifive.nadab.domain.user.core.entity.SignupStatusType; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.domain.user.core.repository.UserRepository; +import com.devkor.ifive.nadab.domain.user.core.service.UserInterestService; +import com.devkor.ifive.nadab.domain.user.core.service.UserProfileUpdateService; +import com.devkor.ifive.nadab.domain.wallet.core.entity.UserWallet; +import com.devkor.ifive.nadab.domain.wallet.core.repository.UserWalletRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TestUserServiceTest { + + @Mock + private UserRepository userRepository; + @Mock + private UserWalletRepository userWalletRepository; + @Mock + private UserProfileUpdateService userProfileUpdateService; + @Mock + private UserInterestService userInterestService; + @Mock + private TermsCommandService termsCommandService; + @Mock + private PasswordEncoder passwordEncoder; + + private TestUserService testUserService; + + @BeforeEach + void setUp() { + testUserService = new TestUserService( + userRepository, + userWalletRepository, + userProfileUpdateService, + userInterestService, + termsCommandService, + passwordEncoder + ); + ReflectionTestUtils.setField(testUserService, "testUserPassword", "test-password"); + } + + @Test + void createTestUser_sets_terms_interest_and_default_crystals() { + CreateTestUserRequest request = new CreateTestUserRequest( + "test@example.com", + "tester" + ); + when(passwordEncoder.encode("test-password")).thenReturn("encoded-password"); + when(userRepository.save(any(User.class))).thenAnswer(invocation -> { + User user = invocation.getArgument(0); + ReflectionTestUtils.setField(user, "id", 1L); + return user; + }); + + var response = testUserService.createTestUser(request); + + ArgumentCaptor userCaptor = ArgumentCaptor.forClass(User.class); + verify(userInterestService).updateUserInterest(userCaptor.capture(), eq(InterestCode.PREFERENCE)); + verify(termsCommandService).saveConsents(1L, true, true, true, false); + + ArgumentCaptor walletCaptor = ArgumentCaptor.forClass(UserWallet.class); + verify(userWalletRepository).save(walletCaptor.capture()); + assertThat(walletCaptor.getValue().getCrystalBalance()).isEqualTo(1_000L); + assertThat(userCaptor.getValue().getSignupStatus()).isEqualTo(SignupStatusType.COMPLETED); + assertThat(response.signupStatus()).isEqualTo(SignupStatusType.COMPLETED.name()); + } +} From 98b1b088b461b535ece39741fccc2c42cc5d8b76 Mon Sep 17 00:00:00 2001 From: 1Seob Date: Tue, 7 Jul 2026 18:18:58 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat(admin):=20=EC=95=B1=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=9E=88=EC=8A=A4?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#189)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(admin): 앱 버전 수정과 순서 검증 추가 관리자 앱 버전 화면에서 최신 버전 문자열을 직접 수정할 수 있도록 API와 UI를 추가하고, version 입력을 major.minor.patch 형식으로 제한함. 같은 플랫폼의 기존 다른 버전보다 낮거나 같은 값은 생성·수정 모두에서 차단하도록 검증을 보강함 * feat(admin): 앱 버전 이력 조회 페이지 추가 앱 버전 히스토리 조회 API와 관리자 페이지를 추가하고, 플랫폼 필터와 latest 상태, summary, 공지 항목, 생성·수정 시각을 함께 확인하도록 구성함 --- .../domain/admin/api/AdminPageController.java | 5 + .../admin/api/AdminVersionController.java | 20 + .../request/AdminVersionCreateRequest.java | 2 + .../request/AdminVersionUpdateRequest.java | 13 + .../AdminVersionHistoryItemResponse.java | 18 + .../response/AdminVersionHistoryResponse.java | 8 + .../AdminVersionCommandService.java | 83 +++ .../application/AdminVersionQueryService.java | 45 ++ .../appversion/core/entity/AppVersion.java | 4 + .../core/repository/AppVersionRepository.java | 10 + .../nadab/global/core/response/ErrorCode.java | 4 + .../templates/admin/version-history.html | 488 ++++++++++++++++++ .../resources/templates/admin/version.html | 104 +++- .../AdminVersionCommandServiceTest.java | 144 ++++++ .../AdminVersionQueryServiceTest.java | 84 +++ 15 files changed, 1029 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionUpdateRequest.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryItemResponse.java create mode 100644 src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryResponse.java create mode 100644 src/main/resources/templates/admin/version-history.html create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandServiceTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryServiceTest.java diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminPageController.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminPageController.java index 54b8ad5b..580d9a54 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminPageController.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminPageController.java @@ -20,4 +20,9 @@ public String adminRoot() { public String adminVersionPage() { return "admin/version"; } + + @GetMapping("/admin/tabs/app-version-history") + public String adminVersionHistoryPage() { + return "admin/version-history"; + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminVersionController.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminVersionController.java index 7859ce12..5d291c4f 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminVersionController.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/AdminVersionController.java @@ -3,9 +3,12 @@ import com.devkor.ifive.nadab.domain.admin.api.dto.request.AdminVersionCreateRequest; import com.devkor.ifive.nadab.domain.admin.api.dto.request.AdminVersionItemUpsertRequest; import com.devkor.ifive.nadab.domain.admin.api.dto.request.AdminVersionSummaryUpdateRequest; +import com.devkor.ifive.nadab.domain.admin.api.dto.request.AdminVersionUpdateRequest; import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminLatestVersionsResponse; +import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionHistoryResponse; import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionCreateResponse; import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionItemCreateResponse; +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppPlatform; import com.devkor.ifive.nadab.domain.admin.application.AdminVersionCommandService; import com.devkor.ifive.nadab.domain.admin.application.AdminVersionItemCommandService; import com.devkor.ifive.nadab.domain.admin.application.AdminVersionQueryService; @@ -22,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Hidden @@ -39,6 +43,13 @@ public ResponseEntity> getLatestVers return ApiResponseEntity.ok(adminVersionQueryService.getLatestVersions()); } + @GetMapping("/history") + public ResponseEntity> getVersionHistory( + @RequestParam(required = false) AppPlatform platform + ) { + return ApiResponseEntity.ok(adminVersionQueryService.getVersionHistory(platform)); + } + @PostMapping public ResponseEntity> createVersion( @RequestBody @Valid AdminVersionCreateRequest request @@ -56,6 +67,15 @@ public ResponseEntity> updateVersionSummary( return ApiResponseEntity.noContent(); } + @PutMapping("/{appVersionId}/version") + public ResponseEntity> updateVersion( + @PathVariable Long appVersionId, + @RequestBody @Valid AdminVersionUpdateRequest request + ) { + adminVersionCommandService.updateVersion(appVersionId, request.version()); + return ApiResponseEntity.noContent(); + } + @PostMapping("/{appVersionId}/items") public ResponseEntity> createVersionItem( @PathVariable Long appVersionId, diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionCreateRequest.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionCreateRequest.java index dad51c94..79934d5e 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionCreateRequest.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionCreateRequest.java @@ -3,6 +3,7 @@ import com.devkor.ifive.nadab.domain.appversion.core.entity.AppPlatform; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; public record AdminVersionCreateRequest( @@ -11,6 +12,7 @@ public record AdminVersionCreateRequest( @NotBlank(message = "버전은 필수입니다.") @Size(max = 30, message = "버전은 30자 이하여야 합니다.") + @Pattern(regexp = "\\d+\\.\\d+\\.\\d+", message = "Version must use major.minor.patch format.") String version, @NotNull(message = "요약은 null일 수 없습니다.") diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionUpdateRequest.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionUpdateRequest.java new file mode 100644 index 00000000..4f17faa3 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/request/AdminVersionUpdateRequest.java @@ -0,0 +1,13 @@ +package com.devkor.ifive.nadab.domain.admin.api.dto.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +public record AdminVersionUpdateRequest( + @NotBlank(message = "Version is required.") + @Size(max = 30, message = "Version must be 30 characters or less.") + @Pattern(regexp = "\\d+\\.\\d+\\.\\d+", message = "Version must use major.minor.patch format.") + String version +) { +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryItemResponse.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryItemResponse.java new file mode 100644 index 00000000..a1a885ef --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryItemResponse.java @@ -0,0 +1,18 @@ +package com.devkor.ifive.nadab.domain.admin.api.dto.response; + +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppPlatform; + +import java.time.OffsetDateTime; +import java.util.List; + +public record AdminVersionHistoryItemResponse( + Long id, + AppPlatform platform, + String version, + Boolean isLatest, + String summary, + OffsetDateTime createdAt, + OffsetDateTime updatedAt, + List items +) { +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryResponse.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryResponse.java new file mode 100644 index 00000000..64d4bc76 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/api/dto/response/AdminVersionHistoryResponse.java @@ -0,0 +1,8 @@ +package com.devkor.ifive.nadab.domain.admin.api.dto.response; + +import java.util.List; + +public record AdminVersionHistoryResponse( + List versions +) { +} diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandService.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandService.java index 6f760a7e..21f490d1 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandService.java @@ -4,6 +4,7 @@ import com.devkor.ifive.nadab.domain.appversion.core.entity.AppVersion; import com.devkor.ifive.nadab.domain.appversion.core.repository.AppVersionRepository; import com.devkor.ifive.nadab.global.core.response.ErrorCode; +import com.devkor.ifive.nadab.global.exception.BadRequestException; import com.devkor.ifive.nadab.global.exception.ConflictException; import com.devkor.ifive.nadab.global.exception.NotFoundException; import lombok.RequiredArgsConstructor; @@ -11,11 +12,18 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigInteger; +import java.util.Comparator; +import java.util.List; +import java.util.regex.Pattern; + @Service @RequiredArgsConstructor @Transactional public class AdminVersionCommandService { + private static final Pattern SEMANTIC_VERSION_PATTERN = Pattern.compile("\\d+\\.\\d+\\.\\d+"); + private final AppVersionRepository appVersionRepository; public Long createVersion(AdminVersionCreateRequest request) { @@ -23,6 +31,12 @@ public Long createVersion(AdminVersionCreateRequest request) { throw new ConflictException(ErrorCode.APP_VERSION_ALREADY_EXISTS); } + SemanticVersion newVersion = SemanticVersion.parse(request.version()); + validateVersionGreaterThanOtherVersions( + newVersion, + appVersionRepository.findByPlatform(request.platform()) + ); + appVersionRepository.findByPlatformAndIsLatestTrue(request.platform()) .ifPresent(AppVersion::markAsNotLatest); appVersionRepository.flush(); @@ -45,4 +59,73 @@ public void updateSummary(Long appVersionId, String summary) { .orElseThrow(() -> new NotFoundException(ErrorCode.APP_VERSION_NOT_FOUND)); appVersion.updateSummary(summary); } + + public void updateVersion(Long appVersionId, String version) { + AppVersion appVersion = appVersionRepository.findById(appVersionId) + .orElseThrow(() -> new NotFoundException(ErrorCode.APP_VERSION_NOT_FOUND)); + + if (appVersionRepository.existsByPlatformAndVersionAndIdNot( + appVersion.getPlatform(), version, appVersionId + )) { + throw new ConflictException(ErrorCode.APP_VERSION_ALREADY_EXISTS); + } + + SemanticVersion newVersion = SemanticVersion.parse(version); + validateVersionGreaterThanOtherVersions( + newVersion, + appVersionRepository.findByPlatformAndIdNot(appVersion.getPlatform(), appVersionId) + ); + + try { + appVersion.updateVersion(version); + appVersionRepository.flush(); + } catch (DataIntegrityViolationException e) { + throw new ConflictException(ErrorCode.APP_VERSION_ALREADY_EXISTS); + } + } + + private void validateVersionGreaterThanOtherVersions( + SemanticVersion newVersion, + List otherAppVersions + ) { + otherAppVersions.stream() + .map(versionEntity -> SemanticVersion.parse(versionEntity.getVersion())) + .max(Comparator.naturalOrder()) + .filter(maxVersion -> newVersion.compareTo(maxVersion) <= 0) + .ifPresent(maxVersion -> { + throw new ConflictException(ErrorCode.APP_VERSION_MUST_BE_GREATER_THAN_EXISTING); + }); + } + + private record SemanticVersion(BigInteger major, BigInteger minor, BigInteger patch) + implements Comparable { + + private static SemanticVersion parse(String version) { + if (!SEMANTIC_VERSION_PATTERN.matcher(version).matches()) { + throw new BadRequestException(ErrorCode.APP_VERSION_INVALID_FORMAT); + } + + String[] parts = version.split("\\."); + return new SemanticVersion( + new BigInteger(parts[0]), + new BigInteger(parts[1]), + new BigInteger(parts[2]) + ); + } + + @Override + public int compareTo(SemanticVersion other) { + int majorComparison = major.compareTo(other.major); + if (majorComparison != 0) { + return majorComparison; + } + + int minorComparison = minor.compareTo(other.minor); + if (minorComparison != 0) { + return minorComparison; + } + + return patch.compareTo(other.patch); + } + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryService.java b/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryService.java index 6b470c35..b4011ffb 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryService.java @@ -1,8 +1,11 @@ package com.devkor.ifive.nadab.domain.admin.application; import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminLatestVersionsResponse; +import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionHistoryItemResponse; +import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionHistoryResponse; import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionItemResponse; import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionResponse; +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppPlatform; import com.devkor.ifive.nadab.domain.appversion.core.entity.AppVersion; import com.devkor.ifive.nadab.domain.appversion.core.entity.AppVersionItem; import com.devkor.ifive.nadab.domain.appversion.core.repository.AppVersionItemRepository; @@ -61,4 +64,46 @@ public AdminLatestVersionsResponse getLatestVersions() { return new AdminLatestVersionsResponse(versions); } + + public AdminVersionHistoryResponse getVersionHistory(AppPlatform platform) { + List appVersions = platform == null + ? appVersionRepository.findAllByOrderByCreatedAtDescIdDesc() + : appVersionRepository.findByPlatformOrderByCreatedAtDescIdDesc(platform); + List appVersionIds = appVersions.stream() + .map(AppVersion::getId) + .toList(); + + List items = appVersionIds.isEmpty() + ? List.of() + : appVersionItemRepository.findByAppVersionIdInOrderByDisplayOrderAsc(appVersionIds); + + Map> itemsByVersionId = items.stream() + .collect(Collectors.groupingBy( + item -> item.getAppVersion().getId(), + Collectors.mapping( + item -> new AdminVersionItemResponse( + item.getId(), + item.getTitle(), + item.getDescription(), + item.getDisplayOrder() + ), + Collectors.toList() + ) + )); + + List versions = appVersions.stream() + .map(version -> new AdminVersionHistoryItemResponse( + version.getId(), + version.getPlatform(), + version.getVersion(), + version.getIsLatest(), + version.getSummary(), + version.getCreatedAt(), + version.getUpdatedAt(), + itemsByVersionId.getOrDefault(version.getId(), List.of()) + )) + .toList(); + + return new AdminVersionHistoryResponse(versions); + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/entity/AppVersion.java b/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/entity/AppVersion.java index 49a3d47b..dc36f0d6 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/entity/AppVersion.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/entity/AppVersion.java @@ -56,4 +56,8 @@ public void markAsNotLatest() { public void updateSummary(String summary) { this.summary = summary; } + + public void updateVersion(String version) { + this.version = version; + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/repository/AppVersionRepository.java b/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/repository/AppVersionRepository.java index dd437ffd..ce937160 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/repository/AppVersionRepository.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/appversion/core/repository/AppVersionRepository.java @@ -13,4 +13,14 @@ public interface AppVersionRepository extends JpaRepository { Optional findByPlatformAndIsLatestTrue(AppPlatform platform); boolean existsByPlatformAndVersion(AppPlatform platform, String version); + + boolean existsByPlatformAndVersionAndIdNot(AppPlatform platform, String version, Long id); + + List findByPlatform(AppPlatform platform); + + List findByPlatformAndIdNot(AppPlatform platform, Long id); + + List findAllByOrderByCreatedAtDescIdDesc(); + + List findByPlatformOrderByCreatedAtDescIdDesc(AppPlatform platform); } diff --git a/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java b/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java index 23bb52ea..f2a0d08e 100644 --- a/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java +++ b/src/main/java/com/devkor/ifive/nadab/global/core/response/ErrorCode.java @@ -432,8 +432,12 @@ public enum ErrorCode { APP_VERSION_NOT_FOUND(HttpStatus.NOT_FOUND, "앱 버전을 찾을 수 없습니다"), APP_VERSION_ITEM_NOT_FOUND(HttpStatus.NOT_FOUND, "앱 버전 항목을 찾을 수 없습니다"), + // 400 Bad Request + APP_VERSION_INVALID_FORMAT(HttpStatus.BAD_REQUEST, "앱 버전은 major.minor.patch 형식이어야 합니다"), + // 409 Conflict APP_VERSION_ALREADY_EXISTS(HttpStatus.CONFLICT, "해당 플랫폼의 같은 버전이 이미 존재합니다"), + APP_VERSION_MUST_BE_GREATER_THAN_EXISTING(HttpStatus.CONFLICT, "앱 버전은 같은 플랫폼의 다른 모든 버전보다 높아야 합니다"), APP_VERSION_ITEM_DISPLAY_ORDER_DUPLICATED(HttpStatus.CONFLICT, "같은 버전 내 displayOrder가 중복됩니다"), // ==================== ADMIN (어드민) ==================== diff --git a/src/main/resources/templates/admin/version-history.html b/src/main/resources/templates/admin/version-history.html new file mode 100644 index 00000000..b6060c30 --- /dev/null +++ b/src/main/resources/templates/admin/version-history.html @@ -0,0 +1,488 @@ + + + + + + NADAB Admin Version History + + + +
+ + + + + + diff --git a/src/main/resources/templates/admin/version.html b/src/main/resources/templates/admin/version.html index db82efe4..2460a529 100644 --- a/src/main/resources/templates/admin/version.html +++ b/src/main/resources/templates/admin/version.html @@ -78,6 +78,19 @@ color: var(--muted); } + .panel-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + flex-wrap: wrap; + margin-bottom: 12px; + } + + .panel-head .panel-title { + margin: 0; + } + .grid { display: grid; gap: 10px; @@ -177,6 +190,24 @@ font-size: 15px; } + .version-editor { + display: grid; + grid-template-columns: minmax(140px, 220px) auto; + gap: 8px; + align-items: end; + } + + .version-editor.confirmed-ui input { + opacity: 0.58; + } + + @media (max-width: 640px) { + .version-editor { + grid-template-columns: 1fr; + width: 100%; + } + } + .items-table { width: 100%; border-collapse: collapse; @@ -287,7 +318,7 @@

Create Version

- +
@@ -300,7 +331,10 @@

Create Version

-

Current Latest Versions

+
+

Current Latest Versions

+ View History +
@@ -449,7 +483,18 @@ versionListEl.innerHTML = versions.map((version) => `
- ${escapeHtml(version.platform)} / ${escapeHtml(version.version)} + ${escapeHtml(version.platform)} +
+
+ + +
+
+ + + +
+
@@ -509,6 +554,27 @@ } } + function toggleVersionEditMode(versionEditor, editing) { + const versionInput = versionEditor.querySelector('.version-value'); + const editBtn = versionEditor.querySelector('[data-action="edit-version"]'); + const saveBtn = versionEditor.querySelector('[data-action="save-version"]'); + const cancelBtn = versionEditor.querySelector('[data-action="cancel-version"]'); + + versionInput.disabled = !editing; + editBtn.classList.toggle('is-hidden', editing); + saveBtn.classList.toggle('is-hidden', !editing); + cancelBtn.classList.toggle('is-hidden', !editing); + + if (editing) { + versionEditor.classList.remove('confirmed-ui'); + versionEditor.classList.add('draft-ui'); + versionInput.focus(); + } else { + versionEditor.classList.remove('draft-ui'); + versionEditor.classList.add('confirmed-ui'); + } + } + function toggleItemEditMode(row, editing) { const titleInput = row.querySelector('.item-title'); const descriptionInput = row.querySelector('.item-description'); @@ -561,6 +627,12 @@ summaryEditor.classList.add('draft-ui'); } + const versionEditor = target.closest('.version-editor'); + if (versionEditor) { + versionEditor.classList.remove('confirmed-ui'); + versionEditor.classList.add('draft-ui'); + } + const row = target.closest('tr[data-item-id], tr[data-new-item]'); if (row) { row.classList.remove('confirmed-ui'); @@ -610,6 +682,32 @@ const appVersionId = Number(versionCard.dataset.versionId); try { + if (action === 'edit-version') { + const versionEditor = versionCard.querySelector('.version-editor'); + toggleVersionEditMode(versionEditor, true); + return; + } + + if (action === 'cancel-version') { + const versionEditor = versionCard.querySelector('.version-editor'); + const versionInput = versionEditor.querySelector('.version-value'); + versionInput.value = versionInput.dataset.original ?? ''; + toggleVersionEditMode(versionEditor, false); + return; + } + + if (action === 'save-version') { + const confirmed = await showConfirmPopup('Save version?'); + if (!confirmed) { + return; + } + const version = versionCard.querySelector('.version-value').value.trim(); + await request('PUT', `/admin/api/versions/${appVersionId}/version`, {version}); + await loadVersions(); + await showResultPopup('Version saved.'); + return; + } + if (action === 'edit-summary') { const summaryEditor = versionCard.querySelector('.summary-editor'); toggleSummaryEditMode(summaryEditor, true); diff --git a/src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandServiceTest.java new file mode 100644 index 00000000..a2d95b76 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionCommandServiceTest.java @@ -0,0 +1,144 @@ +package com.devkor.ifive.nadab.domain.admin.application; + +import com.devkor.ifive.nadab.domain.admin.api.dto.request.AdminVersionCreateRequest; +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppPlatform; +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppVersion; +import com.devkor.ifive.nadab.domain.appversion.core.repository.AppVersionRepository; +import com.devkor.ifive.nadab.global.core.response.ErrorCode; +import com.devkor.ifive.nadab.global.exception.BadRequestException; +import com.devkor.ifive.nadab.global.exception.ConflictException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class AdminVersionCommandServiceTest { + + @Mock + AppVersionRepository appVersionRepository; + + AdminVersionCommandService adminVersionCommandService; + + @BeforeEach + void setUp() { + adminVersionCommandService = new AdminVersionCommandService(appVersionRepository); + } + + @Test + void updateVersion_updates_when_new_version_is_greater_than_other_versions() { + AppVersion target = AppVersion.create(AppPlatform.ANDROID, "1.3.0", "summary"); + when(appVersionRepository.findById(1L)).thenReturn(Optional.of(target)); + when(appVersionRepository.existsByPlatformAndVersionAndIdNot(AppPlatform.ANDROID, "1.10.0", 1L)) + .thenReturn(false); + when(appVersionRepository.findByPlatformAndIdNot(AppPlatform.ANDROID, 1L)) + .thenReturn(List.of( + AppVersion.create(AppPlatform.ANDROID, "1.2.0", "old"), + AppVersion.create(AppPlatform.ANDROID, "1.9.0", "old") + )); + + adminVersionCommandService.updateVersion(1L, "1.10.0"); + + assertThat(target.getVersion()).isEqualTo("1.10.0"); + verify(appVersionRepository).flush(); + } + + @Test + void updateVersion_rejects_version_equal_to_highest_other_version() { + AppVersion target = AppVersion.create(AppPlatform.IOS, "1.3.0", "summary"); + when(appVersionRepository.findById(1L)).thenReturn(Optional.of(target)); + when(appVersionRepository.existsByPlatformAndVersionAndIdNot(AppPlatform.IOS, "1.2.0", 1L)) + .thenReturn(false); + when(appVersionRepository.findByPlatformAndIdNot(AppPlatform.IOS, 1L)) + .thenReturn(List.of(AppVersion.create(AppPlatform.IOS, "1.2.0", "old"))); + + assertThatThrownBy(() -> adminVersionCommandService.updateVersion(1L, "1.2.0")) + .isInstanceOfSatisfying(ConflictException.class, e -> + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.APP_VERSION_MUST_BE_GREATER_THAN_EXISTING) + ); + + assertThat(target.getVersion()).isEqualTo("1.3.0"); + verify(appVersionRepository, never()).flush(); + } + + @Test + void updateVersion_rejects_version_lower_than_highest_other_version() { + AppVersion target = AppVersion.create(AppPlatform.IOS, "1.3.0", "summary"); + when(appVersionRepository.findById(1L)).thenReturn(Optional.of(target)); + when(appVersionRepository.existsByPlatformAndVersionAndIdNot(AppPlatform.IOS, "1.1.2", 1L)) + .thenReturn(false); + when(appVersionRepository.findByPlatformAndIdNot(AppPlatform.IOS, 1L)) + .thenReturn(List.of(AppVersion.create(AppPlatform.IOS, "1.2.0", "old"))); + + assertThatThrownBy(() -> adminVersionCommandService.updateVersion(1L, "1.1.2")) + .isInstanceOfSatisfying(ConflictException.class, e -> + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.APP_VERSION_MUST_BE_GREATER_THAN_EXISTING) + ); + + assertThat(target.getVersion()).isEqualTo("1.3.0"); + verify(appVersionRepository, never()).flush(); + } + + @Test + void updateVersion_rejects_duplicate_version_before_comparing_order() { + AppVersion target = AppVersion.create(AppPlatform.ANDROID, "1.3.0", "summary"); + when(appVersionRepository.findById(1L)).thenReturn(Optional.of(target)); + when(appVersionRepository.existsByPlatformAndVersionAndIdNot(AppPlatform.ANDROID, "1.4.0", 1L)) + .thenReturn(true); + + assertThatThrownBy(() -> adminVersionCommandService.updateVersion(1L, "1.4.0")) + .isInstanceOfSatisfying(ConflictException.class, e -> + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.APP_VERSION_ALREADY_EXISTS) + ); + + verify(appVersionRepository, never()).findByPlatformAndIdNot(AppPlatform.ANDROID, 1L); + verify(appVersionRepository, never()).flush(); + } + + @Test + void updateVersion_rejects_invalid_version_format() { + AppVersion target = AppVersion.create(AppPlatform.ANDROID, "1.3.0", "summary"); + when(appVersionRepository.findById(1L)).thenReturn(Optional.of(target)); + when(appVersionRepository.existsByPlatformAndVersionAndIdNot(AppPlatform.ANDROID, "1.4", 1L)) + .thenReturn(false); + + assertThatThrownBy(() -> adminVersionCommandService.updateVersion(1L, "1.4")) + .isInstanceOfSatisfying(BadRequestException.class, e -> + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.APP_VERSION_INVALID_FORMAT) + ); + + verify(appVersionRepository, never()).findByPlatformAndIdNot(AppPlatform.ANDROID, 1L); + verify(appVersionRepository, never()).flush(); + } + + @Test + void createVersion_rejects_version_lower_than_existing_platform_version() { + AdminVersionCreateRequest request = new AdminVersionCreateRequest( + AppPlatform.ANDROID, + "1.1.2", + "summary" + ); + when(appVersionRepository.existsByPlatformAndVersion(AppPlatform.ANDROID, "1.1.2")) + .thenReturn(false); + when(appVersionRepository.findByPlatform(AppPlatform.ANDROID)) + .thenReturn(List.of(AppVersion.create(AppPlatform.ANDROID, "1.2.0", "old"))); + + assertThatThrownBy(() -> adminVersionCommandService.createVersion(request)) + .isInstanceOfSatisfying(ConflictException.class, e -> + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.APP_VERSION_MUST_BE_GREATER_THAN_EXISTING) + ); + + verify(appVersionRepository, never()).findByPlatformAndIsLatestTrue(AppPlatform.ANDROID); + verify(appVersionRepository, never()).saveAndFlush(org.mockito.ArgumentMatchers.any()); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryServiceTest.java new file mode 100644 index 00000000..5ecdc65d --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/admin/application/AdminVersionQueryServiceTest.java @@ -0,0 +1,84 @@ +package com.devkor.ifive.nadab.domain.admin.application; + +import com.devkor.ifive.nadab.domain.admin.api.dto.response.AdminVersionHistoryResponse; +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppPlatform; +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppVersion; +import com.devkor.ifive.nadab.domain.appversion.core.entity.AppVersionItem; +import com.devkor.ifive.nadab.domain.appversion.core.repository.AppVersionItemRepository; +import com.devkor.ifive.nadab.domain.appversion.core.repository.AppVersionRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class AdminVersionQueryServiceTest { + + @Mock + AppVersionRepository appVersionRepository; + + @Mock + AppVersionItemRepository appVersionItemRepository; + + AdminVersionQueryService adminVersionQueryService; + + @BeforeEach + void setUp() { + adminVersionQueryService = new AdminVersionQueryService( + appVersionRepository, + appVersionItemRepository + ); + } + + @Test + void getVersionHistory_returns_all_versions_with_items() { + AppVersion android = appVersion(1L, AppPlatform.ANDROID, "1.2.0", "android summary"); + AppVersion ios = appVersion(2L, AppPlatform.IOS, "1.1.0", "ios summary"); + AppVersionItem item = AppVersionItem.create(android, "Title", "Description", 1); + ReflectionTestUtils.setField(item, "id", 10L); + + when(appVersionRepository.findAllByOrderByCreatedAtDescIdDesc()) + .thenReturn(List.of(android, ios)); + when(appVersionItemRepository.findByAppVersionIdInOrderByDisplayOrderAsc(List.of(1L, 2L))) + .thenReturn(List.of(item)); + + AdminVersionHistoryResponse response = adminVersionQueryService.getVersionHistory(null); + + assertThat(response.versions()).hasSize(2); + assertThat(response.versions().get(0).id()).isEqualTo(1L); + assertThat(response.versions().get(0).items()).hasSize(1); + assertThat(response.versions().get(0).items().get(0).title()).isEqualTo("Title"); + assertThat(response.versions().get(1).id()).isEqualTo(2L); + assertThat(response.versions().get(1).items()).isEmpty(); + } + + @Test + void getVersionHistory_uses_platform_filter_when_platform_exists() { + AppVersion ios = appVersion(2L, AppPlatform.IOS, "1.1.0", "ios summary"); + when(appVersionRepository.findByPlatformOrderByCreatedAtDescIdDesc(AppPlatform.IOS)) + .thenReturn(List.of(ios)); + when(appVersionItemRepository.findByAppVersionIdInOrderByDisplayOrderAsc(List.of(2L))) + .thenReturn(List.of()); + + AdminVersionHistoryResponse response = adminVersionQueryService.getVersionHistory(AppPlatform.IOS); + + assertThat(response.versions()).hasSize(1); + assertThat(response.versions().get(0).platform()).isEqualTo(AppPlatform.IOS); + verify(appVersionRepository, never()).findAllByOrderByCreatedAtDescIdDesc(); + } + + private AppVersion appVersion(Long id, AppPlatform platform, String version, String summary) { + AppVersion appVersion = AppVersion.create(platform, version, summary); + ReflectionTestUtils.setField(appVersion, "id", id); + return appVersion; + } +} From 09c2cb34b03650eb453aadea682441732d9ed71e Mon Sep 17 00:00:00 2001 From: 1Seob Date: Thu, 9 Jul 2026 01:44:09 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat(report):=20=EB=A6=AC=ED=8F=AC=ED=8A=B8?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EA=B7=B8=EC=97=90=20LLM=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EC=82=AC=EC=9A=A9=EB=9F=89=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D=20=EC=B6=94=EA=B0=80=20(#190)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(report): 리포트 생성 로그에 토큰 사용량 필드 추가 report_generation_logs에 input_tokens, output_tokens, total_tokens 컬럼을 추가하고 ReportGenerationLog의 토큰 기록 경로를 확장함. ReportGenerationLogService와 ReportGenerationLogRecorder에서 별도 트랜잭션 기반 토큰 사용량 기록을 지원하며, nullable usage 저장 케이스와 repository 매핑 테스트를 보강함 * feat(ai): Spring AI 토큰 사용량 추출 모델 추가 Spring AI ChatResponse의 Usage를 내부 LlmTokenUsage로 변환하는 공통 추출기를 추가하고, LLM 결과와 토큰 사용량을 함께 전달하기 위한 LlmGenerationResult를 추가함 * feat(report): 일간 리포트 토큰 사용량 기록 DailyReportLlmClient가 Spring AI ChatResponse에서 본문과 Usage를 함께 추출하도록 변경하고, DailyReportService에서 생성 로그에 input/output/total token 사용량을 기록함 * feat(report): 리포트 생성 로그에 thinking token 기록 report_generation_logs에 thinking_tokens 컬럼을 추가하고 Spring AI GoogleGenAiUsage의 thoughtsTokenCount를 LlmTokenUsage로 추출하도록 확장함. 주간 리포트 생성과 rewrite usage를 합산해 기록 * feat(report): 월간 리포트 토큰 사용량 기록 추가 MonthlyReportLlmClient와 MonthlyReportLlmClientV2가 ChatResponse 기반으로 LLM 응답 본문과 토큰 사용량을 함께 반환하도록 변경하고, 월간 리포트 생성 로그에 input_tokens, output_tokens, total_tokens, thinking_tokens를 기록하도록 추가 * feat(report): 유형 리포트 토큰 사용량 기록 유형 리포트의 Evidence Cards, Pattern Extraction, Type Selection, Content Generation 단계에서 ChatResponse 기반 토큰 사용량을 추출하고 각 generation log에 기록하도록 추가 * test(report): 리포트 생성 로그 토큰 기록 검증 보강 유형 리포트의 단계별 LLM 토큰 사용량 기록 순서를 검증하고, 월간 V2 listener 테스트에서 토큰 기록 후 성공 처리 순서를 확인하도록 보강 --- .../application/DailyReportService.java | 14 +- .../infra/DailyReportLlmClient.java | 29 ++- .../MonthlyReportGenerationListener.java | 13 +- .../MonthlyReportGenerationListenerV2.java | 13 +- .../infra/MonthlyReportLlmClient.java | 74 +++++-- .../infra/MonthlyReportLlmClientV2.java | 47 +++-- .../ReportGenerationLogRecorder.java | 18 ++ .../ReportGenerationLogService.java | 12 ++ .../core/entity/ReportGenerationLog.java | 24 +++ .../TypeReportGenerationListener.java | 31 ++- .../EvidenceCardGenerationService.java | 12 +- .../service/PatternExtractionService.java | 9 +- .../TypeReportContentGenerationService.java | 16 +- .../core/service/TypeSelectionService.java | 9 +- .../infra/TypeEvidenceCardLlmClient.java | 23 ++- .../infra/TypePatternExtractLlmClient.java | 23 ++- .../typereport/infra/TypeReportLlmClient.java | 69 +++++-- .../typereport/infra/TypeSelectLlmClient.java | 23 ++- .../WeeklyReportGenerationListener.java | 14 +- .../infra/WeeklyReportLlmClient.java | 74 +++++-- .../global/infra/llm/LlmGenerationResult.java | 13 ++ .../nadab/global/infra/llm/LlmTokenUsage.java | 39 ++++ .../infra/llm/LlmTokenUsageExtractor.java | 43 ++++ ..._token_usage_to_report_generation_logs.sql | 4 + ...nking_tokens_to_report_generation_logs.sql | 2 + .../application/DailyReportServiceTest.java | 194 ++++++++++++++++++ .../infra/DailyReportLlmClientTest.java | 107 ++++++++++ ...MonthlyReportGenerationListenerV2Test.java | 15 +- .../ReportGenerationLogRepositoryTest.java | 21 ++ .../ReportGenerationLogServiceTest.java | 32 +++ .../TypeReportGenerationListenerTest.java | 174 ++++++++++++++++ .../WeeklyReportGenerationListenerTest.java | 94 +++++++++ .../infra/WeeklyReportLlmClientTest.java | 141 +++++++++++++ .../infra/llm/LlmTokenUsageExtractorTest.java | 149 ++++++++++++++ 34 files changed, 1446 insertions(+), 129 deletions(-) create mode 100644 src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmGenerationResult.java create mode 100644 src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsage.java create mode 100644 src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractor.java create mode 100644 src/main/resources/db/migration/V20260708_1200__IS_add_token_usage_to_report_generation_logs.sql create mode 100644 src/main/resources/db/migration/V20260708_1500__IS_add_thinking_tokens_to_report_generation_logs.sql create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportServiceTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClientTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListenerTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListenerTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClientTest.java create mode 100644 src/test/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractorTest.java diff --git a/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportService.java b/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportService.java index 78d133a2..13f5d561 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportService.java @@ -28,7 +28,9 @@ import com.devkor.ifive.nadab.global.exception.BadRequestException; import com.devkor.ifive.nadab.global.exception.NotFoundException; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import com.devkor.ifive.nadab.global.shared.util.TodayDateTimeProvider; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -104,7 +106,17 @@ public CreateDailyReportResponse generateDailyReport(Long userId, DailyReportReq AiDailyReportResultDto dto; try { - dto = dailyReportLlmClient.generate(question.getQuestionText(), answerEntry); + LlmGenerationResult generationResult = + dailyReportLlmClient.generate(question.getQuestionText(), answerEntry); + dto = generationResult.content(); + LlmTokenUsage tokenUsage = generationResult.tokenUsage(); + reportGenerationLogRecorder.recordTokenUsage( + generationLogId, + tokenUsage.inputTokens(), + tokenUsage.outputTokens(), + tokenUsage.totalTokens(), + tokenUsage.thinkingTokens() + ); reportGenerationLogRecorder.succeed(generationLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(generationLogId, e); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClient.java b/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClient.java index 5f3d06d3..9b72f962 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClient.java @@ -10,12 +10,16 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.content.Media; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; @@ -36,7 +40,7 @@ public class DailyReportLlmClient { private final LlmProvider provider = LlmProvider.OPENAI; - public AiDailyReportResultDto generate(String question, AnswerEntry answerEntry) { + public LlmGenerationResult generate(String question, AnswerEntry answerEntry) { String answer = answerEntry.getContent(); @@ -59,12 +63,15 @@ public AiDailyReportResultDto generate(String question, AnswerEntry answerEntry) UserMessage userMessage = buildUserMessage(prompt, withImagePrompt,answerEntry); String content; + LlmTokenUsage tokenUsage; try { - content = chatClient.prompt() + ChatResponse response = chatClient.prompt() .messages(userMessage) .options(options) .call() - .content(); + .chatResponse(); + content = extractContent(response); + tokenUsage = LlmTokenUsageExtractor.extract(response); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } @@ -85,9 +92,12 @@ public AiDailyReportResultDto generate(String question, AnswerEntry answerEntry) throw new AiResponseParseException(ErrorCode.AI_RESPONSE_FORMAT_INVALID); } - return new AiDailyReportResultDto( - message, - emotion + return new LlmGenerationResult<>( + new AiDailyReportResultDto( + message, + emotion + ), + tokenUsage ); } catch (Exception e) { @@ -96,6 +106,13 @@ public AiDailyReportResultDto generate(String question, AnswerEntry answerEntry) } } + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } + private UserMessage buildUserMessage(String prompt, String withImagePrompt, AnswerEntry answerEntry) { String imageKey = answerEntry.getImageKey(); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListener.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListener.java index 1871b5f8..9618f381 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListener.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListener.java @@ -12,7 +12,9 @@ import com.devkor.ifive.nadab.domain.reportlog.core.entity.ReportGenerationType; import com.devkor.ifive.nadab.domain.weeklyreport.application.helper.WeeklyEntriesAssembler; import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.DailyEntryDto; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import com.devkor.ifive.nadab.global.shared.reportcontent.AiReportResultDto; import com.devkor.ifive.nadab.global.shared.util.MonthRangeCalculator; import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; @@ -66,12 +68,21 @@ public void handle(MonthlyReportGenerationRequestedEventDto event) { ); try { // 트랜잭션 밖(백그라운드)에서 LLM 호출 - dto = monthlyReportLlmClient.generate( + LlmGenerationResult generationResult = monthlyReportLlmClient.generate( range.monthStartDate().toString(), range.monthEndDate().toString(), weeklySummaries, representativeEntries ); + dto = generationResult.content(); + LlmTokenUsage tokenUsage = generationResult.tokenUsage(); + reportGenerationLogRecorder.recordTokenUsage( + generationLogId, + tokenUsage.inputTokens(), + tokenUsage.outputTokens(), + tokenUsage.totalTokens(), + tokenUsage.thinkingTokens() + ); reportGenerationLogRecorder.succeed(generationLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(generationLogId, e); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java index 4cd0af15..ca1d92ea 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2.java @@ -29,7 +29,9 @@ import com.devkor.ifive.nadab.domain.typereport.core.content.TypeEmotionStatsContent; import com.devkor.ifive.nadab.domain.weeklyreport.application.helper.WeeklyEntriesAssembler; import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.DailyEntryDto; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import com.devkor.ifive.nadab.global.shared.util.MonthRangeCalculator; import com.devkor.ifive.nadab.global.shared.util.dto.MonthRangeDto; import lombok.RequiredArgsConstructor; @@ -168,7 +170,7 @@ public void handle(MonthlyReportGenerationRequestedEventDtoV2 event) { ); try { // 트랜잭션 밖(백그라운드)에서 LLM 호출 - dto = monthlyReportLlmClientV2.generate( + LlmGenerationResult generationResult = monthlyReportLlmClientV2.generate( range.monthStartDate().toString(), range.monthEndDate().toString(), weeklySummaries, @@ -176,6 +178,15 @@ public void handle(MonthlyReportGenerationRequestedEventDtoV2 event) { emotionStats, comparisonInput ); + dto = generationResult.content(); + LlmTokenUsage tokenUsage = generationResult.tokenUsage(); + reportGenerationLogRecorder.recordTokenUsage( + generationLogId, + tokenUsage.inputTokens(), + tokenUsage.outputTokens(), + tokenUsage.totalTokens(), + tokenUsage.thinkingTokens() + ); reportGenerationLogRecorder.succeed(generationLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(generationLogId, e); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClient.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClient.java index f2c44c90..b7c20ae9 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClient.java @@ -5,8 +5,11 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.devkor.ifive.nadab.global.shared.reportcontent.*; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -14,6 +17,7 @@ import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.GoogleGenAiChatOptions; import org.springframework.ai.openai.OpenAiChatOptions; @@ -47,7 +51,7 @@ public class MonthlyReportLlmClient { private static final int MIN_SUMMARY = 8; private static final int MAX_SUMMARY = 30; - public AiReportResultDto generate( + public LlmGenerationResult generate( String monthStartDate, String monthEndDate, String weeklySummaries, String representativeEntries) { String prompt = monthlyReportPromptLoader.loadV1Prompt() .replace("{monthStartDate}", monthStartDate) @@ -57,11 +61,13 @@ public AiReportResultDto generate( ChatClient client = llmRouter.route(provider); - String content = switch (provider) { + LlmGenerationResult generationResult = switch (provider) { case OPENAI -> callOpenAi(client, prompt); case CLAUDE -> callClaude(client, prompt); case GEMINI -> callGemini(client, prompt); }; + String content = generationResult.content(); + LlmTokenUsage tokenUsage = generationResult.tokenUsage(); if (content == null || content.trim().isEmpty()) { throw new AiServiceUnavailableException(ErrorCode.AI_NO_RESPONSE); @@ -97,11 +103,14 @@ public AiReportResultDto generate( throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_AI_JSON_MISSING_FIELDS); } - AiReportResultDto dto = enforceLength(new AiReportResultDto(reportContent, discovered, improve)); + LlmGenerationResult lengthResult = + enforceLength(new AiReportResultDto(reportContent, discovered, improve)); + AiReportResultDto dto = lengthResult.content(); + tokenUsage = tokenUsage.plus(lengthResult.tokenUsage()); validateLength(dto); - return dto; + return new LlmGenerationResult<>(dto, tokenUsage); } catch (AiResponseParseException e) { throw e; @@ -110,7 +119,7 @@ public AiReportResultDto generate( } } - private String callOpenAi(ChatClient client, String prompt) { + private LlmGenerationResult callOpenAi(ChatClient client, String prompt) { OpenAiChatOptions options = OpenAiChatOptions.builder() .model(OpenAiApi.ChatModel.GPT_5_MINI) .reasoningEffort("medium") @@ -118,34 +127,36 @@ private String callOpenAi(ChatClient client, String prompt) { .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private String callClaude(ChatClient client, String prompt) { + private LlmGenerationResult callClaude(ChatClient client, String prompt) { AnthropicChatOptions options = AnthropicChatOptions.builder() .model(AnthropicApi.ChatModel.CLAUDE_3_HAIKU) .temperature(0.3) .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private String callGemini(ChatClient client, String prompt) { + private LlmGenerationResult callGemini(ChatClient client, String prompt) { GoogleGenAiChatOptions options = GoogleGenAiChatOptions.builder() .model(GoogleGenAiChatModel.ChatModel.GEMINI_2_5_FLASH) .responseMimeType("application/json") @@ -153,17 +164,18 @@ private String callGemini(ChatClient client, String prompt) { .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private AiReportResultDto enforceLength(AiReportResultDto dto) { + private LlmGenerationResult enforceLength(AiReportResultDto dto) { ReportContent c = dto.content(); int dLen = dto.discovered().length(); @@ -172,15 +184,24 @@ private AiReportResultDto enforceLength(AiReportResultDto dto) { boolean badD = dLen < MIN_DISCOVERED || dLen > MAX_DISCOVERED; boolean badI = iLen < MIN_IMPROVE || iLen > MAX_IMPROVE; - if (!badD && !badI) return dto; + if (!badD && !badI) return new LlmGenerationResult<>(dto, LlmTokenUsage.empty()); ChatClient rewriteClient = llmRouter.route(REWRITE_PROVIDER); StyledText d = c.discovered(); StyledText i = c.improve(); + LlmTokenUsage tokenUsage = LlmTokenUsage.empty(); - if (badD) d = rewriteStyled(rewriteClient, d, true); - if (badI) i = rewriteStyled(rewriteClient, i, false); + if (badD) { + LlmGenerationResult rewriteResult = rewriteStyled(rewriteClient, d, true); + d = rewriteResult.content(); + tokenUsage = tokenUsage.plus(rewriteResult.tokenUsage()); + } + if (badI) { + LlmGenerationResult rewriteResult = rewriteStyled(rewriteClient, i, false); + i = rewriteResult.content(); + tokenUsage = tokenUsage.plus(rewriteResult.tokenUsage()); + } ReportContent newContent = new ReportContent(c.summary(), d, i); String newD = newContent.discovered().plainText(); @@ -193,10 +214,10 @@ private AiReportResultDto enforceLength(AiReportResultDto dto) { throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_REWRITE_FORMAT_INVALID); } - return new AiReportResultDto(newContent, newD, newI); + return new LlmGenerationResult<>(new AiReportResultDto(newContent, newD, newI), tokenUsage); } - private StyledText rewriteStyled(ChatClient client, StyledText in, boolean isDiscovered) { + private LlmGenerationResult rewriteStyled(ChatClient client, StyledText in, boolean isDiscovered) { int min = isDiscovered ? MIN_DISCOVERED : MIN_IMPROVE; int max = isDiscovered ? MAX_DISCOVERED : MAX_IMPROVE; int maxHl = isDiscovered ? MAX_HL_DISCOVERED : MAX_HL_IMPROVE; @@ -229,19 +250,21 @@ private StyledText rewriteStyled(ChatClient client, StyledText in, boolean isDis .temperature(0.0) .build(); - String out; + ChatResponse response; try { - out = client.prompt().user(prompt).options(options).call().content(); + response = client.prompt().user(prompt).options(options).call().chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_REWRITE_NO_RESPONSE, e); } + String out = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (out == null || out.isBlank()) { throw new AiServiceUnavailableException(ErrorCode.AI_REWRITE_NO_RESPONSE); } try { - return objectMapper.readValue(out, StyledText.class); + return new LlmGenerationResult<>(objectMapper.readValue(out, StyledText.class), tokenUsage); } catch (Exception e) { throw new AiResponseParseException(ErrorCode.MONTHLY_REPORT_REWRITE_JSON_MAPPING_FAILED); } @@ -253,6 +276,13 @@ private StyledText rewriteStyled(ChatClient client, StyledText in, boolean isDis } } + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } + private boolean isBlank(String s) { return s == null || s.trim().isEmpty(); } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java index 4210aeb8..76c3c7ea 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/monthlyreport/infra/MonthlyReportLlmClientV2.java @@ -11,8 +11,11 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.devkor.ifive.nadab.global.shared.reportcontent.*; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -20,6 +23,7 @@ import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.GoogleGenAiChatOptions; import org.springframework.ai.openai.OpenAiChatOptions; @@ -59,7 +63,7 @@ public class MonthlyReportLlmClientV2 { private static final int MAX_COMPARISON_EMOTION = 150; private static final int MAX_COMPARISON_BOLD_SEGMENTS = 4; - public AiMonthlyReportResultDto generate( + public LlmGenerationResult generate( String monthStartDate, String monthEndDate, String weeklySummaries, @@ -77,11 +81,13 @@ public AiMonthlyReportResultDto generate( ChatClient client = llmRouter.route(provider); - String content = switch (provider) { + LlmGenerationResult generationResult = switch (provider) { case OPENAI -> callOpenAi(client, prompt); case CLAUDE -> callClaude(client, prompt); case GEMINI -> callGemini(client, prompt); }; + String content = generationResult.content(); + LlmTokenUsage tokenUsage = generationResult.tokenUsage(); if (content == null || content.trim().isEmpty()) { throw new AiServiceUnavailableException(ErrorCode.AI_NO_RESPONSE); @@ -142,9 +148,12 @@ public AiMonthlyReportResultDto generate( discoveredStyled, commentStyled ); - return new AiMonthlyReportResultDto( - normalizedContent, - new TypeTextContent(styledText) + return new LlmGenerationResult<>( + new AiMonthlyReportResultDto( + normalizedContent, + new TypeTextContent(styledText) + ), + tokenUsage ); } catch (AiResponseParseException e) { @@ -188,7 +197,7 @@ private String serializeComparisonInput(MonthlyReportComparisonInputDto comparis } } - private String callOpenAi(ChatClient client, String prompt) { + private LlmGenerationResult callOpenAi(ChatClient client, String prompt) { OpenAiChatOptions options = OpenAiChatOptions.builder() .model(OpenAiApi.ChatModel.GPT_5_MINI) .reasoningEffort("medium") @@ -196,34 +205,36 @@ private String callOpenAi(ChatClient client, String prompt) { .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private String callClaude(ChatClient client, String prompt) { + private LlmGenerationResult callClaude(ChatClient client, String prompt) { AnthropicChatOptions options = AnthropicChatOptions.builder() .model(AnthropicApi.ChatModel.CLAUDE_3_HAIKU) .temperature(0.3) .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private String callGemini(ChatClient client, String prompt) { + private LlmGenerationResult callGemini(ChatClient client, String prompt) { GoogleGenAiChatOptions options = GoogleGenAiChatOptions.builder() .model(GoogleGenAiChatModel.ChatModel.GEMINI_2_5_FLASH) .responseMimeType("application/json") @@ -231,11 +242,12 @@ private String callGemini(ChatClient client, String prompt) { .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } @@ -334,6 +346,13 @@ private StyledText rewriteStyled(ChatClient client, StyledText in, boolean isDis */ + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } + private boolean isBlank(String s) { return s == null || s.trim().isEmpty(); } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogRecorder.java b/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogRecorder.java index f511328b..8c0286fe 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogRecorder.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogRecorder.java @@ -52,6 +52,24 @@ public void succeed(Long logId) { } } + public void recordTokenUsage( + Long logId, + Long inputTokens, + Long outputTokens, + Long totalTokens, + Long thinkingTokens + ) { + if (logId == null) { + return; + } + + try { + reportGenerationLogService.recordTokenUsage(logId, inputTokens, outputTokens, totalTokens, thinkingTokens); + } catch (Exception e) { + log.warn("[REPORT_GENERATION_LOG][TOKEN_USAGE_FAILED] logId={}", logId, e); + } + } + public void fail(Long logId, Exception exception) { if (logId == null) { return; diff --git a/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogService.java b/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogService.java index b1a8eeda..0c1107c2 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogService.java @@ -51,6 +51,18 @@ public void succeed(Long logId) { .ifPresent(ReportGenerationLog::succeed); } + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void recordTokenUsage( + Long logId, + Long inputTokens, + Long outputTokens, + Long totalTokens, + Long thinkingTokens + ) { + reportGenerationLogRepository.findById(logId) + .ifPresent(log -> log.recordTokenUsage(inputTokens, outputTokens, totalTokens, thinkingTokens)); + } + @Transactional(propagation = Propagation.REQUIRES_NEW) public void fail(Long logId, Exception exception) { Integer externalHttpStatus = extractExternalHttpStatus(exception); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/reportlog/core/entity/ReportGenerationLog.java b/src/main/java/com/devkor/ifive/nadab/domain/reportlog/core/entity/ReportGenerationLog.java index 36efa075..df5a3069 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/reportlog/core/entity/ReportGenerationLog.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/reportlog/core/entity/ReportGenerationLog.java @@ -76,6 +76,18 @@ public class ReportGenerationLog extends CreatableEntity { @Column(name = "elapsed_ms") private Long elapsedMs; + @Column(name = "input_tokens") + private Long inputTokens; + + @Column(name = "output_tokens") + private Long outputTokens; + + @Column(name = "total_tokens") + private Long totalTokens; + + @Column(name = "thinking_tokens") + private Long thinkingTokens; + @Column(name = "started_at", nullable = false) private OffsetDateTime startedAt; @@ -107,6 +119,18 @@ public void succeed() { finish(); } + public void recordTokenUsage( + Long inputTokens, + Long outputTokens, + Long totalTokens, + Long thinkingTokens + ) { + this.inputTokens = inputTokens; + this.outputTokens = outputTokens; + this.totalTokens = totalTokens; + this.thinkingTokens = thinkingTokens; + } + public void fail( String errorCode, String exceptionClass, diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListener.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListener.java index 75400229..3d278ae0 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListener.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListener.java @@ -24,7 +24,9 @@ import com.devkor.ifive.nadab.domain.typereport.core.service.TypeSelectionService; import com.devkor.ifive.nadab.domain.user.core.entity.InterestCode; import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.DailyEntryDto; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; @@ -125,7 +127,10 @@ public void handle(TypeReportGenerationRequestedEventDto event) { TYPE_REPORT_OPENAI_MODEL ); try { - cards = evidenceCardGenerationService.generate(recentEntries); + LlmGenerationResult> generationResult = + evidenceCardGenerationService.generate(recentEntries); + cards = generationResult.content(); + recordTokenUsage(evidenceLogId, generationResult.tokenUsage()); reportGenerationLogRecorder.succeed(evidenceLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(evidenceLogId, e); @@ -146,7 +151,10 @@ public void handle(TypeReportGenerationRequestedEventDto event) { TYPE_REPORT_OPENAI_MODEL ); try { - patterns = patternExtractionService.extract(cards); + LlmGenerationResult generationResult = + patternExtractionService.extract(cards); + patterns = generationResult.content(); + recordTokenUsage(patternLogId, generationResult.tokenUsage()); reportGenerationLogRecorder.succeed(patternLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(patternLogId, e); @@ -179,7 +187,10 @@ public void handle(TypeReportGenerationRequestedEventDto event) { TYPE_REPORT_OPENAI_MODEL ); try { - selection = typeSelectionService.select(candidates, patterns); + LlmGenerationResult generationResult = + typeSelectionService.select(candidates, patterns); + selection = generationResult.content(); + recordTokenUsage(selectionLogId, generationResult.tokenUsage()); reportGenerationLogRecorder.succeed(selectionLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(selectionLogId, e); @@ -213,13 +224,15 @@ public void handle(TypeReportGenerationRequestedEventDto event) { TYPE_REPORT_GEMINI_MODEL ); try { - content = typeReportContentGenerationService.generate( + LlmGenerationResult generationResult = typeReportContentGenerationService.generate( selectedType, patterns, cards, emotionStats, selection.analysisTypeCode() ); + content = generationResult.content(); + recordTokenUsage(contentLogId, generationResult.tokenUsage()); reportGenerationLogRecorder.succeed(contentLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(contentLogId, e); @@ -282,4 +295,14 @@ private String getCategoryNameKorean(InterestCode code) { case VALUES -> "가치관"; }; } + + private void recordTokenUsage(Long logId, LlmTokenUsage tokenUsage) { + reportGenerationLogRecorder.recordTokenUsage( + logId, + tokenUsage.inputTokens(), + tokenUsage.outputTokens(), + tokenUsage.totalTokens(), + tokenUsage.thinkingTokens() + ); + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/EvidenceCardGenerationService.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/EvidenceCardGenerationService.java index f3bcf4ca..acb4504e 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/EvidenceCardGenerationService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/EvidenceCardGenerationService.java @@ -7,6 +7,8 @@ import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.DailyEntryDto; import com.devkor.ifive.nadab.global.core.response.ErrorCode; import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,17 +23,17 @@ public class EvidenceCardGenerationService { private final TypeEvidenceCardLlmClient llmClient; - public List generate(List recentEntries) { + public LlmGenerationResult> generate(List recentEntries) { List withIds = EvidenceEntriesAssembler.attachIds(recentEntries); - if (withIds.isEmpty()) return List.of(); + if (withIds.isEmpty()) return new LlmGenerationResult<>(List.of(), LlmTokenUsage.empty()); String entriesText = EvidenceEntriesAssembler.assembleForPrompt(withIds); - List> raw = llmClient.generateRawCardsJsonArray(entriesText); + LlmGenerationResult>> rawResult = llmClient.generateRawCardsJsonArray(entriesText); - List cards = mapAndValidate(withIds, raw); + List cards = mapAndValidate(withIds, rawResult.content()); - return cards; + return new LlmGenerationResult<>(cards, rawResult.tokenUsage()); } private List mapAndValidate(List withIds, List> raw) { diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/PatternExtractionService.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/PatternExtractionService.java index 919285d4..a00a42c1 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/PatternExtractionService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/PatternExtractionService.java @@ -6,6 +6,7 @@ import com.devkor.ifive.nadab.domain.typereport.infra.TypePatternExtractLlmClient; import com.devkor.ifive.nadab.global.core.response.ErrorCode; import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.fasterxml.jackson.databind.JsonNode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,7 +27,7 @@ public class PatternExtractionService { private final TypePatternExtractLlmClient llmClient; - public PatternExtractionResultDto extract(List cards) { + public LlmGenerationResult extract(List cards) { if (cards == null || cards.isEmpty()) { throw new AiResponseParseException(ErrorCode.PATTERN_RESULT_EMPTY); } @@ -37,12 +38,12 @@ public PatternExtractionResultDto extract(List cards) { .collect(Collectors.toSet()); String cardsText = EvidenceCardsAssembler.assembleForPrompt(cards); - JsonNode raw = llmClient.extractPatternsRawJson(cardsText); + LlmGenerationResult rawResult = llmClient.extractPatternsRawJson(cardsText); - PatternExtractionResultDto dto = toDto(raw); + PatternExtractionResultDto dto = toDto(rawResult.content()); validate(dto, validIds); - return dto; + return new LlmGenerationResult<>(dto, rawResult.tokenUsage()); } private PatternExtractionResultDto toDto(JsonNode raw) { diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeReportContentGenerationService.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeReportContentGenerationService.java index 803b49ea..54089374 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeReportContentGenerationService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeReportContentGenerationService.java @@ -11,6 +11,8 @@ import com.devkor.ifive.nadab.domain.typereport.infra.TypeReportLlmClient; import com.devkor.ifive.nadab.global.core.response.ErrorCode; import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.JsonNode; import lombok.RequiredArgsConstructor; @@ -36,7 +38,7 @@ public class TypeReportContentGenerationService { private final TypeReportLlmClient llmClient; private final ObjectMapper objectMapper; - public TypeReportContentDto generate( + public LlmGenerationResult generate( AnalysisTypeCandidateDto selectedType, PatternExtractionResultDto patterns, List allCards, @@ -56,19 +58,23 @@ public TypeReportContentDto generate( String evidenceCardsText = TypeReportInputAssembler.assembleEvidenceCards(representative); String emotionStatsText = TypeReportInputAssembler.assembleEmotionStats(emotionStats); - JsonNode raw = llmClient.generateRaw(selectedTypeText, patternsText, evidenceCardsText, emotionStatsText); + LlmGenerationResult rawResult = + llmClient.generateRaw(selectedTypeText, patternsText, evidenceCardsText, emotionStatsText); + JsonNode raw = rawResult.content(); + LlmTokenUsage tokenUsage = rawResult.tokenUsage(); // 1차 파싱/검증 try { TypeReportContentDto dto = toDto(raw); validate(dto, expectedAnalysisTypeCode); - return dto; + return new LlmGenerationResult<>(dto, tokenUsage); } catch (AiResponseParseException e) { // 리페어 1회 - JsonNode repaired = llmClient.rewriteOnly(raw); + LlmGenerationResult rewriteResult = llmClient.rewriteOnly(raw); + JsonNode repaired = rewriteResult.content(); TypeReportContentDto dto2 = toDto(repaired); validate(dto2, expectedAnalysisTypeCode); - return dto2; + return new LlmGenerationResult<>(dto2, tokenUsage.plus(rewriteResult.tokenUsage())); } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeSelectionService.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeSelectionService.java index 6db4c50d..29c4c4d5 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeSelectionService.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/core/service/TypeSelectionService.java @@ -7,6 +7,7 @@ import com.devkor.ifive.nadab.domain.typereport.infra.TypeSelectLlmClient; import com.devkor.ifive.nadab.global.core.response.ErrorCode; import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.fasterxml.jackson.databind.JsonNode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,7 +27,7 @@ public class TypeSelectionService { private final TypeSelectLlmClient llmClient; - public TypeSelectionResultDto select( + public LlmGenerationResult select( List candidates, PatternExtractionResultDto patternResult ) { @@ -47,12 +48,12 @@ public TypeSelectionResultDto select( String candidatesText = TypeSelectionInputAssembler.assembleCandidates(candidates); String patternsText = TypeSelectionInputAssembler.assemblePatterns(patternResult); - JsonNode raw = llmClient.selectTypeRawJson(candidatesText, patternsText); + LlmGenerationResult rawResult = llmClient.selectTypeRawJson(candidatesText, patternsText); - TypeSelectionResultDto dto = toDto(raw); + TypeSelectionResultDto dto = toDto(rawResult.content()); validate(dto, candidateCodes, validEvidenceIds); - return dto; + return new LlmGenerationResult<>(dto, rawResult.tokenUsage()); } private TypeSelectionResultDto toDto(JsonNode raw) { diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeEvidenceCardLlmClient.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeEvidenceCardLlmClient.java index 3df6a0a9..ac70333f 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeEvidenceCardLlmClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeEvidenceCardLlmClient.java @@ -5,12 +5,16 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.stereotype.Component; @@ -28,25 +32,27 @@ public class TypeEvidenceCardLlmClient { private final LlmProvider provider = LlmProvider.OPENAI; - public List> generateRawCardsJsonArray(String entriesText) { + public LlmGenerationResult>> generateRawCardsJsonArray(String entriesText) { String prompt = promptLoader.loadPrompt() .replace("{entries}", entriesText); ChatClient client = llmRouter.route(provider); - String content; + ChatResponse response; try { - content = client.prompt() + response = client.prompt() .user(prompt) .options(OpenAiChatOptions.builder() .model(OpenAiApi.ChatModel.GPT_4_O_MINI) .temperature(0.0) .build()) .call() - .content(); + .chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_EVIDENCE_CARD_NO_RESPONSE, e); } + String content = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (content == null || content.trim().isEmpty()) { throw new AiServiceUnavailableException(ErrorCode.AI_EVIDENCE_CARD_NO_RESPONSE); @@ -54,7 +60,7 @@ public List> generateRawCardsJsonArray(String entriesText) { try { // JSON 배열 파싱: [{"id":"D1","card":"..."}...] - return objectMapper.readValue(content, new TypeReference<>() {}); + return new LlmGenerationResult<>(objectMapper.readValue(content, new TypeReference<>() {}), tokenUsage); } catch (AiResponseParseException e) { throw e; } catch (Exception e) { @@ -62,4 +68,11 @@ public List> generateRawCardsJsonArray(String entriesText) { throw new AiResponseParseException(ErrorCode.AI_RESPONSE_PARSE_FAILED); } } + + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypePatternExtractLlmClient.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypePatternExtractLlmClient.java index 625b9dee..9d59c986 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypePatternExtractLlmClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypePatternExtractLlmClient.java @@ -5,12 +5,16 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.stereotype.Component; @@ -25,7 +29,7 @@ public class TypePatternExtractLlmClient { private final LlmProvider provider = LlmProvider.OPENAI; - public JsonNode extractPatternsRawJson(String cardsText) { + public LlmGenerationResult extractPatternsRawJson(String cardsText) { String prompt = promptLoader.loadPrompt().replace("{cards}", cardsText); ChatClient client = llmRouter.route(provider); @@ -35,23 +39,25 @@ public JsonNode extractPatternsRawJson(String cardsText) { .temperature(0.0) .build(); - String content; + ChatResponse response; try { - content = client.prompt() + response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_PATTERN_EXTRACT_NO_RESPONSE, e); } + String content = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (content == null || content.trim().isEmpty()) { throw new AiServiceUnavailableException(ErrorCode.AI_PATTERN_EXTRACT_NO_RESPONSE); } try { - return objectMapper.readTree(content); + return new LlmGenerationResult<>(objectMapper.readTree(content), tokenUsage); } catch (AiResponseParseException e) { throw e; } catch (Exception e) { @@ -59,4 +65,11 @@ public JsonNode extractPatternsRawJson(String cardsText) { throw new AiResponseParseException(ErrorCode.AI_RESPONSE_PARSE_FAILED); } } + + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeReportLlmClient.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeReportLlmClient.java index 2d3f37b9..8c8009a4 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeReportLlmClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeReportLlmClient.java @@ -5,8 +5,11 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.devkor.ifive.nadab.global.shared.reportcontent.Mark; import com.devkor.ifive.nadab.global.shared.reportcontent.Segment; import com.devkor.ifive.nadab.global.shared.reportcontent.StyledText; @@ -20,6 +23,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.GoogleGenAiChatOptions; import org.springframework.stereotype.Component; @@ -56,7 +60,7 @@ public class TypeReportLlmClient { "패턴", "분석", "데이터", "기록", "습관", "장점", "단점", "모습", "결국", "보여집니다", "확인됩니다" }; - public JsonNode generateRaw(String selectedType, String patterns, String evidenceCards, String emotionStats) { + public LlmGenerationResult generateRaw(String selectedType, String patterns, String evidenceCards, String emotionStats) { if (blank(selectedType) || blank(patterns) || blank(evidenceCards) || blank(emotionStats)) { throw new AiResponseParseException(ErrorCode.TYPE_REPORT_GENERATE_INPUT_EMPTY); } @@ -75,16 +79,18 @@ public JsonNode generateRaw(String selectedType, String patterns, String evidenc .temperature(0.0) .build(); - String content; + ChatResponse response; try { - content = client.prompt() + response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } + String content = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (content == null || content.trim().isEmpty()) { throw new AiServiceUnavailableException(ErrorCode.AI_NO_RESPONSE); @@ -95,7 +101,7 @@ public JsonNode generateRaw(String selectedType, String patterns, String evidenc if (raw.isObject()) { hydrateTypeAnalysisIfMissing((ObjectNode) raw); } - return raw; + return new LlmGenerationResult<>(raw, tokenUsage); } catch (AiResponseParseException e) { throw e; } catch (Exception e) { @@ -103,11 +109,11 @@ public JsonNode generateRaw(String selectedType, String patterns, String evidenc } } - public JsonNode rewriteOnly(JsonNode raw) { + public LlmGenerationResult rewriteOnly(JsonNode raw) { return enforceLength(raw); } - private JsonNode enforceLength(JsonNode raw) { + private LlmGenerationResult enforceLength(JsonNode raw) { if (raw == null || raw.isNull() || !raw.isObject()) { throw new AiResponseParseException(ErrorCode.TYPE_REPORT_REWRITE_INPUT_SCHEMA_INVALID); } @@ -116,14 +122,14 @@ private JsonNode enforceLength(JsonNode raw) { JsonNode personasNode = root.get("personas"); if (personasNode == null || !personasNode.isArray()) { - return root; + return new LlmGenerationResult<>(root, LlmTokenUsage.empty()); } validateRichContentsIfPresent(root); TypeTextContent sourceTypeAnalysisContent = parseTypeTextContentOrFallback(root.get("typeAnalysisContent"), ""); String typeAnalysis = sourceTypeAnalysisContent.plainText().trim(); if (blank(typeAnalysis)) { - return root; + return new LlmGenerationResult<>(root, LlmTokenUsage.empty()); } root.put("typeAnalysis", typeAnalysis); ArrayNode personasArr = (ArrayNode) personasNode; @@ -140,13 +146,17 @@ private JsonNode enforceLength(JsonNode raw) { badP2 = isOutOfRange(getPersonaContent(personasArr.get(1)).length(), MIN_PERSONA_CONTENT, MAX_PERSONA_CONTENT); } - if (!badTA && !badP1 && !badP2) return root; + if (!badTA && !badP1 && !badP2) return new LlmGenerationResult<>(root, LlmTokenUsage.empty()); ChatClient rewriteClient = llmRouter.route(REWRITE_PROVIDER); + LlmTokenUsage tokenUsage = LlmTokenUsage.empty(); if (badTA) { log.debug("[TypeReportRewrite] typeAnalysis invalid. len={}, twoParagraph={}", typeAnalysis.length(), validTwoParagraphs(typeAnalysis)); - StyledText rewritten = rewriteTypeAnalysis(rewriteClient, sourceTypeAnalysisContent.styledText()); + LlmGenerationResult rewriteResult = + rewriteTypeAnalysis(rewriteClient, sourceTypeAnalysisContent.styledText()); + StyledText rewritten = rewriteResult.content(); + tokenUsage = tokenUsage.plus(rewriteResult.tokenUsage()); validateStyledText(rewritten, true); TypeTextContent rewrittenContent = new TypeTextContent(rewritten).normalized(); root.set("typeAnalysisContent", objectMapper.valueToTree(rewrittenContent)); @@ -157,14 +167,18 @@ private JsonNode enforceLength(JsonNode raw) { ObjectNode p0 = (ObjectNode) personasArr.get(0); String in = safeText(p0.get("content")); log.debug("[TypeReportRewrite] personas[0].content invalid. len={}", in.length()); - p0.put("content", rewritePersonaContent(rewriteClient, in, 1)); + LlmGenerationResult rewriteResult = rewritePersonaContent(rewriteClient, in, 1); + p0.put("content", rewriteResult.content()); + tokenUsage = tokenUsage.plus(rewriteResult.tokenUsage()); } if (personasArr.size() >= 2 && badP2 && personasArr.get(1).isObject()) { ObjectNode p1 = (ObjectNode) personasArr.get(1); String in = safeText(p1.get("content")); log.debug("[TypeReportRewrite] personas[1].content invalid. len={}", in.length()); - p1.put("content", rewritePersonaContent(rewriteClient, in, 2)); + LlmGenerationResult rewriteResult = rewritePersonaContent(rewriteClient, in, 2); + p1.put("content", rewriteResult.content()); + tokenUsage = tokenUsage.plus(rewriteResult.tokenUsage()); } // ===== rewrite 후 검증(원인별 코드로) ===== @@ -195,7 +209,7 @@ private JsonNode enforceLength(JsonNode raw) { } } - return root; + return new LlmGenerationResult<>(root, tokenUsage); } private void validateRichContentsIfPresent(ObjectNode root) { @@ -273,7 +287,7 @@ private void validateStyledText(StyledText styledText, boolean isTypeAnalysis) { } } - private StyledText rewriteTypeAnalysis(ChatClient client, StyledText in) { + private LlmGenerationResult rewriteTypeAnalysis(ChatClient client, StyledText in) { StyledText inputStyled = in == null ? new StyledText(List.of(new Segment("", List.of()))) : in.normalized(); String jsonInput; try { @@ -312,12 +326,14 @@ private StyledText rewriteTypeAnalysis(ChatClient client, StyledText in) { .temperature(0.0) .build(); - String out; + ChatResponse response; try { - out = client.prompt().user(prompt).options(options).call().content(); + response = client.prompt().user(prompt).options(options).call().chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.TYPE_REPORT_REWRITE_NO_RESPONSE, e); } + String out = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (out == null || out.isBlank()) { throw new AiServiceUnavailableException(ErrorCode.TYPE_REPORT_REWRITE_NO_RESPONSE); @@ -328,7 +344,7 @@ private StyledText rewriteTypeAnalysis(ChatClient client, StyledText in) { if (rewritten == null || rewritten.segments() == null || rewritten.segments().isEmpty()) { throw new AiResponseParseException(ErrorCode.TYPE_REPORT_REWRITE_OUTPUT_EMPTY); } - return rewritten; + return new LlmGenerationResult<>(rewritten, tokenUsage); } catch (AiResponseParseException e) { throw e; } catch (JsonParseException e) { @@ -369,7 +385,7 @@ private void hydrateTypeAnalysisIfMissing(ObjectNode root) { } } - private String rewritePersonaContent(ChatClient client, String in, int personaIndex) { + private LlmGenerationResult rewritePersonaContent(ChatClient client, String in, int personaIndex) { String prompt = """ 아래 'personas[%d].content' 본문은 의미는 유지하되 글자수 규칙을 맞춰야 해요. 의미는 유지하면서 글자수(공백 포함)를 최소 %d자 ~ 최대 %d자로 맞춰서 다시 써줘요. @@ -406,12 +422,14 @@ private String rewritePersonaContent(ChatClient client, String in, int personaIn .temperature(0.0) .build(); - String out; + ChatResponse response; try { - out = client.prompt().user(prompt).options(options).call().content(); + response = client.prompt().user(prompt).options(options).call().chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.TYPE_REPORT_REWRITE_NO_RESPONSE, e); } + String out = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (out == null || out.isBlank()) { throw new AiServiceUnavailableException(ErrorCode.TYPE_REPORT_REWRITE_NO_RESPONSE); @@ -421,7 +439,7 @@ private String rewritePersonaContent(ChatClient client, String in, int personaIn JsonNode node = objectMapper.readTree(out); String text = safeText(node.get("text")).trim(); if (blank(text)) throw new AiResponseParseException(ErrorCode.TYPE_REPORT_REWRITE_OUTPUT_EMPTY); - return text; + return new LlmGenerationResult<>(text, tokenUsage); } catch (AiResponseParseException e) { throw e; } catch (JsonParseException e) { @@ -459,6 +477,13 @@ private String safeText(JsonNode node) { return node.asText(); } + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } + private boolean blank(String s) { return s == null || s.isBlank(); } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeSelectLlmClient.java b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeSelectLlmClient.java index a1fe2265..1c7911f1 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeSelectLlmClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/typereport/infra/TypeSelectLlmClient.java @@ -5,12 +5,16 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.stereotype.Component; @@ -25,7 +29,7 @@ public class TypeSelectLlmClient { private final LlmProvider provider = LlmProvider.OPENAI; - public JsonNode selectTypeRawJson(String candidatesText, String patternsText) { + public LlmGenerationResult selectTypeRawJson(String candidatesText, String patternsText) { if (candidatesText == null || candidatesText.isBlank() || patternsText == null || patternsText.isBlank()) { throw new AiResponseParseException(ErrorCode.TYPE_SELECT_INPUT_EMPTY); } @@ -41,27 +45,36 @@ public JsonNode selectTypeRawJson(String candidatesText, String patternsText) { .temperature(0.0) .build(); - String content; + ChatResponse response; try { - content = client.prompt() + response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_TYPE_SELECT_NO_RESPONSE, e); } + String content = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (content == null || content.trim().isEmpty()) { throw new AiServiceUnavailableException(ErrorCode.AI_TYPE_SELECT_NO_RESPONSE); } try { - return objectMapper.readTree(content); + return new LlmGenerationResult<>(objectMapper.readTree(content), tokenUsage); } catch (AiResponseParseException e) { throw e; } catch (Exception e) { throw new AiResponseParseException(ErrorCode.TYPE_SELECT_JSON_MISSING_FIELDS); } } + + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } } diff --git a/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListener.java b/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListener.java index 1e0a11f5..3f045da5 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListener.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListener.java @@ -10,7 +10,9 @@ import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.WeeklyReportGenerationRequestedEventDto; import com.devkor.ifive.nadab.domain.weeklyreport.core.repository.WeeklyQueryRepository; import com.devkor.ifive.nadab.domain.weeklyreport.infra.WeeklyReportLlmClient; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import com.devkor.ifive.nadab.global.shared.reportcontent.AiReportResultDto; import com.devkor.ifive.nadab.global.shared.util.WeekRangeCalculator; import com.devkor.ifive.nadab.global.shared.util.dto.WeekRangeDto; @@ -58,7 +60,17 @@ public void handle(WeeklyReportGenerationRequestedEventDto event) { ); try { // 트랜잭션 밖(백그라운드)에서 LLM 호출 - dto = weeklyReportLlmClient.generate(range.weekStartDate().toString(), range.weekEndDate().toString(), entries); + LlmGenerationResult generationResult = + weeklyReportLlmClient.generate(range.weekStartDate().toString(), range.weekEndDate().toString(), entries); + dto = generationResult.content(); + LlmTokenUsage tokenUsage = generationResult.tokenUsage(); + reportGenerationLogRecorder.recordTokenUsage( + generationLogId, + tokenUsage.inputTokens(), + tokenUsage.outputTokens(), + tokenUsage.totalTokens(), + tokenUsage.thinkingTokens() + ); reportGenerationLogRecorder.succeed(generationLogId); } catch (Exception e) { reportGenerationLogRecorder.fail(generationLogId, e); diff --git a/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClient.java b/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClient.java index e3dd40f2..ba016275 100644 --- a/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClient.java +++ b/src/main/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClient.java @@ -5,8 +5,11 @@ import com.devkor.ifive.nadab.global.exception.ai.AiResponseParseException; import com.devkor.ifive.nadab.global.exception.ai.AiServiceUnavailableException; import com.devkor.ifive.nadab.global.infra.llm.LlmExceptionMapper; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsageExtractor; import com.devkor.ifive.nadab.global.shared.reportcontent.*; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -14,6 +17,7 @@ import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.GoogleGenAiChatOptions; import org.springframework.ai.openai.OpenAiChatOptions; @@ -52,7 +56,7 @@ public class WeeklyReportLlmClient { * @param weekEndDate 예: 2026-01-07 * @param entries WeeklyEntriesAssembler 결과 문자열 */ - public AiReportResultDto generate(String weekStartDate, String weekEndDate, String entries) { + public LlmGenerationResult generate(String weekStartDate, String weekEndDate, String entries) { if (isBlank(entries)) { throw new AiResponseParseException(ErrorCode.WEEKLY_REPORT_INPUT_ENTRIES_EMPTY); @@ -65,11 +69,13 @@ public AiReportResultDto generate(String weekStartDate, String weekEndDate, Stri ChatClient client = llmRouter.route(provider); - String content = switch (provider) { + LlmGenerationResult generationResult = switch (provider) { case OPENAI -> callOpenAi(client, prompt); case CLAUDE -> callClaude(client, prompt); case GEMINI -> callGemini(client, prompt); }; + String content = generationResult.content(); + LlmTokenUsage tokenUsage = generationResult.tokenUsage(); if (content == null || content.trim().isEmpty()) { throw new AiServiceUnavailableException(ErrorCode.AI_NO_RESPONSE); @@ -108,12 +114,15 @@ public AiReportResultDto generate(String weekStartDate, String weekEndDate, Stri } // 길이 맞추기(StyledText 자체 리라이트) - AiReportResultDto dto = enforceLength(new AiReportResultDto(reportContent, discovered, improve)); + LlmGenerationResult lengthResult = + enforceLength(new AiReportResultDto(reportContent, discovered, improve)); + AiReportResultDto dto = lengthResult.content(); + tokenUsage = tokenUsage.plus(lengthResult.tokenUsage()); // 최종 길이 검증 validateLength(dto); - return dto; + return new LlmGenerationResult<>(dto, tokenUsage); } catch (AiResponseParseException e) { throw e; @@ -123,7 +132,7 @@ public AiReportResultDto generate(String weekStartDate, String weekEndDate, Stri } } - private String callOpenAi(ChatClient client, String prompt) { + private LlmGenerationResult callOpenAi(ChatClient client, String prompt) { OpenAiChatOptions options = OpenAiChatOptions.builder() .model(OpenAiApi.ChatModel.GPT_5_MINI) .reasoningEffort("medium") @@ -131,34 +140,36 @@ private String callOpenAi(ChatClient client, String prompt) { .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private String callClaude(ChatClient client, String prompt) { + private LlmGenerationResult callClaude(ChatClient client, String prompt) { AnthropicChatOptions options = AnthropicChatOptions.builder() .model(AnthropicApi.ChatModel.CLAUDE_3_HAIKU) .temperature(0.3) .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private String callGemini(ChatClient client, String prompt) { + private LlmGenerationResult callGemini(ChatClient client, String prompt) { GoogleGenAiChatOptions options = GoogleGenAiChatOptions.builder() .model(GoogleGenAiChatModel.ChatModel.GEMINI_2_5_FLASH) .responseMimeType("application/json") @@ -166,17 +177,18 @@ private String callGemini(ChatClient client, String prompt) { .build(); try { - return client.prompt() + ChatResponse response = client.prompt() .user(prompt) .options(options) .call() - .content(); + .chatResponse(); + return new LlmGenerationResult<>(extractContent(response), LlmTokenUsageExtractor.extract(response)); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_NO_RESPONSE, e); } } - private AiReportResultDto enforceLength(AiReportResultDto dto) { + private LlmGenerationResult enforceLength(AiReportResultDto dto) { ReportContent c = dto.content(); int dLen = dto.discovered().length(); @@ -185,15 +197,24 @@ private AiReportResultDto enforceLength(AiReportResultDto dto) { boolean badD = dLen < MIN_DISCOVERED || dLen > MAX_DISCOVERED; boolean badI = iLen < MIN_IMPROVE || iLen > MAX_IMPROVE; - if (!badD && !badI) return dto; + if (!badD && !badI) return new LlmGenerationResult<>(dto, LlmTokenUsage.empty()); ChatClient rewriteClient = llmRouter.route(REWRITE_PROVIDER); StyledText d = c.discovered(); StyledText i = c.improve(); + LlmTokenUsage tokenUsage = LlmTokenUsage.empty(); - if (badD) d = rewriteStyled(rewriteClient, d, true); - if (badI) i = rewriteStyled(rewriteClient, i, false); + if (badD) { + LlmGenerationResult rewriteResult = rewriteStyled(rewriteClient, d, true); + d = rewriteResult.content(); + tokenUsage = tokenUsage.plus(rewriteResult.tokenUsage()); + } + if (badI) { + LlmGenerationResult rewriteResult = rewriteStyled(rewriteClient, i, false); + i = rewriteResult.content(); + tokenUsage = tokenUsage.plus(rewriteResult.tokenUsage()); + } ReportContent newContent = new ReportContent(c.summary(), d, i); String newD = newContent.discovered().plainText(); @@ -206,10 +227,10 @@ private AiReportResultDto enforceLength(AiReportResultDto dto) { throw new AiResponseParseException(ErrorCode.WEEKLY_REPORT_REWRITE_FORMAT_INVALID); } - return new AiReportResultDto(newContent, newD, newI); + return new LlmGenerationResult<>(new AiReportResultDto(newContent, newD, newI), tokenUsage); } - private StyledText rewriteStyled(ChatClient client, StyledText in, boolean isDiscovered) { + private LlmGenerationResult rewriteStyled(ChatClient client, StyledText in, boolean isDiscovered) { int min = isDiscovered ? MIN_DISCOVERED : MIN_IMPROVE; int max = isDiscovered ? MAX_DISCOVERED : MAX_IMPROVE; int maxHl = isDiscovered ? MAX_HL_DISCOVERED : MAX_HL_IMPROVE; @@ -242,19 +263,21 @@ private StyledText rewriteStyled(ChatClient client, StyledText in, boolean isDis .temperature(0.0) .build(); - String out; + ChatResponse response; try { - out = client.prompt().user(prompt).options(options).call().content(); + response = client.prompt().user(prompt).options(options).call().chatResponse(); } catch (Exception e) { throw LlmExceptionMapper.toUnavailable(ErrorCode.AI_REWRITE_NO_RESPONSE, e); } + String out = extractContent(response); + LlmTokenUsage tokenUsage = LlmTokenUsageExtractor.extract(response); if (out == null || out.isBlank()) { throw new AiServiceUnavailableException(ErrorCode.AI_REWRITE_NO_RESPONSE); } try { - return objectMapper.readValue(out, StyledText.class); + return new LlmGenerationResult<>(objectMapper.readValue(out, StyledText.class), tokenUsage); } catch (Exception e) { throw new AiResponseParseException(ErrorCode.WEEKLY_REPORT_REWRITE_JSON_MAPPING_FAILED); } @@ -267,6 +290,13 @@ private StyledText rewriteStyled(ChatClient client, StyledText in, boolean isDis } } + private String extractContent(ChatResponse response) { + if (response == null || response.getResult() == null || response.getResult().getOutput() == null) { + return null; + } + return response.getResult().getOutput().getText(); + } + private boolean isBlank(String s) { return s == null || s.trim().isEmpty(); } diff --git a/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmGenerationResult.java b/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmGenerationResult.java new file mode 100644 index 00000000..54f11697 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmGenerationResult.java @@ -0,0 +1,13 @@ +package com.devkor.ifive.nadab.global.infra.llm; + +public record LlmGenerationResult( + T content, + LlmTokenUsage tokenUsage +) { + + public LlmGenerationResult { + if (tokenUsage == null) { + tokenUsage = LlmTokenUsage.empty(); + } + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsage.java b/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsage.java new file mode 100644 index 00000000..afc2c162 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsage.java @@ -0,0 +1,39 @@ +package com.devkor.ifive.nadab.global.infra.llm; + +public record LlmTokenUsage( + Long inputTokens, + Long outputTokens, + Long totalTokens, + Long thinkingTokens +) { + + public LlmTokenUsage(Long inputTokens, Long outputTokens, Long totalTokens) { + this(inputTokens, outputTokens, totalTokens, null); + } + + public static LlmTokenUsage empty() { + return new LlmTokenUsage(null, null, null, null); + } + + public LlmTokenUsage plus(LlmTokenUsage other) { + if (other == null) { + return this; + } + return new LlmTokenUsage( + add(inputTokens, other.inputTokens), + add(outputTokens, other.outputTokens), + add(totalTokens, other.totalTokens), + add(thinkingTokens, other.thinkingTokens) + ); + } + + private Long add(Long left, Long right) { + if (left == null) { + return right; + } + if (right == null) { + return left; + } + return left + right; + } +} diff --git a/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractor.java b/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractor.java new file mode 100644 index 00000000..bc27f716 --- /dev/null +++ b/src/main/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractor.java @@ -0,0 +1,43 @@ +package com.devkor.ifive.nadab.global.infra.llm; + +import org.springframework.ai.chat.metadata.EmptyUsage; +import org.springframework.ai.chat.metadata.Usage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.google.genai.metadata.GoogleGenAiUsage; + +public final class LlmTokenUsageExtractor { + + private LlmTokenUsageExtractor() { + } + + public static LlmTokenUsage extract(ChatResponse response) { + if (response == null || response.getMetadata() == null) { + return LlmTokenUsage.empty(); + } + return extract(response.getMetadata().getUsage()); + } + + public static LlmTokenUsage extract(Usage usage) { + if (usage == null || usage instanceof EmptyUsage) { + return LlmTokenUsage.empty(); + } + + return new LlmTokenUsage( + toLong(usage.getPromptTokens()), + toLong(usage.getCompletionTokens()), + toLong(usage.getTotalTokens()), + extractThinkingTokens(usage) + ); + } + + private static Long extractThinkingTokens(Usage usage) { + if (usage instanceof GoogleGenAiUsage googleUsage) { + return toLong(googleUsage.getThoughtsTokenCount()); + } + return null; + } + + private static Long toLong(Integer value) { + return value == null ? null : value.longValue(); + } +} diff --git a/src/main/resources/db/migration/V20260708_1200__IS_add_token_usage_to_report_generation_logs.sql b/src/main/resources/db/migration/V20260708_1200__IS_add_token_usage_to_report_generation_logs.sql new file mode 100644 index 00000000..b03e59e7 --- /dev/null +++ b/src/main/resources/db/migration/V20260708_1200__IS_add_token_usage_to_report_generation_logs.sql @@ -0,0 +1,4 @@ +ALTER TABLE report_generation_logs + ADD COLUMN input_tokens BIGINT, + ADD COLUMN output_tokens BIGINT, + ADD COLUMN total_tokens BIGINT; diff --git a/src/main/resources/db/migration/V20260708_1500__IS_add_thinking_tokens_to_report_generation_logs.sql b/src/main/resources/db/migration/V20260708_1500__IS_add_thinking_tokens_to_report_generation_logs.sql new file mode 100644 index 00000000..bb0421fa --- /dev/null +++ b/src/main/resources/db/migration/V20260708_1500__IS_add_thinking_tokens_to_report_generation_logs.sql @@ -0,0 +1,2 @@ +ALTER TABLE report_generation_logs + ADD COLUMN thinking_tokens BIGINT; diff --git a/src/test/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportServiceTest.java new file mode 100644 index 00000000..b72ed0d7 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/dailyreport/application/DailyReportServiceTest.java @@ -0,0 +1,194 @@ +package com.devkor.ifive.nadab.domain.dailyreport.application; + +import com.devkor.ifive.nadab.domain.dailyreport.api.dto.request.DailyReportRequest; +import com.devkor.ifive.nadab.domain.dailyreport.api.dto.response.CreateDailyReportResponse; +import com.devkor.ifive.nadab.domain.dailyreport.core.dto.AiDailyReportResultDto; +import com.devkor.ifive.nadab.domain.dailyreport.core.dto.ConfirmDailyAndRewardDto; +import com.devkor.ifive.nadab.domain.dailyreport.core.dto.PrepareDailyResultDto; +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.AnswerEntry; +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.Emotion; +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.EmotionCode; +import com.devkor.ifive.nadab.domain.dailyreport.infra.DailyReportLlmClient; +import com.devkor.ifive.nadab.domain.question.core.entity.DailyQuestion; +import com.devkor.ifive.nadab.domain.question.core.entity.UserDailyQuestion; +import com.devkor.ifive.nadab.domain.question.core.repository.DailyQuestionRepository; +import com.devkor.ifive.nadab.domain.question.core.repository.UserDailyQuestionRepository; +import com.devkor.ifive.nadab.domain.reportlog.application.ReportGenerationLogRecorder; +import com.devkor.ifive.nadab.domain.reportlog.core.entity.ReportGenerationStep; +import com.devkor.ifive.nadab.domain.reportlog.core.entity.ReportGenerationType; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.domain.user.core.repository.UserRepository; +import com.devkor.ifive.nadab.domain.user.core.service.ProfileImageService; +import com.devkor.ifive.nadab.domain.user.infra.ProfileImageUrlBuilder; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.test.util.ReflectionTestUtils; + +import java.time.LocalDate; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DailyReportServiceTest { + + @Mock + UserRepository userRepository; + + @Mock + DailyQuestionRepository dailyQuestionRepository; + + @Mock + UserDailyQuestionRepository userDailyQuestionRepository; + + @Mock + DailyReportTxService dailyReportTxService; + + @Mock + ProfileImageService profileImageService; + + @Mock + DailyReportLlmClient dailyReportLlmClient; + + @Mock + ReportGenerationLogRecorder reportGenerationLogRecorder; + + @Mock + ApplicationEventPublisher eventPublisher; + + @Mock + ProfileImageUrlBuilder profileImageUrlBuilder; + + DailyReportService dailyReportService; + + @BeforeEach + void setUp() { + dailyReportService = new DailyReportService( + userRepository, + dailyQuestionRepository, + userDailyQuestionRepository, + dailyReportTxService, + profileImageService, + dailyReportLlmClient, + reportGenerationLogRecorder, + eventPublisher, + profileImageUrlBuilder + ); + ReflectionTestUtils.setField(dailyReportService, "env", "test"); + } + + @Test + void generate_daily_report_records_token_usage_before_succeeding_generation_log() { + // given + Long userId = 1L; + Long reportId = 100L; + Long generationLogId = 10L; + User user = user(userId); + DailyQuestion question = dailyQuestion(20L); + AnswerEntry answerEntry = AnswerEntry.create(user, question, "answer", LocalDate.now(), null); + AiDailyReportResultDto aiResult = new AiDailyReportResultDto("message", "ACHIEVEMENT"); + Emotion emotion = emotion(EmotionCode.ACHIEVEMENT); + + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + when(dailyQuestionRepository.findByIdWithInterest(20L)).thenReturn(Optional.of(question)); + when(userDailyQuestionRepository.findByUserIdAndDate(eq(userId), any(LocalDate.class))) + .thenReturn(Optional.of(UserDailyQuestion.create(user, LocalDate.now(), question))); + when(dailyReportTxService.prepareDaily(user, question, "answer", false, null)) + .thenReturn(new PrepareDailyResultDto(answerEntry, reportId, userId)); + when(reportGenerationLogRecorder.start( + userId, + ReportGenerationType.DAILY, + reportId, + ReportGenerationStep.DAILY_GENERATE, + LlmProvider.OPENAI, + "GPT_4_O_MINI" + )).thenReturn(generationLogId); + when(dailyReportLlmClient.generate("question", answerEntry)) + .thenReturn(new LlmGenerationResult<>(aiResult, new LlmTokenUsage(100L, 50L, 150L))); + when(dailyReportTxService.confirmDailyAndReward( + any(PrepareDailyResultDto.class), + eq(aiResult), + eq(null) + )).thenReturn(new ConfirmDailyAndRewardDto(emotion, 110L)); + + // when + CreateDailyReportResponse response = dailyReportService.generateDailyReport( + userId, + new DailyReportRequest(20L, "answer", null, null) + ); + + // then + assertThat(response.reportId()).isEqualTo(reportId); + assertThat(response.content()).isEqualTo("message"); + assertThat(response.balanceAfter()).isEqualTo(110L); + + InOrder inOrder = inOrder(reportGenerationLogRecorder); + inOrder.verify(reportGenerationLogRecorder).recordTokenUsage(generationLogId, 100L, 50L, 150L, null); + inOrder.verify(reportGenerationLogRecorder).succeed(generationLogId); + } + + @Test + void generate_daily_report_records_null_token_usage_when_usage_is_empty() { + // given + Long userId = 1L; + Long reportId = 100L; + Long generationLogId = 10L; + User user = user(userId); + DailyQuestion question = dailyQuestion(20L); + AnswerEntry answerEntry = AnswerEntry.create(user, question, "answer", LocalDate.now(), null); + AiDailyReportResultDto aiResult = new AiDailyReportResultDto("message", "ACHIEVEMENT"); + Emotion emotion = emotion(EmotionCode.ACHIEVEMENT); + + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + when(dailyQuestionRepository.findByIdWithInterest(20L)).thenReturn(Optional.of(question)); + when(userDailyQuestionRepository.findByUserIdAndDate(eq(userId), any(LocalDate.class))) + .thenReturn(Optional.of(UserDailyQuestion.create(user, LocalDate.now(), question))); + when(dailyReportTxService.prepareDaily(user, question, "answer", false, null)) + .thenReturn(new PrepareDailyResultDto(answerEntry, reportId, userId)); + when(reportGenerationLogRecorder.start(any(), any(), any(), any(), any(), any())) + .thenReturn(generationLogId); + when(dailyReportLlmClient.generate("question", answerEntry)) + .thenReturn(new LlmGenerationResult<>(aiResult, LlmTokenUsage.empty())); + when(dailyReportTxService.confirmDailyAndReward(any(), eq(aiResult), eq(null))) + .thenReturn(new ConfirmDailyAndRewardDto(emotion, 110L)); + + // when + dailyReportService.generateDailyReport(userId, new DailyReportRequest(20L, "answer", null, null)); + + // then + verify(reportGenerationLogRecorder).recordTokenUsage(generationLogId, null, null, null, null); + } + + private User user(Long id) { + User user = User.createUser("test@test.com", "hashed_password"); + ReflectionTestUtils.setField(user, "id", id); + return user; + } + + private DailyQuestion dailyQuestion(Long id) { + DailyQuestion question = mock(DailyQuestion.class); + when(question.getId()).thenReturn(id); + when(question.getQuestionText()).thenReturn("question"); + return question; + } + + private Emotion emotion(EmotionCode code) { + Emotion emotion = mock(Emotion.class); + when(emotion.getCode()).thenReturn(code); + return emotion; + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClientTest.java b/src/test/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClientTest.java new file mode 100644 index 00000000..8723f771 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/dailyreport/infra/DailyReportLlmClientTest.java @@ -0,0 +1,107 @@ +package com.devkor.ifive.nadab.domain.dailyreport.infra; + +import com.devkor.ifive.nadab.domain.dailyreport.core.entity.AnswerEntry; +import com.devkor.ifive.nadab.domain.question.core.entity.DailyQuestion; +import com.devkor.ifive.nadab.domain.user.core.entity.User; +import com.devkor.ifive.nadab.domain.user.infra.ProfileImageUrlBuilder; +import com.devkor.ifive.nadab.global.core.prompt.daily.DailyReportPromptLoader; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.chat.metadata.DefaultUsage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; + +import java.time.LocalDate; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DailyReportLlmClientTest { + + @Mock + DailyReportPromptLoader dailyReportPromptLoader; + + @Mock + LlmRouter llmRouter; + + @Mock + ProfileImageUrlBuilder profileImageUrlBuilder; + + @Mock + ChatClient chatClient; + + @Mock + ChatClient.ChatClientRequestSpec requestSpec; + + @Mock + ChatClient.CallResponseSpec callResponseSpec; + + @Test + void generate_returns_content_with_token_usage() { + // given + DailyReportLlmClient client = new DailyReportLlmClient( + dailyReportPromptLoader, + new ObjectMapper(), + llmRouter, + profileImageUrlBuilder + ); + AnswerEntry answerEntry = AnswerEntry.create( + User.createUser("test@test.com", "hashed_password"), + dailyQuestion(1L), + "answer", + LocalDate.now(), + null + ); + + when(dailyReportPromptLoader.loadPrompt()).thenReturn("question={question}, answer={answer}"); + when(dailyReportPromptLoader.loadWithImagePrompt()).thenReturn("image question={question}, answer={answer}"); + when(llmRouter.route(LlmProvider.OPENAI)).thenReturn(chatClient); + when(chatClient.prompt()).thenReturn(requestSpec); + when(requestSpec.messages(any(Message[].class))).thenReturn(requestSpec); + when(requestSpec.options(any())).thenReturn(requestSpec); + when(requestSpec.call()).thenReturn(callResponseSpec); + when(callResponseSpec.chatResponse()).thenReturn(chatResponse( + "{\"message\":\"good\",\"emotion\":\"ACHIEVEMENT\"}", + new DefaultUsage(100, 50, 150) + )); + + // when + LlmGenerationResult result = client.generate("question", answerEntry); + + // then + assertThat(result.content()).isEqualTo(new com.devkor.ifive.nadab.domain.dailyreport.core.dto.AiDailyReportResultDto( + "good", + "ACHIEVEMENT" + )); + assertThat(result.tokenUsage().inputTokens()).isEqualTo(100L); + assertThat(result.tokenUsage().outputTokens()).isEqualTo(50L); + assertThat(result.tokenUsage().totalTokens()).isEqualTo(150L); + } + + private ChatResponse chatResponse(String content, DefaultUsage usage) { + return new ChatResponse( + List.of(new Generation(new AssistantMessage(content))), + ChatResponseMetadata.builder() + .usage(usage) + .build() + ); + } + + private DailyQuestion dailyQuestion(Long id) { + return mock(DailyQuestion.class); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java index 0354b70f..f5ac586c 100644 --- a/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java +++ b/src/test/java/com/devkor/ifive/nadab/domain/monthlyreport/application/listener/MonthlyReportGenerationListenerV2Test.java @@ -18,10 +18,13 @@ import com.devkor.ifive.nadab.domain.monthlyreport.infra.MonthlyReportLlmClientV2; import com.devkor.ifive.nadab.domain.monthlyreport.infra.OpenAiImageClient; import com.devkor.ifive.nadab.domain.reportlog.application.ReportGenerationLogRecorder; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; import com.devkor.ifive.nadab.global.shared.reportcontent.StyledText; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -32,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -76,8 +80,10 @@ class MonthlyReportGenerationListenerV2Test { when(monthlyWeeklySummariesService.buildWeeklySummaries(anyLong(), any())).thenReturn(""); when(monthlySocialSummaryService.buildSocialSummary(anyLong(), any())) .thenReturn(MonthlySocialSummaryContent.empty(1)); + when(reportGenerationLogRecorder.start(anyLong(), any(), anyLong(), any(), any(), any())) + .thenReturn(200L, 201L, 202L, 203L); when(monthlyReportLlmClientV2.generate(any(), any(), any(), any(), any(), any())) - .thenReturn(result); + .thenReturn(new LlmGenerationResult<>(result, new LlmTokenUsage(100L, 50L, 150L, 30L))); when(monthlyImagePresetAssignmentService.getOrAssignVisualPreset(1L, 10L)) .thenReturn(new MonthlyImageVisualPreset( MonthlyImageStylePreset.INK_WASH, @@ -99,6 +105,9 @@ class MonthlyReportGenerationListenerV2Test { assertThat(context.dominantKeyword()).isEqualTo("성장"); assertThat(context.stylePreset()).isEqualTo(MonthlyImageStylePreset.INK_WASH); assertThat(context.colorPalette()).isEqualTo(MonthlyImageColorPalette.OCEAN_LIGHT); + InOrder inOrder = inOrder(reportGenerationLogRecorder); + inOrder.verify(reportGenerationLogRecorder).recordTokenUsage(200L, 100L, 50L, 150L, 30L); + inOrder.verify(reportGenerationLogRecorder).succeed(200L); verify(monthlyReportTxServiceV2).confirmMonthly(10L, 100L, "monthly/1/10.webp"); } @@ -123,8 +132,10 @@ class MonthlyReportGenerationListenerV2Test { when(monthlyWeeklySummariesService.buildWeeklySummaries(anyLong(), any())).thenReturn(""); when(monthlySocialSummaryService.buildSocialSummary(anyLong(), any())) .thenReturn(MonthlySocialSummaryContent.empty(1)); + when(reportGenerationLogRecorder.start(anyLong(), any(), anyLong(), any(), any(), any())) + .thenReturn(200L, 201L); when(monthlyReportLlmClientV2.generate(any(), any(), any(), any(), any(), any())) - .thenReturn(new AiMonthlyReportResultDto(content, null)); + .thenReturn(new LlmGenerationResult<>(new AiMonthlyReportResultDto(content, null), LlmTokenUsage.empty())); when(monthlyImagePresetAssignmentService.getOrAssignVisualPreset(1L, 10L)) .thenThrow(new IllegalStateException("preset assignment failed")); diff --git a/src/test/java/com/devkor/ifive/nadab/domain/reportlog/ReportGenerationLogRepositoryTest.java b/src/test/java/com/devkor/ifive/nadab/domain/reportlog/ReportGenerationLogRepositoryTest.java index ecd85e8e..a8428f0b 100644 --- a/src/test/java/com/devkor/ifive/nadab/domain/reportlog/ReportGenerationLogRepositoryTest.java +++ b/src/test/java/com/devkor/ifive/nadab/domain/reportlog/ReportGenerationLogRepositoryTest.java @@ -81,6 +81,27 @@ void find_by_status() { .containsOnly(ReportGenerationLogStatus.FAILED); } + @Test + void save_token_usage() { + // given + User user = new UserBuilder(em).build(); + ReportGenerationLog log = startLog(user, ReportGenerationType.DAILY, 101L, ReportGenerationStep.DAILY_GENERATE); + log.recordTokenUsage(100L, 50L, 150L, 30L); + ReportGenerationLog saved = reportGenerationLogRepository.save(log); + + em.flush(); + em.clear(); + + // when + ReportGenerationLog found = reportGenerationLogRepository.findById(saved.getId()).orElseThrow(); + + // then + assertThat(found.getInputTokens()).isEqualTo(100L); + assertThat(found.getOutputTokens()).isEqualTo(50L); + assertThat(found.getTotalTokens()).isEqualTo(150L); + assertThat(found.getThinkingTokens()).isEqualTo(30L); + } + private ReportGenerationLog startLog( User user, ReportGenerationType reportType, diff --git a/src/test/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogServiceTest.java b/src/test/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogServiceTest.java index 019aa218..d3c0f3d3 100644 --- a/src/test/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogServiceTest.java +++ b/src/test/java/com/devkor/ifive/nadab/domain/reportlog/application/ReportGenerationLogServiceTest.java @@ -81,6 +81,38 @@ void succeed_marks_log_succeeded() { assertThat(log.getElapsedMs()).isNotNull(); } + @Test + void record_token_usage_updates_token_fields() { + // given + ReportGenerationLog log = startLog(); + when(reportGenerationLogRepository.findById(1L)).thenReturn(Optional.of(log)); + + // when + reportGenerationLogService.recordTokenUsage(1L, 100L, 50L, 150L, 30L); + + // then + assertThat(log.getInputTokens()).isEqualTo(100L); + assertThat(log.getOutputTokens()).isEqualTo(50L); + assertThat(log.getTotalTokens()).isEqualTo(150L); + assertThat(log.getThinkingTokens()).isEqualTo(30L); + } + + @Test + void record_token_usage_allows_null_values() { + // given + ReportGenerationLog log = startLog(); + when(reportGenerationLogRepository.findById(1L)).thenReturn(Optional.of(log)); + + // when + reportGenerationLogService.recordTokenUsage(1L, null, null, null, null); + + // then + assertThat(log.getInputTokens()).isNull(); + assertThat(log.getOutputTokens()).isNull(); + assertThat(log.getTotalTokens()).isNull(); + assertThat(log.getThinkingTokens()).isNull(); + } + @Test void fail_marks_log_failed_with_external_status() { // given diff --git a/src/test/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListenerTest.java b/src/test/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListenerTest.java new file mode 100644 index 00000000..9e4b95c1 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/typereport/application/listener/TypeReportGenerationListenerTest.java @@ -0,0 +1,174 @@ +package com.devkor.ifive.nadab.domain.typereport.application.listener; + +import com.devkor.ifive.nadab.domain.reportlog.application.ReportGenerationLogRecorder; +import com.devkor.ifive.nadab.domain.typereport.application.TypeReportTxService; +import com.devkor.ifive.nadab.domain.typereport.core.content.TypeContentFactory; +import com.devkor.ifive.nadab.domain.typereport.core.dto.AnalysisTypeCandidateDto; +import com.devkor.ifive.nadab.domain.typereport.core.dto.EvidenceCardDto; +import com.devkor.ifive.nadab.domain.typereport.core.dto.PatternExtractionResultDto; +import com.devkor.ifive.nadab.domain.typereport.core.dto.TypeReportContentDto; +import com.devkor.ifive.nadab.domain.typereport.core.dto.TypeReportGenerationRequestedEventDto; +import com.devkor.ifive.nadab.domain.typereport.core.dto.TypeSelectionResultDto; +import com.devkor.ifive.nadab.domain.typereport.core.entity.TypeReport; +import com.devkor.ifive.nadab.domain.typereport.core.repository.AnalysisTypeRepository; +import com.devkor.ifive.nadab.domain.typereport.core.repository.TypeDailyEntryQueryRepository; +import com.devkor.ifive.nadab.domain.typereport.core.repository.TypeReportRepository; +import com.devkor.ifive.nadab.domain.typereport.core.service.EvidenceCardGenerationService; +import com.devkor.ifive.nadab.domain.typereport.core.service.PatternExtractionService; +import com.devkor.ifive.nadab.domain.typereport.core.service.TypeReportContentGenerationService; +import com.devkor.ifive.nadab.domain.typereport.core.service.TypeSelectionService; +import com.devkor.ifive.nadab.domain.user.core.entity.InterestCode; +import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.DailyEntryDto; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InOrder; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationEventPublisher; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TypeReportGenerationListenerTest { + + @Mock + TypeReportTxService typeReportTxService; + + @Mock + TypeReportRepository typeReportRepository; + + @Mock + TypeDailyEntryQueryRepository typeDailyEntryQueryRepository; + + @Mock + AnalysisTypeRepository analysisTypeRepository; + + @Mock + EvidenceCardGenerationService evidenceCardGenerationService; + + @Mock + PatternExtractionService patternExtractionService; + + @Mock + TypeSelectionService typeSelectionService; + + @Mock + TypeReportContentGenerationService typeReportContentGenerationService; + + @Mock + ReportGenerationLogRecorder reportGenerationLogRecorder; + + @Mock + ApplicationEventPublisher eventPublisher; + + @InjectMocks + TypeReportGenerationListener listener; + + @Test + void handle_records_token_usage_for_each_llm_step_before_succeeding_logs() { + // given + TypeReportGenerationRequestedEventDto event = + new TypeReportGenerationRequestedEventDto(10L, 1L, 100L, null); + TypeReport report = mock(TypeReport.class); + DailyEntryDto entry = dailyEntry(); + EvidenceCardDto card = new EvidenceCardDto("D1", LocalDate.of(2026, 1, 1), "card"); + PatternExtractionResultDto patterns = new PatternExtractionResultDto( + List.of(new PatternExtractionResultDto.PatternDto("pattern", List.of("D1"), "note")) + ); + AnalysisTypeCandidateDto selectedType = new AnalysisTypeCandidateDto( + "TYPE_A", "name", "description", "#a", "#b", "#c" + ); + TypeSelectionResultDto selection = new TypeSelectionResultDto( + "TYPE_A", + 90, + List.of(new TypeSelectionResultDto.BecauseDto("pattern", List.of("D1"))) + ); + TypeReportContentDto content = typeReportContent(); + + when(typeReportRepository.findById(10L)).thenReturn(Optional.of(report)); + when(report.getInterestCode()).thenReturn(InterestCode.ROUTINE); + when(typeDailyEntryQueryRepository.findRecentDailyEntriesByInterest(eq(1L), eq(InterestCode.ROUTINE), any())) + .thenReturn(List.of(entry)); + when(typeDailyEntryQueryRepository.countCompletedEmotionStatsByInterest(anyLong(), eq(InterestCode.ROUTINE), any())) + .thenReturn(List.of()); + when(reportGenerationLogRecorder.start(anyLong(), any(), anyLong(), any(), any(), any())) + .thenReturn(200L, 201L, 202L, 203L, 204L); + when(evidenceCardGenerationService.generate(List.of(entry))) + .thenReturn(new LlmGenerationResult<>(List.of(card), new LlmTokenUsage(10L, 5L, 15L, null))); + when(patternExtractionService.extract(List.of(card))) + .thenReturn(new LlmGenerationResult<>(patterns, new LlmTokenUsage(20L, 6L, 26L, null))); + when(analysisTypeRepository.findCandidatesByInterestCode(InterestCode.ROUTINE)) + .thenReturn(List.of(selectedType)); + when(typeSelectionService.select(List.of(selectedType), patterns)) + .thenReturn(new LlmGenerationResult<>(selection, new LlmTokenUsage(30L, 7L, 37L, null))); + when(typeReportContentGenerationService.generate(selectedType, patterns, List.of(card), TypeContentFactory.emptyEmotionStats().normalized(), "TYPE_A")) + .thenReturn(new LlmGenerationResult<>(content, new LlmTokenUsage(40L, 8L, 80L, 32L))); + + // when + listener.handle(event); + + // then + InOrder inOrder = inOrder(reportGenerationLogRecorder); + inOrder.verify(reportGenerationLogRecorder).recordTokenUsage(200L, 10L, 5L, 15L, null); + inOrder.verify(reportGenerationLogRecorder).succeed(200L); + inOrder.verify(reportGenerationLogRecorder).recordTokenUsage(201L, 20L, 6L, 26L, null); + inOrder.verify(reportGenerationLogRecorder).succeed(201L); + inOrder.verify(reportGenerationLogRecorder).recordTokenUsage(202L, 30L, 7L, 37L, null); + inOrder.verify(reportGenerationLogRecorder).succeed(202L); + inOrder.verify(reportGenerationLogRecorder).recordTokenUsage(203L, 40L, 8L, 80L, 32L); + inOrder.verify(reportGenerationLogRecorder).succeed(203L); + inOrder.verify(reportGenerationLogRecorder).succeed(204L); + + verify(typeReportTxService).confirmType( + 10L, + 100L, + null, + "TYPE_A", + content.typeAnalysis(), + content.typeAnalysisContent(), + content.emotionSummaryContent(), + TypeContentFactory.emptyEmotionStats().normalized(), + "persona1", + "content1", + "persona2", + "content2" + ); + verify(eventPublisher).publishEvent(any(Object.class)); + } + + private DailyEntryDto dailyEntry() { + return new DailyEntryDto( + LocalDate.of(2026, 1, 1), + "question", + "answer", + "daily report", + null + ); + } + + private TypeReportContentDto typeReportContent() { + return new TypeReportContentDto( + "TYPE_A", + "type analysis", + TypeContentFactory.fromPlainText("type analysis").normalized(), + TypeContentFactory.emptyText().normalized(), + List.of( + new TypeReportContentDto.PersonaDto("persona1", "content1"), + new TypeReportContentDto.PersonaDto("persona2", "content2") + ) + ); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListenerTest.java b/src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListenerTest.java new file mode 100644 index 00000000..847cf096 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/application/listener/WeeklyReportGenerationListenerTest.java @@ -0,0 +1,94 @@ +package com.devkor.ifive.nadab.domain.weeklyreport.application.listener; + +import com.devkor.ifive.nadab.domain.reportlog.application.ReportGenerationLogRecorder; +import com.devkor.ifive.nadab.domain.weeklyreport.application.WeeklyReportTxService; +import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.DailyEntryDto; +import com.devkor.ifive.nadab.domain.weeklyreport.core.dto.WeeklyReportGenerationRequestedEventDto; +import com.devkor.ifive.nadab.domain.weeklyreport.core.repository.WeeklyQueryRepository; +import com.devkor.ifive.nadab.domain.weeklyreport.infra.WeeklyReportLlmClient; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmTokenUsage; +import com.devkor.ifive.nadab.global.shared.reportcontent.AiReportResultDto; +import com.devkor.ifive.nadab.global.shared.reportcontent.ReportContent; +import com.devkor.ifive.nadab.global.shared.reportcontent.Segment; +import com.devkor.ifive.nadab.global.shared.reportcontent.StyledText; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InOrder; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationEventPublisher; + +import java.time.LocalDate; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class WeeklyReportGenerationListenerTest { + + @Mock + WeeklyQueryRepository weeklyQueryRepository; + + @Mock + WeeklyReportLlmClient weeklyReportLlmClient; + + @Mock + WeeklyReportTxService weeklyReportTxService; + + @Mock + ReportGenerationLogRecorder reportGenerationLogRecorder; + + @Mock + ApplicationEventPublisher eventPublisher; + + @InjectMocks + WeeklyReportGenerationListener listener; + + @Test + void handle_records_token_usage_before_generation_log_succeeds() { + WeeklyReportGenerationRequestedEventDto event = + new WeeklyReportGenerationRequestedEventDto(10L, 1L, 100L); + AiReportResultDto aiResult = aiResult(); + + when(weeklyQueryRepository.findWeeklyInputs(anyLong(), any(LocalDate.class), any(LocalDate.class))) + .thenReturn(List.of(dailyEntry())); + when(reportGenerationLogRecorder.start(anyLong(), any(), anyLong(), any(), any(), any())) + .thenReturn(200L, 201L); + when(weeklyReportLlmClient.generate(anyString(), anyString(), anyString())) + .thenReturn(new LlmGenerationResult<>(aiResult, new LlmTokenUsage(100L, 50L, 150L, 30L))); + + listener.handle(event); + + InOrder inOrder = inOrder(reportGenerationLogRecorder); + inOrder.verify(reportGenerationLogRecorder).recordTokenUsage(200L, 100L, 50L, 150L, 30L); + inOrder.verify(reportGenerationLogRecorder).succeed(200L); + verify(weeklyReportTxService).confirmWeekly(10L, 100L, aiResult.content()); + verify(eventPublisher).publishEvent(any(Object.class)); + } + + private DailyEntryDto dailyEntry() { + return new DailyEntryDto( + LocalDate.of(2026, 1, 1), + "question", + "answer", + "message", + null + ); + } + + private AiReportResultDto aiResult() { + ReportContent content = new ReportContent( + "steady growth", + new StyledText(List.of(new Segment("a".repeat(150), List.of()))), + new StyledText(List.of(new Segment("b".repeat(80), List.of()))) + ); + return new AiReportResultDto(content, content.discovered().plainText(), content.improve().plainText()); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClientTest.java b/src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClientTest.java new file mode 100644 index 00000000..04258dff --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/domain/weeklyreport/infra/WeeklyReportLlmClientTest.java @@ -0,0 +1,141 @@ +package com.devkor.ifive.nadab.domain.weeklyreport.infra; + +import com.devkor.ifive.nadab.global.core.prompt.weekly.WeeklyReportPromptLoader; +import com.devkor.ifive.nadab.global.infra.llm.LlmGenerationResult; +import com.devkor.ifive.nadab.global.infra.llm.LlmProvider; +import com.devkor.ifive.nadab.global.infra.llm.LlmRouter; +import com.devkor.ifive.nadab.global.shared.reportcontent.AiReportResultDto; +import com.devkor.ifive.nadab.global.shared.reportcontent.LlmResultDto; +import com.devkor.ifive.nadab.global.shared.reportcontent.ReportContent; +import com.devkor.ifive.nadab.global.shared.reportcontent.Segment; +import com.devkor.ifive.nadab.global.shared.reportcontent.StyledText; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.chat.metadata.DefaultUsage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class WeeklyReportLlmClientTest { + + @Mock + WeeklyReportPromptLoader weeklyReportPromptLoader; + + @Mock + LlmRouter llmRouter; + + @Mock + ChatClient chatClient; + + @Mock + ChatClient.ChatClientRequestSpec requestSpec; + + @Mock + ChatClient.CallResponseSpec callResponseSpec; + + @Test + void generate_returns_content_with_token_usage() throws Exception { + WeeklyReportLlmClient client = new WeeklyReportLlmClient( + weeklyReportPromptLoader, + new ObjectMapper(), + llmRouter + ); + + when(weeklyReportPromptLoader.loadPrompt()) + .thenReturn("start={weekStartDate}, end={weekEndDate}, entries={entries}"); + when(llmRouter.route(LlmProvider.GEMINI)).thenReturn(chatClient); + when(chatClient.prompt()).thenReturn(requestSpec); + when(requestSpec.user(anyString())).thenReturn(requestSpec); + when(requestSpec.options(any())).thenReturn(requestSpec); + when(requestSpec.call()).thenReturn(callResponseSpec); + when(callResponseSpec.chatResponse()).thenReturn(chatResponse( + reportJson("steady growth", "a".repeat(150), "b".repeat(80)), + new DefaultUsage(100, 50, 150) + )); + + LlmGenerationResult result = + client.generate("2026-01-01", "2026-01-07", "entries"); + + assertThat(result.content().content().summary()).isEqualTo("steady growth"); + assertThat(result.content().discovered()).hasSize(150); + assertThat(result.content().improve()).hasSize(80); + assertThat(result.tokenUsage().inputTokens()).isEqualTo(100L); + assertThat(result.tokenUsage().outputTokens()).isEqualTo(50L); + assertThat(result.tokenUsage().totalTokens()).isEqualTo(150L); + } + + @Test + void generate_adds_rewrite_token_usage() throws Exception { + WeeklyReportLlmClient client = new WeeklyReportLlmClient( + weeklyReportPromptLoader, + new ObjectMapper(), + llmRouter + ); + + when(weeklyReportPromptLoader.loadPrompt()) + .thenReturn("start={weekStartDate}, end={weekEndDate}, entries={entries}"); + when(llmRouter.route(LlmProvider.GEMINI)).thenReturn(chatClient); + when(chatClient.prompt()).thenReturn(requestSpec); + when(requestSpec.user(anyString())).thenReturn(requestSpec); + when(requestSpec.options(any())).thenReturn(requestSpec); + when(requestSpec.call()).thenReturn(callResponseSpec); + when(callResponseSpec.chatResponse()).thenReturn( + chatResponse( + reportJson("steady growth", "a".repeat(20), "b".repeat(80)), + new DefaultUsage(100, 50, 150) + ), + chatResponse( + styledTextJson("c".repeat(150)), + new DefaultUsage(20, 10, 30) + ) + ); + + LlmGenerationResult result = + client.generate("2026-01-01", "2026-01-07", "entries"); + + assertThat(result.content().discovered()).hasSize(150); + assertThat(result.tokenUsage().inputTokens()).isEqualTo(120L); + assertThat(result.tokenUsage().outputTokens()).isEqualTo(60L); + assertThat(result.tokenUsage().totalTokens()).isEqualTo(180L); + } + + private ChatResponse chatResponse(String content, DefaultUsage usage) { + return new ChatResponse( + List.of(new Generation(new AssistantMessage(content))), + ChatResponseMetadata.builder() + .usage(usage) + .build() + ); + } + + private String reportJson(String summary, String discovered, String improve) throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(new LlmResultDto( + summary, + new StyledText(List.of(new Segment(discovered, List.of()))), + new StyledText(List.of(new Segment(improve, List.of()))) + )); + } + + private String styledTextJson(String text) throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(new ReportContent( + "", + new StyledText(List.of(new Segment(text, List.of()))), + null + ).discovered()); + } +} diff --git a/src/test/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractorTest.java b/src/test/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractorTest.java new file mode 100644 index 00000000..907da467 --- /dev/null +++ b/src/test/java/com/devkor/ifive/nadab/global/infra/llm/LlmTokenUsageExtractorTest.java @@ -0,0 +1,149 @@ +package com.devkor.ifive.nadab.global.infra.llm; + +import org.junit.jupiter.api.Test; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.chat.metadata.DefaultUsage; +import org.springframework.ai.chat.metadata.EmptyUsage; +import org.springframework.ai.chat.metadata.Usage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.google.genai.metadata.GoogleGenAiUsage; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class LlmTokenUsageExtractorTest { + + @Test + void extract_maps_prompt_completion_total_tokens() { + // given + ChatResponse response = new ChatResponse( + List.of(), + ChatResponseMetadata.builder() + .usage(new DefaultUsage(100, 50, 150)) + .build() + ); + + // when + LlmTokenUsage usage = LlmTokenUsageExtractor.extract(response); + + // then + assertThat(usage.inputTokens()).isEqualTo(100L); + assertThat(usage.outputTokens()).isEqualTo(50L); + assertThat(usage.totalTokens()).isEqualTo(150L); + assertThat(usage.thinkingTokens()).isNull(); + } + + @Test + void extract_maps_google_genai_thinking_tokens() { + // given + GoogleGenAiUsage googleUsage = new GoogleGenAiUsage( + 3163, + 369, + 6710, + 3178, + null, + null, + null, + null, + null, + null, + null, + null + ); + + // when + LlmTokenUsage usage = LlmTokenUsageExtractor.extract(googleUsage); + + // then + assertThat(usage.inputTokens()).isEqualTo(3163L); + assertThat(usage.outputTokens()).isEqualTo(369L); + assertThat(usage.totalTokens()).isEqualTo(6710L); + assertThat(usage.thinkingTokens()).isEqualTo(3178L); + } + + @Test + void extract_returns_empty_usage_when_response_is_null() { + // when + LlmTokenUsage usage = LlmTokenUsageExtractor.extract((ChatResponse) null); + + // then + assertThat(usage.inputTokens()).isNull(); + assertThat(usage.outputTokens()).isNull(); + assertThat(usage.totalTokens()).isNull(); + assertThat(usage.thinkingTokens()).isNull(); + assertThat(usage.thinkingTokens()).isNull(); + } + + @Test + void extract_returns_empty_usage_for_empty_usage_metadata() { + // when + LlmTokenUsage usage = LlmTokenUsageExtractor.extract(new EmptyUsage()); + + // then + assertThat(usage.inputTokens()).isNull(); + assertThat(usage.outputTokens()).isNull(); + assertThat(usage.totalTokens()).isNull(); + } + + @Test + void extract_preserves_partially_missing_usage_values() { + // given + Usage partialUsage = new Usage() { + @Override + public Integer getPromptTokens() { + return null; + } + + @Override + public Integer getCompletionTokens() { + return 50; + } + + @Override + public Integer getTotalTokens() { + return null; + } + + @Override + public Object getNativeUsage() { + return null; + } + }; + + // when + LlmTokenUsage usage = LlmTokenUsageExtractor.extract(partialUsage); + + // then + assertThat(usage.inputTokens()).isNull(); + assertThat(usage.outputTokens()).isEqualTo(50L); + assertThat(usage.totalTokens()).isNull(); + assertThat(usage.thinkingTokens()).isNull(); + } + + @Test + void token_usage_plus_sums_existing_values_and_preserves_missing_values() { + // when + LlmTokenUsage usage = new LlmTokenUsage(100L, null, 150L, 10L) + .plus(new LlmTokenUsage(30L, 20L, null, 5L)); + + // then + assertThat(usage.inputTokens()).isEqualTo(130L); + assertThat(usage.outputTokens()).isEqualTo(20L); + assertThat(usage.totalTokens()).isEqualTo(150L); + assertThat(usage.thinkingTokens()).isEqualTo(15L); + } + + @Test + void generation_result_defaults_null_token_usage_to_empty() { + // when + LlmGenerationResult result = new LlmGenerationResult<>("content", null); + + // then + assertThat(result.content()).isEqualTo("content"); + assertThat(result.tokenUsage().inputTokens()).isNull(); + assertThat(result.tokenUsage().outputTokens()).isNull(); + assertThat(result.tokenUsage().totalTokens()).isNull(); + assertThat(result.tokenUsage().thinkingTokens()).isNull(); + } +}
+
+

Admin Console

+ +
+ +
+ +
+
+

Version History

+ Back to App Versions +
+
+
+ + +
+
+ +
+
+
+
+