保誠-保戶業務員媒合平台
wayne
2022-02-17 a3716f72066d25d745f4d5103ff23a553c3e102b
pamapi/src/main/java/com/pollex/pam/service/ScheduleTaskService.java
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,165 @@
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<String, List<AppointmentCustomerView>> 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<String> optionalPhone = Optional.ofNullable(consultant.getPhoneNumber()).filter(StringUtils::hasText);
            Optional<String> 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<AppointmentCustomerView> 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<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(), 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<Long, List<Satisfaction>> 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);
    }
}