From 1342f568f4b6470efdfc69be7bb153e2b12762f9 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期二, 31 三月 2026 17:00:57 +0800
Subject: [PATCH] feat:1.销售,采购,库存,质检模块产品添加批号,供应商 2.销售产品关联批号,供应商递归查询

---
 src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java           |   21 +
 src/main/java/com/ruoyi/stock/pojo/StockInventory.java                                |    6 
 src/main/java/com/ruoyi/stock/service/StockInventoryService.java                      |    6 
 src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java                   |    6 
 src/main/java/com/ruoyi/basic/dto/ProductTreeDto.java                                 |    7 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java          |   30 +-
 src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java                            |    3 
 src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java                                |    7 
 src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java                       |   17 +
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java               |    4 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java                |    3 
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java             |  269 +++++++++++++++++++++++-
 src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java          |   14 
 src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java                              |    3 
 src/main/java/com/ruoyi/stock/pojo/StockInRecord.java                                 |    6 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |   55 +++-
 src/main/java/com/ruoyi/production/dto/DrawMaterialDto.java                           |   38 ++-
 src/main/resources/mapper/stock/StockInventoryMapper.xml                              |   61 ++++
 src/main/java/com/ruoyi/stock/controller/StockInventoryController.java                |   11 
 src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java              |    2 
 src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java              |    9 
 src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java       |   22 +
 src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java                        |    5 
 src/main/java/com/ruoyi/basic/pojo/Product.java                                       |    4 
 src/main/java/com/ruoyi/stock/pojo/StockUninventory.java                              |    6 
 src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml                      |    4 
 26 files changed, 519 insertions(+), 100 deletions(-)

diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
index 00a53f5..22ba5ac 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -13,7 +13,6 @@
 import com.ruoyi.approve.service.IApproveNodeService;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.device.mapper.DeviceRepairMapper;
 import com.ruoyi.device.pojo.DeviceRepair;
@@ -25,7 +24,10 @@
 import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.purchase.service.impl.PurchaseLedgerServiceImpl;
-import com.ruoyi.sales.mapper.*;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.mapper.SalesQuotationMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.SalesQuotation;
@@ -204,7 +206,8 @@
                             purchaseLedgerServiceImpl.addQualityInspect(purchaseLedger, salesLedgerProduct);
                         }else {
                             //鐩存帴鍏ュ簱
-                            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId());
+                            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
+                                    purchaseLedger.getId(),salesLedgerProduct.getBatchNo(),salesLedgerProduct.getCustomer());
                         }
                     }
                 } else if (status.equals(3)) {
diff --git a/src/main/java/com/ruoyi/basic/dto/ProductTreeDto.java b/src/main/java/com/ruoyi/basic/dto/ProductTreeDto.java
index 1fd8c81..0829aae 100644
--- a/src/main/java/com/ruoyi/basic/dto/ProductTreeDto.java
+++ b/src/main/java/com/ruoyi/basic/dto/ProductTreeDto.java
@@ -9,6 +9,13 @@
     private Long id;
     private Long parentId;
     private String productName;
+    private String model;
+    private String batchNo;
+    private String customer;
+    private String uidNo;
+    private String unit;
+    private Long productModelId;
     private String label; // 鐢ㄤ簬鏍戝舰缁撴瀯鐨勬樉绀哄悕绉�
     private List<ProductTreeDto> children;
+    private String nodeType;
 }
diff --git a/src/main/java/com/ruoyi/basic/pojo/Product.java b/src/main/java/com/ruoyi/basic/pojo/Product.java
index 6b4e14b..f5fba59 100644
--- a/src/main/java/com/ruoyi/basic/pojo/Product.java
+++ b/src/main/java/com/ruoyi/basic/pojo/Product.java
@@ -4,9 +4,11 @@
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.io.Serializable;
+
 @Data
 @TableName("product")
-public class Product {
+public class Product implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
diff --git a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
index 26578a0..4f20fb0 100644
--- a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
+++ b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -35,7 +35,7 @@
      * @param recordType
      * @param recordId
      */
-    public void addUnStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void addUnStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
         StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
         stockUninventoryDto.setRecordId(recordId);
         stockUninventoryDto.setRecordType(String.valueOf(recordType));
@@ -51,7 +51,7 @@
      * @param recordType
      * @param recordId
      */
-    public void subtractUnStock(Long productModelId, BigDecimal quantity, Integer recordType,Long recordId) {
+    public void subtractUnStock(Long productModelId, BigDecimal quantity, Integer recordType, Long recordId) {
         StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
         stockUninventoryDto.setRecordId(recordId);
         stockUninventoryDto.setRecordType(String.valueOf(recordType));
@@ -67,7 +67,7 @@
      * @param recordType
      * @param recordId
      */
-    public void addStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void addStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId,String batchNo,String customer) {
         StockInventoryDto stockInventoryDto = new StockInventoryDto();
         stockInventoryDto.setRecordId(recordId);
         if (recordType != null) {
@@ -75,6 +75,8 @@
         }
         stockInventoryDto.setQualitity(quantity);
         stockInventoryDto.setProductModelId(productModelId);
+        stockInventoryDto.setBatchNo(batchNo);
+        stockInventoryDto.setCustomer(customer);
         stockInventoryService.addstockInventory(stockInventoryDto);
     }
 
@@ -85,12 +87,16 @@
      * @param recordType
      * @param recordId
      */
-    public void substractStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId,String batchNo,String customer) {
         StockInventoryDto stockInventoryDto = new StockInventoryDto();
         stockInventoryDto.setRecordId(recordId);
-        stockInventoryDto.setRecordType(String.valueOf(recordType));
+        if (recordType != null) {
+            stockInventoryDto.setRecordType(recordType);
+        }
         stockInventoryDto.setQualitity(quantity);
         stockInventoryDto.setProductModelId(productModelId);
+        stockInventoryDto.setBatchNo(batchNo);
+        stockInventoryDto.setCustomer(customer);
         stockInventoryService.subtractStockInventory(stockInventoryDto);
     }
 
@@ -103,6 +109,7 @@
             stockInRecordService.batchDelete(Collections.singletonList(one.getId()));
         }
     }
