package cn.fw.valhalla.service.bus.follow.strategy.impl; import cn.fw.common.exception.BusinessException; import cn.fw.common.util.ValidationUtils; import cn.fw.valhalla.common.utils.DateUtil; import cn.fw.valhalla.common.utils.MobileUtil; import cn.fw.valhalla.common.utils.StringUtils; import cn.fw.valhalla.domain.db.OriginalData; import cn.fw.valhalla.domain.db.customer.AccidentPool; import cn.fw.valhalla.domain.db.customer.Customer; import cn.fw.valhalla.domain.db.follow.FollowRecord; import cn.fw.valhalla.domain.db.follow.FollowRecordLog; import cn.fw.valhalla.domain.db.follow.FollowTask; import cn.fw.valhalla.domain.db.pool.CustomerCluePool; import cn.fw.valhalla.domain.dto.CustomerDetailDto; import cn.fw.valhalla.domain.dto.FollowAttachmentDTO; import cn.fw.valhalla.domain.enums.*; import cn.fw.valhalla.domain.vo.follow.*; import cn.fw.valhalla.domain.vo.setting.SettingVO; import cn.fw.valhalla.rpc.angel.dto.InsuranceDTO; import cn.fw.valhalla.rpc.erp.dto.BackLogItemDTO; import cn.fw.valhalla.rpc.erp.dto.UserInfoDTO; import cn.fw.valhalla.rpc.oop.dto.ShopDTO; import cn.fw.valhalla.service.bus.follow.strategy.AbstractFollowStrategy; import cn.fw.valhalla.service.data.AccidentPoolService; import cn.fw.valhalla.service.event.CancelApproveEvent; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.time.LocalDateTime; import java.util.*; import static cn.fw.common.businessvalidator.Validator.BV; import static cn.fw.valhalla.common.utils.DateUtil.date2LocalDateTime; import static cn.fw.valhalla.common.utils.StringUtils.getStrWithDefault; /** * @author : kurisu * @className : ACFollowStrategy * @description : 事故车策略 * @date: 2020-08-17 10:48 */ @Slf4j @Component public class ACFollowStrategy extends AbstractFollowStrategy { private final AccidentPoolService accidentPoolService; @Autowired public ACFollowStrategy(final AccidentPoolService accidentPoolService) { this.accidentPoolService = accidentPoolService; } @Override public FollowTypeEnum getFollowType() { return FollowTypeEnum.AC; } @Override public List getList(Integer startIndex, Integer pageSize, Long userId) { List list = list(startIndex, pageSize, userId, getFollowType()); if (CollectionUtils.isEmpty(list)) { return new ArrayList<>(); } List voList = new ArrayList<>(); for (FollowRecord followRecord : list) { ACTodoListVO vo = new ACTodoListVO(); vo.setId(followRecord.getId()); vo.setTaskId(followRecord.getTaskId()); vo.setCustomerId(followRecord.getCustomerId()); vo.setDeadline(followRecord.getDeadline()); AccidentPool accidentPool = accidentPoolService.getById(followRecord.getCustomerId()); if (Objects.nonNull(accidentPool)) { vo.setName(accidentPool.getName()); vo.setInsComName(accidentPool.getInsurerName()); vo.setPlateNo(accidentPool.getPlateNo()); } voList.add(vo); } return voList; } @Override public FollowDetailVO getDetail(Long id) { FollowRecord followRecord = followRecordService.getById(id); BV.notNull(followRecord, "跟进记录不存在"); int count = followRecordLogService.count(Wrappers.lambdaQuery() .eq(FollowRecordLog::getRecordId, followRecord.getId()) .eq(FollowRecordLog::getAttType, AttTypeEnum.SMART_PHONE) ); ACDetailVO vo = assemble(followRecord.getCustomerId()); vo.setId(followRecord.getId()); vo.setTaskId(followRecord.getTaskId()); vo.setHadCall(count > 0 || !ValidationUtils.checkMobile(vo.getReportMobile())); vo.setDeadline(followRecord.getDeadline()); return vo; } @Override public List getRecordList(Long taskId) { return super.getRecordList(taskId); } @Override public void completeRecordAndEnd(FollowRecord record) { final Date followTime = DateUtil.localDateTime2Date(LocalDateTime.now()); BackLogItemDTO dto = new BackLogItemDTO(record.getUserId(), getItemCode(record.getType()), String.valueOf(record.getId()), followTime, record.getShopId()); if (Boolean.FALSE.equals(record.getOutTime()) && Objects.isNull(record.getFollowTime())) { record.setFollowTime(followTime); followRecordService.updateById(record); todoRpcService.complete(dto); return; } if (record.getLimitTime().after(followTime)) { todoRpcService.cancel(dto); } } @Override public void uploadAtt(FollowAttachmentDTO dto, Long userId) { FollowRecord record = followRecordService.getById(dto.getRecordId()); if (Objects.isNull(record)) { return; } BV.isTrue(record.getUserId().equals(userId), () -> "无法跟进非本人待办任务"); FollowRecordLog recordLog = new FollowRecordLog(); recordLog.setId(dto.getId()); recordLog.setTaskId(record.getTaskId()); recordLog.setAttachments(dto.getAttachments()); recordLog.setAttType(dto.getAttTypeEnum()); recordLog.setFeedbackType(dto.getFeedbackTypeEnum()); recordLog.setDescribes(dto.getDescribes()); recordLog.setRecordId(dto.getRecordId()); if (Objects.isNull(dto.getId())) { recordLog.setUploadTime(new Date()); } followRecordLogService.save(recordLog); feedbackTask(record.getTaskId(), dto.getFeedbackTypeEnum()); if (Boolean.FALSE.equals(record.getOutTime()) && Objects.isNull(record.getFollowTime())) { record.setFollowTime(DateUtil.localDateTime2Date(LocalDateTime.now())); BackLogItemDTO backLogItemDTO = new BackLogItemDTO(record.getUserId(), getItemCode(record.getType()), String.valueOf(record.getId()), DateUtil.localDateTime2Date(LocalDateTime.now()), record.getShopId()); todoRpcService.complete(backLogItemDTO); followRecordService.updateById(record); } } @Override @Transactional(rollbackFor = Exception.class) public void cancelFollowTask(Long customerId, Date time, Long groupId) { //事故车进站取消的情况暂时不考虑 } @Override public void settingChanged(List setting, Long groupId) { //更改设置不影响事故车跟进 } @Override public boolean origin2task(OriginalData originalData) { finishClue(originalData); return true; } @Override public void updateTask(Long customerId) { //事故车无二次跟进 } @Override @Transactional(rollbackFor = Exception.class) public void overdueProcessing(FollowRecord record) { followRecordService.overdue(record.getId()); } @Override public FollowDetailVO followPoolDetail(FollowTask task) { ACDetailVO vo = assemble(task.getCustomerId()); vo.setTaskId(task.getId()); queryTimes(task.getClueId(), vo); return vo; } @Override @Transactional(rollbackFor = Exception.class) public void closeTask(FollowTask task) throws BusinessException { task.setState(TaskStateEnum.DEFEAT); task.setCloseTime(new Date()); task.setReason(TaskDefeatTypeEnum.C); followTaskService.updateById(task); customerBizService.abandon(task, false); CancelApproveEvent event = new CancelApproveEvent(task.getId(), ApproveTypeEnum.FOLLOW_DEFEAT); eventPublisher.publishEvent(event); } /** * 处理线索 * * @param originalData * @return 完成的线索id */ @Transactional(rollbackFor = Exception.class) public void finishClue(OriginalData originalData) { final String plateNo = originalData.getPlateNo(); if (StringUtils.isEmpty(plateNo)) { return; } CustomerCluePool cluePool = customerCluePoolService.queryByPlateNo(plateNo, originalData.getGroupId(), getFollowType()); if (Objects.isNull(cluePool) || !ClueStatusEnum.ONGOING.equals(cluePool.getClueStatus())) { return; } if (date2LocalDateTime(cluePool.getDeadline()).isAfter(date2LocalDateTime(originalData.getGenerateTime()))) { cluePool.setFinishShopId(cluePool.getOriginalShopId()); cluePool.setFinishShopName(cluePool.getOriginalShopName()); cluePool.setFinishUserId(cluePool.getOriginalUserId()); cluePool.setFinishUserName(cluePool.getOriginalUserName()); cluePool.setCloseTime(originalData.getGenerateTime()); cluePool.setClueStatus(ClueStatusEnum.COMPLETE); customerCluePoolService.updateById(cluePool); completeTask(cluePool, originalData); } } /** * 完成生成的跟进待办 * * @param taskId */ @Override @Transactional(rollbackFor = Exception.class) protected void completeTodo(Long taskId) { followRecordService.remove(Wrappers.lambdaQuery() .eq(FollowRecord::getTaskId, taskId) .eq(FollowRecord::getOutTime, Boolean.FALSE) .eq(FollowRecord::getAddTodo, Boolean.FALSE) .isNull(FollowRecord::getFollowTime) .ge(FollowRecord::getDeadline, new Date()) ); List list = Optional.ofNullable(followRecordService.list(Wrappers.lambdaQuery() .eq(FollowRecord::getTaskId, taskId) .eq(FollowRecord::getType, getFollowType()) .eq(FollowRecord::getAddTodo, Boolean.TRUE) .ge(FollowRecord::getLimitTime, new Date()) )).orElse(new ArrayList<>()); if (CollectionUtils.isEmpty(list)) { return; } for (FollowRecord record : list) { BackLogItemDTO dto = new BackLogItemDTO(record.getUserId(), getItemCode(record.getType()), String.valueOf(record.getId()), record.getPlanTime(), record.getShopId()); todoRpcService.complete(dto); record.setFollowTime(new Date()); record.setOutTime(Boolean.FALSE); } followRecordService.updateBatchById(list); } /** * 处理进行中的跟进任务 * * @param cluePool * @return */ @Transactional(rollbackFor = Exception.class) public void completeTask(CustomerCluePool cluePool, OriginalData originalData) { FollowTask task = followTaskService.queryOngoingTaskByClueId(cluePool.getId()); if (Objects.isNull(task)) { return; } task.setState(TaskStateEnum.COMPLETE); task.setFinishUser(cluePool.getFinishUserId()); task.setFinishUserName(cluePool.getFinishUserName()); task.setFinishShop(cluePool.getFinishShopId()); task.setCloseTime(cluePool.getCloseTime()); UserInfoDTO user = userService.user(originalData.getUserId()); if (Objects.nonNull(user)) { task.setReceptionUserId(originalData.getUserId()); task.setReceptionUserName(user.getUserName()); } ShopDTO shop = oopService.shop(originalData.getShopId()); if (Objects.nonNull(shop)) { task.setReceptionShopId(originalData.getShopId()); task.setReceptionShopName(shop.getShortName()); } task.setCloseTime(cluePool.getCloseTime()); boolean succeed = followTaskService.updateById(task); if (succeed) { completeTodo(task.getId()); CancelApproveEvent event = new CancelApproveEvent(task.getId(), ApproveTypeEnum.FOLLOW_DEFEAT); eventPublisher.publishEvent(event); } } @Override public ACDetailVO assemble(Long customerId) { AccidentPool accidentPool = accidentPoolService.getById(customerId); BV.notNull(accidentPool, "事故车信息不存在"); Customer customer = customerService.queryByPlateNo(accidentPool.getPlateNo(), accidentPool.getGroupId()); ACDetailVO vo = new ACDetailVO(); vo.setAccidentId(customerId); vo.setName(accidentPool.getName()); vo.setMobile(accidentPool.getMobile()); vo.setRegion(MobileUtil.attribution(accidentPool.getMobile())); vo.setRealMobile(accidentPool.getReportMobile()); vo.setReportMobile(accidentPool.getReportMobile()); vo.setAddress(accidentPool.getAddress()); vo.setShopId(accidentPool.getShopId()); vo.setShopName(accidentPool.getShopName()); vo.setSms(accidentPool.getSms()); vo.setPlateNo(accidentPool.getPlateNo()); vo.setCarModel(getStrWithDefault(accidentPool.getBrandName(), "") + " " + getStrWithDefault(accidentPool.getSeriesName(), "")); if (Objects.nonNull(customer)) { CustomerDetailDto customerDetailDto = customerBizService.queryById(customer.getId()); vo.setCustomerId(customer.getId()); vo.setAdviserId(customerDetailDto.getAdviserId()); vo.setAdviserName(customerDetailDto.getAdviserName()); vo.setCusLevel(customerDetailDto.getCusLevel()); vo.setArrivalCount(customerDetailDto.getArrivalCount()); vo.setVin(customerDetailDto.getFrameNo()); Optional insuranceDTO = queryInsuInfo(customer.getId()); insuranceDTO.ifPresent(ins -> vo.setInsComName(ins.getTciInsurerName())); } return vo; } }