Skip to content

[Fix] Tool Plan 수정 사항 반영#342

Merged
yechan-kim merged 3 commits intodevelopfrom
fix/#341
Dec 1, 2025
Merged

[Fix] Tool Plan 수정 사항 반영#342
yechan-kim merged 3 commits intodevelopfrom
fix/#341

Conversation

@yechan-kim
Copy link
Member

@yechan-kim yechan-kim commented Dec 1, 2025

📣 Related Issue

📝 Summary

  • 플랜 가격 이원화 (연간, 월간)
  • 플랜 정보 DTO에 플랜 링크 필드 추가

🙏 Question & PR point

📬 Postman

툴 생성 시

image

플랜 조회 시

image

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 월간 및 연간 요금제 옵션 분리 — 각 플랜에 월별/연간 가격 표시
    • 요금제 목록에 플랜 링크 추가 — 플랜별 링크 제공
  • 변경사항

    • 월간 요금 항목을 필수화하고 입력 안내 메시지 업데이트
    • 요금제 응답 형식이 월간/연간 가격을 모두 반환하도록 변경

✏️ Tip: You can customize this high-level summary in your review settings.

@yechan-kim yechan-kim self-assigned this Dec 1, 2025
@yechan-kim yechan-kim linked an issue Dec 1, 2025 that may be closed by this pull request
2 tasks
@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Walkthrough

도구 플랜의 가격 필드를 월간/연간으로 분리하고(planPrice → priceMonthly, priceAnnual), 플랜 응답에 플랜 링크(planLink)를 추가하며 DTO, 엔티티, 서비스 계층의 매핑과 팩토리 시그니처를 일괄 업데이트합니다.

Changes

Cohort / File(s) 변경 요약
플랜 가격 이원화
src/main/java/com/daruda/darudaserver/domain/admin/dto/request/CreateToolPlanRequest.java, src/main/java/com/daruda/darudaserver/domain/tool/entity/Plan.java, src/main/java/com/daruda/darudaserver/domain/tool/dto/res/PlanRes.java
단일 가격 필드(planPrice/price)를 priceMonthly(필수)와 priceAnnual(선택)로 분리. 엔티티 컬럼(price_monthly, price_annual) 및 DTO/레코드 시그니처와 매핑 로직 업데이트
플랜 처리 로직 업데이트 (관리자)
src/main/java/com/daruda/darudaserver/domain/admin/service/AdminService.java
updateTool 내 플랜 필터 조건을 planPricepriceMonthly로 변경하고, Plan 생성 시 priceMonthlypriceAnnual을 모두 설정하도록 매핑 확장
플랜 응답에 링크 추가 / 서비스 호출 변경
src/main/java/com/daruda/darudaserver/domain/tool/dto/res/PlanListRes.java, src/main/java/com/daruda/darudaserver/domain/tool/service/ToolService.java
PlanListResplanLink 필드 추가 및 정적 팩토리 메서드 시그니처 변경(of(String planLink, List<PlanRes>)). ToolService.getPlan에서 tool.getPlanLink()를 함께 전달하도록 호출부 수정

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 분

  • 추가 검토 필요 영역:
    • Plan 엔티티의 컬럼 변경(기존 price 컬럼 마이그레이션 또는 호환성) 확인
    • AdminService.updateTool의 필터/매핑 변경이 기존 데이터 및 호출 흐름에 미치는 영향
    • PlanListRes.of 시그니처 변경으로 인한 호출부(다른 서비스/컨트롤러) 누락 여부 점검
    • priceAnnual의 nullable 처리와 유효성(비즈니스 시나리오) 확인

Possibly related PRs

  • PR #332 — AdminService.updateTool 관련 변경: 동일 메서드의 플랜 처리 로직을 수정하는 PR로 코드 레벨 충돌 가능성 있음
  • PR #339 — CreateToolPlanRequest/플랜 가격 관련 변경: 이전 planPrice 필드 유효성/스키마를 다루던 PR으로 관련성 높음