+
     public void deleteStockOutRecord(Long recordId, String recordType) {
         StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>()
                 .lambda().eq(StockOutRecord::getRecordId, recordId)
diff --git a/src/main/java/com/ruoyi/production/dto/DrawMaterialDto.java b/src/main/java/com/ruoyi/production/dto/DrawMaterialDto.java
index f53fe59..7cab486 100644
--- a/src/main/java/com/ruoyi/production/dto/DrawMaterialDto.java
+++ b/src/main/java/com/ruoyi/production/dto/DrawMaterialDto.java
@@ -1,28 +1,44 @@
 package com.ruoyi.production.dto;
 
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-
 import java.math.BigDecimal;
 
 @Data
+@ApiModel("棰嗘枡鍗旸TO")
 public class DrawMaterialDto {
 
-    //璁㈠崟id
+    @ApiModelProperty("璁㈠崟ID")
     private Long id;
-    //鍨嬪彿id
+
+    @ApiModelProperty("鍨嬪彿ID")
     private Long productModelId;
-    //搴撳瓨鏁伴噺
+
+    @ApiModelProperty("搴撳瓨鏁伴噺")
     private BigDecimal qualitity;
-    //棰嗙敤鏁伴噺
+
+    @ApiModelProperty("棰嗙敤鏁伴噺")
     private BigDecimal requisitionQty;
-    //浜у搧鍚嶇О
+
+    @ApiModelProperty("浜у搧鍚嶇О")
     private String productName;
-    //浜у搧鍨嬪彿
+
+    @ApiModelProperty("浜у搧鍨嬪彿")
     private String model;
-    //浜у搧鍗曚綅
+
+    @ApiModelProperty("浜у搧鍗曚綅")
     private String unit;
-    //鎶ュ伐棰嗙敤鏁伴噺
+
+    @ApiModelProperty("鎶ュ伐棰嗙敤鏁伴噺")
     private BigDecimal reportQty;
-    //浜у搧鍗曚綅
+
+    @ApiModelProperty("澶囨敞")
     private String remark;
-}
+
+    @ApiModelProperty("鎵瑰彿")
+    private String batchNo;
+
+    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    private String customer;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
index 404a09b..13338c7 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
@@ -33,4 +33,10 @@
 
     @ApiModelProperty(value = "澶囨敞")
     private String remark;
+
+    @ApiModelProperty("鎵瑰彿")
+    private String batchNo;
+
+    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    private String customer;
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
index 3d694ca..f479a16 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -24,6 +24,7 @@
 import com.ruoyi.production.service.ProductOrderService;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.pojo.StockInventory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -247,8 +248,9 @@
 
     @Override
     public List<SelectOptionDTO<String>> getProductOrderBatchNo() {
-        List<ProductOrder> productOrders = productOrderMapper.selectList(null);
-        return productOrders.stream().map(productOrder -> new SelectOptionDTO<>(productOrder.getBatchNo(), productOrder.getBatchNo())).collect(Collectors.toList());
+        //鏌ヨ搴撳瓨鎵瑰彿
+        List<StockInventory> stockInventoryList = stockInventoryMapper.selectList(null);
+        return stockInventoryList.stream().map(stockInventory -> new SelectOptionDTO<>(stockInventory.getBatchNo(), stockInventory.getBatchNo())).collect(Collectors.toList());
     }
 
     @Override
@@ -278,7 +280,9 @@
         if (productOrder != null) {
             List<DrawMaterialDto> materialDtoList = JSON.parseArray(productOrder.getDrawMaterials(), DrawMaterialDto.class);
             for (DrawMaterialDto drawMaterialDto : materialDtoList) {
-                stockUtils.addStock(drawMaterialDto.getProductModelId(), drawMaterialDto.getRequisitionQty(), null, productOrderDto.getId());
+                stockUtils.addStock(drawMaterialDto.getProductModelId(), drawMaterialDto.getRequisitionQty(), null, productOrderDto.getId(),
+                        drawMaterialDto.getBatchNo(), drawMaterialDto.getCustomer()
+                );
             }
         }
 
@@ -288,7 +292,9 @@
                 if (drawMaterialDto.getProductModelId() == null) {
                     throw new RuntimeException("浜у搧鍨嬪彿ID涓嶈兘涓虹┖");
                 }
-                stockUtils.substractStock(drawMaterialDto.getProductModelId(), drawMaterialDto.getRequisitionQty(), StockOutQualifiedRecordTypeEnum.DRAW_MATERIALS_STOCK_OUT.getCode(), productOrderDto.getId());
+                stockUtils.substractStock(drawMaterialDto.getProductModelId(), drawMaterialDto.getRequisitionQty(),
+                        StockOutQualifiedRecordTypeEnum.DRAW_MATERIALS_STOCK_OUT.getCode(), productOrderDto.getId(),
+                        drawMaterialDto.getBatchNo(),drawMaterialDto.getCustomer());
             }
         } catch (Exception e) {
             throw new RuntimeException("棰嗘枡澶辫触锛�" + e.getMessage());
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 578ea2d..7175825 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -143,28 +143,32 @@
         productionProductMain.setDeviceId(dto.getDeviceId());
         productionProductMainMapper.insert(productionProductMain);
         /* 鏂板鎶ュ伐鎶曞叆琛� */
+        ProductWorkOrder WorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
+        if (WorkOrder == null) {
+            throw new RuntimeException("宸ュ崟涓嶅瓨鍦�");
+        }
+
+        ProductOrder order = productOrderMapper.selectById(WorkOrder.getProductOrderId());
+        if (order == null) {
+            throw new RuntimeException("浜у搧璁㈠崟涓嶅瓨鍦�");
+        }
         List<DrawMaterialDto> drawMaterialList = dto.getDrawMaterialList();
         if (!CollectionUtils.isEmpty(drawMaterialList)) {
-            // 1. 鎵归噺鏌ヨ鏁版嵁
-            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
-            if (productWorkOrder == null) {
-                throw new RuntimeException("宸ュ崟涓嶅瓨鍦�");
-            }
 
-            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
-            if (productOrder == null) {
-                throw new RuntimeException("浜у搧璁㈠崟涓嶅瓨鍦�");
-            }
-
-            // 2. 瑙f瀽骞舵瀯寤虹墿鏂橫ap
-            List<DrawMaterialDto> existingMaterialList = JSON.parseArray(productOrder.getDrawMaterials(), DrawMaterialDto.class);
+            // 鐗╂枡Map
+            List<DrawMaterialDto> existingMaterialList = JSON.parseArray(order.getDrawMaterials(), DrawMaterialDto.class);
             if (CollectionUtils.isEmpty(existingMaterialList)) {
                 throw new RuntimeException("鍙鐢ㄧ墿鏂欏垪琛ㄤ负绌�");
             }
 
-            Map<Long, DrawMaterialDto> materialMap = existingMaterialList.stream()
-                    .collect(Collectors.toMap(DrawMaterialDto::getProductModelId,
-                            Function.identity()));
+            Map<String, DrawMaterialDto> materialMap = existingMaterialList.stream()
+                    .collect(Collectors.toMap(
+                            materialDto -> materialDto.getProductModelId() + "_" +
+                                    (materialDto.getBatchNo() == null ? "" : materialDto.getBatchNo()) + "_" +
+                                    (materialDto.getCustomer() == null ? "" : materialDto.getCustomer()),
+                            Function.identity(),
+                            (existing, replacement) -> existing
+                    ));
 
             // 澶勭悊鎶ュ伐鐗╂枡
             List<ProductionProductInput> inputList = new ArrayList<>();
@@ -173,9 +177,15 @@
                 Long modelId = drawMaterial.getProductModelId();
                 BigDecimal reportQty = drawMaterial.getReportQty();
 
-                DrawMaterialDto material = materialMap.get(modelId);
+                String key = drawMaterial.getProductModelId() + "_" +
+                        (drawMaterial.getBatchNo() == null ? "" : drawMaterial.getBatchNo()) + "_" +
+                        (drawMaterial.getCustomer() == null ? "" : drawMaterial.getCustomer());
+
+                DrawMaterialDto material = materialMap.get(key);
                 if (material == null) {
-                    throw new RuntimeException("鐗╂枡涓嶅瓨鍦�: " + modelId);
+                    throw new RuntimeException("鐗╂枡涓嶅瓨鍦�: 浜у搧鍨嬪彿ID=" + modelId +
+                            ", 鎵规鍙�=" + drawMaterial.getBatchNo() +
+                            ", 瀹㈡埛=" + drawMaterial.getCustomer());
                 }
 
                 // 楠岃瘉搴撳瓨
@@ -194,6 +204,8 @@
                 input.setQuantity(reportQty);
                 input.setProductMainId(productionProductMain.getId());
                 input.setRemark(drawMaterial.getRemark());
+                input.setBatchNo(drawMaterial.getBatchNo());
+                input.setCustomer(drawMaterial.getCustomer());
                 inputList.add(input);
             }
 
@@ -201,8 +213,8 @@
                 for (ProductionProductInput productionProductInput : inputList) {
                     productionProductInputMapper.insert(productionProductInput);
                 }
-                productOrder.setDrawMaterials(JSON.toJSONString(existingMaterialList));
-                productOrderMapper.updateById(productOrder);
+                order.setDrawMaterials(JSON.toJSONString(existingMaterialList));
+                productOrderMapper.updateById(order);
             }
         }
         /*鏂板鎶ュ伐浜у嚭琛�*/
