Browse Source

新增超时取消运单定时任务

donglang 7 hours ago
parent
commit
b095662899

+ 4 - 2
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/AbstractWaybillOrderHandler.java

@@ -109,8 +109,10 @@ public abstract class AbstractWaybillOrderHandler<T extends WaybillOrderProcessP
         if (param == null) {
             throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "参数不能为空");
         }
-        if (StringUtils.isBlank(param.getLng()) || StringUtils.isBlank(param.getLat())) {
-            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "未获取到定位,请重启app后再次操作");
+        if (!(param instanceof WaybillOrderCancelParam)) {
+            if (StringUtils.isBlank(param.getLng()) || StringUtils.isBlank(param.getLat())) {
+                throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "未获取到定位,请重启app后再次操作");
+            }
         }
         // 非接单流程必须校验运单ID
         if (!(param instanceof OrderCirculateTakingQueryParam) && param.getWaybillOrderId() == null) {

+ 2 - 2
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/CancelHandler.java

@@ -166,7 +166,7 @@ public class CancelHandler extends AbstractWaybillOrderHandler<WaybillOrderCance
             log.warn("【司机违规取消运单】企业{}的司机违规取消运单分钟数/分数异常,运单ID:{}", waybillOrder.getEntId(), waybillOrder.getId());
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "【司机违规取消运单】配置的分钟数/分数需大于0!");
         }
-
+        long cancelOrderInMillis = cancelOrderMinutes * 60 * 1000;
         //司机接单时间
         KwtWaybillOrderNode takingOrderNodes = getNodesByOrderId(waybillOrder.getId(), CarWaybillV1Enum.PENDING_VEHICLE.getCode());
         Date takingOrderTime = takingOrderNodes.getCreateTime() != null ? takingOrderNodes.getCreateTime() : null;
@@ -176,7 +176,7 @@ public class CancelHandler extends AbstractWaybillOrderHandler<WaybillOrderCance
 
         // 计算两个时间的分钟差
         Long timeDiffMinutes = DateUtils.calculateTimeDiffMinutes(takingOrderTime, cancelNodeTime);
-        if (timeDiffMinutes > cancelOrderMinutes.longValue()) {
+        if (timeDiffMinutes > cancelOrderInMillis) {
             log.info("【司机违规取消运单】超时!司机违规取消运单分钟数限制:" + cancelOrderMinutes + "分钟,实际:" + timeDiffMinutes + "分钟");
             //1、更新司机分数(减分)
             cancelOrderScore = -Math.abs(cancelOrderScore);

+ 2 - 1
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/ComeIntoHandler.java

@@ -169,6 +169,7 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
             log.warn("【司机未按时到场】企业{}的司机超时限制配置异常,运单ID:{}", entId,wOrderId);
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "【司机未按时到场】司机超时限制配置需大于0!");
         }
+        long driverTimeoutInMillis = driverTimeout * 60 * 1000;
         //司机接单时间
         KwtWaybillOrderNode takingOrderNodes = getNodesByOrderId(wOrderId, CarWaybillV1Enum.PENDING_VEHICLE.getCode());
         Date takingOrderTime = takingOrderNodes.getCreateTime() != null ? takingOrderNodes.getCreateTime() : null;
@@ -179,7 +180,7 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
         // 计算两个时间的分钟差
         Long timeDiffMinutes = DateUtils.calculateTimeDiffMinutes(takingOrderTime, comeIntoTime);
         //超时
