package com.pollex.pam.service; import java.time.Instant; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import com.pollex.pam.config.ApplicationProperties; import com.pollex.pam.service.dto.AppointmentUpdateDTO; 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.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.pollex.pam.domain.Appointment; import com.pollex.pam.domain.AppointmentCustomerView; import com.pollex.pam.enums.ContactStatusEnum; 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.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 { private static final Logger log = LoggerFactory.getLogger(AppointmentService.class); private static final String NOTIFY_EMAIL_SUBJECT = "保誠媒合平台系統通知:新預約單"; @Autowired AppointmentRepository appointmentRepository; @Autowired AppointmentDTOMapper appointmentDTOMapper; @Autowired ConsultantService consultantService; @Autowired AppointmentCustomerViewMapper appointmentCustomerViewMapper; @Autowired AppointmentCustomerViewRepository appointmentCustomerViewRepository; @Autowired SatisfactionService satisfactionService; @Autowired SendMsgService sendMsgService; @Autowired ApplicationProperties applicationProperties; @Autowired SpringTemplateEngine springTemplateEngine; public Appointment customerCreateAppointment(AppointmentCreateDTO appointmentCreateDTO) { Appointment appointment = appointmentDTOMapper.toAppointment(appointmentCreateDTO); appointment.setStatus(AVAILABLE); appointment.setCustomerId(SecurityUtils.getCustomerDBId()); appointment.setCommunicateStatus(ContactStatusEnum.RESERVED); return appointmentRepository.save(appointment); } public void updateAppointment(AppointmentUpdateDTO updateAppointmentDTO) { Appointment appointment = appointmentRepository.findById(updateAppointmentDTO.getId()).get(); 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()); appointmentRepository.save(appointment); } public void markAppointmentDeleted(Long appointmentId) { Appointment appointment = appointmentRepository.findById(appointmentId).get(); appointment.setStatus(DELETED); appointment.setLastModifiedDate(Instant.now()); appointmentRepository.save(appointment); } public List findByAgentNo(String agentNo) { return appointmentRepository.findByAgentNo(agentNo); } public Appointment markAsContacted(Long appointmentId) { Appointment appointment = appointmentRepository.findById(appointmentId).get(); appointment.setCommunicateStatus(ContactStatusEnum.CONTACTED); 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); AppointmentCustomerViewDTO dto = appointmentCustomerViewMapper.toAppointmentCustomerViewDTO(appointment); setSatisfactionScore(dto, appointmentId); return dto; } public List 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 findAvailableByAgentNoAndCustomerId(String agentNo, Long customerId) { return appointmentCustomerViewRepository.findByAgentNoAndCustomerId(agentNo, customerId) .stream() .filter(appointmentCustomerView -> appointmentCustomerView.getStatus() == AVAILABLE) .collect(Collectors.toList()); } public Optional 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 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? = {}", applicationProperties.isSendNotifyMsg()); if(applicationProperties.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 senderEmail = applicationProperties.getEmail().getSenderEmail(); 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(senderEmail, 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; } }