Forráskód Böngészése

优化按照装货量卸货计算司机分值

donglang 1 napja
szülő
commit
eb93ef6ff2

+ 4 - 8
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/DateUtils.java

@@ -869,7 +869,7 @@ public class DateUtils extends DateUtil {
     }
 
     /**
-     * 计算两个时间的分钟差值
+     * 计算两个时间的差值
      * @param startTime 开始时间
      * @param endTime 结束时间
      * @return
@@ -880,18 +880,14 @@ public class DateUtils extends DateUtil {
             throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR,
                     "计算时间差失败:,startTime=[" + startTime + "], endTime=[" + endTime + "]");
         }
-
         // 计算时间戳差值(毫秒)
         long diffMillis = endTime.getTime() - startTime.getTime();
-
-        long diffMinutes = TimeUnit.MILLISECONDS.toMinutes(diffMillis);
-
         // 时间顺序异常提醒(结束时间早于开始时间)
-        if (diffMinutes < 0) {
+        if (diffMillis < 0) {
             throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR,
-                    "时间顺序异常,结束时间早于开始时间,startTime=[" + startTime + "], endTime=[" + endTime + "], 差值:[" + diffMinutes + "]分钟");
+                    "时间顺序异常,结束时间早于开始时间,startTime=[" + startTime + "], endTime=[" + endTime + "], 差值:[" + diffMillis + "]毫秒");
         }
-        return diffMinutes;
+        return diffMillis/1000;
     }
 
 

+ 0 - 25
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/AbstractWaybillOrderHandler.java

@@ -315,31 +315,6 @@ public abstract class AbstractWaybillOrderHandler<T extends WaybillOrderProcessP
         return waybillOrderNodeList;
     }
 
-    /**
-     * 给连续的N次的节点数据打标
-     */
-    protected void updateNode(KwtWaybillOrder waybillOrder, List<Long> nodeIds, Integer continuousOnTimes, Integer continuousOnTimeScore) {
-        if (CollectionUtils.isEmpty(nodeIds)) {
-            return;
-        }
-        List<KwtWaybillOrderNode> nodes = waybillOrderNodeRepository.queryContinuousNodesByIds(nodeIds);
-
-        Set<Long> wOrderIds = nodes.stream()
-                .map(KwtWaybillOrderNode::getWOrderId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-
-        KwtWaybillOrderNode updateEntity = new KwtWaybillOrderNode();
-        updateEntity.setContinuous(1);
-        LambdaQueryWrapper<KwtWaybillOrderNode> updateWrapper = new LambdaQueryWrapper<KwtWaybillOrderNode>()
-                .eq(KwtWaybillOrderNode::getDriverId, waybillOrder.getDriverId())
-                .in(KwtWaybillOrderNode::getWOrderId, wOrderIds)
-                .eq(KwtWaybillOrderNode::getOrderStatus, CarWaybillV1Enum.REFUSE_TRAFFIC.getCode());
-        waybillOrderNodeRepository.update(updateEntity, updateWrapper);
-        log.info("司机{}最新{}条节点全部未超时,加分:{},涉及运单ID:{}", waybillOrder.getDriverId(), continuousOnTimes, continuousOnTimeScore, wOrderIds);
-    }
-
-
     /**
      * 修改司机评分
      * @param supeEntId

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

@@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
 import java.math.BigDecimal;
 import java.util.Date;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Author: donglang
@@ -167,9 +168,9 @@ public class CancelHandler extends AbstractWaybillOrderHandler<WaybillOrderCance
         KwtWaybillOrderNode cancelNode = getNodesByOrderId(waybillOrder.getId(), CarWaybillV1Enum.CANCELLED.getCode());
         Date cancelNodeTime = cancelNode.getCreateTime();
 
-        // 计算两个时间的分钟
+        // 计算两个时间的
         Long timeDiffMinutes = DateUtils.calculateTimeDiffMinutes(takingOrderTime, cancelNodeTime);
-        if (timeDiffMinutes > cancelOrderMinutes.longValue()) {
+        if (timeDiffMinutes > TimeUnit.MINUTES.toSeconds(cancelOrderMinutes)) {
             log.info("【司机违规取消运单】超时!司机违规取消运单分钟数限制:" + cancelOrderMinutes + "分钟,实际:" + timeDiffMinutes + "分钟");
             //1、更新司机分数(减分)
             cancelOrderScore = -Math.abs(cancelOrderScore);

+ 28 - 3
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/ComeIntoHandler.java

@@ -7,6 +7,7 @@ import com.sckw.core.common.enums.enums.ErrorCodeEnum;
 import com.sckw.core.exception.BusinessPlatfromException;
 import com.sckw.core.model.enums.AddressTypeEnum;
 import com.sckw.core.model.enums.CarWaybillV1Enum;
+import com.sckw.core.utils.CollectionUtils;
 import com.sckw.core.utils.DateUtils;
 import com.sckw.fleet.api.model.vo.DriverConductRulesVO;
 import com.sckw.fleet.api.model.vo.RTruckVo;
@@ -24,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -195,7 +197,7 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
         }
         if (allOnTime && nodeIds.size() == continuousOnTimeArriveTimes) {
             //1. 给连续的N次节点数据打标
-            updateNode(waybillOrder, nodeIds, continuousOnTimeArriveTimes, continuousOnTimeScore);
+            updateNode(waybillOrder, nodeIds, continuousOnTimeScore);
 
             //2 .更新司机分数(加分)
             updateDriverScore(supEntId, waybillOrder.getEntId(), waybillOrder.getDriverId(), continuousOnTimeScore, "司机连续按时到场");
@@ -205,7 +207,30 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
         } else {
             log.info("司机{}最近{}次中存在超时,未加分", waybillOrder.getDriverId(), continuousOnTimeArriveTimes);
         }
+    }
+
+    /**
+     * 给连续的N次的节点数据打标
+     */
+    protected void updateNode(KwtWaybillOrder waybillOrder, List<Long> nodeIds, Integer continuousOnTimeScore) {
+        if (CollectionUtils.isEmpty(nodeIds)) {
+            return;
+        }
+        List<KwtWaybillOrderNode> nodes = waybillOrderNodeRepository.queryContinuousNodesByIds(nodeIds);
+
+        Set<Long> wOrderIds = nodes.stream()
+                .map(KwtWaybillOrderNode::getWOrderId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
 
+        KwtWaybillOrderNode updateEntity = new KwtWaybillOrderNode();
+        updateEntity.setContinuous(1);
+        LambdaQueryWrapper<KwtWaybillOrderNode> updateWrapper = new LambdaQueryWrapper<KwtWaybillOrderNode>()
+                .eq(KwtWaybillOrderNode::getDriverId, waybillOrder.getDriverId())
+                .in(KwtWaybillOrderNode::getWOrderId, wOrderIds)
+                .eq(KwtWaybillOrderNode::getOrderStatus, CarWaybillV1Enum.REFUSE_TRAFFIC.getCode());
+        waybillOrderNodeRepository.update(updateEntity, updateWrapper);
+        log.info("司机{}连续执行运单,加分:{},涉及运单ID:{}", waybillOrder.getDriverId(), continuousOnTimeScore, wOrderIds);
     }
 
     /**
@@ -254,10 +279,10 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
         KwtWaybillOrderNode comeIntoNode = getNodesByOrderId(wOrderId, CarWaybillV1Enum.REFUSE_TRAFFIC.getCode());
         Date comeIntoTime = comeIntoNode.getCreateTime() != null ? comeIntoNode.getCreateTime() : null;
 
-        // 计算两个时间的分钟差
+        // 计算两个时间的秒差值
         Long timeDiffMinutes = DateUtils.calculateTimeDiffMinutes(takingOrderTime, comeIntoTime);
         //超时
-        if (timeDiffMinutes > driverTimeout.longValue()) {
+        if (timeDiffMinutes > TimeUnit.MINUTES.toSeconds(driverTimeout)) {
             log.info("司机到场耗时超时!司机超时限制:" + driverTimeout + "分钟,实际:" + timeDiffMinutes + "分钟");
             return true;
         }

+ 93 - 95
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/UnloadingHandler.java

@@ -1,6 +1,8 @@
 package com.sckw.transport.handler;
 
 
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.sckw.core.common.enums.enums.ErrorCodeEnum;
 import com.sckw.core.exception.BusinessPlatfromException;
 import com.sckw.core.model.constant.Global;
@@ -26,6 +28,7 @@ import org.springframework.stereotype.Service;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -279,18 +282,15 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
 
     @Override
     protected void calculateAutoDispatchScore(WaybillOrderUnloadParam param, KwtWaybillOrder waybillOrder) {
-        //查询运单装卸货地址
-        List<KwtWaybillOrderAddress> addressList = waybillOrderAddressRepository.queryByWOrderId(waybillOrder.getId());
-        if (CollectionUtils.isEmpty(addressList)) {
-            log.info("物流运单无装卸货地址信息,运单id:{}", waybillOrder.getId());
-            throw new BusinessPlatfromException(ErrorCodeEnum.LOGISTICS_ORDER_NOT_ADDRESS, "物流订单无装卸货地址信息");
-        }
-        Map<Integer, KwtWaybillOrderAddress> addressMap = addressList.stream()
-                .filter(addr -> addr.getAddressType() != null)
-                .collect(Collectors.toMap(KwtWaybillOrderAddress::getAddressType, Function.identity(), (x,y) ->x));
+        //查询物流订单
+        KwtLogisticsOrder logisticsOrder = logisticsOrderRepository.queryByLogisticsOrderId(waybillOrder.getLOrderId());
+        //供应商
+        Long supEntId = getSupplierId(waybillOrder);
+        // 获取司机行为规则配置
+        DriverConductRulesVO driverRulesVO = getDriverConductRulesByEntId(supEntId);
 
         //1. 校验司机是否虚假卸货
-        checkFakeUnloadDistance(waybillOrder, addressMap);
+        checkFakeUnloadDistance(waybillOrder, driverRulesVO);
 
         //订单若按照装货方式计算:此时整个运单已经结束,计算运单总耗时。如按照卸货方式计算,运单还未结算,不进行司机加减分
         if (this.targetStatus == null || this.targetStatus != Global.NUMERICAL_ONE) {
@@ -298,11 +298,11 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
             return;
         }
 
-        //2. 校验司机卸货严重超时(运单完成)
-        checkWaybillCompletionTimeout(waybillOrder, addressMap);
+        //2. 校验司机运单完成是否超时
+        checkWaybillCompletionTimeout(waybillOrder, logisticsOrder, driverRulesVO);
 
         //3. 校验司机连续准时卸货
-        checkContinuousUnload(waybillOrder, addressMap);
+        checkContinuousUnload(waybillOrder, logisticsOrder, driverRulesVO);
     }
 
 
@@ -312,20 +312,27 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
      * @return
      */
     @NotNull
-    private void checkFakeUnloadDistance(KwtWaybillOrder waybillOrder, Map<Integer, KwtWaybillOrderAddress> addressMap) {
+    private void checkFakeUnloadDistance(KwtWaybillOrder waybillOrder, DriverConductRulesVO driverRulesVO) {
         log.info("校验司机是否虚假卸货:waybillOrderId:{}", waybillOrder.getId());
-        //供应商
-        Long supEntId = getSupplierId(waybillOrder);
-        // 获取司机行为规则配置
-        DriverConductRulesVO driverRulesVO = getDriverConductRulesByEntId(supEntId);
         //虚假卸货分数
         Integer fakeUnloadScore = driverRulesVO.getFakeUnloadScore();
         //虚假卸货偏离距离
         Integer distance = driverRulesVO.getFakeUnloadDistance();
         if (fakeUnloadScore <= 0 || distance <= 0) {
-            log.warn("【虚假卸货】企业{}的虚假卸货配置分数/偏差距离异常,运单ID:{}", supEntId, waybillOrder.getId());
+            log.warn("【虚假卸货】企业{}的虚假卸货配置分数/偏差距离异常,运单ID:{}", driverRulesVO.getEntId(), waybillOrder.getId());
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "【虚假卸货】配置分数/偏差距离需大于0!");
         }
+
+        //查询运单装卸货地址
+        List<KwtWaybillOrderAddress> addressList = waybillOrderAddressRepository.queryByWOrderId(waybillOrder.getId());
+        if (CollectionUtils.isEmpty(addressList)) {
+            log.info("物流运单无装卸货地址信息,运单id:{}", waybillOrder.getId());
+            throw new BusinessPlatfromException(ErrorCodeEnum.LOGISTICS_ORDER_NOT_ADDRESS, "物流订单无装卸货地址信息");
+        }
+        Map<Integer, KwtWaybillOrderAddress> addressMap = addressList.stream()
+                .filter(addr -> addr.getAddressType() != null)
+                .collect(Collectors.toMap(KwtWaybillOrderAddress::getAddressType, Function.identity(), (x,y) ->x));
+
         //运单应卸货地址
         KwtWaybillOrderAddress takeAddress = addressMap.getOrDefault(AddressTypeEnum.TAKE.getCode(), new KwtWaybillOrderAddress());
         //实际卸货地址
@@ -349,37 +356,35 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
             log.info("【虚假卸货】运单ID={},卸货地址偏差={}KM",waybillOrder.getId(), distanceKm);
             //1、更新司机分数(减分)
             fakeUnloadScore = -Math.abs(fakeUnloadScore);
-            updateDriverScore(supEntId, waybillOrder.getEntId(), waybillOrder.getDriverId(), fakeUnloadScore, "虚假卸货");
+            updateDriverScore(driverRulesVO.getEntId(), waybillOrder.getEntId(), waybillOrder.getDriverId(), fakeUnloadScore, "虚假卸货");
             //2、更新企业分数(减分)
-            updateLogEntScore(waybillOrder, supEntId, fakeUnloadScore, "虚假卸货");
+            updateLogEntScore(waybillOrder, driverRulesVO.getEntId(), fakeUnloadScore, "虚假卸货");
         }
     }
 
     /**
      * 校验司机运单完成是否超时
      * @param waybillOrder 运单
-     * @param addressMap  运单地址
+     * @param logisticsOrder  物流订单
      */
-    protected void checkWaybillCompletionTimeout(KwtWaybillOrder waybillOrder, Map<Integer, KwtWaybillOrderAddress> addressMap) {
-        Long supEntId = getSupplierId(waybillOrder);
-        //查询司机行为规则配置
-        DriverConductRulesVO rulesVO = getDriverConductRulesByEntId(supEntId);
+    protected void checkWaybillCompletionTimeout(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, DriverConductRulesVO driverRulesVO) {
         //严重超时倍数
-        BigDecimal timeoutMultiple = rulesVO.getUnloadSeriousTimeoutMultiple();
+        BigDecimal timeoutMultiple = driverRulesVO.getUnloadSeriousTimeoutMultiple();
         //严重超时分数
-        Integer timeoutScore = rulesVO.getUnloadSeriousTimeoutScore();
+        Integer timeoutScore = driverRulesVO.getUnloadSeriousTimeoutScore();
         if (timeoutMultiple == null || timeoutMultiple.compareTo(BigDecimal.ZERO) <= 0 || timeoutScore <= 0) {
-            log.warn("【卸货严重超时】扣分失败,企业{}的司机卸货严重超时倍数/分数配置为空,运单ID:{}", supEntId, waybillOrder.getId());
+            log.warn("【卸货严重超时】扣分失败,企业{}的司机卸货严重超时倍数/分数配置为空,运单ID:{}", driverRulesVO.getEntId(), waybillOrder.getId());
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "【卸货严重超时】配置严重超时倍数/分数需大于0!");
         }
         //校验是否超时
-        Boolean timeOut = isTimeOut(supEntId, waybillOrder, addressMap, timeoutMultiple);
+        Boolean timeOut = isTimeOut(waybillOrder, logisticsOrder, driverRulesVO.getEntId(), timeoutMultiple);
         if (timeOut) {
             //1、更新司机分数(减分)
             timeoutScore = -Math.abs(timeoutScore);
-            updateDriverScore(supEntId, waybillOrder.getEntId(), waybillOrder.getDriverId(), timeoutScore, "卸货严重超时");
+            updateDriverScore(driverRulesVO.getEntId(), waybillOrder.getEntId(), waybillOrder.getDriverId(), timeoutScore, "卸货严重超时");
+
             //2、更新企业分数(减分)
-            updateLogEntScore(waybillOrder, supEntId, timeoutScore, "卸货严重超时");
+            updateLogEntScore(waybillOrder, driverRulesVO.getEntId(), timeoutScore, "卸货严重超时");
         }
 
     }
@@ -387,14 +392,14 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
     /**
      * 校验司机运单完成是否超时
      * @param waybillOrder 运单
-     * @param addressMap  运单地址
+     * @param supEntId  供应商企业id
      */
-    protected Boolean isTimeOut(Long supEntId, KwtWaybillOrder waybillOrder, Map<Integer, KwtWaybillOrderAddress> addressMap, BigDecimal timeoutMultiple) {
+    protected Boolean isTimeOut(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, Long supEntId, BigDecimal timeoutMultiple) {
         log.info("校验司机运单完成是否超时:运单ID:{}", waybillOrder.getId());
-        //运单总耗时
+        //运单总耗时(秒)
         Long orderTotalTimes = calOrderTotalTimes(waybillOrder);
-        //平台配置的单趟总耗时
-        Integer singleTripTotalTimes = calSingleTripTotalTimes(supEntId, waybillOrder, addressMap);
+        //平台配置的单趟总耗时(秒)
+        Long singleTripTotalTimes = calSingleTripTotalTimes(waybillOrder,logisticsOrder, supEntId);
         //计算超时阈值
         BigDecimal threshold = timeoutMultiple.compareTo(BigDecimal.ZERO) == 0 ?
                 new BigDecimal(singleTripTotalTimes) : timeoutMultiple.multiply(new BigDecimal(singleTripTotalTimes));
@@ -418,7 +423,7 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
         //司机完成运单时间
         KwtWaybillOrderNode overOrderNodes = getNodesByOrderId(waybillOrder.getId(), CarWaybillV1Enum.COMPLETED.getCode());
         Date overOrderTime = overOrderNodes.getCreateTime();
-        //运单总耗时(分钟
+        //运单总耗时(
         Long orderTotalTimes = DateUtils.calculateTimeDiffMinutes(takingOrderTime, overOrderTime);
         log.info("司机完成运单总耗时:{}", orderTotalTimes);
         return orderTotalTimes;
@@ -427,10 +432,10 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
     /**
      * 计算平台配置的运单单趟总耗时
      * @param waybillOrder
-     * @param addressMap
+     * @param logisticsOrder
      * @return
      */
-    private Integer calSingleTripTotalTimes(Long supEntId, KwtWaybillOrder waybillOrder, Map<Integer, KwtWaybillOrderAddress> addressMap) {
+    private Long calSingleTripTotalTimes(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, Long supEntId) {
         // 获取自动派单系数配置(单趟耗时 = 装货时间 + 卸货时间 + 运输时间 + 返回时间)
         TruckDispatchCoefficientVO truckDispatchVO = getAutoTruckDispatchByEntId(supEntId);
         //装货时长
@@ -444,38 +449,24 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
                     supEntId, vehicleLoadingHours, vehicleUnloadingHours, vehicleAvgSpeed, waybillOrder.getId());
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "司机配置的装货时长/卸货时长/平均行驶速度需要大于0!");
         }
-        //查询运单装卸货地址
-        KwtWaybillOrderAddress shipmentAddress = addressMap.getOrDefault(AddressTypeEnum.SHIPMENT.getCode(), new KwtWaybillOrderAddress());
-        KwtWaybillOrderAddress takeAddress = addressMap.getOrDefault(AddressTypeEnum.TAKE.getCode(), new KwtWaybillOrderAddress());
-
         //应卸货地与实际卸货地之间距离
-        double twoPlaceDistanceKm = com.sckw.core.utils.LocUtils.calculateDistanceByAmap(
-                Optional.ofNullable(takeAddress.getLng()).map(String::valueOf).orElse(null),
-                Optional.ofNullable(takeAddress.getLat()).map(String::valueOf).orElse(null),
-                Optional.ofNullable(shipmentAddress.getLng()).map(String::valueOf).orElse(null),
-                Optional.ofNullable(shipmentAddress.getLat()).map(String::valueOf).orElse(null));
-        // 如果高德API调用失败,使用原始方法作为备选
-        if (twoPlaceDistanceKm == -1) {
-            twoPlaceDistanceKm = DistanceUtils.calculateDistance(
-                    Optional.ofNullable(takeAddress.getLng()).map(Double::valueOf).orElse(null),
-                    Optional.ofNullable(takeAddress.getLat()).map(Double::valueOf).orElse(null),
-                    Optional.ofNullable(shipmentAddress.getLng()).map(Double::valueOf).orElse(null),
-                    Optional.ofNullable(shipmentAddress.getLat()).map(Double::valueOf).orElse(null));
-        }
-        //运输时间/返回时间(小时) = 两地距离除以平均行驶速度
-        if (twoPlaceDistanceKm == 0.0 || Double.isNaN(twoPlaceDistanceKm)) {
+        String distance = logisticsOrder.getDistance();
+        if (StringUtils.isBlank(distance)) {
             throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "物流运单装货地址有误!");
         }
-        BigDecimal bdDividend = BigDecimal.valueOf(twoPlaceDistanceKm);
+        BigDecimal bdDividend = new BigDecimal(distance);
+
         BigDecimal bdDivisor = BigDecimal.valueOf(vehicleAvgSpeed);
-        //运输时间小时
+        //运输时间(小时) = 两地距离/平均行驶速度
         BigDecimal transportTimeHours = bdDividend.divide(bdDivisor, 4, RoundingMode.HALF_UP);
-        //运输时间分钟取整
-        Integer transportTimeMinutes = transportTimeHours.multiply(BigDecimal.valueOf(60)).setScale(0, RoundingMode.HALF_UP).intValue();
+        //运输时间(秒)
+        long transportTimeMillis = transportTimeHours.multiply(BigDecimal.valueOf(3600))
+                .setScale(0, RoundingMode.HALF_UP).longValue();
+
         //往返时间=运输时间
-        Integer returnTimeMinutes = transportTimeMinutes;
-        //单趟总耗时
-        Integer singleTripTotalTimes = vehicleLoadingHours + vehicleUnloadingHours + transportTimeMinutes + returnTimeMinutes;
+        long returnTimeMinutes = transportTimeMillis;
+        //单趟总耗时(秒)
+        Long singleTripTotalTimes = TimeUnit.MINUTES.toSeconds(vehicleLoadingHours) + TimeUnit.MINUTES.toSeconds(vehicleUnloadingHours) + transportTimeMillis + returnTimeMinutes;
         log.info("平台配置的运单单趟总耗时:{}", singleTripTotalTimes);
         return singleTripTotalTimes;
 
@@ -485,59 +476,66 @@ public class UnloadingHandler extends AbstractWaybillOrderHandler<WaybillOrderUn
      * 校验连续准时卸货
      * @param waybillOrder
      */
-    private void checkContinuousUnload(KwtWaybillOrder waybillOrder, Map<Integer, KwtWaybillOrderAddress> addressMap) {
-        Long supEntId = getSupplierId(waybillOrder);
-        // 获取司机行为规则配置(连续准时卸货次数)
-        DriverConductRulesVO driverRulesVO = getDriverConductRulesByEntId(supEntId);
+    private void checkContinuousUnload(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder,  DriverConductRulesVO driverRulesVO) {
         //连续卸货次数
         Integer continuousOnTimes = driverRulesVO.getContinuousOnTimeUnloadTimes();
         //连续卸货分数
         Integer continuousUnloadScore = driverRulesVO.getContinuousOnTimeUnloadScore();
         if (continuousOnTimes <= 0 || continuousUnloadScore <= 0) {
-            log.warn("【连续准时卸货】该司机无需加分,企业{}的连续按时到场配置次数/分数异常,运单ID:{}", supEntId, waybillOrder.getId());
+            log.warn("【连续准时卸货】该司机无需加分,企业{}的连续按时到场配置次数/分数异常,运单ID:{}", driverRulesVO.getEntId(), waybillOrder.getId());
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "【连续准时卸货】配置次数/分数需大于0!");
         }
 
         //查询该司机连续准时卸货的节点数据
         List<KwtWaybillOrderNode> waybillOrderNodeList = getWaybillOrderNodesByStatus(waybillOrder, continuousOnTimes, CarWaybillV1Enum.COMPLETED);
-        if (waybillOrderNodeList == null)  {
+        //取continuousOnTimes条节点数据
+        List<KwtWaybillOrderNode> fileterWaybillOrderNodeList = waybillOrderNodeList.stream().sorted(Comparator.comparing(KwtWaybillOrderNode::getCreateTime).reversed())
+                .limit(continuousOnTimes).collect(Collectors.toList());
+        if (fileterWaybillOrderNodeList.size() != continuousOnTimes) {
+            log.info("司机{}最近连续准时卸货记录不足{}条,当前:{}", waybillOrder.getDriverId(), continuousOnTimes, waybillOrderNodeList.size());
             return;
         }
-        //记录连续卸货次数
-        int continuousCount = 0;
-        List<Long> qualifiedNodeIds = new ArrayList<>();
+
+        //记录连续准时卸货
         List<Long> nodeIds = new ArrayList<>();
+        boolean allOnTime = true;
         for (KwtWaybillOrderNode orderNode : waybillOrderNodeList) {
+            if (orderNode.getContinuous() == 1) {
+                break;
+            }
+            //计算每次运单是否准时卸货
             KwtWaybillOrder wOrder = getWaybillOrder(orderNode.getWOrderId());
-            Boolean timeOut = isTimeOut(supEntId, wOrder, addressMap, BigDecimal.ZERO);
+            Boolean timeOut = isTimeOut(wOrder, logisticsOrder, driverRulesVO.getEntId(), BigDecimal.ZERO);
             if (timeOut) {
                 log.info("司机{}存在超时情况,运单id:{}", orderNode.getDriverId(), orderNode.getWOrderId());
-                return;
-            }
-            continuousCount++;
-            qualifiedNodeIds.add(orderNode.getId());
-            // 达到10次,返回最新的10条ID
-            if (continuousCount >= continuousOnTimes) {
-                // 截断前10条
-                nodeIds = qualifiedNodeIds.subList(0, continuousOnTimes);
+                allOnTime = false;
                 break;
             }
+            nodeIds.add(orderNode.getId());
         }
         // 校验是否达到次数
-        if (continuousCount < continuousOnTimes) {
-            log.info("司机{}连续准时卸货次数{},未达到配置阈值{}", waybillOrder.getDriverId(), continuousCount, continuousOnTimes);
-            return;
-        }
-        //1. 给连续的10次节点数据打标
-        updateNode(waybillOrder, nodeIds, continuousCount, continuousUnloadScore);
-
-        //2 .更新司机分数(加分)
-        updateDriverScore(supEntId, waybillOrder.getEntId(), waybillOrder.getDriverId(), continuousUnloadScore, "连续准时卸货");
+        if (allOnTime && nodeIds.size() == continuousOnTimes) {
+            //1. 给连续的N次节点数据打标
+            updateNode(waybillOrder, nodeIds, continuousUnloadScore);
 
-        //3. 更新企业分数(加分)
-        updateLogEntScore(waybillOrder, supEntId, continuousUnloadScore, "连续准时卸货");
+            //2 .更新司机分数(加分)
+            updateDriverScore(driverRulesVO.getEntId(), waybillOrder.getEntId(), waybillOrder.getDriverId(), continuousUnloadScore, "连续准时卸货");
 
+            //3. 更新企业分数(加分)
+            updateLogEntScore(waybillOrder, driverRulesVO.getEntId(), continuousUnloadScore, "连续准时卸货");
+        }
     }
 
+    /**
+     * 给连续的N次的节点数据打标
+     */
+    protected void updateNode(KwtWaybillOrder waybillOrder, List<Long> nodeIds, Integer continuousOnTimeScore) {
+        KwtWaybillOrderNode updateEntity = new KwtWaybillOrderNode();
+        updateEntity.setContinuous(1);
+        LambdaQueryWrapper<KwtWaybillOrderNode> updateWrapper = new LambdaQueryWrapper<KwtWaybillOrderNode>()
+                .in(KwtWaybillOrderNode::getId, nodeIds);
+        waybillOrderNodeRepository.update(updateEntity, updateWrapper);
+        log.info("司机{}连续准时卸货,加分:{},节点ID:{}", waybillOrder.getDriverId(), continuousOnTimeScore, JSON.toJSONString(nodeIds));
+    }
 
 }

+ 26 - 35
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java

@@ -4657,10 +4657,10 @@ public class KwtWaybillOrderV1Service {
             checkCompletionTimeout(billOrder, logisticsOrder, driverRulesVO);
 
             //3. 校验司机连续准时卸货(审核通过)
-            checkContinuousUnload(billOrder, logisticsOrder, supEntId);
+            checkContinuousUnload(billOrder, logisticsOrder, driverRulesVO);
 
             //4. 校验司机连续准确填写卸货信息(审核通过)
-            checkContinuousPass(billOrder, supEntId);
+            checkContinuousPass(billOrder, driverRulesVO);
         } catch (Exception e) {
             log.info("司机分数计算失败!", e);
         }
@@ -4709,7 +4709,7 @@ public class KwtWaybillOrderV1Service {
         }
 
         //校验司机运单完成是否超时
-        Boolean isTimeOut = isTimeOut(waybillOrder, logisticsOrder, timeoutMultiple);
+        Boolean isTimeOut = isTimeOut(waybillOrder, logisticsOrder, driverRulesVO.getEntId(), timeoutMultiple);
         if (isTimeOut) {
             //1、更新司机分数(减分)
             timeoutScore = -Math.abs(timeoutScore);
@@ -4725,12 +4725,12 @@ public class KwtWaybillOrderV1Service {
      * @param waybillOrder 运单
      * @param logisticsOrder  运单地址
      */
-    protected Boolean isTimeOut(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, BigDecimal timeoutMultiple) {
+    protected Boolean isTimeOut(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, Long supeEntId, BigDecimal timeoutMultiple) {
         log.info("校验司机运单完成是否超时:运单ID:{}", waybillOrder.getId());
-        //运单总耗时
+        //运单总耗时(秒)
         Long orderTotalTimes = calOrderTotalTimes(waybillOrder);
-        //平台配置的单趟总耗时
-        Integer singleTripTotalTimes = calSingleTripTotalTimes(waybillOrder, logisticsOrder);
+        //平台配置的单趟总耗时(秒)
+        Long singleTripTotalTimes = calSingleTripTotalTimes(waybillOrder, logisticsOrder, supeEntId);
         //计算超时阈值
         BigDecimal threshold = timeoutMultiple.compareTo(BigDecimal.ZERO) == 0 ?
                 new BigDecimal(singleTripTotalTimes) : timeoutMultiple.multiply(new BigDecimal(singleTripTotalTimes));
@@ -4760,7 +4760,7 @@ public class KwtWaybillOrderV1Service {
             throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_NODE_NOT_EXIST, "未找到关联的运单节点数据!");
         }
         Date overOrderTime = overOrderNodes.getCreateTime() != null ? overOrderNodes.getCreateTime() : null;
-        //运单总耗时(分钟
+        //运单总耗时(
         Long orderTotalTimes = DateUtils.calculateTimeDiffMinutes(takingOrderTime, overOrderTime);
         log.info("司机完成运单总耗时:{}", orderTotalTimes);
         return orderTotalTimes;
@@ -4772,9 +4772,9 @@ public class KwtWaybillOrderV1Service {
      * @param logisticsOrder
      * @return
      */
-    private Integer calSingleTripTotalTimes(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder) {
+    private Long calSingleTripTotalTimes(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, Long supeEntId) {
         // 获取自动派单系数配置(单趟耗时 = 装货时间 + 卸货时间 + 运输时间 + 返回时间)
-        TruckDispatchCoefficientVO truckDispatchVO = remoteFleetService.findAutoTruckDispatchByEntId(waybillOrder.getEntId());
+        TruckDispatchCoefficientVO truckDispatchVO = remoteFleetService.findAutoTruckDispatchByEntId(supeEntId);
         if (truckDispatchVO == null) {
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "未找到自动派车系数!");
         }
@@ -4799,12 +4799,13 @@ public class KwtWaybillOrderV1Service {
         BigDecimal bdDivisor = BigDecimal.valueOf(vehicleAvgSpeed);
         //运输时间小时
         BigDecimal transportTimeHours = bdDividend.divide(bdDivisor, 4, RoundingMode.HALF_UP);
-        //运输时间分钟取整
-        Integer transportTimeMinutes = transportTimeHours.multiply(BigDecimal.valueOf(60)).setScale(0, RoundingMode.HALF_UP).intValue();
+        //运输时间(秒)
+        long transportTimeMillis = transportTimeHours.multiply(BigDecimal.valueOf(3600))
+                .setScale(0, RoundingMode.HALF_UP).longValue();
         //往返时间=运输时间
-        Integer returnTimeMinutes = transportTimeMinutes;
+        long returnTimeMillis = transportTimeMillis;
         //单趟总耗时
-        Integer singleTripTotalTimes = vehicleLoadingHours + vehicleUnloadingHours + transportTimeMinutes + returnTimeMinutes;
+        Long singleTripTotalTimes = TimeUnit.MINUTES.toSeconds(vehicleLoadingHours) + TimeUnit.MINUTES.toSeconds(vehicleUnloadingHours) + transportTimeMillis + returnTimeMillis;
         log.info("平台配置的运单单趟总耗时:{}", singleTripTotalTimes);
         return singleTripTotalTimes;
 
@@ -4814,18 +4815,13 @@ public class KwtWaybillOrderV1Service {
      * 校验司机连续准时卸货
      * @param waybillOrder
      */
-    private void checkContinuousUnload(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, Long supEntId) {
-        // 获取司机行为规则配置(连续准时卸货次数)
-         DriverConductRulesVO driverRulesVO = remoteFleetService.findDriverConductRulesByEntId(supEntId);
-        if (driverRulesVO == null) {
-            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "未找到司机行为规则数据!");
-        }
+    private void checkContinuousUnload(KwtWaybillOrder waybillOrder, KwtLogisticsOrder logisticsOrder, DriverConductRulesVO driverRulesVO) {
         //连续卸货次数
         Integer continuousOnTimes = driverRulesVO.getContinuousOnTimeUnloadTimes();
         //连续卸货加分分数
         Integer continuousScore = driverRulesVO.getContinuousOnTimeUnloadScore();
         if (continuousOnTimes <= 0 || continuousScore <= 0) {
-            log.warn("【连续准时卸货】获取连续准时卸货数据失败:企业{}的连续按时到场次数/分数配置异常,运单ID:{}", supEntId, waybillOrder.getId());
+            log.warn("【连续准时卸货】获取连续准时卸货数据失败:企业{}的连续按时到场次数/分数配置异常,运单ID:{}", driverRulesVO.getEntId(), waybillOrder.getId());
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "【连续准时卸货】配置的次数/分数需大于0!");
         }
 
@@ -4844,7 +4840,7 @@ public class KwtWaybillOrderV1Service {
             }
             //计算每次运单是否准时卸货
             KwtWaybillOrder wOrder = kwtWaybillOrderRepository.queryByBillOrderId(orderNode.getWOrderId());
-            if (isTimeOut(wOrder, logisticsOrder, BigDecimal.ZERO)) {
+            if (isTimeOut(wOrder, logisticsOrder, driverRulesVO.getEntId(), BigDecimal.ZERO)) {
                 log.info("司机{}存在超时情况,运单id:{}", orderNode.getDriverId(), orderNode.getWOrderId());
                 allOnTime = false;
                 break;
@@ -4856,10 +4852,10 @@ public class KwtWaybillOrderV1Service {
             updateNode(waybillOrder, nodeIds, continuousScore);
 
             //2 .更新司机分数(加分)
-            updateDriverScore(supEntId, waybillOrder.getEntId(), waybillOrder.getDriverId(), continuousScore, "连续准时卸货");
+            updateDriverScore(driverRulesVO.getEntId(), waybillOrder.getEntId(), waybillOrder.getDriverId(), continuousScore, "连续准时卸货");
 
             //3. 更新企业分数(加分)
-            updateLogEntScore(waybillOrder, supEntId, continuousScore, "连续准时卸货");
+            updateLogEntScore(waybillOrder, driverRulesVO.getEntId(), continuousScore, "连续准时卸货");
         }
     }
 
@@ -4867,18 +4863,13 @@ public class KwtWaybillOrderV1Service {
      * 校验司机连续准确填写卸货信息
      * @param waybillOrder
      */
-    private void checkContinuousPass(KwtWaybillOrder waybillOrder, Long supEntId) {
-        // 获取司机行为规则配置(连续准确填写卸货信息次数)
-        DriverConductRulesVO driverRulesVO = remoteFleetService.findDriverConductRulesByEntId(supEntId);
-        if (driverRulesVO == null) {
-            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "未找到司机行为规则数据!");
-        }
+    private void checkContinuousPass(KwtWaybillOrder waybillOrder, DriverConductRulesVO driverRulesVO) {
         //连续卸货次数
         Integer continuousUnloadTimes = driverRulesVO.getContinuousAccurateUnloadTimes();
         //连续卸货加分分数
         Integer continuousScore = driverRulesVO.getContinuousAccurateUnloadScore();
         if (continuousUnloadTimes <= 0 || continuousScore <= 0) {
-            log.warn("【连续准确填写卸货信息】企业{}的连续准确填写卸货信息配置的次数/分数异常,运单ID:{}", supEntId, waybillOrder.getId());
+            log.warn("【连续准确填写卸货信息】企业{}的连续准确填写卸货信息配置的次数/分数异常,运单ID:{}", driverRulesVO.getEntId(), waybillOrder.getId());
             throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "【连续准确填写卸货信息】配置的次数/分数需大于0!");
         }
 
@@ -4908,10 +4899,10 @@ public class KwtWaybillOrderV1Service {
             updateReviewNode(waybillOrder, nodeIds, continuousScore);
 
             //2 .更新司机分数(加分)
-            updateDriverScore(supEntId, waybillOrder.getEntId(), waybillOrder.getDriverId(), continuousScore, "连续准确填写卸货信息");
+            updateDriverScore(driverRulesVO.getEntId(), waybillOrder.getEntId(), waybillOrder.getDriverId(), continuousScore, "连续准确填写卸货信息");
 
             //3. 更新企业分数(加分)
-            updateLogEntScore(waybillOrder, supEntId, continuousScore, "连续准确填写卸货信息");
+            updateLogEntScore(waybillOrder, driverRulesVO.getEntId(), continuousScore, "连续准确填写卸货信息");
         }
     }
 
@@ -4951,7 +4942,7 @@ public class KwtWaybillOrderV1Service {
         LambdaQueryWrapper<KwtWaybillOrderNode> updateWrapper = new LambdaQueryWrapper<KwtWaybillOrderNode>()
                 .in(KwtWaybillOrderNode::getId, nodeIds);
         kwtWaybillOrderNodeRepository.update(updateEntity, updateWrapper);
-        log.info("司机{}连续执行运单节点,加分:{},节点ID:{}", waybillOrder.getDriverId(), continuousOnTimeScore, JSON.toJSONString(nodeIds));
+        log.info("司机{}连续准时卸货,加分:{},节点ID:{}", waybillOrder.getDriverId(), continuousOnTimeScore, JSON.toJSONString(nodeIds));
     }
 
     /**
@@ -4963,7 +4954,7 @@ public class KwtWaybillOrderV1Service {
         LambdaQueryWrapper<KwtWaybillOrderNode> updateWrapper = new LambdaQueryWrapper<KwtWaybillOrderNode>()
                 .in(KwtWaybillOrderNode::getId, nodeIds);
         kwtWaybillOrderNodeRepository.update(updateEntity, updateWrapper);
-        log.info("司机{}连续执行运单节点,加分:{},节点ID:{}", waybillOrder.getDriverId(), continuousOnTimeScore, JSON.toJSONString(nodeIds));
+        log.info("司机{}连续准确填写卸货信息,加分:{},节点ID:{}", waybillOrder.getDriverId(), continuousOnTimeScore, JSON.toJSONString(nodeIds));
     }
 
     // 查询供应商id

+ 3 - 1
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/task/LogisticsOrderCompletionTask.java

@@ -31,6 +31,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -259,8 +260,9 @@ public class LogisticsOrderCompletionTask {
             //司机超时限制分钟数
             Integer driverTimeout = truckDispatchVO.getDriverTimeoutLimit();
             for (KwtWaybillOrder waybillOrder : waybillOrderList) {
+                //两时间的秒差值
                 Long timeDiffMinutes = DateUtils.calculateTimeDiffMinutes(waybillOrder.getCreateTime(), new Date());
-                if (timeDiffMinutes > driverTimeout.longValue()) {
+                if (timeDiffMinutes > TimeUnit.MINUTES.toSeconds(driverTimeout)) {
                     nearingCompletionOrders.add(waybillOrder);
                 }
             }