147 lines
6.7 KiB
Java

package com.mirna.hospitalmanagementapi.application.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mirna.hospitalmanagementapi.application.usecase.consultation.FindConsultationByIdUseCase;
import com.mirna.hospitalmanagementapi.application.usecase.consultation.SaveConsultationUseCase;
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindDoctorByIdUseCase;
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindOneFreeDoctorBySpecialtyUseCase;
import com.mirna.hospitalmanagementapi.application.usecase.patient.FindPatientByIdUseCase;
import com.mirna.hospitalmanagementapi.domain.dtos.consultation.ConsultationCanceledDTO;
import com.mirna.hospitalmanagementapi.domain.dtos.consultation.ConsultationDTO;
import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
import com.mirna.hospitalmanagementapi.domain.entities.Doctor;
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
import com.mirna.hospitalmanagementapi.domain.exceptions.ConsultationValidationException;
import com.mirna.hospitalmanagementapi.domain.services.ConsultationService;
import com.mirna.hospitalmanagementapi.domain.services.DoctorScheduleService;
import com.mirna.hospitalmanagementapi.domain.repositories.ConsultationRepository;
import jakarta.persistence.EntityNotFoundException;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ConsultationServiceImpl implements ConsultationService {
@Autowired
private SaveConsultationUseCase saveConsultation;
@Autowired
private FindConsultationByIdUseCase findConsultationById;
@Autowired
private ConsultationRepository consultationRepository;
@Autowired
private FindPatientByIdUseCase findPatientById;
@Autowired
private FindDoctorByIdUseCase findDoctorById;
@Autowired
private FindOneFreeDoctorBySpecialtyUseCase findOneFreeDoctorBySpecialty;
@Autowired
private DoctorScheduleService doctorScheduleService;
private static final ZoneOffset BANGKOK_ZONE_OFFSET = ZoneOffset.ofHours(7);
@Override
@Transactional
public Consultation addConsultation(ConsultationDTO consultationDTO) throws ConsultationValidationException {
Patient patient = validatePatient(consultationDTO.patientId(), consultationDTO.consultationDate());
Doctor doctor = validateAndFindDoctor(consultationDTO);
validatePatientAndDoctorAvailability(patient, doctor, consultationDTO.consultationDate());
Consultation consultation = new Consultation(patient, doctor, consultationDTO.consultationDate());
return saveConsultation.execute(consultation);
}
private Patient validatePatient(Long patientId, OffsetDateTime consultationDate) throws ConsultationValidationException {
if (patientId == null) {
throw new ConsultationValidationException("Patient ID cannot be null");
}
Patient patient = findPatientById.execute(patientId);
if (patient == null) {
throw new ConsultationValidationException("This patient is not found");
}
if (!patient.getActive()) {
throw new ConsultationValidationException("This patient is not active");
}
OffsetDateTime consultationDateInBkkZone = consultationDate.withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
OffsetDateTime startOfDay = consultationDateInBkkZone.with(LocalTime.MIN);
OffsetDateTime endOfDay = consultationDateInBkkZone.with(LocalTime.MAX);
// แก้ไขบรรทัดนี้: ส่งพารามิเตอร์ที่ถูกต้องไปยัง Repository
if (consultationRepository.findConsultationByPatientAndDate(patient.getId(), startOfDay, endOfDay) != null) {
throw new ConsultationValidationException("This patient is not free on this date");
}
return patient;
}
private Doctor validateAndFindDoctor(ConsultationDTO consultationDTO) throws ConsultationValidationException {
Doctor doctor = null;
OffsetDateTime consultationDateInBkkZone = consultationDTO.consultationDate().withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
if (consultationDTO.doctorId() != null) {
doctor = findDoctorById.execute(consultationDTO.doctorId());
} else if (consultationDTO.specialty() != null) {
doctor = findOneFreeDoctorBySpecialty.execute(consultationDTO.specialty(), consultationDateInBkkZone);
} else {
throw new ConsultationValidationException("At least the specialty or doctor ID must be filled in");
}
if (doctor == null) {
throw new ConsultationValidationException("No doctors found at the requested time or specialty.");
}
return doctor;
}
private void validatePatientAndDoctorAvailability(Patient patient, Doctor doctor, OffsetDateTime consultationDate) throws ConsultationValidationException {
OffsetDateTime consultationDateInBkkZone = consultationDate.withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
OffsetDateTime startOfDay = consultationDateInBkkZone.with(LocalTime.MIN);
OffsetDateTime endOfDay = consultationDateInBkkZone.with(LocalTime.MAX);
// แก้ไขบรรทัดนี้: ส่งพารามิเตอร์ที่ถูกต้องไปยัง Repository
if (consultationRepository.findConsultationByDoctorAndDate(doctor.getId(), startOfDay, endOfDay) != null) {
throw new ConsultationValidationException("This doctor is not free on this date");
}
boolean isDoctorAvailable = doctorScheduleService.isDoctorAvailable(
doctor.getId(),
consultationDateInBkkZone.getDayOfWeek(),
consultationDateInBkkZone.toLocalTime()
);
if (!isDoctorAvailable) {
throw new ConsultationValidationException("The selected doctor is not on duty at the requested time.");
}
}
@Override
public Consultation findConsultationById(Long id) {
Consultation consultation = findConsultationById.execute(id);
if (consultation == null)
throw new EntityNotFoundException("No existing consultation with this id");
return consultation;
}
@Override
public Consultation cancelConsultation(ConsultationCanceledDTO consultationCanceledDTO) {
Consultation consultation = this.findConsultationById(consultationCanceledDTO.consultationId());
consultation.setCanceled(true);
consultation.setReasonCancellation(consultationCanceledDTO.reasonCancellation());
return saveConsultation.execute(consultation);
}
}