package com.pollex.pam.service; import com.pollex.pam.config.ApplicationProperties; import com.pollex.pam.config.Constants; import com.pollex.pam.domain.*; import com.pollex.pam.enums.AppointmentStatusEnum; import com.pollex.pam.enums.ContactStatusEnum; import com.pollex.pam.enums.SatisfactionStatusEnum; import com.pollex.pam.enums.SatisfactionTypeEnum; import com.pollex.pam.repository.AppointmentCustomerViewRepository; import com.pollex.pam.repository.AppointmentExpiringNotifyRecordRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import org.thymeleaf.context.Context; import org.thymeleaf.spring5.SpringTemplateEngine; import java.time.Instant; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @Service @Transactional public class ScheduleTaskService { private static final String NOT_CONTACTED_NOTIFY_SUBJECT = "預約單未進行聯繫通知"; private static final Logger log = LoggerFactory.getLogger(ScheduleTaskService.class); @Autowired ConsultantService consultantService; @Autowired AppointmentService appointmentService; @Autowired AppointmentCustomerViewRepository appointmentCustomerViewRepository; @Autowired SendMsgService sendMsgService; @Autowired SpringTemplateEngine springTemplateEngine; @Autowired ApplicationProperties applicationProperties; @Autowired AppointmentExpiringNotifyRecordRepository appointmentExpiringNotifyRecordRepository; @Autowired SatisfactionService satisfactionService; @Autowired PersonalNotificationService personalNotificationService; @Scheduled(cron = "0 30 8 * * *") public void sendAppointmentPendingNotifyToConsultant() { log.info("Starting send appointment pending notify to consultant"); Map> consultantWithPendingAppointments = appointmentCustomerViewRepository.findAllByCommunicateStatusAndStatus(ContactStatusEnum.RESERVED, AppointmentStatusEnum.AVAILABLE) .stream() .filter(appointment -> appointmentService.isAppointmentDateNotInIntervalFromNow(appointment, Constants.APPOINTMENT_PENDING_PHONE_INTERVAL, Constants.APPOINTMENT_PENDING_EMAIL_INTERVAL) ) .collect(Collectors.groupingBy(AppointmentCustomerView::getAgentNo)); consultantWithPendingAppointments.forEach((agentNo, pendingAppointments) -> { int pendingAppointmentsSum = pendingAppointments.size(); Consultant consultant = consultantService.findByAgentNo(agentNo); Optional optionalPhone = Optional.ofNullable(consultant.getPhoneNumber()).filter(StringUtils::hasText); Optional optionalEmail = Optional.ofNullable(consultant.getEmail()).filter(StringUtils::hasText); String emailContent = getAppointmentPendingNotifyEmailContent(pendingAppointmentsSum); optionalPhone.ifPresent(phone -> { sendMsgService.sendMsgBySMS(phone, String.format("您有%s則預約單未進行聯繫,請盡速處理", pendingAppointmentsSum)); }); optionalEmail.ifPresent(email -> { sendMsgService.sendMsgByEmail(email, NOT_CONTACTED_NOTIFY_SUBJECT, emailContent, true); }); }); log.info("Sending appointment pending notify to consultant finish"); } @Scheduled(cron = "0 30 8 * * *") public void sendAppointmentExpiringNotifyToCustomer() { log.info("Starting send appointment expiring notify to customer"); List allByCommunicateStatus = appointmentCustomerViewRepository.findAllByCommunicateStatusAndStatus(ContactStatusEnum.RESERVED, AppointmentStatusEnum.AVAILABLE) .stream() .filter(appointment -> appointmentService.isAppointmentDateNotInIntervalFromNow(appointment, Constants.APPOINTMENT_EXPIRING_PHONE_INTERVAL, Constants.APPOINTMENT_EXPIRING_EMAIL_INTERVAL) ) .filter(this::isAppointmentExpiringNotifyNotOnLimit) .collect(Collectors.toList()); allByCommunicateStatus.forEach(appointment -> { Consultant consultant = consultantService.findByAgentNo(appointment.getAgentNo()); Optional optionalPhone = Optional.ofNullable(appointment.getPhone()).filter(StringUtils::hasText); Optional optionalEmail = Optional.ofNullable(appointment.getEmail()).filter(StringUtils::hasText); optionalPhone.ifPresent(phone -> sendMsgService.sendMsgBySMS(phone, String.format("很抱歉!您預約%s顧問正忙碌中,請您取消預約並改選其他顧問,請點擊網址:%s" , consultant.getName(), getAppointmentExpiringNotifyUrl(appointment.getId()))) ); optionalEmail.ifPresent(email -> sendMsgService.sendMsgByEmail(email, NOT_CONTACTED_NOTIFY_SUBJECT, getAppointmentExpiringNotifyEmail(consultant.getName(), getAppointmentExpiringNotifyUrl(appointment.getId())), true) ); AppointmentExpiringNotifyRecord record = new AppointmentExpiringNotifyRecord(); record.setAppointmentId(appointment.getId()); record.setSendTime(Instant.now()); appointmentExpiringNotifyRecordRepository.save(record); }); log.info("Sending appointment expiring notify to customer finish"); } // todo 需確認該時間, otis todo=134497 @Scheduled(cron = "0 30 8 * * *") public void sendNotFillAppointmentSatisfactionToPersonalNotification() { Map> customerNotFillSatisfactions = satisfactionService.getByStatusAndType(SatisfactionStatusEnum.UNFILLED, SatisfactionTypeEnum.APPOINTMENT) .stream() .collect(Collectors.groupingBy(Satisfaction::getCustomerId)); customerNotFillSatisfactions.forEach((customerId, notFillSatisfactions) -> personalNotificationService.createNotFillAppointmentSatisfactionNumberToCustomer(customerId, notFillSatisfactions.size()) ); } private boolean isAppointmentExpiringNotifyNotOnLimit(AppointmentCustomerView appointment) { int sendNotifyToCustomerRecordSum = appointmentExpiringNotifyRecordRepository.findAllByAppointmentId(appointment.getId()).size(); return sendNotifyToCustomerRecordSum < Constants.SEND_EXPIRING_NOTIFY_LIMIT; } private String getAppointmentExpiringNotifyUrl(Long appointmentId) { return applicationProperties.getFrontEndDomain() + "?notContactAppointmentId=" + appointmentId; } private String getAppointmentPendingNotifyEmailContent(int sum) { Context context = new Context(); context.setVariable("pendingAppointmentSum", sum); return springTemplateEngine.process("mail/appointmentPendingNotifyEmail", context); } private String getAppointmentExpiringNotifyEmail(String consultantName, String notifyUrl) { Context context = new Context(); context.setVariable("consultantName", consultantName); context.setVariable("notifyUrl", notifyUrl); return springTemplateEngine.process("mail/appointmentExpiringNotifyEmail", context); } }