¤ñ¹ï·sÀÉ®× |
| | |
| | | package com.pollex.pam.service; |
| | | |
| | | import com.pollex.pam.config.ApplicationProperties; |
| | | import com.pollex.pam.domain.Appointment; |
| | | import com.pollex.pam.domain.AppointmentExpiringNotifyRecord; |
| | | import com.pollex.pam.domain.Consultant; |
| | | import com.pollex.pam.enums.AppointmentStatusEnum; |
| | | import com.pollex.pam.enums.ContactStatusEnum; |
| | | import com.pollex.pam.repository.AppointmentExpiringNotifyRecordRepository; |
| | | import com.pollex.pam.repository.AppointmentRepository; |
| | | 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.util.StringUtils; |
| | | import org.thymeleaf.context.Context; |
| | | import org.thymeleaf.spring5.SpringTemplateEngine; |
| | | |
| | | import java.time.Instant; |
| | | import java.time.LocalDate; |
| | | import java.time.ZoneId; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Optional; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | | public class ScheduleTaskService { |
| | | |
| | | /** |
| | | * é»è©±åemailå¨å»ºç«é ç´å®(T)å¾çN天è¦çºæªèçé ç´å® |
| | | * ç®åNçæ«å®çº2 |
| | | */ |
| | | private static final int APPOINTMENT_PENDING_PHONE_INTERVAL = 2; |
| | | private static final int APPOINTMENT_PENDING_EMAIL_INTERVAL = 2; |
| | | |
| | | /** |
| | | * é»è©±åemailå¨å»ºç«é ç´å®(T)å¾çN天æè¢«è¦çºæªèçé ç´å®ï¼ç¶å¤©æ¹æ¬¡æç¼éæé給顧å |
| | | * èå¨å¾ä¸å¤©(T+N+1)ï¼å°±æç¼éæ¹æ¬¡çµ¦å®¢æ¶åç¥ è©²é¡§åå¯è½å¿ç¢ç¡æ³èçï¼æ¯å¦éè¦åæ¶ |
| | | */ |
| | | private static final int APPOINTMENT_EXPIRING_PHONE_INTERVAL = APPOINTMENT_PENDING_PHONE_INTERVAL + 1; |
| | | private static final int APPOINTMENT_EXPIRING_EMAIL_INTERVAL = APPOINTMENT_PENDING_EMAIL_INTERVAL + 1; |
| | | |
| | | /** |
| | | * éç¥å®¢æ¶ç次æ¸éå¶ |
| | | */ |
| | | private static final int SEND_EXPIRING_NOTIFY_LIMIT = 1; |
| | | |
| | | private static final String NOT_CONTACTED_NOTIFY_SUBJECT = "é ç´å®æªé²è¡è¯ç¹«éç¥"; |
| | | private static final Logger log = LoggerFactory.getLogger(ScheduleTaskService.class); |
| | | |
| | | @Autowired |
| | | ConsultantService consultantService; |
| | | |
| | | @Autowired |
| | | AppointmentService appointmentService; |
| | | |
| | | @Autowired |
| | | AppointmentRepository appointmentRepository; |
| | | |
| | | @Autowired |
| | | SendMsgService sendMsgService; |
| | | |
| | | @Autowired |
| | | SpringTemplateEngine springTemplateEngine; |
| | | |
| | | @Autowired |
| | | ApplicationProperties applicationProperties; |
| | | |
| | | @Autowired |
| | | AppointmentExpiringNotifyRecordRepository appointmentExpiringNotifyRecordRepository; |
| | | |
| | | @Scheduled(cron = "0 30 8 * * *") |
| | | public void sendAppointmentPendingNotifyToConsultant() { |
| | | log.info("Starting send appointment pending notify to consultant"); |
| | | |
| | | Map<String, List<Appointment>> consultantWithPendingAppointments = |
| | | appointmentRepository.findAllByCommunicateStatusAndStatus(ContactStatusEnum.RESERVED, AppointmentStatusEnum.AVAILABLE) |
| | | .stream() |
| | | .filter(appointment -> isAppointmentInInterval(appointment, APPOINTMENT_PENDING_PHONE_INTERVAL, APPOINTMENT_PENDING_EMAIL_INTERVAL)) |
| | | .collect(Collectors.groupingBy(Appointment::getAgentNo)); |
| | | |
| | | consultantWithPendingAppointments.forEach((agentNo, pendingAppointments) -> { |
| | | int pendingAppointmentsSum = pendingAppointments.size(); |
| | | Consultant consultant = consultantService.findByAgentNo(agentNo); |
| | | String consultantPhoneNumber = consultant.getPhoneNumber(); |
| | | String consultantEmail = consultant.getEmail(); |
| | | String emailContent = getAppointmentPendingNotifyEmailContent(pendingAppointmentsSum); |
| | | |
| | | sendMsgService.sendMsgBySMS(consultantPhoneNumber, String.format("æ¨æ%såé ç´å®æªé²è¡è¯ç¹«ï¼è«ç¡éèç", pendingAppointmentsSum)); |
| | | sendMsgService.sendMsgByEmail(consultantEmail, 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<Appointment> allByCommunicateStatus = |
| | | appointmentRepository.findAllByCommunicateStatusAndStatus(ContactStatusEnum.RESERVED, AppointmentStatusEnum.AVAILABLE) |
| | | .stream() |
| | | .filter(appointment -> isAppointmentInInterval(appointment, APPOINTMENT_EXPIRING_PHONE_INTERVAL, APPOINTMENT_EXPIRING_EMAIL_INTERVAL)) |
| | | .filter(this::isAppointmentNotifyNotOnLimit) |
| | | .collect(Collectors.toList()); |
| | | |
| | | allByCommunicateStatus.forEach(appointment -> { |
| | | Consultant consultant = consultantService.findByAgentNo(appointment.getAgentNo()); |
| | | Optional<String> optionalPhone = Optional.ofNullable(appointment.getPhone()).filter(StringUtils::hasText); |
| | | Optional<String> optionalEmail = Optional.ofNullable(appointment.getEmail()).filter(StringUtils::hasText); |
| | | |
| | | optionalPhone.ifPresent(phone -> |
| | | sendMsgService.sendMsgBySMS(phone, String.format("徿±æï¼æ¨é ç´%s顧忣å¿ç¢ä¸ï¼è«æ¨åæ¶é ç´ä¸¦æ¹é¸å
¶ä»é¡§åï¼è«é»æç¶²åï¼%s" |
| | | , consultant.getName(), getAppointmentUrl(appointment.getId()))) |
| | | ); |
| | | optionalEmail.ifPresent(email -> |
| | | sendMsgService.sendMsgByEmail(email, NOT_CONTACTED_NOTIFY_SUBJECT, getAppointmentExpiringNotifyEmail(consultant.getName(), getAppointmentUrl(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"); |
| | | } |
| | | |
| | | private boolean isAppointmentInInterval(Appointment appointment, int phoneInterval, int emailInterval) { |
| | | final boolean isHavePhone = StringUtils.hasText(appointment.getPhone()); |
| | | final boolean isHaveEmail = StringUtils.hasText(appointment.getEmail()); |
| | | |
| | | LocalDate appointmentDate = appointment.getAppointmentDate().atZone(ZoneId.systemDefault()).toLocalDate(); |
| | | LocalDate nowDate = Instant.now().atZone(ZoneId.systemDefault()).toLocalDate(); |
| | | long intervalDays = nowDate.toEpochDay() - appointmentDate.toEpochDay(); |
| | | |
| | | final boolean isAppointmentExpiringByPhone = isHavePhone && intervalDays >= phoneInterval; |
| | | final boolean isAppointmentExpiringByEmail = isHaveEmail && intervalDays >= emailInterval; |
| | | |
| | | return isAppointmentExpiringByPhone || isAppointmentExpiringByEmail; |
| | | } |
| | | |
| | | private boolean isAppointmentNotifyNotOnLimit(Appointment appointment) { |
| | | int sendNotifyToCustomerRecordSum = |
| | | appointmentExpiringNotifyRecordRepository.findAllByAppointmentId(appointment.getId()).size(); |
| | | |
| | | return sendNotifyToCustomerRecordSum < SEND_EXPIRING_NOTIFY_LIMIT; |
| | | } |
| | | |
| | | private String getAppointmentUrl(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); |
| | | } |
| | | } |