Explorar o código

Merge branch 'refs/heads/dev_20260131' into dev_20260131_youshen430

# Conflicts:
#	sckw-modules/sckw-contract/src/main/java/com/sckw/contract/controller/KwcPurchaseController.java
#	sckw-modules/sckw-order/src/main/java/com/sckw/order/dao/KwoTradeOrderMapper.java
tangyishan hai 1 mes
pai
achega
ab4825f694
Modificáronse 31 ficheiros con 788 adicións e 50 borrados
  1. 5 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/enums/ForkliftStatusEnum.java
  2. 5 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/enums/GatekeeperStatusEnum.java
  3. 22 0
      sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/dubbo/TransportRemoteStatisticsService.java
  4. 2 2
      sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/model/param/AddLogisticOrderParam.java
  5. 13 0
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/controller/KwcPurchaseController.java
  6. 6 3
      sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/operateService/KwcContractTradeService.java
  7. 0 1
      sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/model/request/DriverAssociatedTruckSaveRequest.java
  8. 12 0
      sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/model/vo/QueryFleetResp.java
  9. 12 0
      sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/model/vo/TruckValidateVo.java
  10. 6 0
      sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/repository/KwfTruckRepository.java
  11. 3 0
      sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/service/KwfFleetService.java
  12. 14 6
      sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/service/KwfTruckService.java
  13. 4 4
      sckw-modules/sckw-fleet/src/main/resources/bootstrap-cxf.yml
  14. 9 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/controller/KwoTradeOrderController.java
  15. 37 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/res/TradeOrderDashboardVO.java
  16. 104 3
      sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderService.java
  17. 51 0
      sckw-modules/sckw-order/src/main/java/com/sckw/order/util/TradeOrderDashboardUtils.java
  18. 55 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/controller/enterpriseApp/AppSalesWayBillController.java
  19. 23 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/dao/KwtLogisticsOrderMapper.java
  20. 133 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/dubbo/TransportStatisticsServiceImpl.java
  21. 22 9
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/CancelHandler.java
  22. 21 11
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/ComeIntoHandler.java
  23. 24 3
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/EmptyLoadLeaveHandler.java
  24. 3 6
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/LoadingHandler.java
  25. 4 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/KwtWaybillOrder.java
  26. 2 2
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/dto/AddLogisticOrderDTO.java
  27. 32 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/SalesWaybillOrderQueryParam.java
  28. 8 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/repository/KwtForkliftWaybillOrderRepository.java
  29. 3 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtLogisticsConsignmentService.java
  30. 109 0
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/app/SalesWaybillOrderService.java
  31. 44 0
      sckw-modules/sckw-transport/src/main/resources/mapper/KwtLogisticsOrderMapper.xml

+ 5 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/enums/ForkliftStatusEnum.java

@@ -29,6 +29,11 @@ public enum ForkliftStatusEnum {
      */
     COMPLETED(10, "已装载"),
 
+    /**
+     * 已取消
+     */
+    CANCEL(99, "已装载"),
+
     ;
 
     private final Integer code;

+ 5 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/enums/GatekeeperStatusEnum.java

@@ -45,6 +45,11 @@ public enum GatekeeperStatusEnum {
     EMPTY_EXITED(25, "空载离场", "空载离场"),
 
 
+    /**
+     * 取消
+     */
+    CANCEL(99, "取消"),
+
     ;
 
     private final Integer code;

+ 22 - 0
sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/dubbo/TransportRemoteStatisticsService.java

@@ -1,5 +1,7 @@
 package com.sckw.transport.api.dubbo;
 
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.List;
 
 /**
@@ -43,4 +45,24 @@ public interface TransportRemoteStatisticsService {
      */
     Integer statisticsPendingVerificationWaybill(Long topEntId);
 
+    /**
+     * 统计贸易订单已派车次,排除已取消运单。
+     *
+     * @param tOrderId 贸易订单ID
+     * @return 已派车次数
+     */
+    Long countDispatchedWaybillsByTradeOrderId(Long tOrderId);
+
+    /**
+     * 按时间范围汇总贸易订单已完成运单的完成量。
+     *
+     * @param tradeOrderId 贸易订单ID
+     * @param chargeType 计费方式:1-装货量,2-卸货量
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 完成量
+     */
+    BigDecimal sumCompletedWaybillVolumeByTimeRange(Long tradeOrderId, Integer chargeType,
+                                                    LocalDateTime startTime, LocalDateTime endTime);
+
 }

+ 2 - 2
sckw-modules-api/sckw-transport-api/src/main/java/com/sckw/transport/api/model/param/AddLogisticOrderParam.java

@@ -233,14 +233,14 @@ public class AddLogisticOrderParam implements Serializable {
      * 计划卸货时间
      */
     @NotNull(message = "计划卸货时间不能为空")
-    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDate endTime;
 
     /**
      * 计划发货时间
      */
     @NotNull(message = "计划发货时间不能为空")
-    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDate startTime;
 
 

+ 13 - 0
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/controller/KwcPurchaseController.java

@@ -9,6 +9,8 @@ import com.sckw.contract.api.model.dto.res.TradeEntInfoResVo;
 import com.sckw.contract.service.operateService.KwcContractTradeService;
 import com.sckw.core.model.enums.EntTypeEnum;
 import com.sckw.core.web.context.LoginUserHolder;
+import com.sckw.core.web.context.LoginEntHolder;
+import com.sckw.core.web.context.LoginUserHolder;
 import com.sckw.core.web.response.BaseResult;
 import com.sckw.core.web.response.HttpResult;
 import jakarta.servlet.http.HttpServletResponse;
@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -52,6 +55,16 @@ public class KwcPurchaseController {
         if(queryFeignDto.getCurEntId() == null){
             queryFeignDto.setCurEntId(LoginUserHolder.getEntId());
         }
+        if(queryFeignDto.getTradeEntType() == null){
+            String entTypes = LoginEntHolder.get().getEntTypes();
+            if (entTypes.contains(String.valueOf(EntTypeEnum.SUPPLIER.getCode()))) {
+                queryFeignDto.setTradeEntType(EntTypeEnum.PURCHASER.getCode());
+            } else if (entTypes.contains(String.valueOf(EntTypeEnum.PURCHASER.getCode()))) {
+                queryFeignDto.setTradeEntType(EntTypeEnum.SUPPLIER.getCode());
+            } else {
+                return BaseResult.success(Collections.emptyList());
+            }
+        }
         return BaseResult.success(kwcContractTradeService.queryTradeEntList(queryFeignDto));
     }
 

+ 6 - 3
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/service/operateService/KwcContractTradeService.java

@@ -2139,18 +2139,21 @@ public class KwcContractTradeService {
         List<KwcContractLogisticsGoods> kwcContractLogisticsGoods = kwcContractLogisticsGoodsRepository.queryByLogIdsAndGoodsId(logTradeContractIds,
                 logisticsOrderDto.getGoodsId());
         Map<Long, KwcContractLogisticsGoods> contractLogisticsGoodsMap = Maps.newHashMap();
-
+        Set<Long> goodsContractIds = new HashSet<>();
         if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwcContractLogisticsGoods)) {
             contractLogisticsGoodsMap = kwcContractLogisticsGoods.stream()
                     .collect(Collectors.toMap(KwcContractLogisticsGoods::getContractId,
                             Function.identity(), (x, y) -> x));
-            logTradeContractIds = kwcContractLogisticsGoods.stream()
+            goodsContractIds = kwcContractLogisticsGoods.stream()
                     .map(KwcContractLogisticsGoods::getContractId)
                     .collect(Collectors.toSet());
         }
 
-        //查询物流订单
+        //查询物流订单  如果是通用价格不为空的不能过滤掉
         List<KwcContractLogistics> logistics = contractLogisticsRepository.queryByLogisticContractIds(logTradeContractIds);
+        Set<Long> finalGoodsContractIds = goodsContractIds;
+        logistics = logistics.stream().filter(x-> finalGoodsContractIds.contains(x.getId()) || Objects.nonNull(x.getCommonPrice()))
+                .distinct().collect(Collectors.toList());
         if (CollectionUtils.isEmpty(logistics)) {
             return Collections.emptyList();
         }

+ 0 - 1
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/model/request/DriverAssociatedTruckSaveRequest.java

@@ -42,7 +42,6 @@ public class DriverAssociatedTruckSaveRequest implements Serializable {
     private Integer energyType;
 
     @Schema(description = "排放标准")
-    @NotNull(message = "排放标准不能为空")
     private Integer eev;
 
     @Schema(description = "货车行驶证")

+ 12 - 0
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/model/vo/QueryFleetResp.java

@@ -121,5 +121,17 @@ public class QueryFleetResp  implements Serializable {
          */
         @Schema(description = "车辆轴数")
         private String axleNum;
+
+        /**
+         * 车辆类别(牵引车、货车)
+         */
+        @Schema(description = "车辆类别(牵引车、货车)")
+        private Integer type;
+
+        /**
+         * 车辆类别描述
+         */
+        @Schema(description = "车辆类别描述")
+        private String typeDesc;
     }
 }

+ 12 - 0
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/model/vo/TruckValidateVo.java

@@ -77,4 +77,16 @@ public class TruckValidateVo implements Serializable {
      */
     @Schema(description = "企业名称")
     private String entName;
+
+    /**
+     * 车辆类别(牵引车、货车)
+     */
+    @Schema(description = "车辆类别(牵引车、货车)")
+    private Integer type;
+
+    /**
+     * 车辆类别描述
+     */
+    @Schema(description = "车辆类别描述")
+    private String typeDesc;
 }

+ 6 - 0
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/repository/KwfTruckRepository.java

@@ -87,4 +87,10 @@ public class KwfTruckRepository extends ServiceImpl<KwfTruckMapper, KwfTruck> {
         );
     }
 
