From 8352c314f8a15a5caf6dfa2837562f839eeef6c3 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 24 四月 2026 10:13:28 +0800
Subject: [PATCH] feat: 库存管理调整为按照大类进行区分

---
 src/main/java/com/ruoyi/stock/service/StockInventoryService.java            |    2 
 src/main/resources/mapper/basic/ProductModelMapper.xml                      |   16 ++
 src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java                    |   31 ++++
 src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java           |   14 +
 src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java              |    1 
 src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java |    1 
 src/main/resources/mapper/stock/StockInventoryMapper.xml                    |  184 ++++++++++++++++++++++++--
 src/main/resources/mapper/stock/StockUninventoryMapper.xml                  |    3 
 src/main/java/com/ruoyi/basic/pojo/ProductModel.java                        |    7 +
 src/main/java/com/ruoyi/stock/controller/StockInventoryController.java      |    7 +
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java   |   99 ++++++++++---
 11 files changed, 320 insertions(+), 45 deletions(-)

diff --git a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
index 7aa975f..9ec0661 100644
--- a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
+++ b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -69,10 +69,17 @@
 
     @TableField(exist = false)
     private LocalDateTime createTime;
+    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
 
     @TableField(exist = false)
     private Long parentId;
 
     @TableField(exist = false)
     private String parentName;
+
+    @ApiModelProperty("椤堕儴鐖朵骇鍝乮d")
+    @TableField(exist = false)
+    private Long topProductParentId;
 }
diff --git a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
index 70f638e..c253728 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
@@ -44,6 +44,13 @@
         return R.ok(stockInventoryDtoIPage);
     }
 
+    @GetMapping("/pageListCombinedStockInventory")
+    @ApiOperation("鍒嗛〉鏌ヨ鑱斿悎搴撳瓨鍒楄〃")
+    public R pageListCombinedStockInventory(Page page, StockInventoryDto stockInventoryDto) {
+        IPage<StockInventoryDto> stockInventoryDtoIPage = stockInventoryService.pageListCombinedStockInventory(page, stockInventoryDto);
+        return R.ok(stockInventoryDtoIPage);
+    }
+
     @PostMapping("/addstockInventory")
     @ApiOperation("鏂板搴撳瓨")
     public R addstockInventory(@RequestBody StockInventoryDto stockInventoryDto) {
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
index ac3b27b..1763396 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
@@ -2,6 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.stock.pojo.StockInventory;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -50,4 +51,34 @@
      * 鍘氬害
      */
     private BigDecimal thickness;
+
+    @ApiModelProperty("椤堕儴鐖朵骇鍝乮d")
+    private Long topParentProductId;
+    
+    @ApiModelProperty("搴撳瓨绫诲瀷锛歲ualified(鍚堟牸)銆乽nqualified(涓嶅悎鏍�)")
+    private String stockType;
+    
+    @ApiModelProperty("鍚堟牸搴撳瓨鏁伴噺")
+    private BigDecimal qualifiedQuantity;
+    
+    @ApiModelProperty("涓嶅悎鏍煎簱瀛樻暟閲�")
+    private BigDecimal unQualifiedQuantity;
+    
+    @ApiModelProperty("鍚堟牸搴撳瓨鍐荤粨鏁伴噺")
+    private BigDecimal qualifiedLockedQuantity;
+    
+    @ApiModelProperty("涓嶅悎鏍煎簱瀛樺喕缁撴暟閲�")
+    private BigDecimal unQualifiedLockedQuantity;
+    
+    @ApiModelProperty("鍚堟牸搴撳瓨鏈喕缁撴暟閲�")
+    private BigDecimal qualifiedUnLockedQuantity;
+    
+    @ApiModelProperty("涓嶅悎鏍煎簱瀛樻湭鍐荤粨鏁伴噺")
+    private BigDecimal unQualifiedUnLockedQuantity;
+    
+    @ApiModelProperty("鍚堟牸搴撳瓨ID")
+    private Long qualifiedId;
+    
+    @ApiModelProperty("涓嶅悎鏍煎簱瀛業D")
+    private Long unQualifiedId;
 }
diff --git a/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java b/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
index 4b7553f..a5cec35 100644
--- a/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
+++ b/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
@@ -19,14 +19,20 @@
     @Excel(name = "鍗曚綅")
     private String unit;
 
-    @Excel(name = "搴撳瓨鏁伴噺")
-    private BigDecimal qualitity;
+    @Excel(name = "鍚堟牸搴撳瓨鏁伴噺")
+    private BigDecimal qualifiedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎簱瀛樻暟閲�")
+    private BigDecimal unQualifiedQuantity;
 
     @Excel(name = "棰勮鏁伴噺")
     private BigDecimal warnNum;
 
