package com.pollex.pam.service;
|
|
import com.pollex.pam.config.ApplicationProperties;
|
import com.pollex.pam.domain.Appointment;
|
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 com.pollex.pam.service.mapper.ConsultantDTOMapper;
|
import com.pollex.pam.service.mapper.ConsultantMapper;
|
import com.pollex.pam.service.util.FileUtil;
|
import com.pollex.pam.web.rest.errors.ConsultantNotFoundException;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
import org.thymeleaf.context.Context;
|
import org.thymeleaf.spring5.SpringTemplateEngine;
|
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.FileNotFoundException;
|
import java.io.InputStream;
|
import java.math.BigDecimal;
|
import java.time.Instant;
|
import java.util.Comparator;
|
import java.util.List;
|
import java.util.Objects;
|
import java.util.Optional;
|
import java.util.stream.Collectors;
|
|
import static com.pollex.pam.consts.SeniorityQueryConst.*;
|
import static com.pollex.pam.enums.ContactStatusEnum.*;
|
|
@Service
|
@Transactional
|
public class ConsultantService {
|
|
private static final Logger log = LoggerFactory.getLogger(ConsultantService.class);
|
|
@Autowired
|
ConsultantRepository consultantRepository;
|
|
@Autowired
|
CustomerFavoriteConsultantRepository customerFavoriteConsultantRepository;
|
|
@Autowired
|
ConsultantMapper consultantMapper;
|
|
@Autowired
|
AppointmentService appointmentService;
|
|
@Autowired
|
LoginRecordService loginRecordService;
|
|
@Autowired
|
AppointmentCustomerViewMapper appointmentCustomerViewMapper;
|
|
@Autowired
|
SatisfactionService satisfactionService;
|
|
@Autowired
|
ConsultantDTOMapper consultantDTOMapper;
|
|
@Autowired
|
ApplicationProperties applicationProperty;
|
|
@Autowired
|
SendMsgService sendMsgService;
|
|
@Autowired
|
SpringTemplateEngine springTemplateEngine;
|
|
@Autowired
|
ApplicationProperties applicationProperties;
|
|
@Autowired
|
ConsultantService consultantService;
|
|
@Autowired
|
SatisfactionRepository satisfactionRepository;
|
|
@Autowired
|
PersonalNotificationService personalNotificationService;
|
|
public List<CustomerFavoriteConsultantDTO> getMyConsultantList() {
|
Long customerId = SecurityUtils.getCustomerDBId();
|
|
return customerFavoriteConsultantRepository.findAllByCustomerId(customerId)
|
.stream()
|
.map(relation -> {
|
Consultant consultant = relation.getConsultant();
|
CustomerFavoriteConsultantDTO dto = consultantMapper.toCustomerFavoriteConsultantDto(consultant);
|
dto.setCreateTime(relation.getCreatedDate());
|
dto.setUpdateTime(relation.getCreatedDate());
|
dto.setCustomerViewTime(relation.getViewTime());
|
|
setInfoByAvailableAppointment(
|
dto,
|
appointmentService.findAvailableByAgentNoAndCustomerId(consultant.getAgentNo(), customerId)
|
);
|
|
setFavoriteConsultantUpdatedTime(relation, dto);
|
|
return dto;
|
|
}).collect(Collectors.toList());
|
}
|
|
public void setFavoriteConsultantUpdatedTime(CustomerFavoriteConsultant relation,
|
CustomerFavoriteConsultantDTO dto) {
|
Consultant consultant = relation.getConsultant();
|
appointmentService.findLatestAppointmentByAgentNoAndCustomerId(consultant.getAgentNo(), relation.getCustomerId())
|
.ifPresent(latestAppointment -> {
|
dto.setUpdateTime(latestAppointment.getLastModifiedDate());
|
});
|
|
if(dto.getUpdateTime().isBefore(relation.getCreatedDate())) {
|
dto.setUpdateTime(relation.getCreatedDate());
|
}
|
}
|
|
private void setInfoByAvailableAppointment(CustomerFavoriteConsultantDTO customerFavoriteConsultantDTO, List<AppointmentCustomerView> appointmentList) {
|
List<AppointmentCustomerView> appointments = appointmentList.stream()
|
.sorted(Comparator.comparing(AppointmentCustomerView::getAppointmentDate).reversed())
|
.collect(Collectors.toList());
|
|
List<AppointmentCustomerViewDTO> appointmentCustomerViewDTOS = appointmentCustomerViewMapper.toAppointmentCustomerViewDTO(appointments);
|
customerFavoriteConsultantDTO.setAppointments(appointmentCustomerViewDTOS);
|
|
if (!appointments.isEmpty()) {
|
AppointmentCustomerView latestAvailableAppointment = appointments.get(0);
|
ContactStatusEnum latestStatus = latestAvailableAppointment.getCommunicateStatus();
|
if(latestStatus != ContactStatusEnum.DONE && latestStatus != ContactStatusEnum.CLOSED)
|
customerFavoriteConsultantDTO.setContactStatus(latestStatus);
|
else
|
customerFavoriteConsultantDTO.setContactStatus(PICKED);
|
}else {
|
customerFavoriteConsultantDTO.setContactStatus(PICKED);
|
}
|
}
|
|
public List<ConsultantDTO> getRecommendConsultantList() {
|
return consultantRepository.findAllByRecommendIsTrue()
|
.stream()
|
.map(consultantMapper::toDto)
|
.collect(Collectors.toList());
|
}
|
|
public List<ConsultantDTO> strictQueryConsultant(StrictQueryConsultantParam param) {
|
return consultantRepository.findAll(ConsultantQuerySpec.getStrictQuerySpec(param))
|
.stream()
|
.map(consultant -> {
|
int suitabilityScore = getStrictQuerySuitabilityScore(param, consultant);
|
|
ConsultantDTO dto = consultantMapper.toDto(consultant);
|
dto.setSuitability(suitabilityScore);
|
|
return dto;
|
})
|
.collect(Collectors.toList());
|
}
|
|
private int getStrictQuerySuitabilityScore(StrictQueryConsultantParam param, Consultant consultant) {
|
Float queryAvgScore = param.getAvgScore();
|
String querySeniority = param.getSeniority();
|
List<String> queryRequirements = param.getRequirements();
|
|
int score = 0;
|
if(isConsultantGreaterThanScore(queryAvgScore, consultant.getAvgScore())) {
|
score += 30;
|
}
|
|
if(isConsultantInSeniority(querySeniority, consultant.getSeniorityYear())) {
|
score += 20;
|
}
|
|
if(isAllRequirementsIncludeConsultant(queryRequirements, consultant.getExpertise())) {
|
score += 50;
|
}
|
|
return score;
|
}
|
|
private boolean isAllRequirementsIncludeConsultant(List<String> queryRequirements, String consultantExpertise) {
|
return queryRequirements
|
.stream()
|
.allMatch(queryRequirement -> consultantExpertise.matches(".*"+queryRequirement+".*"));
|
}
|
|
private boolean isConsultantInSeniority(String querySeniority, Long consultantSeniorityYear) {
|
switch (querySeniority == null ? "" : querySeniority) {
|
case YOUNG:
|
return consultantSeniorityYear < 5;
|
case SENIOR:
|
return consultantSeniorityYear > 5;
|
case UNLIMITED:
|
case "":
|
return true;
|
default:
|
return false;
|
}
|
}
|
|
private boolean isConsultantGreaterThanScore(Float queryAvgScore, Float consultantAvgScore) {
|
return Objects.isNull(queryAvgScore) || queryAvgScore < consultantAvgScore;
|
}
|
|
public List<ConsultantDTO> fastQueryConsultant(FastQueryConsultantParam param) {
|
return consultantRepository.findAll(ConsultantQuerySpec.getFastQuerySpec(param))
|
.stream()
|
.map(consultantMapper::toDto)
|
.collect(Collectors.toList());
|
}
|
|
public ConsultantDetailDTO getConsultantDetail(String agentNo) {
|
Consultant consultant = consultantRepository.findOneByAgentNo(agentNo).orElseThrow(ConsultantNotFoundException::new);
|
ConsultantDetailDTO consultantDetailDTO = consultantMapper.toDetailDto(consultant);
|
|
loginRecordService.findLatestLoginRecord(agentNo, LoginResult.SUCCESS)
|
.ifPresent(loginRecord -> consultantDetailDTO.setLatestLoginTime(loginRecord.getLoginDate()));
|
|
return consultantDetailDTO;
|
}
|
|
@Transactional
|
public void addConsultantToCustomList(AddConsultantParam param) {
|
List<String> agentNoList = param.getAgentNoList();
|
List<Consultant> consultants = consultantRepository.findAllByAgentNoIn(agentNoList);
|
Long userId = SecurityUtils.getCustomerDBId();
|
|
consultants.forEach(consultant -> {
|
boolean isConsultantInList = customerFavoriteConsultantRepository.findOneByCustomerIdAndConsultant(userId, consultant).isPresent();
|
|
if(!isConsultantInList) {
|
CustomerFavoriteConsultant customerFavoriteConsultant = new CustomerFavoriteConsultant();
|
customerFavoriteConsultant.setConsultant(consultant);
|
customerFavoriteConsultant.setCustomerId(userId);
|
|
customerFavoriteConsultantRepository.save(customerFavoriteConsultant);
|
}
|
else {
|
log.info("The consultant is in customer favorite list! customId = {}, consultant AgentNo = {}", userId, consultant.getAgentNo());
|
}
|
});
|
|
}
|
|
public List<AppointmentCustomerViewDTO> getMyAppointment() {
|
String agentNo = SecurityUtils.getAgentNo();
|
return appointmentService.getConsultantAvailableAppointments(agentNo);
|
}
|
|
public void removeConsultantFromCustomList(String agentNo) {
|
Long customId = SecurityUtils.getCustomerDBId();
|
Consultant consultant = consultantRepository.findOneByAgentNo(agentNo).orElseThrow(ConsultantNotFoundException::new);
|
CustomerFavoriteConsultant target = customerFavoriteConsultantRepository.findOneByCustomerIdAndConsultant(customId, consultant).orElse(null);
|
|
if(target != null) {
|
customerFavoriteConsultantRepository.delete(target);
|
}
|
else {
|
log.info("this consultant is not in customer list! agentNo = {}, customId = {}", agentNo, customId);
|
}
|
}
|
|
public void recordAllAppointmentsView() {
|
String agentNo = SecurityUtils.getAgentNo();
|
appointmentService.recordAllAppointmentsView(agentNo);
|
}
|
|
public void recordMyConsultantListView() {
|
Long customerId = SecurityUtils.getCustomerDBId();
|
List<CustomerFavoriteConsultant> notViewRelation = customerFavoriteConsultantRepository
|
.findAllByCustomerId(customerId)
|
.stream()
|
.filter(relation -> Objects.isNull(relation.getViewTime()))
|
.collect(Collectors.toList());
|
|
notViewRelation.forEach(relation -> {
|
relation.setViewTime(Instant.now());
|
});
|
|
customerFavoriteConsultantRepository.saveAll(notViewRelation);
|
}
|
|
public Consultant findByAgentNo(String agentNo) {
|
return consultantRepository.findOneByAgentNo(agentNo).get();
|
}
|
|
public Consultant editConsultant(ConsultantEditDTO editDTO) {
|
Consultant consultant = consultantRepository.findOneByAgentNo(editDTO.getAgentNo())
|
.orElseThrow(ConsultantNotFoundException::new);
|
consultantDTOMapper.copyToConsultant(editDTO, consultant);
|
FileUtil.base64ToFile(editDTO.getPhotoBase64(), editDTO.getPhotoFileName(), applicationProperty.getFileFolderPath());
|
consultantRepository.save(consultant);
|
personalNotificationService.createEditConsultantToConsultant(consultant);
|
return consultant;
|
}
|
|
public InputStream getAvatarImage(String agentNo) {
|
Consultant consultant = consultantRepository.findOneByAgentNo(agentNo)
|
.orElseThrow(ConsultantNotFoundException::new);
|
File file = new File(consultant.getPhotoPath());
|
try {
|
InputStream in = new FileInputStream(file);
|
return in;
|
} catch (FileNotFoundException e) {
|
log.error("agent photo not found , agentNo:"+agentNo,e);
|
return null;
|
}
|
}
|
|
public void sendSatisfactionToClient(Appointment appointment) {
|
String subject = "滿意度填寫通知";
|
|
if(StringUtils.hasText(appointment.getEmail())) {
|
String content = genSendSatisfactionEmailContent(appointment);
|
sendMsgService.sendMsgByEmail(appointment.getEmail(), subject, content, true);
|
|
}if(StringUtils.hasText(appointment.getPhone())) {
|
String content = genSendSatisfactionSMSContent(appointment);
|
sendMsgService.sendMsgBySMS(appointment.getPhone(), content);
|
}
|
|
personalNotificationService.createSendSatisfactionToClientToCustomer(appointment);
|
}
|
|
private String genSendSatisfactionSMSContent(Appointment appointment) {
|
String agentNo = appointment.getAgentNo();
|
Consultant consultant = consultantService.findByAgentNo(agentNo);
|
String contsultantName = consultant.getName();
|
String content = contsultantName+"顧問請您填寫保誠媒合平台的滿意度評比"+getSendSatisfactionToClientUrl(appointment.getId());
|
return content;
|
}
|
|
private String genSendSatisfactionEmailContent(Appointment appointment) {
|
String agentNo = appointment.getAgentNo();
|
Consultant consultant = consultantService.findByAgentNo(agentNo);
|
Context context = new Context();
|
context.setVariable("consultantName", consultant.getName());
|
context.setVariable("appointmentUrl", getSendSatisfactionToClientUrl(appointment.getId()));
|
String content = springTemplateEngine.process("mail/writeSatisfactionNotice", context);
|
return content;
|
}
|
|
public String getSendSatisfactionToClientUrl(Long appointmentId) {
|
return applicationProperties.getFrontEndDomain() + "/?appointmentId=" + appointmentId;
|
}
|
|
public void setConsultantAvgScore(Satisfaction satisfaction) {
|
Optional<Float> avgScore = getAgentAvgScore(satisfaction.getAgentNo());
|
|
if(avgScore.isPresent()) {
|
BigDecimal bigDecimal = BigDecimal.valueOf(avgScore.get());
|
|
Consultant consultant = consultantRepository.findOneByAgentNo(satisfaction.getAgentNo()).get();
|
consultant.setAvgScore(bigDecimal.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue());
|
consultantRepository.save(consultant);
|
}
|
}
|
|
public Optional<Float> getAgentAvgScore(String agentNo) {
|
return satisfactionRepository.getAgentScoreAvg(agentNo);
|
}
|
}
|