Skip to content

[Feat]: 약물노트 병원+처방일 그룹 상세 조회 API 구현 - #56

Merged
kangcheolung merged 6 commits into
developfrom
feature/55
Jul 9, 2026
Merged

kangcheolung merged 6 commits into
developfrom
feature/55

Conversation

@kangcheolung

@kangcheolung kangcheolung commented Jul 9, 2026 •

Copy link
Copy Markdown
Member

🔍️작업 내용

✨ 상세 설명

약물노트 병원+처방일 그룹 상세 조회 API 구현

변경 내용

  • GET /api/medications/{id}/detail 제거
  • GET /api/medications/group 신규 추가
    • 파라미터: seniorId, hospitalName(선택), prescriptionDate(선택)
    • 응답: 병원+처방일 그룹에 속한 약 리스트 (약 이름, 복용 정보, memo)
  • 그룹 키: hospitalName + prescriptionDate 조합 (둘 다 null 허용)
  • userId non-null 시 seniorId 소유권 검증

삭제

  • MedicationDetailResponse
  • MedicationConverter.toDetailResponse()
  • MedicationQueryService.getDetail()

🛠 추후 리팩토링 및 고도화 계획

  • 인증 필터 도입 후 GET /api/medications/** permitAll 제거 및 소유권 검증 의무화

💬 리뷰 요구사항

Summary by CodeRabbit

  • New Features
    • 약물 조회가 단건 상세에서 그룹 상세 목록으로 바뀌었습니다.
    • 새 그룹 상세 조회 API로 약 리스트와 메모를 함께 확인할 수 있으며, 병원명과 처방일로도 필터링할 수 있습니다.
  • Bug Fixes
    • 활성 상태의 약만 그룹 조회에 포함되도록 개선했습니다.
    • 사용자-대상자 매칭 검증을 강화해 권한 없는 조회를 방지했습니다.
  • Documentation
    • 응답 항목과 API 문서 정보가 새 그룹 조회 형식에 맞게 갱신되었습니다.

kangcheolung and others added 5 commits July 9, 2026 16:16
DrugInfo 기반 상세 응답 폐기, 약물노트 그룹 상세 조회용 DTO로 교체

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
병원명 + 처방일 조합으로 그룹 조회, null 파라미터 처리 포함

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
병원명 + 처방일 기준 그룹 내 약 리스트 조회, userId 소유권 검증 포함

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kangcheolung, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe44c0c7-69fa-4d07-a2b0-85509f9f4373

📥 Commits

Reviewing files that changed from the base of the PR and between f0af124 and af55d56.

📒 Files selected for processing (1)
  • src/main/java/com/piuda/callcare/domain/medication/service/query/MedicationQueryService.java
📝 Walkthrough

Walkthrough

약물노트의 "약 상세 정보 조회" 기능(MedicationDetailResponse, getDetail, /{medicationId}/detail)이 통째로 제거되고, 병원명과 처방일 기준으로 약을 그룹핑해 반환하는 "약물노트 그룹 조회" 기능(MedicationGroupItemResponse, getGroup, GET /api/medications/group)이 컨트롤러·서비스·리포지토리·컨버터에 새로 도입되었다.

Changes

약 상세 조회 → 그룹 조회 전환

Layer / File(s) Summary
그룹 응답 DTO 정의
.../dto/response/MedicationGroupItemResponse.java
약 단건 정보(id, drugName, drugType, imageUrl, timesPerDay, dosagePerTime, startDate, endDate, totalDays, memo)를 담는 신규 레코드 DTO와 Schema 문서화 추가.
그룹 키 기반 조회 쿼리
.../repository/MedicationRepository.java
seniorId + hospitalName/prescriptionDate(NULL 매칭 포함)로 활성 약을 조회해 createdAt 오름차순 반환하는 findByGroup 추가.
그룹 항목 변환 로직
.../converter/MedicationConverter.java
DrugInfo 분기로 null 처리하던 toDetailResponse 제거, Medication 필드를 그대로 매핑하는 toGroupItemResponse 추가.
그룹 조회 서비스 로직
.../service/query/MedicationQueryService.java
getDetail(소유권 검증) 제거, SeniorRepository로 선임-사용자 매칭 검증 후 findByGroup + toGroupItemResponse로 리스트 반환하는 getGroup 추가.
그룹 조회 엔드포인트 노출
.../controller/MedicationController.java
/{medicationId}/detail 제거, seniorId 필수·hospitalName/prescriptionDate(선택) 파라미터를 받는 GET /group 신규 추가.

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

Possibly related PRs

  • PIUDAProject/Backend#54: 동일한 MedicationController/MedicationConverter/MedicationQueryService의 약 상세 조회 경로를 다뤄 이번 PR의 제거 대상 코드와 직접 연결됨.

Suggested labels: ✨ Feature


버그/성능/설계 관점 코멘트: 삭제된 상세 조회 대신 그룹 조회로 완전히 갈아탄 점은 명확하지만, findByGroup의 JPQL에서 hospitalName/prescriptionDate NULL 매칭 조건이 실제로 "병원 정보 없음" 그룹 요구사항(이슈 #55)을 충족하는지, 그리고 getGroup이 리스트가 비었을 때(그룹 없음) 별도 예외 없이 빈 리스트를 반환하는지 확인이 필요합니다. 또한 SeniorRepository 의존성 추가로 MedicationQueryService의 책임이 다소 늘었으니 SRP 관점에서 그룹핑 로직을 별도 클래스로 분리할지 검토해볼 만합니다.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 상세 조회를 병원+처방일 그룹 조회로 전환한 핵심 변경을 간결하게 잘 담고 있습니다.
Linked Issues check ✅ Passed 상세 조회 제거, 그룹 조회 API 추가, memo 포함 응답, Swagger 반영까지 요구사항과 대체로 일치합니다.
Out of Scope Changes check ✅ Passed 요구사항과 무관한 변경은 요약상 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/55

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationGroupItemResponse.java (1)

16-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

@Schema에 nullable = true 누락 — null 허용 필드 문서 부정확

drugType, imageUrl, endDate, totalDays, memo 필드는 설명에 "(없으면 null)"로 명시되어 있으나 @Schema(nullable = true)가 설정되지 않았습니다. springdoc 2.8.9는 참조 타입 필드를 기본적으로 non-nullable로 생성하므로, OpenAPI 스펙을 소비하는 클라이언트에서 null 처리 누락이 발생할 수 있습니다.

♻️ 제안: nullable 필드에 `@Schema`(nullable = true) 추가
         `@Schema`(description = "약 종류 (없으면 null)", nullable = true)
         String drugType,

         `@Schema`(description = "약 이미지 URL (없으면 null)", nullable = true)
         String imageUrl,

         `@Schema`(description = "1일 복용 횟수")
         Integer timesPerDay,

         `@Schema`(description = "1회 복용량 (예: 1정, 5ml)")
         String dosagePerTime,

         `@Schema`(description = "복용 시작일")
         LocalDate startDate,

         `@Schema`(description = "복용 종료일 (없으면 null)", nullable = true)
         LocalDate endDate,

         `@Schema`(description = "총 복용 일수 (없으면 null)", nullable = true)
         Integer totalDays,

         `@Schema`(description = "메모 — OCR 자동 생성 또는 사용자 직접 입력 (없으면 null)", nullable = true)
         String memo
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationGroupItemResponse.java`
around lines 16 - 37, The OpenAPI annotations in MedicationGroupItemResponse are
missing nullable metadata for fields documented as “없으면 null”, so update the
`@Schema` declarations on drugType, imageUrl, endDate, totalDays, and memo to
explicitly set nullable = true. Keep the existing DTO shape intact and ensure
the nullable flag is applied on the relevant record components so springdoc
generates the correct schema.
src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java (1)

31-43: 🚀 Performance & Scalability | 🔵 Trivial

JPQL null-safe 패턴 및 정렬 로직 검증 완료

(:param IS NULL AND m.field IS NULL) OR m.field = :param 패턴이 null 파라미터와 non-null 파라미터 모두에 대해 올바르게 동작합니다. m.createdAt 기준 오름차순 정렬도 BaseEntity의 @CreatedDate 필드와 일치합니다. 엔티티 필드 경로(m.senior.id, m.hospitalName, m.prescriptionDate, m.isActive)도 Medication 엔티티 정의와 정확히 매칭됩니다.

운영 관점 제안: findByGroup 쿼리가 senior_id, hospital_name, prescription_date, is_active 조건으로 필터링하므로, 해당 컬럼 조합에 복합 인덱스를 추가하면 대량 데이터 환경에서 성능이 크 개선됩니다.

CREATE INDEX idx_medication_group ON medication (senior_id, hospital_name, prescription_date, is_active);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java`
around lines 31 - 43, The `findByGroup` query in `MedicationRepository` is
correct, but its filter pattern can benefit from a composite index for better
performance on large datasets. Add a database index covering the columns used by
this query (`senior_id`, `hospital_name`, `prescription_date`, `is_active`)
through the project’s migration/schema mechanism so the `Medication` lookups for
group retrieval stay efficient.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/piuda/callcare/domain/medication/service/query/MedicationQueryService.java`:
- Around line 26-30: The ownership check in MedicationQueryService.getGroup is
incorrectly skipped when userId is null, which can allow unauthorized access to
another senior’s medication data. Update getGroup so
seniorRepository.findByIdAndUser_Id is always used to verify that the given
seniorId belongs to the requesting user, regardless of whether userId is
present, and keep throwing CallCareException with ErrorCode.SENIOR_NOT_FOUND
when the senior is missing or not owned by the caller. Use the getGroup method
and seniorRepository lookup as the key points for the fix.

---

Nitpick comments:
In
`@src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationGroupItemResponse.java`:
- Around line 16-37: The OpenAPI annotations in MedicationGroupItemResponse are
missing nullable metadata for fields documented as “없으면 null”, so update the
`@Schema` declarations on drugType, imageUrl, endDate, totalDays, and memo to
explicitly set nullable = true. Keep the existing DTO shape intact and ensure
the nullable flag is applied on the relevant record components so springdoc
generates the correct schema.

In
`@src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java`:
- Around line 31-43: The `findByGroup` query in `MedicationRepository` is
correct, but its filter pattern can benefit from a composite index for better
performance on large datasets. Add a database index covering the columns used by
this query (`senior_id`, `hospital_name`, `prescription_date`, `is_active`)
through the project’s migration/schema mechanism so the `Medication` lookups for
group retrieval stay efficient.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6eb09ee4-4ffc-449e-b666-53e604ef2dff

📥 Commits

Reviewing files that changed from the base of the PR and between f73a00a and f0af124.

📒 Files selected for processing (6)
  • src/main/java/com/piuda/callcare/domain/medication/controller/MedicationController.java
  • src/main/java/com/piuda/callcare/domain/medication/converter/MedicationConverter.java
  • src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationDetailResponse.java
  • src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationGroupItemResponse.java
  • src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java
  • src/main/java/com/piuda/callcare/domain/medication/service/query/MedicationQueryService.java
💤 Files with no reviewable changes (1)
  • src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationDetailResponse.java

인증 없는 요청으로 타인 약물 데이터 조회 방지

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@kangcheolung
kangcheolung merged commit af8e6cc into develop Jul 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] 약 상세 정보 조회 기능 제거 및 병원별 처방 그룹 조회 기능으로 전환

1 participant