NoticeBizService.java 13.7 KB
package cn.fw.valhalla.service.bus.follow;

import cn.fw.valhalla.common.utils.DateUtil;
import cn.fw.valhalla.domain.db.customer.Customer;
import cn.fw.valhalla.domain.db.customer.CustomerBaseInfo;
import cn.fw.valhalla.domain.db.follow.ClueTask;
import cn.fw.valhalla.domain.db.follow.FollowClue;
import cn.fw.valhalla.domain.db.follow.FollowNoticeRecord;
import cn.fw.valhalla.domain.enums.*;
import cn.fw.valhalla.domain.vo.setting.SettingVO;
import cn.fw.valhalla.rpc.ehr.EhrRpcService;
import cn.fw.valhalla.rpc.ehr.dto.StaffInfoDTO;
import cn.fw.valhalla.rpc.hestia.HestiaRpcService;
import cn.fw.valhalla.rpc.hestia.dto.TemplateDTO;
import cn.fw.valhalla.rpc.hestia.dto.TemplateResult;
import cn.fw.valhalla.rpc.oop.OopService;
import cn.fw.valhalla.rpc.oop.dto.ShopDTO;
import cn.fw.valhalla.rpc.sms.SmsRpcService;
import cn.fw.valhalla.service.bus.setting.SettingBizService;
import cn.fw.valhalla.service.data.*;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;

import static cn.fw.valhalla.service.bus.follow.strategy.AbstractFollowStrategy.getCalendarType;
import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID;

