OrderOverTimeEventJob.java 18.7 KB
package com.order.erp.job;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.order.erp.common.constant.Constant;
import com.order.erp.common.utils.EmailSendUtils;
import com.order.erp.common.utils.RedisUtils;
import com.order.erp.common.utils.StringUtils;
import com.order.erp.common.utils.TransactionHelper;
import com.order.erp.domain.EmailTemplateEnum;
import com.order.erp.domain.OrderEventEnum;
import com.order.erp.domain.dto.order.OrderBaseInfoDO;
import com.order.erp.domain.dto.order.OrderInspectionStageDO;
import com.order.erp.domain.dto.order.OrderTrackStageDO;
import com.order.erp.domain.dto.order.ReceiveEmailMappingDO;
import com.order.erp.domain.vo.order.*;
import com.order.erp.service.order.*;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;



/**
 * @author: xms
 * @description: TODO
 * @date: 2023/6/25 10:35
 * @version: 1.0
 */
@Slf4j
@Component
public class OrderOverTimeEventJob {

    @Resource
    private OrderBaseInfoService orderBaseInfoService;

    @Resource
    private OrderProfitAnalysisService profitAnalysisService;

    @Resource
    private OrderCompletionReportService reportService;

    @Resource
    private OrderTrackStageService trackStageService;

    @Resource
    private OrderInspectionStageService inspectionStageService;

    @Resource
    private TransactionHelper transactionHelper;

    @Resource
    private EmailSendUtils emailSendUtils;

    @Resource
    private ReceiveEmailMappingService receiveEmailMappingService;

    @Resource
    private RedisUtils redisUtils;

