From a45c4fb6232faf2f23b7b2ba45416f11a5390d77 Mon Sep 17 00:00:00 2001
From: buhuazhen <hua100783@gmail.com>
Date: 星期六, 21 三月 2026 16:50:15 +0800
Subject: [PATCH] feat(purchase): 完善采购退货模块及关联退货数量统计

---
 src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java                    |   32 ++++
 src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java                     |    6 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java |   77 +++++++++
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java       |    6 
 src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java          |    6 
 src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java                         |    8 +
 src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml                        |    6 
 src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java                   |    1 
 src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml           |   11 +
 src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java                     |    2 
 src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java    |    8 +
 src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml                  |    6 
 src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java                |   21 ++
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                       |    6 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java             |  195 ++++++++++++------------
 src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java            |   12 +
 src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java          |    1 
 src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java         |   22 ++
 src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java     |    7 
 src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java                   |   38 ++++
 20 files changed, 361 insertions(+), 110 deletions(-)

diff --git a/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java b/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java
index 37ee471..5e8fe53 100644
--- a/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java
@@ -8,6 +8,7 @@
     CUSTOMIZATION_STOCK_OUT("1", "鍚堟牸鑷畾涔夊嚭搴�"),
     PRODUCTION_REPORT_STOCK_OUT("3", "鐢熶骇鎶ュ伐-鍑哄簱"),
     SALE_STOCK_OUT("8", "閿�鍞�-鍑哄簱"),
+    PURCHASE_RETURN_STOCK_OUT("9", "閲囪喘閫�璐�"),
     SALE_SHIP_STOCK_OUT("13", "閿�鍞�-鍙戣揣鍑哄簱");
 
     private final String code;
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
index 1e56411..c23fd4a 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
@@ -46,4 +46,12 @@
         }
         return AjaxResult.success(purchaseReturnOrdersService.add(purchaseReturnOrderDto));
     }
+
+
+    @GetMapping("/selectById/{id}")
+    public AjaxResult selectById(@PathVariable Long id) {
+        return AjaxResult.success(purchaseReturnOrdersService.getPurchaseReturnOrderDtoById(id));
+    }
+
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java b/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java
index a154c94..192bea5 100644
--- a/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java
@@ -82,4 +82,16 @@
     @Excel(name = "褰曞叆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private Date entryDate;
 
+    /**
+     * 閫�璐ф暟閲�
+     */
+    @Excel(name = "閫�璐ф暟閲�")
+
+    private BigDecimal returnQuantity;
+
+    /**
+     * 閫�璐ч噾棰�
+     */
+    @Excel(name = "閫�璐ч噾棰�")
+    private BigDecimal returnAmount;
 }
diff --git a/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java b/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java
index f10a853..c0b98e6 100644
--- a/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java
@@ -11,6 +11,7 @@
     // 鏄惁浣跨敤绯荤粺鍗曞彿
     private Boolean isDefaultNo;
 
+    private String supplierName;
 
     private List<PurchaseReturnOrderProductsDto> purchaseReturnOrderProductsDtos;
 }
diff --git a/src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java b/src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java
new file mode 100644
index 0000000..dc9220a
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java
@@ -0,0 +1,21 @@
+package com.ruoyi.purchase.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/21
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SimpleReturnOrderGroupDto implements Serializable {
+    private Long salesLedgerProductId;
+    private BigDecimal sumReturnQuantity;
+}
diff --git a/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java b/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java
index f4ab57b..89aa81d 100644
--- a/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java
+++ b/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java
@@ -1,8 +1,13 @@
 package com.ruoyi.purchase.mapper;
 
