Merge branch 'Phase3' of https://dev.pollex.com.tw:8443/r/pcalife/PAM into Phase3
| | |
| | | <template> |
| | | <div> |
| | | <div class="interview__header"> |
| | | <div class="mdTxt">ç´è¨ªç´é</div> |
| | | <div class="pam-link-button--lg" |
| | | @click="addInterview">+æ°å¢</div> |
| | | </div> |
| | | |
| | | <template v-if="!interviewList.length"> |
| | | <div class="record-card record-card--empty"> |
| | | ç¡ç´è¨ªç´é |
| | | </div> |
| | | </template> |
| | | |
| | | <template v-if="interviewList.length"> |
| | | <div |
| | | v-for="(item, index) in futureList" |
| | | :key="index + 'feature'" |
| | | class="interview--future" |
| | | @click="editInterview(item)" |
| | | > |
| | | |
| | | <div class="record-card"> |
| | | <div class="record-card-date"> |
| | | <div> |
| | | <UiDateFormat |
| | | class="date bold" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="DAY" /> |
| | | </div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="time mt-5 line-space" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="TIME" /> |
| | | </div> |
| | | </div> |
| | | <div class="record-card-content"> |
| | | <span>{{item.content}}</span> |
| | | </div> |
| | | </div> |
| | | <div class="interview__header"> |
| | | <div class="mdTxt">ç´è¨ªç´é</div> |
| | | <div class="pam-link-button--lg" |
| | | @click="addInterview">+æ°å¢</div> |
| | | </div> |
| | | <InterviewCard :interviewList="displayList.slice(0, 3)"></InterviewCard> |
| | | |
| | | <section |
| | | class="interview--past" |
| | | v-for="(item, index) in pastList" |
| | | :key="index + 'past'" |
| | | @click="editInterview(item)" |
| | | > |
| | | <div class="record-card"> |
| | | <div class="record-card-date"> |
| | | <div> |
| | | <UiDateFormat |
| | | class="date bold" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="DAY" /> |
| | | </div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="time mt-5 line-space" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="TIME" /> |
| | | </div> |
| | | </div> |
| | | <div class="record-card-content"> |
| | | <span>{{item.content}}</span> |
| | | </div> |
| | | </div> |
| | | <section class="text--right mt-30" v-if="interviewList.length > 3"> |
| | | <div class="pam-link-button--lg" @click="readMoreBtn">å±éçæ´å¤</div> |
| | | </section> |
| | | |
| | | <section class="more-log-action"> |
| | | <div class="pam-link-button--lg">å±éçæ´å¤</div> |
| | | </section> |
| | | </template> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component, Prop, Watch, Mutation } from 'nuxt-property-decorator'; |
| | | import { Vue, Component, Prop, Watch } from 'nuxt-property-decorator'; |
| | | import { InterviewRecord } from '~/shared/models/appointment.model'; |
| | | |
| | | @Component |
| | |
| | | @Prop() |
| | | interviewList!: InterviewRecord[]; |
| | | |
| | | @Mutation |
| | | updateInterviewRecord!: (data: InterviewRecord) => void; |
| | | |
| | | appointmentId!: string; |
| | | |
| | | futureList: InterviewRecord[] = []; |
| | | pastList: InterviewRecord[] = []; |
| | | displayList: InterviewRecord[] = []; |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | |
| | | @Watch('interviewList', {immediate: true}) |
| | | updateInterviewList() { |
| | | if (this.interviewList && this.interviewList.length > 0) { |
| | | this.futureList = this.interviewList |
| | | .filter(item => new Date(item.interviewDate).getTime() >= new Date().getTime()) |
| | | this.pastList = this.interviewList |
| | | .filter(item => new Date(item.interviewDate).getTime() < new Date().getTime()); |
| | | this.displayList = this.interviewList |
| | | .map((i) => ({ ...i, sortDate: new Date(i.interviewDate)})) |
| | | .sort((preItem, nextItem) => +nextItem.sortDate - +preItem.sortDate); |
| | | } |
| | | } |
| | | |
| | |
| | | this.$router.push(`/appointment/${this.appointmentId}/interview/new`); |
| | | } |
| | | |
| | | editInterview(interviewRecord) { |
| | | this.updateInterviewRecord(interviewRecord); |
| | | this.$router.push(`/appointment/${this.appointmentId}/interview/${interviewRecord.id}`); |
| | | readMoreBtn() { |
| | | this.$router.push(`/appointment/${this.appointmentId}/interviewList`); |
| | | } |
| | | |
| | | } |
| | |
| | | display : flex; |
| | | justify-content: space-between; |
| | | margin-bottom : 10px; |
| | | } |
| | | .interview--future{ |
| | | border-bottom: 1px solid #CCCCCC; |
| | | padding-bottom: 17px; |
| | | margin-bottom: 17px; |
| | | .record{ |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | .record-card { |
| | | height: 62px; |
| | | border: 1px solid #707070; |
| | | border-radius: 5px; |
| | | display: flex; |
| | | border-bottom: 1px solid #000; |
| | | .record-card-date{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | margin-left: 10px; |
| | | margin-right: 10px; |
| | | margin-top: 10px; |
| | | } |
| | | .record-card-content{ |
| | | height: 42px; |
| | | margin-top: 10px; |
| | | margin-right: 10px; |
| | | line-height: 1.2; |
| | | } |
| | | &.record-card--empty { |
| | | align-items : center; |
| | | background-color: #fff; |
| | | color : $MID_GREY; |
| | | justify-content : center; |
| | | } |
| | | } |
| | | .line-space{ |
| | | letter-spacing: 1px; |
| | | } |
| | | .more-log-action{ |
| | | margin-top: 30px; |
| | | display: flex; |
| | | justify-content:flex-end; |
| | | } |
| | | </style> |
| | |
| | | <div class="record-log-component"> |
| | | <div class="mdTxt mt-30 mb-10">系統éç¥ç´é</div> |
| | | |
| | | <div v-for="(item, index) in displayLogs" |
| | | :key="index"> |
| | | <section |
| | | class="record-log-card" |
| | | > |
| | | <div class="record-log-card-date-container"> |
| | | <div class="record-log-card-date-container-circle"> |
| | | <div class="xxsTxt bold line-height">{{item.createdDate | formatYear}}</div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="xxsTxt bold line-height" |
| | | :date="item.createdDate" |
| | | onlyShowSection="DAY" /> |
| | | </div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="xxsTxt mt-4 line-space" |
| | | :date="item.createdDate" |
| | | onlyShowSection="TIME" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="record-log-msg"> |
| | | <div>ç¼éç´è¨ªéç¥ |
| | | <span v-if="item.email && item.phone">(ææ©ç°¡è¨ãEmail)</span> |
| | | <span v-else-if="item.email">(Email)</span> |
| | | <span v-else>(ææ©ç°¡è¨)</span> |
| | | </div> |
| | | <div class="mt-10">é ç´{{item.interviewDate | formatDate}}</div> |
| | | </div> |
| | | </section> |
| | | <div class="time-line"></div> |
| | | </div> |
| | | <InterviewRecordCard :noticeLogsList="displayLogs.slice(0, 3)"></InterviewRecordCard> |
| | | |
| | | <section class="more-log-action"> |
| | | <section class="text--right mt-30" v-if="displayLogs.length > 3"> |
| | | <div class="pam-link-button--lg" |
| | | @click="readMoreBtn" |
| | | >å±éçæ´å¤</div> |
| | | </section> |
| | | </div> |
| | |
| | | import { Vue, Component, Prop, Watch } from 'nuxt-property-decorator'; |
| | | import { NoticeLogs } from '~/shared/models/appointment.model'; |
| | | |
| | | @Component({ |
| | | filters: { |
| | | formatYear(value) { |
| | | if (value) { |
| | | return new Date(value).getFullYear(); |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | @Component |
| | | export default class AppointmentRecordList extends Vue { |
| | | |
| | | @Prop() |
| | |
| | | |
| | | appointmentId: string = ''; |
| | | displayLogs : NoticeLogs[] = []; |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | | mounted() { |
| | | this.appointmentId = this.$route.params.appointmentId; |
| | |
| | | } |
| | | } |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | | readMoreBtn() { |
| | | this.$router.push(`/appointment/${this.appointmentId}/recordList`); |
| | | } |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .record-log-component{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | .record-log-card{ |
| | | display: flex; |
| | | .record-log-card-date-container{ |
| | | position:relative; |
| | | .record-log-card-date-container-circle{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 56px; |
| | | height: 56px; |
| | | border-radius: 50%; |
| | | border:1px solid $PRIMARY_BLACK; |
| | | justify-content: center; |
| | | align-items: center; |
| | | align-content: center; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .mt-4{ |
| | | margin-top: 4px; |
| | | } |
| | | .line-space{ |
| | | letter-spacing: 1px; |
| | | } |
| | | .line-height{ |
| | | line-height:1.2; |
| | | } |
| | | .time-line{ |
| | | border-left: 1px solid black; |
| | | height: 30px; |
| | | margin-left: 28px; |
| | | |
| | | } |
| | | .record-log-msg{ |
| | | margin-left: 13px; |
| | | margin-top: 10px; |
| | | } |
| | | .more-log-action{ |
| | | display: flex; |
| | | justify-content:flex-end; |
| | | } |
| | | |
| | | </style> |
| | |
| | | import * as _ from 'lodash'; |
| | | import { Role } from '~/shared/models/enum/Role'; |
| | | |
| | | const roleStorage = namespace('localStorage'); |
| | | const appointmentStore = namespace('appointment.store'); |
| | | const roleStorage = namespace('localStorage'); |
| | | |
| | | @Component |
| | | export default class UiCarousel extends Vue { |
| | |
| | | @roleStorage.Getter |
| | | currentRole!:string; |
| | | |
| | | @appointmentStore.Getter |
| | | isCloseAppointment!: boolean; |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | | goBack(): void { |
| | | const pathName = this.$route.name; |
| | | pathName?.includes('myConsultantList') ? this.$router.push('/') : this.$router.go(-1); |
| | | pathName?.includes('myConsultantList') |
| | | ? this.$router.push('/') |
| | | : this.$router.go(-1); |
| | | } |
| | | |
| | | get label(): string { |
| | |
| | | featureLabel = 'F&Q 常è¦åé¡'; |
| | | break; |
| | | case 'appointment': |
| | | const appointmentFeatureLabel = this.$route.name.includes('close') ? 'çµæ¡' : 'é ç´è³è¨'; |
| | | const appointmentFeatureLabel = this.$route.name.includes('close') |
| | | ? 'çµæ¡' |
| | | : this.isCloseAppointment ? 'çµæ¡æç´°' : 'é ç´è³è¨'; |
| | | const inInterview = this.$route.name.includes('interview'); |
| | | const addNewInterview = this.$route.name.includes('new'); |
| | | if (inInterview) { |
| | | featureLabel = addNewInterview ? 'æ°å¢ç´è¨ªç´é' : '編輯ç´è¨ªç´é'; |
| | | const interviewList = this.$route.name.includes('interviewList'); |
| | | const recordList = this.$route.name.includes('recordList'); |
| | | if (interviewList) { |
| | | featureLabel = 'ç´è¨ªç´é'; |
| | | } else if (recordList) { |
| | | featureLabel = '系統éç¥ç´é'; |
| | | } else if (inInterview) { |
| | | featureLabel = addNewInterview |
| | | ? 'æ°å¢ç´è¨ªç´é' |
| | | : '編輯ç´è¨ªç´é'; |
| | | } else { |
| | | featureLabel = appointmentFeatureLabel; |
| | | } |
| | |
| | | <template> |
| | | <div class="edit-appointment-record"> |
| | | <div class="edit-appointment-record-date" v-if="interviewId"> |
| | | <div class="edit-appointment-record-date" v-if="interviewId && interviewRecord"> |
| | | <span>{{interviewRecord.createdDate | formatDate}} 建ç«</span> |
| | | <span>{{interviewRecord.lastModifiedDate | formatDate}} æ´æ°</span> |
| | | </div> |
| | |
| | | |
| | | <InterviewMsg |
| | | :isVisible.sync="showInterviewMsgPopup" |
| | | :client="appointmentDetail" |
| | | @closeDialog="closePopup" |
| | | ></InterviewMsg> |
| | | </div> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { InterviewRecord, InterviewRecordInfo } from '~/shared/models/appointment.model'; |
| | | import { Vue, Component, Prop, State, Mutation, Watch, Action } from 'nuxt-property-decorator'; |
| | | import { Appointment, InterviewRecord, InterviewRecordInfo } from '~/shared/models/appointment.model'; |
| | | import { Vue, Component, Watch, namespace } from 'nuxt-property-decorator'; |
| | | import appointmentService from '~/shared/services/appointment.service'; |
| | | |
| | | const appointmentStore = namespace('appointment.store'); |
| | | |
| | | @Component |
| | | export default class InterviewAdd extends Vue { |
| | | @State |
| | | interviewRecord!: InterviewRecord; |
| | | |
| | | @Mutation |
| | | updateInterviewRecord!: (data: InterviewRecord) => void; |
| | | @appointmentStore.State |
| | | appointmentDetail!: Appointment; |
| | | |
| | | @Mutation |
| | | clearInterviewRecord!: () => void; |
| | | @appointmentStore.Action |
| | | updateAppointmentDetail!: (id: number) => Appointment; |
| | | |
| | | interviewTime = ''; |
| | | content = ''; |
| | |
| | | |
| | | defaultValue = ''; |
| | | |
| | | interviewRecord!: InterviewRecord; |
| | | |
| | | //////////////////////////////////////////////////////////////////// |
| | | |
| | | mounted() { |
| | | this.interviewId = this.$route.params.interviewId; |
| | | this.appointmentId = this.$route.params.appointmentId; |
| | | const isEditPage = this.interviewId && this.interviewRecord; |
| | | if (isEditPage) { |
| | | this.checkInterviewRecord(); |
| | | } |
| | | } |
| | | |
| | | private checkInterviewRecord() { |
| | | if (this.interviewRecord.appointmentId !== +this.appointmentId |
| | | || this.interviewRecord.id !== +this.interviewId) { |
| | | appointmentService.getAppointmentDetail(+this.appointmentId).then((data) => { |
| | | const currentInterviewRecord = data.interviewRecordDTOs.filter(item => item.id === +this.interviewId)[0]; |
| | | this.updateInterviewRecord(currentInterviewRecord); |
| | | }) |
| | | } |
| | | } |
| | | |
| | | destroyed() { |
| | | this.clearInterviewRecord(); |
| | | this.onAppointmentDetailChange(); |
| | | } |
| | | |
| | | //////////////////////////////////////////////////////////////////// |
| | | |
| | | @Watch('interviewRecord', {immediate: true}) |
| | | watchInterviewRecord() { |
| | | if (this.interviewRecord && this.interviewRecord.content) { |
| | | this.content = this.interviewRecord.content; |
| | | this.defaultValue = this.interviewRecord.interviewDate; |
| | | @Watch('appointmentDetail', {immediate: true}) |
| | | onAppointmentDetailChange() { |
| | | if (this.appointmentDetail && this.appointmentDetail.id === +this.appointmentId) { |
| | | this.interviewRecord = this.appointmentDetail.interviewRecordDTOs |
| | | .filter(item => item.id === +this.interviewId)[0]; |
| | | |
| | | if (this.interviewRecord && this.interviewId) { |
| | | this.content = this.interviewRecord.content; |
| | | this.defaultValue = this.interviewRecord.interviewDate; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | private createdRecord(interviewRecordInfo) { |
| | | appointmentService.createInterviewRecord(interviewRecordInfo).then(res => { |
| | | this.confirmTxt = 'æ°å¢æå' |
| | | this.showPopUp(); |
| | | this.showPopUp('æ°å¢æå'); |
| | | }); |
| | | } |
| | | |
| | | private updateRecord(updateInterviewRecord) { |
| | | appointmentService.updateInterviewRecord(updateInterviewRecord).then(res => { |
| | | this.confirmTxt = '編輯æå'; |
| | | this.showPopUp(); |
| | | this.showPopUp('編輯æå'); |
| | | }); |
| | | } |
| | | |
| | | private showPopUp() { |
| | | private showPopUp(confirmTxt) { |
| | | this.confirmTxt = confirmTxt; |
| | | this.updateAppointmentDetail(+this.appointmentId); |
| | | |
| | | if (new Date(this.interviewTime).getTime() >= new Date().getTime()) { |
| | | this.showFutureDateConfirmPopup = true; |
| | | } else { |
| | |
| | | } |
| | | } |
| | | |
| | | closePopup() { |
| | | this.$router.push(`/appointment/${this.appointmentId}`); |
| | | } |
| | | |
| | | deleteInterviewRecord() { |
| | | appointmentService.deleteInterviewRecord(this.interviewId).then(res => { |
| | | this.confirmTxt = 'åªé¤æå'; |
| | | this.showConfirmPopup = true; |
| | | this.updateAppointmentDetail(+this.appointmentId); |
| | | }); |
| | | } |
| | | |
| | |
| | | this.defaultValue = this.interviewRecord.interviewDate; |
| | | this.isEdit = false; |
| | | } else { |
| | | this.$router.push(`/appointment/${this.appointmentId}`); |
| | | this.$router.go(-1); |
| | | } |
| | | } |
| | | |
| | | closePopup() { |
| | | this.$router.go(-1); |
| | | } |
| | | |
| | | //////////////////////////////////////////////////////////////////// |
| | | |
| | | get formatInterviewDate() { |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <template> |
| | | <div> |
| | | <template v-if="!interviewList.length"> |
| | | <div class="record-card record-card--empty"> |
| | | ç¡ç´è¨ªç´é |
| | | </div> |
| | | </template> |
| | | |
| | | <template v-else> |
| | | <div class="interview--future"> |
| | | <div class="record-card mb-10" |
| | | v-for="(item, index) in futureList" |
| | | :key="index + 'feature'" |
| | | @click="editInterview(item)" |
| | | > |
| | | <div class="record-card-date"> |
| | | <div> |
| | | <UiDateFormat |
| | | class="date bold" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="DAY" /> |
| | | </div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="time mt-5 line-space" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="TIME" /> |
| | | </div> |
| | | </div> |
| | | <div class="record-card-content"> |
| | | <span>{{item.content}}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <section class="interview--past" v-if="pastList.length"> |
| | | <div class="record-card mb-10" |
| | | v-for="(item, index) in pastList" |
| | | :key="index + 'past'" |
| | | @click="editInterview(item)" |
| | | > |
| | | <div class="record-card-date"> |
| | | <div> |
| | | <UiDateFormat |
| | | class="date bold" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="DAY" /> |
| | | </div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="time mt-5 line-space" |
| | | :date="item.interviewDate" |
| | | onlyShowSection="TIME" /> |
| | | </div> |
| | | </div> |
| | | <div class="record-card-content"> |
| | | <span>{{item.content}}</span> |
| | | </div> |
| | | </div> |
| | | </section> |
| | | </template> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Component, Prop, Vue, Watch } from "nuxt-property-decorator"; |
| | | import { InterviewRecord } from "~/shared/models/appointment.model"; |
| | | |
| | | @Component |
| | | export default class InterviewCard extends Vue { |
| | | |
| | | @Prop() |
| | | interviewList!: InterviewRecord[]; |
| | | |
| | | futureList: InterviewRecord[] = []; |
| | | pastList: InterviewRecord[] = []; |
| | | |
| | | appointmentId!: number; |
| | | |
| | | mounted() { |
| | | this.appointmentId = +this.$route.params.appointmentId; |
| | | } |
| | | |
| | | @Watch('interviewList', {immediate: true}) |
| | | onInterviewListChange() { |
| | | if (this.interviewList.length > 0) { |
| | | this.futureList = this.interviewList |
| | | .filter(item => new Date(item.interviewDate).getTime() >= new Date().getTime()) |
| | | .sort((preItem, nextItem) => +new Date(nextItem.interviewDate) - +new Date(preItem.interviewDate)); |
| | | this.pastList = this.interviewList |
| | | .filter(item => new Date(item.interviewDate).getTime() < new Date().getTime()) |
| | | .sort((preItem, nextItem) => +new Date(nextItem.interviewDate) - +new Date(preItem.interviewDate)); |
| | | } |
| | | |
| | | } |
| | | |
| | | editInterview(interviewRecord) { |
| | | this.$router.push(`/appointment/${this.appointmentId}/interview/${interviewRecord.id}`); |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .interview--future{ |
| | | .record{ |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | .interview--past { |
| | | border-top: 1px solid #CCCCCC; |
| | | padding-top: 17px; |
| | | margin-top: 17px; |
| | | } |
| | | .record-card { |
| | | height: 62px; |
| | | border: 1px solid #707070; |
| | | border-radius: 5px; |
| | | display: flex; |
| | | border-bottom: 1px solid #000; |
| | | .record-card-date{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | margin-left: 10px; |
| | | margin-right: 10px; |
| | | margin-top: 10px; |
| | | } |
| | | .record-card-content{ |
| | | height: 42px; |
| | | margin-top: 10px; |
| | | margin-right: 10px; |
| | | line-height: 1.2; |
| | | } |
| | | &.record-card--empty { |
| | | align-items : center; |
| | | background-color: #fff; |
| | | color : $MID_GREY; |
| | | justify-content : center; |
| | | } |
| | | } |
| | | .line-space{ |
| | | letter-spacing: 1px; |
| | | } |
| | | </style> |
| | |
| | | import { AgentInfo } from '~/shared/models/agent-info.model'; |
| | | |
| | | const loginStore = namespace('login.store'); |
| | | const appointmentStore = namespace('appointment.store'); |
| | | |
| | | @Component |
| | | export default class InterviewMsg extends Vue { |
| | | |
| | | @Action |
| | | storeMyAppointmentList!: () => Promise<number>; |
| | | |
| | | @appointmentStore.Action |
| | | updateAppointmentDetail!: (id: number) => Appointment; |
| | | |
| | | @PropSync('isVisible') |
| | | dialogVisible!: boolean; |
| | |
| | | }; |
| | | appointmentService.informAppointment(appointmentInformation).then((_) => { |
| | | this.isShowSuccessAlert = true ; |
| | | this.updateAppointmentDetail(this.client.id); |
| | | }); |
| | | } |
| | | |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <template> |
| | | <div class="record-log-component"> |
| | | <div v-for="(item, index) in noticeLogsList" |
| | | :key="index"> |
| | | <section |
| | | class="record-log-card" |
| | | > |
| | | <div class="record-log-card-date-container"> |
| | | <div class="record-log-card-date-container-circle"> |
| | | <div> |
| | | <UiDateFormat |
| | | class="xxsTxt bold line-height" |
| | | :date="item.createdDate" |
| | | onlyShowSection="YEAR" /> |
| | | </div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="xxsTxt bold line-height" |
| | | :date="item.createdDate" |
| | | onlyShowSection="DATE" /> |
| | | </div> |
| | | <div> |
| | | <UiDateFormat |
| | | class="xxsTxt mt-4 line-space" |
| | | :date="item.createdDate" |
| | | onlyShowSection="TIME" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="record-log-msg"> |
| | | <div>ç¼éç´è¨ªéç¥ |
| | | <span v-if="item.email && item.phone">(ææ©ç°¡è¨ãEmail)</span> |
| | | <span v-else-if="item.email">(Email)</span> |
| | | <span v-else>(ææ©ç°¡è¨)</span> |
| | | </div> |
| | | <div class="mt-10">é ç´{{item.interviewDate | formatDate}}</div> |
| | | </div> |
| | | </section> |
| | | <div class="time-line"></div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Component, Prop, Vue } from "nuxt-property-decorator"; |
| | | import { NoticeLogs } from "~/shared/models/appointment.model"; |
| | | |
| | | @Component |
| | | export default class RecordCard extends Vue { |
| | | @Prop() |
| | | noticeLogsList!: NoticeLogs[]; |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .record-log-component{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | .record-log-card{ |
| | | display: flex; |
| | | .record-log-card-date-container{ |
| | | position:relative; |
| | | .record-log-card-date-container-circle{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 56px; |
| | | height: 56px; |
| | | border-radius: 50%; |
| | | border:1px solid $PRIMARY_BLACK; |
| | | justify-content: center; |
| | | align-items: center; |
| | | align-content: center; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .mt-4{ |
| | | margin-top: 4px; |
| | | } |
| | | .line-space{ |
| | | letter-spacing: 1px; |
| | | } |
| | | .line-height{ |
| | | line-height:1.2; |
| | | } |
| | | .time-line{ |
| | | border-left: 1px solid black; |
| | | height: 30px; |
| | | margin-left: 28px; |
| | | |
| | | } |
| | | .record-log-msg{ |
| | | margin-left: 13px; |
| | | margin-top: 10px; |
| | | } |
| | | </style> |
| | |
| | | date!: Date | string; |
| | | |
| | | @Prop() |
| | | onlyShowSection!: 'DAY' | 'TIME'; |
| | | onlyShowSection!: 'YEAR' | 'DATE' | 'DAY' | 'TIME'; |
| | | |
| | | compareTarget!: Date; |
| | | displayValue = ''; |
| | |
| | | this.displayValue = isThisYear(compareTarget) ? thisYearDayLabel : `${compareTarget.getFullYear()}/${compareTarget.getMonth() + 1}/${compareTarget.getDate()}`; |
| | | } else if (this.onlyShowSection === 'TIME') { |
| | | this.displayValue = `${compareTarget.getHours()}:${minutes}`; |
| | | } else if (this.onlyShowSection === 'DATE') { |
| | | this.displayValue = isThisYear(compareTarget) |
| | | ? thisYearDayLabel |
| | | : `${compareTarget.getMonth() + 1}/${compareTarget.getDate()}`; |
| | | } else if (this.onlyShowSection === 'YEAR') { |
| | | this.displayValue = `${compareTarget.getFullYear()}`; |
| | | } |
| | | |
| | | if (this.onlyShowSection) return; |
| | |
| | | <template v-if="appointmentCloseInfo.selectCloseOption === 'done'"> |
| | | <el-row |
| | | type="flex" |
| | | class="pam-paragraph"> |
| | | class="pam-paragraph" style="flex-direction: column"> |
| | | <UiField label="ä¿æ¶èº«åèåè" :labelSize="20"> |
| | | <input |
| | | class="appointment-client-detail-close__input" |
| | | :class="{'is-invalid':!identityIdValid}" |
| | | v-model="appointmentCloseInfo.policyholderIdentityId" |
| | | placeholder="è«è¼¸å
¥" |
| | | type="text"> |
| | | </UiField> |
| | | <div class="error mt-5 mb-5" v-show="!identityIdValid"> |
| | | <span>身åèåèæ ¼å¼æèª¤</span> |
| | | </div> |
| | | </el-row> |
| | | |
| | | <el-row |
| | |
| | | type="flex" |
| | | class="pam-paragraph"> |
| | | <UiField label="é²ä»¶æé" :labelSize="20"> |
| | | <DateTimePicker @changeDateTime="appointmentCloseDate = $event"></DateTimePicker> |
| | | <DateTimePicker @changeDateTime="appointmentCloseDate = $event"></DateTimePicker> |
| | | </UiField> |
| | | </el-row> |
| | | </template> |
| | |
| | | justify="center" |
| | | class="pam-paragraph"> |
| | | <el-button @click="$router.go(-1)">åæ¶</el-button> |
| | | <el-button @click="closeAppointment">確èª</el-button> |
| | | <el-button @click="closeAppointment" :disabled="isSubmitBtnDisabled">確èª</el-button> |
| | | </el-row> |
| | | |
| | | <PopUpFrame :isOpen.sync="isShowSuccessAlert"> |
| | |
| | | this.$router.push(`/myAppointmentList/contactedList`); |
| | | } |
| | | |
| | | get isSubmitBtnDisabled() { |
| | | const { |
| | | selectCloseOption, |
| | | policyholderIdentityId, |
| | | planCode, |
| | | remark, |
| | | closedReason, |
| | | closedOtherReason |
| | | } = this.appointmentCloseInfo; |
| | | // this.appointmentCloseInfo.policyEntryDate ä¸¦æ²æè¾¦æ³åå¼å° this.appointmentCloseDate |
| | | if (selectCloseOption === 'done') { |
| | | return !policyholderIdentityId || !this.identityIdValid || !planCode || !this.appointmentCloseDate || !remark |
| | | } else if (closedReason === 'other' || closedReason === 'no_suitable_commodity') { |
| | | return !closedOtherReason || !remark |
| | | } |
| | | return !remark |
| | | } |
| | | |
| | | get identityIdValid() { |
| | | const rule = /^[A-Z]\d{9}$/; |
| | | const identityId = this.appointmentCloseInfo.policyholderIdentityId; |
| | | return identityId ? rule.test(identityId) : true; |
| | | } |
| | | |
| | | } |
| | | </script> |
| | | |
| | |
| | | &::placeholder { |
| | | color: $MID_GREY; |
| | | } |
| | | &.is-invalid { |
| | | border-color: $PRIMARY_RED !important; |
| | | } |
| | | } |
| | | .invite-review{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | .error { |
| | | @extend .smTxt_bold; |
| | | @extend .text--primary; |
| | | height: 16px; |
| | | } |
| | | </style> |
| | |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Context } from '@nuxt/types'; |
| | | |
| | | import { Vue, Component } from 'vue-property-decorator'; |
| | | import { namespace } from 'nuxt-property-decorator'; |
| | | |
| | | import appointmentService from '~/shared/services/appointment.service'; |
| | | import { Appointment } from '~/shared/models/appointment.model'; |
| | | import { ContactStatus } from '~/shared/models/enum/contact-status'; |
| | | |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | <template> |
| | | <div> |
| | | <div class="text--right mb-30"> |
| | | <div class="pam-link-button--lg" |
| | | @click="addInterview">+æ°å¢</div> |
| | | </div> |
| | | <InterviewCard :interviewList="appointmentDetail.interviewRecordDTOs"></InterviewCard> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Component, namespace, Vue } from "nuxt-property-decorator"; |
| | | import { Appointment } from "~/shared/models/appointment.model"; |
| | | |
| | | const appointmentStore = namespace('appointment.store'); |
| | | |
| | | @Component |
| | | export default class InterviewList extends Vue { |
| | | @appointmentStore.State |
| | | appointmentDetail!: Appointment; |
| | | |
| | | appointmentId!: number; |
| | | |
| | | //////////////////////////////////////////////////////// |
| | | |
| | | mounted() { |
| | | this.appointmentId = +this.$route.params.appointmentId; |
| | | } |
| | | |
| | | //////////////////////////////////////////////////////// |
| | | |
| | | addInterview(): void { |
| | | this.$router.push(`/appointment/${this.appointmentId}/interview/new`); |
| | | } |
| | | |
| | | } |
| | | </script> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | |
| | | <template> |
| | | <InterviewRecordCard :noticeLogsList="displayLogs"></InterviewRecordCard> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Component, namespace, Vue, Watch } from "nuxt-property-decorator"; |
| | | import { Appointment, NoticeLogs } from "~/shared/models/appointment.model"; |
| | | |
| | | const appointmentStore = namespace('appointment.store'); |
| | | |
| | | @Component |
| | | export default class RecordList extends Vue { |
| | | @appointmentStore.State |
| | | appointmentDetail!: Appointment; |
| | | |
| | | displayLogs: NoticeLogs[] = []; |
| | | |
| | | //////////////////////////////////////////////////////// |
| | | |
| | | @Watch('appointmentDetail', {immediate: true}) |
| | | onAppointmentDetailChange() { |
| | | if (this.appointmentDetail?.appointmentNoticeLogs.length) { |
| | | this.displayLogs = this.appointmentDetail?.appointmentNoticeLogs |
| | | .map((i) => ({ ...i, sortDate: new Date(i.createdDate)})) |
| | | .sort((preItem, nextItem) => +nextItem.sortDate - +preItem.sortDate); |
| | | } |
| | | } |
| | | |
| | | } |
| | | </script> |
| | |
| | | ></i> |
| | | </el-input> |
| | | |
| | | <div class="sort-indicator mb-10 text--primary text--underline cursor--pointer" @click="changeSortType"> |
| | | {{ this.sortType === 'DESC' ? 'æ°->è' : 'è->æ°' }} |
| | | </div> |
| | | |
| | | <ClientList |
| | | :clients="pageList" |
| | | :title="'contactedList'" |
| | | ></ClientList> |
| | | |
| | | <UiPagination |
| | | v-if="togglePagination" |
| | | :totalList="filterList" |
| | | :currentPage="currentPage" |
| | | @changePage="changePage" |
| | |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component, Watch, State, namespace } from 'nuxt-property-decorator'; |
| | | import { Vue, Component, Watch, namespace } from 'nuxt-property-decorator'; |
| | | |
| | | import { Appointment } from '~/shared/models/appointment.model'; |
| | | |
| | |
| | | @localStorage.Getter |
| | | currentAppointmentIdFromMsg!: string; |
| | | |
| | | contactedList: Appointment[] = []; |
| | | filterList : Appointment[] = []; |
| | | keyWord : string = ''; |
| | | pageList : Appointment[] = []; |
| | | currentPage : number = 1; |
| | | contactedList : Appointment[] = []; |
| | | currentPage : number = 1; |
| | | filterList : Appointment[] = []; |
| | | keyWord : string = ''; |
| | | pageList : Appointment[] = []; |
| | | sortType : 'ASC' | 'DESC' = 'DESC'; |
| | | togglePagination: boolean = true; |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | |
| | | |
| | | @Watch('myAppointmentList') |
| | | onMyAppointmentListChange() { |
| | | this.setContactedList(); |
| | | } |
| | | |
| | | @Watch('sortType') |
| | | onSortTypeChange() { |
| | | this.togglePagination = false; |
| | | setTimeout(() => { |
| | | this.togglePagination = true; |
| | | this.currentPage = 1; |
| | | this.setContactedList(); |
| | | }, 0) |
| | | } |
| | | |
| | | private setContactedList(): void { |
| | | this.contactedList = (this.myAppointmentList || []) |
| | | .filter(item => item.communicateStatus === 'contacted') |
| | | .map((item) => ({...item, sortTime: new Date(item.contactTime)})) |
| | | .sort((prevItem, nextItem) => +nextItem.sortTime - +prevItem.sortTime); |
| | | .map((item) => ({...item, sortTime: new Date(item.lastModifiedDate)})) |
| | | .sort((prevItem, nextItem) => { |
| | | return this.sortType === 'DESC' ? +nextItem.sortTime - +prevItem.sortTime : +prevItem.sortTime - +nextItem.sortTime |
| | | }); |
| | | this.filterList = this.contactedList; |
| | | |
| | | this.getCurrentPage(); |
| | | } |
| | | |
| | | private getCurrentPage() { |
| | | private getCurrentPage(): void { |
| | | const currentIndex = this.filterList.findIndex(item => item.id === +this.currentAppointmentIdFromMsg); |
| | | const pageSize = 5; |
| | | if (currentIndex > -1) { |
| | |
| | | this.pageList = pageList; |
| | | } |
| | | |
| | | changeSortType(): void { |
| | | if (this.sortType === 'DESC') { |
| | | this.sortType = 'ASC'; |
| | | } else { |
| | | this.sortType = 'DESC'; |
| | | } |
| | | } |
| | | |
| | | } |
| | | </script> |
| | |
| | | import { ContactStatus } from "./enum/contact-status"; |
| | | |
| | | export interface AppointmentLog { |
| | | id : number; |
| | | createdDate : string; |
| | | lastModifiedDate: string; |
| | | customerId : number; |
| | | agentNo : string; |
| | | status : 'UNFILLED' | 'FILLED'; |
| | | score : number; |
| | | agentName : string; |
| | | agentNo : string; |
| | | appointmentId : number; |
| | | createdDate : string; |
| | | customerId : number; |
| | | customerName : string; |
| | | id : number; |
| | | lastModifiedDate: string; |
| | | score : number; |
| | | status : 'UNFILLED' | 'FILLED'; |
| | | } |
| | | |
| | | export interface Appointment { |
| | |
| | | |
| | | //客æ¶é²è¡æ»¿æåº¦è©å |
| | | userReviewsConsultants(data: UserReviewsConsultantsParams) { |
| | | return http.post('/satisfaction/create', data ); |
| | | return http.post('/satisfaction/score', data ); |
| | | } |
| | | |
| | | //å徿æè©åç´é |
| | | async getMyReviewLog(): Promise<AppointmentLog[]> { |
| | | return http.get('/satisfaction/getMySatisfaction').then(res => res.data); |
| | | } |
| | | |
| | | // é¡§å主åç¼é滿æåº¦éç¥ |
| | | sendSatisfactionToClient(appointmentId: number): void { |
| | | http.post('/consultant/sendSatisfactionToClient/').then((res) => res); |
| | | } |
| | | } |
| | | |
| | | export default new ReviewsService(); |
| | |
| | | .filter(item => item.communicateStatus === this.contactStatus.DONE || item.communicateStatus === this.contactStatus.CLOSE ).length; |
| | | } |
| | | |
| | | get isCloseAppointment(): boolean { |
| | | const closedStatusList = [this.contactStatus.DONE, this.contactStatus.CLOSE, this.contactStatus.CANCEL]; |
| | | return closedStatusList.includes(this.appointmentDetail!.communicateStatus); |
| | | } |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | | @Mutation |
| | |
| | | import reviewsService from '~/shared/services/reviews.service'; |
| | | import { Consultant } from '~/shared/models/consultant.model'; |
| | | import { getFavoriteFromStorage, setFavoriteToStorage } from '~/shared/storageConsultant'; |
| | | import { AppointmentLog, InterviewRecord } from '~/shared/models/appointment.model'; |
| | | import { AppointmentLog } from '~/shared/models/appointment.model'; |
| | | import { AgentOfStrictQuery, StrictQueryParams } from '~/shared/models/strict-query.model'; |
| | | |
| | | @Module |
| | |
| | | myConsultantList: Consultant[] = []; |
| | | |
| | | myAppointmentReviewLogList: AppointmentLog[] = []; |
| | | interviewRecord: InterviewRecord = { |
| | | appointmentId : 0, |
| | | content : '', |
| | | createdBy : '', |
| | | createdDate : '', |
| | | id : 0, |
| | | interviewDate : '', |
| | | lastModifiedBy : '', |
| | | lastModifiedDate: '' |
| | | } |
| | | |
| | | get isUserLogin() { |
| | | return this.context.getters['localStorage/isUserLogin']; |
| | |
| | | @Mutation |
| | | updateMyAppointmentReviewLog(data: AppointmentLog[]) { |
| | | this.myAppointmentReviewLogList = data; |
| | | } |
| | | |
| | | @Mutation |
| | | updateInterviewRecord(data: InterviewRecord) { |
| | | this.interviewRecord = data; |
| | | } |
| | | |
| | | @Mutation |
| | | clearInterviewRecord() { |
| | | this.interviewRecord = { |
| | | appointmentId : 0, |
| | | content : '', |
| | | createdBy : '', |
| | | createdDate : '', |
| | | id : 0, |
| | | interviewDate : '', |
| | | lastModifiedBy : '', |
| | | lastModifiedDate: '' |
| | | } |
| | | } |
| | | |
| | | @Action |
| | |
| | | http post : |
| | | |
| | | http://localhost:8080/api/satisfaction/create |
| | | http://localhost:8080/api/satisfaction/score |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | appointmentNoticeLogs: é ç´å®ç¼ééç¥çæ·ç¨ |
| | | appointmentClosedInfo: é ç´å®çµæ¡è³æ |
| | | |
| | | |
| | | response body: |
| | | [ { |
| | | "id" : 385, |
| | | "phone" : "0911223344", |
| | | "email" : "SDD", |
| | | "contactType" : "phone", |
| | | "gender" : "female", |
| | | "age" : "21-30", |
| | | "job" : "å
§å¤", |
| | | "requirement" : "å¥åº·èä¿é", |
| | | "communicateStatus" : "contacted", |
| | | "hopeContactTime" : "'ææä¸,ææäº,ææä¸,ææå,ææäº,ææå
,æææ¥ã9:00~12:00,12:00~14:00,14:00~18:00,18:00~21:00'", |
| | | "otherRequirement" : null, |
| | | "appointmentDate" : "2021-12-16T07:11:05.400Z", |
| | | "lastModifiedDate" : "2021-12-28T07:16:37.004Z", |
| | | "agentNo" : "A568420", |
| | | "customerId" : 139, |
| | | "name" : "Angula-test", |
| | | "consultantViewTime" : "2021-12-27T02:02:18.711Z", |
| | | "consultantReadTime" : "2021-12-28T07:16:01.295Z", |
| | | "contactTime" : "2021-12-28T07:16:37.004Z", |
| | | "satisfactionScore" : null, |
| | | "appointmentMemoList" : [ ], |
| | | "interviewRecordDTOs" : [ ], |
| | | "appointmentNoticeLogs" : [ { |
| | | "id" : 1, |
| | | "phone" : "0912345678", |
| | | "email" : "pollex@gmail.com", |
| | | "appointmentId" : 385, |
| | | "content" : "notice customer invterview time", |
| | | "createdDate" : "2022-01-11T08:54:35.651Z" |
| | | }, { |
| | | "id" : 2, |
| | | "phone" : "0912345678", |
| | | "email" : "pollex@gmail.com", |
| | | "appointmentId" : 385, |
| | | "content" : "notice customer invterview time", |
| | | "createdDate" : "2022-01-11T08:57:23.133Z" |
| | | } ] |
| | | } ] |
| | | { |
| | | "id": 385, |
| | | "phone": "0911223344", |
| | | "email": "SDD", |
| | | "contactType": "phone", |
| | | "gender": "female", |
| | | "age": "21-30", |
| | | "job": "å
§å¤", |
| | | "requirement": "å¥åº·èä¿é", |
| | | "communicateStatus": "done", |
| | | "hopeContactTime": "'ææä¸,ææäº,ææä¸,ææå,ææäº,ææå
,æææ¥ã9:00~12:00,12:00~14:00,14:00~18:00,18:00~21:00'", |
| | | "otherRequirement": null, |
| | | "appointmentDate": "2021-12-16T07:11:05.400Z", |
| | | "lastModifiedDate": "2022-01-19T10:57:51.380Z", |
| | | "agentNo": "A568420", |
| | | "customerId": 139, |
| | | "name": "Angula-test", |
| | | "consultantViewTime": "2021-12-27T02:02:18.711Z", |
| | | "consultantReadTime": "2021-12-28T07:16:01.295Z", |
| | | "contactTime": "2021-12-28T07:16:37.004Z", |
| | | "satisfactionScore": null, |
| | | "appointmentMemoList": [], |
| | | "interviewRecordDTOs": [], |
| | | "appointmentNoticeLogs": [ |
| | | { |
| | | "id": 4, |
| | | "phone": "0912345678", |
| | | "email": "pollex@gmail.com", |
| | | "appointmentId": 385, |
| | | "content": "notice customer invterview time", |
| | | "createdDate": "2022-01-11T09:33:57.754Z", |
| | | "interviewDate": null |
| | | }, |
| | | { |
| | | "id": 6, |
| | | "phone": "0912345678", |
| | | "email": "pollex@gmail.com", |
| | | "appointmentId": 385, |
| | | "content": "notice customer invterview time", |
| | | "createdDate": "2022-01-19T10:38:42.187Z", |
| | | "interviewDate": "2022-11-01T08:00:00.000+00:00" |
| | | } |
| | | ], |
| | | "appointmentClosedInfo": { |
| | | "id": 9, |
| | | "policyholderIdentityId": "A123456789", |
| | | "planCode": "ATMdd", |
| | | "policyEntryDate": "2022-01-12T00:00:00.000+00:00", |
| | | "remark": "test remark", |
| | | "closedReason": "other2", |
| | | "closedOtherReason": "å¿æ
ä¸å¥½ä¸æ³è²·2", |
| | | "appointmentId": 385 |
| | | } |
| | | } |
| | |
| | | http post : |
| | | æ°å¢çµæ¡æç´°: |
| | | æ°å¢çµæ¡æç´°, æ´æ°çµæ¡æç´°: |
| | | http://localhost:8080/api/appointment/close |
| | | |
| | | æ´æ°çµæ¡æç´°: |
| | | http://localhost:8080/api/appointment/close/info/edit |
| | | |
| | | |
| | | request body : |
| | |
| | | package com.pollex.pam.appointment.process; |
| | | |
| | | import java.time.Instant; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | |
| | | |
| | | import com.pollex.pam.domain.Appointment; |
| | | import com.pollex.pam.domain.AppointmentClosedInfo; |
| | | import com.pollex.pam.enums.ContactStatusEnum; |
| | | import com.pollex.pam.repository.AppointmentClosedInfoRepository; |
| | | import com.pollex.pam.repository.AppointmentRepository; |
| | | import com.pollex.pam.service.AppointmentClosedInfoService; |
| | |
| | | |
| | | public void process(AbstractAppointmentProcessDTO dto) { |
| | | |
| | | // AbstractAppointmentProcessDTO appointmentProcessDTO = dto; |
| | | processList.stream().forEach(process ->{ |
| | | if(process.getProcessType() == dto.getContactStatus()) { |
| | | process.createProcess(dto); |
| | | Optional<AppointmentClosedInfo> closedInfoOP = appointmentClosedInfoRepository.findByAppointmentId(dto.getAppointmentId()); |
| | | if(closedInfoOP.isPresent()) { |
| | | process.editClosedInfo(dto, closedInfoOP.get()); |
| | | }else { |
| | | process.create(dto); |
| | | } |
| | | } |
| | | }); |
| | | Appointment appointment = appointmentService.findById(dto.getAppointmentId()); |
| | | appointment.setCommunicateStatus(dto.getContactStatus()); |
| | | appointmentRepository.save(appointment); |
| | | |
| | | changeAppointmentCommunicateStatus(dto.getAppointmentId(), dto.getContactStatus()); |
| | | } |
| | | |
| | | public void editClosedInfo(AbstractAppointmentProcessDTO dto) { |
| | | processList.stream().forEach(process ->{ |
| | | if(process.getProcessType() == dto.getContactStatus()) { |
| | | process.editClosedInfo(dto); |
| | | } |
| | | }); |
| | | Appointment appointment = appointmentService.findById(dto.getAppointmentId()); |
| | | appointment.setCommunicateStatus(dto.getContactStatus()); |
| | | private void changeAppointmentCommunicateStatus(Long appointmentId, ContactStatusEnum contactStatus) { |
| | | Appointment appointment = appointmentService.findById(appointmentId); |
| | | appointment.setCommunicateStatus(contactStatus); |
| | | appointmentRepository.save(appointment); |
| | | } |
| | | |
| | |
| | | |
| | | public interface AppointmentProcessInterface { |
| | | |
| | | void createProcess(AbstractAppointmentProcessDTO dto); |
| | | AppointmentClosedInfo editClosedInfo(AbstractAppointmentProcessDTO dto); |
| | | AppointmentClosedInfo create(AbstractAppointmentProcessDTO dto); |
| | | AppointmentClosedInfo editClosedInfo(AbstractAppointmentProcessDTO dto |
| | | , AppointmentClosedInfo closedInfo); |
| | | ContactStatusEnum getProcessType(); |
| | | |
| | | } |
| | |
| | | package com.pollex.pam.appointment.process; |
| | | |
| | | import java.util.Optional; |
| | | |
| | | import org.springframework.beans.BeanUtils; |
| | | 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.AppointmentClosedInfo; |
| | |
| | | import com.pollex.pam.repository.AppointmentClosedInfoRepository; |
| | | import com.pollex.pam.service.AppointmentClosedInfoService; |
| | | import com.pollex.pam.service.AppointmentService; |
| | | import com.pollex.pam.service.SatisfactionService; |
| | | import com.pollex.pam.service.dto.AbstractAppointmentProcessDTO; |
| | | import com.pollex.pam.service.dto.ClosedProcessDTO; |
| | | import com.pollex.pam.service.dto.DoneProcessDTO; |
| | | import com.pollex.pam.web.rest.errors.AppointmentClosedInfoNotFoundException; |
| | | |
| | | @Service |
| | | @Transactional |
| | | public class ClosedProcess implements AppointmentProcessInterface{ |
| | | |
| | | @Autowired |
| | |
| | | @Autowired |
| | | AppointmentClosedInfoService appointmentClosedInfoService; |
| | | |
| | | @Autowired |
| | | SatisfactionService satisfactionService; |
| | | |
| | | @Override |
| | | public void createProcess(AbstractAppointmentProcessDTO processDTO) { |
| | | checkClosedInfo(processDTO.getAppointmentId()); |
| | | public AppointmentClosedInfo create(AbstractAppointmentProcessDTO processDTO) { |
| | | ClosedProcessDTO closeProcess = toClosedProcessDTO(processDTO); |
| | | AppointmentClosedInfo closedInfo = new AppointmentClosedInfo(); |
| | | BeanUtils.copyProperties(closeProcess, closedInfo); |
| | | appointmentClosedInfoRepository.save(closedInfo); |
| | | |
| | | Appointment appointment = appointmentService.findById(processDTO.getAppointmentId()); |
| | | satisfactionService.createSatisfaction(appointment); |
| | | return appointmentClosedInfoRepository.save(closedInfo); |
| | | } |
| | | |
| | | private ClosedProcessDTO toClosedProcessDTO(AbstractAppointmentProcessDTO processDTO) { |
| | |
| | | return closeProcess; |
| | | } |
| | | |
| | | private void checkClosedInfo(Long appointmentId) { |
| | | Optional<AppointmentClosedInfo> closedInfo = appointmentClosedInfoRepository.findByAppointmentId(appointmentId); |
| | | if(closedInfo.isPresent()) { |
| | | throw new IllegalArgumentException("appointment closed info exist"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public ContactStatusEnum getProcessType() { |
| | | return ContactStatusEnum.CLOSED; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public AppointmentClosedInfo editClosedInfo(AbstractAppointmentProcessDTO abstractDTO) { |
| | | public AppointmentClosedInfo editClosedInfo( |
| | | AbstractAppointmentProcessDTO abstractDTO |
| | | , AppointmentClosedInfo closedInfo) { |
| | | ClosedProcessDTO closeProcess = toClosedProcessDTO(abstractDTO); |
| | | AppointmentClosedInfo closedInfo = appointmentClosedInfoService.findByAppointmentId(abstractDTO.getAppointmentId()); |
| | | |
| | | BeanUtils.copyProperties(closeProcess, closedInfo); |
| | | return appointmentClosedInfoRepository.save(closedInfo); |
| | | } |
| | |
| | | package com.pollex.pam.appointment.process; |
| | | |
| | | import java.util.Optional; |
| | | |
| | | import org.springframework.beans.BeanUtils; |
| | | 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.AppointmentClosedInfo; |
| | | import com.pollex.pam.enums.ContactStatusEnum; |
| | | import com.pollex.pam.repository.AppointmentClosedInfoRepository; |
| | | import com.pollex.pam.service.AppointmentClosedInfoService; |
| | | import com.pollex.pam.service.AppointmentService; |
| | | import com.pollex.pam.service.SatisfactionService; |
| | | import com.pollex.pam.service.dto.AbstractAppointmentProcessDTO; |
| | | import com.pollex.pam.service.dto.ClosedProcessDTO; |
| | | import com.pollex.pam.service.dto.DoneProcessDTO; |
| | | import com.pollex.pam.web.rest.errors.AppointmentClosedInfoNotFoundException; |
| | | |
| | | @Service |
| | | @Transactional |
| | | public class DoneProcess implements AppointmentProcessInterface{ |
| | | |
| | | @Autowired |
| | |
| | | @Autowired |
| | | AppointmentClosedInfoService appointmentClosedInfoService; |
| | | |
| | | @Autowired |
| | | SatisfactionService satisfactionService; |
| | | |
| | | @Autowired |
| | | AppointmentService appointmentService; |
| | | |
| | | @Override |
| | | public void createProcess(AbstractAppointmentProcessDTO processDTO) { |
| | | checkClosedInfo(processDTO.getAppointmentId()); |
| | | public AppointmentClosedInfo create(AbstractAppointmentProcessDTO processDTO) { |
| | | DoneProcessDTO doneProcess = toDoneProcessDTO(processDTO); |
| | | AppointmentClosedInfo closedInfo = new AppointmentClosedInfo(); |
| | | BeanUtils.copyProperties(doneProcess, closedInfo); |
| | | appointmentClosedInfoRepository.save(closedInfo); |
| | | Appointment appointment = appointmentService.findById(processDTO.getAppointmentId()); |
| | | satisfactionService.createSatisfaction(appointment); |
| | | return appointmentClosedInfoRepository.save(closedInfo); |
| | | } |
| | | |
| | | @Override |
| | |
| | | return ContactStatusEnum.DONE; |
| | | } |
| | | |
| | | private void checkClosedInfo(Long appointmentId) { |
| | | Optional<AppointmentClosedInfo> closedInfo = appointmentClosedInfoRepository.findByAppointmentId(appointmentId); |
| | | if(closedInfo.isPresent()) { |
| | | throw new IllegalArgumentException("appointment closed info exist"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public AppointmentClosedInfo editClosedInfo(AbstractAppointmentProcessDTO abstractDTO) { |
| | | public AppointmentClosedInfo editClosedInfo( |
| | | AbstractAppointmentProcessDTO abstractDTO |
| | | , AppointmentClosedInfo closedInfo) { |
| | | DoneProcessDTO doneProcess = toDoneProcessDTO(abstractDTO); |
| | | AppointmentClosedInfo closedInfo = appointmentClosedInfoService.findByAppointmentId(abstractDTO.getAppointmentId()); |
| | | BeanUtils.copyProperties(doneProcess, closedInfo); |
| | | return appointmentClosedInfoRepository.save(closedInfo); |
| | | } |
| | | |
| | | private DoneProcessDTO toDoneProcessDTO(AbstractAppointmentProcessDTO abstractDTO) { |
| | | |
| | | DoneProcessDTO doneProcess = (DoneProcessDTO)abstractDTO; |
| | | BeanUtils.copyProperties(abstractDTO, doneProcess); |
| | | return doneProcess; |
| | |
| | | import javax.persistence.Table; |
| | | |
| | | import org.springframework.data.annotation.CreatedDate; |
| | | import org.springframework.data.annotation.LastModifiedDate; |
| | | import org.springframework.data.jpa.domain.support.AuditingEntityListener; |
| | | |
| | | import com.pollex.pam.enums.AppointmentStatusEnum; |
| | |
| | | private Instant appointmentDate = Instant.now(); |
| | | |
| | | @Column(name = "last_modified_date") |
| | | @LastModifiedDate |
| | | private Instant lastModifiedDate = Instant.now(); |
| | | |
| | | @Column(name = "agent_no") |
| | |
| | | Optional<Satisfaction> findOneByAppointmentId(Long appointmentId); |
| | | |
| | | @Query(value = "SELECT avg(score) FROM satisfaction where agent_no=:agent_no" |
| | | + " and score is not null" |
| | | , nativeQuery = true) |
| | | Float getAgentScoreAvg(@Param("agent_no") String agentNo); |
| | | } |
| | |
| | | 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.service.dto.AppointmentUpdateDTO; |
| | | import com.pollex.pam.service.dto.ClosedProcessDTO; |
| | | import com.pollex.pam.service.dto.DoneProcessDTO; |
| | | import com.pollex.pam.service.dto.InterviewRecordDTO; |
| | | 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; |
| | |
| | | import com.pollex.pam.repository.AppointmentCustomerViewRepository; |
| | | import com.pollex.pam.repository.AppointmentRepository; |
| | | import com.pollex.pam.security.SecurityUtils; |
| | | import com.pollex.pam.service.dto.AppointmentCloseDTO; |
| | | import com.pollex.pam.service.dto.AppointmentCreateDTO; |
| | | import com.pollex.pam.service.dto.AppointmentCustomerViewDTO; |
| | | import com.pollex.pam.service.mapper.AppointmentCustomerViewMapper; |
| | |
| | | |
| | | @Autowired |
| | | InterviewRecordService interviewRecordService; |
| | | |
| | | @Autowired |
| | | AppointmentProcess abstractAppointmentProcess; |
| | | |
| | | public Appointment customerCreateAppointment(AppointmentCreateDTO appointmentCreateDTO) { |
| | | Appointment appointment = appointmentDTOMapper.toAppointment(appointmentCreateDTO); |
| | |
| | | .map(appointmentCustomerView -> { |
| | | AppointmentCustomerViewDTO dto = appointmentCustomerViewMapper.toAppointmentCustomerViewDTO(appointmentCustomerView); |
| | | setSatisfactionScore(dto, appointmentCustomerView.getId()); |
| | | |
| | | return dto; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.pollex.pam.domain.AppointmentCustomerView; |
| | | import com.pollex.pam.domain.Consultant; |
| | | import com.pollex.pam.domain.CustomerFavoriteConsultant; |
| | | import com.pollex.pam.domain.Satisfaction; |
| | | import com.pollex.pam.enums.ContactStatusEnum; |
| | | import com.pollex.pam.enums.LoginResult; |
| | | import com.pollex.pam.repository.ConsultantRepository; |
| | | import com.pollex.pam.repository.CustomerFavoriteConsultantRepository; |
| | | import com.pollex.pam.repository.SatisfactionRepository; |
| | | import com.pollex.pam.security.SecurityUtils; |
| | | import com.pollex.pam.service.dto.*; |
| | | import com.pollex.pam.service.mapper.AppointmentCustomerViewMapper; |
| | |
| | | import java.io.FileNotFoundException; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.math.BigDecimal; |
| | | import java.time.Instant; |
| | | import java.util.Comparator; |
| | | import java.util.List; |
| | |
| | | |
| | | @Autowired |
| | | ConsultantService consultantService; |
| | | |
| | | @Autowired |
| | | SatisfactionRepository satisfactionRepository; |
| | | |
| | | public List<CustomerFavoriteConsultantDTO> getMyConsultantList() { |
| | | Long customerId = SecurityUtils.getCustomerDBId(); |
| | |
| | | public String getSendSatisfactionToClientUrl(Long appointmentId) { |
| | | return applicationProperties.getFrontEndDomain() + "/?appointmentId=" + appointmentId; |
| | | } |
| | | |
| | | public void setConsultantAvgScore(Satisfaction satisfaction) { |
| | | float avgScore = getAgentAvgScore(satisfaction.getAgentNo()); |
| | | Consultant consultant = consultantRepository.findOneByAgentNo(satisfaction.getAgentNo()) |
| | | .get(); |
| | | consultant.setAvgScore(avgScore); |
| | | consultantRepository.save(consultant); |
| | | } |
| | | |
| | | public float getAgentAvgScore(String agentNo) { |
| | | Float avgScore = satisfactionRepository.getAgentScoreAvg(agentNo); |
| | | if(avgScore==null)return 0; |
| | | BigDecimal bigDecimal = new BigDecimal(avgScore); |
| | | return avgScore = bigDecimal.setScale(1,BigDecimal.ROUND_HALF_UP).floatValue(); |
| | | } |
| | | } |
| | |
| | | package com.pollex.pam.service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import com.pollex.pam.domain.Appointment; |
| | | import com.pollex.pam.domain.Consultant; |
| | | import com.pollex.pam.domain.Satisfaction; |
| | | import com.pollex.pam.enums.SatisfactionStatusEnum; |
| | | import com.pollex.pam.repository.ConsultantRepository; |
| | | import com.pollex.pam.repository.CustomerRepository; |
| | | import com.pollex.pam.repository.SatisfactionRepository; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerCreateDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerScoreDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionDTO; |
| | | import com.pollex.pam.service.mapper.AppointmentMapper; |
| | | import com.pollex.pam.service.mapper.SatisfactionDTOMapper; |
| | | import com.pollex.pam.service.mapper.SatisfactionMapper; |
| | | import com.pollex.pam.web.rest.errors.SatisfactionAlreadyExistException; |
| | | import com.pollex.pam.web.rest.errors.SatisfactionNotFoundException; |
| | | |
| | | @Service |
| | | @Transactional |
| | |
| | | |
| | | @Autowired |
| | | ConsultantRepository consultantRepository; |
| | | |
| | | @Autowired |
| | | ConsultantService consultantService; |
| | | |
| | | public Satisfaction createSatisfaction(Satisfaction satisfaction) { |
| | | public Satisfaction save(Satisfaction satisfaction) { |
| | | satisfaction = satisfactionRepository.save(satisfaction); |
| | | setConsultantAvgScore(satisfaction); |
| | | consultantService.setConsultantAvgScore(satisfaction); |
| | | return satisfaction; |
| | | } |
| | | |
| | | |
| | | |
| | | private void setConsultantAvgScore(Satisfaction satisfaction) { |
| | | float avgScore = getAgentAvgScore(satisfaction); |
| | | Consultant consultant = consultantRepository.findOneByAgentNo(satisfaction.getAgentNo()) |
| | | .get(); |
| | | consultant.setAvgScore(avgScore); |
| | | consultantRepository.save(consultant); |
| | | } |
| | | |
| | | |
| | | |
| | | private float getAgentAvgScore(Satisfaction satisfaction) { |
| | | Float avgScore = satisfactionRepository.getAgentScoreAvg(satisfaction.getAgentNo()); |
| | | BigDecimal bigDecimal = new BigDecimal(avgScore); |
| | | return avgScore = bigDecimal.setScale(1,BigDecimal.ROUND_HALF_UP).floatValue(); |
| | | } |
| | | |
| | | |
| | | public Satisfaction scorefaction(SatisfactionCustomerScoreDTO scoreDTO) { |
| | | Optional<Satisfaction> satisfactionOP = getByAppointmentId(scoreDTO.getAppointmentId()); |
| | | Satisfaction satisfaction = satisfactionOP.orElseThrow(SatisfactionNotFoundException::new); |
| | | satisfaction.setScore(scoreDTO.getScore()); |
| | | satisfaction.setStatus(SatisfactionStatusEnum.FILLED); |
| | | return save(satisfaction); |
| | | } |
| | | |
| | | |
| | | public Satisfaction createSatisfaction(Appointment appointment) { |
| | | boolean isexist = getByAppointmentId(appointment.getId()).isPresent(); |
| | | if(isexist) { |
| | | throw new SatisfactionAlreadyExistException(); |
| | | } |
| | | Satisfaction satisfaction = appointmentMapper.toSatisfaction(appointment); |
| | | return createSatisfaction(satisfaction); |
| | | return save(satisfaction); |
| | | } |
| | | |
| | | public Satisfaction createSatisfaction(SatisfactionCustomerCreateDTO createDTO) { |
| | | // todo : å°æªæ¨è¨å·²è¯çµ¡çé ç´å®ä¸è©²å¯ä»¥æ°å¢æ»¿æåº¦è©å |
| | | // todo : éèªå·±çé ç´å®ä¸è©²å¯ä»¥é²è¡è©å |
| | | Satisfaction satisfaction = satisfactionDTOMapper.toSatisfaction(createDTO); |
| | | return createSatisfaction(satisfaction); |
| | | } |
| | | // |
| | | // public Satisfaction createSatisfaction(SatisfactionCustomerScoreDTO createDTO) { |
| | | // Satisfaction satisfaction = satisfactionDTOMapper.toSatisfaction(createDTO); |
| | | // return save(satisfaction); |
| | | // } |
| | | |
| | | public List<SatisfactionDTO> getByAgentNo(String agentNo) { |
| | | List<Satisfaction> satisfactionList = satisfactionRepository.findByAgentNo(agentNo); |
| | |
| | | import java.time.Instant; |
| | | import java.util.List; |
| | | |
| | | import com.pollex.pam.domain.AppointmentClosedInfo; |
| | | import com.pollex.pam.domain.AppointmentMemo; |
| | | import com.pollex.pam.domain.AppointmentNoticeLog; |
| | | import com.pollex.pam.domain.InterviewRecord; |
| | |
| | | private List<AppointmentMemo> appointmentMemoList; |
| | | private List<InterviewRecordDTO> interviewRecordDTOs; |
| | | private List<AppointmentNoticeLog> appointmentNoticeLogs; |
| | | private AppointmentClosedInfo appointmentClosedInfo; |
| | | |
| | | public Long getId() { |
| | | return id; |
| | |
| | | public void setAppointmentNoticeLogs(List<AppointmentNoticeLog> appointmentNoticeLogs) { |
| | | this.appointmentNoticeLogs = appointmentNoticeLogs; |
| | | } |
| | | public AppointmentClosedInfo getAppointmentClosedInfo() { |
| | | return appointmentClosedInfo; |
| | | } |
| | | public void setAppointmentClosedInfo(AppointmentClosedInfo appointmentClosedInfo) { |
| | | this.appointmentClosedInfo = appointmentClosedInfo; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
File was renamed from pamapi/src/main/java/com/pollex/pam/service/dto/SatisfactionCustomerCreateDTO.java |
| | |
| | | package com.pollex.pam.service.dto; |
| | | |
| | | public class SatisfactionCustomerCreateDTO { |
| | | public class SatisfactionCustomerScoreDTO { |
| | | |
| | | private Long appointmentId; |
| | | private Float score; |
| | |
| | | import static java.util.stream.Collectors.toList; |
| | | |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import com.pollex.pam.domain.AppointmentClosedInfo; |
| | | import com.pollex.pam.domain.AppointmentCustomerView; |
| | | import com.pollex.pam.domain.AppointmentNoticeLog; |
| | | import com.pollex.pam.repository.AppointmentClosedInfoRepository; |
| | | import com.pollex.pam.service.AppointmentClosedInfoService; |
| | | import com.pollex.pam.service.AppointmentNoticeLogService; |
| | | import com.pollex.pam.service.AppointmentService; |
| | | import com.pollex.pam.service.dto.AppointmentCustomerViewDTO; |
| | |
| | | @Autowired |
| | | AppointmentNoticeLogService appointmentNoticeLogService; |
| | | |
| | | @Autowired |
| | | AppointmentClosedInfoRepository appointmentClosedInfoRepository; |
| | | |
| | | @Transactional |
| | | public AppointmentCustomerViewDTO toAppointmentCustomerViewDTO(AppointmentCustomerView source) { |
| | | AppointmentCustomerViewDTO target = new AppointmentCustomerViewDTO(); |
| | |
| | | appointmentService.setInterviewRecordDTO(target); |
| | | List<AppointmentNoticeLog> noticeLogs = appointmentNoticeLogService.findByAppointmentId(source.getId()); |
| | | target.setAppointmentNoticeLogs(noticeLogs); |
| | | Optional<AppointmentClosedInfo> appointmentClosedInfoOP = appointmentClosedInfoRepository |
| | | .findByAppointmentId(source.getId()); |
| | | if(appointmentClosedInfoOP.isPresent()) { |
| | | target.setAppointmentClosedInfo(appointmentClosedInfoOP.get()); |
| | | } |
| | | |
| | | return target; |
| | | } |
| | | |
| | |
| | | import com.pollex.pam.enums.SatisfactionStatusEnum; |
| | | import com.pollex.pam.repository.AppointmentRepository; |
| | | import com.pollex.pam.service.dto.AppointmentDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerCreateDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerScoreDTO; |
| | | |
| | | @Service |
| | | public class AppointmentMapper { |
| | |
| | | target.setAppointmentId(appointment.getId()); |
| | | target.setAgentNo(appointment.getAgentNo()); |
| | | target.setCustomerId(appointment.getCustomerId()); |
| | | target.setStatus(SatisfactionStatusEnum.UNFILLED); |
| | | return target; |
| | | } |
| | | |
| | |
| | | package com.pollex.pam.service.mapper; |
| | | |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import com.pollex.pam.domain.AppointmentNoticeLog; |
| | |
| | | |
| | | public AppointmentNoticeLog toAppointmentNoticeLog(AppointmentNoticeSendDTO source) { |
| | | AppointmentNoticeLog target = new AppointmentNoticeLog(); |
| | | target.setAppointmentId(source.getAppointmentId()); |
| | | BeanUtils.copyProperties(source, target); |
| | | // target.setAppointmentId(source.getAppointmentId()); |
| | | target.setContent(source.getMessage()); |
| | | target.setEmail(source.getEmail()); |
| | | target.setPhone(source.getPhone()); |
| | | // target.setEmail(source.getEmail()); |
| | | // target.setPhone(source.getPhone()); |
| | | return target; |
| | | } |
| | | } |
| | |
| | | |
| | | import com.pollex.pam.domain.Satisfaction; |
| | | import com.pollex.pam.enums.SatisfactionStatusEnum; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerCreateDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerScoreDTO; |
| | | |
| | | @Service |
| | | public class SatisfactionDTOMapper { |
| | |
| | | @Autowired |
| | | AppointmentMapper appointmentMapper; |
| | | |
| | | public Satisfaction toSatisfaction(SatisfactionCustomerCreateDTO source) { |
| | | public Satisfaction toSatisfaction(SatisfactionCustomerScoreDTO source) { |
| | | Satisfaction satisfaction = appointmentMapper.toSatisfaction(source.getAppointmentId()); |
| | | satisfaction.setScore(source.getScore()); |
| | | if(satisfaction.getScore()!=null) { |
| | |
| | | |
| | | @PostMapping("/close") |
| | | public ResponseEntity<Void> closeAppointment(@RequestBody 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); |
| | | }else { |
| | | return ResponseEntity.notFound().build(); |
| | | } |
| | | |
| | | appointmentService.closeAppointment(closeDTO); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | | @PostMapping("/close/info/edit") |
| | | public ResponseEntity<Void> editAppointmentClosedInfo(@RequestBody AppointmentCloseDTO closeDTO) { |
| | | |
| | | if(closeDTO.getContactStatus() == ContactStatusEnum.DONE) { |
| | | DoneProcessDTO dto = new DoneProcessDTO(); |
| | | BeanUtils.copyProperties(closeDTO, dto); |
| | | abstractAppointmentProcess.editClosedInfo(dto); |
| | | }else if(closeDTO.getContactStatus() == ContactStatusEnum.CLOSED){ |
| | | ClosedProcessDTO dto = new ClosedProcessDTO(); |
| | | BeanUtils.copyProperties(closeDTO, dto); |
| | | abstractAppointmentProcess.editClosedInfo(dto); |
| | | }else { |
| | | return ResponseEntity.notFound().build(); |
| | | } |
| | | |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | // @PostMapping("/close/info/edit") |
| | | // public ResponseEntity<Void> editAppointmentClosedInfo(@RequestBody AppointmentCloseDTO closeDTO) { |
| | | // |
| | | // if(closeDTO.getContactStatus() == ContactStatusEnum.DONE) { |
| | | // DoneProcessDTO dto = new DoneProcessDTO(); |
| | | // BeanUtils.copyProperties(closeDTO, dto); |
| | | // abstractAppointmentProcess.editClosedInfo(dto); |
| | | // }else if(closeDTO.getContactStatus() == ContactStatusEnum.CLOSED){ |
| | | // ClosedProcessDTO dto = new ClosedProcessDTO(); |
| | | // BeanUtils.copyProperties(closeDTO, dto); |
| | | // abstractAppointmentProcess.editClosedInfo(dto); |
| | | // }else { |
| | | // return ResponseEntity.notFound().build(); |
| | | // } |
| | | // |
| | | // return ResponseEntity.noContent().build(); |
| | | // } |
| | | } |
| | |
| | | import com.pollex.pam.domain.Satisfaction; |
| | | import com.pollex.pam.security.SecurityUtils; |
| | | import com.pollex.pam.service.SatisfactionService; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerCreateDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionCustomerScoreDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionDTO; |
| | | import com.pollex.pam.service.dto.SatisfactionUpdateDTO; |
| | | |
| | |
| | | @Autowired |
| | | SatisfactionService satisfactionService; |
| | | |
| | | @PostMapping("/create") |
| | | public Satisfaction createSatisfaction(@RequestBody SatisfactionCustomerCreateDTO createDTO) { |
| | | return satisfactionService.createSatisfaction(createDTO); |
| | | @PostMapping("/score") |
| | | public Satisfaction scorefaction(@RequestBody SatisfactionCustomerScoreDTO scoreDTO) { |
| | | return satisfactionService.scorefaction(scoreDTO); |
| | | } |
| | | |
| | | @GetMapping("/getMySatisfaction") |
¤ñ¹ï·sÀÉ®× |
| | |
| | | package com.pollex.pam.web.rest.errors; |
| | | |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.web.bind.annotation.ResponseStatus; |
| | | |
| | | @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR, reason = "Satisfaction already exist") |
| | | public class SatisfactionAlreadyExistException extends RuntimeException{ |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = 1L; |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | package com.pollex.pam.web.rest.errors; |
| | | |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.web.bind.annotation.ResponseStatus; |
| | | |
| | | @ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Satisfaction not found") |
| | | public class SatisfactionNotFoundException extends RuntimeException{ |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = 1L; |
| | | } |