+    public List<KwfTruck> findTruckByTruckNos(List<String> truckNos) {
+        return list(Wrappers.<KwfTruck>lambdaQuery()
+                .eq(BaseModel::getDelFlag,0)
+                .in(KwfTruck::getTruckNo, truckNos)
+                .orderByDesc(BaseModel::getId));
+    }
 }

+ 3 - 0
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/service/KwfFleetService.java

@@ -22,6 +22,7 @@ import com.sckw.fleet.model.KwfFleetTruck;
 import com.sckw.fleet.model.KwfTruck;
 import com.sckw.fleet.model.TmsTruckAxleNum;
 import com.sckw.fleet.model.dto.KwfFleetDto;
+import com.sckw.fleet.model.enums.TruckTypeEnum;
 import com.sckw.fleet.model.request.QueryFleetReq;
 import com.sckw.fleet.model.vo.KwfFleetTruckCountVo;
 import com.sckw.fleet.model.vo.KwfFleetVo;
@@ -337,6 +338,8 @@ public class KwfFleetService {
         truckInfo.setTruckId(truck.getId());
         truckInfo.setTruckNo(truck.getTruckNo());
         truckInfo.setAxleNum(truckAxleNum.getName());
+        truckInfo.setType(truck.getType());
+        truckInfo.setTypeDesc(TruckTypeEnum.getName(truck.getType()));
         return truckInfo;
     }
 

+ 14 - 6
sckw-modules/sckw-fleet/src/main/java/com/sckw/fleet/service/KwfTruckService.java

@@ -1978,6 +1978,11 @@ public class KwfTruckService {
         if (CollectionUtils.isNotEmpty( result)){
             result =  result.stream().filter(x->x.getValid()).collect(Collectors.toList());
         }
+        List<TruckValidateVo> r = result.stream().filter(x -> Objects.nonNull(x.getTruckId()))
+                .collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(r)){
+            throw new BusinessException("车牌识别失败");
+        }
         return result;
     }
 