@@ -266,7 +278,10 @@
                 }
             } else {
                 //鐩存帴鍏ュ簱
-                stockUtils.addStock(productProcessRouteItem.getProductModelId(), productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
+                String customer = "闀挎不甯傝酱鎵垮埗閫犳湁闄愬叕鍙�";
+                stockUtils.addStock(productProcessRouteItem.getProductModelId(), productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()),
+                        StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId(),order.getBatchNo(),customer
+                );
             }
             /*鏇存柊宸ュ崟鍜岀敓浜ц鍗�*/
             ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
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 41c3350..f9c45e5 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -1,29 +1,23 @@
 package com.ruoyi.purchase.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.AccountIncome;
 import com.ruoyi.account.service.AccountExpenseService;
-import com.ruoyi.account.service.AccountIncomeService;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
 import com.ruoyi.approve.vo.ApproveProcessVO;
 import com.ruoyi.basic.mapper.ProductMapper;
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.mapper.SupplierManageMapper;
-import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.basic.pojo.SupplierManage;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.exception.base.BaseException;
-import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -39,19 +33,25 @@
 import com.ruoyi.purchase.dto.PurchaseLedgerImportDto;
 import com.ruoyi.purchase.dto.PurchaseLedgerProductImportDto;
 import com.ruoyi.purchase.mapper.*;
-import com.ruoyi.purchase.pojo.*;
+import com.ruoyi.purchase.pojo.PaymentRegistration;
+import com.ruoyi.purchase.pojo.ProductRecord;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.purchase.pojo.TicketRegistration;
 import com.ruoyi.purchase.service.IPurchaseLedgerService;
 import com.ruoyi.quality.mapper.*;
