PubFollowStrategy.java 10.7 KB
package cn.fw.valhalla.service.bus.follow.strategy.impl;

import cn.fw.shirasawa.sdk.enums.BusinessTypeEnum;
import cn.fw.shirasawa.sdk.enums.DataTypeEnum;
import cn.fw.valhalla.common.utils.DateUtil;
import cn.fw.valhalla.domain.db.OriginalData;
import cn.fw.valhalla.domain.db.follow.ClueTask;
import cn.fw.valhalla.domain.db.follow.FollowClue;
import cn.fw.valhalla.domain.db.pub.PubCluePool;
import cn.fw.valhalla.domain.dto.CustomerDetailDto;
import cn.fw.valhalla.domain.enums.*;
import cn.fw.valhalla.domain.vo.setting.SettingVO;
import cn.fw.valhalla.rpc.oop.OopService;
import cn.fw.valhalla.rpc.oop.dto.ShopDTO;
import cn.fw.valhalla.rpc.shirasawa.ShirasawaRpcService;
import cn.fw.valhalla.rpc.shirasawa.dto.ClueStopDTO;
import cn.fw.valhalla.rpc.shirasawa.dto.FollowInitDTO;
import cn.fw.valhalla.service.bus.cust.CustomerBizService;
import cn.fw.valhalla.service.bus.follow.strategy.FollowStrategy;
import cn.fw.valhalla.service.bus.setting.SettingBizService;
import cn.fw.valhalla.service.data.ClueTaskService;
import cn.fw.valhalla.service.data.PubCluePoolService;
import cn.fw.valhalla.service.data.StammkundePoolService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

import static cn.fw.common.businessvalidator.Validator.BV;
import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID;

/**
 * 公共池线索跟进
 *
 * @author : kurisu
 * @version : 1.0
 * @className : PubFollowStrategy
 * @description : 公共池线索跟进
 * @date : 2023-03-21 16:52
 */
@Slf4j
@Component
public class PubFollowStrategy implements FollowStrategy {
    private final PubCluePoolService pubCluePoolService;
    private final ClueTaskService clueTaskService;
    private final CustomerBizService customerBizService;
    private final ShirasawaRpcService shirasawaRpcService;
    private final OopService oopService;
    private final SettingBizService settingBizService;
    private final StammkundePoolService stammkundePoolService;

    @Autowired
    public PubFollowStrategy(final PubCluePoolService pubCluePoolService,
                             final ClueTaskService clueTaskService,
                             final CustomerBizService customerBizService,
                             final ShirasawaRpcService shirasawaRpcService,
                             final OopService oopService,
                             final SettingBizService settingBizService,
                             final StammkundePoolService stammkundePoolService) {
        this.pubCluePoolService = pubCluePoolService;
        this.clueTaskService = clueTaskService;
        this.customerBizService = customerBizService;
        this.shirasawaRpcService = shirasawaRpcService;
        this.oopService = oopService;
        this.settingBizService = settingBizService;
        this.stammkundePoolService = stammkundePoolService;
    }

    @Override
    public FollowTypeEnum getFollowType() {
        return FollowTypeEnum.PL;
    }

    /**
     * 公共池线索跟进此方法无效
     *
     * @param originalData
     * @return
     */
    @Override
    public boolean origin2task(final OriginalData originalData) {
        return false;
    }

    /**
     * 公共池线索跟进此方法无效
     *
     * @param followClue
     * @return
     */
    @Override
    public void startClue(final FollowClue followClue) {
    }

    @Override
    public void settingChanged(List<SettingVO> setting, Long groupId) {
        // 更改设置不影响公共池线索跟进
    }

    @Override
    public void forceStopClue(final FollowClue clue) {

    }