    /**
     * 凌晨1点执行,一天一次
     */
        @Scheduled(cron = "0 0 2 * * ?")
    public void checkOverTimeExecuteV2() throws MessagingException, TemplateException, IOException {
        List<OrderBaseInfoDO> orderBaseInfoDOList = orderBaseInfoService.getEventList();
        Set<Long> orderIds = orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getId).collect(Collectors.toSet());
        List<OrderInspectionStageDO> orderInspectionStageDOList = inspectionStageService.list(new LambdaQueryWrapper<OrderInspectionStageDO>()
                .in(OrderInspectionStageDO::getOrderId, orderIds));
        List<OrderTrackStageDO> orderTrackStageDOList = trackStageService.list(new LambdaQueryWrapper<OrderTrackStageDO>()
                .in(OrderTrackStageDO::getOrderId, orderIds));
        List<OrderEventJobVO> jobVOList = transfer2OrderEventList(orderBaseInfoDOList, orderInspectionStageDOList, orderTrackStageDOList);
        Map<String, List<OrderEventJobVO>> map = handlerOrderEvent(jobVOList);
        for (Map.Entry<String, List<OrderEventJobVO>> entry : map.entrySet()) {
            sendEmail4OrderEvent(OrderEventEnum.getEvent(entry.getKey()), entry.getValue());
        }
    }

    /**
     * @param eventEnum
     * @param eventJobVOS
     */
    //发送邮件。
    private void sendEmail4OrderEvent(OrderEventEnum eventEnum, List<OrderEventJobVO> eventJobVOS) throws MessagingException, TemplateException, IOException {
        HashSet<String> strings = new HashSet<>();
        for (OrderEventJobVO orderEventJob : eventJobVOS) {
            if (!redisUtils.hasKey(EmailTemplateEnum.byTemplate(
                    eventEnum.getTemplateId()) + Constant.POINT_BAR_CHARACTER + orderEventJob.getBaseInfo().getId())){
                strings.add(orderEventJob.getBaseInfo().getCustomerCode());
            }
        }
        LambdaQueryWrapper<ReceiveEmailMappingDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ReceiveEmailMappingDO::getEnableFlag, Constant.ENABLE_TEN);
        if (strings == null || strings.isEmpty()) {
            queryWrapper.eq(ReceiveEmailMappingDO::getTypeValue,  " ");
        } else {
            queryWrapper.in(ReceiveEmailMappingDO::getTypeValue, strings);
        }
        queryWrapper.apply("JSON_CONTAINS(JSON_EXTRACT(config_infos, '$[*].event'), JSON_QUOTE({0}), '$')", eventEnum.getEvent());
       List<ReceiveEmailMappingDO> receiveEmailMappingDOList = receiveEmailMappingService.list(queryWrapper);

       /* List<ReceiveEmailMappingDO> receiveEmailMappingDOList = receiveEmailMappingService.list(
                new LambdaQueryWrapper<ReceiveEmailMappingDO>()
                .eq(ReceiveEmailMappingDO::getEnableFlag, Constant.ENABLE_TEN)
                .in(CollectionUtils.isNotEmpty(strings),ReceiveEmailMappingDO::getTypeValue, strings)
                .apply("JSON_CONTAINS(JSON_EXTRACT(config_infos, '$[*].event'), JSON_QUOTE({0}), '$')", eventEnum.getEvent()));*/

        Set<Map<String, List<String>>> set = receiveEmailMappingDOList.stream().map(x -> {
            Map<String, List<String>> map = new HashMap<>();
            String customerCode = x.getTypeValue();
//            ReceiveEmailConfigItemVO receiveEmailConfigItemVO = JSON.parseObject(x.getConfigInfos(), ReceiveEmailConfigItemVO.class);
            List<ReceiveEmailConfigItemVO> receiveEmailConfigItemVOList = JSON.parseObject(
                    x.getConfigInfos(), new TypeReference<List<ReceiveEmailConfigItemVO>>() {
                    });
            List<String> strings1 = new ArrayList<>();
            for (ReceiveEmailConfigItemVO item : receiveEmailConfigItemVOList) {
                strings1 = item.getEmails();
            }
            List<String> emails = strings1;
            map.put(customerCode, emails);
            return map;
        }).collect(Collectors.toSet());
        for (OrderEventJobVO orderEventJob : eventJobVOS) {
            for (Map<String, List<String>> map : set) {
                if (orderEventJob.getBaseInfo().getCustomerCode().equals(map.keySet().iterator().next())) {
                    emailSendUtils.sendEmail(EmailTemplateEnum.byTemplate(eventEnum.getTemplateId()),
                            map.get(map.keySet().iterator().next()), orderEventJob);
                    redisUtils.set(EmailTemplateEnum.byTemplate(
                                    eventEnum.getTemplateId()) + Constant.POINT_BAR_CHARACTER + orderEventJob.getBaseInfo().getId(),
                            orderEventJob);
                }
            }

        }
    }

    /**
     * @param orderBaseInfoList        订单基础信息集合。
     * @param orderInspectionStageList 订单质检信息集合。  (需要尾期验货申请时间,判断尾期验货日期到期时间)/(还需要尾期验货报告和中期验货报告)
     * @param orderTrackStageList      订单跟单信息集合。   (需要各个属性,判断其他各种事件)
     * @return 0rderEventJobVO 订单数据整合集合
     */
    //这个方法的作用应该是筛选出订单数据。
    private List<OrderEventJobVO> transfer2OrderEventList(List<OrderBaseInfoDO> orderBaseInfoList, List<OrderInspectionStageDO> orderInspectionStageList, List<OrderTrackStageDO> orderTrackStageList) {
        // todo
        Map<Long, OrderInspectionStageDO> OrderInspectionStageMap = orderInspectionStageList.stream().collect(Collectors.toMap(OrderInspectionStageDO::getOrderId, Function.identity(), (x, y) -> x));
        Map<Long, OrderTrackStageDO> OrderTrackStageMap = orderTrackStageList.stream().collect(Collectors.toMap(OrderTrackStageDO::getOrderId, Function.identity(), (x, y) -> x));
        List<OrderEventJobVO> orderEventJobVOList = orderBaseInfoList.stream().map(x -> {
                    OrderEventJobVO orderEventJobVO = new OrderEventJobVO();
                    if (x.getId() == OrderInspectionStageMap.get(x.getId()).getOrderId() &&
                            x.getId() == OrderTrackStageMap.get(x.getId()).getOrderId()) {
                        OrderBaseInfoVO orderBaseInfoVO = new OrderBaseInfoVO();
                        OrderTrackStageVO orderTrackStageVO = new OrderTrackStageVO();
                        OrderInspectionStageVO orderInspectionStageVO = new OrderInspectionStageVO();
                        BeanUtil.copyProperties(x, orderBaseInfoVO);
                        BeanUtil.copyProperties(OrderInspectionStageMap.get(x.getId()), orderInspectionStageVO);
                        BeanUtil.copyProperties(OrderTrackStageMap.get(x.getId()), orderTrackStageVO);
                        orderEventJobVO.setOrderId(orderBaseInfoVO.getId());
                        orderEventJobVO.setInspectionStageInfo(orderInspectionStageVO);
                        orderEventJobVO.setBaseInfo(orderBaseInfoVO);
                        orderEventJobVO.setTrackStageInfo(orderTrackStageVO);
                    }
                    return orderEventJobVO;
                }).filter(Objects::nonNull)
                .collect(Collectors.toList());
        return orderEventJobVOList;
    }

    /**
     * @param orderEventJobVOList
     * @return
     */
    private Map<String, List<OrderEventJobVO>> handlerOrderEvent(List<OrderEventJobVO> orderEventJobVOList) {
        Map<String, List<OrderEventJobVO>> map = new HashMap<>();
        for (OrderEventJobVO eventJobVO : orderEventJobVOList) {
            Map<String, OrderEventJobVO> eventJobVOMap = groupByOrderEvent(eventJobVO);
            if (CollectionUtils.isNotEmpty(eventJobVOMap)) {
                for (Map.Entry<String, OrderEventJobVO> entry : eventJobVOMap.entrySet()) {
                    String key = entry.getKey();
                    if (map.containsKey(key)) {
                        List<OrderEventJobVO> list = map.get(key);
                        list.add(entry.getValue());
                        map.put(key, list);
                    } else {
                        List<OrderEventJobVO> list = new ArrayList<>();
                        list.add(entry.getValue());
                        map.put(key, list);
                    }
                }
            }
        }
        return map;
    }

    /**
     * @param eventJobVO
     * @return
     */
    private Map<String, OrderEventJobVO> groupByOrderEvent(OrderEventJobVO eventJobVO) {
        Map<String, OrderEventJobVO> map = new HashMap<>();
        if (filterConfirmSampleOrderEvent(eventJobVO)) {
            map.put(OrderEventEnum.CONFIRM_SAMPLE_EVENT.getEvent(), eventJobVO);
        }
        if (filterOtherSampleEvent(eventJobVO)) {
            map.put(OrderEventEnum.OTHER_SAMPLE_EVENT.getEvent(), eventJobVO);
        }
        if (filterBigSampleEvent(eventJobVO)) {
            map.put(OrderEventEnum.BIG_SAMPLE_EVENT.getEvent(), eventJobVO);
        }
        if (filterAITEXSGSTestEvent(eventJobVO)) {
            map.put(OrderEventEnum.AITEX_SGS_TEST_EVENT.getEvent(), eventJobVO);
        }
        if (filterBarcodeArrivalEvent(eventJobVO)) {
            map.put(OrderEventEnum.BARCODE_ARRIVAL_EVENT.getEvent(), eventJobVO);
        }
        if (filterLatestDCEvent(eventJobVO)) {
            map.put(OrderEventEnum.LATEST_DC_EVENT.getEvent(), eventJobVO);
        }
        if (filterEndCheckDateEvent(eventJobVO)) {
            map.put(OrderEventEnum.END_CHECK_DATE_EVENT.getEvent(), eventJobVO);
        }
        // todo 其他订单超期事件判断  中期验货报告和尾期验货报告。
        return map;
    }

    /**
     * @param eventJobVO
     * @return
     */
    private Boolean filterConfirmSampleOrderEvent(OrderEventJobVO eventJobVO) {

        // todo 判断是否未能在规定的期限内完成以下货号的确认样确认
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String ppConfirmResult = eventJobVO.getTrackStageInfo().getPpConfirmResult();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(ppConfirmResult)) {
            if (!ppConfirmResult.contains("ok") && org.apache.commons.lang3.StringUtils.countMatches(ppConfirmResult, "fail") == 3) {
                return true;
            } else if (ppConfirmResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(ppConfirmResult, "fail") < 3) {
                String[] parats = ppConfirmResult.split("\\+");
                String lastTime = parats[parats.length - 3];
                LocalDate parse1 = LocalDate.parse(lastTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
                LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
                long daysBetween = ChronoUnit.DAYS.between(parse1, parse2);
                if (daysBetween == 21) {
                    return true;
                }
            }
        }
        return false;
    }

    private Boolean filterOtherSampleEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String esoSampleSendTime = eventJobVO.getTrackStageInfo().getEsoSampleSendTime();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(esoSampleSendTime)) {
            LocalDate parse1 = LocalDate.parse(esoSampleSendTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            if (ChronoUnit.DAYS.between(parse1, parse2) == 7) {
                return true;
            }
        }
        return false;
    }

    private Boolean filterBigSampleEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String shippmentSampleConfirmResult = eventJobVO.getTrackStageInfo().getShippmentSampleConfirmResult();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(shippmentSampleConfirmResult)) {
            if (!shippmentSampleConfirmResult.contains("ok") && org.apache.commons.lang3.StringUtils.countMatches(shippmentSampleConfirmResult, "fail") == 3) {
                return true;
            } else if (shippmentSampleConfirmResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(shippmentSampleConfirmResult, "fail") < 3) {
                String[] parats = shippmentSampleConfirmResult.split("\\+");
                String lastTime = parats[parats.length - 3];
                LocalDate parse1 = LocalDate.parse(lastTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
                LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
                long daysBetween = ChronoUnit.DAYS.between(parse1, parse2);
                if (daysBetween == 7) {
                    return true;
                }
            }
        }
        return false;
    }


    private Boolean filterAITEXSGSTestEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String shippmentSampleConfirmResult = eventJobVO.getTrackStageInfo().getAitexTestFinishResult();
        String sgsTestFinishResult = eventJobVO.getTrackStageInfo().getSgsTestFinishResult();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(shippmentSampleConfirmResult) ||
                StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(sgsTestFinishResult)) {
            if (!shippmentSampleConfirmResult.contains("ok") && org.apache.commons.lang3.StringUtils.countMatches(shippmentSampleConfirmResult, "fail") == 3 ||
                    !shippmentSampleConfirmResult.contains("ok") && org.apache.commons.lang3.StringUtils.countMatches(sgsTestFinishResult, "fail") == 3) {
                return true;
            } else if ((shippmentSampleConfirmResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(shippmentSampleConfirmResult, "fail") < 3) ||
                    (sgsTestFinishResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(sgsTestFinishResult, "fail") < 3)) {
                String[] parats = shippmentSampleConfirmResult.split("\\+");
                String lastTime = parats[parats.length - 3];
                String[] parats1 = sgsTestFinishResult.split("\\+");
                String lastTime1 = parats1[parats1.length - 3];
                LocalDate parse1 = LocalDate.parse(lastTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
                LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
                LocalDate parse3 = LocalDate.parse(lastTime1, DateTimeFormatter.ofPattern("yyyy-M-d"));
                long daysBetween = ChronoUnit.DAYS.between(parse1, parse2);
                long daysBetween1 = ChronoUnit.DAYS.between(parse3, parse2);
                if (daysBetween == 3 || daysBetween1 == 3) {
                    return true;
                }
            }
        }
        return false;
    }


    private Boolean filterBarcodeArrivalEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String lastArrivalTime = eventJobVO.getTrackStageInfo().getLatestArrivalTime();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(lastArrivalTime)) {
            LocalDate parse1 = LocalDate.parse(lastArrivalTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            if (ChronoUnit.DAYS.between(parse1, parse2) == 7) {
                return true;
            }
        }
        return false;
    }

    private Boolean filterLatestDCEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String latestBkTime = eventJobVO.getTrackStageInfo().getLatestBkTime();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(latestBkTime)) {
            LocalDate parse1 = LocalDate.parse(latestBkTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            if (ChronoUnit.DAYS.between(parse1, parse2) == 10) {
                return true;
            }
        }
        return false;
    }

    private Boolean filterEndCheckDateEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String endCheckApplyTime = eventJobVO.getInspectionStageInfo().getEndCheckApplyTime();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(endCheckApplyTime)) {
            LocalDate parse1 = LocalDate.parse(endCheckApplyTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            if (ChronoUnit.DAYS.between(parse1, parse2) == 2) {
                return true;
            }
        }
        return false;
    }
}