From 6fa4bba623713c396432ba8b863846883d6a1906 Mon Sep 17 00:00:00 2001 From: wayne <wayne8692wayne8692@gmail.com> Date: 星期三, 26 一月 2022 10:52:23 +0800 Subject: [PATCH] Merge branch 'pollex-dev' into sit --- pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 263 insertions(+), 14 deletions(-) diff --git a/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java b/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java index 7b0ebfa..3ae99c4 100644 --- a/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java +++ b/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java @@ -1,7 +1,25 @@ package com.pollex.pam.service; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Comparator; import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import com.pollex.pam.appointment.process.AppointmentProcess; +import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.config.Constants; +import com.pollex.pam.service.dto.*; +import com.pollex.pam.web.rest.errors.NotFoundExpiringAppointmentException; +import com.pollex.pam.web.rest.errors.SendEmailFailException; +import com.pollex.pam.web.rest.errors.SendSMSFailException; +import io.jsonwebtoken.lang.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -9,21 +27,29 @@ import com.pollex.pam.domain.Appointment; import com.pollex.pam.domain.AppointmentCustomerView; import com.pollex.pam.enums.ContactStatusEnum; +import com.pollex.pam.enums.InterviewRecordStatusEnum; import com.pollex.pam.repository.AppointmentCustomerViewRepository; import com.pollex.pam.repository.AppointmentRepository; import com.pollex.pam.security.SecurityUtils; -import com.pollex.pam.service.dto.AppointmentCreateDTO; -import com.pollex.pam.service.dto.AppointmentCustomerViewDTO; import com.pollex.pam.service.mapper.AppointmentCustomerViewMapper; import com.pollex.pam.service.mapper.AppointmentDTOMapper; -import com.pollex.pam.service.mapper.AppointmentMapper; import com.pollex.pam.web.rest.errors.AppointmentNotFoundException; +import org.springframework.util.StringUtils; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring5.SpringTemplateEngine; + +import static com.pollex.pam.enums.AppointmentStatusEnum.AVAILABLE; +import static com.pollex.pam.enums.AppointmentStatusEnum.DELETED; @Service @Transactional public class AppointmentService { - @Autowired + private static final Logger log = LoggerFactory.getLogger(AppointmentService.class); + + private static final String NOTIFY_EMAIL_SUBJECT = "靽���像�蝟餌絞�嚗���"; + + @Autowired AppointmentRepository appointmentRepository; @Autowired @@ -38,33 +64,256 @@ @Autowired AppointmentCustomerViewRepository appointmentCustomerViewRepository; - public void customerCreateAppointment(AppointmentCreateDTO appointmentCreateDTO) { + @Autowired + SatisfactionService satisfactionService; + + @Autowired + SendMsgService sendMsgService; + + @Autowired + ApplicationProperties applicationProperties; + + @Autowired + SpringTemplateEngine springTemplateEngine; + + @Autowired + InterviewRecordService interviewRecordService; + + @Autowired + AppointmentProcess abstractAppointmentProcess; + + @Autowired + PersonalNotificationService personalNotificationService; + + public Appointment customerCreateAppointment(AppointmentCreateDTO appointmentCreateDTO) { Appointment appointment = appointmentDTOMapper.toAppointment(appointmentCreateDTO); - appointment.setCustomerId(SecurityUtils.getCustomerId()); + appointment.setStatus(AVAILABLE); + appointment.setCustomerId(SecurityUtils.getCustomerDBId()); appointment.setCommunicateStatus(ContactStatusEnum.RESERVED); - appointmentRepository.save(appointment); + return appointmentRepository.save(appointment); } + + public Appointment updateAppointment(AppointmentUpdateDTO updateAppointmentDTO) { + Appointment appointment = appointmentRepository.findById(updateAppointmentDTO.getId()).get(); + BeanUtils.copyProperties(updateAppointmentDTO, appointment); + appointment.setPhone(updateAppointmentDTO.getPhone()); + appointment.setEmail(updateAppointmentDTO.getEmail()); + appointment.setContactType(updateAppointmentDTO.getContactType()); + appointment.setGender(updateAppointmentDTO.getGender()); + appointment.setAge(updateAppointmentDTO.getAge()); + appointment.setJob(updateAppointmentDTO.getJob()); + appointment.setRequirement(updateAppointmentDTO.getRequirement()); + appointment.setHopeContactTime(updateAppointmentDTO.getHopeContactTime()); + appointment.setOtherRequirement(updateAppointmentDTO.getOtherRequirement()); + appointment.setLastModifiedDate(Instant.now()); + + return appointmentRepository.save(appointment); + } + + public void markAppointmentDeleted(Long appointmentId) { + Appointment appointment = appointmentRepository.findById(appointmentId).get(); + appointment.setStatus(DELETED); + appointment.setLastModifiedDate(Instant.now()); + appointment.setCommunicateStatus(ContactStatusEnum.CANCEL); + appointmentRepository.save(appointment); + personalNotificationService.createMarkAppointmentDeletedToConsultant(appointment); + + } public List<Appointment> findByAgentNo(String agentNo) { return appointmentRepository.findByAgentNo(agentNo); } - public void markAsContacted(Long appointmentId) { - + public Appointment markAsContacted(Long appointmentId) { Appointment appointment = appointmentRepository.findById(appointmentId).get(); appointment.setCommunicateStatus(ContactStatusEnum.CONTACTED); - appointmentRepository.save(appointment); + appointment.setContactTime(Instant.now()); + appointment.setLastModifiedDate(Instant.now()); + return appointmentRepository.save(appointment); } - public AppointmentCustomerViewDTO getAppointmentDetail(Long appointmentId) { AppointmentCustomerView appointment = appointmentCustomerViewRepository.findById(appointmentId) .orElseThrow(AppointmentNotFoundException::new); - return appointmentCustomerViewMapper.toAppointmentCustomerViewDTO(appointment); + + AppointmentCustomerViewDTO dto = appointmentCustomerViewMapper.toAppointmentCustomerViewDTO(appointment); + setSatisfactionScore(dto, appointmentId); +// setInterviewRecordDTO(dto); + return dto; } + public void setInterviewRecordDTO(AppointmentCustomerViewDTO dto) { + List<InterviewRecordDTO> interviewRecords = interviewRecordService.findByAppointmentIdAndStatus(dto.getId(), InterviewRecordStatusEnum.AVAILABLE); + dto.setInterviewRecordDTOs(interviewRecords); + } - public List<Appointment> findByAgentNoAndCustomerId(String agentNo, Long customerId) { - return appointmentRepository.findByAgentNoAndCustomerId(agentNo, customerId); + public List<AppointmentCustomerViewDTO> getConsultantAvailableAppointments(String agentNo) { + return appointmentCustomerViewRepository.findByAgentNo(agentNo).stream() + .filter(appointment -> appointment.getStatus() == AVAILABLE) + .map(appointmentCustomerView -> { + AppointmentCustomerViewDTO dto = appointmentCustomerViewMapper.toAppointmentCustomerViewDTO(appointmentCustomerView); + setSatisfactionScore(dto, appointmentCustomerView.getId()); + return dto; + }) + .collect(Collectors.toList()); + } + + public void setSatisfactionScore(AppointmentCustomerViewDTO dto, Long appointmentId) { + satisfactionService.getByAppointmentId(appointmentId).ifPresent(satisfaction -> { + dto.setSatisfactionScore(satisfaction.getScore()); + }); + } + + public List<AppointmentCustomerView> findAvailableByAgentNoAndCustomerId(String agentNo, Long customerId) { + return appointmentCustomerViewRepository.findByAgentNoAndCustomerId(agentNo, customerId) + .stream() + .filter(appointmentCustomerView -> appointmentCustomerView.getStatus() == AVAILABLE) + .collect(Collectors.toList()); + } + + public Optional<Appointment> findLatestAppointmentByAgentNoAndCustomerId(String agentNo, Long customerId) { + return appointmentRepository.findTopByAgentNoAndCustomerIdOrderByAppointmentDateDesc(agentNo, customerId); + } + + public void recordConsultantReadTime(Long appointmentId) { + Appointment appointment = appointmentRepository.findById(appointmentId).get(); + + if(appointment.getConsultantReadTime() == null) { + appointment.setConsultantReadTime(Instant.now()); + appointmentRepository.save(appointment); + } + else { + log.debug("this appointment was read, read time = {}", appointment.getConsultantReadTime()); + } + } + + public void recordAllAppointmentsView(String agentNo) { + List<Appointment> consultantNotViewAppointments = findByAgentNo(agentNo) + .stream() + .filter(appointment -> Objects.isNull(appointment.getConsultantViewTime())) + .collect(Collectors.toList()); + + consultantNotViewAppointments.forEach(appointment -> appointment.setConsultantViewTime(Instant.now())); + appointmentRepository.saveAll(consultantNotViewAppointments); + } + + public void sendAppointmentNotify(Appointment appointment) { + Assert.notNull(appointment, "appointment entity cannot be null"); + + log.debug("is need send appointment notify msg? sms = {}, email = {}", + applicationProperties.getSms().isSendNotifyMsg(), applicationProperties.getEmail().isSendNotifyMsg()); + + log.debug("sending appointment notify, appointmentId = {}", appointment.getId()); + sendAppointmentNotifyBySMS(appointment); + sendAppointmentNotifyByHtmlEmail(appointment); + } + + private void sendAppointmentNotifyBySMS(Appointment appointment) { + String msg = getAppointmentNotifyWording(appointment); + String consultantMobile = consultantService.findByAgentNo(appointment.getAgentNo()).getPhoneNumber(); + + try { + if(!StringUtils.hasText(consultantMobile)) { + throw new SendSMSFailException("the consultant does not have mobile!"); + } + + sendMsgService.sendMsgBySMS(consultantMobile, msg); + } catch (SendSMSFailException e) { + log.warn("send appointment notify by sms was fail, appointment Id = {}", appointment.getId(), e); + } + } + + private String getAppointmentNotifyWording(Appointment appointment) { + String normalContent; + if(StringUtils.hasText(appointment.getPhone())) { + normalContent = "閬芣��“��憟踝����蝑�靽�犖憯賢��像��������恥�����Ⅳ�" + appointment.getPhone(); + } + else { + normalContent = "閬芣��“��憟踝����蝑�靽�犖憯賢��像������"; + } + + String urlContent = "嚗���雯��嚗�" + getAppointmentDetailUrl(appointment.getId()) + "����蒂摰�蝯∟赤隢�����"; + return normalContent + urlContent; + } + + private void sendAppointmentNotifyByHtmlEmail(Appointment appointment) { + String consultantEmail = consultantService.findByAgentNo(appointment.getAgentNo()).getEmail(); + String customerMobile = appointment.getPhone(); + String normalContent; + + if(StringUtils.hasText(customerMobile)) { + normalContent = "閬芣��“��憟踝����蝑�靽�犖憯賢��像��������恥�����Ⅳ�" + customerMobile + "嚗�"; + } + else { + normalContent = "閬芣��“��憟踝����蝑�靽�犖憯賢��像�������"; + } + + Context context = new Context(); + context.setVariable("content", normalContent); + context.setVariable("urlHint", getAppointmentDetailUrl(appointment.getId())); + String content = springTemplateEngine.process("mail/appointmentNotifyEmail", context); + + try { + if(!StringUtils.hasText(consultantEmail)) { + throw new SendEmailFailException("the consultant does not have email!"); + } + + sendMsgService.sendMsgByEmail(consultantEmail, NOTIFY_EMAIL_SUBJECT, content, true); + } catch (SendEmailFailException e) { + log.warn("send appointment notify by email was fail, appointment Id = {}", appointment.getId(), e); + } + } + + public String getAppointmentDetailUrl(Long appointmentId) { + return applicationProperties.getFrontEndDomain() + "/myAppointmentList/contactedList?appointmentId=" + appointmentId; + } + + public Appointment findById(Long id) { + return appointmentRepository.findById(id) + .orElseThrow(AppointmentNotFoundException::new); + } + + public void closeAppointment(AppointmentCloseDTO closeDTO) { + if(closeDTO.getContactStatus() == ContactStatusEnum.DONE) { + DoneProcessDTO dto = new DoneProcessDTO(); + BeanUtils.copyProperties(closeDTO, dto); + abstractAppointmentProcess.process(dto); + }else if(closeDTO.getContactStatus() == ContactStatusEnum.CLOSED){ + ClosedProcessDTO dto = new ClosedProcessDTO(); + BeanUtils.copyProperties(closeDTO, dto); + abstractAppointmentProcess.process(dto); + } + } + + public Long getConsultantPendingAppointmentSum(String agentNo) { + return appointmentCustomerViewRepository.findAllByCommunicateStatusAndStatus(ContactStatusEnum.RESERVED, AVAILABLE) + .stream() + .filter(appointment -> agentNo.equals(appointment.getAgentNo())) + .filter(appointment -> isAppointmentDateNotInIntervalFromNow(appointment, Constants.APPOINTMENT_PENDING_PHONE_INTERVAL, Constants.APPOINTMENT_PENDING_EMAIL_INTERVAL)) + .count(); + } + + public AppointmentCustomerViewDTO getCustomerNewestExpiringAppointment(Long customerId) { + return appointmentCustomerViewRepository.findAllByCommunicateStatusAndStatus(ContactStatusEnum.RESERVED, AVAILABLE) + .stream() + .filter(appointment -> customerId.equals(appointment.getCustomerId())) + .filter(appointment -> isAppointmentDateNotInIntervalFromNow(appointment, Constants.APPOINTMENT_EXPIRING_PHONE_INTERVAL, Constants.APPOINTMENT_EXPIRING_EMAIL_INTERVAL)) + .max(Comparator.comparing(AppointmentCustomerView::getAppointmentDate)) + .map(appointmentCustomerView -> appointmentCustomerViewMapper.toAppointmentCustomerViewDTO(appointmentCustomerView)) + .orElse(null); + } + + public boolean isAppointmentDateNotInIntervalFromNow(AppointmentCustomerView 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; } } -- Gitblit v1.8.0