-        if (timeDiffMinutes > driverTimeout.longValue()) {
+        if (timeDiffMinutes > driverTimeoutInMillis) {
             log.info("司机到场耗时超时!司机超时限制:" + driverTimeout + "分钟,实际:" + timeDiffMinutes + "分钟");
             return true;
         }

+ 104 - 2
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/task/LogisticsOrderCompletionTask.java

@@ -2,20 +2,32 @@ package com.sckw.transport.task;
 
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.sckw.contract.api.RemoteContractService;
+import com.sckw.core.common.enums.enums.ErrorCodeEnum;
 import com.sckw.core.exception.BusinessException;
+import com.sckw.core.exception.BusinessPlatfromException;
 import com.sckw.core.model.enums.CarWaybillV1Enum;
 import com.sckw.core.model.enums.LogisticsOrderV1Enum;
+import com.sckw.core.utils.DateUtils;
+import com.sckw.fleet.api.RemoteFleetService;
+import com.sckw.fleet.api.model.vo.TruckDispatchCoefficientVO;
+import com.sckw.transport.handler.CancelHandler;
 import com.sckw.transport.model.KwtLogisticsOrder;
+import com.sckw.transport.model.KwtLogisticsOrderUnit;
+import com.sckw.transport.model.KwtWaybillOrder;
 import com.sckw.transport.model.KwtWaybillOrderSubtask;
-import com.sckw.transport.repository.KwtLogisticsOrderRepository;
-import com.sckw.transport.repository.KwtWaybillOrderSubtaskRepository;
+import com.sckw.transport.model.param.WaybillOrderCancelParam;
+import com.sckw.transport.repository.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -31,6 +43,17 @@ public class LogisticsOrderCompletionTask {
 
     private final KwtLogisticsOrderRepository logisticsOrderRepository;
     private final KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
+    private final KwtWaybillOrderRepository waybillOrderRepository;
+    private final KwtLogisticsOrderContractRepository logisticsOrderContractRepository;
+    private final KwtLogisticsOrderUnitRepository logisticsOrderUnitRepository;
+
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
+    protected RemoteFleetService remoteFleetService;
+
+    @DubboReference(version = "1.0.0", group = "design", check = false)
+    private RemoteContractService remoteContractService;
+
+    private final CancelHandler cancelHandler;
 
     /**
      * 定时任务:每5分钟执行一次
@@ -130,4 +153,83 @@ public class LogisticsOrderCompletionTask {
             throw new BusinessException("物流订单自动完成定时任务执行异常", e);
         }
     }
+
+
+    /**
+     * 定时任务:每2分钟执行一次
+     * cron表达式:0 0/2 * * * ? 表示每2分钟执行一次
+     * 可以根据实际需求调整执行频率
+     */
+    @Scheduled(cron = "${schedule.waybill-order-completion-cron}")
+    public void processWaybillOrder() {
+        log.info("超时取消运单定时任务开始...");
+
+        try {
+            // 查询状态为"已接单"的物流运单
+            List<KwtWaybillOrder> waybillOrderOrders = waybillOrderRepository.list(
+                    new LambdaQueryWrapper<KwtWaybillOrder>()
+                            .eq(KwtWaybillOrder::getStatus, CarWaybillV1Enum.PENDING_VEHICLE.getCode())
+                            .eq(KwtWaybillOrder::getDelFlag, 0)
+            );
+            if (CollectionUtils.isEmpty(waybillOrderOrders)) {
+                log.info("没有状态为'已接单'的物流运单需要处理");
+                return;
+            }
+
+            //运单根据物流订单id分组
+            Map<Long, List<KwtWaybillOrder>> waybillOrderAndLogOrderMap = waybillOrderOrders.stream()
+                    .collect(Collectors.groupingBy(KwtWaybillOrder::getLOrderId));
+
+            //提取物流订单id
+            Set<Long> logisticOrderIds = waybillOrderOrders.stream().map(KwtWaybillOrder::getLOrderId).collect(Collectors.toSet());
+
+            //物流订单和企业映射
+            List<KwtLogisticsOrderUnit> logisticsOrderUnits = logisticsOrderUnitRepository.queryByLOrderIdsAndUnitType(logisticOrderIds, 2);
+            Map<Long, KwtLogisticsOrderUnit> logisticsOrderAndUnitMap = logisticsOrderUnits.stream()
+                    .collect(Collectors.toMap(KwtLogisticsOrderUnit::getLOrderId, Function.identity(), (x, y) -> x));
+            if (MapUtils.isEmpty(logisticsOrderAndUnitMap)) {
+                throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "未找的物流订单和企业映射信息!");
+            }
+
+            //过滤超时的运单
+            List<KwtWaybillOrder> nearingCompletionOrders = new ArrayList<>();
+            for (Map.Entry<Long, List<KwtWaybillOrder>> entry : waybillOrderAndLogOrderMap.entrySet()) {
+                Long logisticOrderId = entry.getKey();
+                //物流运单
+                List<KwtWaybillOrder> waybillOrderList = entry.getValue();
+                //供应商企业信息
+                KwtLogisticsOrderUnit logisticsOrderUnit = logisticsOrderAndUnitMap.get(logisticOrderId);
+                TruckDispatchCoefficientVO truckDispatchVO = remoteFleetService.findAutoTruckDispatchByEntId(logisticsOrderUnit.getEntId());
+                if (truckDispatchVO == null) {
+                    throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "未找到自动派车系数!");
+                }
+                Integer driverTimeout = truckDispatchVO.getDriverTimeoutLimit();
+                long timestampInMillis = driverTimeout * 60 * 1000;
+
+                for (KwtWaybillOrder waybillOrder : waybillOrderList) {
+                    Long timeDiffMinutes = DateUtils.calculateTimeDiffMinutes(waybillOrder.getCreateTime(), new Date());
+                    if (timeDiffMinutes > timestampInMillis) {
+                        nearingCompletionOrders.add(waybillOrder);
+                    }
+                }
+            }
+
+            // 如果没有需要更新的物流运单,则直接返回
+            if (CollectionUtils.isEmpty(nearingCompletionOrders)){
+                log.info("没有需要超时取消运单物流运单");
+                return;
+            }
+
+            for (KwtWaybillOrder nearingCompletionOrder : nearingCompletionOrders) {
+                WaybillOrderCancelParam param = new WaybillOrderCancelParam();
+                param.setLogOrderId(nearingCompletionOrder.getLOrderId());
+                //执行取消接单
+                cancelHandler.handler(param);
+            }
+            log.info("查询到{}条状态为'已接单'的物流运单", nearingCompletionOrders.size());
+        } catch (Exception e) {
+            log.error("超时取消运单定时任务执行异常", e);
+            throw new BusinessException("超时取消运单定时任务执行异常", e);
+        }
+    }
 }