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); } }