pamapi/src/doc/sql/20211222_w.sql
¤ñ¹ï·sÀÉ®× @@ -0,0 +1 @@ ALTER TABLE omo.consultant ADD email varchar NULL; pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java
@@ -18,6 +18,8 @@ private String eServiceLoginUrl; private String eServiceLoginFunc; private String eServiceLoginSys; private String frontEndDomain; private boolean sendNotifyMsg; private SMS sms; private Email email; @@ -75,6 +77,22 @@ public void seteServiceLoginSys(String eServiceLoginSys) { this.eServiceLoginSys = eServiceLoginSys; } public String getFrontEndDomain() { return frontEndDomain; } public void setFrontEndDomain(String frontEndDomain) { this.frontEndDomain = frontEndDomain; } public boolean isSendNotifyMsg() { return sendNotifyMsg; } public void setSendNotifyMsg(boolean sendNotifyMsg) { this.sendNotifyMsg = sendNotifyMsg; } public SMS getSms() { @@ -135,6 +153,7 @@ public static class Email { private String url; private String functionId; private String senderEmail; public String getUrl() { return url; @@ -151,5 +170,13 @@ public void setFunctionId(String functionId) { this.functionId = functionId; } public String getSenderEmail() { return senderEmail; } public void setSenderEmail(String senderEmail) { this.senderEmail = senderEmail; } } } pamapi/src/main/java/com/pollex/pam/domain/Consultant.java
@@ -71,6 +71,9 @@ @Column(name = "communication_style") private String communicationStyle; @Column(name = "email") private String email; public Long getId() { return id; } @@ -230,6 +233,14 @@ this.communicationStyle = communicationStyle; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "Consultant{" + @@ -245,13 +256,14 @@ ", gender=" + gender + ", phoneNumber='" + phoneNumber + '\'' + ", companyAddress='" + companyAddress + '\'' + ", seniorityYear='" + seniorityYear + '\'' + ", seniorityMonth='" + seniorityMonth + '\'' + ", seniorityYear=" + seniorityYear + ", seniorityMonth=" + seniorityMonth + ", concept='" + concept + '\'' + ", experience='" + experience + '\'' + ", award='" + award + '\'' + ", recommend=" + recommend + ", communicationStyle='" + communicationStyle + '\'' + ", email='" + email + '\'' + '}'; } } pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java
@@ -53,12 +53,12 @@ @Autowired SatisfactionService satisfactionService; public void customerCreateAppointment(AppointmentCreateDTO appointmentCreateDTO) { public Appointment customerCreateAppointment(AppointmentCreateDTO appointmentCreateDTO) { Appointment appointment = appointmentDTOMapper.toAppointment(appointmentCreateDTO); appointment.setStatus(AVAILABLE); appointment.setCustomerId(SecurityUtils.getCustomerDBId()); appointment.setCommunicateStatus(ContactStatusEnum.RESERVED); appointmentRepository.save(appointment); return appointmentRepository.save(appointment); } public void updateAppointment(AppointmentUpdateDTO updateAppointmentDTO) { pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java
@@ -1,16 +1,23 @@ package com.pollex.pam.service; import com.fasterxml.jackson.databind.ObjectMapper; import com.pollex.pam.config.ApplicationProperties; import com.pollex.pam.config.ApplicationProperties.SMS; import com.pollex.pam.domain.Appointment; import com.pollex.pam.repository.ConsultantRepository; import com.pollex.pam.service.dto.*; import com.pollex.pam.service.util.HttpRequestUtil; 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.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.thymeleaf.context.Context; import org.thymeleaf.spring5.SpringTemplateEngine; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; @@ -27,10 +34,95 @@ private static final Logger log = LoggerFactory.getLogger(SendMsgService.class); private final Encoder encoder = Base64.getEncoder(); private static final String EMAIL_SUBJECT = "ä¿èª åªåå¹³å°ç³»çµ±éç¥ï¼æ°é ç´å®"; @Autowired ApplicationProperties applicationProperties; public void sendMsgBySMS(String toMobile, String content) throws SendSMSFailException{ @Autowired ConsultantRepository consultantRepository; @Autowired SpringTemplateEngine springTemplateEngine; public void sendAppointmentNotify(Appointment appointment) { Assert.notNull(appointment); log.debug("is need sending notify msg = {}", applicationProperties.isSendNotifyMsg()); if(applicationProperties.isSendNotifyMsg()) { log.debug("sending appointment notify, appointmentId = {}", appointment.getId()); sendAppointmentNotifyBySMS(appointment); sendAppointmentNotifyByEmail(appointment); // todo é確èªä¿èª æ¯å¦æéæ±ä½¿ç¨html mail // sendAppointmentNotifyByHtmlEmail(appointment); } } private void sendAppointmentNotifyBySMS(Appointment appointment) throws SendSMSFailException { String msg = getAppointmentNotifyWording(appointment); String consultantMobile = consultantRepository.findOneByAgentNo(appointment.getAgentNo()).get().getPhoneNumber(); try { sendMsgBySMS(consultantMobile, msg); } catch (SendSMSFailException e) { log.debug("send sms failed, appointment Id = {}", appointment.getId(), e); } } private void sendAppointmentNotifyByEmail(Appointment appointment) { // todo éå¾ç¥ä¿èª 系統å¯ä»¶ä¿¡ç®± (ä¸¦æ¹æ¼è¨å®æªä¸) String senderEmail = applicationProperties.getEmail().getSenderEmail(); String consultantEmail = consultantRepository.findOneByAgentNo(appointment.getAgentNo()).get().getEmail(); String content = getAppointmentNotifyWording(appointment); try { sendMsgByEmail(senderEmail, consultantEmail, EMAIL_SUBJECT, content, false); } catch (SendEmailFailException e) { log.debug("send email failed, appointment Id = {}", appointment.getId(), e); } } private void sendAppointmentNotifyByHtmlEmail(Appointment appointment) { // todo éå¾ç¥ä¿èª 系統å¯ä»¶ä¿¡ç®± (ä¸¦æ¹æ¼è¨å®æªä¸) String senderEmail = applicationProperties.getEmail().getSenderEmail(); String consultantEmail = consultantRepository.findOneByAgentNo(appointment.getAgentNo()).get().getEmail(); String customerMobile = appointment.getPhone(); String normalContent; if(StringUtils.hasText(customerMobile)) { normalContent = "親æçé¡§åæ¨å¥½ï¼æ¨æä¸çä¾èªä¿èª åªåå¹³å°çæ°é ç´å®ï¼è©²å®¢æ¶ææ©è碼çº" + customerMobile + "\n"; } else { normalContent = "親æçé¡§åæ¨å¥½ï¼æ¨æä¸çä¾èªä¿èª åªåå¹³å°çæ°é ç´å®\n"; } Context context = new Context(); context.setVariable("content", normalContent); context.setVariable("urlHint", getAppointmentDetailUrl(appointment.getId())); String content = springTemplateEngine.process("mail/appointmentNotifyEmail", context); try { sendMsgByEmail(senderEmail, consultantEmail, EMAIL_SUBJECT, content, true); } catch (SendEmailFailException e) { log.debug("send email failed, appointment Id = {}", appointment.getId(), e); } } private String getAppointmentNotifyWording(Appointment appointment) { String normalContent; if(StringUtils.hasText(appointment.getPhone())) { normalContent = "親æçé¡§åæ¨å¥½ï¼æ¨æä¸çä¾èªä¿èª åªåå¹³å°çæ°é ç´å®ï¼è©²å®¢æ¶ææ©è碼çº" + appointment.getPhone() + "\n"; } else { normalContent = "親æçé¡§åæ¨å¥½ï¼æ¨æä¸çä¾èªä¿èª åªåå¹³å°çæ°é ç´å®\n"; } String urlContent = "é»æç¶²åï¼" + getAppointmentDetailUrl(appointment.getId()) + " éååªå平尿¥çã"; return normalContent + urlContent; } public SendSMSResponse sendMsgBySMS(String toMobile, String content) throws SendSMSFailException { SMS smsProperties = applicationProperties.getSms(); SendSMSRequest sendSMSRequest = new SendSMSRequest(); @@ -54,6 +146,7 @@ log.debug("response status code = {}", responseEntity.getStatusCode()); log.debug("smsResponse = {}", responseEntity.getBody()); return responseEntity.getBody(); // todo å¯è½éè¦åè£ä¸å¾çºé¯èª¤èçï¼ä½è¦å 測é } catch (Exception e) { @@ -62,11 +155,20 @@ } } public void sendMsgByEmail(String from, String to, String subject, String content, boolean htmlFormat) throws SendEmailFailException{ sendMsgByEmail(from, to, subject, content, htmlFormat, Collections.emptyList(), Collections.emptyList()); public String sendMsgByHtmlTestTemplateEmail(String from, String to) { Context context = new Context(); context.setVariable("content", "親æçé¡§åæ¨å¥½ï¼æ¨æä¸çä¾èªä¿èª åªåå¹³å°çæ°é ç´å®\n"); context.setVariable("urlHint", getAppointmentDetailUrl(0L)); String content = springTemplateEngine.process("mail/appointmentNotifyEmail", context); return sendMsgByEmail(from, to, EMAIL_SUBJECT, content, true); } public void sendMsgByEmail( public String sendMsgByEmail(String from, String to, String subject, String content, boolean htmlFormat) throws SendEmailFailException{ return sendMsgByEmail(from, to, subject, content, htmlFormat, Collections.emptyList(), Collections.emptyList()); } public String sendMsgByEmail( String fromAddress, String toAddress, String subject, String content, boolean htmlFormat, List<String> toCCAddress, List<String> attachments) throws SendEmailFailException { @@ -80,21 +182,23 @@ sendMailRequest.setHtmlFormat(htmlFormat); sendMailRequest.setFunctionId(applicationProperties.getEmail().getFunctionId()); sendMsgByEmail(sendMailRequest); return sendMsgByEmail(sendMailRequest); } public void sendMsgByEmail(SendMailRequest sendMailRequest) throws SendEmailFailException{ private String sendMsgByEmail(SendMailRequest sendMailRequest) throws SendEmailFailException{ try { ResponseEntity<SendMailResponse> responseEntity = HttpRequestUtil.postWithJson( applicationProperties.getEmail().getUrl(), sendMailRequest, SendMailResponse.class); ResponseEntity<String> responseEntity = HttpRequestUtil.postWithJson( applicationProperties.getEmail().getUrl(), sendMailRequest, String.class); log.debug("responseEntity = {}", responseEntity); SendMailResponse sendMailResponse = responseEntity.getBody(); log.debug("response status code = {}", responseEntity.getStatusCode()); log.debug("emailResponse = {}", responseEntity.getBody()); SendMailResponse sendMailResponse = new ObjectMapper().readValue(responseEntity.getBody(), SendMailResponse.class); log.debug("sendMailResponse = {}", sendMailResponse); if(sendMailResponse == null || sendMailResponse.getData() == null || "ADDED".equalsIgnoreCase(sendMailResponse.getData().getMessageStatus())) { throw new SendEmailFailException(); } // if(sendMailResponse == null || sendMailResponse.getData() == null || "ADDED".equalsIgnoreCase(sendMailResponse.getData().getMessageStatus())) { // throw new SendEmailFailException(); // } return responseEntity.getBody(); } catch (SendEmailFailException e) { throw e; @@ -104,4 +208,8 @@ throw new SendEmailFailException(); } } private String getAppointmentDetailUrl(Long appointmentId) { return applicationProperties.getFrontEndDomain() + "/myAppointmentList/contactedList?appointmentId=" + appointmentId; } } pamapi/src/main/java/com/pollex/pam/service/dto/SendMailResponse.java
@@ -1,5 +1,8 @@ package com.pollex.pam.service.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class SendMailResponse { private Data data; @@ -11,6 +14,7 @@ this.data = data; } @JsonIgnoreProperties(ignoreUnknown = true) public static class Data { private String messageStatus; pamapi/src/main/java/com/pollex/pam/web/rest/AppointmentResource.java
@@ -1,5 +1,7 @@ package com.pollex.pam.web.rest; import com.pollex.pam.domain.Appointment; import com.pollex.pam.service.SendMsgService; import com.pollex.pam.service.dto.AppointmentUpdateDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; @@ -20,6 +22,9 @@ @Autowired SatisfactionService satisfactionService; @Autowired SendMsgService sendMsgService; @PutMapping("") public ResponseEntity<Void> updateAppointment(@RequestBody AppointmentUpdateDTO appointment) { appointmentService.updateAppointment(appointment); @@ -34,8 +39,9 @@ @PostMapping("/customer/create") public void clientCreateAppointment(@RequestBody AppointmentCreateDTO appointmentCreateDTO) { appointmentService.customerCreateAppointment(appointmentCreateDTO); } Appointment appointment = appointmentService.customerCreateAppointment(appointmentCreateDTO); sendMsgService.sendAppointmentNotify(appointment); } @PostMapping("/markAsContacted/{appointmentId}") public void markAsContacted(@PathVariable Long appointmentId) { pamapi/src/main/java/com/pollex/pam/web/rest/TestSendMsgResource.java
@@ -1,6 +1,8 @@ package com.pollex.pam.web.rest; import com.pollex.pam.repository.AppointmentRepository; import com.pollex.pam.service.SendMsgService; import com.pollex.pam.service.dto.SendSMSResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -13,21 +15,35 @@ @Autowired SendMsgService sendMsgService; @Autowired AppointmentRepository appointmentRepository; @GetMapping("/bySMS") public ResponseEntity<Void> bySMS(@RequestParam String toMobile, @RequestParam String content) { sendMsgService.sendMsgBySMS(toMobile, content); return ResponseEntity.noContent().build(); public ResponseEntity<SendSMSResponse> bySMS(@RequestParam String toMobile, @RequestParam String content) { return ResponseEntity.ok(sendMsgService.sendMsgBySMS(toMobile, content)); } @GetMapping("/byEmail") public ResponseEntity<Void> byEmail( public ResponseEntity<String> byEmail( @RequestParam String from, @RequestParam String to, @RequestParam String subject, @RequestParam String content, @RequestParam boolean htmlFormat ) { sendMsgService.sendMsgByEmail(from, to, subject, content, htmlFormat); return ResponseEntity.noContent().build(); return ResponseEntity.ok(sendMsgService.sendMsgByEmail(from, to, subject, content, htmlFormat)); } @GetMapping("/byHtmlEmail") public ResponseEntity<String> byHtmlEmail( @RequestParam String from, @RequestParam String to ) { return ResponseEntity.ok(sendMsgService.sendMsgByHtmlTestTemplateEmail(from, to)); } @GetMapping("/appointment/{appointmentId}") public void sendAppointmentNotify(@PathVariable Long appointmentId) { sendMsgService.sendAppointmentNotify(appointmentRepository.findById(appointmentId).get()); } } pamapi/src/main/java/com/pollex/pam/web/rest/errors/SendSMSFailException.java
@@ -3,7 +3,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR, reason = "send email failed") @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR, reason = "send sms failed") public class SendSMSFailException extends RuntimeException{ public SendSMSFailException(){} public SendSMSFailException(String message) { pamapi/src/main/resources/config/application-dev.yml
@@ -119,6 +119,8 @@ e-service-login-url: https://eserviceuat.pcalife.com.tw/sso/chatbotValidate e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: http://localhost:3000 send-notify-msg: false sms: url: https://localhost:8081/testSMS source-code: ePos @@ -127,3 +129,4 @@ email: url: https://localhost:8081/testEmail function-id: epos sender-email: test@pollex.com.tw pamapi/src/main/resources/config/application-pollex.yml
@@ -117,3 +117,14 @@ e-service-login-url: https://eserviceuat.pcalife.com.tw/sso/chatbotValidate e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: http://dev.pollex.com.tw:5566/pam send-notify-msg: false sms: url: https://localhost:8081/testSMS source-code: ePos sender: POS sms-type: '0017' email: url: https://localhost:8081/testEmail function-id: epos sender-email: test@pollex.com.tw pamapi/src/main/resources/config/application-sit.yml
@@ -117,6 +117,8 @@ e-service-login-url: https://eserviceuat.pcalife.com.tw/sso/chatbotValidate e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: https://vtwlifeopensyssit.pru.intranet.asia/pam send-notify-msg: true sms: url: https://vtwlifewinbo66.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource source-code: ePos @@ -125,3 +127,4 @@ email: url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail function-id: epos sender-email: test@pollex.com.tw pamapi/src/main/resources/config/application-uat.yml
@@ -117,6 +117,8 @@ e-service-login-url: https://eserviceuat.pcalife.com.tw/sso/chatbotValidate e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: https://vtwlifeopensysuat.pru.intranet.asia/pam send-notify-msg: true sms: url: https://vtwlifewinbo66.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource source-code: ePos @@ -125,3 +127,4 @@ email: url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail function-id: epos sender-email: test@pollex.com.tw pamapi/src/main/resources/templates/mail/appointmentNotifyEmail.html
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,15 @@ <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" lang="zh"> <head> <title>æ°çé ç´å®éç¥</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <p th:text="${content}">親æçé¡§åæ¨å¥½ï¼æ¨æä¸çä¾èªä¿èª åªåå¹³å°çæ°é ç´å®</p> <p> é»æç¶²åï¼ <a th:href="${urlHint}" th:text="${urlHint}">Url Position</a> éååªå平尿¥ç </p> </body> </html>