-    @Excel(name = "鍐荤粨鏁伴噺")
-    private BigDecimal lockedQuantity;
+    @Excel(name = "鍚堟牸鍐荤粨鏁伴噺")
+    private BigDecimal qualifiedLockedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎喕缁撴暟閲�")
+    private BigDecimal unQualifiedLockedQuantity;
 
     @Excel(name = "澶囨敞")
     private String remark;
diff --git a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
index 0d345df..9f493d2 100644
--- a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
+++ b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
@@ -29,6 +29,7 @@
 
     IPage<StockInventoryDto> pagestockInventory(Page page, @Param("ew") StockInventoryDto stockInventoryDto);
 
+    IPage<StockInventoryDto> pageListCombinedStockInventory(Page page, @Param("ew") StockInventoryDto stockInventoryDto);
 
     int updateAddStockInventory(@Param("ew") StockInventoryDto stockInventoryDto);
 
diff --git a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
index 65dcca3..429eeea 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
@@ -23,6 +23,8 @@
 
     IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto);
 
+    IPage<StockInventoryDto> pageListCombinedStockInventory(Page page, StockInventoryDto stockInventoryDto);
+
     Boolean addstockInventory(StockInventoryDto stockInventoryDto);
 
     Boolean subtractStockInventory(StockInventoryDto stockInventoryDto);
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 8baa113..c0b752d 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -6,7 +6,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.R;
@@ -15,12 +15,14 @@
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.dto.StockOutRecordDto;
+import com.ruoyi.stock.dto.StockUninventoryDto;
 import com.ruoyi.stock.execl.StockInventoryExportData;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
 import com.ruoyi.stock.pojo.StockInventory;
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.stock.service.StockInventoryService;
 import com.ruoyi.stock.service.StockOutRecordService;
+import com.ruoyi.stock.service.StockUninventoryService;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -29,7 +31,9 @@
 import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -46,11 +50,17 @@
     private StockInventoryMapper stockInventoryMapper;
     private StockInRecordService stockInRecordService;
     private StockOutRecordService stockOutRecordService;
+    private StockUninventoryService stockUninventoryService;
     private SalesLedgerProductMapper salesLedgerProductMapper;
 
     @Override
     public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
         return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
+    }
+
+    @Override
+    public IPage<StockInventoryDto> pageListCombinedStockInventory(Page page, StockInventoryDto stockInventoryDto) {
+        return stockInventoryMapper.pageListCombinedStockInventory(page, stockInventoryDto);
     }
 
     //鍏ュ簱璋冪敤