/**
 * @author : kurisu
 * @className : SendNoticeService
 * @description : 发送消息
 * @date: 2020-08-26 15:48
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class NoticeBizService {
    private final HestiaRpcService hestiaRpcService;
    private final FollowNoticeRecordService followNoticeRecordService;
    private final SettingBizService settingBizService;
    private final CustomerService customerService;
    private final CustomerBaseInfoService customerBaseInfoService;
    private final OopService oopService;
    private final SmsRpcService smsRpcService;
    private final ClueTaskService clueTaskService;
    private final EhrRpcService ehrRpcService;
    private final FollowClueService followClueService;

    private final String type = "d";
    private final int day = 2;

    @Value("${follow.FmTemplateCode}")
    @Getter
    private String fmTemplateCode;

    @Value("${follow.RmTemplateCode}")
    @Getter
    private String rmTemplateCode;

    @Value("${follow.IrTemplateCode}")
    @Getter
    private String irTemplateCode;


    /**
     * 发送模板消息
     */
    public void sendNotice() {
        List<FollowNoticeRecord> list = followNoticeRecordService.list(Wrappers.<FollowNoticeRecord>lambdaQuery()
                .eq(FollowNoticeRecord::getStatus, SendStatusEnum.NOT_SENT)
                .le(FollowNoticeRecord::getSendTime, DateUtil.localDateTime2Date(LocalDateTime.now()))
                .last("limit 0, 100")
        );
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (FollowNoticeRecord record : list) {
            sendNoticeAndCreate(record);
        }
    }

    /**
     * 推送模板消息 完成后生成下一次推送
     *
     * @param record
     */
    private void sendNoticeAndCreate(FollowNoticeRecord record) {
        FollowClue cluePool = followClueService.getById(record.getClueId());
        if (Objects.isNull(cluePool)) {
            followNoticeRecordService.removeById(record.getId());
            return;
        }
        if (ClueStatusEnum.FAILURE.equals(cluePool.getClueState()) || ClueStatusEnum.COMPLETE.equals(cluePool.getClueState()) || cluePool.getEndTime().isBefore(LocalDateTime.now())) {
            followNoticeRecordService.removeById(record.getId());
            return;
        }
        Customer customer = customerService.queryByFrameNo(cluePool.getVin(), cluePool.getGroupId());
        if (Objects.isNull(customer)) {
            createNextNotice(record, cluePool.getGroupId());
            return;
        }
        CustomerBaseInfo baseInfo = customerBaseInfoService.queryById(customer.getBaseId());
        if (Objects.isNull(baseInfo)) {
            createNextNotice(record, cluePool.getGroupId());
            return;
        }
        ShopDTO shop = oopService.shop(customer.getShopId());
        if (Objects.isNull(shop)) {
            shop = oopService.shop(cluePool.getSuggestShopId());
        }
        String shopName = Objects.isNull(shop) ? "" : shop.getShortName();
        boolean flag = false;
        if (FollowTypeEnum.IR.equals(record.getFollowType())) {
            flag = sendIR(record, cluePool, baseInfo, shopName);
        }
        if (FollowTypeEnum.FM.equals(record.getFollowType())) {
            flag = sendFM(record, cluePool, baseInfo, shopName);
        }
        if (FollowTypeEnum.RM.equals(record.getFollowType())) {
            flag = sendRM(record, cluePool, baseInfo, shopName);
        }
        if (flag) {
            createNextNotice(record, cluePool.getGroupId());
        }
    }

    private boolean sendIR(final FollowNoticeRecord record, final FollowClue cluePool, CustomerBaseInfo baseInfo, String shopName) {
        if (DateUtil.sub(new Date(), record.getSendTime(), type) > day) {
            record.setStatus(SendStatusEnum.SUCCESS);
            return followNoticeRecordService.updateById(record);
        }
        Customer customer = Optional.ofNullable(customerService.queryByFrameNo(cluePool.getVin(), cluePool.getGroupId())).orElse(new Customer());
        //页面附带参数
        HashMap<String, String> paramMap = new HashMap<>(1);
        paramMap.put("bizType", "2");
        //额外展示数据
        HashMap<String, String> extraMap = new HashMap<>(2);
        extraMap.put("车牌号", customer.getPlateNo());
        extraMap.put("车险到期时间", DateUtil.getStringDateShort(customer.getInsuranceExpires()));
        //生成发送实体
        TemplateDTO templateDTO = TemplateDTO.builder()
                .content("您好!您购买的车险即将到期,现在预约续保可享养车大礼包!")
                .memberId(baseInfo.getMemberId())
                .title("车险到期提醒")
                .remark(shopName + " 竭诚为您服务")
                .path("/pgCas/Insurance/Append/index")
                .paramMap(paramMap)
                .extraMap(extraMap)
                .build();
        TemplateResult templateResult = hestiaRpcService.senTemplateMsg(templateDTO);
        record.setStatus(Objects.nonNull(templateResult) ? SendStatusEnum.SUCCESS : SendStatusEnum.FAILED);
        record.setStatusDesc(templateResult.getSceneToken().toString());
        if (SendStatusEnum.FAILED.equals(record.getStatus())) {
            Long staffId = customer.getAdviserId();
            ClueTask task = clueTaskService.queryOngoingTaskByClueId(cluePool.getId());
            if (Objects.nonNull(task)) {
                staffId = task.getFollowUser();
            }
            StaffInfoDTO infoDTO = ehrRpcService.queryStaffInfo(staffId);
            if (Objects.nonNull(infoDTO)) {
                Map<String, Object> map = new HashMap<>(4);
                map.put("date", DateUtil.getStringDateShort(customer.getInsuranceExpires()));
                map.put("shopName", shopName);
                map.put("userName", infoDTO.getName());
                map.put("phone", infoDTO.getMobile());
                smsRpcService.sendSms(getIrTemplateCode(), baseInfo.getMobile(), map, cluePool.getSuggestShopId());
            }
        }
        return followNoticeRecordService.updateById(record);
    }

    private boolean sendFM(final FollowNoticeRecord record, final FollowClue cluePool, CustomerBaseInfo baseInfo, String shopName) {
        if (DateUtil.sub(new Date(), record.getSendTime(), type) > day) {
            record.setStatus(SendStatusEnum.SUCCESS);
            return followNoticeRecordService.updateById(record);
        }
        //额外展示数据
        HashMap<String, String> extraMap = new HashMap<>(2);
        extraMap.put("车牌号", cluePool.getPlateNo());
        extraMap.put("到期时间", DateUtil.getStringDateShort(DateUtil.localDateTime2Date(cluePool.getEndTime())));
        //生成发送实体
        TemplateDTO templateDTO = TemplateDTO.builder()
                .content("您好!您的爱车的首次保养即将到期,请尽快进店进行保养!")
                .memberId(baseInfo.getMemberId())
                .title("首保到期提醒")
                .remark(shopName + " 竭诚为您服务")
                .path("/pgCas/Appoint/Index/index")
                .extraMap(extraMap)
                .build();
        TemplateResult templateResult = hestiaRpcService.senTemplateMsg(templateDTO);
        record.setStatus(Objects.nonNull(templateResult) ? SendStatusEnum.SUCCESS : SendStatusEnum.FAILED);
        record.setStatusDesc(templateResult.getSceneToken().toString());
        if (SendStatusEnum.FAILED.equals(record.getStatus())) {
            Long staffId = null;
            ClueTask task = clueTaskService.queryOngoingTaskByClueId(cluePool.getId());
            if (Objects.nonNull(task)) {
                staffId = task.getFollowUser();
            }
            StaffInfoDTO infoDTO = ehrRpcService.queryStaffInfo(staffId);
            if (Objects.nonNull(infoDTO)) {
                Map<String, Object> map = new HashMap<>(3);
                map.put("shopName", shopName);
                map.put("userName", infoDTO.getName());
                map.put("phone", infoDTO.getMobile());
                smsRpcService.sendSms(getFmTemplateCode(), baseInfo.getMobile(), map, cluePool.getSuggestShopId());
            }
        }
        return followNoticeRecordService.updateById(record);
    }

    private boolean sendRM(final FollowNoticeRecord record, final FollowClue cluePool, CustomerBaseInfo baseInfo, String shopName) {
        if (DateUtil.sub(new Date(), record.getSendTime(), type) > day) {
            record.setStatus(SendStatusEnum.SUCCESS);
            return followNoticeRecordService.updateById(record);
        }
        //额外展示数据
        HashMap<String, String> extraMap = new HashMap<>(2);
        extraMap.put("车牌号", cluePool.getPlateNo());
        extraMap.put("推荐保养时间", DateUtil.getStringDateShort(DateUtil.localDateTime2Date(cluePool.getEndTime())) + " 前");
        //生成发送实体
        TemplateDTO templateDTO = TemplateDTO.builder()
                .content("您好!即将到达您的爱车下次保养日期,请尽快进店进行保养!")
                .memberId(baseInfo.getMemberId())
                .title("保养提醒")
                .remark(shopName + " 竭诚为您服务")
                .path("/pgCas/Appoint/Index/index")
                .extraMap(extraMap)
                .build();
        TemplateResult templateResult = hestiaRpcService.senTemplateMsg(templateDTO);
        record.setStatus(Objects.nonNull(templateResult) ? SendStatusEnum.SUCCESS : SendStatusEnum.FAILED);
        record.setStatusDesc(templateResult.getSceneToken().toString());
        if (SendStatusEnum.FAILED.equals(record.getStatus())) {
            Long staffId = null;
            ClueTask task = clueTaskService.queryOngoingTaskByClueId(cluePool.getId());
            if (Objects.nonNull(task)) {
                staffId = task.getFollowUser();
            }
            StaffInfoDTO infoDTO = ehrRpcService.queryStaffInfo(staffId);
            if (Objects.nonNull(infoDTO)) {
                Integer m = DateUtil.sub(DateUtil.localDateTime2Date(cluePool.getOriginTime()), new Date(), "m");
                Map<String, Object> map = new HashMap<>(4);
                map.put("num", Math.abs(m));
                map.put("shopName", shopName);
                map.put("userName", infoDTO.getName());
                map.put("phone", infoDTO.getMobile());
                smsRpcService.sendSms(getRmTemplateCode(), baseInfo.getMobile(), map, cluePool.getSuggestShopId());
            }
        }
        return followNoticeRecordService.updateById(record);
    }

    private void createNextNotice(final FollowNoticeRecord record, Long groupId) {
        Long brandId = COMMON_BRAND_ID;
        Customer customer = customerService.queryById(record.getCustomerId());
        if (Objects.nonNull(customer)) {
            brandId = customer.getBrandId();
        }
        Optional<SettingVO> timesSetting = settingBizService.querySettingByType(record.getFollowType(), SettingTypeEnum.NOTICE_TIMES, groupId, brandId);
        if (!timesSetting.isPresent()) {
            return;
        }
        int count = followNoticeRecordService.count(Wrappers.<FollowNoticeRecord>lambdaQuery().eq(FollowNoticeRecord::getClueId, record.getClueId()));
        int value = Optional.ofNullable(timesSetting.get().getDetailValue()).orElse(0);
        if (count >= value) {
            return;
        }
        Optional<SettingVO> cycleSetting = settingBizService.querySettingByType(record.getFollowType(), SettingTypeEnum.NOTICE_CYCLE, groupId, brandId);
        cycleSetting.ifPresent(r -> {
            Timestamp expired = DateUtil.getExpired(record.getSendTime(), r.getDetailValue(), getCalendarType(Objects.requireNonNull(SettingUnitEnum.ofValue(r.getUnit()))));
            followNoticeRecordService.save(createEntity(record, expired));
        });
    }

    private FollowNoticeRecord createEntity(final FollowNoticeRecord record, Timestamp time) {
        FollowNoticeRecord noticeRecord = new FollowNoticeRecord();
        noticeRecord.setCustomerId(record.getCustomerId());
        noticeRecord.setClueId(record.getClueId());
        noticeRecord.setFollowType(record.getFollowType());
        noticeRecord.setStatus(SendStatusEnum.NOT_SENT);
        noticeRecord.setSendTime(time);
        noticeRecord.setCreateTime(DateUtil.localDateTime2Date(LocalDateTime.now()));
        return noticeRecord;
    }
}