-import com.ruoyi.quality.pojo.*;
-import com.ruoyi.sales.dto.SalesLedgerImportDto;
-import com.ruoyi.sales.dto.SalesLedgerProductImportDto;
-import com.ruoyi.sales.mapper.*;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.quality.pojo.QualityTestStandard;
+import com.ruoyi.quality.pojo.QualityTestStandardParam;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
 import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
-import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
 import org.springframework.beans.BeanUtils;
@@ -207,7 +207,7 @@
         // 4. 澶勭悊瀛愯〃鏁版嵁
         List<SalesLedgerProduct> productList = purchaseLedgerDto.getProductData();
         if (productList != null && !productList.isEmpty()) {
-            handleSalesLedgerProducts(purchaseLedger.getId(), productList, purchaseLedgerDto.getType());
+            handleSalesLedgerProducts(purchaseLedger.getId(), productList, purchaseLedgerDto.getType(),supplierManage);
         }
         //鏂板鍘熸潗鏂欐楠�  瀹℃壒涔嬪悗鎵嶇敓鎴愭楠�
 //        if (productList != null) {
@@ -254,7 +254,7 @@
         }
     }
 
-    private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) {
+    private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type,SupplierManage supplierManage) {
         if (products == null || products.isEmpty()) {
             throw new BaseException("浜у搧淇℃伅涓嶅瓨鍦�");
         }
@@ -324,6 +324,8 @@
                 salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
                 salesLedgerProduct.setFutureTicketsAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                 salesLedgerProduct.setPendingTicketsTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
+                salesLedgerProduct.setCustomer(supplierManage.getSupplierName());
+                salesLedgerProduct.setBatchNo(salesLedgerProduct.getBatchNo());
                 salesLedgerProductMapper.insert(salesLedgerProduct);
             }
         }
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index b4156c3..1c46b5f 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -15,6 +15,12 @@
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.procurementrecord.service.ProcurementRecordService;
 import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.production.mapper.ProductOrderMapper;
+import com.ruoyi.production.mapper.ProductWorkOrderMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
+import com.ruoyi.production.pojo.ProductOrder;
+import com.ruoyi.production.pojo.ProductWorkOrder;
+import com.ruoyi.production.pojo.ProductionProductMain;
 import com.ruoyi.quality.dto.QualityInspectDto;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.quality.mapper.QualityTestStandardMapper;
@@ -58,6 +64,13 @@
 
     private ProductModelMapper productModelMapper;
 
+    private ProductionProductMainMapper productionProductMainMapper;
+
+    private ProductWorkOrderMapper productWorkOrderMapper;
+
+    private ProductOrderMapper productOrderMapper;
+
+
     @Override
     public int add(QualityInspectDto qualityInspectDto) {
         QualityInspect qualityInspect = new QualityInspect();
@@ -85,6 +98,9 @@
     @Override
     public int submit(QualityInspect inspect) {
         QualityInspect qualityInspect = qualityInspectMapper.selectById(inspect.getId());
+        ProductionProductMain productionProductMain = productionProductMainMapper.selectById(qualityInspect.getProductMainId());
+        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId());
+        ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
         //鎻愪氦鍓嶅繀椤诲垽鏂槸鍚﹀悎鏍�
         if (ObjectUtils.isNull(qualityInspect.getCheckResult())) {
             throw new RuntimeException("璇峰厛鍒ゆ柇鏄惁鍚堟牸");
@@ -101,7 +117,10 @@
             qualityUnqualifiedMapper.insert(qualityUnqualified);
         } else {
             //鍚堟牸鐩存帴鍏ュ簱
-            stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId());
+            String customer = "闀挎不甯傝酱鎵垮埗閫犳湁闄愬叕鍙�";
+            stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(),
+                    qualityInspect.getId(),productOrder.getBatchNo(),customer
+            );
         }
         qualityInspect.setInspectState(1);//宸叉彁浜�
         return qualityInspectMapper.updateById(qualityInspect);
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
index a3c199d..b8ac021 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -13,14 +13,8 @@
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.mapper.ProductProcessRouteItemMapper;
-import com.ruoyi.production.mapper.ProductProcessRouteMapper;
-import com.ruoyi.production.mapper.ProductWorkOrderMapper;
-import com.ruoyi.production.mapper.ProductionProductMainMapper;
-import com.ruoyi.production.pojo.ProductOrder;
-import com.ruoyi.production.pojo.ProductProcessRoute;
-import com.ruoyi.production.pojo.ProductProcessRouteItem;
-import com.ruoyi.production.pojo.ProductWorkOrder;
+import com.ruoyi.production.mapper.*;
+import com.ruoyi.production.pojo.*;
 import com.ruoyi.production.service.ProductOrderService;
 import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
 import com.ruoyi.quality.pojo.QualityInspect;
@@ -54,6 +48,7 @@
     private ProductProcessRouteItemMapper productProcessRouteItemMapper;
     private ProductWorkOrderMapper productWorkOrderMapper;
     private StockUninventoryService stockUninventoryService;
