OrderOverTimeEventJob.java 21.2 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;

import static com.order.erp.common.utils.DateUtils.DATE;
import static com.order.erp.common.utils.DateUtils.DATE_TIME;


/**
 * @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 * * * * *")
    //存储的日期都必须为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) {
                if (!redisUtils.hasKey(EmailTemplateEnum.byTemplate(
                        eventEnum.getTemplateId()) + Constant.CROSS_BAR_CHARACTER + orderEventJob.getBaseInfo().getId())) {
                    //转化一下日期格式,为yyyy-MM-dd。
                    OrderBaseInfoVO orderBaseInfoFormat = getDateFormat(orderEventJob.getBaseInfo().getProductionDepartmentConsignTime(), orderEventJob.getBaseInfo().getOrderHodTime());
                    orderEventJob.getBaseInfo().setProductionDepartmentConsignTime(orderBaseInfoFormat.getProductionDepartmentConsignTime());
                    orderEventJob.getBaseInfo().setOrderHodTime(orderBaseInfoFormat.getOrderHodTime());
                    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())) {
                        //转化一下日期格式,为yyyy-MM-dd。
                        OrderBaseInfoVO orderBaseInfoFormat = getDateFormat(orderEventJob.getBaseInfo().getProductionDepartmentConsignTime(), orderEventJob.getBaseInfo().getOrderHodTime());
                        orderEventJob.getBaseInfo().setProductionDepartmentConsignTime(orderBaseInfoFormat.getProductionDepartmentConsignTime());
                        orderEventJob.getBaseInfo().setOrderHodTime(orderBaseInfoFormat.getOrderHodTime());
                        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.FOURTEEN) {
                return true;
            }

        }
        return false;
    }

    private Boolean filterBigSampleEvent(OrderEventJobVO eventJobVO) {
        String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
        String shippmentSampleConfirmResult = eventJobVO.getTrackStageInfo().getShippmentSampleConfirmResult();
        String shippmentSampleConfirmTime = eventJobVO.getTrackStageInfo().getShippmentSampleConfirmTime();
        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) {
        int aitextestDaysBetween=0;
        int sgstestDaysBetween=0;
        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)){
             aitextestDaysBetween = getDaysBetween(aitexTestFinishResult, aitexTestFinishTime, orderHodTime);
        } else if(StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(sgsTestFinishResult) && StringUtils.isNotBlank(sgsTestFinishTime)){
             sgstestDaysBetween = getDaysBetween(sgsTestFinishResult, sgsTestFinishTime, orderHodTime);
        }
            if (aitextestDaysBetween == Constant.THREE || sgstestDaysBetween == Constant.THREE || 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;
    }

    public OrderBaseInfoVO  getDateFormat(String productionDepartmentConsignTime,String orderHodTime){
        String substring = productionDepartmentConsignTime.substring(0, 10);
        String substring1 = orderHodTime.substring(0, 10);
        String productionDepartmentConsignTimeFormat = DateUtils.format(DateUtils.parseDate(substring, DATE), DateUtils.DATE);
        String orderHodTimeFormat = DateUtils.format(DateUtils.parseDate(substring1,DATE), DateUtils.DATE);
        OrderBaseInfoVO orderBaseInfoVO = new OrderBaseInfoVO();
        orderBaseInfoVO.setProductionDepartmentConsignTime(productionDepartmentConsignTimeFormat);
        orderBaseInfoVO.setOrderHodTime(orderHodTimeFormat);
        return orderBaseInfoVO;
    }
}