source: backend/src/main/java/medora/service/ProcedureService.java

Last change on this file was cdcff72, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance and fix bugs

  • Property mode set to 100644
File size: 14.9 KB
Line 
1package medora.service;
2
3import medora.dto.SimpleProcedureDTO;
4import medora.models.domain.*;
5import medora.repository.*;
6import org.slf4j.Logger;
7import org.slf4j.LoggerFactory;
8import org.springframework.stereotype.Service;
9import org.springframework.transaction.annotation.Transactional;
10
11import jakarta.persistence.EntityManager;
12import java.time.LocalDate;
13import java.util.List;
14import java.util.Optional;
15
16@Service
17public class ProcedureService {
18
19 private static final Logger logger = LoggerFactory.getLogger(ProcedureService.class);
20
21 private final PerformedProcedureRepository performedProcedureRepository;
22 private final ProcedureRepository procedureRepository;
23 private final PatientRepository patientRepository;
24 private final DoctorRepository doctorRepository;
25 private final DiagnosisRepository diagnosisRepository;
26 private final MedicalRecordRepository medicalRecordRepository;
27 private final MedicalRecordProcedureRepository medicalRecordProcedureRepository;
28 private final ProcedureResultRepository procedureResultRepository;
29 private final MedicalRecordProcedureResultRepository medicalRecordProcedureResultRepository;
30 private final EntityManager entityManager;
31 private final BillingService billingService;
32
33 public ProcedureService(PerformedProcedureRepository performedProcedureRepository,
34 ProcedureRepository procedureRepository,
35 PatientRepository patientRepository,
36 DoctorRepository doctorRepository,
37 DiagnosisRepository diagnosisRepository,
38 MedicalRecordRepository medicalRecordRepository,
39 MedicalRecordProcedureRepository medicalRecordProcedureRepository,
40 ProcedureResultRepository procedureResultRepository,
41 MedicalRecordProcedureResultRepository medicalRecordProcedureResultRepository,
42 EntityManager entityManager,
43 BillingService billingService) {
44
45 this.performedProcedureRepository = performedProcedureRepository;
46 this.procedureRepository = procedureRepository;
47 this.patientRepository = patientRepository;
48 this.doctorRepository = doctorRepository;
49 this.diagnosisRepository = diagnosisRepository;
50 this.medicalRecordRepository = medicalRecordRepository;
51 this.medicalRecordProcedureRepository = medicalRecordProcedureRepository;
52 this.procedureResultRepository = procedureResultRepository;
53 this.medicalRecordProcedureResultRepository = medicalRecordProcedureResultRepository;
54 this.entityManager = entityManager;
55 this.billingService = billingService;
56 }
57
58 // ================= REQUEST PROCEDURE (NEW) =================
59 @Transactional
60 public PerformedProcedures requestProcedureForPatient(Long patientId,
61 Long doctorId,
62 Long procedureId,
63 Long diagnosisId,
64 LocalDate procedureDate,
65 String notes) {
66
67 if (patientId == null || patientId <= 0)
68 throw new IllegalArgumentException("Patient ID must be valid");
69
70 if (doctorId == null || doctorId <= 0)
71 throw new IllegalArgumentException("Doctor ID must be valid");
72
73 if (procedureId == null || procedureId <= 0)
74 throw new IllegalArgumentException("Procedure ID must be valid");
75
76 if (procedureDate == null)
77 throw new IllegalArgumentException("Procedure date is required");
78
79 Patient patient = patientRepository.findById(patientId)
80 .orElseThrow(() -> new RuntimeException("Patient not found"));
81
82 Doctors doctor = doctorRepository.findById(doctorId)
83 .orElseThrow(() -> new RuntimeException("Doctor not found"));
84
85 Procedure procedure = procedureRepository.findById(procedureId)
86 .orElseThrow(() -> new RuntimeException("Procedure not found"));
87
88 PerformedProcedures performed = new PerformedProcedures();
89 performed.setProcedure(procedure);
90 performed.setDoctor(doctor);
91 performed.setPatient(patient);
92 performed.setProcedureDate(procedureDate);
93 performed.setNotes(notes);
94
95 if (diagnosisId != null && diagnosisId > 0) {
96 Diagnosis diagnosis = diagnosisRepository.findById(diagnosisId)
97 .orElseThrow(() -> new RuntimeException("Diagnosis not found"));
98 performed.setDiagnosis(diagnosis);
99 }
100
101 logger.info("Requested procedure {} for patient {} by doctor {}", procedureId, patientId, doctorId);
102 PerformedProcedures saved = performedProcedureRepository.saveAndFlush(performed);
103
104 // Auto-generate billing for the patient on this date
105 billingService.autoGenerateBillingForPatientService(patientId, procedureDate);
106
107 return saved;
108 }
109
110 // ================= UC016 =================
111 @Transactional
112 public PerformedProcedures recordProcedure(Long procedureId,
113 Long doctorId,
114 Long patientId,
115 Long diagnosisId,
116 LocalDate procedureDate) {
117
118 if (procedureId == null || procedureId <= 0)
119 throw new IllegalArgumentException("Procedure ID must be valid");
120
121 if (doctorId == null || doctorId <= 0)
122 throw new IllegalArgumentException("Doctor ID must be valid");
123
124 if (patientId == null || patientId <= 0)
125 throw new IllegalArgumentException("Patient ID must be valid");
126
127 if (procedureDate == null)
128 throw new IllegalArgumentException("Procedure date is required");
129
130 Procedure procedure = procedureRepository.findById(procedureId)
131 .orElseThrow(() -> new RuntimeException("Procedure not found"));
132
133 Doctors doctor = doctorRepository.findById(doctorId)
134 .orElseThrow(() -> new RuntimeException("Doctor not found"));
135
136 Patient patient = patientRepository.findById(patientId)
137 .orElseThrow(() -> new RuntimeException("Patient not found"));
138
139 PerformedProcedures performed = new PerformedProcedures();
140 performed.setProcedure(procedure);
141 performed.setDoctor(doctor);
142 performed.setPatient(patient);
143 performed.setProcedureDate(procedureDate);
144
145 if (diagnosisId != null && diagnosisId > 0) {
146 Diagnosis diagnosis = diagnosisRepository.findById(diagnosisId)
147 .orElseThrow(() -> new RuntimeException("Diagnosis not found"));
148 performed.setDiagnosis(diagnosis);
149 }
150
151 logger.info("Recorded procedure {} for patient {}", procedureId, patientId);
152 PerformedProcedures saved = performedProcedureRepository.saveAndFlush(performed);
153
154 // Auto-generate billing for the patient on this date
155 billingService.autoGenerateBillingForPatientService(patientId, procedureDate);
156
157 return saved;
158 }
159
160 // ================= UC017 =================
161 @Transactional
162 public PerformedProcedures recordProcedureOutcome(Long performedProcedureId, String notes) {
163
164 if (performedProcedureId == null || performedProcedureId <= 0)
165 throw new IllegalArgumentException("Performed procedure ID must be valid");
166
167 PerformedProcedures performed = performedProcedureRepository.findById(performedProcedureId)
168 .orElseThrow(() -> new RuntimeException("Performed procedure not found"));
169
170 if (notes != null && !notes.isBlank()) {
171 performed.setNotes(notes);
172 }
173
174 logger.info("Updated procedure outcome {}", performedProcedureId);
175 return performedProcedureRepository.save(performed);
176 }
177
178 // ================= LINK TO MEDICAL RECORD =================
179 @Transactional
180 public MedicalRecordProcedures linkProcedureToMedicalRecord(Long medicalRecordId,
181 Long procedureId) {
182
183 if (medicalRecordId == null || medicalRecordId <= 0)
184 throw new IllegalArgumentException("Medical record ID must be valid");
185
186 if (procedureId == null || procedureId <= 0)
187 throw new IllegalArgumentException("Procedure ID must be valid");
188
189 MedicalRecord record = medicalRecordRepository.findById(medicalRecordId)
190 .orElseThrow(() -> new RuntimeException("Medical record not found"));
191
192 Procedure procedure = procedureRepository.findById(procedureId)
193 .orElseThrow(() -> new RuntimeException("Procedure not found"));
194
195 // Prevent duplicates
196 if (medicalRecordProcedureRepository
197 .existsByMedicalRecordRecordIdAndProcedureProcedureId(medicalRecordId, procedureId)) {
198 throw new RuntimeException("Procedure already linked to this medical record");
199 }
200
201 MedicalRecordProcedures link = new MedicalRecordProcedures(record, procedure);
202
203 logger.info("Linked procedure {} to record {}", procedureId, medicalRecordId);
204 return medicalRecordProcedureRepository.save(link);
205 }
206
207 // ================= READ METHODS =================
208 @Transactional(readOnly = true)
209 public List<PerformedProcedures> getProcedureRequestsForPatient(Long patientId) {
210
211 if (patientId == null || patientId <= 0)
212 throw new IllegalArgumentException("Patient ID must be valid");
213
214 if (!patientRepository.existsById(patientId))
215 throw new RuntimeException("Patient not found");
216
217 return performedProcedureRepository.findByPatientPatientId(patientId);
218 }
219
220 @Transactional(readOnly = true)
221 public List<PerformedProcedures> getProcedureRequestsByDoctor(Long doctorId) {
222
223 if (doctorId == null || doctorId <= 0)
224 throw new IllegalArgumentException("Doctor ID must be valid");
225
226 if (!doctorRepository.existsById(doctorId))
227 throw new RuntimeException("Doctor not found");
228
229 return performedProcedureRepository.findByDoctorDoctorId(doctorId);
230 }
231
232 @Transactional(readOnly = true)
233 public List<PerformedProcedures> getProceduresForPatient(Long patientId) {
234
235 if (patientId == null || patientId <= 0)
236 throw new IllegalArgumentException("Patient ID must be valid");
237
238 if (!patientRepository.existsById(patientId))
239 throw new RuntimeException("Patient not found");
240
241 return performedProcedureRepository.findByPatientPatientId(patientId);
242 }
243
244 @Transactional(readOnly = true)
245 public List<MedicalRecordProcedures> getProceduresForMedicalRecord(Long medicalRecordId) {
246
247 if (medicalRecordId == null || medicalRecordId <= 0)
248 throw new IllegalArgumentException("Medical record ID must be valid");
249
250 if (!medicalRecordRepository.existsById(medicalRecordId))
251 throw new RuntimeException("Medical record not found");
252
253 return medicalRecordProcedureRepository.findByMedicalRecordRecordId(medicalRecordId);
254 }
255
256 @Transactional(readOnly = true)
257 public List<SimpleProcedureDTO> getAllProcedures() {
258 return procedureRepository.findAll().stream()
259 .map(proc -> new SimpleProcedureDTO(
260 proc.getProcedureId(),
261 proc.getProcedureType(),
262 proc.getDescription(),
263 proc.getCost()
264 ))
265 .toList();
266 }
267
268 @Transactional(readOnly = true)
269 public Optional<PerformedProcedures> getPerformedProcedureById(Long id) {
270
271 if (id == null || id <= 0)
272 throw new IllegalArgumentException("ID must be valid");
273
274 return performedProcedureRepository.findById(id);
275 }
276
277 // ================= STORE PROCEDURE RESULT (UC017 Enhanced) =================
278 @Transactional
279 public ProcedureResults storeProcedureResult(Long medicalRecordId,
280 Long procedureId,
281 String resultDescription,
282 LocalDate resultDate) {
283
284 if (medicalRecordId == null || medicalRecordId <= 0)
285 throw new IllegalArgumentException("Medical record ID must be valid");
286
287 if (procedureId == null || procedureId <= 0)
288 throw new IllegalArgumentException("Procedure ID must be valid");
289
290 if (resultDate == null)
291 throw new IllegalArgumentException("Result date is required");
292
293 MedicalRecord record = medicalRecordRepository.findById(medicalRecordId)
294 .orElseThrow(() -> new RuntimeException("Medical record not found"));
295
296 Procedure procedure = procedureRepository.findById(procedureId)
297 .orElseThrow(() -> new RuntimeException("Procedure not found"));
298
299 // Check if result already exists for this medical record and procedure
300 List<ProcedureResults> existingResults = procedureResultRepository.findByMedicalRecordAndProcedure(medicalRecordId, procedureId);
301
302 ProcedureResults result;
303 if (!existingResults.isEmpty()) {
304 // Update existing result
305 result = existingResults.get(0);
306 result.setResultDescription(resultDescription);
307 result.setResultDate(resultDate);
308 ProcedureResults savedResult = procedureResultRepository.save(result);
309 logger.info("Updated procedure result {} for medical record {}", savedResult.getResultId(), medicalRecordId);
310 return savedResult;
311 } else {
312 // Create new result
313 result = new ProcedureResults();
314 result.setProcedure(procedure);
315 result.setResultDescription(resultDescription);
316 result.setResultDate(resultDate);
317
318 // Save result first to generate ID
319 ProcedureResults savedResult = procedureResultRepository.save(result);
320
321 // Then link to medical record
322 MedicalRecordProcedureResults link = new MedicalRecordProcedureResults(record, savedResult);
323 medicalRecordProcedureResultRepository.save(link);
324 logger.info("Created new procedure result {} for medical record {}", savedResult.getResultId(), medicalRecordId);
325 return savedResult;
326 }
327 }
328
329 @Transactional(readOnly = true)
330 public List<ProcedureResults> getProcedureResultsForMedicalRecord(Long medicalRecordId) {
331
332 if (medicalRecordId == null || medicalRecordId <= 0)
333 throw new IllegalArgumentException("Medical record ID must be valid");
334
335 if (!medicalRecordRepository.existsById(medicalRecordId))
336 throw new RuntimeException("Medical record not found");
337
338 return procedureResultRepository.findByMedicalRecordId(medicalRecordId);
339 }
340}
Note: See TracBrowser for help on using the repository browser.