+    private ProductOrderMapper productOrderMapper;
 
     @Override
     public IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) {
@@ -71,6 +66,9 @@
     public int deal(QualityUnqualified qualityUnqualified) {
         QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId());
         QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
+        ProductionProductMain productionProductMain = productionProductMainMapper.selectById(qualityInspect.getProductMainId());
+        ProductWorkOrder workOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId());
+        ProductOrder orders = productOrderMapper.selectById(workOrder.getProductOrderId());
         if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType() != 0) {
             switch (qualityUnqualified.getDealResult()) {
                 case "杩斾慨":
@@ -137,7 +135,10 @@
                     break;
                 case "璁╂鏀捐":
                     //璋冪敤鎻愪氦鍚堟牸鐨勬帴鍙�
-                    stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
+                    String customer = "闀挎不甯傝酱鎵垮埗閫犳湁闄愬叕鍙�";
+                    stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId(),
+                            orders.getBatchNo(), customer
+                    );
                     break;
                 case "杩斿伐":
                 default:
@@ -153,7 +154,8 @@
                     break;
                 case "璁╂鏀捐":
                     //璋冪敤鎻愪氦鍚堟牸鐨勬帴鍙�
-                    stockUtils.addStock(modelId, unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
+                    String customer = "闀挎不甯傝酱鎵垮埗閫犳湁闄愬叕鍙�";
+                    stockUtils.addStock(modelId, unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId(), orders.getBatchNo(), customer);
                     break;
                 default:
                     break;
diff --git a/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java b/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
index 49548e1..65e3230 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
@@ -87,7 +87,7 @@
 
 
             //鍑哄簱
-            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(),null,null);
         }
 
         return AjaxResult.success();
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index dff5d64..bc3e5fd 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -241,4 +241,7 @@
 
     @ApiModelProperty(value = "鎵瑰彿")
     private String batchNo;
+
+    @ApiModelProperty(value = "渚涘簲鍟�")
+    private String customer;
 }
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 c32457c..bd71f54 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -194,6 +194,9 @@
             product.setTempnoInvoiceAmount(product.getNoInvoiceAmount());
             product.setTempNoInvoiceNum(product.getNoInvoiceNum());
             product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
+            product.setUidNo(product.getUidNo());
+            product.setUnit(product.getUnit());
+            product.setBatchNo(product.getBatchNo());
             product.setRegisterDate(LocalDateTime.now());
             // 鍙戣揣淇℃伅
             ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
index c9651a7..625e765 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -67,7 +67,9 @@
         //鎵e噺搴撳瓨
         if(!"宸插彂璐�".equals(byId.getStatus())){
             SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
-            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(),
+                    StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(),null,null
+            );
         }
         byId.setExpressNumber(req.getExpressNumber());
         byId.setExpressCompany(req.getExpressCompany());
diff --git a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
index 5540404..ed2092f 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
@@ -2,6 +2,7 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.ProductDto;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -108,7 +109,13 @@
 
     @ApiOperation("鏌ヨ搴撳瓨鍘熸潗鏂�")
     @GetMapping("/getMaterials")
-    public R getMaterials() {
-        return R.ok(stockInventoryService.getMaterials());
+    public R getMaterials(StockInventoryDto stockInventoryDto) {
+        return R.ok(stockInventoryService.getMaterials(stockInventoryDto));
+    }
+
+    @ApiOperation("鏌ヨ搴撳瓨浜у搧")
+    @GetMapping("/getStockInventoryAll")
+    public R getStockInventoryAll(ProductDto productDto) {
+        return R.ok(stockInventoryService.getStockInventoryAll(productDto));
     }
 }
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
index 1f00a00..f28c0eb 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
@@ -42,4 +42,7 @@
     private BigDecimal currentStock;
 
     private BigDecimal  unLockedQuantity;
+    private Long productId;      // 浜у搧ID
+    private Long parentId;  // 鐖剁骇浜у搧ID
+    private Long productModelId;   // 浜у搧鍨嬪彿ID
 }
diff --git a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
index 2280374..07fd0db 100644
--- a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
+++ b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.ProductDto;
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.execl.StockInventoryExportData;
@@ -52,5 +53,7 @@
 
     List<StockInventoryDto> getStockInventory(@Param("ids") List<Long> ids);
 
-    List<StockInventoryDto> getMaterials();
+    List<StockInventoryDto> getMaterials(@Param("ew")StockInventoryDto stockInventoryDto);
+
+    List<StockInventoryDto> getStockInventoryAll(@Param("ew") ProductDto productDto);
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
index c0b8a27..1d058af 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
@@ -63,4 +63,10 @@
     @ApiModelProperty(value = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
+
+    @ApiModelProperty("鎵瑰彿")
+    private String batchNo;
+
+    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    private String customer;
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockInventory.java b/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
index 36e7cf0..c0b379f 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
@@ -63,4 +63,10 @@
 
     @ApiModelProperty("澶囨敞")
     private String remark;
+
+    @ApiModelProperty("鎵瑰彿")
+    private String batchNo;
+
+    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    private String customer;
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
index e4e3b82..b14ae2e 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
@@ -71,4 +71,11 @@
 
     @ApiModelProperty(value = "绫诲瀷  0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
     private String type;
+
+    @ApiModelProperty("鎵瑰彿")
+    private String batchNo;
+
+    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    private String customer;
+
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java b/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
index 6ed47de..0d6f83b 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
@@ -59,4 +59,10 @@
     @ApiModelProperty("琚鍗曢攣瀹氭暟閲�")
     private BigDecimal lockedQuantity;
 
+    @ApiModelProperty("鎵瑰彿")
+    private String batchNo;
+
+    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    private String customer;
+
 }
diff --git a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
index 9b43570..6a0e368 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
@@ -3,6 +3,8 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.dto.ProductDto;
+import com.ruoyi.basic.dto.ProductTreeDto;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
@@ -40,5 +42,7 @@
 
     Boolean thawStock(StockInventoryDto stockInventoryDto);
 
-    List<StockInventoryDto> getMaterials();
+    List<StockInventoryDto> getMaterials(StockInventoryDto stockInventoryDto);
+
+    List<ProductTreeDto> getStockInventoryAll(ProductDto productDto);
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
index 3de9e50..97354b1 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -1,11 +1,19 @@
 package com.ruoyi.stock.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.dto.ProductDto;
+import com.ruoyi.basic.dto.ProductTreeDto;
+import com.ruoyi.basic.mapper.ProductMapper;
+import com.ruoyi.basic.mapper.ProductModelMapper;
+import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
@@ -19,15 +27,14 @@
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.stock.service.StockInventoryService;
 import com.ruoyi.stock.service.StockOutRecordService;
-import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 /**
  * <p>
@@ -38,13 +45,22 @@
  * @since 2026-01-21 04:16:36
  */
 @Service
-@AllArgsConstructor
 public class StockInventoryServiceImpl extends ServiceImpl<StockInventoryMapper, StockInventory> implements StockInventoryService {
 
+    @Autowired
     private  StockInventoryMapper stockInventoryMapper;
+    @Autowired
     private StockInRecordService stockInRecordService;
+    @Autowired
     private StockOutRecordService stockOutRecordService;
+    @Autowired
     private SalesLedgerProductMapper salesLedgerProductMapper;
+    @Autowired
+    private ProductMapper productMapper;
+    @Autowired
+    private ProductModelMapper productModelMapper;
+
+
     @Override
     public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
         return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
@@ -62,11 +78,17 @@
             stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
             stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
             stockInRecordDto.setType("0");
+            stockInRecordDto.setBatchNo(stockInventoryDto.getBatchNo());
+            stockInRecordDto.setCustomer(stockInventoryDto.getCustomer());
             stockInRecordService.add(stockInRecordDto);
         }
         //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
         //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
-        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
+        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda()
+                .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
+                .eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo())
+                .eq(StockInventory::getCustomer, stockInventoryDto.getCustomer())
+        );
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             StockInventory newStockInventory = new StockInventory();
             newStockInventory.setProductModelId(stockInventoryDto.getProductModelId());