Suggested reviewers

  • woals2840
  • bigpie1367

Poem

🐇✨ 월간과 연간, 둘로 나뉜 당근빛 가격
새 링크 한 줄로 플랜이 반짝 반겨요
DTO와 엔티티, 서비스가 손잡고 춤을 춰
깔끔히 정리했으니 배포도 뽀송해요 🥕🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 링크된 이슈의 주요 변경 사항인 플랜 가격 이원화 및 플랜 링크 필드 추가를 명확하게 반영하고 있습니다.
Linked Issues check ✅ Passed 플랜 가격을 연간/월간으로 이원화하고(CreateToolPlanRequest, Plan, PlanRes), 플랜 링크 필드를 PlanListRes에 추가한 모든 요구사항이 구현되었습니다.
Out of Scope Changes check ✅ Passed AdminService의 필터링 조건 변경과 PlanListRes 팩토리 메서드 수정은 모두 이슈 #341의 요구사항 구현에 직접적으로 필요한 변경사항입니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/#341

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link

github-actions bot commented Dec 1, 2025

Test Results

110 tests   110 ✅  4s ⏱️
 22 suites    0 💤
 22 files      0 ❌

Results for commit 611b92e.

♻️ This comment has been updated with latest results.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6c6af8 and db29b4e.

📒 Files selected for processing (6)
  • src/main/java/com/daruda/darudaserver/domain/admin/dto/request/CreateToolPlanRequest.java (1 hunks)
  • src/main/java/com/daruda/darudaserver/domain/admin/service/AdminService.java (1 hunks)
  • src/main/java/com/daruda/darudaserver/domain/tool/dto/res/PlanListRes.java (1 hunks)
  • src/main/java/com/daruda/darudaserver/domain/tool/dto/res/PlanRes.java (1 hunks)
  • src/main/java/com/daruda/darudaserver/domain/tool/entity/Plan.java (2 hunks)
  • src/main/java/com/daruda/darudaserver/domain/tool/service/ToolService.java (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: yechan-kim
Repo: Tool-daruda/35-APPJAM-SERVER-DARUDA PR: 340
File: src/main/java/com/daruda/darudaserver/domain/admin/controller/AdminController.java:55-87
Timestamp: 2025-11-27T08:53:05.793Z
Learning: In `src/main/java/com/daruda/darudaserver/domain/admin/controller/AdminController.java`, the `planType` field accepts Korean string values ("무료", "월간", "구매", "월간 & 연간") from the API request and internally converts them to enum values (FREE, MONTHLY, PURCHASE, MONTHLY_ANNUAL). The API documentation should show the Korean strings that clients need to send, not the internal enum names.
📚 Learning: 2025-11-27T08:53:05.793Z
Learnt from: yechan-kim
Repo: Tool-daruda/35-APPJAM-SERVER-DARUDA PR: 340
File: src/main/java/com/daruda/darudaserver/domain/admin/controller/AdminController.java:55-87
Timestamp: 2025-11-27T08:53:05.793Z
Learning: In `src/main/java/com/daruda/darudaserver/domain/admin/controller/AdminController.java`, the `planType` field accepts Korean string values ("무료", "월간", "구매", "월간 & 연간") from the API request and internally converts them to enum values (FREE, MONTHLY, PURCHASE, MONTHLY_ANNUAL). The API documentation should show the Korean strings that clients need to send, not the internal enum names.

Applied to files:

  • src/main/java/com/daruda/darudaserver/domain/admin/dto/request/CreateToolPlanRequest.java
🔇 Additional comments (6)
src/main/java/com/daruda/darudaserver/domain/admin/service/AdminService.java (1)

267-276: priceAnnual 필터링 누락 가능성 검토

priceMonthlynull 체크를 하고 있습니다. CreateToolPlanRequest에서 priceAnnual@NotNull이 적용되어 있다면 이 필터 조건은 충분합니다. 하지만 priceAnnual이 선택 사항으로 변경될 경우, 필터 조건도 함께 업데이트해야 합니다.

CreateToolPlanRequest의 검증 어노테이션과 일관성을 확인해주세요.

src/main/java/com/daruda/darudaserver/domain/tool/dto/res/PlanListRes.java (1)

8-17: LGTM!

planLink 필드 추가 및 팩토리 메서드 업데이트가 깔끔하게 구현되었습니다.

src/main/java/com/daruda/darudaserver/domain/tool/dto/res/PlanRes.java (1)

8-23: LGTM!

단일 가격 필드를 priceAnnualpriceMonthly로 분리하는 변경이 일관성 있게 적용되었습니다.

src/main/java/com/daruda/darudaserver/domain/tool/service/ToolService.java (1)

94-100: LGTM!

변수명 변경(plantoolPlans)으로 가독성이 향상되었고, PlanListRes.of 호출이 새로운 시그니처에 맞게 업데이트되었습니다.

src/main/java/com/daruda/darudaserver/domain/tool/entity/Plan.java (2)

35-39: 월/연간 가격 컬럼 null 정책이 비즈니스 요구와 일치하는지 확인 필요

price_monthlynullable = false, price_annual은 nullable 로 두셨는데, 지금 구조상 모든 플랜에 월간 가격이 반드시 있어야 하는 전제로 보입니다.

  • Admin 쪽에서 priceMonthly를 필터 조건으로 사용하고 있다면(요약에 따르면 p.priceMonthly() != null), "구매" 타입이나 향후 "연간 전용"과 같은 플랜이 생겼을 때 월간 가격을 어떻게 처리할지(0으로 둘지, 반드시 존재해야 할지) 명확히 해야 합니다.
  • 기존 데이터 마이그레이션 시에도 price_monthly가 NOT NULL 제약을 만족하는지 한번 더 체크해 두는 게 안전해 보입니다.

요구사항 상 "월간 & 연간" 조합 타입까지 고려했을 때 이 설계가 의도와 정확히 맞는지 한 번만 더 검토 부탁드립니다.

Based on learnings.


48-55: CreateToolPlanRequest → Plan 매핑은 자연스럽지만 null 처리 의도 재확인 권장

Plan.create에서:

.planName(toolPlanRequest.planName())
.priceMonthly(toolPlanRequest.priceMonthly())
.priceAnnual(toolPlanRequest.priceAnnual())

로 매핑하신 부분은 직관적이고 DTO 변경사항과도 잘 맞습니다. 다만:

  • priceMonthly()가 null인 요청이 들어올 경우 JPA 레벨에서 NOT NULL 제약 위반이 날 수 있으므로,
    • DTO에서 @NotNull + 검증으로 막을지,
    • 아니면 여기서 기본값(예: 0L)을 강제할지 정책을 한 번만 더 명시해 두시는 게 좋습니다.
  • priceAnnual()은 null 허용이므로, "월간 전용" 플랜에 대해 실제로 null을 저장하는 것이 의도인지, 아니면 0 등의 기본값을 두고 싶은지 API 설계와 맞춰 주세요.

현재 구현 자체는 문제 없어 보이며, 상위 계층 DTO/서비스의 검증과 일관성만 확인되면 그대로 가도 될 것 같습니다.

Copy link
Member

@bigpie1367 bigpie1367 left a comment

Choose a reason for hiding this comment

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

고생 많으셨습니다!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/main/java/com/daruda/darudaserver/domain/admin/dto/request/CreateToolPlanRequest.java (2)

23-23: 검증 메시지 구체화 권장

두 필드 모두 동일한 메시지 "플랜 가격은 0 이상이어야 합니다."를 사용하고 있습니다. 더 명확한 메시지로 개선할 수 있습니다:

-	@PositiveOrZero(message = "플랜 가격은 0 이상이어야 합니다.")
+	@PositiveOrZero(message = "월간 플랜 가격은 0 이상이어야 합니다.")
 	Long priceMonthly,
 	@Schema(
 		description = "연간 플랜 가격(원화)",
 		example = "10000",
 		requiredMode = Schema.RequiredMode.NOT_REQUIRED
 	)
-	@PositiveOrZero(message = "플랜 가격은 0 이상이어야 합니다.")
+	@PositiveOrZero(message = "연간 플랜 가격은 0 이상이어야 합니다.")
 	Long priceAnnual,

Also applies to: 30-30


19-19: 예시 값 차별화 권장

월간 가격과 연간 가격 모두 "10000"을 예시로 사용하고 있습니다. 일반적으로 연간 플랜은 할인된 가격을 제공하므로, 예시 값을 다르게 설정하면 API 사용자에게 더 명확한 가이드를 제공할 수 있습니다.

 	@Schema(
 		description = "월간 플랜 가격(원화)",
 		example = "10000",
 		requiredMode = Schema.RequiredMode.REQUIRED
 	)
 	@NotNull(message = "월간 플랜 가격은 필수입니다.")
 	@PositiveOrZero(message = "플랜 가격은 0 이상이어야 합니다.")
 	Long priceMonthly,
 	@Schema(
 		description = "연간 플랜 가격(원화)",
-		example = "10000",
+		example = "100000",
 		requiredMode = Schema.RequiredMode.NOT_REQUIRED
 	)

Also applies to: 27-27

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db29b4e and 611b92e.

📒 Files selected for processing (1)
  • src/main/java/com/daruda/darudaserver/domain/admin/dto/request/CreateToolPlanRequest.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-27T08:53:05.793Z
Learnt from: yechan-kim
Repo: Tool-daruda/35-APPJAM-SERVER-DARUDA PR: 340
File: src/main/java/com/daruda/darudaserver/domain/admin/controller/AdminController.java:55-87
Timestamp: 2025-11-27T08:53:05.793Z
Learning: In `src/main/java/com/daruda/darudaserver/domain/admin/controller/AdminController.java`, the `planType` field accepts Korean string values ("무료", "월간", "구매", "월간 & 연간") from the API request and internally converts them to enum values (FREE, MONTHLY, PURCHASE, MONTHLY_ANNUAL). The API documentation should show the Korean strings that clients need to send, not the internal enum names.

Applied to files:

  • src/main/java/com/daruda/darudaserver/domain/admin/dto/request/CreateToolPlanRequest.java
🔇 Additional comments (2)
src/main/java/com/daruda/darudaserver/domain/admin/dto/request/CreateToolPlanRequest.java (2)

18-31: 검증 어노테이션 일관성 수정 확인

이전 리뷰에서 지적된 검증 어노테이션 불일치 문제가 수정되었습니다:

  • priceMonthly: @NotNull 추가 및 REQUIRED 스키마와 일치 ✓
  • priceAnnual: @NotNull 제거 및 NOT_REQUIRED 스키마와 일치 ✓

API 문서와 실제 검증 동작이 일관되게 정렬되었습니다.


25-31: No issue found - priceAnnual null handling is correct

The priceAnnual field is properly designed as optional and handles null values correctly throughout the codebase:

  • The DTO field has no @NotNull constraint and is marked NOT_REQUIRED, allowing null values
  • The @PositiveOrZero validation only applies when the value is present (not null)
  • The Plan entity correctly defines priceAnnual as nullable in the database schema
  • Both Plan.create() and AdminService.updateTool() properly pass null values without issues

No null handling verification or changes are needed.

Likely an incorrect or invalid review comment.

@yechan-kim yechan-kim merged commit 3311c0a into develop Dec 1, 2025
3 checks passed
@yechan-kim yechan-kim deleted the fix/#341 branch December 1, 2025 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Fix] Tool Plan 수정 사항 반영

2 participants

Comments