package edu.gjoko.schedlr.services; import edu.gjoko.schedlr.dto.AppointmentInfoDto; import edu.gjoko.schedlr.entity.*; import edu.gjoko.schedlr.exceptions.BlockingTimeException; import edu.gjoko.schedlr.mappers.AppointmentInfoDtoBusinessMapper; import edu.gjoko.schedlr.mappers.AppointmentInfoDtoCustomerMapper; import edu.gjoko.schedlr.repositories.AppointmentRepository; import edu.gjoko.schedlr.repositories.ServiceRepository; import edu.gjoko.schedlr.repositories.StakeholderRepository; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import javax.persistence.EntityNotFoundException; import javax.security.sasl.AuthenticationException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; @Service @AllArgsConstructor public class AppointmentsService { private final AppointmentRepository appointmentRepository; private final StakeholderRepository stakeholderRepository; private final ServiceRepository serviceRepository; private final AppointmentInfoDtoBusinessMapper appointmentInfoDtoBusinessMapper; private final AppointmentInfoDtoCustomerMapper appointmentInfoDtoCustomerMapper; public void saveAppointment(Appointment appointment) { var service = serviceRepository.findById(appointment.getService().getId()).get(); // remove 1 minute in order to prevent overlapping appointment.setEndTime(appointment.getStartTime().plusMinutes(service.getDuration() - 1)); List blockingAppointments = appointmentRepository. findBlockingAppointments( appointment.getService().getBusiness().getId(), appointment.getStartTime(), appointment.getEndTime()); // check to see if there are blocking exceptions if (blockingAppointments != null && !blockingAppointments.isEmpty()) { throw new BlockingTimeException(); } appointmentRepository.save(appointment); } public List getFutureAppointmentInfoList(Long stakeholderId) { StakeholderType type = stakeholderRepository.findById(stakeholderId).get().getStakeholderType(); List appointmentInfoDtoList = new ArrayList<>(); switch (type) { case BUSINESS_OWNER -> appointmentInfoDtoList = appointmentRepository.findFutureAppointmentsByBusinessOwnerId(stakeholderId, LocalDateTime.now()) .stream() .map(appointmentInfoDtoBusinessMapper::appointmentToAppointmentInfoDto) .toList(); case CUSTOMER -> appointmentInfoDtoList = appointmentRepository.findFutureAppointmentsByCustomerId(stakeholderId, LocalDateTime.now()) .stream() .map(appointmentInfoDtoCustomerMapper::appointmentToAppointmentInfoDto) .toList(); } return appointmentInfoDtoList; } public List getPastAppointmentInfoList(Long stakeholderId) { StakeholderType type = stakeholderRepository.findById(stakeholderId).get().getStakeholderType(); List appointmentInfoDtoList = new ArrayList<>(); switch (type) { case BUSINESS_OWNER -> appointmentInfoDtoList = appointmentRepository.findPastAppointmentsByBusinessOwnerId(stakeholderId, LocalDateTime.now()); case CUSTOMER -> appointmentInfoDtoList = appointmentRepository.findPastAppointmentsByCustomerId(stakeholderId, LocalDateTime.now()); } return appointmentInfoDtoList .stream() .map(appointmentInfoDtoBusinessMapper::appointmentToAppointmentInfoDto) .toList(); } public List getActiveAppointmentsByBusiness(Long businessId) { return appointmentRepository.getActiveAppointmentsByBusiness(businessId); } public void deleteAppointment(Long appointmentId, Long stakeholderId) throws AuthenticationException { Optional stakeholderOptional = stakeholderRepository.findById(stakeholderId); if (stakeholderOptional.isPresent()) { Optional optional = appointmentRepository.findAppointmentByIdAndCustomer_Id(appointmentId, stakeholderId); if (optional.isEmpty()) { optional = appointmentRepository.findAppointmentByIdAndService_Business_Owner_Id(appointmentId, stakeholderId); if (optional.isEmpty()) { throw new EntityNotFoundException("No appointment was found for the give stakeholder and appointment id."); } else { softDeleteAppointment(optional.get(), AppointmentStatus.CANCELLED_BY_BUSINESS_OWNER); } } else { softDeleteAppointment(optional.get(), AppointmentStatus.CANCELLED_BY_CUSTOMER); } } else { throw new AuthenticationException(); } } public void softDeleteAppointment(Appointment appointment, AppointmentStatus appointmentStatus) { appointment.setAppointmentStatus(appointmentStatus); appointmentRepository.save(appointment); } }