@@ -75,6 +97,8 @@
             newStockInventory.setRemark(stockInventoryDto.getRemark());
             newStockInventory.setLockedQuantity(stockInventoryDto.getLockedQuantity());
             newStockInventory.setWarnNum(stockInventoryDto.getWarnNum());
+            newStockInventory.setBatchNo(stockInventoryDto.getBatchNo());
+            newStockInventory.setCustomer(stockInventoryDto.getCustomer());
             stockInventoryMapper.insert(newStockInventory);
         }else {
              stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
@@ -87,14 +111,22 @@
     @Transactional(rollbackFor = Exception.class)
     public Boolean subtractStockInventory(StockInventoryDto stockInventoryDto) {
         //  鏂板鍑哄簱璁板綍
-        StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
-        stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId());
-        stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType());
-        stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
-        stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
-        stockOutRecordDto.setType("0");
-        stockOutRecordService.add(stockOutRecordDto);
-        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
+        if (stockInventoryDto.getRecordType() != null) {
+            StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
+            stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId());
+            stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType());
+            stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
+            stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
+            stockOutRecordDto.setBatchNo(stockInventoryDto.getBatchNo());
+            stockOutRecordDto.setCustomer(stockInventoryDto.getCustomer());
+            stockOutRecordDto.setType("0");
+            stockOutRecordService.add(stockOutRecordDto);
+        }
+        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda()
+                .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
+                .eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo())
+                .eq(StockInventory::getCustomer, stockInventoryDto.getCustomer())
+        );
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
         }
@@ -210,7 +242,214 @@
     }
 
     @Override