    public void startClue(final PubCluePool pubClue) {
        ClueTask clueTask = new ClueTask();
        clueTask.setClueId(pubClue.getId());
        clueTask.setType(getFollowType());
        clueTask.setBeginTime(pubClue.getStartTime().atStartOfDay());
        clueTask.setRedistribution(Boolean.FALSE);
        clueTask.setDeadline(pubClue.getDeadline().atStartOfDay());
        clueTask.setState(TaskStateEnum.ONGOING);
        clueTask.setGroupId(pubClue.getGroupId());
        clueTask.setFollowShop(pubClue.getShopId());
        clueTask.setFollowUser(pubClue.getAdviserId());
        clueTask.setFollowUserName(pubClue.getAdviserName());
        clueTaskService.save(clueTask);

        final FollowInitDTO followInitDTO = creteFollowInitDTO(pubClue, clueTask);
        pubClue.setNextTime(clueTask.getDeadline().plusDays(1L).toLocalDate());
        shirasawaRpcService.createFollowData(followInitDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void onRoleChangeCloseTask(final ClueTask task) {
        task.setState(TaskStateEnum.DEFEAT);
        task.setCloseTime(LocalDateTime.now());
        task.setReason(TaskDefeatTypeEnum.D);

        boolean rpcSucess = rpcStopTask(task);
        if (!rpcSucess) {
            log.info("跟进系统终止任务失败");
        }
        task.setRpcSuccess(rpcSucess);
        clueTaskService.updateById(task);
    }

    @Override
    public void forceStopTask(final ClueTask task) {

    }

    @Override
    public void onFollowComplete(final ClueTask task, final Long preRecordId, final LocalDate originTime, final boolean overdue) {

    }

    @Override
    public void createNextFollowTodo(final FollowClue clue) {

    }

    @Override
    public void syncEndTask(final ClueTask task) {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeTask(final ClueTask task) {
        final Long clueId = task.getClueId();
        PubCluePool pubCluePool = pubCluePoolService.getById(clueId);
        BV.notNull(pubCluePool, () -> "公共池跟进线索不存在: " + clueId);
        task.setState(TaskStateEnum.DEFEAT);
        task.setCloseTime(task.getDeadline().minusSeconds(1L));
        task.setReason(TaskDefeatTypeEnum.C);
        boolean rpcSucess = rpcStopTask(task);
        if (!rpcSucess) {
            log.info("跟进系统终止任务失败");
        }
        task.setRpcSuccess(rpcSucess);
        clueTaskService.updateById(task);
        pubCluePool.setCloseTime(task.getCloseTime());
        pubCluePool.setState(PublicClueStateEnum.DEFEAT);
        pubCluePool.setDefeatReason(task.getReason());
        pubCluePoolService.updateById(pubCluePool);
        customerBizService.pubTaskEndAbandon(pubCluePool);
    }

    private boolean rpcStopTask(ClueTask clueTask) {
        ClueStopDTO clueStopDTO = new ClueStopDTO();
        clueStopDTO.setType(DataTypeEnum.ofValue(clueTask.getType().getValue()));
        clueStopDTO.setBusinessType(BusinessTypeEnum.AS);
        if (TaskStateEnum.DEFEAT.equals(clueTask.getState())) {
            clueStopDTO.setTermination(Boolean.TRUE);
        }
        clueStopDTO.setDetailId(String.valueOf(clueTask.getId()));
        clueStopDTO.setShopId(clueTask.getFinishShop());
        ShopDTO shop = oopService.shop(clueTask.getFinishShop());
        if (Objects.nonNull(shop)) {
            clueStopDTO.setShopName(shop.getShortName());
        }
        clueStopDTO.setCompleteTime(DateUtil.localDateTime2Date(clueTask.getCloseTime()));
        clueStopDTO.setGroupId(clueTask.getGroupId());
        clueStopDTO.setUserId(clueTask.getFollowUser());
        clueStopDTO.setUserName(clueTask.getFollowUserName());
        return shirasawaRpcService.stopTask(clueStopDTO);
    }

    private FollowInitDTO creteFollowInitDTO(PubCluePool pubClue, ClueTask clueTask) {
        CustomerDetailDto customerDetailDto = customerBizService.queryByFrameNo(pubClue.getVin(), pubClue.getGroupId());
        BV.notNull(customerDetailDto, () -> "档案信息有误");

        final FollowInitDTO followInitDTO = FollowInitDTO.builder()
                .businessType(BusinessTypeEnum.AS)
                .type(DataTypeEnum.ofValue(getFollowType().getValue()))
                .customerId(customerDetailDto.getId())
                .customerName(customerDetailDto.getName())
                .memberId(customerDetailDto.getMemberId())
                .plateNo(customerDetailDto.getPlateNo())
                .frameNo(pubClue.getVin())
                .contacts(customerDetailDto.getMobile())
                .detailId(String.valueOf(clueTask.getId()))
                .generateTime(DateUtil.localDateTime2Date(clueTask.getBeginTime()))
                .deadline(DateUtil.localDateTime2Date(clueTask.getDeadline()))
                .groupId(clueTask.getGroupId())
                .shopId(clueTask.getFollowShop())
                .userId(clueTask.getFollowUser())
                .userName(clueTask.getFollowUserName())
                .bizId(pubClue.getVin())
                .secondary(Boolean.FALSE)
                .build();
        followInitDTO.setShopName(pubClue.getShopName());
        // 除事故车以外,其他待办跟进时长统一配置
        Optional<SettingVO> setting = settingBizService.querySettingByType(FollowTypeEnum.OT, SettingTypeEnum.EFFECTIVE_TIME, clueTask.getGroupId(), COMMON_BRAND_ID);
        setting.ifPresent(r -> {
                    LocalDateTime dateTime = calTime(clueTask.getBeginTime(), Objects.requireNonNull(SettingUnitEnum.ofValue(r.getUnit())), r.getDetailValue());
                    followInitDTO.setFirstRecordDeadline(DateUtil.localDateTime2Date(dateTime.minusSeconds(1L)));
                });
        Map<String, String> noteMap = createNoteMap(pubClue, customerDetailDto);
        followInitDTO.setNoteMap(noteMap);
        return followInitDTO;
    }


    private Map<String, String> createNoteMap(PubCluePool pubClue, CustomerDetailDto detailDto) {
        Map<String, String> dynamicMap = new HashMap<>();
        if (Objects.nonNull(pubClue)) {
            int count = Optional.ofNullable(detailDto.getArrivalCount()).orElse(0);
            Date buyDate = detailDto.getBuyDate();
            Date expires = detailDto.getInsuranceExpires();

            String name = detailDto.getName();
            String vin = pubClue.getVin();
            String arrivalCount = String.valueOf(count);
            String defeatCount = "0";
            String vehicleAge = String.valueOf(Math.abs(DateUtil.sub(buyDate, new Date(), "y")));
            String _buyDate = DateUtil.getStringDateShort(buyDate);
            String insuranceExpires = DateUtil.getStringDateShort(expires);

            dynamicMap.put("name", name);
            dynamicMap.put("vin", vin);
            dynamicMap.put("arrivalCount", arrivalCount);
            dynamicMap.put("defeatCount", defeatCount);
            dynamicMap.put("vehicleAge", vehicleAge + "年");
            dynamicMap.put("buyDate", _buyDate);
            dynamicMap.put("insuranceExpires", insuranceExpires);
        }
        return dynamicMap;
    }

}