@@ -2020,7 +2025,9 @@ public class KwfTruckService {
             builder.exists(true)
                    .truckId(truck.getId())
                    .carAxis(axleNum.getName())
-                   .entId(ent.getId());
+                   .entId(ent.getId())
+                    .type(truck.getType())
+                    .typeDesc(TruckTypeEnum.getName(truck.getType()));
 
             // 获取企业名称
             if (ent != null) {
@@ -2140,12 +2147,12 @@ public class KwfTruckService {
     }
 
     /**
-     * 分页查询铲车订单
+     * 车辆详情
      * @param param
      * @return
      */
     public TruckDetailResp truckDetail(TruckDetailParam param) {
-        log.info("查询司机详情,id:{}", JSON.toJSONString(param));
+        log.info("查询车辆详情,id:{}", JSON.toJSONString(param));
         if (param.getId() == null && (param.getTruckNo() == null || param.getTruckNo().trim().isEmpty())) {
             return new TruckDetailResp();
         }
@@ -2187,9 +2194,10 @@ public class KwfTruckService {
 
         //车队班组
         KwfFleet fleet = findByFleetTruck(truck.getId(), LoginUserHolder.getEntId());
-        truckDetailResp.setFleetId(fleet.getId());
-        truckDetailResp.setFleetName(fleet.getName());
-
+        if (fleet != null) {
+            truckDetailResp.setFleetId(fleet.getId());
+            truckDetailResp.setFleetName(fleet.getName());
+        }
         //查询司机信息
         KwfDriver driver = getDriverInfo(truck.getId(), LoginUserHolder.getEntId());
         truckDetailResp.setDriverName(driver.getName());

+ 4 - 4
sckw-modules/sckw-fleet/src/main/resources/bootstrap-cxf.yml

@@ -3,16 +3,16 @@ spring:
     nacos:
       discovery:
         # 服务注册地址
-        server-addr: @nacos.server@
+        server-addr: 118.116.4.155:8848
         # 命名空间
-        namespace: @nacos.namespace@
+        namespace: sckw-ng-service-platform-xf
         # 共享配置
         group: sckw-ng-service-platform
       config:
         # 配置中心地址
-        server-addr: @nacos.server@
+        server-addr: 118.116.4.155:8848
         # 命名空间
-        namespace: @nacos.namespace@
+        namespace: sckw-ng-service-platform-xf
         # 共享配置
         group: sckw-ng-service-platform
         # 配置文件格式

+ 9 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/controller/KwoTradeOrderController.java

@@ -138,6 +138,15 @@ public class KwoTradeOrderController {
         return HttpResult.ok("贸易订单详情查询成功", kwoTradeOrderService.getDetail(id));
     }
 
+    /**
+     * 贸易订单详情看板:完成率、今日/本月运单完成量、派车次数
+     */
+    @GetMapping("/dashboardStatistic")
+    @Operation(summary = "贸易订单看板统计", description = "完成率、今日总量、车次、本月总量")
+    public HttpResult dashboardStatistic(@RequestParam Long id) {
+        return HttpResult.ok("查询成功", kwoTradeOrderService.tradeOrderDashboardStatistic(id));
+    }
+
     @PostMapping("/audit")
     @Operation(summary = "审核贸易订单", description = "审核贸易订单")
 //    @GlobalTransactional(name = "default_tx_group")

+ 37 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/model/vo/res/TradeOrderDashboardVO.java

@@ -0,0 +1,37 @@
+package com.sckw.order.model.vo.res;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 贸易订单详情页看板统计(完成率、今日/本月完成量、车次)
+ */
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+@Schema(description = "贸易订单看板统计")
+public class TradeOrderDashboardVO implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "完成率(%),已完成量/订单总量*100,保留两位小数")
+    private BigDecimal completionRate;
+
+    @Schema(description = "今日完成量(吨),按计费方式取装货量或审核后卸货量")
+    private BigDecimal todayTotalVolume;
+
+    @Schema(description = "已派车次数(非已取消运单数)")
+    private Long tripCount;
+
+    @Schema(description = "本月完成量(吨),按计费方式取装货量或审核后卸货量")
+    private BigDecimal monthTotalVolume;
+}

+ 104 - 3
sckw-modules/sckw-order/src/main/java/com/sckw/order/serivce/KwoTradeOrderService.java

@@ -58,6 +58,7 @@ import com.sckw.order.model.vo.res.OrderDetailRes;
 import com.sckw.order.model.vo.res.UnitInfoDetailRes;
 import com.sckw.order.model.vo.res.*;
 import com.sckw.order.repository.KwoTradeOrderUnitRepository;
+import com.sckw.order.util.TradeOrderDashboardUtils;
 import com.sckw.payment.api.dubbo.PayCenterDubboService;
 import com.sckw.payment.api.dubbo.PaymentDubboService;
 import com.sckw.payment.api.feign.PaymentFeignService;
@@ -82,6 +83,7 @@ import com.sckw.system.api.feign.DataPermissionFeignService;
 import com.sckw.system.api.model.dto.req.ActualDisPatchDto;
 import com.sckw.system.api.model.dto.req.DataPermissionFilterReqDto;
 import com.sckw.system.api.model.dto.res.*;
+import com.sckw.transport.api.dubbo.TransportRemoteStatisticsService;
 import com.sckw.transport.api.dubbo.TransportRemoteService;
 import com.sckw.transport.api.model.dto.TradeOrderWaybillAggDto;
 import com.sckw.transport.api.model.param.AddLogisticOrderParam;
@@ -102,7 +104,10 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
@@ -141,6 +146,9 @@ public class KwoTradeOrderService {
     @DubboReference(version = "1.0.0", group = "design", check = false)
     private TransportRemoteService transportRemoteService;
 
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
+    private TransportRemoteStatisticsService transportRemoteStatisticsService;
+
     @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
     protected RemoteFleetService remoteFleetService;
 
@@ -672,6 +680,7 @@ public class KwoTradeOrderService {
         List<OrderProcess> orderProcesses = new ArrayList<>(tracks.size());
         List<Long> createBys = tracks.stream().map(KwoTradeOrderTrack::getCreateBy).distinct().toList();
         Map<Long, UserCacheResDto> map = remoteSystemService.queryUserCacheMapByIds(createBys);
+        List<Integer> statusList = Arrays.asList(TradeOrderStatusEnum.AUDIT.getCode(), TradeOrderStatusEnum.ING.getCode(), TradeOrderStatusEnum.DEAL.getCode());
         tracks.forEach(e -> {
             OrderProcess process = BeanUtil.copyProperties(e, OrderProcess.class);
             UserCacheResDto user = map.get(process.getCreateBy());
@@ -682,10 +691,22 @@ public class KwoTradeOrderService {
                     process.setRoleName(String.join(",", roleNames));
                 }
             }
-            process.setStatusLabel(OrderStatusEnum.getMsg(process.getStatus()));
-            orderProcesses.add(process);
+            if (statusList.contains(process.getStatus())){
+                if (Objects.equals(process.getStatus(),TradeOrderStatusEnum.AUDIT.getCode())){
+                    process.setStatusLabel("订单创建");
+                }
+                if (Objects.equals(process.getStatus(),TradeOrderStatusEnum.ING.getCode())){
+                    process.setStatusLabel("审核");
+                }
+                if (Objects.equals(process.getStatus(),TradeOrderStatusEnum.DEAL.getCode())){
+                    process.setStatusLabel("结算");
+                }
+                orderProcesses.add(process);
+            }
         });
-        detail.setOrderProcess(orderProcesses);
+        List<OrderProcess> orderProcesses1 = orderProcesses.stream().sorted(Comparator.comparing(OrderProcess::getCreateTime).reversed()).collect(Collectors.toList());
+
+        detail.setOrderProcess(orderProcesses1);
         return detail;
     }
 
@@ -1881,6 +1902,86 @@ public class KwoTradeOrderService {
         return statistics;
     }
 
+    /**
+     * 贸易订单详情看板:完成率、今日/本月完成量、已派车次数(与贸易订单关联运单,按计费方式统计装卸货量)
+     *
+     * @param tOrderId 贸易订单主键
+     * @return 看板数据
+     */
+    public TradeOrderDashboardVO tradeOrderDashboardStatistic(Long tOrderId) {
+        if (Objects.isNull(tOrderId) || tOrderId <= 0) {
+            throw new BusinessException("贸易订单主键不能为空");
+        }
+        KwoTradeOrder order = kwoTradeOrderMapper.selectById(tOrderId);
+        if (order == null) {
+            throw new BusinessException("不存在该订单!");
+        }
+        ZoneId zone = ZoneId.of("Asia/Shanghai");
+        LocalDate today = LocalDate.now(zone);
+        LocalDateTime dayStart = today.atStartOfDay();
+        LocalDateTime dayEnd = dayStart.plusDays(1);
+        LocalDateTime monthStart = today.with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay();
+        LocalDateTime monthEnd = monthStart.plusMonths(1);
+
+        BigDecimal completionRate = TradeOrderDashboardUtils.completionRateOf(order);
+        Long tripCount = getDispatchedWaybillCount(tOrderId);
+
+        Integer chargeType = order.getChargeType();
+        BigDecimal todayVol = BigDecimal.ZERO;
+        BigDecimal monthVol = BigDecimal.ZERO;
+        if (Objects.equals(chargeType, ChargingTypeEnum.ON.getCode())
+                || Objects.equals(chargeType, ChargingTypeEnum.OFF.getCode())) {
+            todayVol = getCompletedWaybillVolume(tOrderId, chargeType, dayStart, dayEnd);
+            monthVol = getCompletedWaybillVolume(tOrderId, chargeType, monthStart, monthEnd);
+        }
+        todayVol = todayVol.setScale(2, RoundingMode.HALF_UP);
+        monthVol = monthVol.setScale(2, RoundingMode.HALF_UP);
+
+        return new TradeOrderDashboardVO()
+                .setCompletionRate(completionRate)
+                .setTodayTotalVolume(todayVol)
+                .setTripCount(tripCount)
+                .setMonthTotalVolume(monthVol);
+    }
+
+    /**
+     * 获取贸易订单已派车次。
+     *
+     * @param tOrderId 贸易订单ID
+     * @return 已派车次数
+     */
+    private Long getDispatchedWaybillCount(Long tOrderId) {
+        try {
+            return Optional.ofNullable(transportRemoteStatisticsService.countDispatchedWaybillsByTradeOrderId(tOrderId))
+                    .orElse(0L);
+        } catch (Exception e) {
+            log.error("查询贸易订单已派车次失败,tOrderId={}", tOrderId, e);
+            throw new BusinessException("查询贸易订单已派车次失败");
+        }
+    }
+
+    /**
+     * 获取贸易订单指定时间范围内的运单完成量。
+     *
+     * @param tOrderId 贸易订单ID
+     * @param chargeType 计费方式
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 运单完成量
+     */
+    private BigDecimal getCompletedWaybillVolume(Long tOrderId, Integer chargeType,
+                                                 LocalDateTime startTime, LocalDateTime endTime) {
+        try {
+            return Optional.ofNullable(transportRemoteStatisticsService.sumCompletedWaybillVolumeByTimeRange(
+                            tOrderId, chargeType, startTime, endTime))
+                    .orElse(BigDecimal.ZERO);
+        } catch (Exception e) {
+            log.error("查询贸易订单运单完成量失败,tOrderId={}, chargeType={}, startTime={}, endTime={}",
+                    tOrderId, chargeType, startTime, endTime, e);
+            throw new BusinessException("查询贸易订单运单完成量失败");
+        }
+    }
+
     /**
      * @desc: 贸易订单列表导出
      * @author: yzc

+ 51 - 0
sckw-modules/sckw-order/src/main/java/com/sckw/order/util/TradeOrderDashboardUtils.java

@@ -0,0 +1,51 @@
+package com.sckw.order.util;
+
+import com.sckw.core.model.enums.ChargingTypeEnum;
+import com.sckw.order.model.KwoTradeOrder;
+import org.springframework.lang.Nullable;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * 贸易订单看板统计用计算工具(完成率等)
+ */
+public final class TradeOrderDashboardUtils {
+
+    private static final BigDecimal HUNDRED = new BigDecimal("100");
+
+    private TradeOrderDashboardUtils() {
+    }
+
+    /**
+     * 完成率 = 已完成量 / 订单货物总量(吨等) * 100,四舍五入保留两位小数。
+     * 装货量结算取累计装货量;卸货量结算取累计卸货量;按车次计费取实际交付量;总量为空或小于等于0时返回0.
+     */
+    public static BigDecimal completionRateOf(@Nullable KwoTradeOrder order) {
+        if (order == null) {
+            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        }
+        BigDecimal total = order.getAmount();
+        if (total == null || total.compareTo(BigDecimal.ZERO) <= 0) {
+            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        }
+        Integer chargeType = order.getChargeType();
+        BigDecimal done;
+        if (Objects.equals(chargeType, ChargingTypeEnum.ON.getCode())) {
+            done = Optional.ofNullable(order.getLoadAmount()).orElse(BigDecimal.ZERO);
+        } else if (Objects.equals(chargeType, ChargingTypeEnum.OFF.getCode())) {
+            done = Optional.ofNullable(order.getUnloadAmount()).orElse(BigDecimal.ZERO);
+        } else if (Objects.equals(chargeType, ChargingTypeEnum.CAR.getCode())) {
+            done = Optional.ofNullable(order.getActualAmount()).orElse(BigDecimal.ZERO);
+        } else {
+            done = Optional.ofNullable(order.getActualAmount())
+                    .filter(a -> a.compareTo(BigDecimal.ZERO) > 0)
+                    .or(() -> Optional.ofNullable(order.getLoadAmount()))
+                    .or(() -> Optional.ofNullable(order.getUnloadAmount()))
+                    .orElse(BigDecimal.ZERO);
+        }
+        return done.multiply(HUNDRED).divide(total, 2, RoundingMode.HALF_UP);
+    }
+}

+ 55 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/controller/enterpriseApp/AppSalesWayBillController.java

@@ -0,0 +1,55 @@
+package com.sckw.transport.controller.enterpriseApp;
+
+import com.sckw.core.web.response.BaseResult;
+import com.sckw.transport.model.param.SalesWaybillOrderQueryParam;
+import com.sckw.transport.model.param.SalesWaybillOrderResp;
+import com.sckw.transport.service.KwtLogisticsConsignmentService;
+import com.sckw.transport.service.KwtWaybillManagementService;
+import com.sckw.transport.service.KwtWaybillManagementV1Service;
+import com.sckw.transport.service.app.SalesWaybillOrderService;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.validation.Valid;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author jc
+ * @description 企业端app运单controller
+ * @date 2023-08-21 16:08:41
+ */
+@Slf4j
+@RestController
+@RequestMapping("/appSalesWaybill")
+public class AppSalesWayBillController {
+
+    @Autowired
+    KwtWaybillManagementService waybillManagementService;
+    @Autowired
+    KwtWaybillManagementV1Service waybillManagementV1Service;
+    @Autowired
+    KwtLogisticsConsignmentService logisticsConsignmentService;
+    @Autowired
+    SalesWaybillOrderService salesWaybillOrderService;
+
+
+    /**
+     * 分页查询运单
+     *
+     * @param param
+     * @return
+     */
+    @Operation(summary = "分页查询运单", description = "查询司机关联车辆接单的运单")
+    @PostMapping("/querySalesStatistics")
+    public BaseResult<SalesWaybillOrderResp> querySalesStatistics(@RequestBody @Valid SalesWaybillOrderQueryParam param){
+        SalesWaybillOrderResp salesWaybillOrderResp = salesWaybillOrderService.querySalesStatistics(param);
+        return BaseResult.success(salesWaybillOrderResp);
+    }
+
+
+
+}
+

+ 23 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/dao/KwtLogisticsOrderMapper.java

@@ -16,6 +16,7 @@ import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -482,4 +483,26 @@ public interface KwtLogisticsOrderMapper extends BaseMapper<KwtLogisticsOrder> {
     Long queryCount(@Param("ids") List<Long> ids);
 
     List<LogisticsBaseOrderVo> selectBase(@Param("para")LogisticsOrderPara orderPara);
+
+    /**
+     * 统计贸易订单已派车次,排除已取消运单。
+     *
+     * @param tOrderId 贸易订单ID
+     * @return 已派车次数
+     */
+    Long countDispatchedWaybillsByTradeOrderId(@Param("tOrderId") Long tOrderId);
+
+    /**
+     * 按时间范围汇总贸易订单已完成运单的完成量。
+     *
+     * @param tOrderId 贸易订单ID
+     * @param chargeType 计费方式:1-装货量,2-卸货量
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 完成量
+     */
+    BigDecimal sumCompletedWaybillVolumeByTimeRange(@Param("tOrderId") Long tOrderId,
+                                                    @Param("chargeType") Integer chargeType,
+                                                    @Param("startTime") LocalDateTime startTime,
+                                                    @Param("endTime") LocalDateTime endTime);
 }

+ 133 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/dubbo/TransportStatisticsServiceImpl.java

@@ -1,19 +1,34 @@
 package com.sckw.transport.dubbo;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.sckw.core.exception.BusinessException;
+import com.sckw.core.model.constant.Global;
 import com.sckw.core.model.constant.NumberConstant;
 import com.sckw.core.model.enums.CarWaybillEnum;
+import com.sckw.core.model.enums.CarWaybillV1Enum;
 import com.sckw.core.model.enums.LogisticsOrderEnum;
 import com.sckw.transport.api.dubbo.TransportRemoteStatisticsService;
 import com.sckw.transport.dao.KwtLogisticsOrderMapper;
 import com.sckw.transport.dao.KwtWaybillOrderMapper;
+import com.sckw.transport.dao.KwtWaybillOrderSubtaskMapper;
+import com.sckw.transport.model.KwtLogisticsOrder;
+import com.sckw.transport.model.KwtWaybillOrder;
+import com.sckw.transport.model.KwtWaybillOrderSubtask;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
 import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
@@ -32,6 +47,9 @@ public class TransportStatisticsServiceImpl implements TransportRemoteStatistics
     @Autowired
     KwtLogisticsOrderMapper logisticsOrderMapper;
 
+    @Autowired
+    KwtWaybillOrderSubtaskMapper waybillOrderSubtaskMapper;
+
     /**
      * 统计调度派车次数
      *
@@ -126,4 +144,119 @@ public class TransportStatisticsServiceImpl implements TransportRemoteStatistics
         Integer count = logisticsOrderMapper.statisticsLogisticsByTopEntIdAndOrderStatus(topEntId, orderList,"1",enterpriseIds);
         return count;
     }
+    /**
+     * 统计贸易订单已派车次。
+     *
+     * @param tOrderId 贸易订单ID
+     * @return 已派车次数
+     */
+    @Override
+    public Long countDispatchedWaybillsByTradeOrderId(Long tOrderId) {
+        if (Objects.isNull(tOrderId)) {
+            throw new BusinessException("贸易订单ID不能为空");
+        }
+        List<Long> logisticsOrderIds = listLogisticsOrderIdsByTradeOrderId(tOrderId);
+        if (CollectionUtils.isEmpty(logisticsOrderIds)) {
+            return 0L;
+        }
+        return Optional.ofNullable(waybillOrderMapper.selectCount(new QueryWrapper<KwtWaybillOrder>()
+                        .eq("del_flag", Global.NO)
+                        .in("l_order_id", logisticsOrderIds)
+                        .ne("status", CarWaybillV1Enum.CANCELLED.getCode())))
+                .orElse(0L);
+    }
+
+    /**
+     * 按时间范围汇总贸易订单已完成运单的完成量。
+     *
+     * @param tradeOrderId 贸易订单ID
+     * @param chargeType 计费方式:1-装货量,2-卸货量
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 完成量
+     */
+    @Override
+    public BigDecimal sumCompletedWaybillVolumeByTimeRange(Long tradeOrderId, Integer chargeType,
+                                                           LocalDateTime startTime, LocalDateTime endTime) {
+        if (Objects.isNull(tradeOrderId)) {
+            throw new BusinessException("贸易订单ID不能为空");
+        }
+        if (Objects.isNull(chargeType)) {
+            throw new BusinessException("计费方式不能为空");
+        }
+        if (!Objects.equals(chargeType, NumberConstant.ONE) && !Objects.equals(chargeType, NumberConstant.TWO)) {
+            return BigDecimal.ZERO;
+        }
+        List<Long> logisticsOrderIds = listLogisticsOrderIdsByTradeOrderId(tradeOrderId);
+        if (CollectionUtils.isEmpty(logisticsOrderIds)) {
+            return BigDecimal.ZERO;
+        }
+
+        QueryWrapper<KwtWaybillOrder> waybillWrapper = new QueryWrapper<KwtWaybillOrder>()
+                .select("id")
+                .eq("del_flag", Global.NO)
+                .in("l_order_id", logisticsOrderIds)
+                .eq("status", CarWaybillV1Enum.COMPLETED.getCode());
+        if (Objects.nonNull(startTime) && Objects.nonNull(endTime)) {
+            waybillWrapper.ge("update_time", toDate(startTime))
+                    .lt("update_time", toDate(endTime));
+        }
+
+        List<Long> waybillOrderIds = Optional.ofNullable(waybillOrderMapper.selectList(waybillWrapper))
+                .orElse(Collections.emptyList())
+                .stream()
+                .map(KwtWaybillOrder::getId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(waybillOrderIds)) {
+            return BigDecimal.ZERO;
+        }
+
+        QueryWrapper<KwtWaybillOrderSubtask> subtaskWrapper = new QueryWrapper<KwtWaybillOrderSubtask>()
+                .eq("del_flag", Global.NO)
+                .in("w_order_id", waybillOrderIds);
+        if (Objects.equals(chargeType, NumberConstant.ONE)) {
+            subtaskWrapper.select("load_amount")
+                    .isNotNull("load_amount");
+        } else {
+            subtaskWrapper.select("unload_amount")
+                    .isNotNull("unload_amount");
+        }
+
+        return Optional.ofNullable(waybillOrderSubtaskMapper.selectList(subtaskWrapper))
+                .orElse(Collections.emptyList())
+                .stream()
+                .map(item -> Objects.equals(chargeType, NumberConstant.ONE) ? item.getLoadAmount() : item.getUnloadAmount())
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+    /**
+     * 根据贸易订单ID查询有效物流订单ID列表,统一复用 MyBatis-Plus 查询条件,避免手写SQL。
+     *
+     * @param tradeOrderId 贸易订单ID
+     * @return 有效物流订单ID列表
+     */
+    private List<Long> listLogisticsOrderIdsByTradeOrderId(Long tradeOrderId) {
+        return Optional.ofNullable(logisticsOrderMapper.selectList(new QueryWrapper<KwtLogisticsOrder>()
+                        .select("id")
+                        .eq("del_flag", Global.NO)
+                        .eq("t_order_id", tradeOrderId)))
+                .orElse(Collections.emptyList())
+                .stream()
+                .map(KwtLogisticsOrder::getId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * LocalDateTime 转 Date,保持与数据库时间字段类型一致。
+     *
+     * @param dateTime 本地日期时间
+     * @return Date时间
+     */
+    private Date toDate(LocalDateTime dateTime) {
+        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
+    }
 }

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

@@ -4,22 +4,16 @@ package com.sckw.transport.handler;
 import com.sckw.core.common.enums.enums.ErrorCodeEnum;
 import com.sckw.core.exception.BusinessPlatfromException;
 import com.sckw.core.model.enums.CarWaybillV1Enum;
+import com.sckw.core.model.enums.GatekeeperStatusEnum;
+import com.sckw.core.model.enums.GatekeeperTypeEnum;
 import com.sckw.core.utils.DateUtils;
-import com.sckw.fleet.api.RemoteFleetService;
 import com.sckw.fleet.api.model.vo.DriverConductRulesVO;
 import com.sckw.order.api.model.OrderDetailVo;
 import com.sckw.order.api.model.UpdateActualAmountParam;
-import com.sckw.transport.model.KwtLogisticsOrder;
-import com.sckw.transport.model.KwtWaybillOrder;
-import com.sckw.transport.model.KwtWaybillOrderNode;
-import com.sckw.transport.model.KwtWaybillOrderSubtask;
+import com.sckw.transport.model.*;
 import com.sckw.transport.model.param.WaybillOrderCancelParam;
-import com.sckw.transport.repository.KwtLogisticsOrderRepository;
-import com.sckw.transport.repository.KwtWaybillOrderRepository;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.dubbo.config.annotation.DubboReference;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -66,6 +60,10 @@ public class CancelHandler extends AbstractWaybillOrderHandler<WaybillOrderCance
 
         //4.更新上游订单:更新贸易订单运输量
 //        updateTradeOrder(logOrder, entrustAmount);
+
+        //5.取消门卫订单
+        cancelGatekeeperStatus(waybill);
+
     }
 
     /**
@@ -122,6 +120,21 @@ public class CancelHandler extends AbstractWaybillOrderHandler<WaybillOrderCance
         log.info("更新上游贸易订单运输量成功, 贸易订单ID:{}", tradeOrder.getId());
     }
 
+
+    /**
+     * 取消门卫订单
+     * @param waybill
+     */
+    private void cancelGatekeeperStatus(KwtWaybillOrder waybill) {
+        KwtGatekeeperWaybillOrder gatekeeperWaybillOrder = gatekeeperWaybillOrderRepository
+                .queryGatekeeperWaybillOrderByWOrderId(waybill.getId(), GatekeeperTypeEnum.LOADING.getCode());
+        if (gatekeeperWaybillOrder == null) {
+            throw new BusinessPlatfromException(ErrorCodeEnum.GATEKEEPER_ORDER_NOT_FOUND, "门卫订单不存在!");
+        }
+        gatekeeperWaybillOrder.setStatus(GatekeeperStatusEnum.CANCEL.getCode());
+        gatekeeperWaybillOrderRepository.updateById(gatekeeperWaybillOrder);
+    }
+
     @Override
     protected String getProcessName() {
         return "取消接单";

+ 21 - 11
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/ComeIntoHandler.java

@@ -39,9 +39,6 @@ import java.util.stream.Collectors;
 @Service
 public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCmeIntoWeighParam> {
 
-    //用于存储动态状态
-    private Integer targetStatus;
-
     @Override
     protected KwtWaybillOrder getWaybillOrder(WaybillOrderCmeIntoWeighParam param) {
         return getWaybillOrder(param.getWaybillOrderId());
@@ -281,8 +278,8 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
     //
 
     /**
-     * 计算并设定离场目标状态
-     *                      空载离场:净重<=0.5,        状态更改为:空载待离场
+     * 计算并设定离场目标状态   其它情况:净重<-0.5          状态更改为:直接返回
+     *                      空载离场:-0.5<=净重<=0.5,  状态更改为:空载待离场
      *                      正常流程:0.5<净重<=任务量,  状态更改为:待离场
      *                      超载流程:净重>任务量,       状态更改为:卸货中
      * @param waybillOrder
@@ -294,11 +291,21 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
         if (waybillSubtask.getEntrustAmount() == null) {
             throw new BusinessPlatfromException(ErrorCodeEnum.SYSTEM_ERROR, "[称重过磅]子运单任务量信息缺失!");
         }
-        BigDecimal entrustAmount = waybillSubtask.getEntrustAmount();
 
-        //场景一:空载离场,净重<=0.5
+        KwtForkliftWaybillOrder forklift = forkliftWaybillOrderRepository.queryForkliftWaybillOrderByWOrderId(waybillOrder.getId());
+        if (Objects.equals(forklift.getStatus(), ForkliftStatusEnum.ORDER_TAKING.getCode())) {
+            //如果铲车司机未接单,则二次过磅的时候,直接返回,不走其它流程
+            return;
+        }
+
+        BigDecimal entrustAmount = waybillSubtask.getEntrustAmount();
+        //场景一:净重<-0.5
+        if (loadAmount.compareTo(BigDecimal.valueOf(-0.5)) < 0) {
+            return;
+        }
+        //场景二:空载离场,-0.5<=净重<=0.5
         if (loadAmount.compareTo(BigDecimal.valueOf(0.5)) <= 0) {
-            this.targetStatus = 1;
+            waybillOrder.setTargetStatus(1);
             return;
         }
         // 非空载情况,必须校验是否完成装载
@@ -306,11 +313,11 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
 
         // 场景二:正常流程,0.5<净重<=任务量
         if (loadAmount.compareTo(entrustAmount) <= 0) {
-            this.targetStatus = 2;
+            waybillOrder.setTargetStatus(2);
             return;
         }
         // 场景三:超载流程, 净重>任务量
-        this.targetStatus = 3;
+        waybillOrder.setTargetStatus(3);
     }
 
     /**
@@ -335,7 +342,10 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
         if (checkIsFirst(waybillOrder)) {
             status = CarWaybillV1Enum.REFUSE_TRAFFIC.getCode();
         } else {
-            status = switch (this.targetStatus) {
+            if (waybillOrder.getTargetStatus() == null) {
+                return;
+            }
+            status = switch (waybillOrder.getTargetStatus()) {
                 case 1 -> CarWaybillV1Enum.EMPTY_WAIT_LEAVE.getCode();
                 case 2 -> CarWaybillV1Enum.WAIT_LEAVE.getCode();
                 case 3 -> CarWaybillV1Enum.UNLOADING.getCode();

+ 24 - 3
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/EmptyLoadLeaveHandler.java

@@ -4,9 +4,8 @@ package com.sckw.transport.handler;
 import com.alibaba.fastjson.JSON;
 import com.sckw.core.common.enums.enums.ErrorCodeEnum;
 import com.sckw.core.exception.BusinessPlatfromException;
-import com.sckw.core.model.enums.CarWaybillV1Enum;
-import com.sckw.core.model.enums.GatekeeperStatusEnum;
-import com.sckw.core.model.enums.GatekeeperTypeEnum;
+import com.sckw.core.model.enums.*;
+import com.sckw.transport.model.KwtForkliftWaybillOrder;
 import com.sckw.transport.model.KwtGatekeeperWaybillOrder;
 import com.sckw.transport.model.KwtWaybillOrder;
 import com.sckw.transport.model.KwtWaybillOrderSubtask;
@@ -45,6 +44,10 @@ public class EmptyLoadLeaveHandler extends AbstractWaybillOrderHandler<WaybillOr
 
         // 修改门卫数据状态:待放行
         updateGatekeeperOrderStatus(waybillOrder);
+
+        // 校验铲车订单是否是待接单
+        updateForkliftOrderStatus(waybillOrder);
+
     }
 
 
@@ -68,6 +71,24 @@ public class EmptyLoadLeaveHandler extends AbstractWaybillOrderHandler<WaybillOr
         gatekeeperWaybillOrderRepository.updateById(gatekeeper);
     }
 
+    /**
+     * 修改门卫订单状态
+     * @param waybillOrder
+     * @return
+     */
+    public void updateForkliftOrderStatus(KwtWaybillOrder waybillOrder) {
+        KwtForkliftWaybillOrder forkliftWaybillOrder = forkliftWaybillOrderRepository
+                .queryForkliftWaybillOrderByWOrderIdAndType(waybillOrder.getId(), LoadingTypeEnum.LOADING.getCode());
+        if (forkliftWaybillOrder == null) {
+            throw new BusinessPlatfromException(ErrorCodeEnum.FORKLIFT_ORDER_NOT_FOUND, "铲车订单数据不存在!");
+        }
+        // 司机空载离场,铲车待接单的状态改为:取消
+        if (ForkliftStatusEnum.PENDING_ORDERS.getCode().equals(forkliftWaybillOrder.getStatus())) {
+            forkliftWaybillOrder.setStatus(ForkliftStatusEnum.CANCEL.getCode());
+            forkliftWaybillOrderRepository.updateById(forkliftWaybillOrder);
+        }
+    }
+
 
     @Override
     protected void calculateAutoDispatchScore(WaybillOrderEmptyLoadLeaveParam param, KwtWaybillOrder waybillOrder) {

+ 3 - 6
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/LoadingHandler.java

@@ -30,10 +30,7 @@ public class LoadingHandler extends AbstractWaybillOrderHandler<WaybillOrderLoad
 
     @Override
     protected void checkState(WaybillOrderLoadingParam param, KwtWaybillOrder waybillOrder) {
-        if (!Objects.equals(CarWaybillV1Enum.REFUSE_TRAFFIC.getCode(), waybillOrder.getStatus())
-                && !Objects.equals(CarWaybillV1Enum.REPLENISHING.getCode(), waybillOrder.getStatus())) {
-            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_STATUS_ERROR, "运单状态不是“到达装货地点”或“卸货中”状态, 无法推进下一节点!");
-        }
+
     }
 
     @Override
@@ -54,8 +51,8 @@ public class LoadingHandler extends AbstractWaybillOrderHandler<WaybillOrderLoad
     @Override
     protected void getStatus(KwtWaybillOrder waybillOrder) {
         //第一次过磅,状态为:已装货;后续过磅,状态为:补货完成
-        CarWaybillV1Enum status = Objects.equals(waybillOrder.getStatus(), CarWaybillV1Enum.REFUSE_TRAFFIC.getCode())
-                ? CarWaybillV1Enum.EXIT_COMPLETED : CarWaybillV1Enum.REPLENISH_FINISH;
+        CarWaybillV1Enum status = Objects.equals(waybillOrder.getStatus(), CarWaybillV1Enum.REPLENISHING.getCode())
+                ? CarWaybillV1Enum.REPLENISH_FINISH : CarWaybillV1Enum.EXIT_COMPLETED;
 
         // 1. 修改运单状态
         waybillOrder.setStatus(status.getCode());

+ 4 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/KwtWaybillOrder.java

@@ -176,4 +176,8 @@ public class KwtWaybillOrder implements Serializable {
      * 派车方式
      */
     private Integer dispatchWay;
+
+    //用于存储动态状态
+    @TableField(exist = false)
+    private Integer targetStatus;
 }

+ 2 - 2
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/dto/AddLogisticOrderDTO.java

@@ -235,14 +235,14 @@ public class AddLogisticOrderDTO implements Serializable {
      * 计划卸货时间
      */
     @NotNull(message = "计划卸货时间不能为空")
-    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDate endTime;
 
     /**
      * 计划发货时间
      */
     @NotNull(message = "计划发货时间不能为空")
-    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDate startTime;
 
     /**

+ 32 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/SalesWaybillOrderQueryParam.java

@@ -0,0 +1,32 @@
+package com.sckw.transport.model.param;
+
+import com.sckw.core.web.request.PageReq;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author :donglang
+ * @version :1.0
+ * @description :
+ * @create :2025-11-13 08:59:00
+ */
+@Data
+public class SalesWaybillOrderQueryParam extends PageReq implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -9098396227857171692L;
+
+    /**
+     * 企业id
+     */
+    @Schema(description = "企业id")
+    @NotNull(message = "企业id不能为空!")
+    private Long entId;
+
+
+
+}

+ 8 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/repository/KwtForkliftWaybillOrderRepository.java

@@ -57,6 +57,14 @@ public class KwtForkliftWaybillOrderRepository extends ServiceImpl<KwtForkliftWa
                 .last("limit 1"));
     }
 
+    public KwtForkliftWaybillOrder queryForkliftWaybillOrderByWOrderIdAndType(Long wOrderId, Integer type) {
+        return getOne(Wrappers.<KwtForkliftWaybillOrder>lambdaQuery()
+                .eq(KwtForkliftWaybillOrder::getWOrderId, wOrderId)
+                .eq(KwtForkliftWaybillOrder::getLoadingType, type)
+                .orderByDesc(KwtForkliftWaybillOrder::getId)
+                .last("limit 1"));
+    }
+
 
 
 

+ 3 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtLogisticsConsignmentService.java

@@ -3734,6 +3734,9 @@ public class KwtLogisticsConsignmentService {
                 .filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                 .map(Long::valueOf)
                 .toList();
+        if (CollectionUtils.isEmpty(reqTruckIds)) {
+            throw new BusinessException("车辆id不能为空");
+        }
         Map<Long, RTruckVo> truckMap = remoteFleetService.findTruckByTruckIds(reqTruckIds).stream()
                 .collect(Collectors.toMap(RTruckVo::getId, Function.identity(), (k1, k2) -> k1));
         final int disabledTruckStatus = 1;

+ 109 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/app/SalesWaybillOrderService.java

@@ -0,0 +1,109 @@
+package com.sckw.transport.service.app;
+
+
+import com.alibaba.fastjson.JSON;
+import com.sckw.fleet.api.RemoteFleetService;
+import com.sckw.order.api.dubbo.TradeOrderInfoService;
+import com.sckw.product.api.dubbo.GoodsInfoService;
+import com.sckw.system.api.RemoteSystemService;
+import com.sckw.transport.handler.*;
+import com.sckw.transport.model.param.SalesWaybillOrderQueryParam;
+import com.sckw.transport.model.param.SalesWaybillOrderResp;
+import com.sckw.transport.model.param.WaybillOrderReq;
+import com.sckw.transport.model.vo.StatisticsWaybillResp;
+import com.sckw.transport.repository.*;
+import com.sckw.transport.service.KwtWaybillOrderV1Service;
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+/**
+ * @author zk
+ * @desc 司机app接单Service
+ * @date 2023/7/19 0019
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SalesWaybillOrderService {
+
+    private final KwtLogisticsOrderRepository logisticsOrderRepository;
+    private final KwtLogisticsOrderCirculateRepository logisticsOrderCirculateRepository;
+    private final KwtLogisticsOrderGoodsRepository logisticsOrderGoodsRepository;
+    private final KwtLogisticsOrderAddressRepository logisticsOrderAddressRepository;
+    private final KwtLogisticsOrderUnitRepository logisticsOrderUnitRepository;
+
+    private final KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
+    private final KwtWaybillOrderRepository waybillOrderRepository;
+    private final KwtWaybillOrderAddressRepository waybillOrderAddressRepository;
+    private final KwtWaybillOrderTicketRepository waybillOrderTicketRepository;
+    private final KwtWaybillOrderNodeRepository waybillOrderNodeRepository;
+
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
+    RemoteSystemService remoteSystemService;
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 80000)
+    TradeOrderInfoService tradeOrderInfoService;
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
+    RemoteFleetService remoteFleetService;
+    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
+    GoodsInfoService goodsInfoService;
+
+    private final TakingOrderHandler takingOrderHandler;
+    private final CancelHandler cancelHandler;
+    private final ComeIntoHandler comeIntoHandler;
+    private final LoadingHandler loadingHandler;
+    private final LeaveMockHandler leaveMockHandler;
+    private final LeaveHandler leaveHandler;
+    private final EmptyLoadLeaveHandler emptyLoadLeaveHandler;
+    private final ReplenishHandler replenishHandler;
+    private final LiftRodReleaseHandler liftRodReleaseHandler;
+
+    private final UnloadingHandler unloadingHandler;
+
+    private final KwtWaybillOrderV1Service waybillOrderV1Service;
+
+    // 注入RedisTemplate用于分布式锁
+    @Resource
+    private RedisTemplate<String, String> redisTemplate;
+
+    // 分布式锁相关常量
+    private static final String TAKING_ORDER_LOCK_PREFIX = "transport:taking_order:lock:";
+    // 锁超时时间30秒
+    private static final long LOCK_EXPIRE_SECONDS = 30;
+    // 锁等待时间500毫秒
+    private static final long LOCK_WAIT_MILLIS = 500;
+    // 锁重试间隔100毫秒
+    private static final long LOCK_RETRY_INTERVAL = 100;
+
+    //载重任务量浮动吨数
+    private static final BigDecimal TWO_TONS = new BigDecimal("2");
+    //载重任务量计算比例
+    private static final BigDecimal EIGHTY_PERCENT = new BigDecimal("0.8");
+
+    /**
+     * 查询销售数据
+     * @param param
+     * @return
+     */
+    public SalesWaybillOrderResp querySalesStatistics(SalesWaybillOrderQueryParam param) {
+        log.info("查询销售数据:{}", JSON.toJSONString(param));
+        SalesWaybillOrderResp salesResp = new SalesWaybillOrderResp();
+        // 查询执行中订单(物流订单)
+        WaybillOrderReq req = new WaybillOrderReq();
+        req.setEntId(String.valueOf(param.getEntId()));
+
+        StatisticsWaybillResp statisticsWaybillResp = waybillOrderV1Service.statisticsWaybillOrder(req);
+
+
+        log.info("查询销售数据成功,结果:{}", JSON.toJSONString(salesResp));
+
+        return salesResp;
+
+    }
+
+}

+ 44 - 0
sckw-modules/sckw-transport/src/main/resources/mapper/KwtLogisticsOrderMapper.xml

@@ -2160,6 +2160,50 @@
         </if>
     </select>
 
+    <select id="countDispatchedWaybillsByTradeOrderId" resultType="java.lang.Long">
+        SELECT COUNT(1)
+        FROM kwt_logistics_order lo
+                 INNER JOIN kwt_waybill_order wo ON wo.l_order_id = lo.id AND wo.del_flag = 0
+        WHERE lo.t_order_id = #{tOrderId}
+          AND lo.del_flag = 0
+          AND wo.status &lt;&gt; 99
+    </select>
+
+    <select id="sumCompletedWaybillVolumeByTimeRange" resultType="java.math.BigDecimal">
+        SELECT COALESCE(SUM(
+        <choose>
+            <when test="chargeType == 1">
+                wos.load_amount
+            </when>
+            <when test="chargeType == 2">
+                wos.unload_amount
+            </when>
+            <otherwise>
+                0
+            </otherwise>
+        </choose>
+        ), 0)
+        FROM kwt_logistics_order lo
+                 INNER JOIN kwt_waybill_order wo ON wo.l_order_id = lo.id AND wo.del_flag = 0
+                 INNER JOIN kwt_waybill_order_subtask wos ON wos.w_order_id = wo.id AND wos.del_flag = 0
+        WHERE lo.t_order_id = #{tOrderId}
+          AND lo.del_flag = 0
+          AND wo.status = 25
+        <if test="chargeType == 1">
+          AND wos.load_amount IS NOT NULL
+        </if>
+        <if test="chargeType == 2">
+          AND wos.unload_amount IS NOT NULL
+        </if>
+        <if test="chargeType == null or (chargeType != 1 and chargeType != 2)">
+          AND 1 = 0
+        </if>
+        <if test="startTime != null and endTime != null">
+          AND wo.update_time <![CDATA[ >= ]]> #{startTime}
+          AND wo.update_time <![CDATA[ < ]]> #{endTime}
+        </if>
+    </select>
+
     <select id="statisticsLogistics" resultType="java.lang.Long">
         SELECT DISTINCT a.id
         FROM kwt_logistics_order a