diff --git a/src/main/java/com/piuda/callcare/domain/medication/controller/MedicationController.java b/src/main/java/com/piuda/callcare/domain/medication/controller/MedicationController.java index 422a668..96eb833 100644 --- a/src/main/java/com/piuda/callcare/domain/medication/controller/MedicationController.java +++ b/src/main/java/com/piuda/callcare/domain/medication/controller/MedicationController.java @@ -1,7 +1,7 @@ package com.piuda.callcare.domain.medication.controller; import com.piuda.callcare.domain.medication.dto.request.MedicationCreateRequest; -import com.piuda.callcare.domain.medication.dto.response.MedicationDetailResponse; +import com.piuda.callcare.domain.medication.dto.response.MedicationGroupItemResponse; import com.piuda.callcare.domain.medication.dto.response.MedicationResponse; import com.piuda.callcare.domain.medication.service.command.MedicationCommandService; import com.piuda.callcare.domain.medication.service.query.MedicationQueryService; @@ -11,10 +11,12 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; +import java.time.LocalDate; import java.util.List; @Tag(name = "Medication", description = "약 등록 API") @@ -35,12 +37,14 @@ public ResponseEntity>> registerBatch( return ResponseUtils.created(medicationCommandService.registerBatch(userId, requests)); } - @Operation(summary = "약 상세 정보 조회", description = "약 카드 클릭 시 주의사항/부작용/용법·용량/효능·효과를 반환합니다. DrugInfo 미연결 약은 의약품 정보 필드 null로 반환됩니다.") - @GetMapping("/{medicationId}/detail") - public ResponseEntity> getDetail( + @Operation(summary = "약물노트 그룹 상세 조회", description = "병원+처방일 그룹 카드 클릭 시 해당 그룹의 약 리스트와 각 약의 메모를 반환합니다. hospitalName/prescriptionDate 미전달 시 null 그룹 조회.") + @GetMapping("/group") + public ResponseEntity>> getGroup( @AuthenticationPrincipal Long userId, - @PathVariable Long medicationId + @RequestParam Long seniorId, + @RequestParam(required = false) String hospitalName, + @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate prescriptionDate ) { - return ResponseUtils.ok(medicationQueryService.getDetail(userId, medicationId)); + return ResponseUtils.ok(medicationQueryService.getGroup(userId, seniorId, hospitalName, prescriptionDate)); } } diff --git a/src/main/java/com/piuda/callcare/domain/medication/converter/MedicationConverter.java b/src/main/java/com/piuda/callcare/domain/medication/converter/MedicationConverter.java index 7b70b87..5319793 100644 --- a/src/main/java/com/piuda/callcare/domain/medication/converter/MedicationConverter.java +++ b/src/main/java/com/piuda/callcare/domain/medication/converter/MedicationConverter.java @@ -1,7 +1,6 @@ package com.piuda.callcare.domain.medication.converter; -import com.piuda.callcare.domain.druginfo.entity.DrugInfo; -import com.piuda.callcare.domain.medication.dto.response.MedicationDetailResponse; +import com.piuda.callcare.domain.medication.dto.response.MedicationGroupItemResponse; import com.piuda.callcare.domain.medication.dto.response.MedicationResponse; import com.piuda.callcare.domain.medication.entity.Medication; import com.piuda.callcare.domain.medication.entity.MedicationSchedule; @@ -13,18 +12,19 @@ @Component public class MedicationConverter { - // Medication → MedicationDetailResponse (약 상세 조회용, DrugInfo 없으면 전 필드 null) - public MedicationDetailResponse toDetailResponse(Medication medication) { - DrugInfo drugInfo = medication.getDrugInfo(); - if (drugInfo == null) { - return new MedicationDetailResponse(medication.getDrugName(), null, null, null, null); - } - return new MedicationDetailResponse( + // Medication → MedicationGroupItemResponse (약물노트 그룹 상세 조회용) + public MedicationGroupItemResponse toGroupItemResponse(Medication medication) { + return new MedicationGroupItemResponse( + medication.getId(), medication.getDrugName(), - drugInfo.getEfcyQesitm(), - drugInfo.getUseMethodQesitm(), - drugInfo.getAtpnQesitm(), - drugInfo.getSeQesitm() + medication.getDrugType(), + medication.getImageUrl(), + medication.getTimesPerDay(), + medication.getDosagePerTime(), + medication.getStartDate(), + medication.getEndDate(), + medication.getTotalDays(), + medication.getMemo() ); } diff --git a/src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationDetailResponse.java b/src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationDetailResponse.java deleted file mode 100644 index 9caeb76..0000000 --- a/src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationDetailResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.piuda.callcare.domain.medication.dto.response; - -import io.swagger.v3.oas.annotations.media.Schema; - -@Schema(description = "약 상세 정보 응답 — drugName은 항상 반환, DrugInfo 미연결 시 의약품 정보 필드 null") -public record MedicationDetailResponse( - - @Schema(description = "약품명") - String drugName, - - @Schema(description = "효능·효과 (없으면 null)") - String efcyQesitm, - - @Schema(description = "용법·용량 (없으면 null)") - String useMethodQesitm, - - @Schema(description = "주의사항 (없으면 null)") - String atpnQesitm, - - @Schema(description = "부작용 (없으면 null)") - String seQesitm -) { -} diff --git a/src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationGroupItemResponse.java b/src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationGroupItemResponse.java new file mode 100644 index 0000000..d5f5f74 --- /dev/null +++ b/src/main/java/com/piuda/callcare/domain/medication/dto/response/MedicationGroupItemResponse.java @@ -0,0 +1,39 @@ +package com.piuda.callcare.domain.medication.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDate; + +@Schema(description = "그룹 내 약 단건 응답") +public record MedicationGroupItemResponse( + + @Schema(description = "약 ID") + Long medicationId, + + @Schema(description = "약 이름") + String drugName, + + @Schema(description = "약 종류 (없으면 null)") + String drugType, + + @Schema(description = "약 이미지 URL (없으면 null)") + String imageUrl, + + @Schema(description = "1일 복용 횟수") + Integer timesPerDay, + + @Schema(description = "1회 복용량 (예: 1정, 5ml)") + String dosagePerTime, + + @Schema(description = "복용 시작일") + LocalDate startDate, + + @Schema(description = "복용 종료일 (없으면 null)") + LocalDate endDate, + + @Schema(description = "총 복용 일수 (없으면 null)") + Integer totalDays, + + @Schema(description = "메모 — OCR 자동 생성 또는 사용자 직접 입력 (없으면 null)") + String memo +) {} diff --git a/src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java b/src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java index edba5c0..0ccf481 100644 --- a/src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java +++ b/src/main/java/com/piuda/callcare/domain/medication/repository/MedicationRepository.java @@ -1,5 +1,6 @@ package com.piuda.callcare.domain.medication.repository; +import java.time.LocalDate; import java.util.List; import com.piuda.callcare.domain.medication.entity.Medication; @@ -27,4 +28,17 @@ public interface MedicationRepository extends JpaRepository { AND m.isActive = true """) List findActiveWithDrugInfoBySeniorId(@Param("seniorId") Long seniorId); + + // 약물노트 그룹 상세 조회: 병원명 + 처방일 조합이 그룹 키 (둘 다 null 가능) + @Query(""" + SELECT m FROM Medication m + WHERE m.senior.id = :seniorId + AND ((:hospitalName IS NULL AND m.hospitalName IS NULL) OR m.hospitalName = :hospitalName) + AND ((:prescriptionDate IS NULL AND m.prescriptionDate IS NULL) OR m.prescriptionDate = :prescriptionDate) + AND m.isActive = true + ORDER BY m.createdAt ASC + """) + List findByGroup(@Param("seniorId") Long seniorId, + @Param("hospitalName") String hospitalName, + @Param("prescriptionDate") LocalDate prescriptionDate); } diff --git a/src/main/java/com/piuda/callcare/domain/medication/service/query/MedicationQueryService.java b/src/main/java/com/piuda/callcare/domain/medication/service/query/MedicationQueryService.java index 9ed22d0..7bebaf0 100644 --- a/src/main/java/com/piuda/callcare/domain/medication/service/query/MedicationQueryService.java +++ b/src/main/java/com/piuda/callcare/domain/medication/service/query/MedicationQueryService.java @@ -1,29 +1,37 @@ package com.piuda.callcare.domain.medication.service.query; import com.piuda.callcare.domain.medication.converter.MedicationConverter; -import com.piuda.callcare.domain.medication.dto.response.MedicationDetailResponse; +import com.piuda.callcare.domain.medication.dto.response.MedicationGroupItemResponse; import com.piuda.callcare.domain.medication.entity.Medication; import com.piuda.callcare.domain.medication.repository.MedicationRepository; +import com.piuda.callcare.domain.senior.repository.SeniorRepository; import com.piuda.callcare.global.exception.CallCareException; import com.piuda.callcare.global.exception.ErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; +import java.util.List; + @Service @Transactional(readOnly = true) @RequiredArgsConstructor public class MedicationQueryService { private final MedicationRepository medicationRepository; + private final SeniorRepository seniorRepository; private final MedicationConverter medicationConverter; - public MedicationDetailResponse getDetail(Long userId, Long medicationId) { - Medication medication = medicationRepository.findById(medicationId) - .orElseThrow(() -> new CallCareException(ErrorCode.MEDICATION_NOT_FOUND)); - if (userId != null && !medication.getSenior().getUser().getId().equals(userId)) { + public List getGroup(Long userId, Long seniorId, String hospitalName, LocalDate prescriptionDate) { + if (userId == null) { throw new CallCareException(ErrorCode.FORBIDDEN); } - return medicationConverter.toDetailResponse(medication); + seniorRepository.findByIdAndUser_Id(seniorId, userId) + .orElseThrow(() -> new CallCareException(ErrorCode.SENIOR_NOT_FOUND)); + List medications = medicationRepository.findByGroup(seniorId, hospitalName, prescriptionDate); + return medications.stream() + .map(medicationConverter::toGroupItemResponse) + .toList(); } }