-    public List<StockInventoryDto> getMaterials() {
-        return stockInventoryMapper.getMaterials();
+    public List<StockInventoryDto> getMaterials(StockInventoryDto stockInventoryDto) {
+        return stockInventoryMapper.getMaterials(stockInventoryDto);
+    }
+
+    @Override
+    public List<ProductTreeDto> getStockInventoryAll(ProductDto productDto) {
+        // 鏌ヨ搴撳瓨鍒楄〃
+        List<StockInventoryDto> stockList = stockInventoryMapper.getStockInventoryAll(productDto);
+
+        if (CollectionUtils.isEmpty(stockList)) {
+            return new ArrayList<>();
+        }
+
+        // 鏋勫缓浜у搧鏍戯紙鍩轰簬浜у搧琛ㄧ殑鐖跺瓙鍏崇郴锛�
+        Map<Long, ProductTreeDto> productNodeMap = buildProductTree(stockList);
+
+        // 灏嗗簱瀛樻暟鎹紙鍨嬪彿->鎵规->瀹㈡埛锛夋寕杞藉埌瀵瑰簲鐨勪骇鍝佽妭鐐逛笅
+        attachStockDataToProduct(productNodeMap, stockList);
+
+        // 杩斿洖鏍硅妭鐐�
+        List<ProductTreeDto> tree = new ArrayList<>();
+        for (ProductTreeDto node : productNodeMap.values()) {
+            if (node.getParentId() == null || node.getParentId() == 0) {
+                tree.add(node);
+            }
+        }
+
+        return tree;
+    }
+
+    /**
+     * 鏋勫缓浜у搧鏍戯紙鑷姩閫掑綊鏌ヨ鎵�鏈夌埗绾э紝鍖呭惈鏍硅妭鐐癸級
+     */
+    private Map<Long, ProductTreeDto> buildProductTree(List<StockInventoryDto> stockList) {
+        // 1. 鏀堕泦鎵�鏈夐渶瑕佸姞杞界殑浜у搧ID
+        Set<Long> needQueryIds = new HashSet<>();
+        for (StockInventoryDto stock : stockList) {
+            if (stock.getProductId() != null) {
+                needQueryIds.add(stock.getProductId());
+            }
+        }
+
+        // 閫掑綊鏌ヨ鎵�鏈夎妭鐐癸紙鐩村埌鏍硅妭鐐癸級
+        Set<Long> allAncestors = getAllAncestorIds(needQueryIds);
+        needQueryIds.addAll(allAncestors);
+
+        // 鎵归噺鏌ヨ鎵�鏈変骇鍝侊紙鍖呭惈瀹屾暣灞傜骇锛�
+        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(Product::getId, needQueryIds);
+        List<Product> products = productMapper.selectList(wrapper);
+
+        // 鏋勫缓鑺傜偣Map
+        Map<Long, ProductTreeDto> nodeMap = new HashMap<>();
+        for (Product product : products) {
+            ProductTreeDto node = new ProductTreeDto();
+            node.setId(product.getId());
+            node.setParentId(product.getParentId());
+            node.setProductName(product.getProductName());
+            node.setLabel(product.getProductName());
+            node.setNodeType("product");
+            node.setChildren(new ArrayList<>());
+            nodeMap.put(product.getId(), node);
+        }
+
+        // 鏋勫缓鐖跺瓙鍏崇郴
+        for (ProductTreeDto node : nodeMap.values()) {
+            Long parentId = node.getParentId();
+            if (parentId != null && parentId != 0 && nodeMap.containsKey(parentId)) {
+                nodeMap.get(parentId).getChildren().add(node);
+            }
+        }
+
+        return nodeMap;
+    }
+
+    /**
+     * 閫掑綊鏌ヨ鎵�鏈変骇鍝佺殑绁栧厛ID锛堢洿鍒版牴鑺傜偣锛�
+     */
+    private Set<Long> getAllAncestorIds(Set<Long> productIds) {
+        Set<Long> ancestorIds = new HashSet<>();
+        Queue<Long> queue = new LinkedList<>(productIds);
+
+        while (!queue.isEmpty()) {
+            Long currentId = queue.poll();
+            Product product = productMapper.selectById(currentId);
+            if (product == null) continue;
+
+            Long parentId = product.getParentId();
+            if (parentId != null && parentId != 0 && !ancestorIds.contains(parentId)) {
+                ancestorIds.add(parentId);
+                queue.add(parentId);
+            }
+        }
+        return ancestorIds;
+    }
+
+    /**
+     * 灏嗗簱瀛樻暟鎹紙鍨嬪彿->鎵规->瀹㈡埛锛夋寕杞藉埌浜у搧鑺傜偣涓�
+     */
+    private void attachStockDataToProduct(Map<Long, ProductTreeDto> productNodeMap,
+                                          List<StockInventoryDto> stockList) {
+        for (StockInventoryDto stock : stockList) {
+            Long productId = stock.getProductId();
+            if (productId == null || !productNodeMap.containsKey(productId)) {
+                continue;
+            }
+
+            ProductTreeDto productNode = productNodeMap.get(productId);
+
+            // 鏋勫缓璇ヤ骇鍝佺殑搴撳瓨鏍戯紙鍨嬪彿 -> 鎵规 -> 瀹㈡埛锛�
+            ProductTreeDto stockTree = buildStockTree(stock);
+
+            // 鍚堝苟鍒颁骇鍝佽妭鐐圭殑 children 涓�
+            mergeStockTree(productNode.getChildren(), stockTree);
+        }
+    }
+
+    /**
+     * 鏋勫缓鍗曚釜搴撳瓨鐨勬爲缁撴瀯锛堝瀷鍙� -> 鎵规 -> 瀹㈡埛锛�
+     */
+    private ProductTreeDto buildStockTree(StockInventoryDto stock) {
+        // 鍨嬪彿鑺傜偣
+        ProductTreeDto modelNode = new ProductTreeDto();
+        modelNode.setModel(stock.getModel());
+        modelNode.setUidNo(stock.getUidNo());
+        modelNode.setUnit(stock.getUnit());
+        modelNode.setProductModelId(stock.getProductModelId());
+        modelNode.setLabel(stock.getModel());
+        modelNode.setNodeType("model");
+        modelNode.setChildren(new ArrayList<>());
+
+        // 鎵规鑺傜偣
+        ProductTreeDto batchNode = new ProductTreeDto();
+        String batchNo = StringUtils.isBlank(stock.getBatchNo()) ? "鏃犳壒娆�" : stock.getBatchNo();
+        batchNode.setBatchNo(batchNo);
+        batchNode.setLabel("鎵规: " + batchNo);
+        batchNode.setNodeType("batch");
+        batchNode.setChildren(new ArrayList<>());
+
+        // 瀹㈡埛鑺傜偣
+        ProductTreeDto customerNode = new ProductTreeDto();
+        String customer = StringUtils.isBlank(stock.getCustomer()) ? "鏃犲鎴�" : stock.getCustomer();
+        customerNode.setCustomer(customer);
+        customerNode.setLabel(customer);
+        customerNode.setNodeType("customer");
+        customerNode.setChildren(new ArrayList<>());
+
+        batchNode.getChildren().add(customerNode);
+        modelNode.getChildren().add(batchNode);
+
+        return modelNode;
+    }
+
+    /**
+     * 鍚堝苟搴撳瓨鏍戝埌浜у搧鑺傜偣鐨� children 涓�
+     */
+    private void mergeStockTree(List<ProductTreeDto> children, ProductTreeDto newStockTree) {
+        if (children == null) {
+            return;
+        }
+
+        // 鏌ユ壘鏄惁宸叉湁鐩稿悓鍨嬪彿鐨勮妭鐐�
+        ProductTreeDto existingModelNode = null;
+        for (ProductTreeDto child : children) {
+            if (child.getNodeType().equals("model") &&
+                    child.getModel() != null &&
+                    child.getModel().equals(newStockTree.getModel())) {
+                existingModelNode = child;
+                break;
+            }
+        }
+
+        if (existingModelNode == null) {
+            // 娌℃湁鐩稿悓鍨嬪彿锛岀洿鎺ユ坊鍔�
+            children.add(newStockTree);
+        } else {
+            // 鏈夌浉鍚屽瀷鍙凤紝鍚堝苟鎵规鑺傜偣
+            ProductTreeDto newBatchNode = newStockTree.getChildren().get(0);
+
+            // 鏌ユ壘鏄惁宸叉湁鐩稿悓鎵规
+            ProductTreeDto existingBatchNode = null;
+            for (ProductTreeDto batchChild : existingModelNode.getChildren()) {
+                if (batchChild.getNodeType().equals("batch") &&
+                        batchChild.getBatchNo() != null &&
+                        batchChild.getBatchNo().equals(newBatchNode.getBatchNo())) {
+                    existingBatchNode = batchChild;
+                    break;
+                }
+            }
+
+            if (existingBatchNode == null) {
+                existingModelNode.getChildren().add(newBatchNode);
+            } else {
+                // 鍚堝苟瀹㈡埛鑺傜偣
+                ProductTreeDto newCustomerNode = newBatchNode.getChildren().get(0);
+                boolean customerExists = false;
+                for (ProductTreeDto customerChild : existingBatchNode.getChildren()) {
+                    if (customerChild.getNodeType().equals("customer") &&
+                            customerChild.getCustomer() != null &&
+                            customerChild.getCustomer().equals(newCustomerNode.getCustomer())) {
+                        customerExists = true;
+                        break;
+                    }
+                }
+                if (!customerExists) {
+                    existingBatchNode.getChildren().add(newCustomerNode);
+                }
+            }
+        }
     }
 }
