Explorar o código

feat(order): 添加客户发货单查询功能

- 在IOrderDeliverService中新增listDeliverOrderByCustomerIdPage方法用于分页查询客户发货单
- 在OrderDeliverController中添加getCustomerDeliverOrders接口用于根据客户ID查询发货单
- 在OrderDeliverController中添加getCustomerOrderProductList接口用于根据订单ID查询订单商品
- 在OrderDeliverServiceImpl中实现getCustomerOrderProductList方法处理客户订单商品查询逻辑
- 在OrderDeliverServiceImpl中实现listDeliverOrderByCustomerIdPage方法处理客户发货单分页查询
- 修复StatementOrderServiceImpl中的订单产品处理逻辑,增加空值检查
hurx hai 2 meses
pai
achega
4dfa351e84

+ 7 - 2
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/StatementDetail.java

@@ -48,15 +48,20 @@ public class StatementDetail extends TenantEntity {
     private String type;
 
     /**
-     * 关联的订单id
+     * 关联的订单id----关联的发货单的订单id
      */
     private Long orderId;
 
     /**
-     * 关联的订单编号
+     * 关联的订单编号----订单主表的订单编号
      */
     private String orderNo;
 
+    /**
+     * 订单发货单编号
+     */
+    private String deliverCode;
+
     /**
      * 该明细金额
      */

+ 2 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/bo/StatementDetailBo.java

@@ -51,6 +51,8 @@ public class StatementDetailBo extends BaseEntity {
      */
     private String orderNo;
 
+    private String deliverCode;
+
     /**
      * 该明细金额
      */

+ 2 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/vo/StatementDetailVo.java

@@ -70,6 +70,8 @@ public class StatementDetailVo implements Serializable {
     @ExcelProperty(value = "关联的订单编号")
     private String orderNo;
 
+    private String deliverCode;
+
     /**
      * 该明细金额
      */

+ 8 - 4
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/impl/StatementOrderServiceImpl.java

@@ -128,7 +128,7 @@ public class StatementOrderServiceImpl extends ServiceImpl<StatementOrderMapper,
 
         // 查询客户的所有有效对账单
         LambdaQueryWrapper<StatementOrder> orderWrapper = new LambdaQueryWrapper<>();
-        orderWrapper.eq(StatementOrder::getCustomerId, customerId).ne(StatementOrder::getIsInvoiceStatus, InvoiceStatus.INVOICED.getCode())
+        orderWrapper.eq(StatementOrder::getCustomerId, customerId)//.ne(StatementOrder::getIsInvoiceStatus, InvoiceStatus.INVOICED.getCode())
             .eq(StatementOrder::getDelFlag, "0");
 
         List<StatementOrder> statementOrders = baseMapper.selectList(orderWrapper);
@@ -308,14 +308,18 @@ public class StatementOrderServiceImpl extends ServiceImpl<StatementOrderMapper,
         Map<Long, List<StatementProductBo>> productGroupByOrderId =
             CollectionUtil.isNotEmpty(bo.getProductList())
                 ? bo.getProductList().stream()
+                .filter(product -> product.getOrderId() != null)
                 .collect(Collectors.groupingBy(StatementProductBo::getOrderId))
                 : Collections.emptyMap();
 
-        // 3. 为每个明细,找到对应的商品
+        // 3. 处理每个明细
         for (StatementDetailBo detailBo : bo.getDetailList()) {
-            Long originalOrderId = detailBo.getOrderId();
-            List<StatementProductBo> productListForThisOrder = productGroupByOrderId.get(originalOrderId);
+            Long originalOrderId = detailBo.getOrderId(); // 可能为 null
+            if (originalOrderId == null) {
+                continue; // 跳过无效明细
+            }
 
+            List<StatementProductBo> productListForThisOrder = productGroupByOrderId.get(originalOrderId);
             if (CollectionUtil.isNotEmpty(productListForThisOrder)) {
                 for (StatementProductBo productBo : productListForThisOrder) {
                     StatementProduct product = MapstructUtils.convert(productBo, StatementProduct.class);

+ 31 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderDeliverController.java

@@ -1,11 +1,17 @@
 package org.dromara.order.controller;
 
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.order.domain.OrderDeliver;
+import org.dromara.order.domain.vo.OrderDeliverProductVo;
+import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.order.utils.kd100.domain.TrackVO;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
@@ -113,4 +119,29 @@ public class OrderDeliverController extends BaseController {
                           @PathVariable("ids") Long[] ids) {
         return toAjax(orderDeliverService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    /*根据客户id查询客户对账单对应的订单*/
+    @GetMapping("/getCustomerDeliverOrders/{customerId}")
+    public TableDataInfo<OrderDeliverVo> getCustomerDeliverOrders(@PathVariable Long customerId,
+                                                                  PageQuery pageQuery) {
+        return orderDeliverService.listDeliverOrderByCustomerIdPage(customerId, pageQuery);
+    }
+
+    /**
+     * 根据订单id查询订单商品
+     */
+    @GetMapping("/getCustomerOrderProductList")
+    public TableDataInfo<OrderDeliverProductVo> getCustomerOrderProductList(
+        @RequestParam(value = "orderId", required = false) List<Long> orderIdList) {
+
+        if (CollectionUtils.isEmpty(orderIdList)) {
+            throw new IllegalArgumentException("订单ID列表不能为空");
+        }
+        if (orderIdList.size() > 1000) {
+            throw new IllegalArgumentException("订单ID数量不能超过1000个");
+        }
+
+        Set<Long> uniqueOrderIds = new HashSet<>(orderIdList);
+        return orderDeliverService.getCustomerOrderProductList(uniqueOrderIds);
+    }
 }

+ 12 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderDeliverProduct.java

@@ -6,6 +6,7 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 import java.io.Serial;
+import java.math.BigDecimal;
 
 /**
  * 订单发货商品明细对象 order_deliver_product
@@ -62,6 +63,17 @@ public class OrderDeliverProduct extends TenantEntity {
      */
     private Long deliverNum;
 
+
+    /**
+     * 订单单价(元)
+     */
+    private BigDecimal orderPrice;
+
+    /**
+     * 行小计金额(元)
+     */
+    private BigDecimal subtotal;
+
     private String dataSource;
 
     /**

+ 12 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderDeliverProductBo.java

@@ -9,6 +9,8 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import jakarta.validation.constraints.*;
 
+import java.math.BigDecimal;
+
 /**
  * 订单发货商品明细业务对象 order_deliver_product
  *
@@ -60,6 +62,16 @@ public class OrderDeliverProductBo extends BaseEntity {
      */
     private Long deliverNum;
 
+    /**
+     * 订单单价(元)
+     */
+    private BigDecimal orderPrice;
+
+    /**
+     * 行小计金额(元)
+     */
+    private BigDecimal subtotal;
+
     private String dataSource;
 
     /**

+ 13 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderDeliverProductVo.java

@@ -10,6 +10,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Date;
 
 
@@ -74,6 +75,16 @@ public class OrderDeliverProductVo implements Serializable {
     @ExcelProperty(value = "本次发货数量")
     private Long deliverNum;
 
+    /**
+     * 订单单价(元)
+     */
+    private BigDecimal orderPrice;
+
+    /**
+     * 行小计金额(元)
+     */
+    private BigDecimal subtotal;
+
     /**
      * 备注
      */
@@ -82,5 +93,7 @@ public class OrderDeliverProductVo implements Serializable {
 
     private String dataSource;
 
+    private String orderNo;
+
 
 }

+ 15 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderDeliverVo.java

@@ -10,6 +10,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
@@ -131,5 +132,19 @@ public class OrderDeliverVo implements Serializable {
 
     private Date createTime;
 
+    private String customerName;
+
+    private BigDecimal totalAmount;
+
+    private Date orderTime;
+
+    private Long createBy;
+
+    private String createName;
+
+    private Long createDept;
+
+    private String createDeptName;
+
     private List<OrderDeliverProductVo> deliverProductList;
 }

+ 1 - 1
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/mapper/OrderDeliverMapper.java

@@ -1,8 +1,8 @@
 package org.dromara.order.mapper;
 
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 import org.dromara.order.domain.OrderDeliver;
 import org.dromara.order.domain.vo.OrderDeliverVo;
-import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 
 /**
  * 订单发货主Mapper接口

+ 14 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderDeliverService.java

@@ -2,14 +2,17 @@ package org.dromara.order.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.dromara.order.domain.OrderDeliver;
+import org.dromara.order.domain.vo.OrderDeliverProductVo;
 import org.dromara.order.domain.vo.OrderDeliverVo;
 import org.dromara.order.domain.bo.OrderDeliverBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.order.utils.kd100.domain.TrackVO;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * 订单发货主Service接口
@@ -77,4 +80,15 @@ public interface IOrderDeliverService extends IService<OrderDeliver> {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 分页查询客户发货单
+     *
+     * @param customerId 客户ID
+     * @param pageQuery  分页参数
+     * @return 分页结果
+     */
+    TableDataInfo<OrderDeliverVo> listDeliverOrderByCustomerIdPage(Long customerId, PageQuery pageQuery);
+
+    TableDataInfo<OrderDeliverProductVo> getCustomerOrderProductList(Set<Long> orderIdList);
 }

+ 144 - 6
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderDeliverServiceImpl.java

@@ -1,12 +1,16 @@
 package org.dromara.order.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.enums.InvoiceStatus;
 import org.dromara.common.core.enums.OrderStatus;
 import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.MapstructUtils;
@@ -14,13 +18,14 @@ import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.SequenceUtils;
+import org.dromara.customer.api.RemoteCustomerService;
 import org.dromara.order.domain.OrderDeliver;
 import org.dromara.order.domain.OrderDeliverProduct;
 import org.dromara.order.domain.OrderMain;
+import org.dromara.order.domain.OrderProduct;
 import org.dromara.order.domain.bo.OrderDeliverBo;
 import org.dromara.order.domain.bo.OrderDeliverProductBo;
-import org.dromara.order.domain.vo.OrderDeliverVo;
-import org.dromara.order.domain.vo.OrderQuantitySummary;
+import org.dromara.order.domain.vo.*;
 import org.dromara.order.mapper.OrderDeliverMapper;
 import org.dromara.order.mapper.OrderDeliverProductMapper;
 import org.dromara.order.mapper.OrderMainMapper;
@@ -29,13 +34,13 @@ import org.dromara.order.service.IOrderDeliverService;
 import org.dromara.order.utils.kd100.Kd100Util;
 import org.dromara.order.utils.kd100.domain.QueryTrackDTO;
 import org.dromara.order.utils.kd100.domain.TrackVO;
+import org.dromara.system.api.RemoteDeptService;
+import org.dromara.system.api.RemoteUserService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.math.BigDecimal;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -49,6 +54,15 @@ import java.util.stream.Collectors;
 @Service
 public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, OrderDeliver> implements IOrderDeliverService {
 
+    @DubboReference
+    private RemoteUserService remoteUserService;
+
+    @DubboReference
+    private RemoteDeptService remoteDeptService;
+
+    @DubboReference
+    private RemoteCustomerService remoteCustomerService;
+
     private final OrderDeliverMapper baseMapper;
 
     private final OrderMainMapper orderMainMapper;
@@ -219,6 +233,38 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
         }
     }
 
+    @Override
+    public TableDataInfo<OrderDeliverProductVo> getCustomerOrderProductList(Set<Long> orderIdList) {
+        // 1. 空值与空集合校验
+        if (CollectionUtils.isEmpty(orderIdList)) {
+            return TableDataInfo.build(Collections.emptyList());
+        }
+
+        List<OrderDeliverVo> orderDeliverVoList = baseMapper.selectVoList(
+            new LambdaQueryWrapper<OrderDeliver>()
+                .in(OrderDeliver::getId, orderIdList)
+        );
+
+        /*构建发货id与订单编号对应关系的map*/
+        Map<Long, String> deliverIdToOrderNoMap = orderDeliverVoList.stream()
+            .collect(Collectors.toMap(
+                OrderDeliverVo::getId,
+                OrderDeliverVo::getOrderCode,
+                (v1, v2) -> v1
+            ));
+
+        List<OrderDeliverProductVo> orderProductVoList = orderDeliverProductMapper.selectVoList(
+            new LambdaQueryWrapper<OrderDeliverProduct>()
+                .in(OrderDeliverProduct::getDeliverId, orderIdList)
+        );
+
+        orderProductVoList.forEach(v -> {
+            v.setOrderNo(deliverIdToOrderNoMap.get(v.getDeliverId()));
+        });
+
+        return TableDataInfo.build(orderProductVoList);
+    }
+
     /**
      * 修改订单发货主
      *
@@ -267,6 +313,7 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
             .map(bo -> {
                 OrderDeliverProduct product = MapstructUtils.convert(bo, OrderDeliverProduct.class);
                 product.setDeliverId(deliverId);
+                product.setSubtotal(product.getOrderPrice().multiply(BigDecimal.valueOf(product.getDeliverNum())));
                 return product;
             })
             .collect(Collectors.toList());
@@ -276,6 +323,97 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
         }
     }
 
+    @Override
+    public TableDataInfo<OrderDeliverVo> listDeliverOrderByCustomerIdPage(Long customerId, PageQuery pageQuery) {
+        if (customerId == null) {
+            return TableDataInfo.build(new Page<>(0, 0));
+        }
+
+        // 查询客户的所有有效订单
+        LambdaQueryWrapper<OrderMain> orderWrapper = new LambdaQueryWrapper<>();
+        orderWrapper.eq(OrderMain::getCustomerId, customerId)
+            .eq(OrderMain::getDelFlag, "0");
+
+        List<OrderMain> orderMainList = orderMainMapper.selectList(orderWrapper);
+        if (orderMainList.isEmpty()) {
+            return TableDataInfo.build(new Page<>(0, 0));
+        }
+
+        List<Long> orderIds = orderMainList.stream()
+            .map(OrderMain::getId)
+            .collect(Collectors.toList());
+
+        // 构建 orderId -> totalAmount 映射
+        Map<Long, BigDecimal> orderIdToAmountMap = orderMainList.stream()
+            .collect(Collectors.toMap(
+                OrderMain::getId,
+                OrderMain::getTotalAmount,
+                (v1, v2) -> v1
+            ));
+
+        // 构建 orderId -> orderTime 映射
+        Map<Long, Date> orderIdToorderTimeMap = orderMainList.stream()
+            .collect(Collectors.toMap(
+                OrderMain::getId,
+                OrderMain::getOrderTime,
+                (v1, v2) -> v1
+            ));
+
+        Set<Long> createUserIds = orderMainList.stream().map(OrderMain::getCreateBy).collect(Collectors.toSet());
+        Set<Long> createDeptIds = orderMainList.stream().map(OrderMain::getCreateDept).collect(Collectors.toSet());
+
+        final Map<Long, String> userMap = new HashMap<>();
+        if (!createUserIds.isEmpty()) {
+            userMap.putAll(remoteUserService.selectUserNamesByIds(new ArrayList<>(createUserIds)));
+        }
+
+        final Map<Long, String> deptMap = new HashMap<>();
+        if (!createDeptIds.isEmpty()) {
+            deptMap.putAll(remoteDeptService.selectDeptNameByIds(new HashSet<>(createDeptIds)));
+        }
+
+        // 查询明细(分页)
+        LambdaQueryWrapper<OrderDeliver> deliverWrapper = new LambdaQueryWrapper<>();
+        deliverWrapper.in(OrderDeliver::getOrderId, orderIds)
+            .eq(OrderDeliver::getDelFlag, "0");
+
+        Page<OrderDeliverVo> pageResult = baseMapper.selectVoPage(pageQuery.build(), deliverWrapper);
+        List<OrderDeliverVo> records = pageResult.getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            // 1. 提取所有 deliverId
+            List<Long> deliverIds = records.stream()
+                .map(OrderDeliverVo::getId)
+                .collect(Collectors.toList());
+
+            // 批量查询所有商品明细
+            List<OrderDeliverProductVo> allProducts = orderDeliverProductMapper.selectVoList(
+                new LambdaQueryWrapper<OrderDeliverProduct>()
+                    .in(OrderDeliverProduct::getDeliverId, deliverIds)
+            );
+
+            // 安全聚合:处理 null subtotal
+            Map<Long, BigDecimal> deliverIdToTotalAmount = allProducts.stream()
+                .collect(Collectors.groupingBy(
+                    OrderDeliverProductVo::getDeliverId,
+                    Collectors.reducing(
+                        BigDecimal.ZERO,
+                        product -> Optional.ofNullable(product.getSubtotal()).orElse(BigDecimal.ZERO),
+                        BigDecimal::add
+                    )
+                ));
+
+            // 4. 回填 totalAmount 和其他字段
+            for (OrderDeliverVo record : records) {
+                record.setTotalAmount(deliverIdToTotalAmount.getOrDefault(record.getId(), BigDecimal.ZERO));
+                record.setCreateName(userMap.getOrDefault(record.getCreateBy(), "未知用户"));
+                record.setCreateDeptName(deptMap.getOrDefault(record.getCreateDept(), "未知部门"));
+                record.setOrderTime(orderIdToorderTimeMap.get(record.getOrderId()));
+            }
+        }
+
+        return TableDataInfo.build(pageResult);
+    }
+
     /**
      * 保存前的数据校验
      */

+ 2 - 2
ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderDeliverMapper.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper
-PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.dromara.order.mapper.OrderDeliverMapper">
 
 </mapper>

+ 2 - 3
ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderProductMapper.xml

@@ -83,13 +83,12 @@
     </select>
 
     <select id="getAssignmentStats" resultType="org.dromara.order.domain.dto.AssignmentStatsDto">
-        SELECT COUNT(*)                                                 AS total,
-               SUM(CASE WHEN assignment_status = '1' THEN 1 ELSE 0 END) AS assigned
+        SELECT COUNT(*)                                                              AS total,
+               COALESCE(SUM(CASE WHEN assignment_status = '1' THEN 1 ELSE 0 END), 0) AS assigned
         FROM order_product
         WHERE order_id = #{parentId}
           AND original_item_id IS NULL
     </select>
-
     <update id="updateAssignmentInfo">
         UPDATE order_product
         SET assignment_status = #{assignmentStatus},