+import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
 import com.ruoyi.purchase.pojo.PurchaseReturnOrderProducts;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
 
 /**
  * <p>
@@ -14,5 +19,5 @@
  */
 @Mapper
 public interface PurchaseReturnOrderProductsMapper extends BaseMapper<PurchaseReturnOrderProducts> {
-
+    List<SimpleReturnOrderGroupDto> getReturnOrderGroupListByProductIds(@NotNull @Param("productIds") List<Long> productIds);
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java
index 3de6e3d..5ff997f 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java
@@ -13,8 +13,10 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import io.swagger.models.auth.In;
 import lombok.Getter;
 import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -57,8 +59,14 @@
     @ApiModelProperty("鍒跺崟浜篿d")
     private Long preparedUserId;
 
+    @ApiModelProperty("鍒跺崟浜哄悕绉�")
+    private String preparedUserName;
+
     @ApiModelProperty("閫�鏂欎汉id")
     private Long returnUserId;
+
+    @ApiModelProperty("閫�鏂欎汉鍚嶇О")
+    private String returnUserName;
 
     @ApiModelProperty("閲囪喘璁㈠崟id")
     private Long purchaseLedgerId;
@@ -77,9 +85,33 @@
 
     @ApiModelProperty("褰曞叆鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
     @ApiModelProperty("鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
+
+    @ApiModelProperty("鏀跺叆绫诲瀷")
+    @TableField(value = "income_type")
+    private Integer incomeType;
+
+
+    /**
+     *
+     */
+    @TableField(value = "create_user",fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(value = "update_user",fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(value = "create_user_name", fill = FieldFill.INSERT)
+    private String createUserName;
+
+    @TableField(value = "update_user_name", fill = FieldFill.INSERT_UPDATE)
+    private String updateUserName;
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java b/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java
index 6ec7650..ff71adf 100644
--- a/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java
+++ b/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java
@@ -5,7 +5,10 @@
 import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
 import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.purchase.vo.PurchaseReturnDetailsVo;
 import com.ruoyi.purchase.vo.PurchaseReturnOrderVo;
+
+import javax.validation.constraints.NotNull;
 
 /**
  * <p>
@@ -19,4 +22,7 @@
     IPage<PurchaseReturnOrderVo> listPage(Page page, PurchaseReturnOrderDto purchaseReturnOrderDto);
 
     Boolean add(PurchaseReturnOrderDto purchaseReturnOrderDto);
+
+
+    PurchaseReturnDetailsVo getPurchaseReturnOrderDtoById(@NotNull Long id);
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index d71b3bb..b23148a 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -159,6 +159,12 @@
         if (StringUtils.isNotBlank(purchaseLedger.getPurchaseContractNumber())) {
             queryWrapper.like(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber());
         }
+        if(purchaseLedger.getSupplierId()!=null){
+            queryWrapper.eq(PurchaseLedger::getSupplierId, purchaseLedger.getSupplierId());
+        }
+        if (purchaseLedger.getApprovalStatus() != null) {
+            queryWrapper.eq(PurchaseLedger::getApprovalStatus, purchaseLedger.getApprovalStatus());
+        }
         return purchaseLedgerMapper.selectList(queryWrapper);
     }
 
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
index 37c2f5b..5e40d8a 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
@@ -1,22 +1,41 @@
 package com.ruoyi.purchase.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.pojo.AccountIncome;
+import com.ruoyi.account.service.AccountIncomeService;
+import com.ruoyi.common.enums.SaleEnum;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.procurementrecord.utils.StockUtils;
 import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
 import com.ruoyi.purchase.dto.PurchaseReturnOrderProductsDto;
 import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
-import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrderProducts;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import com.ruoyi.purchase.service.PurchaseReturnOrdersService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.purchase.vo.PurchaseReturnDetailsVo;
 import com.ruoyi.purchase.vo.PurchaseReturnOrderVo;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.service.ISalesLedgerService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
 /**
  * <p>
- *  鏈嶅姟瀹炵幇绫�
+ * 鏈嶅姟瀹炵幇绫�
  * </p>
  *
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
@@ -29,6 +48,12 @@
     @Autowired
     private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
 
+    @Autowired
+    private ISalesLedgerService salesLedgerService;
+
+    @Resource
+    private AccountIncomeService accountIncomeService;
+
     @Override
     public IPage<PurchaseReturnOrderVo> listPage(Page page, PurchaseReturnOrderDto purchaseReturnOrderDto) {
         return purchaseReturnOrdersMapper.listPage(page, purchaseReturnOrderDto);
@@ -38,14 +63,58 @@
     @Transactional(rollbackFor = Exception.class)
     public Boolean add(PurchaseReturnOrderDto purchaseReturnOrderDto) {
         this.save(purchaseReturnOrderDto);
+
         if (!purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos().isEmpty()) {
-            for (PurchaseReturnOrderProductsDto purchaseReturnOrderProductsDto :purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos()) {
+            for (PurchaseReturnOrderProductsDto purchaseReturnOrderProductsDto : purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos()) {
                 purchaseReturnOrderProductsDto.setSalesLedgerProductId(purchaseReturnOrderProductsDto.getSalesLedgerProductId());
                 purchaseReturnOrderProductsDto.setPurchaseReturnOrderId(purchaseReturnOrderDto.getId());
                 purchaseReturnOrderProductsDto.setReturnQuantity(purchaseReturnOrderProductsDto.getReturnQuantity());
+                // 杩欓噷涓烘柊澧炲洜姝d涓簄ull
+                purchaseReturnOrderProductsDto.setId(null);
                 purchaseReturnOrderProductsMapper.insert(purchaseReturnOrderProductsDto);
             }
+        }else {
+            throw new RuntimeException("璇烽�夋嫨閫�璐у晢鍝�");
         }
+
+        // 瀵硅储鍔$鐞嗗彴璐︽坊鍔犱竴绗旇繘璐︽敹鍏�.
+        AccountIncome accountIncome = new AccountIncome();
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        accountIncome.setInputUser(loginUser.getUsername());
+        accountIncome.setIncomeMoney(purchaseReturnOrderDto.getTotalAmount());
+        accountIncome.setIncomeDate(DateUtils.toDate(purchaseReturnOrderDto.getPreparedAt()));
+        accountIncome.setInputTime(DateUtils.toDate(purchaseReturnOrderDto.getPreparedAt()));
+        accountIncome.setBusinessId(purchaseReturnOrderDto.getId());
+        accountIncome.setBusinessType(1);
+        accountIncome.setIncomeType("4");
+        accountIncome.setCustomerName(purchaseReturnOrderDto.getSupplierName());
+        accountIncome.setIncomeDescribed(purchaseReturnOrderDto.getRemark());
+        accountIncome.setIncomeMethod(String.valueOf(purchaseReturnOrderDto.getIncomeType()));
+        accountIncomeService.save(accountIncome);
         return true;
     }
+
+    @Override
+    public PurchaseReturnDetailsVo getPurchaseReturnOrderDtoById(Long id) {
+        PurchaseReturnOrders purchaseReturnOrders = purchaseReturnOrdersMapper.selectById(id);
+        PurchaseReturnDetailsVo purchaseReturnOrderDto = BeanUtil.copyProperties(purchaseReturnOrders, PurchaseReturnDetailsVo.class);
+        // 鏌ヨ鍑轰粬鍏蜂綋瀵瑰簲鐨勯��璐�
+        LambdaQueryWrapper<PurchaseReturnOrderProducts> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(PurchaseReturnOrderProducts::getPurchaseReturnOrderId, purchaseReturnOrders.getId());
+
+        List<PurchaseReturnOrderProducts> purchaseReturnOrderProducts = purchaseReturnOrderProductsMapper.selectList(queryWrapper);
+        List<PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo> purchaseReturnOrderProductsDetailVos = BeanUtil.copyToList(purchaseReturnOrderProducts, PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo.class);
+        // 鏌ヨ鍑哄搴旂殑鍟嗗搧淇℃伅
+        List<Long> productIds = purchaseReturnOrderProductsDetailVos.stream().map(PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo::getSalesLedgerProductId).distinct().filter(Objects::nonNull).collect(Collectors.toList());
+        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerService.getSalesLedgerProductListByIds(productIds, SaleEnum.PURCHASE);
+        Map<Long, SalesLedgerProduct> productmap = salesLedgerProducts.stream().collect(Collectors.toMap(SalesLedgerProduct::getId, product -> product));
+        purchaseReturnOrderProductsDetailVos.forEach(purchaseReturnOrderProductsDetailVo -> {
+            purchaseReturnOrderProductsDetailVo.setSalesLedgerProduct(productmap.get(purchaseReturnOrderProductsDetailVo.getSalesLedgerProductId()));
+        });
+
+        purchaseReturnOrderDto.setPurchaseReturnOrderProductsDetailVoList(purchaseReturnOrderProductsDetailVos);
+
+
+        return purchaseReturnOrderDto;
+    }
 }
diff --git a/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java
new file mode 100644
index 0000000..02317e6
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java
@@ -0,0 +1,38 @@
+package com.ruoyi.purchase.vo;
+
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/21
+ * @email 3038525872@qq.com
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PurchaseReturnDetailsVo extends PurchaseReturnOrders implements Serializable {
+
+    private List<PurchaseReturnOrderProductsDetailVo> purchaseReturnOrderProductsDetailVoList;
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class PurchaseReturnOrderProductsDetailVo implements Serializable {
+        private Long id;
+        private BigDecimal returnQuantity;
+        private Long salesLedgerProductId;
+        private Long purchaseReturnOrderId;
+
+        private SalesLedgerProduct salesLedgerProduct;
+    }
+}
diff --git a/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java
index 8e19f8c..fb02943 100644
--- a/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java
+++ b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java
@@ -1,7 +1,13 @@
 package com.ruoyi.purchase.vo;
 
 import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
 public class PurchaseReturnOrderVo extends PurchaseReturnOrders {
     //渚涘簲鍟嗗悕绉�
     private String supplierName;
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
index aed72ef..aaedff4 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
@@ -2,6 +2,8 @@
 
 import javax.servlet.http.HttpServletResponse;
 
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -10,6 +12,9 @@
 import com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy;
 import com.ruoyi.procurementrecord.service.ProcurementRecordService;
 import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrderProducts;
 import com.ruoyi.sales.dto.SalesLedgerProductDto;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.service.ISalesLedgerProductService;
@@ -29,6 +34,8 @@
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 浜у搧淇℃伅Controller
@@ -46,6 +53,9 @@
     private ProcurementRecordService procurementRecordService;
     @Autowired
     private StockUtils stockUtils;
+
+    @Autowired
+    private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
 
 
     /**
@@ -74,6 +84,14 @@
     @GetMapping("/list")
     public AjaxResult list(SalesLedgerProduct salesLedgerProduct) {
         List<SalesLedgerProduct> list = salesLedgerProductService.selectSalesLedgerProductList(salesLedgerProduct);
+        if (CollUtil.isEmpty(list)) {
+            return AjaxResult.success(list);
+        }
+        //
+        List<Long> productIds = list.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
+        List<SimpleReturnOrderGroupDto> groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
+        Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, item -> item.getSumReturnQuantity()));
+
         list.forEach(item -> {
             if (item.getFutureTickets().compareTo(BigDecimal.ZERO) == 0) {
                 item.setFutureTickets(BigDecimal.ZERO);
@@ -95,6 +113,10 @@
                     item.setApproveStatus(1);
                 }
             }
+            // 缁熻閫�璐ф暟閲�
+            BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO);
+            item.setReturnQuality(returnQuality);
+            item.setAvailableQuality(item.getQuantity().subtract(returnQuality));
         });
         return AjaxResult.success(list);
     }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index 1df16bd..1bf9aa2 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -235,4 +235,12 @@
 
     @TableField(exist = false)
     private Integer hasSufficientStock;
+
+    // 閫�璐ф暟閲�
+    @TableField(exist = false)
+    private BigDecimal returnQuality;
+
+    // 鍙敤鏁伴噺  quantity - returnQuality
+    @TableField(exist = false)
+    private BigDecimal availableQuality;
 }
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index 79aea98..eda9da4 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -13,6 +13,7 @@
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Nullable;
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
 import java.util.List;
@@ -32,6 +33,7 @@
     int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto);
 
     List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(@NotNull Long relateId,@NotNull SaleEnum type);
+    List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, @NotNull SaleEnum type);
 
     void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type);
 
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index c8da4ca..570b2f5 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -31,6 +31,8 @@
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.sales.dto.*;
 import com.ruoyi.sales.mapper.*;
@@ -39,6 +41,7 @@
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
+import org.jetbrains.annotations.Nullable;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -76,69 +79,41 @@
 @RequiredArgsConstructor
 @Slf4j
 public class SalesLedgerServiceImpl extends ServiceImpl<SalesLedgerMapper, SalesLedger> implements ISalesLedgerService {
-    private final AccountIncomeService accountIncomeService;
-
-    private final SalesLedgerMapper salesLedgerMapper;
-
-    private final CustomerMapper customerMapper;
-
-    private final SalesLedgerProductMapper salesLedgerProductMapper;
-    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
-
-    private final CommonFileMapper commonFileMapper;
-
-    private final TempFileMapper tempFileMapper;
-
-    private final ReceiptPaymentMapper receiptPaymentMapper;
-
-    private final ShippingInfoServiceImpl shippingInfoServiceImpl;
-
-    private final CommonFileServiceImpl commonFileService;
-
-    private final ShippingInfoMapper shippingInfoMapper;
-
-    private final InvoiceLedgerMapper invoiceLedgerMapper;
-
-    private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper;
-
-    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
-
-    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-
-    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-
-    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
-
-    private final ProductOrderMapper productOrderMapper;
-
-    private final ProcessRouteMapper processRouteMapper;
-    private final ProductProcessRouteMapper productProcessRouteMapper;
-
-    private final ProcessRouteItemMapper processRouteItemMapper;
-
-    private final ProductProcessRouteItemMapper productProcessRouteItemMapper;
-
-    private final ProductWorkOrderMapper productWorkOrderMapper;
-
-    private final ProductionProductMainMapper productionProductMainMapper;
-
-    private final ProductionProductOutputMapper productionProductOutputMapper;
-
-    private final ProductionProductInputMapper productionProductInputMapper;
-
-    private final QualityInspectMapper qualityInspectMapper;
-
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
-
-    @Value("${file.upload-dir}")
-    private String uploadDir;
-
     private static final String LOCK_PREFIX = "contract_no_lock:";
     private static final long LOCK_WAIT_TIMEOUT = 10; // 閿佺瓑寰呰秴鏃舵椂闂达紙绉掞級
     private static final long LOCK_EXPIRE_TIME = 30;  // 閿佽嚜鍔ㄨ繃鏈熸椂闂达紙绉掞級
-
+    private final AccountIncomeService accountIncomeService;
+    private final SalesLedgerMapper salesLedgerMapper;
+    private final CustomerMapper customerMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
+    private final CommonFileMapper commonFileMapper;
+    private final TempFileMapper tempFileMapper;
+    private final ReceiptPaymentMapper receiptPaymentMapper;
+    private final ShippingInfoServiceImpl shippingInfoServiceImpl;
+    private final CommonFileServiceImpl commonFileService;
+    private final ShippingInfoMapper shippingInfoMapper;
+    private final InvoiceLedgerMapper invoiceLedgerMapper;
+    private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper;
+    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
+    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
+    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
+    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
+    private final ProductOrderMapper productOrderMapper;
+    private final ProcessRouteMapper processRouteMapper;
+    private final ProductProcessRouteMapper productProcessRouteMapper;
+    private final ProcessRouteItemMapper processRouteItemMapper;
+    private final ProductProcessRouteItemMapper productProcessRouteItemMapper;
+    private final ProductWorkOrderMapper productWorkOrderMapper;
+    private final ProductionProductMainMapper productionProductMainMapper;
+    private final ProductionProductOutputMapper productionProductOutputMapper;
+    private final ProductionProductInputMapper productionProductInputMapper;
+    private final QualityInspectMapper qualityInspectMapper;
     private final RedisTemplate<String, String> redisTemplate;
+    @Autowired
+    private SysDeptMapper sysDeptMapper;
+    @Value("${file.upload-dir}")
+    private String uploadDir;
     @Autowired
     private ProductModelMapper productModelMapper;
 
@@ -148,19 +123,48 @@
     private ProductStructureMapper productStructureMapper;
     @Autowired
     private ProductionProductMainService productionProductMainService;
+    @Autowired
+    private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
     ;
+    @Autowired
+    private SysUserMapper sysUserMapper;
 
     @Override
     public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
         return salesLedgerMapper.selectSalesLedgerList(salesLedgerDto);
     }
 
-
-    public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type){
+    public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type) {
         LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
         productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, relateId);
         productWrapper.eq(SalesLedgerProduct::getType, type.getCode());
         return salesLedgerProductMapper.selectList(productWrapper);
+    }
+
+    @Override
+    public List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, SaleEnum type) {
+        if (CollectionUtils.isEmpty(relateIds)) {
+            return Collections.emptyList();
+        }
+        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
+        productWrapper.in(SalesLedgerProduct::getId, relateIds);
+        productWrapper.eq(SalesLedgerProduct::getType, type.getCode());
+        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(productWrapper);
+        if (type.equals(SaleEnum.PURCHASE)) {
+            // 鏌ヨ閫�璐т俊鎭�
+            List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
+            List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>();
+            if(CollectionUtils.isNotEmpty(productIds)){
+                groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
+            }
+            Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity));
+            salesLedgerProducts.forEach(item -> {
+                BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO);
+                item.setReturnQuality(returnQuality);
+                item.setAvailableQuality(item.getQuantity().subtract(returnQuality));
+            });
+        }
+        return salesLedgerProducts;
     }
 
     @Override
@@ -334,9 +338,6 @@
         return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
     }
 
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult importData(MultipartFile file) {
@@ -494,37 +495,6 @@
         return salesLedgerDtoIPage;
     }
 
-
-    // 鍐呴儴绫荤敤浜庡瓨鍌ㄨ仛鍚堢粨鏋�
-    private static class GroupedCustomer {
-        private final Long customerId;
-        private final String customerName;
-        private BigDecimal totalAmount = BigDecimal.ZERO;
-
-        public GroupedCustomer(Long customerId, String customerName) {
-            this.customerId = customerId;
-            this.customerName = customerName;
-        }
-
-        public void addAmount(BigDecimal amount) {
-            if (amount != null) {
-                this.totalAmount = this.totalAmount.add(amount);
-            }
-        }
-
-        public Long getCustomerId() {
-            return customerId;
-        }
-
-        public String getCustomerName() {
-            return customerName;
-        }
-
-        public BigDecimal getTotalAmount() {
-            return totalAmount;
-        }
-    }
-
     /**
      * 涓嬪垝绾垮懡鍚嶈浆椹煎嘲鍛藉悕
      */
@@ -643,7 +613,7 @@
             // 4. 澶勭悊瀛愯〃鏁版嵁
             List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
             if (productList != null && !productList.isEmpty()) {
-                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class,salesLedgerDto.getType()));
+                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()));
                 updateMainContractAmount(
                         salesLedger.getId(),
                         productList,
@@ -662,8 +632,6 @@
             throw new BaseException("鏂囦欢杩佺Щ澶辫触: " + e.getMessage());
         }
     }
-
-    // 鏂囦欢杩佺Щ鏂规硶
 
     /**
      * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
@@ -740,6 +708,7 @@
         }
     }
 
+    // 鏂囦欢杩佺Щ鏂规硶
 
     @Override
     public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
@@ -881,4 +850,34 @@
             throw new RuntimeException("鍔ㄦ�佹洿鏂颁富琛ㄩ噾棰濆け璐�", e);
         }
     }
+
+    // 鍐呴儴绫荤敤浜庡瓨鍌ㄨ仛鍚堢粨鏋�
+    private static class GroupedCustomer {
+        private final Long customerId;
+        private final String customerName;
+        private BigDecimal totalAmount = BigDecimal.ZERO;
+
+        public GroupedCustomer(Long customerId, String customerName) {
+            this.customerId = customerId;
+            this.customerName = customerName;
+        }
+
+        public void addAmount(BigDecimal amount) {
+            if (amount != null) {
+                this.totalAmount = this.totalAmount.add(amount);
+            }
+        }
+
+        public Long getCustomerId() {
+            return customerId;
+        }
+
+        public String getCustomerName() {
+            return customerName;
+        }
+
+        public BigDecimal getTotalAmount() {
+            return totalAmount;
+        }
+    }
 }
diff --git a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
index f501849..1aed9b4 100644
--- a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -62,6 +62,12 @@
             <if test="c.entryDateEnd != null and c.entryDateEnd != ''">
                 AND pl.entry_date &lt;= #{c.entryDateEnd}
             </if>
+            <if test="c.supplierId != null">
+                AND pl.supplier_id = #{c.supplierId}
+            </if>
+            <if test="c.approvalStatus != null">
+                AND pl.approval_status = #{c.approvalStatus}
+            </if>
         </where>
         ORDER BY pl.entry_date DESC
     </select>
diff --git a/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml b/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml
index 9ae589f..cd13f3c 100644
--- a/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml
@@ -11,5 +11,14 @@
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
     </resultMap>
-
+    <select id="getReturnOrderGroupListByProductIds" resultType="com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto"
+            parameterType="java.util.List">
+        select t1.sales_ledger_product_id,sum(t1.return_quantity) as sum_return_quantity from purchase_return_order_products as t1
+        inner join purchase_return_orders as t2 on t1.purchase_return_order_id = t2.id
+        WHERE t1.sales_ledger_product_id IN
+        <foreach item="id" collection="productIds" separator="," open="(" close=")">
+            #{id}
+        </foreach>
+        group by t1.sales_ledger_product_id
+    </select>
 </mapper>
diff --git a/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml b/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
index 8976a3a..d8f0a88 100644
--- a/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
@@ -23,14 +23,10 @@
         SELECT
         pro.*,
         sm.supplier_name as supplierName,
-        pl.purchase_contract_number as purchaseContractNumber,
-        su.user_name as returnUserName,
-        su1.user_name as createUserName
+        pl.purchase_contract_number as purchaseContractNumber
         FROM purchase_return_orders pro
         LEFT JOIN supplier_manage sm ON pro.supplier_id = sm.id
         LEFT JOIN purchase_ledger pl ON pl.id = pro.purchase_ledger_id
-        LEFT JOIN sys_user su ON su.user_id = pro.return_user_id
-        LEFT JOIN sys_user su1 ON su1.user_id = pro.prepared_user_id
         where 1=1
         <if test="params.no != null and params.no != '' ">
             AND pro.no LIKE CONCAT('%',#{params.no},'%')
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 73026c8..712124a 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -114,10 +114,14 @@
         <!-- 骞冲潎鍗曚环 = 鎬婚噰璐噾棰�/鎬婚噰璐暟閲忥紝淇濈暀2浣嶅皬鏁帮紝閬垮厤闄�0 -->
         ROUND(IF(SUM(slp.quantity) = 0, 0, SUM(slp.tax_inclusive_total_price) / SUM(slp.quantity)), 2) AS averagePrice,
         <!-- 璇ヤ骇鍝佸ぇ绫讳笅鏈�鍚庝竴涓綍鍏ユ棩鏈燂紙鍙栧彴璐︿富琛ㄧ殑entry_date锛� -->
-        MAX(sl.entry_date) AS entryDate
+        MAX(sl.entry_date) AS entryDate,
+        COALESCE(NULLIF(SUM(t1.return_quantity), 0), 0) AS return_quantity,
+        COALESCE(SUM(t2.total_amount), 0) AS return_amount
         FROM sales_ledger_product slp
         <!-- 鍏宠仈鍙拌处涓昏〃锛氳幏鍙栧綍鍏ユ棩鏈焑ntry_date -->
         LEFT JOIN purchase_ledger sl ON slp.sales_ledger_id = sl.id
+        left join purchase_return_order_products as t1 on t1.sales_ledger_product_id = slp.id
+        left join purchase_return_orders as t2 on t2.id = t1.purchase_return_order_id
         WHERE slp.type = 2 <!-- 鍥哄畾绛涢�夛細閲囪喘鍙拌处锛坱ype=2锛� -->
         <!-- 閲囪喘鏃ユ湡绛涢�夛細鍙�夋潯浠� -->
         <if test="req.entryDateStart != null and req.entryDateEnd != null">

--
Gitblit v1.9.3