diff --git a/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml b/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
index c5c007e..1446ab6 100644
--- a/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
+++ b/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
@@ -189,7 +189,7 @@
         T1.supplier_name,
         SUM(contract_amount) AS invoiceAmount,
         IFNULL( SUM(T2.current_payment_amount) , 0 ) AS paymentAmount,
-        IFNULL((IFNULL(SUM(contract_amount),0)  - IFNULL(SUM(T2.current_payment_amount),0)),0) AS payableAmount
+        IFNULL((IFNULL(SUM(contract_amount),0) - IFNULL(SUM(T2.current_payment_amount),0)),0) AS payableAmount
         FROM purchase_ledger T1
         LEFT JOIN payment_registration T2 ON T1.id = T2.purchase_ledger_id
         <where>
@@ -197,7 +197,7 @@
                 T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
             </if>
         </where>
-        GROUP BY T1.supplier_name
+        GROUP BY T1.supplier_id, T1.supplier_name
     </select>
 
     <select id="supplierNameListPageDetails" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index da3f233..21bc11e 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -65,7 +65,9 @@
         si.remark,
         pm.unit,
         pm.uid_no as uidNo,
-        p.product_name
+        p.product_name,
+        si.batch_no,
+        si.customer
         from stock_inventory si
         left join product_model pm on si.product_model_id = pm.id
         left join product p on pm.product_id = p.id
@@ -259,6 +261,40 @@
 
     <select id="getMaterials" resultType="com.ruoyi.stock.dto.StockInventoryDto">
         SELECT
+        si.id,
+        si.qualitity,
+        COALESCE(si.locked_quantity, 0) AS locked_quantity,
+        si.product_model_id,
+        si.create_time,
+        si.update_time,
+        COALESCE(si.warn_num, 0) AS warn_num,
+        si.version,
+        (si.qualitity - COALESCE(si.locked_quantity, 0)) AS un_locked_quantity,
+        pm.model,
+        si.remark,
+        pm.unit,
+        pm.uid_no AS uidNo,
+        p.product_name,
+        p1.product_name AS parentName,
+        si.batch_no,
+        si.customer
+        FROM
+        stock_inventory si
+        LEFT JOIN product_model pm ON si.product_model_id = pm.id
+        LEFT JOIN product p ON pm.product_id = p.id
+        LEFT JOIN product p1 ON p1.id = p.parent_id
+        WHERE
+            p1.product_name = '鍘熸潗鏂�';
+        <if test="ew.batchNo != null and ew.batchNo !=''">
+            and si.batch_no like concat('%',#{ew.batchNo},'%')
+        </if>
+        <if test="ew.customer != null and ew.customer !=''">
+            and si.customer like concat('%',#{ew.customer},'%')
+        </if>
+    </select>
+
+    <select id="getStockInventoryAll" resultType="com.ruoyi.stock.dto.StockInventoryDto">
+        SELECT
             si.id,
             si.qualitity,
             COALESCE(si.locked_quantity, 0) AS locked_quantity,
@@ -268,19 +304,28 @@
             COALESCE(si.warn_num, 0) AS warn_num,
             si.version,
             (si.qualitity - COALESCE(si.locked_quantity, 0)) AS un_locked_quantity,
+            pm.id as productModelId,
             pm.model,
             si.remark,
             pm.unit,
             pm.uid_no AS uidNo,
+            p.id AS product_id,
             p.product_name,
-            p1.product_name AS parentName
-        FROM
+            p.parent_id AS parent_id,
+            p1.product_name AS parentName,
+            si.batch_no,
+            si.customer
+            FROM
             stock_inventory si
-                LEFT JOIN product_model pm ON si.product_model_id = pm.id
-                LEFT JOIN product p ON pm.product_id = p.id
-                LEFT JOIN product p1 ON p1.id = p.parent_id
-        WHERE
-            p1.product_name = '鍘熸潗鏂�';
+            LEFT JOIN product_model pm ON si.product_model_id = pm.id
+            LEFT JOIN product p ON pm.product_id = p.id
+            LEFT JOIN product p1 ON p1.id = p.parent_id
+        <where>
+            <if test="ew.productName != null and ew.productName != ''">
+                AND p.product_name LIKE CONCAT('%', #{ew.productName}, '%')
+            </if>
+        </where>
     </select>
 
+
 </mapper>

--
Gitblit v1.9.3