Quellcode durchsuchen

```
refactor(order): 优化订单发货服务的多级订单状态同步逻辑

- 添加OrderMainVo导入以支持多级订单查询
- 修改queryPageList方法提取records变量便于后续处理
- 实现getAllChildOrderIds方法支持递归查询订单及其所有子订单
- 更新查询逻辑支持按订单ID查询当前订单及所有子订单的发货记录
- 重构发货状态更新逻辑支持1-3级订单的层级状态同步
- 添加updateOrderDeliveryStatus方法实现多级订单独立计算发货状态

```

hurx vor 1 Woche
Ursprung
Commit
3b204e0c00

+ 220 - 50
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderDeliverServiceImpl.java

@@ -28,6 +28,7 @@ import org.dromara.order.domain.bo.OrderDeliverBo;
 import org.dromara.order.domain.bo.OrderDeliverProductBo;
 import org.dromara.order.domain.vo.OrderDeliverProductVo;
 import org.dromara.order.domain.vo.OrderDeliverVo;
+import org.dromara.order.domain.vo.OrderMainVo;
 import org.dromara.order.domain.vo.OrderQuantitySummary;
 import org.dromara.order.mapper.*;
 import org.dromara.order.service.IOrderDeliverService;
@@ -113,6 +114,8 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
     public TableDataInfo<OrderDeliverVo> queryPageList(OrderDeliverBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<OrderDeliver> lqw = buildQueryWrapper(bo);
         Page<OrderDeliverVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        List<OrderDeliverVo> records = result.getRecords();
+
         return TableDataInfo.build(result);
     }
 
@@ -188,7 +191,14 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<OrderDeliver> lqw = Wrappers.lambdaQuery();
         lqw.orderByDesc(OrderDeliver::getId);
-        lqw.eq(bo.getOrderId() != null, OrderDeliver::getOrderId, bo.getOrderId());
+        
+        // 处理订单ID查询:支持查询当前订单及其所有子订单的发货记录
+        if (bo.getOrderId() != null) {
+            // 获取当前订单及其所有子订单的ID列表
+            List<Long> targetOrderIds = getAllChildOrderIds(bo.getOrderId());
+            lqw.in(OrderDeliver::getOrderId, targetOrderIds);
+        }
+        
         lqw.eq(StringUtils.isNotBlank(bo.getOrderCode()), OrderDeliver::getOrderCode, bo.getOrderCode());
         lqw.eq(StringUtils.isNotBlank(bo.getLogisticPackNo()), OrderDeliver::getLogisticPackNo, bo.getLogisticPackNo());
         lqw.eq(StringUtils.isNotBlank(bo.getDeliverMethod()), OrderDeliver::getDeliverMethod, bo.getDeliverMethod());
@@ -265,51 +275,65 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
                 newStatus = OrderStatus.PARTIALLY_SHIPPED.getCode();
             }
 
-            // 6. 插入发货单主表和明细 (略,保持你原有的逻辑)
+            // 6. 插入发货单主表和明细
             OrderDeliver deliver = MapstructUtils.convert(bo, OrderDeliver.class);
             validEntityBeforeSave(deliver);
             boolean inserted = baseMapper.insert(deliver) > 0;
             if (!inserted) return false;
             bo.setId(deliver.getId());
             saveOrderDeliverProducts(deliver.getId(), bo.getOrderDeliverProducts(), false);
