|
|
@@ -273,6 +273,8 @@ public class WaybillOrderService {
|
|
|
}
|
|
|
Map<Long, List<KwtWaybillOrderSubtask>> logOrderIdAndSubtaskMap = orderSubtaskList.stream()
|
|
|
.collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getLOrderId));
|
|
|
+ // 预加载运单磅单信息,避免在余量计算中出现 N+1 查询
|
|
|
+ Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList = getWaybillOrderIdAndTicketList(orderSubtaskList);
|
|
|
|
|
|
//获取贸易订单
|
|
|
List<OrderDetailVo> orderDetailVos = tradeOrderInfoService.queryByTradeOrderIds(tradeOrderIds);
|
|
|
@@ -292,7 +294,7 @@ public class WaybillOrderService {
|
|
|
.map(order -> {
|
|
|
return getLogisticsOrderResp(order, logOrderIdAndGoodsMap, goodsIdAndGoodsMap, logOrderIdAndUnitMap,
|
|
|
tOrderIdAndUnitMap, logOrderIdAndAddressMap, logOrderIdAndCirculateMap, tradeIdAndOrderDetailVoMap,
|
|
|
- tradeIdAndLogOrderList, logOrderIdAndSubtaskMap, dictValueAndDictResDtoMap);
|
|
|
+ tradeIdAndLogOrderList, logOrderIdAndSubtaskMap, waybillOrderIdAndTicketList, dictValueAndDictResDtoMap);
|
|
|
})
|
|
|
.filter(logisticsOrderResp -> {
|
|
|
// 校验是否满足车辆任务量,满足才保留
|
|
|
@@ -404,6 +406,7 @@ public class WaybillOrderService {
|
|
|
Map<Long, OrderDetailVo> tradeIdAndOrderDetailVoMap,
|
|
|
Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogOrderList ,
|
|
|
Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList,
|
|
|
+ Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList,
|
|
|
Map<String, Map<String, String>> dictValueAndDictResDtoMap) {
|
|
|
LogisticsOrderResp orderResp = new LogisticsOrderResp();
|
|
|
orderResp.setLogisticsOrderId(Optional.ofNullable(order.getId()).map(String::valueOf).orElse(null));
|
|
|
@@ -453,7 +456,8 @@ public class WaybillOrderService {
|
|
|
orderResp.setStatus(Optional.ofNullable(order.getStatus()).map(String::valueOf).orElse(null));
|
|
|
orderResp.setStatusDesc(LogisticsOrderV1Enum.IN_TRANSIT.getCode().equals(order.getStatus()) ? "待接单" : "未知状态");
|
|
|
//设置余量
|
|
|
- BigDecimal orderSurplus = getSupAmount(order.getTOrderId(), tradeIdAndOrderDetailVoMap, tradeIdAndLogOrderList, logisticsOrderIdAndSubtaskList);
|
|
|
+ BigDecimal orderSurplus = getSupAmount(order.getTOrderId(), tradeIdAndOrderDetailVoMap, tradeIdAndLogOrderList,
|
|
|
+ logisticsOrderIdAndSubtaskList, waybillOrderIdAndTicketList);
|
|
|
orderResp.setOrderSurplus(orderSurplus.toPlainString());
|
|
|
orderResp.setRemainingAmount(orderSurplus);
|
|
|
|
|
|
@@ -758,6 +762,8 @@ public class WaybillOrderService {
|
|
|
.collect(Collectors.groupingBy(KwtLogisticsOrder::getTOrderId));
|
|
|
Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList = orderSubtaskList.stream()
|
|
|
.collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getLOrderId));
|
|
|
+ // 预加载运单磅单信息,避免在余量计算中出现 N+1 查询
|
|
|
+ Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList = getWaybillOrderIdAndTicketList(orderSubtaskList);
|
|
|
//物流订单商品
|
|
|
List<KwtLogisticsOrderGoods> logOrderGoods = logisticsOrderGoodsRepository.queryByLogOrderIds(logOrderIdList);
|
|
|
if (CollectionUtils.isEmpty(logOrderGoods)) {
|
|
|
@@ -807,7 +813,8 @@ public class WaybillOrderService {
|
|
|
billOrder -> {
|
|
|
return getWaybillOrderResp(billOrder, subtaskMap, logOrderMap, logOrderIdAndCirculateMap,
|
|
|
logOrderIdAndGoodsMap, logOrderIdAndUnitMap, logOrderIdAndAddressMap, ticketMap,
|
|
|
- tradeIdAndOrderDetailVoMap,tradeIdAndLogOrderList,logisticsOrderIdAndSubtaskList,dictValueAndDictResDtoMap, goodsIdAndGoodsMap);
|
|
|
+ tradeIdAndOrderDetailVoMap,tradeIdAndLogOrderList,logisticsOrderIdAndSubtaskList,
|
|
|
+ waybillOrderIdAndTicketList,dictValueAndDictResDtoMap, goodsIdAndGoodsMap);
|
|
|
}).collect(Collectors.toList());
|
|
|
return ordderList;
|
|
|
}
|
|
|
@@ -831,6 +838,7 @@ public class WaybillOrderService {
|
|
|
Map<Long, OrderDetailVo> tradeIdAndOrderDetailVoMap,
|
|
|
Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogOrderList ,
|
|
|
Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList,
|
|
|
+ Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList,
|
|
|
Map<String, Map<String, String>> dictValueAndDictResDtoMap,
|
|
|
Map<Long, KwpGoods> goodsIdAndGoodsMap) {
|
|
|
WaybillOrderStatusResp wbOrderResp = new WaybillOrderStatusResp();
|
|
|
@@ -850,7 +858,8 @@ public class WaybillOrderService {
|
|
|
wbOrderResp.setChargeTypeDesc(DictEnum.getLabel(DictTypeEnum.CHARGING_TYPE.getType(), logOrder.getBillingMode()));
|
|
|
//设置余量
|
|
|
KwtLogisticsOrder order = logOrderMap.getOrDefault(wbOrder.getLOrderId(), new KwtLogisticsOrder());
|
|
|
- BigDecimal supAmount = getSupAmount(order.getTOrderId(), tradeIdAndOrderDetailVoMap, tradeIdAndLogOrderList, logisticsOrderIdAndSubtaskList);
|
|
|
+ BigDecimal supAmount = getSupAmount(order.getTOrderId(), tradeIdAndOrderDetailVoMap, tradeIdAndLogOrderList,
|
|
|
+ logisticsOrderIdAndSubtaskList, waybillOrderIdAndTicketList);
|
|
|
wbOrderResp.setOrderSurplus(supAmount);
|
|
|
//托运企业
|
|
|
KwtLogisticsOrderUnit consignEnt = logOrderIdAndUnitMap.getOrDefault(wbOrder.getLOrderId() + "-" + UnitTypeEnum.CONSIGN.getCode(), new KwtLogisticsOrderUnit());
|
|
|
@@ -925,47 +934,137 @@ public class WaybillOrderService {
|
|
|
|
|
|
}
|
|
|
|
|
|
- private static BigDecimal getSupAmount(Long tradeOrderId,
|
|
|
- Map<Long, OrderDetailVo> tradeIdAndOrderDetailVoMap,
|
|
|
- Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogOrderList,
|
|
|
- Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList) {
|
|
|
- // KwtLogisticsOrder order = logOrderMap.getOrDefault(wbOrder.getLOrderId(), new KwtLogisticsOrder());
|
|
|
+ /**
|
|
|
+ * 计算贸易订单余量
|
|
|
+ * 逻辑:贸易订单总量 - (所有关联物流订单下,非取消/完成状态的子运单委托量 + 对应计费模式的磅单量)
|
|
|
+ *
|
|
|
+ * @param tradeOrderId 贸易订单ID
|
|
|
+ * @param tradeIdAndOrderDetailVoMap 贸易订单详情映射
|
|
|
+ * @param tradeIdAndLogOrderList 贸易订单关联的物流订单列表映射
|
|
|
+ * @param logisticsOrderIdAndSubtaskList 物流订单关联的子运单列表映射
|
|
|
+ * @param waybillOrderIdAndTicketList 运单ID关联的磅单列表映射
|
|
|
+ * @return 订单余量,保留两位小数
|
|
|
+ */
|
|
|
+ private BigDecimal getSupAmount(Long tradeOrderId,
|
|
|
+ Map<Long, OrderDetailVo> tradeIdAndOrderDetailVoMap,
|
|
|
+ Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogOrderList,
|
|
|
+ Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList,
|
|
|
+ Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList) {
|
|
|
+ log.debug("开始计算贸易订单余量,tradeOrderId: {}", tradeOrderId);
|
|
|
+
|
|
|
+ // 1. 获取贸易订单总货物量
|
|
|
OrderDetailVo detailVo = tradeIdAndOrderDetailVoMap.getOrDefault(tradeOrderId, new OrderDetailVo());
|
|
|
BigDecimal tradeAmount = Optional.ofNullable(detailVo).map(OrderDetailVo::getAmount).orElse(BigDecimal.ZERO);
|
|
|
+ log.debug("贸易订单[{}]总货物量: {}", tradeOrderId, tradeAmount);
|
|
|
+
|
|
|
+ // 2. 获取该贸易订单下的所有物流订单
|
|
|
List<KwtLogisticsOrder> kwtLogisticsOrders = tradeIdAndLogOrderList.get(tradeOrderId);
|
|
|
- BigDecimal logTotatalAmount = BigDecimal.ZERO;
|
|
|
- if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)){
|
|
|
- String billingMode = kwtLogisticsOrders.get(0).getBillingMode();
|
|
|
+
|
|
|
+ // 已占用总量初始化
|
|
|
+ BigDecimal usedAmount = BigDecimal.ZERO;
|
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)) {
|
|
|
+ log.debug("贸易订单[{}]关联物流订单数量: {}", tradeOrderId, kwtLogisticsOrders.size());
|
|
|
+
|
|
|
for (KwtLogisticsOrder kwtLogisticsOrder : kwtLogisticsOrders) {
|
|
|
- List<KwtWaybillOrderSubtask> waybillOrderSubtasks = logisticsOrderIdAndSubtaskList.getOrDefault(kwtLogisticsOrder.getId(), new ArrayList<>());
|
|
|
- BigDecimal loadAmountSum = waybillOrderSubtasks.stream()
|
|
|
- .filter(x->!Arrays.asList(CarWaybillV1Enum.COMPLETED.getCode(), CarWaybillV1Enum.CANCELLED.getCode()).contains(x.getStatus()))
|
|
|
+ Long logOrderId = kwtLogisticsOrder.getId();
|
|
|
+ // 获取当前物流订单下的所有子运单
|
|
|
+ List<KwtWaybillOrderSubtask> waybillOrderSubtasks = logisticsOrderIdAndSubtaskList.getOrDefault(logOrderId, Collections.emptyList());
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(waybillOrderSubtasks)) {
|
|
|
+ log.debug("物流订单[{}]无子运单,跳过", logOrderId);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 确定计费模式对应的磅单类型
|
|
|
+ // CHARGING_TYPE_1: 按装货量计费 -> 取装货磅单 (SHIPMENT)
|
|
|
+ // CHARGING_TYPE_2: 按卸货量计费 -> 取卸货磅单 (TAKE)
|
|
|
+ Integer ticketType;
|
|
|
+ String billingMode = kwtLogisticsOrder.getBillingMode();
|
|
|
+ if (StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_1.getValue())) {
|
|
|
+ ticketType = AddressTypeEnum.SHIPMENT.getCode();
|
|
|
+ } else if (StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_2.getValue())) {
|
|
|
+ ticketType = AddressTypeEnum.TAKE.getCode();
|
|
|
+ } else {
|
|
|
+ log.warn("余量计算跳过未知计费模式,tradeOrderId:{}, logOrderId:{}, billingMode:{}",
|
|
|
+ tradeOrderId, logOrderId, billingMode);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 定义需要剔除的状态:已取消、已完成(这些状态下的运单不再占用当前可接单的余量,或者其量已结算)
|
|
|
+ // 注意:具体业务逻辑中,通常“进行中”的运单会占用余量。这里根据原代码逻辑,剔除CANCELLED和COMPLETED。
|
|
|
+ List<Integer> excludeStatusList = Arrays.asList(CarWaybillV1Enum.CANCELLED.getCode(), CarWaybillV1Enum.COMPLETED.getCode());
|
|
|
+
|
|
|
+ // 4. 计算子运单委托量合计(仅统计未取消/未完成的有效子运单)
|
|
|
+ BigDecimal entrustAmount = waybillOrderSubtasks.stream()
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .filter(subtask -> !excludeStatusList.contains(subtask.getStatus()))
|
|
|
.map(KwtWaybillOrderSubtask::getEntrustAmount)
|
|
|
.filter(Objects::nonNull)
|
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- if (org.apache.commons.lang3.StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_1.getValue())){
|
|
|
- BigDecimal unloadAmountSum = waybillOrderSubtasks.stream()
|
|
|
- .filter(x->!Objects.equals(x.getStatus(),CarWaybillV1Enum.CANCELLED.getCode()))
|
|
|
- .map(KwtWaybillOrderSubtask::getLoadAmount)
|
|
|
- .filter(Objects::nonNull)
|
|
|
- .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- logTotatalAmount = logTotatalAmount.add(loadAmountSum).add(unloadAmountSum);
|
|
|
- }else if (org.apache.commons.lang3.StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_2.getValue())){
|
|
|
- BigDecimal unloadAmountSum = waybillOrderSubtasks.stream()
|
|
|
- .filter(x->!Objects.equals(x.getStatus(),CarWaybillV1Enum.CANCELLED.getCode()))
|
|
|
- .map(KwtWaybillOrderSubtask::getUnloadAmount)
|
|
|
- .filter(Objects::nonNull)
|
|
|
- .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- logTotatalAmount = logTotatalAmount.add(loadAmountSum).add(unloadAmountSum);
|
|
|
- }
|
|
|
+
|
|
|
+ log.debug("物流订单[{}]子运单委托量合计: {}", logOrderId, entrustAmount);
|
|
|
|
|
|
- //logTotatalAmount = logTotatalAmount.add(unloadAmountSum);
|
|
|
+ // 5. 计算磅单量合计
|
|
|
+ // 逻辑:通过子运单找到关联的运单ID,再找到对应的磅单,过滤出指定类型(装/卸)的磅单量
|
|
|
+ BigDecimal ticketAmount = waybillOrderSubtasks.stream()
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .filter(subtask -> !Objects.equals(subtask.getStatus(), CarWaybillV1Enum.CANCELLED.getCode()))
|
|
|
+ .map(KwtWaybillOrderSubtask::getWOrderId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ // 展开每个运单ID对应的磅单列表
|
|
|
+ .flatMap(wOrderId -> waybillOrderIdAndTicketList.getOrDefault(wOrderId, Collections.emptyList()).stream())
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ // 只保留符合计费模式的磅单类型(装货或卸货)
|
|
|
+ .filter(ticket -> Objects.equals(ticket.getType(), ticketType))
|
|
|
+ .map(KwtWaybillOrderTicket::getAmount)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+ log.debug("物流订单[{}]磅单量合计(type:{}): {}", logOrderId, ticketType, ticketAmount);
|
|
|
+
|
|
|
+ // 累加到总占用量
|
|
|
+ usedAmount = usedAmount.add(entrustAmount).add(ticketAmount);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- BigDecimal subSurplus = tradeAmount.subtract(logTotatalAmount).compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : tradeAmount.subtract(logTotatalAmount);
|
|
|
- return subSurplus.setScale(2, RoundingMode.HALF_UP);
|
|
|
+ log.debug("贸易订单[{}]总占用量: {}", tradeOrderId, usedAmount);
|
|
|
+
|
|
|
+ // 6. 计算余量:贸易订单总量 - 已占用量
|
|
|
+ // 如果计算结果小于等于0,则余量为0,避免负数
|
|
|
+ BigDecimal surplus = tradeAmount.subtract(usedAmount);
|
|
|
+ BigDecimal finalSurplus = surplus.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : surplus;
|
|
|
+
|
|
|
+ // 保留两位小数,四舍五入
|
|
|
+ BigDecimal result = finalSurplus.setScale(2, RoundingMode.HALF_UP);
|
|
|
+ log.debug("贸易订单[{}]最终余量: {}", tradeOrderId, result);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量构建运单ID与磅单信息映射,供订单余量计算复用。
|
|
|
+ */
|
|
|
+ private Map<Long, List<KwtWaybillOrderTicket>> getWaybillOrderIdAndTicketList(List<KwtWaybillOrderSubtask> orderSubtaskList) {
|
|
|
+ if (CollectionUtils.isEmpty(orderSubtaskList)) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+ List<Long> waybillOrderIds = orderSubtaskList.stream()
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .map(KwtWaybillOrderSubtask::getWOrderId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (CollectionUtils.isEmpty(waybillOrderIds)) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+ List<KwtWaybillOrderTicket> ticketList = waybillOrderTicketRepository.queryByWOrderIds(waybillOrderIds);
|
|
|
+ if (CollectionUtils.isEmpty(ticketList)) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+ return ticketList.stream()
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.groupingBy(KwtWaybillOrderTicket::getWOrderId));
|
|
|
}
|
|
|
|
|
|
/**
|