OrderOverTimeEventJob.java 19.1 KB
package com.order.erp.job;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.*;
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.*;
import com.order.erp.domain.EmailTemplateEnum;
import com.order.erp.domain.OrderEventEnum;
import com.order.erp.domain.dto.BaseDO;
import com.order.erp.domain.dto.admin.AdminUserDO;
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.admin.AdminUserService;
import com.order.erp.service.order.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
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 OrderTrackStageService trackStageService;

    @Resource
    private OrderInspectionStageService inspectionStageService;

    @Resource
    private EmailSendUtils emailSendUtils;

    @Resource
    private ReceiveEmailMappingService receiveEmailMappingService;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private AdminUserService adminUserService;

    /**
     * 凌晨1点执行,一天一次
     */
    @Scheduled(cron = "0 0 1 * * ?")
    //存储的日期都必须为yyyy-MM-dd HH:mm:ss。
    public void checkOverTimeExecuteV2() {
        List<OrderBaseInfoDO> orderBaseInfoDOList = orderBaseInfoService.getEventList();
        if (CollectionUtils.isNotEmpty(orderBaseInfoDOList)) {
            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) {

        HashSet<String> customerCodeList = new HashSet<>();
        for (OrderEventJobVO orderEventJob : eventJobVOS) {
            if (!redisUtils.hasKey(EmailTemplateEnum.byTemplate(
                    eventEnum.getTemplateId()) + Constant.CROSS_BAR_CHARACTER + orderEventJob.getBaseInfo().getId())) {
                customerCodeList.add(orderEventJob.getBaseInfo().getCustomerCode());
            }
        }
        LambdaQueryWrapper<ReceiveEmailMappingDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ReceiveEmailMappingDO::getEnableFlag, Constant.ENABLE_TEN);
        if (CollectionUtils.isEmpty(customerCodeList)) {
            queryWrapper.eq(ReceiveEmailMappingDO::getTypeValue, "");
        } else {
            queryWrapper.in(ReceiveEmailMappingDO::getTypeValue, customerCodeList);
        }
//        queryWrapper.apply("JSON_CONTAINS(JSON_EXTRACT(config_infos,'$[*].event'),JSON_QUOTE({0}),'$')", eventEnum.getEvent());

        List<ReceiveEmailMappingDO> receiveEmailMappingDOList = receiveEmailMappingService.list(queryWrapper);
        List<ReceiveEmailMappingDO> receiveEmailMappingDOS = receiveEmailMappingDOList.stream().map(x -> {
                    List<ReceiveEmailConfigItemVO> receiveEmailConfigItemVOList = JSON.parseObject(x.getConfigInfos(), new TypeReference<List<ReceiveEmailConfigItemVO>>() {
                    });
                    for (ReceiveEmailConfigItemVO receiveEmailConfigItemVO : receiveEmailConfigItemVOList) {
                        if (eventEnum.getEvent().equals(receiveEmailConfigItemVO.getEvent())) {
                            return x;
                        }
                    }
                    return null;
                }).filter(Objects::nonNull)
                .collect(Collectors.toList());
        //如果为尾期验货事件的话,需要从订单中的生产科角色中得到邮箱。而不是从邮件配置中得到邮箱。
        if (OrderEventEnum.END_CHECK_DATE_EVENT.equals(eventEnum)) {
            for (OrderEventJobVO orderEventJob : eventJobVOS) {
                String productionDepartment = orderEventJob.getBaseInfo().getProductionDepartment();
                //根据订单的生产科得到生产科用户信息。
                AdminUserDO productionDepartmentUser = adminUserService.getOne(new LambdaQueryWrapper<AdminUserDO>()
                        .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
                        .eq(AdminUserDO::getUserName, productionDepartment));
                List<String> productionEmail = Arrays.asList(productionDepartmentUser.getEmail().split("[,,]+"))
                        .stream().map(String::trim)
                        .collect(Collectors.toList());
                emailSendUtils.sendEmail(EmailTemplateEnum.byTemplate(eventEnum.getTemplateId()),
                        productionEmail, orderEventJob);
                redisUtils.set(EmailTemplateEnum.byTemplate(
                                eventEnum.getTemplateId()) + Constant.CROSS_BAR_CHARACTER + orderEventJob.getBaseInfo().getId(),
                        orderEventJob, 90, TimeUnit.DAYS);
            }
        } else {
            Set<Map<String, List<String>>> set = receiveEmailMappingDOS.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> emailList = new ArrayList<>();
                for (ReceiveEmailConfigItemVO item : receiveEmailConfigItemVOList) {
                    if (eventEnum.getEvent().equals(item.getEvent())) {
                        emailList = item.getEmails();
                    }
                }
                List<String> emails = emailList;
                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.CROSS_BAR_CHARACTER + orderEventJob.getBaseInfo().getId(),
                                orderEventJob, Constant.REDIS_EMAIL_TIME, TimeUnit.DAYS);
                    }
                }
            }
        }
    }

    /**
     * @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 (OrderInspectionStageMap.containsKey(x.getId()) && OrderTrackStageMap.containsKey(x.getId())) {
                        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;
                    } else {
                        return null;
                    }
                }).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);
        }
        return map;
    }

    /**
     * @param eventJobVO
     * @return
     */
    private Boolean filterConfirmSampleOrderEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String ppConfirmTime = eventJobVO.getTrackStageInfo().getPpConfirmTime();
        String ppConfirmResult = eventJobVO.getTrackStageInfo().getPpConfirmResult();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(ppConfirmResult) && StringUtils.isNotBlank(ppConfirmTime)) {
            int daysBetween = getDaysBetween(ppConfirmResult, ppConfirmTime, orderHodTime);
            if (daysBetween == Constant.TWENTY_FIRST || daysBetween == Constant.NEGATIVE_ONE) {
                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 orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
            LocalDate esoSampleSendTimelocalDate = DateUtils.parseDate(esoSampleSendTime);
            if (ChronoUnit.DAYS.between(esoSampleSendTimelocalDate, orderHodTimelocalDate) == Constant.SEVEN) {
                return true;
            }

        }
        return false;
    }

    private Boolean filterBigSampleEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String shippmentSampleConfirmResult = eventJobVO.getTrackStageInfo().getShippmentSampleConfirmResult();
        String shippmentSampleConfirmTime = eventJobVO.getTrackStageInfo().getShippmentSampleSendTime();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(shippmentSampleConfirmResult) && StringUtils.isNotBlank(shippmentSampleConfirmTime)) {
            int daysBetween = getDaysBetween(shippmentSampleConfirmResult, shippmentSampleConfirmTime, orderHodTime);
            if (daysBetween == Constant.SEVEN || daysBetween == Constant.NEGATIVE_ONE) {
                return true;
            }
        }
        return false;
    }


    private Boolean filterAITEXSGSTestEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String aitexTestFinishResult = eventJobVO.getTrackStageInfo().getAitexTestFinishResult();
        String sgsTestFinishResult = eventJobVO.getTrackStageInfo().getSgsTestFinishResult();
        String sgsTestFinishTime = eventJobVO.getTrackStageInfo().getSgsTestFinishTime();
        String aitexTestFinishTime = eventJobVO.getTrackStageInfo().getAitexTestFinishTime();
        if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(aitexTestFinishResult) && StringUtils.isNotBlank(aitexTestFinishTime) ||
                StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(sgsTestFinishResult) && StringUtils.isNotBlank(sgsTestFinishTime)) {
            int aitextestDaysBetween = getDaysBetween(aitexTestFinishResult, aitexTestFinishTime, orderHodTime);
            int sgstestDaysBetween = getDaysBetween(sgsTestFinishResult, sgsTestFinishTime, orderHodTime);
            if (aitextestDaysBetween == Constant.THREE || sgstestDaysBetween == Constant.LOCK_ERROR_TIMES || aitextestDaysBetween == Constant.NEGATIVE_ONE || sgstestDaysBetween == Constant.NEGATIVE_ONE) {
                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 orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
            LocalDate lastArrivalTimelocalDate = DateUtils.parseDate(lastArrivalTime);
            if (ChronoUnit.DAYS.between(lastArrivalTimelocalDate, orderHodTimelocalDate) == Constant.SEVEN) {
                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 latestBkTimelocalDate = DateUtils.parseDate(latestBkTime);
            LocalDate orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
            if (ChronoUnit.DAYS.between(latestBkTimelocalDate, orderHodTimelocalDate) == Constant.ENABLE_TEN) {
                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 endCheckApplyTimelocalDate = DateUtils.parseDate(endCheckApplyTime);
            LocalDate orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
            if (ChronoUnit.DAYS.between(endCheckApplyTimelocalDate, orderHodTimelocalDate) == Constant.TWO) {
                return true;
            }
        }
        return false;
    }


    public int getDaysBetween(String resultStatus, String startDateStr, String orderHodTime) {
        if (!resultStatus.contains("ok") && resultStatus.startsWith("3")) {
            return Constant.NEGATIVE_ONE;
        } else if (!resultStatus.contains("ok") && (resultStatus.startsWith("2") || resultStatus.startsWith("1"))) {
            LocalDate ppConfirmTimeDate = DateUtils.parseDate(startDateStr);
            LocalDate orderHodTimeDate = DateUtils.parseDate(orderHodTime);
            return (int) ChronoUnit.DAYS.between(ppConfirmTimeDate, orderHodTimeDate);
        }
        return Constant.ZERO;
    }
}