+            // 7. 处理父订单状态同步 - 根据订单层级更新不同级别订单的发货状态
+            Integer currentLevel = orderMain.getCurrentLevel();
+            if (currentLevel == null) currentLevel = 1;
+
+            if (currentLevel == 3) {
+                // 3级订单发货:需要更新3级、2级、1级订单的发货状态
+                // 第一步:直接更新当前3级订单(通过发货单的order_id)
+                updateOrderDeliveryStatus(orderId, null, null, null);
+
+                // 第二步:通过subOrderId找到2级订单并更新
+                if (orderMain.getSubOrderId() != null) {
+                    updateOrderDeliveryStatus(orderMain.getSubOrderId(), null, null, null);
+                }
 
-            // 7. 【核心修复】更新订单主表
-            // 必须同时更新:1. 已发货数量 2. 订单状态
-            // 并且要带上版本号或条件判断,防止并发覆盖
-            LambdaUpdateWrapper<OrderMain> updateWrapper = new LambdaUpdateWrapper<OrderMain>()
-                .eq(OrderMain::getId, orderId)
-                // 乐观锁检查:确保更新时的基础数量和我们计算时的一致,防止中间被别人改了
-                // 如果你的表有 version 字段,优先用 version
-                // .eq(OrderMain::getVersion, orderMain.getVersion())
-                // 如果没有 version,至少校验当前已发货数量是否变动(防止重复提交或并发)
-                .eq(OrderMain::getQuantityShipped, currentDeliveredQty)
-                .set(OrderMain::getQuantityShipped, newDeliveredTotalQty)
-                .set(OrderMain::getOrderStatus, newStatus);
-
-            // 如果使用了 version,这里也要 +1
-            // .set(OrderMain::getVersion, orderMain.getVersion() + 1)
+                // 第三步:通过parentOrderId找到1级订单并更新
+                if (orderMain.getParentOrderId() != null) {
+                    updateOrderDeliveryStatus(orderMain.getParentOrderId(), null, null, null);
+                }
+            } else if (currentLevel == 2) {
+                // 2级订单发货:需要更新2级、1级订单的发货状态
+                updateOrderDeliveryStatus(orderId, null, null, null);
 
-            int updateCount = orderMainMapper.update(null, updateWrapper);
-            if (updateCount == 0) {
-                // 更新失败,说明数据被其他人修改了(并发冲突),抛出异常让事务回滚,前端重试
-                throw new RuntimeException("订单状态更新失败,可能存在并发操作,请刷新后重试");
+                // 更新1级订单(parentOrderId)
+                if (orderMain.getParentOrderId() != null) {
+                    updateOrderDeliveryStatus(orderMain.getParentOrderId(), null, null, null);
+                }
+            } else {
+                // 1级订单发货:只更新当前订单
+                updateOrderDeliveryStatus(orderId, null, null, null);
             }
+
             /*中车订单发货后调用接口通知中车*/
             if ("zhongche".equals(orderMain.getDataSource())) {
-                OrderMainCrrcExt orderMainCrrcExt = orderMainCrrcExtService.getById(bo.getOrderId());
+                if (orderMain.getCurrentLevel() == 1) {
+                    orderId = orderMain.getId();
+                } else {
+                    orderId = orderMain.getParentOrderId();
+                }
+                OrderMainCrrcExt orderMainCrrcExt = orderMainCrrcExtService.getById(orderId);
                 ZhongCheOrderDeliverBo zhongCheOrderDeliverBo = new ZhongCheOrderDeliverBo();
                 zhongCheOrderDeliverBo.setOrderNo(orderMainCrrcExt.getCrrcOrderNo());
-                if (Objects.equals(bo.getDeliverMethod(),"0")) {
+                if (Objects.equals(bo.getDeliverMethod(), "0")) {
                     zhongCheOrderDeliverBo.setDeliveryType("2");
-                }else if (Objects.equals(bo.getDeliverMethod(),"1")){
+                } else if (Objects.equals(bo.getDeliverMethod(), "1")) {
                     zhongCheOrderDeliverBo.setDeliveryType("1");
-                    if(ObjectUtil.isNotEmpty(bo.getLogisticsCompanyName())){
+                    if (ObjectUtil.isNotEmpty(bo.getLogisticsCompanyName())) {
                         zhongCheOrderDeliverBo.setExpressCode(bo.getLogisticNo());
                         zhongCheOrderDeliverBo.setExpressCompanyName(bo.getLogisticsCompanyName());
-                    }else{
-                        String companyName = remoteComLogisticsCompanyService.selectLogisticsCompanyNameById(bo.getLogisticsCompanyId());
+                    } else {
+//                        String companyName = remoteComLogisticsCompanyService.selectLogisticsCompanyNameById(bo.getLogisticsCompanyId());
                         zhongCheOrderDeliverBo.setExpressCode(bo.getLogisticNo());
-                        zhongCheOrderDeliverBo.setExpressCompanyName(companyName);
+                        zhongCheOrderDeliverBo.setExpressCompanyName(null);
                     }
                 }
                 List<OrderDeliverGoods> orderDeliverGoods = bo.getOrderDeliverProducts().stream().map(orderDeliverProductBo -> {
@@ -319,27 +343,32 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
                     return zhongCheOrderDeliverGoods;
                 }).toList();
                 zhongCheOrderDeliverBo.setOrderDeliverGoods(orderDeliverGoods);
-                ZhongCheOrderDeliverVo zhongCheOrderDeliverVo = remoteZhongChePullService.mallOrderDeliverGoods(zhongCheOrderDeliverBo);
+//                ZhongCheOrderDeliverVo zhongCheOrderDeliverVo = remoteZhongChePullService.mallOrderDeliverGoods(zhongCheOrderDeliverBo);
                 //保存第三方订单发货信息
                 OrderDeliverThird orderDeliverThird = new OrderDeliverThird();
                 orderDeliverThird.setDeliverId(deliver.getId());
                 orderDeliverThird.setOrderId(orderId);
-                orderDeliverThird.setOutgoingCode(zhongCheOrderDeliverVo.getOutgoingCode());
-                orderDeliverThirdService.save(orderDeliverThird);
+                orderDeliverThird.setOutgoingCode(null);
+//                orderDeliverThirdService.save(orderDeliverThird);
             }
             /*同济订单发货后调用接口通知同济*/
             if ("tongji".equals(orderMain.getDataSource())) {
+                if (orderMain.getCurrentLevel() == 1) {
+                    orderId = orderMain.getId();
+                } else {
+                    orderId = orderMain.getParentOrderId();
+                }
                 OrderMainCrrcExt orderMainCrrcExt = orderMainCrrcExtService.getById(bo.getOrderId());
                 ZhongCheOrderDeliverBo zhongCheOrderDeliverBo = new ZhongCheOrderDeliverBo();
                 zhongCheOrderDeliverBo.setOrderNo(orderMainCrrcExt.getCrrcOrderNo());
-                if (Objects.equals(bo.getDeliverMethod(),"0")) {
+                if (Objects.equals(bo.getDeliverMethod(), "0")) {
                     zhongCheOrderDeliverBo.setDeliveryType("2");
-                }else if (Objects.equals(bo.getDeliverMethod(),"1")){
+                } else if (Objects.equals(bo.getDeliverMethod(), "1")) {
                     zhongCheOrderDeliverBo.setDeliveryType("1");
-                    if(ObjectUtil.isNotEmpty(bo.getLogisticsCompanyName())){
+                    if (ObjectUtil.isNotEmpty(bo.getLogisticsCompanyName())) {
                         zhongCheOrderDeliverBo.setExpressCode(bo.getLogisticNo());
                         zhongCheOrderDeliverBo.setExpressCompanyName(bo.getLogisticsCompanyName());
-                    }else{
+                    } else {
                         String companyName = remoteComLogisticsCompanyService.selectLogisticsCompanyNameById(bo.getLogisticsCompanyId());
                         zhongCheOrderDeliverBo.setExpressCode(bo.getLogisticNo());
                         zhongCheOrderDeliverBo.setExpressCompanyName(companyName);
@@ -361,21 +390,6 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
                 orderDeliverThirdService.save(orderDeliverThird);
             }
 
-            // 8. 处理父订单状态同步
-            // 只有当当前子单成功更新为 SHIPPED 时,才需要检查父订单
-            if (OrderStatus.SHIPPED.getCode().equals(newStatus)) {
-                syncParentOrderStatus(orderId, orderMain.getParentOrderId());
-            } else if (OrderStatus.PARTIALLY_SHIPPED.getCode().equals(newStatus)) {
-                // 部分发货时,父订单理论上至少是部分发货
-                if (orderMain.getParentOrderId() != null) {
-                    LambdaUpdateWrapper<OrderMain> parentPartialWrapper = new LambdaUpdateWrapper<OrderMain>()
-                        .eq(OrderMain::getId, orderMain.getParentOrderId())
-                        .ne(OrderMain::getOrderStatus, OrderStatus.PARTIALLY_SHIPPED.getCode())
-                        // 只有当父订单状态是“未发货”或其他非部分/全发状态时才升级
-                        .set(OrderMain::getOrderStatus, OrderStatus.PARTIALLY_SHIPPED.getCode());
-                    orderMainMapper.update(null, parentPartialWrapper);
-                }
-            }
 
             if ("0".equals(bo.getDeliverMethod())) {
                 OrderStatusLog orderStatusLog = new OrderStatusLog();
@@ -711,4 +725,160 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
         }
         return trackVO;
     }
+
+    /**
+     * 更新订单发货状态(支持多级订单独立计算)
+     *
+     * @param orderId              订单ID
+     * @param newStatus            新状态(如果为null,则重新计算)
+     * @param currentDeliveredQty  当前已发货数量(如果为null,则从数据库查询)
+     * @param newDeliveredTotalQty 新的累计发货数量(如果为null,则重新计算)
+     */
+    private void updateOrderDeliveryStatus(Long orderId, String newStatus, Long currentDeliveredQty, Long newDeliveredTotalQty) {
+        if (orderId == null) {
+            return;
+        }
+
+        // 1. 查询订单信息
+        OrderMain orderMain = orderMainMapper.selectById(orderId);
+        if (orderMain == null) {
+            log.warn("订单不存在,无法更新发货状态: {}", orderId);
+            return;
+        }
+
+        // 2. 如果没有传入新状态,则需要重新计算
+        if (newStatus == null || currentDeliveredQty == null || newDeliveredTotalQty == null) {
+            // 查询该订单及其所有子订单的发货记录,重新计算已发货数量
+            List<Long> targetOrderIds = getAllChildOrderIds(orderId);
+
+            log.info("开始重新计算订单发货状态,订单ID: {}, 包含的订单IDs: {}", orderId, targetOrderIds);
+
+            // 先查询这些订单对应的发货单ID列表
+            List<OrderDeliver> delivers = baseMapper.selectList(
+                new LambdaQueryWrapper<OrderDeliver>()
+                    .in(OrderDeliver::getOrderId, targetOrderIds)
+                    .select(OrderDeliver::getId, OrderDeliver::getOrderId)
+            );
+
+            List<Long> deliverIds = delivers.stream()
+                .map(OrderDeliver::getId)
+                .collect(Collectors.toList());
+
+            log.info("订单ID: {} 对应的发货单IDs: {}", orderId, deliverIds);
+
+            // 再根据发货单ID查询发货商品明细
+            long totalDeliveredQty = 0;
+            if (!deliverIds.isEmpty()) {
+                List<OrderDeliverProductVo> deliverProducts = orderDeliverProductMapper.selectVoList(
+                    new LambdaQueryWrapper<OrderDeliverProduct>()
+                        .in(OrderDeliverProduct::getDeliverId, deliverIds)
+                );
+
+                // 累加该订单及其子订单的总发货数量
+                totalDeliveredQty = deliverProducts.stream()
+                    .mapToLong(OrderDeliverProductVo::getDeliverNum)
+                    .sum();
+
+                log.info("订单ID: {} 的发货商品明细数量: {}, 累计发货数量: {}",
+                    orderId, deliverProducts.size(), totalDeliveredQty);
+            } else {
+                log.warn("订单ID: {} 没有找到对应的发货单,targetOrderIds: {}", orderId, targetOrderIds);
+            }
+
+            // 获取订单总数量(使用当前订单的总数量)
+            Long orderTotalQty = orderMain.getProductQuantity();
+            if (orderTotalQty == null || orderTotalQty == 0) {
+                // 如果主表没有,从商品明细统计
+                OrderQuantitySummary summary = orderProductMapper.selectOrderAndDeliveredQuantity(orderId);
+                orderTotalQty = Optional.ofNullable(summary.getOrderTotalQty()).orElse(0L);
+            }
+
+            // 计算新状态
+            if (totalDeliveredQty <= 0) {
+                // 如果没有发货记录,保持原状态,但如果原状态是待确认/待支付,则改为待发货
+                if (OrderStatus.PENDING_CONFIRMATION.getCode().equals(orderMain.getOrderStatus()) ||
+                    OrderStatus.PENDING_PAYMENT.getCode().equals(orderMain.getOrderStatus())) {
+                    newStatus = OrderStatus.PENDING_SHIPMENT.getCode();
+                } else {
+                    newStatus = orderMain.getOrderStatus();
+                }
+                log.info("订单ID: {} 没有发货记录,保持原状态或改为待发货: {}", orderId, newStatus);
+            } else if (totalDeliveredQty >= orderTotalQty) {
+                newStatus = OrderStatus.SHIPPED.getCode();
+                log.info("订单ID: {} 发货完成,发货数量: {}, 订单总数: {}", orderId, totalDeliveredQty, orderTotalQty);
+            } else {
+                newStatus = OrderStatus.PARTIALLY_SHIPPED.getCode();
+                log.info("订单ID: {} 部分发货,发货数量: {}, 订单总数: {}", orderId, totalDeliveredQty, orderTotalQty);
+            }
+
+            currentDeliveredQty = totalDeliveredQty;
+            newDeliveredTotalQty = totalDeliveredQty;
+        }
+
+        // 3. 更新订单发货状态
+        if (newStatus != null && !newStatus.equals(orderMain.getOrderStatus())) {
+            LambdaUpdateWrapper<OrderMain> updateWrapper = new LambdaUpdateWrapper<OrderMain>()
+                .eq(OrderMain::getId, orderId)
+                .set(OrderMain::getQuantityShipped, newDeliveredTotalQty)
+                .set(OrderMain::getOrderStatus, newStatus);
+
+            int updateCount = orderMainMapper.update(null, updateWrapper);
+            if (updateCount > 0) {
+                log.info("成功更新订单发货状态,订单ID: {}, 新状态: {}, 已发货数量: {}",
+                    orderId, newStatus, newDeliveredTotalQty);
+            } else {
+                log.warn("更新订单发货状态失败,订单ID: {}", orderId);
+            }
+        }
+    }
+
+    /**
+     * 获取订单及其所有子订单的ID列表(递归查询)
+     * <p>
+     * 查询规则:
+     * - 通过 parentOrderId 查找直接子订单
+     * - 通过 subOrderId 查找间接子订单(3级订单场景)
+     *
+     * @param orderId 订单ID
+     * @return 订单ID列表(包含自身和所有子订单)
+     */
+    private List<Long> getAllChildOrderIds(Long orderId) {
+        List<Long> result = new ArrayList<>();
+        result.add(orderId);
+
+        // 1. 查询直接子订单(parentOrderId = 当前订单ID)
+        List<OrderMain> directChildOrders = orderMainMapper.selectList(
+            new LambdaQueryWrapper<OrderMain>()
+                .eq(OrderMain::getParentOrderId, orderId)
+                .select(OrderMain::getId)
+        );
+
+        for (OrderMain child : directChildOrders) {
+            if (!result.contains(child.getId())) {
+                result.add(child.getId());
+                // 递归查询子订单的子订单
+                List<Long> grandChildIds = getAllChildOrderIds(child.getId());
+                result.addAll(grandChildIds);
+            }
+        }
+
+        // 2. 查询间接子订单(subOrderId = 当前订单ID,用于3级订单场景)
+        List<OrderMain> indirectChildOrders = orderMainMapper.selectList(
+            new LambdaQueryWrapper<OrderMain>()
+                .eq(OrderMain::getSubOrderId, orderId)
+                .select(OrderMain::getId)
+        );
+
+        for (OrderMain child : indirectChildOrders) {
+            if (!result.contains(child.getId())) {
+                result.add(child.getId());
+                // 递归查询子订单的子订单
+                List<Long> grandChildIds = getAllChildOrderIds(child.getId());
+                result.addAll(grandChildIds);
+            }
+        }
+
+        log.debug("订单ID: {} 的所有子订单IDs: {}", orderId, result);
+        return result;
+    }
 }