保誠-保戶業務員媒合平台
Tomas
2022-01-24 73307b0ada907f8ac857b3dfc4e7d50e3b7b92e9
Merge branch 'Phase3' of https://dev.pollex.com.tw:8443/r/pcalife/PAM into Phase3
修改15個檔案
新增2個檔案
242 ■■■■ 已變更過的檔案
PAMapp/assets/scss/vendors/elementUI/_rate.scss 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/DateTimePicker.vue 5 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Ui/UiDatePicker.vue 20 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Ui/UiTimePicker.vue 33 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/appointment/_appointmentId/close/index.vue 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/questionnaire/_agentNo.vue 11 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/doc/sql/淨空整個系統資料(除顧問).sql 12 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java 37 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/config/Constants.java 2 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/enums/SendEmailMsgMethod.java 6 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java 3 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java 63 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-dev.yml 18 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-pollex.yml 18 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-prod.yml 4 ●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-sit.yml 4 ●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
pamapi/src/main/resources/config/application-uat.yml 4 ●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_rate.scss
@@ -45,6 +45,7 @@
  display: flex;
  justify-content: center;
  margin-top: 10px;
  @extend .fix-chrome-click--issue;
  .el-rate__item {
    .el-rate__icon {
      font-size: 30px;
PAMapp/components/DateTimePicker.vue
@@ -5,12 +5,14 @@
        <UiDatePicker
            @changeDate="changeDateTime($event, 'date')"
            :isPastDateDisabled="isPastDateDisabled"
            :isFutureDateDisabled="isFutureDateDisabled"
            :defaultValue="defaultValue"
        ></UiDatePicker>
        <UiTimePicker
            @changeTime="changeDateTime($event, 'time')"
            :defaultValue="defaultValue"
            :isPastDateDisabled="isPastDateDisabled"
            :isFutureDateDisabled="isFutureDateDisabled"
            :changeDate="changeDate"
        ></UiTimePicker>
    </div>
@@ -30,6 +32,9 @@
    @Prop()
    isPastDateDisabled!: boolean;
    @Prop()
    isFutureDateDisabled!: boolean;
    @Emit('changeDateTime')
    changeDateTime(event, type) {
        if (type === 'date') {
PAMapp/components/Ui/UiDatePicker.vue
@@ -5,6 +5,7 @@
        v-model="dateValue"
        :clearable="false"
        type="date"
        :editable="false"
        format="yyyy/MM/dd"
        placeholder="選擇日期"
        prefix-icon="icon-down down-icon"
@@ -27,6 +28,9 @@
    @Prop({default: false})
    isPastDateDisabled!: boolean;
    @Prop({default: false})
    isFutureDateDisabled!: boolean;
    @Emit('changeDate')
    changeDate() {
        return this.dateValue;
@@ -41,16 +45,26 @@
    }
    get pickerOptions() {
        const date = new Date();
        const currentDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
        if (this.isPastDateDisabled) {
            return {
                disabledDate(time: Date) {
                    const date = new Date();
                    const currentDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
                    const pickedDate = `${time.getFullYear()}/${time.getMonth() + 1}/${time.getDate()}`
                    const pickedDate = `${time.getFullYear()}/${time.getMonth() + 1}/${time.getDate()}`;
                    return new Date(pickedDate).getTime() < new Date(currentDate).getTime();
                }
            }
        }
        if (this.isFutureDateDisabled) {
            return {
                disabledDate(time: Date) {
                    const pickedDate = `${time.getFullYear()}/${time.getMonth() + 1}/${time.getDate()}`;
                    return new Date(pickedDate).getTime() > new Date(currentDate).getTime();
                }
            }
        }
    }
}
PAMapp/components/Ui/UiTimePicker.vue
@@ -4,6 +4,7 @@
        popper-class="pam-time-popper"
        v-model="timeValue"
        :clearable="false"
        :editable="false"
        :picker-options="pickerOptions"
        placeholder="選擇時間"
        prefix-icon="icon-down down-icon"
@@ -29,6 +30,9 @@
    @Prop()
    isPastDateDisabled!: boolean;
    @Prop()
    isFutureDateDisabled!: boolean;
    ///////////////////////////////////////////////////////////////////////
    @Emit('changeTime')
@@ -49,25 +53,40 @@
    get pickerOptions() {
        let minTime = '';
        let maxTime = '';
        const currentDate = new Date();
        if (this.isPastDateDisabled && this.changeDate && this.isPickedToday(currentDate)) {
            minTime = this.formatTimeString(currentDate);
            this.isPickedDisableTime(currentDate, minTime);
        if (this.changeDate && this.isPickedToday(currentDate)) {
            if (this.isPastDateDisabled) {
                minTime = this.formatTimeString(currentDate);
                this.isPickedDisableTime(currentDate, minTime);
            }
            if (this.isFutureDateDisabled) {
                maxTime = this.formatTimeString(currentDate);
                this.isPickedDisableTime(currentDate, maxTime);
            }
        }
        return {
            start: '09:00',
            step: '00:15',
            end: '21:00',
            minTime: minTime
            minTime: minTime,
            maxTime: maxTime
        }
    }
    private isPickedDisableTime(currentDate: Date, minTime: string) {
        const currentTime = this.getTimeValue(currentDate, minTime);
    private isPickedDisableTime(currentDate: Date, minMaxTime: string) {
        const currentTime = this.getTimeValue(currentDate, minMaxTime);
        const pickedTime = this.getTimeValue(currentDate, this.timeValue);
        if (pickedTime < currentTime) {
        if (this.isPastDateDisabled && pickedTime < currentTime) {
            this.timeValue = '';
            this.changeTime();
        }
        if (this.isFutureDateDisabled && currentTime < pickedTime) {
            this.timeValue = '';
            this.changeTime();
        }
PAMapp/pages/appointment/_appointmentId/close/index.vue
@@ -46,6 +46,7 @@
          <UiField label="進件時間" :labelSize="20" class="required">
            <DateTimePicker
              :defaultValue="appointmentCloseInfo.policyEntryDate"
              :isFutureDateDisabled="true"
              @changeDateTime="appointmentCloseDate = $event"></DateTimePicker>
          </UiField>
        </el-row>
PAMapp/pages/questionnaire/_agentNo.vue
@@ -24,8 +24,12 @@
              <div class="ques-header__input-block">
                  <span>Email:</span>
                  <input class="ques-header__input"
                    :class="{ 'is-invalid': !emailValid}"
                    placeholder="請輸入"
                    v-model="myRequest.email">
              </div>
              <div class="error mt-5 mb-5" style="margin-left:65px">
                  <span v-show="!emailValid">Email格式有誤</span>
              </div>
          </div>
        </div>
@@ -466,6 +470,11 @@
            : true;
    }
    get emailValid() {
      const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
      return this.myRequest.email ? rule.test(this.myRequest.email) : true;
    }
    get userInfo(): RegisterInfo {
      const initUserInfo = JSON.parse(localStorage.getItem('userInfo')!);
      return initUserInfo;
@@ -473,7 +482,7 @@
    get isDisabledSubmitBtn(): boolean {
           return _.includes(this.myRequest.contactType,ContactType.PHONE)
      ? !this.isHopeContactTimeDone()
      ? !this.isHopeContactTimeDone() || !this.emailValid
      : !this.phoneValid;
    }
pamapi/src/doc/sql/²bªÅ¾ã­Ó¨t²Î¸ê®Æ(°£ÅU°Ý).sql
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,12 @@
truncate public.appointment;
truncate public.appointment_closed_info;
truncate public.appointment_expiring_notify_record;
truncate public.appointment_memo;
truncate public.appointment_notice_log;
truncate public.customer;
truncate public.interview_record;
truncate public.login_record;
truncate public.otp_tmp;
truncate public.personal_notification;
truncate public.satisfaction;
truncate public.customer_favorite_consultant;
pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java
@@ -1,5 +1,6 @@
package com.pollex.pam.config;
import com.pollex.pam.enums.SendEmailMsgMethod;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
@@ -19,7 +20,6 @@
    private String eServiceLoginFunc;
    private String eServiceLoginSys;
    private String frontEndDomain;
    private boolean sendNotifyMsg;
    private SMS sms;
    private Email email;
    private String fileFolderPath;
@@ -88,14 +88,6 @@
        this.frontEndDomain = frontEndDomain;
    }
    public boolean isSendNotifyMsg() {
        return sendNotifyMsg;
    }
    public void setSendNotifyMsg(boolean sendNotifyMsg) {
        this.sendNotifyMsg = sendNotifyMsg;
    }
    public SMS getSms() {
        return sms;
    }
@@ -118,6 +110,7 @@
        private String sender;
        private String smsType;
        private String subject;
        private boolean sendNotifyMsg;
        public String getUrl() {
            return url;
@@ -158,12 +151,22 @@
        public void setSubject(String subject) {
            this.subject = subject;
        }
        public boolean isSendNotifyMsg() {
            return sendNotifyMsg;
        }
        public void setSendNotifyMsg(boolean sendNotifyMsg) {
            this.sendNotifyMsg = sendNotifyMsg;
        }
    }
    public static class Email {
        private String url;
        private String functionId;
        private String senderEmail;
        private boolean sendNotifyMsg;
        private SendEmailMsgMethod method;
        public String getUrl() {
            return url;
@@ -188,6 +191,22 @@
        public void setSenderEmail(String senderEmail) {
            this.senderEmail = senderEmail;
        }
        public boolean isSendNotifyMsg() {
            return sendNotifyMsg;
        }
        public void setSendNotifyMsg(boolean sendNotifyMsg) {
            this.sendNotifyMsg = sendNotifyMsg;
        }
        public SendEmailMsgMethod getMethod() {
            return method;
        }
        public void setMethod(SendEmailMsgMethod method) {
            this.method = method;
        }
    }
    public String getFileFolderPath() {
        return fileFolderPath;
pamapi/src/main/java/com/pollex/pam/config/Constants.java
@@ -30,5 +30,7 @@
     */
    public static final int SEND_EXPIRING_NOTIFY_LIMIT = 1;
    public static final String SPRING_PROFILE_POLLEX_DEVELOPMENT = "pollex";
    private Constants() {}
}
pamapi/src/main/java/com/pollex/pam/enums/SendEmailMsgMethod.java
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,6 @@
package com.pollex.pam.enums;
public enum SendEmailMsgMethod {
    PAM_EMAIL_SERVICE,
    POLLEX_GMAIL
}
pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java
@@ -200,7 +200,8 @@
    public void sendAppointmentNotify(Appointment appointment) {
        Assert.notNull(appointment, "appointment entity cannot be null");
        log.debug("is need send appointment notify msg? = {}", applicationProperties.isSendNotifyMsg());
        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);
pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java
@@ -2,7 +2,10 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pollex.pam.config.ApplicationProperties;
import com.pollex.pam.config.ApplicationProperties.Email;
import com.pollex.pam.config.ApplicationProperties.SMS;
import com.pollex.pam.config.Constants;
import com.pollex.pam.enums.SendEmailMsgMethod;
import com.pollex.pam.repository.ConsultantRepository;
import com.pollex.pam.service.dto.*;
import com.pollex.pam.service.util.HttpRequestUtil;
@@ -11,9 +14,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.thymeleaf.spring5.SpringTemplateEngine;
import tech.jhipster.config.JHipsterConstants;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
@@ -38,13 +44,19 @@
    @Autowired
    SpringTemplateEngine springTemplateEngine;
    @Autowired
    Environment environment;
    @Autowired
    MailService mailService;
    public SendSMSResponse sendMsgBySMS(String toMobile, String content) throws SendSMSFailException {
        if(!applicationProperties.isSendNotifyMsg()) {
        SMS smsProperties = applicationProperties.getSms();
        if(!smsProperties.isSendNotifyMsg()) {
//            return getMockSMSResponse();
            return null;
        }
        SMS smsProperties = applicationProperties.getSms();
            return null;
        }
        SendSMSRequest sendSMSRequest = new SendSMSRequest();
        sendSMSRequest.setpKey(UUID.randomUUID().toString());
@@ -94,7 +106,7 @@
    public String sendMsgByEmail(String toAddress, String subject, String content, boolean htmlFormat, List<String> toCCAddress,
        List<String> attachments) throws SendEmailFailException {
        String fromAddress = applicationProperties.getEmail().getSenderEmail();
        SendMailRequest sendMailRequest = new SendMailRequest();
        sendMailRequest.setSendMailAddresses(Collections.singletonList(toAddress));
        sendMailRequest.setFrom(fromAddress);
@@ -109,25 +121,48 @@
    }
    public String sendMsgByEmail(SendMailRequest sendMailRequest) throws SendEmailFailException{
        if(!applicationProperties.isSendNotifyMsg()) {
            return null;
        }
        try {
        final Email emailProperties = applicationProperties.getEmail();
        if(!emailProperties.isSendNotifyMsg()) {
            return null;
        }
        if(emailProperties.getMethod() == SendEmailMsgMethod.POLLEX_GMAIL) {
            return sendMsgByPollexGmail(sendMailRequest);
        }
        else if(emailProperties.getMethod() == SendEmailMsgMethod.PAM_EMAIL_SERVICE) {
            return sendMsgByPamEmailService(sendMailRequest);
        }
        return null;
    }
    private String sendMsgByPollexGmail(SendMailRequest sendMailRequest) {
        String subject = sendMailRequest.getSubject();
        String content = sendMailRequest.getContent();
        boolean isHtml = sendMailRequest.isHtmlFormat();
        sendMailRequest.getSendMailAddresses().forEach(receiver -> mailService.sendEmail(receiver, subject, content, false, isHtml));
        return null;
    }
    private String sendMsgByPamEmailService(SendMailRequest sendMailRequest) {
        final Email emailProperties = applicationProperties.getEmail();
        try {
            ResponseEntity<String> responseEntity =
                HttpRequestUtil.postWithJson( applicationProperties.getEmail().getUrl(), sendMailRequest, String.class);
                HttpRequestUtil.postWithJson(emailProperties.getUrl(), sendMailRequest, String.class);
            log.debug("responseEntity = {}", responseEntity);
            String rawResponseString = responseEntity.getBody();
            SendMailResponse sendMailResponse = new ObjectMapper().readValue(rawResponseString, SendMailResponse.class);
            log.debug("sendMailResponse = {}", sendMailResponse);
            if(sendMailResponse == null || sendMailResponse.getData() == null || !"ADDED".equalsIgnoreCase(sendMailResponse.getData().getMessageStatus())) {
            if (sendMailResponse == null || sendMailResponse.getData() == null || !"ADDED".equalsIgnoreCase(sendMailResponse.getData().getMessageStatus())) {
                throw new SendEmailFailException("send email service return error msg! raw response string= " + rawResponseString);
            }
            return responseEntity.getBody();
        }
        catch (SendEmailFailException e) {
        } catch (SendEmailFailException e) {
            throw e;
        } catch (Exception e) {
            log.warn("send email fail by other reason", e);
pamapi/src/main/resources/config/application-dev.yml
@@ -45,10 +45,16 @@
    # Remove 'faker' if you do not want the sample data to be loaded automatically
    contexts: dev, faker
  mail:
    host: localhost
    port: 25
    username:
    password:
    host: smtp.gmail.com
    port: 587
    username: pollex.testing@gmail.com
    password: ilismmmhtscppxft
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
  messages:
    cache-duration: PT1S # 1 second, see the ISO 8601 standard
  thymeleaf:
@@ -120,15 +126,17 @@
  e-service-login-func: ValidateUsrLogin
  e-service-login-sys: epos
  front-end-domain: http://localhost:3000
  send-notify-msg: false
  sms:
    send-notify-msg: false
    url: https://localhost:8081/testSMS
    source-code: ePos
    sender: POS
    sms-type: '0017'
    subject: '媒合平台通知'
  email:
    send-notify-msg: false
    url: https://localhost:8081/testEmail
    function-id: epos
    sender-email: noreply@pcalife.com.tw
    method: 'POLLEX_GMAIL'
  file-folder-path: C://pam_file
pamapi/src/main/resources/config/application-pollex.yml
@@ -43,10 +43,16 @@
    # Remove 'faker' if you do not want the sample data to be loaded automatically
    contexts: pollex, faker
  mail:
    host: localhost
    port: 25
    username:
    password:
    host: smtp.gmail.com
    port: 587
    username: pollex.testing@gmail.com
    password: ilismmmhtscppxft
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
  messages:
    cache-duration: PT1S # 1 second, see the ISO 8601 standard
  thymeleaf:
@@ -118,15 +124,17 @@
  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:
    send-notify-msg: false
    url: https://localhost:8081/testSMS
    source-code: ePos
    sender: POS
    sms-type: '0017'
    subject: '媒合平台通知'
  email:
    send-notify-msg: true
    url: https://localhost:8081/testEmail
    function-id: epos
    sender-email: noreply@pcalife.com.tw
    method: 'POLLEX_GMAIL'
  file-folder-path: C://pam_file
pamapi/src/main/resources/config/application-prod.yml
@@ -140,15 +140,17 @@
  e-service-login-func: ValidateUsrLogin
  e-service-login-sys: epos
  front-end-domain: https://vtwlifeopensysuat.pru.intranet.asia/pam
  send-notify-msg: true
  sms:
    send-notify-msg: true
    url: https://vtwlifeopensysuat.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource
    source-code: ePos
    sender: POS
    sms-type: '0017'
    subject: '媒合平台通知'
  email:
    send-notify-msg: true
    url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail
    function-id: epos
    sender-email: noreply@pcalife.com.tw
    method: 'PAM_EMAIL_SERVICE'
  file-folder-path: /sfs_omo/vtwlifewpsfs01/SensitiveData4AP$/OMO
pamapi/src/main/resources/config/application-sit.yml
@@ -118,15 +118,17 @@
  e-service-login-func: ValidateUsrLogin
  e-service-login-sys: epos
  front-end-domain: https://vtwlifeopensyssit.pru.intranet.asia/pam
  send-notify-msg: true
  sms:
    send-notify-msg: true
    url: https://vtwlifeopensysuat.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource
    source-code: ePos
    sender: POS
    sms-type: '0017'
    subject: '媒合平台通知'
  email:
    send-notify-msg: true
    url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail
    function-id: epos
    sender-email: noreply@pcalife.com.tw
    method: 'PAM_EMAIL_SERVICE'
  file-folder-path: /sfs_omo/vtwlifewuftp66/sensitivedata4ap$/OMOSIT
pamapi/src/main/resources/config/application-uat.yml
@@ -118,15 +118,17 @@
  e-service-login-func: ValidateUsrLogin
  e-service-login-sys: epos
  front-end-domain: https://vtwlifeopensysuat.pru.intranet.asia/pam
  send-notify-msg: true
  sms:
    send-notify-msg: true
    url: https://vtwlifeopensysuat.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource
    source-code: ePos
    sender: POS
    sms-type: '0017'
    subject: '媒合平台通知'
  email:
    send-notify-msg: true
    url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail
    function-id: epos
    sender-email: noreply@pcalife.com.tw
    method: 'PAM_EMAIL_SERVICE'
  file-folder-path: /sfs_omo/vtwlifewuftp66/sensitivedata4ap$/OMO