ACFollowStrategy.java 13.6 KB
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<FollowTodoListVO> getList(Integer startIndex, Integer pageSize, Long userId) {
        List<FollowRecord> list = list(startIndex, pageSize, userId, getFollowType());
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<FollowTodoListVO> 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.<FollowRecordLog>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(Objects.isNull(followRecord.getLimitTime()) ? followRecord.getDeadline() : followRecord.getLimitTime());
        return vo;
    }

    @Override
    public List<FollowRecordVO> 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.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<SettingVO> 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());
        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.<FollowRecord>lambdaQuery()
                .eq(FollowRecord::getTaskId, taskId)
                .eq(FollowRecord::getOutTime, Boolean.FALSE)
                .eq(FollowRecord::getAddTodo, Boolean.FALSE)
                .isNull(FollowRecord::getFollowTime)
                .ge(FollowRecord::getDeadline, new Date())
        );
        List<FollowRecord> list = Optional.ofNullable(followRecordService.list(Wrappers.<FollowRecord>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> insuranceDTO = queryInsuInfo(customer.getId());
            insuranceDTO.ifPresent(ins -> vo.setInsComName(ins.getTciInsurerName()));
        }
        return vo;
    }
}