Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ docs/*
# --- Claude/Gemini context files (local only, never push) ---
CLAUDE.md
GEMINI.md
.claude/*
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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')")
Expand All @@ -52,4 +58,29 @@ public ResponseEntity<ApiResponse<MedicalRecordDetailResponse>> getMedicalRecord
ApiResponse.success(data, "Get medical record detail successfully", HttpStatus.OK.value())
);
}

@PostMapping
@PreAuthorize("hasRole('ROLE_DOCTOR')")
public ResponseEntity<ApiResponse<MedicalRecordDetailResponse>> 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<ApiResponse<MedicalRecordDetailResponse>> 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())
);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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<CreateMedicalRecordRequest, MedicalRecordDetailResponse> {

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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<UpdateMedicalRecordRequest, MedicalRecordDetailResponse> {

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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}

}
Loading