diff --git a/.gitignore b/.gitignore index 7cdf4c9..6cd18f1 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ docs/* # --- Claude/Gemini context files (local only, never push) --- CLAUDE.md GEMINI.md +.claude/* diff --git a/hms-api/src/main/java/com/hospital/hms/auth/service/AccountQueryService.java b/hms-api/src/main/java/com/hospital/hms/auth/service/AccountQueryService.java new file mode 100644 index 0000000..1cd6680 --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/auth/service/AccountQueryService.java @@ -0,0 +1,18 @@ +package com.hospital.hms.auth.service; + +import com.hospital.hms.auth.entity.Account; +import com.hospital.hms.auth.repository.AccountRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class AccountQueryService { + private final AccountRepository accountRepository; + + public Account getReferenceById(UUID id) { + return accountRepository.getReferenceById(id); + } +} diff --git a/hms-api/src/main/java/com/hospital/hms/billing/service/InvoiceQueryService.java b/hms-api/src/main/java/com/hospital/hms/billing/service/InvoiceQueryService.java new file mode 100644 index 0000000..8949497 --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/billing/service/InvoiceQueryService.java @@ -0,0 +1,37 @@ +package com.hospital.hms.billing.service; + +import com.hospital.hms.billing.entity.MedicineInvoice; +import com.hospital.hms.billing.entity.ServiceInvoice; +import com.hospital.hms.billing.repository.MedicineInvoiceRepository; +import com.hospital.hms.billing.repository.ServiceInvoiceRepository; +import com.hospital.hms.medical.entity.MedicalRecord; +import com.hospital.hms.medical.service.MedicalRecordQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class InvoiceQueryService { + private final MedicineInvoiceRepository medicineInvoiceRepository; + private final ServiceInvoiceRepository serviceInvoiceRepository; + private final MedicalRecordQueryService medicalRecordQueryService; + + @Transactional + public void initInvoices(UUID id) { + MedicalRecord mr = medicalRecordQueryService.getReferenceById(id); + + MedicineInvoice mi = MedicineInvoice.builder() + .medicalRecord(mr) + .isPaid(false) + .build(); + medicineInvoiceRepository.save(mi); + + ServiceInvoice si = ServiceInvoice.builder() + .medicalRecord(mr) + .build(); + serviceInvoiceRepository.save(si); + } +} diff --git a/hms-api/src/main/java/com/hospital/hms/medical/controller/MedicalRecordController.java b/hms-api/src/main/java/com/hospital/hms/medical/controller/MedicalRecordController.java index 3f90f0c..7c838c4 100644 --- a/hms-api/src/main/java/com/hospital/hms/medical/controller/MedicalRecordController.java +++ b/hms-api/src/main/java/com/hospital/hms/medical/controller/MedicalRecordController.java @@ -2,12 +2,16 @@ import com.hospital.hms.base.api.ApiResponse; import com.hospital.hms.base.response.PaginatedResponse; +import com.hospital.hms.medical.request.CreateMedicalRecordRequest; import com.hospital.hms.medical.request.MedicalRecordIdRequest; import com.hospital.hms.medical.request.SearchMedicalRecordRequest; +import com.hospital.hms.medical.request.UpdateMedicalRecordRequest; import com.hospital.hms.medical.response.MedicalRecordDetailResponse; import com.hospital.hms.medical.response.MedicalRecordResponse; +import com.hospital.hms.medical.service.CreateMedicalRecordService; import com.hospital.hms.medical.service.GetMedicalRecordDetailService; import com.hospital.hms.medical.service.GetMedicalRecordService; +import com.hospital.hms.medical.service.UpdateMedicalRecordService; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -28,6 +32,8 @@ public class MedicalRecordController { private final GetMedicalRecordService getMedicalRecordService; private final GetMedicalRecordDetailService getMedicalRecordDetailService; + private final CreateMedicalRecordService createMedicalRecordService; + private final UpdateMedicalRecordService updateMedicalRecordService; @GetMapping @PreAuthorize("hasAnyRole('ADMIN', 'RECEPTIONIST', 'DOCTOR')") @@ -52,4 +58,29 @@ public ResponseEntity> getMedicalRecord ApiResponse.success(data, "Get medical record detail successfully", HttpStatus.OK.value()) ); } + + @PostMapping + @PreAuthorize("hasRole('ROLE_DOCTOR')") + public ResponseEntity> createMedicalRecord( + @Valid @RequestBody CreateMedicalRecordRequest request + ) { + MedicalRecordDetailResponse data = createMedicalRecordService.execute(request); + return ResponseEntity.status(HttpStatus.CREATED).body( + ApiResponse.success(data, "Create medical record successfully", HttpStatus.CREATED.value()) + ); + } + + @PutMapping("/{id}") + @PreAuthorize("hasRole('ROLE_DOCTOR')") + public ResponseEntity> updateMedicalRecord( + @Valid @RequestBody UpdateMedicalRecordRequest request, + @PathVariable UUID id + ) { + request.setId(id); + + MedicalRecordDetailResponse data = updateMedicalRecordService.execute(request); + return ResponseEntity.status(HttpStatus.OK).body( + ApiResponse.success(data, "Update medical record detail successfully", HttpStatus.OK.value()) + ); + } } diff --git a/hms-api/src/main/java/com/hospital/hms/medical/request/CreateMedicalRecordRequest.java b/hms-api/src/main/java/com/hospital/hms/medical/request/CreateMedicalRecordRequest.java new file mode 100644 index 0000000..a6a9582 --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/medical/request/CreateMedicalRecordRequest.java @@ -0,0 +1,26 @@ +package com.hospital.hms.medical.request; + +import com.hospital.hms.base.request.BaseRequest; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.UUID; + +@Getter +@Setter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class CreateMedicalRecordRequest extends BaseRequest { + + @NotNull(message = "Id are required") + private UUID patientId; + + private String advice; + + @NotBlank(message = "Description is required") + private String description; +} diff --git a/hms-api/src/main/java/com/hospital/hms/medical/request/UpdateMedicalRecordRequest.java b/hms-api/src/main/java/com/hospital/hms/medical/request/UpdateMedicalRecordRequest.java new file mode 100644 index 0000000..182fa48 --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/medical/request/UpdateMedicalRecordRequest.java @@ -0,0 +1,21 @@ +package com.hospital.hms.medical.request; + +import com.hospital.hms.base.request.BaseRequest; +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.UUID; + +@Getter +@Setter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class UpdateMedicalRecordRequest extends BaseRequest { + private UUID id; + + private String advice; + + private String description; +} diff --git a/hms-api/src/main/java/com/hospital/hms/medical/service/CreateMedicalRecordService.java b/hms-api/src/main/java/com/hospital/hms/medical/service/CreateMedicalRecordService.java new file mode 100644 index 0000000..1ea44df --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/medical/service/CreateMedicalRecordService.java @@ -0,0 +1,55 @@ +package com.hospital.hms.medical.service; + +import com.hospital.hms.auth.service.AccountQueryService; +import com.hospital.hms.base.service.BaseService; +import com.hospital.hms.billing.service.InvoiceQueryService; +import com.hospital.hms.employee.response.EmployeeResponse; +import com.hospital.hms.employee.service.EmployeeQueryService; +import com.hospital.hms.medical.entity.MedicalRecord; +import com.hospital.hms.medical.repository.MedicalRecordRepository; +import com.hospital.hms.medical.request.CreateMedicalRecordRequest; +import com.hospital.hms.medical.response.MedicalRecordDetailResponse; +import com.hospital.hms.patient.service.PatientQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class CreateMedicalRecordService extends BaseService { + + private final PatientQueryService patientQueryService; + private final EmployeeQueryService employeeQueryService; + private final AccountQueryService accountQueryService; + private final MedicalRecordRepository medicalRecordRepository; + private final InvoiceQueryService invoiceQueryService; + + @Override + @Transactional + public MedicalRecordDetailResponse execute(CreateMedicalRecordRequest request) { + return super.execute(request); + } + + @Override + protected MedicalRecordDetailResponse doProcess(CreateMedicalRecordRequest request) { + if (request.getUserContext() == null) { + throw new AccessDeniedException("You do not have permission to access this resource"); + } + + MedicalRecord mr = MedicalRecord.builder() + .patient(patientQueryService.getReferenceById(request.getPatientId())) + .doctor(accountQueryService.getReferenceById(request.getUserContext().getUserId())) + .doctorAdvice(request.getAdvice()) + .description(request.getDescription()) + .build(); + + MedicalRecord saved = medicalRecordRepository.save(mr); + + invoiceQueryService.initInvoices(saved.getId()); + + EmployeeResponse er = employeeQueryService.getByAccountId(request.getUserContext().getUserId()); + + return MedicalRecordDetailResponse.from(saved, er); + } +} diff --git a/hms-api/src/main/java/com/hospital/hms/medical/service/MedicalRecordQueryService.java b/hms-api/src/main/java/com/hospital/hms/medical/service/MedicalRecordQueryService.java new file mode 100644 index 0000000..323a5ae --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/medical/service/MedicalRecordQueryService.java @@ -0,0 +1,19 @@ +package com.hospital.hms.medical.service; + +import com.hospital.hms.medical.entity.MedicalRecord; +import com.hospital.hms.medical.repository.MedicalRecordRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class MedicalRecordQueryService { + + private final MedicalRecordRepository medicalRecordRepository; + + public MedicalRecord getReferenceById(UUID id) { + return medicalRecordRepository.getReferenceById(id); + } +} diff --git a/hms-api/src/main/java/com/hospital/hms/medical/service/UpdateMedicalRecordService.java b/hms-api/src/main/java/com/hospital/hms/medical/service/UpdateMedicalRecordService.java new file mode 100644 index 0000000..f7e134c --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/medical/service/UpdateMedicalRecordService.java @@ -0,0 +1,57 @@ +package com.hospital.hms.medical.service; + +import com.hospital.hms.base.service.BaseService; +import com.hospital.hms.employee.response.EmployeeResponse; +import com.hospital.hms.employee.service.EmployeeQueryService; +import com.hospital.hms.exception.NotFoundException; +import com.hospital.hms.medical.entity.MedicalRecord; +import com.hospital.hms.medical.repository.MedicalRecordRepository; +import com.hospital.hms.medical.request.UpdateMedicalRecordRequest; +import com.hospital.hms.medical.response.MedicalRecordDetailResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class UpdateMedicalRecordService extends BaseService { + + private final MedicalRecordRepository medicalRecordRepository; + private final EmployeeQueryService employeeQueryService; + + @Override + @Transactional + public MedicalRecordDetailResponse execute(UpdateMedicalRecordRequest request) { + return super.execute(request); + } + + @Override + protected MedicalRecordDetailResponse doProcess(UpdateMedicalRecordRequest request) { + if (request.getUserContext() == null) { + throw new AccessDeniedException("You do not have permission to access this resource"); + } + + MedicalRecord response = medicalRecordRepository.findById(request.getId()).orElseThrow( + () -> new NotFoundException("Medical record not found") + ); + + if (!response.getDoctor().getId().equals(request.getUserContext().getUserId())) { + throw new AccessDeniedException("You do not have permission to access this resource"); + } + + if (request.getAdvice() != null && !request.getAdvice().isBlank()) { + response.setDoctorAdvice(request.getAdvice()); + } + + if (request.getDescription() != null && !request.getDescription().isBlank()) { + response.setDescription(request.getDescription()); + } + + MedicalRecord saved = medicalRecordRepository.save(response); + + EmployeeResponse er = employeeQueryService.getByAccountId(saved.getDoctor().getId()); + + return MedicalRecordDetailResponse.from(saved, er); + } +} diff --git a/hms-api/src/main/java/com/hospital/hms/patient/service/PatientQueryService.java b/hms-api/src/main/java/com/hospital/hms/patient/service/PatientQueryService.java new file mode 100644 index 0000000..ccb20c1 --- /dev/null +++ b/hms-api/src/main/java/com/hospital/hms/patient/service/PatientQueryService.java @@ -0,0 +1,26 @@ +package com.hospital.hms.patient.service; + +import com.hospital.hms.exception.NotFoundException; +import com.hospital.hms.patient.entity.PatientInfo; +import com.hospital.hms.patient.repository.PatientInfoRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class PatientQueryService { + + private final PatientInfoRepository patientInfoRepository; + + @Transactional(readOnly = true) + public PatientInfo getReferenceById(UUID id) { + if (!patientInfoRepository.existsById(id)) { + throw new NotFoundException("Patient with id " + id + " not found"); + } + return patientInfoRepository.getReferenceById(id); + } + +}