@@ -135,59 +145,98 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public R importStockInventory(MultipartFile file) {
         try {
             // 鏌ヨ鎵�鏈夌殑浜у搧
             List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectProduct();
+            Map<String, SalesLedgerProduct> productMap = new HashMap<>();
+            for (SalesLedgerProduct product : salesLedgerProducts) {
+                // 浣跨敤浜у搧绫诲埆鍜岃鏍煎瀷鍙蜂綔涓洪敭
+                String key = product.getProductCategory() + "|" + product.getSpecificationModel();
+                productMap.put(key, product);
+            }
 
             ExcelUtil<StockInventoryExportData> util = new ExcelUtil<StockInventoryExportData>(StockInventoryExportData.class);
             List<StockInventoryExportData> list = util.importExcel(file.getInputStream());
 
             // 璁板綍鏈壘鍒板尮閰嶉」鐨勬暟鎹�
             List<String> unmatchedRecords = new ArrayList<>();
+            int successCount = 0;
 
-            list.forEach(dto -> {
-                boolean matched = false;
-                for (SalesLedgerProduct item : salesLedgerProducts) {
-                    if (item.getProductCategory().equals(dto.getProductName()) &&
-                            item.getSpecificationModel().equals(dto.getModel())) {
+            for (StockInventoryExportData dto : list) {
+                // 鏋勫缓鏌ユ壘閿�
+                String key = dto.getProductName() + "|" + dto.getModel();
+                SalesLedgerProduct matchedProduct = productMap.get(key);
+                
+                if (matchedProduct != null) {
+                    // 澶勭悊鍚堟牸搴撳瓨
+                    if (dto.getQualifiedQuantity() != null && dto.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) {
                         StockInventoryDto stockInventoryDto = new StockInventoryDto();
                         stockInventoryDto.setRecordId(0L);
                         stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode());
-                        stockInventoryDto.setQualitity(dto.getQualitity());
+                        stockInventoryDto.setQualitity(dto.getQualifiedQuantity());
                         stockInventoryDto.setRemark(dto.getRemark());
                         stockInventoryDto.setWarnNum(dto.getWarnNum());
-                        if (ObjectUtils.isNotEmpty(dto.getLockedQuantity()) && dto.getLockedQuantity().compareTo(dto.getQualitity()) > 0) {
-                            throw new RuntimeException("鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫簱瀛樻暟閲�");
+                        // 楠岃瘉鍚堟牸鍐荤粨鏁伴噺
+                        if (ObjectUtils.isNotEmpty(dto.getQualifiedLockedQuantity())) {
+                            if (dto.getQualifiedLockedQuantity().compareTo(dto.getQualifiedQuantity()) > 0) {
+                                throw new ServiceException("鍚堟牸鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫悎鏍煎簱瀛樻暟閲�");
+                            }
+                            stockInventoryDto.setLockedQuantity(dto.getQualifiedLockedQuantity());
+                        } else {
+                            stockInventoryDto.setLockedQuantity(BigDecimal.ZERO);
                         }
-                        stockInventoryDto.setLockedQuantity(dto.getLockedQuantity());
-                        stockInventoryDto.setProductModelId(item.getProductModelId());
+                        
+                        stockInventoryDto.setProductModelId(matchedProduct.getProductModelId());
                         this.addstockInventory(stockInventoryDto);
-                        matched = true;
-                        break; // 鎵惧埌鍖归厤椤瑰悗璺冲嚭寰幆
+                        successCount++;
                     }
+
+                    // 澶勭悊涓嶅悎鏍煎簱瀛�
+                    if (dto.getUnQualifiedQuantity() != null && dto.getUnQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) {
+                        StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
+                        stockUninventoryDto.setRecordId(0L);
+                        stockUninventoryDto.setRecordType(StockInUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_IN.getCode());
+                        stockUninventoryDto.setQualitity(dto.getUnQualifiedQuantity());
+                        stockUninventoryDto.setRemark(dto.getRemark());
+                        
+                        // 楠岃瘉涓嶅悎鏍煎喕缁撴暟閲�
+                        if (ObjectUtils.isNotEmpty(dto.getUnQualifiedLockedQuantity())) {
+                            if (dto.getUnQualifiedLockedQuantity().compareTo(dto.getUnQualifiedQuantity()) > 0) {
+                                throw new ServiceException("涓嶅悎鏍煎喕缁撴暟閲忎笉鑳借秴杩囨湰娆″鍏ョ殑涓嶅悎鏍煎簱瀛樻暟閲�");
+                            }
+                            stockUninventoryDto.setLockedQuantity(dto.getUnQualifiedLockedQuantity());
+                        } else {
+                            stockUninventoryDto.setLockedQuantity(BigDecimal.ZERO);
+                        }
+
+                        stockUninventoryDto.setProductModelId(matchedProduct.getProductModelId());
+                        stockUninventoryService.addStockUninventory(stockUninventoryDto);
+                        successCount++;
+                    }
+                } else {
+                    // 璁板綍鏈尮閰嶇殑浜у搧
+                    String unmatchedRecord = "浜у搧鍚嶇О锛�" + dto.getProductName() + "锛屽瀷鍙凤細" + dto.getModel();
+                    unmatchedRecords.add(unmatchedRecord);
                 }
-                if (!matched) {
-                    // 璁板綍鏈尮閰嶇殑鏁版嵁
-                    String unmatchedInfo = String.format("浜у搧鍚嶇О锛�%s锛岃鏍煎瀷鍙凤細%s",
-                            dto.getProductName(), dto.getModel());
-                    unmatchedRecords.add(unmatchedInfo);
-                }
-            });
+            }
+            
             // 鏋勫缓杩斿洖淇℃伅
             StringBuilder message = new StringBuilder();
             if (!unmatchedRecords.isEmpty()) {
-                message.append("浠ヤ笅浜у搧鏈壘鍒板尮閰嶉」锛歕n");
+                message.append("瀵煎叆鎴愬姛 " + successCount + " 鏉¤褰曪紝浠ヤ笅浜у搧鏈壘鍒板尮閰嶉」锛歕n");
                 for (String record : unmatchedRecords) {
                     message.append(record).append("\n");
                 }
-                throw new RuntimeException(message.toString());
+                return R.ok(message.toString());
             }
+            
+            return R.ok("瀵煎叆鎴愬姛锛屽叡澶勭悊 " + successCount + " 鏉¤褰�");
         } catch (Exception e) {
-            e.printStackTrace();
+            log.error("瀵煎叆搴撳瓨澶辫触", e);
             return R.fail("瀵煎叆澶辫触锛�" + e.getMessage());
         }
-        return R.ok("瀵煎叆鎴愬姛");
     }
 
 
@@ -232,4 +281,4 @@
         stockInventory.setLockedQuantity(stockInventory.getLockedQuantity().subtract(stockInventoryDto.getLockedQuantity()));
         return this.updateById(stockInventory);
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
index cfa9044..3fa75da 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
@@ -67,6 +67,7 @@
             StockUninventory newStockUnInventory = new StockUninventory();
             newStockUnInventory.setProductModelId(stockUninventoryDto.getProductModelId());
             newStockUnInventory.setQualitity(stockUninventoryDto.getQualitity());
+            newStockUnInventory.setLockedQuantity(stockUninventoryDto.getLockedQuantity());
             newStockUnInventory.setVersion(1);
             newStockUnInventory.setRemark(stockUninventoryDto.getRemark());
             stockUninventoryMapper.insert(newStockUnInventory);
diff --git a/src/main/resources/mapper/basic/ProductModelMapper.xml b/src/main/resources/mapper/basic/ProductModelMapper.xml
index cb80816..9a7e927 100644
--- a/src/main/resources/mapper/basic/ProductModelMapper.xml
+++ b/src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -56,6 +56,22 @@
             <if test="c.parentName != null and c.parentName != ''">
                 AND pt.top_name LIKE CONCAT('%', #{c.parentName}, '%')
             </if>
+            <if test="c.topProductParentId != null and c.topProductParentId > 0">
+                and p.id in (
+                    WITH RECURSIVE product_tree AS (
+                        SELECT id
+                        FROM product
+                        WHERE id = #{c.topProductParentId}
+                        
+                        UNION ALL
+                        
+                        SELECT p.id
+                        FROM product p
+                        INNER JOIN product_tree pt ON p.parent_id = pt.id
+                    )
+                    select id from product_tree
+                )
+            </if>
         </where>
         ORDER BY pm.id DESC
     </select>
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index d898c2c..6428e9c 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -80,22 +80,174 @@
         </if>
     </select>
 
+    <select id="pageListCombinedStockInventory" resultType="com.ruoyi.stock.dto.StockInventoryDto">
+        WITH RECURSIVE product_tree AS (
+        SELECT id
+        FROM product
+        WHERE id = #{ew.topParentProductId}
+
+        UNION ALL
+
+        SELECT p.id
+        FROM product p
+        INNER JOIN product_tree pt ON p.parent_id = pt.id
+        )
+        select
+            MAX(qualifiedId) as qualifiedId,
+            MAX(unQualifiedId) as unQualifiedId,
+            SUM(qualifiedQuantity) as qualifiedQuantity,
+            SUM(unQualifiedQuantity) as unQualifiedQuantity,
+            SUM(qualifiedLockedQuantity) as qualifiedLockedQuantity,
+            SUM(unQualifiedLockedQuantity) as unQualifiedLockedQuantity,
+            SUM(qualifiedQuantity - qualifiedLockedQuantity) as qualifiedUnLockedQuantity,
+            SUM(unQualifiedQuantity - unQualifiedLockedQuantity) as unQualifiedUnLockedQuantity,
+            product_model_id,
+            MAX(create_time) as create_time,
+            MAX(update_time) as update_time,
+            MAX(warn_num) as warn_num,
+            MAX(version) as version,
+            model,
+            MAX(remark) as remark,
+            unit,
+            product_name,
+            product_id,
+            'combined' as stockType
+        from (
+            select
+            si.id as qualifiedId,
+            null as unQualifiedId,
+            si.qualitity as qualifiedQuantity,
+            0 as unQualifiedQuantity,
+            COALESCE(si.locked_quantity, 0) as locked_quantity,
+            COALESCE(si.locked_quantity, 0) as qualifiedLockedQuantity,
+            0 as unQualifiedLockedQuantity,
+            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,
+            p.product_name,
+            p.id as product_id
+            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
+
+            union all
+
+            select
+            null as qualifiedId,
+            su.id as unQualifiedId,
+            0 as qualifiedQuantity,
+            su.qualitity as unQualifiedQuantity,
+            COALESCE(su.locked_quantity, 0) as locked_quantity,
+            0 as qualifiedLockedQuantity,
+            COALESCE(su.locked_quantity, 0) as unQualifiedLockedQuantity,
+            su.product_model_id,
+            su.create_time,
+            su.update_time,
+            0 as warn_num,
+            su.version,
+            (su.qualitity - COALESCE(su.locked_quantity, 0)) as un_locked_quantity,
+            pm.model,
+            su.remark,
+            pm.unit,
+            p.product_name,
+            p.id as product_id
+            from stock_uninventory su
+            left join product_model pm on su.product_model_id = pm.id
+            left join product p on pm.product_id = p.id
+        ) as combined
+        <where>
+            <if test="ew.productName != null and ew.productName !=''">
+                and combined.product_name like concat('%',#{ew.productName},'%')
+            </if>
+            <if test="ew.model != null and ew.model !=''">
+                and combined.model like concat('%',#{ew.model},'%')
+            </if>
+            <if test="ew.topParentProductId != null and ew.topParentProductId > 0">
+                and combined.product_id in (select id from product_tree)
+            </if>
+        </where>
+        group by product_model_id, model, unit, product_name, product_id
+    </select>
     <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData">
-        select si.qualitity,
-        pm.model,
-        pm.unit,
-        p.product_name,
-        coalesce(si.warn_num, 0) as warn_num,
-        coalesce(si.locked_quantity, 0) as locked_quantity,
-        si.remark,
-        si.update_time
-        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
-        where 1 = 1
-        <if test="ew.productName != null and ew.productName !=''">
-            and p.product_name like concat('%',#{ew.productName},'%')
-        </if>
+        WITH RECURSIVE product_tree AS (
+        SELECT id
+        FROM product
+        WHERE id = #{ew.topParentProductId}
+
+        UNION ALL
+
+        SELECT p.id
+        FROM product p
+        INNER JOIN product_tree pt ON p.parent_id = pt.id
+        )
+        select
+            SUM(qualifiedQuantity) as qualifiedQuantity,
+            SUM(unQualifiedQuantity) as unQualifiedQuantity,
+            SUM(qualifiedLockedQuantity) as qualifiedLockedQuantity,
+            SUM(unQualifiedLockedQuantity) as unQualifiedLockedQuantity,
+            model,
+            unit,
+            product_name,
+            MAX(warn_num) as warn_num,
+            MAX(remark) as remark,
+            MAX(update_time) as update_time
+        from (
+            select
+            si.qualitity as qualifiedQuantity,
+            0 as unQualifiedQuantity,
+            COALESCE(si.locked_quantity, 0) as qualifiedLockedQuantity,
+            0 as unQualifiedLockedQuantity,
+            si.product_model_id,
+            si.create_time,
+            si.update_time,
+            COALESCE(si.warn_num, 0) as warn_num,
+            si.remark,
+            pm.model,
+            pm.unit,
+            p.product_name,
+            p.id as product_id
+            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
+
+            union all
+
+            select
+            0 as qualifiedQuantity,
+            su.qualitity as unQualifiedQuantity,
+            0 as qualifiedLockedQuantity,
+            COALESCE(su.locked_quantity, 0) as unQualifiedLockedQuantity,
+            su.product_model_id,
+            su.create_time,
+            su.update_time,
+            0 as warn_num,
+            su.remark,
+            pm.model,
+            pm.unit,
+            p.product_name,
+            p.id as product_id
+            from stock_uninventory su
+            left join product_model pm on su.product_model_id = pm.id
+            left join product p on pm.product_id = p.id
+        ) as combined
+        <where>
+            <if test="ew.productName != null and ew.productName !=''">
+                and combined.product_name like concat('%',#{ew.productName},'%')
+            </if>
+            <if test="ew.model != null and ew.model !=''">
+                and combined.model like concat('%',#{ew.model},'%')
+            </if>
+            <if test="ew.topParentProductId != null and ew.topParentProductId > 0">
+                and combined.product_id in (select id from product_tree)
+            </if>
+        </where>
+        group by product_model_id, model, unit, product_name
     </select>
     <select id="stockInventoryPage" resultType="com.ruoyi.stock.dto.StockInRecordDto">
         select sir.*,si.qualitity as current_stock,
@@ -246,4 +398,4 @@
         ORDER BY DATE(sor.create_time) ASC
     </select>
 
-</mapper>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/stock/StockUninventoryMapper.xml b/src/main/resources/mapper/stock/StockUninventoryMapper.xml
index 1ebd219..8f2a215 100644
--- a/src/main/resources/mapper/stock/StockUninventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockUninventoryMapper.xml
@@ -34,6 +34,9 @@
             <if test="ew.qualitity != null">
                 qualitity = qualitity + #{ew.qualitity},
             </if>
+            <if test="ew.lockedQuantity != null">
+                locked_quantity = locked_quantity + #{ew.lockedQuantity},
+            </if>
             <if test="ew.version != null">
                 version = version + 1,
             </if>

--
Gitblit v1.9.3