From a76e1d17d67641993dea6335cb8e1465a94df58d Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期四, 21 五月 2026 15:39:05 +0800
Subject: [PATCH] feat(stock): 优化库存管理和成品树结构功能 1- 为ApproveProcessMapper.xml和ProductBomMapper.xml添加排序功能 2- 在ProductionProductMainDto中新增bomInputQty字段用于产品结构投入数量 3- 修改ProductionProductMainServiceImpl中投入数量计算逻辑,使用前端传入的bomInputQty值 4- 在ProductWorkOrderDto中添加bomInputQty字段并在服务实现中计算标准投入数量 5- 更新SalesLedgerMapper.xml查询逻辑,从product_summary获取电压信息 6- 为SalesLedgerProduct添加stockId字段并修改库存扣减逻辑使用具体库存ID 7- 重构StockInventoryController中的成品库存树查询接口和导入导出功能 8- 新增成品和非成品库存导入导出的数据模型和Excel工具类 9- 优化StockInventoryServiceImpl中的库存扣减逻辑,支持按特定库存ID操作 10- 更新库存导入导出功能,区分成品和非成品类型并提供相应模板

---
 src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java                              |    4 
 src/main/java/com/ruoyi/stock/service/StockInventoryService.java                      |    4 
 src/main/resources/mapper/sales/SalesLedgerMapper.xml                                 |    5 
 src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java                            |    4 
 src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java                       |   17 +
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java               |    3 
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                          |    7 
 src/main/java/com/ruoyi/stock/execl/FinishedProductInventoryExportData.java           |   54 +++
 src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java                       |    4 
 src/main/java/com/ruoyi/stock/dto/FinishedProductTreeDto.java                         |   34 +
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java             |  382 ++++++++++++++------------
 src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java                              |    5 
 src/main/resources/mapper/stock/StockOutRecordMapper.xml                              |   14 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |   13 
 src/main/resources/mapper/production/ProductBomMapper.xml                             |    1 
 src/main/java/com/ruoyi/stock/execl/NonFinishedProductInventoryExportData.java        |   48 +++
 src/main/resources/mapper/stock/StockInventoryMapper.xml                              |   33 ++
 src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java             |   33 ++
 src/main/java/com/ruoyi/stock/controller/StockInventoryController.java                |   39 +
 src/main/resources/mapper/approve/ApproveProcessMapper.xml                            |    1 
 src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java                  |    3 
 src/main/java/com/ruoyi/stock/execl/StockOutRecordExportData.java                     |    3 
 src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java      |   63 ++++
 src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java                     |   10 
 src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java                        |    3 
 25 files changed, 566 insertions(+), 221 deletions(-)

diff --git a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
index 288f721..27ebea8 100644
--- a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
+++ b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -152,7 +152,7 @@
      * @param recordType
      * @param recordId
      */
-    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId,String batchNo) {
+    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId,String batchNo,Long stockId) {
         StockInventoryDto stockInventoryDto = new StockInventoryDto();
         stockInventoryDto.setRecordId(recordId);
         stockInventoryDto.setRecordType(String.valueOf(recordType));
@@ -161,6 +161,7 @@
         if (batchNo !=null && !batchNo.isEmpty()) {
             stockInventoryDto.setBatchNo(batchNo);
         }
+        stockInventoryDto.setStockId(stockId);
         stockInventoryService.subtractStockInventory(stockInventoryDto);
     }
 
@@ -185,4 +186,18 @@
             stockOutRecordService.batchDelete(idList);
         }
     }
+
+    /**
+     * 浠呮寜recordId鍒犻櫎鍑哄簱璁板綍锛堢敤浜巖ecordType涓哄姩鎬佸�肩殑鍦烘櫙锛�
+     */
+    public void deleteStockOutRecordByRecordId(Long recordId) {
+        List<StockOutRecord> one = stockOutRecordService.list(new QueryWrapper<StockOutRecord>()
+                .lambda().eq(StockOutRecord::getRecordId, recordId));
+        if (ObjectUtils.isNotEmpty(one)) {
+            List<Long> idList = one.stream()
+                    .map(StockOutRecord::getId)
+                    .collect(Collectors.toList());
+            stockOutRecordService.batchDelete(idList);
+        }
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java b/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
index 2ba3567..ee9e07b 100644
--- a/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
+++ b/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
@@ -62,6 +62,10 @@
     @ApiModelProperty(value = "鎶曞叆鏁伴噺")
     private BigDecimal inputQty;
 
+    // 浜у搧缁撴瀯鎶曞叆鏁伴噺
+    @ApiModelProperty(value = "浜у搧缁撴瀯鎶曞叆鏁伴噺")
+    private BigDecimal bomInputQty;
+
     @ApiModelProperty(value = "宸ュ崟绫诲瀷 姝e父 /杩斿伐杩斾慨")
     private String workOrderType;
 
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java b/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
index 5518c27..a02e40c 100644
--- a/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
+++ b/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
@@ -86,4 +86,7 @@
 
     @ApiModelProperty(value = "鐢熶骇鎵瑰彿")
     private String batchNo;
+
+    @ApiModelProperty(value = "浜у搧缁撴瀯鎶曞叆鏁伴噺")
+    private BigDecimal bomInputQty;
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
index 982009f..b73d629 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
@@ -11,6 +11,7 @@
 import com.deepoove.poi.data.Pictures;
 import com.ruoyi.common.utils.MatrixToImageWriter;
 import com.ruoyi.production.dto.ProductWorkOrderDto;
+import com.ruoyi.production.dto.ProductStructureDto;
 import com.ruoyi.production.mapper.*;
 import com.ruoyi.production.pojo.*;
 import com.ruoyi.production.service.ProductWorkOrderService;
@@ -30,6 +31,7 @@
 import java.math.RoundingMode;
 import java.net.URLEncoder;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Service
@@ -44,6 +46,10 @@
     private ProductProcessRouteItemMapper productProcessRouteItemMapper;
     @Autowired
     private ProductProcessMapper productProcessMapper;
+    @Autowired
+    private ProductProcessRouteMapper productProcessRouteMapper;
+    @Autowired
+    private ProductStructureMapper productStructureMapper;
     @Autowired
     private ProductionProductMainMapper productionProductMainMapper;
     @Autowired
@@ -61,6 +67,7 @@
     @Override
     public IPage<ProductWorkOrderDto> listPage(Page<ProductWorkOrderDto> page, ProductWorkOrderDto productWorkOrder) {
         IPage<ProductWorkOrderDto> productWorkOrderDtoIPage = productWorkOrdermapper.pageProductWorkOrder(page, productWorkOrder);
+        Map<String, BigDecimal> bomInputQtyCache = new HashMap<>();
         productWorkOrderDtoIPage.getRecords().forEach(record -> {
             // 鏄惁鑳芥姤宸ワ細 1. 绗竴涓伐搴忚兘鎶ュ伐 2. 涓婁竴涓伐搴忓凡鎶ュ伐 3. 涔嬪墠鐨勫伐搴忔湭琚殧绂�
             Integer currentDragSort = record.getDragSort();
@@ -126,6 +133,62 @@
             } else {
                 record.setActualQualifiedRate((record.getCompleteQuantity().subtract(totalScrapQty)).multiply(BigDecimal.valueOf(100)));
             }
+
+            // 鏌ヨ褰撳墠宸ュ崟瀵瑰簲浜у搧缁撴瀯涓殑鏍囧噯鎶曞叆鏁伴噺
+            String bomInputQtyCacheKey = record.getProductRouteId() + "_" + record.getProcessId() + "_" + record.getPlanQuantity();
+            BigDecimal bomInputQty = bomInputQtyCache.get(bomInputQtyCacheKey);
+            if (bomInputQty == null) {
+                bomInputQty = BigDecimal.ZERO;
+                ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectById(record.getProductRouteId());
+                if (productProcessRoute != null && productProcessRoute.getBomId() != null && record.getProcessId() != null) {
+                    List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(
+                            productProcessRoute.getBomId(),
+                            record.getProcessId()
+                    );
+
+                    if (CollectionUtils.isEmpty(productStructureDtos)) {
+                        bomInputQty = record.getPlanQuantity() == null ? BigDecimal.ZERO : record.getPlanQuantity();
+                    } else {
+                        Set<Long> parentIds = productStructureDtos.stream()
+                                .map(ProductStructureDto::getParentId)
+                                .filter(Objects::nonNull)
+                                .collect(Collectors.toSet());
+
+                        Map<Long, ProductStructureDto> parentMap = new HashMap<>();
+                        if (CollectionUtils.isNotEmpty(parentIds)) {
+                            parentMap = productStructureMapper.selectByIds(parentIds)
+                                    .stream()
+                                    .collect(Collectors.toMap(ProductStructureDto::getId, Function.identity(), (a, b) -> a));
+                        }
+
+                        BigDecimal planQty = record.getPlanQuantity() == null ? BigDecimal.ZERO : record.getPlanQuantity();
+                        for (ProductStructureDto productStructureDto : productStructureDtos) {
+                            BigDecimal childQty = productStructureDto.getUnitQuantity();
+                            if (childQty == null || childQty.compareTo(BigDecimal.ZERO) <= 0) {
+                                continue;
+                            }
+
+                            BigDecimal parentQty = BigDecimal.ONE;
+                            if (productStructureDto.getParentId() != null) {
+                                ProductStructureDto parent = parentMap.get(productStructureDto.getParentId());
+                                if (parent != null && parent.getUnitQuantity() != null && parent.getUnitQuantity().compareTo(BigDecimal.ZERO) > 0) {
+                                    parentQty = parent.getUnitQuantity();
+                                }
+                            }
+
+                            if (parentQty.compareTo(BigDecimal.ZERO) <= 0) {
+                                continue;
+                            }
+
+                            bomInputQty = bomInputQty.add(
+                                    childQty.divide(parentQty, 6, RoundingMode.HALF_UP).multiply(planQty)
+                            );
+                        }
+                    }
+                }
+                bomInputQtyCache.put(bomInputQtyCacheKey, bomInputQty);
+            }
+            record.setBomInputQty(bomInputQty);
         });
         return productWorkOrderDtoIPage;
     }
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 47e7fcd..5b1177c 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -37,7 +37,6 @@
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
@@ -99,6 +98,7 @@
 
         BigDecimal reportQty = dto.getQuantity();
         BigDecimal scrapQty = dto.getScrapQty() == null ? BigDecimal.ZERO : dto.getScrapQty();
+        BigDecimal bomInputQty = dto.getBomInputQty();
         if (reportQty == null || reportQty.compareTo(BigDecimal.ZERO) <= 0) {
             throw new ServiceException("鎶ュ伐鏁伴噺蹇呴』澶т簬0");
         }
@@ -107,6 +107,9 @@
         }
         if (scrapQty.compareTo(reportQty) > 0) {
             throw new ServiceException("鎶ュ簾鏁伴噺涓嶈兘澶т簬鎶ュ伐鏁伴噺");
+        }
+        if (bomInputQty == null || bomInputQty.compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("浜у搧缁撴瀯鎶曞叆鏁伴噺涓嶈兘灏忎簬0");
         }
 
         // 绗簩姝ワ細鍔犺浇褰撳墠宸ュ簭銆佸伐鍗曘�佸伐鑹鸿矾绾垮拰璁㈠崟鏁版嵁锛屽苟鏍¢獙鍩虹鍏宠仈鍏崇郴
@@ -313,6 +316,9 @@
                     .collect(Collectors.toMap(ProductStructureDto::getId, Function.identity(), (a, b) -> a));
         }
 
+        // 绗竷姝�-1锛氭姇鍏ユ暟閲忓己鍒跺彇鍓嶇浼犲叆鐨� bomInputQty
+        BigDecimal inputBaseQty = bomInputQty;
+
         for (ProductStructureDto productStructureDto : productStructureDtos) {
             if (productStructureDto.getProductModelId() == null) {
                 throw new ServiceException("鎶曞叆鐗╂枡浜у搧鍨嬪彿涓嶈兘涓虹┖");
@@ -335,9 +341,7 @@
                 throw new ServiceException("鐖剁骇鐗╂枡鐢ㄩ噺蹇呴』澶т簬0");
             }
 
-            BigDecimal needQty = childQty
-                    .divide(parentQty, 6, RoundingMode.HALF_UP)
-                    .multiply(reportQty);
+            BigDecimal needQty = inputBaseQty;
 
             ProductionProductInput productionProductInput = new ProductionProductInput();
             productionProductInput.setProductModelId(productStructureDto.getProductModelId());
@@ -350,6 +354,7 @@
                     needQty,
                     StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(),
                     productionProductMain.getId(),
+                    null,
                     null
             );
         }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index 299ac3f..67219f7 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -13,7 +13,6 @@
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Date;
-import java.util.List;
 
 /**
  * 浜у搧淇℃伅瀵硅薄 sales_ledger_product
@@ -261,4 +260,7 @@
 
     @ApiModelProperty("鎵瑰彿")
     private String batchNo;
+
+    @ApiModelProperty("搴撳瓨id")
+    private Long stockId;
 }
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 a39cb72..5735ffb 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -66,7 +66,8 @@
         //鎵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(),null);
+            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(),
+                    StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(),null,salesLedgerProduct.getStockId());
         }
         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 8781257..76ac7c5 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
@@ -10,6 +10,8 @@
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.stock.dto.FinishedProductTreeDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.execl.FinishedProductInventoryExportData;
+import com.ruoyi.stock.execl.NonFinishedProductInventoryExportData;
 import com.ruoyi.stock.execl.StockInventoryExportData;
 import com.ruoyi.stock.service.StockInventoryService;
 import io.swagger.annotations.Api;
@@ -48,11 +50,13 @@
         return R.ok(stockInventoryDtoIPage);
     }
 
-    @GetMapping("/finishedProductList")
+    /**
+     * 鏌ヨ鎴愬搧搴撳瓨鏍�
+     */
     @ApiOperation("鏌ヨ鎴愬搧搴撳瓨鏍�")
-    public R finishedProductList(StockInventoryDto stockInventoryDto) {
-        List<FinishedProductTreeDto> list = stockInventoryService.finishedProductList(stockInventoryDto);
-        return R.ok(list);
+    @GetMapping("/finishedProductList")
+    public List<FinishedProductTreeDto> finishedProductList(StockInventoryDto stockInventoryDto) {
+        return stockInventoryService.finishedProductList(stockInventoryDto);
     }
 
 
@@ -85,22 +89,33 @@
 
     @PostMapping("importStockInventory")
     @ApiOperation("瀵煎叆搴撳瓨")
-    public R importStockInventory(MultipartFile file) {
-        return stockInventoryService.importStockInventory(file);
+    public R importStockInventory(MultipartFile file,
+                                  @RequestParam Integer productType) {
+        return stockInventoryService.importStockInventory(file, productType);
     }
 
     @Log(title = "涓嬭浇搴撳瓨瀵煎叆妯℃澘", businessType = BusinessType.EXPORT)
     @PostMapping("/downloadStockInventory")
-    public void downloadStockInventory(HttpServletResponse response) {
-        List<StockInventoryExportData> list = new ArrayList<>();
-        ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
-        util.exportExcel(response, list, "搴撳瓨妯℃澘");
+    public void downloadStockInventory(HttpServletResponse response,
+                                        @RequestParam Integer productType) {
+        // productType: 1=鎴愬搧, 0=闈炴垚鍝�
+        if (productType == 1) {
+            List<FinishedProductInventoryExportData> list = new ArrayList<>();
+            ExcelUtil<FinishedProductInventoryExportData> util = new ExcelUtil<>(FinishedProductInventoryExportData.class);
+            util.exportExcel(response, list, "鎴愬搧搴撳瓨妯℃澘");
+        } else {
+            List<NonFinishedProductInventoryExportData> list = new ArrayList<>();
+            ExcelUtil<NonFinishedProductInventoryExportData> util = new ExcelUtil<>(NonFinishedProductInventoryExportData.class);
+            util.exportExcel(response, list, "闈炴垚鍝佸簱瀛樻ā鏉�");
+        }
     }
 
     @PostMapping("/exportStockInventory")
     @ApiOperation("瀵煎嚭搴撳瓨")
-    public void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto) {
-        stockInventoryService.exportStockInventory(response, stockInventoryDto);
+    public void exportStockInventory(HttpServletResponse response,
+                                      StockInventoryDto stockInventoryDto,
+                                      @RequestParam Integer productType) {
+        stockInventoryService.exportStockInventory(response, stockInventoryDto, productType);
     }
 
     @GetMapping("stockInventoryPage")
diff --git a/src/main/java/com/ruoyi/stock/dto/FinishedProductTreeDto.java b/src/main/java/com/ruoyi/stock/dto/FinishedProductTreeDto.java
index 9f78801..a17d163 100644
--- a/src/main/java/com/ruoyi/stock/dto/FinishedProductTreeDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/FinishedProductTreeDto.java
@@ -1,31 +1,45 @@
 package com.ruoyi.stock.dto;
 
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.util.List;
 
 @Data
+@ApiModel(value = "FinishedProductTreeDto", description = "鎴愬搧鏍戝舰DTO")
 public class FinishedProductTreeDto {
 
-    private Long id;
-
-    private Long parentId;
-
-    private String productName;
-
-    private String label;
-
+    @ApiModelProperty(value = "浜у搧ID")
     private Long productId;
 
+    @ApiModelProperty(value = "浜у搧鍚嶇О")
+    private String productName;
+
+    @ApiModelProperty(value = "鏍囩/鏄剧ず鍚嶇О")
+    private String label;
+
+    @ApiModelProperty(value = "搴撳瓨ID")
+    private Long stockId;
+
+    @ApiModelProperty(value = "浜у搧鍨嬪彿ID")
     private Long productModelId;
 
+    @ApiModelProperty(value = "鍨嬪彿")
     private String model;
 
-    private String materialCode;
-
+    @ApiModelProperty(value = "宸ュ簭绫诲埆")
     private String processCategory;
 
+    @ApiModelProperty(value = "鐢靛帇")
     private String voltage;
 
+    @ApiModelProperty(value = "鐗╂枡缂栫爜")
+    private String materialCode;
+
+    @ApiModelProperty(value = "鍗曚綅")
+    private String unit;
+
+    @ApiModelProperty(value = "瀛愯妭鐐瑰垪琛�")
     private List<FinishedProductTreeDto> children;
 }
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
index 40de24a..7dcddf7 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
@@ -2,13 +2,16 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.stock.pojo.StockInventory;
+import io.swagger.annotations.ApiModelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
 
+@EqualsAndHashCode(callSuper = true)
 @Data
 public class StockInventoryDto extends StockInventory {
 
@@ -74,4 +77,6 @@
     @Schema(description = "涓嶅悎鏍兼壒娆″彿")
     private String unQualifiedBatchNo;
 
+    @ApiModelProperty("搴撳瓨id")
+    private Long stockId;
 }
diff --git a/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java b/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java
index a39c30d..9f42e3e 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java
@@ -30,6 +30,10 @@
 
     private String createBy;
 
+    private String processName;
+
+    private String recordTypeName;
+
     // 椤堕儴鐖朵骇鍝乮d
     private Long topParentProductId;
 }
diff --git a/src/main/java/com/ruoyi/stock/execl/FinishedProductInventoryExportData.java b/src/main/java/com/ruoyi/stock/execl/FinishedProductInventoryExportData.java
new file mode 100644
index 0000000..647a4fd
--- /dev/null
+++ b/src/main/java/com/ruoyi/stock/execl/FinishedProductInventoryExportData.java
@@ -0,0 +1,54 @@
+package com.ruoyi.stock.execl;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鎴愬搧搴撳瓨瀵煎叆瀵煎嚭瀹炰綋锛堝寘鍚伐搴忕被鍒拰鐢靛帇锛�
+ */
+@Data
+public class FinishedProductInventoryExportData {
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Excel(name = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+    @Excel(name = "鏂欏彿")
+    private String materialCode;
+
+    @Excel(name = "宸ュ簭绫诲埆")
+    private String processCategory;
+
+    @Excel(name = "鐢靛帇")
+    private String voltage;
+
+    // @Excel(name = "鍚堟牸搴撳瓨鎵瑰彿")
+    private String qualifiedBatchNo;
+
+    // @Excel(name = "涓嶅悎鏍煎簱瀛樻壒鍙�")
+    private String unQualifiedBatchNo;
+
+    @Excel(name = "鍚堟牸搴撳瓨鏁伴噺")
+    private BigDecimal qualifiedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎簱瀛樻暟閲�")
+    private BigDecimal unQualifiedQuantity;
+
+    @Excel(name = "棰勮鏁伴噺")
+    private BigDecimal warnNum;
+
+    @Excel(name = "鍚堟牸鍐荤粨鏁伴噺")
+    private BigDecimal qualifiedLockedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎喕缁撴暟閲�")
+    private BigDecimal unQualifiedLockedQuantity;
+
+    @Excel(name = "澶囨敞")
+    private String remark;
+}
diff --git a/src/main/java/com/ruoyi/stock/execl/NonFinishedProductInventoryExportData.java b/src/main/java/com/ruoyi/stock/execl/NonFinishedProductInventoryExportData.java
new file mode 100644
index 0000000..5e33f9f
--- /dev/null
+++ b/src/main/java/com/ruoyi/stock/execl/NonFinishedProductInventoryExportData.java
@@ -0,0 +1,48 @@
+package com.ruoyi.stock.execl;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 闈炴垚鍝佸簱瀛樺鍏ュ鍑哄疄浣擄紙涓嶅寘鍚伐搴忕被鍒拰鐢靛帇锛�
+ */
+@Data
+public class NonFinishedProductInventoryExportData {
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Excel(name = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+    @Excel(name = "鏂欏彿")
+    private String materialCode;
+
+    // @Excel(name = "鍚堟牸搴撳瓨鎵瑰彿")
+    private String qualifiedBatchNo;
+
+    // @Excel(name = "涓嶅悎鏍煎簱瀛樻壒鍙�")
+    private String unQualifiedBatchNo;
+
+    @Excel(name = "鍚堟牸搴撳瓨鏁伴噺")
+    private BigDecimal qualifiedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎簱瀛樻暟閲�")
+    private BigDecimal unQualifiedQuantity;
+
+    @Excel(name = "棰勮鏁伴噺")
+    private BigDecimal warnNum;
+
+    @Excel(name = "鍚堟牸鍐荤粨鏁伴噺")
+    private BigDecimal qualifiedLockedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎喕缁撴暟閲�")
+    private BigDecimal unQualifiedLockedQuantity;
+
+    @Excel(name = "澶囨敞")
+    private String remark;
+}
diff --git a/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java b/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
index 128d708..771f52b 100644
--- a/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
+++ b/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
@@ -10,25 +10,25 @@
     @Excel(name = "浜у搧鍚嶇О")
     private String productName;
 
-    @Excel(name = "鍨嬪彿")
+    @Excel(name = "瑙勬牸鍨嬪彿")
     private String model;
 
     @Excel(name = "鍗曚綅")
     private String unit;
 
-    @Excel(name = "鐗╂枡缂栫爜")
+    @Excel(name = "鏂欏彿")
     private String materialCode;
 
-    @Excel(name = "鎴愬搧绫诲埆")
+    @Excel(name = "宸ュ簭绫诲埆")
     private String processCategory;
 
     @Excel(name = "鐢靛帇")
     private String voltage;
 
-    @Excel(name = "鍚堟牸搴撳瓨鎵瑰彿")
+    // @Excel(name = "鍚堟牸搴撳瓨鎵瑰彿")
     private String qualifiedBatchNo;
 
-    @Excel(name = "涓嶅悎鏍煎簱瀛樻壒鍙�")
+    // @Excel(name = "涓嶅悎鏍煎簱瀛樻壒鍙�")
     private String unQualifiedBatchNo;
 
     @Excel(name = "鍚堟牸搴撳瓨鏁伴噺")
diff --git a/src/main/java/com/ruoyi/stock/execl/StockOutRecordExportData.java b/src/main/java/com/ruoyi/stock/execl/StockOutRecordExportData.java
index e70fc96..28334e6 100644
--- a/src/main/java/com/ruoyi/stock/execl/StockOutRecordExportData.java
+++ b/src/main/java/com/ruoyi/stock/execl/StockOutRecordExportData.java
@@ -30,4 +30,7 @@
 
     @Excel(isExport = false)
     private String type;
+
+    @Excel(isExport = false)
+    private String processName;
 }
diff --git a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
index 29e85d9..d668368 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.stock.dto.FinishedProductTreeDto;
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.execl.StockInventoryExportData;
@@ -54,4 +55,6 @@
     List<StockInventoryDto> selectProductList();
 
     List<StockInventoryDto> selectFinishedProductInventoryList(@Param("ew") StockInventoryDto stockInventoryDto);
+
+    List<FinishedProductTreeDto> selectFinishedProductList(@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 ddf851c..5fb5f8a 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
@@ -35,9 +35,9 @@
 
     Boolean subtractStockInventory(StockInventoryDto stockInventoryDto);
 
-    R importStockInventory(MultipartFile file);
+    R importStockInventory(MultipartFile file, Integer productType);
 
-    void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto);
+    void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto, Integer productType);
 
     IPage<StockInRecordDto> stockInventoryPage(StockInventoryDto stockInventoryDto,Page page);
 
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 5a2681f..bda2907 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -16,17 +16,14 @@
 import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.stock.dto.FinishedProductTreeDto;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-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.dto.*;
+import com.ruoyi.stock.execl.FinishedProductInventoryExportData;
+import com.ruoyi.stock.execl.NonFinishedProductInventoryExportData;
 import com.ruoyi.stock.execl.StockInventoryExportData;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
 import com.ruoyi.stock.pojo.StockInRecord;
@@ -45,12 +42,7 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -79,40 +71,40 @@
         return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
     }
 
-    /**
-     * 鏌ヨ鎴愬搧搴撳瓨鏍戙��
-     * 杩斿洖缁撴瀯娌跨敤鍩虹璧勬枡浜у搧鏍戯紝鍙跺瓙鑺傜偣琛ュ厖鎴愬搧搴撳瓨缁村害锛氬瀷鍙枫�佸伐搴忓垎绫汇�佺數鍘嬨��
-     */
     @Override
     public List<FinishedProductTreeDto> finishedProductList(StockInventoryDto stockInventoryDto) {
-        List<StockInventoryDto> inventoryList = stockInventoryMapper.selectFinishedProductInventoryList(stockInventoryDto);
-        if (inventoryList.isEmpty()) {
+        // 鏌ヨ搴撳瓨鏁版嵁
+        List<FinishedProductTreeDto> dataList = stockInventoryMapper.selectFinishedProductList(stockInventoryDto);
+        if (dataList.isEmpty()) {
             return new ArrayList<>();
         }
 
-        List<Product> allProducts = productMapper.selectList(null);
-        Map<Long, Product> productMap = new HashMap<>();
-        Map<Long, List<Product>> childrenMap = new HashMap<>();
-        for (Product product : allProducts) {
-            productMap.put(product.getId(), product);
-            childrenMap.computeIfAbsent(product.getParentId(), key -> new ArrayList<>()).add(product);
+        // 鎸変骇鍝両D鍒嗙粍锛屾瀯寤烘爲褰㈢粨鏋�
+        Map<Long, FinishedProductTreeDto> productMap = new LinkedHashMap<>();
+        for (FinishedProductTreeDto data : dataList) {
+            Long productId = data.getProductId();
+            if (!productMap.containsKey(productId)) {
+                // 鍒涘缓浜у搧澶х被鑺傜偣
+                FinishedProductTreeDto productNode = new FinishedProductTreeDto();
+                productNode.setProductId(productId);
+                productNode.setProductName(data.getProductName());
+                productNode.setLabel(data.getLabel());
+                productNode.setChildren(new ArrayList<>());
+                productMap.put(productId, productNode);
+            }
+            // 娣诲姞搴撳瓨鍙跺瓙鑺傜偣
+            FinishedProductTreeDto leafNode = new FinishedProductTreeDto();
+            leafNode.setStockId(data.getStockId());
+            leafNode.setProductModelId(data.getProductModelId());
+            leafNode.setModel(data.getModel());
+            leafNode.setProcessCategory(data.getProcessCategory());
+            leafNode.setVoltage(data.getVoltage());
+            leafNode.setMaterialCode(data.getMaterialCode());
+            leafNode.setUnit(data.getUnit());
+            productMap.get(productId).getChildren().add(leafNode);
         }
 
-        Map<Long, List<FinishedProductTreeDto>> leafMap = buildFinishedProductLeafMap(inventoryList);
-        Set<Long> visibleProductIds = collectVisibleProductIds(leafMap.keySet(), productMap);
-
-        List<FinishedProductTreeDto> result = new ArrayList<>();
-        for (Product rootProduct : allProducts) {
-            if (!isFinishedRoot(rootProduct)) {
-                continue;
-            }
-            FinishedProductTreeDto rootNode = buildProductNode(rootProduct);
-            rootNode.setChildren(buildFinishedChildren(rootProduct.getId(), childrenMap, leafMap, visibleProductIds));
-            if (!rootNode.getChildren().isEmpty()) {
-                result.add(rootNode);
-            }
-        }
-        return result;
+        return new ArrayList<>(productMap.values());
     }
 
     @Override
@@ -279,6 +271,25 @@
         stockOutRecordDto.setType("0");
         stockOutRecordService.add(stockOutRecordDto);
 
+        //閿�鍞嚭搴撴寜鐓т繚瀛樼殑搴撳瓨id
+        if (stockInventoryDto.getStockId() != null) {
+            StockInventory stockInventory = stockInventoryMapper.selectById(stockInventoryDto.getStockId());
+            if (ObjectUtils.isEmpty(stockInventory)) {
+                throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
+            }
+            BigDecimal lockedQty = defaultDecimal(stockInventory.getLockedQuantity());
+            if (stockInventoryDto.getQualitity().compareTo(defaultDecimal(stockInventory.getQualitity()).subtract(lockedQty)) > 0) {
+                ProductModel productModel = productModelMapper.selectById(stockInventoryDto.getProductModelId());
+                Product product = productMapper.selectById(productModel.getProductId());
+                throw new RuntimeException(product.getProductName() + "/" + productModel.getModel() + "搴撳瓨涓嶈冻锛屾棤娉曞嚭搴�");
+            }
+            stockInventory.setQualitity(defaultDecimal(stockInventory.getQualitity()).subtract(stockInventoryDto.getQualitity()));
+            stockInventory.setVersion(stockInventory.getVersion() == null ? 1 : stockInventory.getVersion() + 1);
+            stockInventory.setUpdateTime(LocalDateTime.now());
+            stockInventoryMapper.updateById(stockInventory);
+            return true;
+        }
+
         if (StringUtils.isBlank(stockInventoryDto.getBatchNo()) && !usesDimensionIdentity(normalizeDimension(stockInventoryDto.getProcessCategory()), normalizeDimension(stockInventoryDto.getVoltage()))) {
             List<StockInventory> stockInventories = stockInventoryMapper.selectList(new QueryWrapper<StockInventory>().lambda()
                     .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
@@ -335,7 +346,7 @@
     }
 
     @Override
-    public R importStockInventory(MultipartFile file) {
+    public R importStockInventory(MultipartFile file, Integer productType) {
         try {
             List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectProduct();
             Map<String, SalesLedgerProduct> productMap = new HashMap<>();
@@ -344,65 +355,129 @@
                 productMap.put(key, product);
             }
 
-            ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
-            List<StockInventoryExportData> list = util.importExcel(file.getInputStream());
             List<String> unmatchedRecords = new ArrayList<>();
             int successCount = 0;
 
-            for (StockInventoryExportData dto : list) {
-                String key = dto.getProductName() + "|" + dto.getModel();
-                SalesLedgerProduct matchedProduct = productMap.get(key);
+            // productType: 1=鎴愬搧, 0=闈炴垚鍝�
+            if (productType == 1) {
+                // 鎴愬搧瀵煎叆锛堝寘鍚伐搴忕被鍒拰鐢靛帇锛�
+                ExcelUtil<FinishedProductInventoryExportData> util = new ExcelUtil<>(FinishedProductInventoryExportData.class);
+                List<FinishedProductInventoryExportData> list = util.importExcel(file.getInputStream());
 
-                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.getQualifiedQuantity());
-                        stockInventoryDto.setRemark(dto.getRemark());
-                        stockInventoryDto.setWarnNum(dto.getWarnNum());
-                        stockInventoryDto.setBatchNo(dto.getQualifiedBatchNo());
-                        stockInventoryDto.setProcessCategory(dto.getProcessCategory());
-                        stockInventoryDto.setVoltage(dto.getVoltage());
+                for (FinishedProductInventoryExportData dto : list) {
+                    String key = dto.getProductName() + "|" + dto.getModel();
+                    SalesLedgerProduct matchedProduct = productMap.get(key);
 
-                        if (ObjectUtils.isNotEmpty(dto.getQualifiedLockedQuantity())) {
-                            if (dto.getQualifiedLockedQuantity().compareTo(dto.getQualifiedQuantity()) > 0) {
-                                throw new RuntimeException("鍚堟牸鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫悎鏍煎簱瀛樻暟閲�");
+                    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.getQualifiedQuantity());
+                            stockInventoryDto.setRemark(dto.getRemark());
+                            stockInventoryDto.setWarnNum(dto.getWarnNum());
+                            stockInventoryDto.setBatchNo(dto.getQualifiedBatchNo());
+                            stockInventoryDto.setProcessCategory(dto.getProcessCategory());
+                            stockInventoryDto.setVoltage(dto.getVoltage());
+
+                            if (ObjectUtils.isNotEmpty(dto.getQualifiedLockedQuantity())) {
+                                if (dto.getQualifiedLockedQuantity().compareTo(dto.getQualifiedQuantity()) > 0) {
+                                    throw new RuntimeException("鍚堟牸鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫悎鏍煎簱瀛樻暟閲�");
+                                }
+                                stockInventoryDto.setLockedQuantity(dto.getQualifiedLockedQuantity());
+                            } else {
+                                stockInventoryDto.setLockedQuantity(BigDecimal.ZERO);
                             }
-                            stockInventoryDto.setLockedQuantity(dto.getQualifiedLockedQuantity());
-                        } else {
-                            stockInventoryDto.setLockedQuantity(BigDecimal.ZERO);
+
+                            stockInventoryDto.setProductModelId(matchedProduct.getProductModelId());
+                            this.addstockInventory(stockInventoryDto);
+                            successCount++;
                         }
 
-                        stockInventoryDto.setProductModelId(matchedProduct.getProductModelId());
-                        this.addstockInventory(stockInventoryDto);
-                        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());
+                            stockUninventoryDto.setBatchNo(dto.getUnQualifiedBatchNo());
 
-                    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());
-                        stockUninventoryDto.setBatchNo(dto.getUnQualifiedBatchNo());
-
-                        if (ObjectUtils.isNotEmpty(dto.getUnQualifiedLockedQuantity())) {
-                            if (dto.getUnQualifiedLockedQuantity().compareTo(dto.getUnQualifiedQuantity()) > 0) {
-                                throw new RuntimeException("涓嶅悎鏍煎喕缁撴暟閲忎笉鑳借秴杩囨湰娆″鍏ョ殑涓嶅悎鏍煎簱瀛樻暟閲�");
+                            if (ObjectUtils.isNotEmpty(dto.getUnQualifiedLockedQuantity())) {
+                                if (dto.getUnQualifiedLockedQuantity().compareTo(dto.getUnQualifiedQuantity()) > 0) {
+                                    throw new RuntimeException("涓嶅悎鏍煎喕缁撴暟閲忎笉鑳借秴杩囨湰娆″鍏ョ殑涓嶅悎鏍煎簱瀛樻暟閲�");
+                                }
+                                stockUninventoryDto.setLockedQuantity(dto.getUnQualifiedLockedQuantity());
+                            } else {
+                                stockUninventoryDto.setLockedQuantity(BigDecimal.ZERO);
                             }
-                            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);
+                    }
+                }
+            } else {
+                // 闈炴垚鍝佸鍏ワ紙涓嶅寘鍚伐搴忕被鍒拰鐢靛帇锛�
+                ExcelUtil<NonFinishedProductInventoryExportData> util = new ExcelUtil<>(NonFinishedProductInventoryExportData.class);
+                List<NonFinishedProductInventoryExportData> list = util.importExcel(file.getInputStream());
+
+                for (NonFinishedProductInventoryExportData 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.getQualifiedQuantity());
+                            stockInventoryDto.setRemark(dto.getRemark());
+                            stockInventoryDto.setWarnNum(dto.getWarnNum());
+                            stockInventoryDto.setBatchNo(dto.getQualifiedBatchNo());
+
+                            if (ObjectUtils.isNotEmpty(dto.getQualifiedLockedQuantity())) {
+                                if (dto.getQualifiedLockedQuantity().compareTo(dto.getQualifiedQuantity()) > 0) {
+                                    throw new RuntimeException("鍚堟牸鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫悎鏍煎簱瀛樻暟閲�");
+                                }
+                                stockInventoryDto.setLockedQuantity(dto.getQualifiedLockedQuantity());
+                            } else {
+                                stockInventoryDto.setLockedQuantity(BigDecimal.ZERO);
+                            }
+
+                            stockInventoryDto.setProductModelId(matchedProduct.getProductModelId());
+                            this.addstockInventory(stockInventoryDto);
+                            successCount++;
                         }
 
-                        stockUninventoryDto.setProductModelId(matchedProduct.getProductModelId());
-                        stockUninventoryService.addStockUninventory(stockUninventoryDto);
-                        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());
+                            stockUninventoryDto.setBatchNo(dto.getUnQualifiedBatchNo());
+
+                            if (ObjectUtils.isNotEmpty(dto.getUnQualifiedLockedQuantity())) {
+                                if (dto.getUnQualifiedLockedQuantity().compareTo(dto.getUnQualifiedQuantity()) > 0) {
+                                    throw new RuntimeException("涓嶅悎鏍煎喕缁撴暟閲忎笉鑳借秴杩囨湰娆″鍏ョ殑涓嶅悎鏍煎簱瀛樻暟閲�");
+                                }
+                                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);
                     }
-                } else {
-                    String unmatchedRecord = "浜у搧鍚嶇О锛�" + dto.getProductName() + "锛屽瀷鍙凤細" + dto.getModel() + " 鏈尮閰嶅埌搴撳瓨浜у搧";
-                    unmatchedRecords.add(unmatchedRecord);
                 }
             }
 
@@ -423,10 +498,55 @@
     }
 
     @Override
-    public void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto) {
+    public void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto, Integer productType) {
         List<StockInventoryExportData> list = stockInventoryMapper.listStockInventoryExportData(stockInventoryDto);
-        ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class);
-        util.exportExcel(response, list, "搴撳瓨淇℃伅");
+
+        // productType: 1=鎴愬搧, 0=闈炴垚鍝�
+        if (productType == 1) {
+            // 鎴愬搧瀵煎嚭锛堝寘鍚伐搴忕被鍒拰鐢靛帇锛�
+            List<FinishedProductInventoryExportData> finishedList = new ArrayList<>();
+            for (StockInventoryExportData data : list) {
+                FinishedProductInventoryExportData finishedData = new FinishedProductInventoryExportData();
+                finishedData.setProductName(data.getProductName());
+                finishedData.setModel(data.getModel());
+                finishedData.setUnit(data.getUnit());
+                finishedData.setMaterialCode(data.getMaterialCode());
+                finishedData.setProcessCategory(data.getProcessCategory());
+                finishedData.setVoltage(data.getVoltage());
+                finishedData.setQualifiedBatchNo(data.getQualifiedBatchNo());
+                finishedData.setUnQualifiedBatchNo(data.getUnQualifiedBatchNo());
+                finishedData.setQualifiedQuantity(data.getQualifiedQuantity());
+                finishedData.setUnQualifiedQuantity(data.getUnQualifiedQuantity());
+                finishedData.setWarnNum(data.getWarnNum());
+                finishedData.setQualifiedLockedQuantity(data.getQualifiedLockedQuantity());
+                finishedData.setUnQualifiedLockedQuantity(data.getUnQualifiedLockedQuantity());
+                finishedData.setRemark(data.getRemark());
+                finishedList.add(finishedData);
+            }
+            ExcelUtil<FinishedProductInventoryExportData> util = new ExcelUtil<>(FinishedProductInventoryExportData.class);
+            util.exportExcel(response, finishedList, "鎴愬搧搴撳瓨淇℃伅");
+        } else {
+            // 闈炴垚鍝佸鍑猴紙涓嶅寘鍚伐搴忕被鍒拰鐢靛帇锛�
+            List<NonFinishedProductInventoryExportData> nonFinishedList = new ArrayList<>();
+            for (StockInventoryExportData data : list) {
+                NonFinishedProductInventoryExportData nonFinishedData = new NonFinishedProductInventoryExportData();
+                nonFinishedData.setProductName(data.getProductName());
+                nonFinishedData.setModel(data.getModel());
+                nonFinishedData.setUnit(data.getUnit());
+                nonFinishedData.setMaterialCode(data.getMaterialCode());
+                nonFinishedData.setQualifiedBatchNo(data.getQualifiedBatchNo());
+                nonFinishedData.setUnQualifiedBatchNo(data.getUnQualifiedBatchNo());
+                nonFinishedData.setQualifiedQuantity(data.getQualifiedQuantity());
+                nonFinishedData.setUnQualifiedQuantity(data.getUnQualifiedQuantity());
+                nonFinishedData.setWarnNum(data.getWarnNum());
+                nonFinishedData.setQualifiedLockedQuantity(data.getQualifiedLockedQuantity());
+                nonFinishedData.setUnQualifiedLockedQuantity(data.getUnQualifiedLockedQuantity());
+                nonFinishedData.setRemark(data.getRemark());
+                nonFinishedList.add(nonFinishedData);
+            }
+            ExcelUtil<NonFinishedProductInventoryExportData> util = new ExcelUtil<>(NonFinishedProductInventoryExportData.class);
+            util.exportExcel(response, nonFinishedList, "闈炴垚鍝佸簱瀛樹俊鎭�");
+        }
     }
 
     @Override
@@ -505,89 +625,5 @@
 
     private BigDecimal defaultDecimal(BigDecimal value) {
         return value == null ? BigDecimal.ZERO : value;
-    }
-
-    private Map<Long, List<FinishedProductTreeDto>> buildFinishedProductLeafMap(List<StockInventoryDto> inventoryList) {
-        Map<Long, List<FinishedProductTreeDto>> leafMap = new HashMap<>();
-        for (StockInventoryDto inventory : inventoryList) {
-            FinishedProductTreeDto leafNode = new FinishedProductTreeDto();
-            leafNode.setId(inventory.getId() == null ? null : -inventory.getId());
-            leafNode.setParentId(inventory.getProductId());
-            leafNode.setProductId(inventory.getProductId());
-            leafNode.setProductModelId(inventory.getProductModelId());
-            leafNode.setProductName(inventory.getProductName());
-            leafNode.setLabel(buildLeafLabel(inventory));
-            leafNode.setModel(inventory.getModel());
-            leafNode.setMaterialCode(inventory.getMaterialCode());
-            leafNode.setProcessCategory(inventory.getProcessCategory());
-            leafNode.setVoltage(inventory.getVoltage());
-            leafNode.setChildren(new ArrayList<>());
-            leafMap.computeIfAbsent(inventory.getProductId(), key -> new ArrayList<>()).add(leafNode);
-        }
-        return leafMap;
-    }
-
-    private Set<Long> collectVisibleProductIds(Set<Long> leafProductIds, Map<Long, Product> productMap) {
-        Set<Long> visibleIds = new HashSet<>();
-        for (Long productId : leafProductIds) {
-            Long currentId = productId;
-            while (currentId != null) {
-                Product current = productMap.get(currentId);
-                if (current == null) {
-                    break;
-                }
-                visibleIds.add(currentId);
-                currentId = current.getParentId();
-            }
-        }
-        return visibleIds;
-    }
-
-    private List<FinishedProductTreeDto> buildFinishedChildren(Long parentId,
-                                                               Map<Long, List<Product>> childrenMap,
-                                                               Map<Long, List<FinishedProductTreeDto>> leafMap,
-                                                               Set<Long> visibleProductIds) {
-        List<FinishedProductTreeDto> children = new ArrayList<>();
-        List<Product> childProducts = childrenMap.getOrDefault(parentId, new ArrayList<>());
-        for (Product childProduct : childProducts) {
-            if (!visibleProductIds.contains(childProduct.getId())) {
-                continue;
-            }
-            FinishedProductTreeDto childNode = buildProductNode(childProduct);
-            List<FinishedProductTreeDto> subChildren = buildFinishedChildren(childProduct.getId(), childrenMap, leafMap, visibleProductIds);
-            subChildren.addAll(leafMap.getOrDefault(childProduct.getId(), new ArrayList<>()));
-            childNode.setChildren(subChildren);
-            children.add(childNode);
-        }
-        return children;
-    }
-
-    private FinishedProductTreeDto buildProductNode(Product product) {
-        FinishedProductTreeDto node = new FinishedProductTreeDto();
-        BeanUtils.copyProperties(product, node);
-        node.setLabel(product.getProductName());
-        node.setChildren(new ArrayList<>());
-        return node;
-    }
-
-    private boolean isFinishedRoot(Product product) {
-        return product.getParentId() == null && "鎴愬搧".equals(StringUtils.trimToEmpty(product.getProductName()));
-    }
-
-    private String buildLeafLabel(StockInventoryDto inventory) {
-        List<String> parts = new ArrayList<>();
-        if (StringUtils.isNotBlank(inventory.getProductName())) {
-            parts.add(StringUtils.trim(inventory.getProductName()));
-        }
-        if (StringUtils.isNotBlank(inventory.getModel())) {
-            parts.add(StringUtils.trim(inventory.getModel()));
-        }
-        if (StringUtils.isNotBlank(inventory.getProcessCategory())) {
-            parts.add(StringUtils.trim(inventory.getProcessCategory()));
-        }
-        if (StringUtils.isNotBlank(inventory.getVoltage())) {
-            parts.add(StringUtils.trim(inventory.getVoltage()));
-        }
-        return String.join(" / ", parts);
     }
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
index cb8c395..08be3ba 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
@@ -10,6 +10,7 @@
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.EnumUtil;
 import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.stock.dto.StockInventoryDto;
@@ -49,7 +50,11 @@
 
     @Override
     public IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto) {
-        return stockOutRecordMapper.listPage(page, stockOutRecordDto);
+        IPage<StockOutRecordDto> result = stockOutRecordMapper.listPage(page, stockOutRecordDto);
+        for (StockOutRecordDto record : result.getRecords()) {
+            record.setRecordTypeName(resolveRecordTypeName(record.getType(), record.getRecordType(), record.getProcessName()));
+        }
+        return result;
     }
 
     @Override
@@ -131,7 +136,7 @@
         List<StockOutRecordExportData> list = stockOutRecordMapper.listStockOutRecordExportData(stockOutRecordDto);
         for (StockOutRecordExportData stockInRecordExportData : list) {
             if (stockInRecordExportData.getType().equals("0")) {
-                stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
+                stockInRecordExportData.setRecordType(resolveQualifiedRecordType(stockInRecordExportData.getRecordType(), stockInRecordExportData.getProcessName()));
             }else {
                 stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutUnQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue());
             }
@@ -139,4 +144,26 @@
         ExcelUtil<StockOutRecordExportData> util = new ExcelUtil<>(StockOutRecordExportData.class);
         util.exportExcel(response,list, "鍑哄簱璁板綍淇℃伅");
     }
-}
\ No newline at end of file
+
+    private String resolveRecordTypeName(String type, String recordType, String processName) {
+        if ("0".equals(type)) {
+            return resolveQualifiedRecordType(recordType, processName);
+        }
+        return EnumUtil.fromCode(StockOutUnQualifiedRecordTypeEnum.class, Integer.parseInt(recordType)).getValue();
+    }
+
+    private String resolveQualifiedRecordType(String recordType, String processName) {
+        if (StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode().equals(recordType)
+                && StringUtils.isNotEmpty(processName)) {
+            return "鐢熶骇鎶ュ伐-" + processName + "-鍑哄簱";
+        }
+        if (recordType == null) {
+            return null;
+        }
+        try {
+            return EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(recordType)).getValue();
+        } catch (NumberFormatException ex) {
+            return recordType;
+        }
+    }
+}
diff --git a/src/main/resources/mapper/approve/ApproveProcessMapper.xml b/src/main/resources/mapper/approve/ApproveProcessMapper.xml
index 33b29a9..ca02119 100644
--- a/src/main/resources/mapper/approve/ApproveProcessMapper.xml
+++ b/src/main/resources/mapper/approve/ApproveProcessMapper.xml
@@ -38,5 +38,6 @@
         <if test="req.approveType != null ">
             and approve_type = #{req.approveType}
         </if>
+        order by approve_time desc
     </select>
 </mapper>
diff --git a/src/main/resources/mapper/production/ProductBomMapper.xml b/src/main/resources/mapper/production/ProductBomMapper.xml
index 4ac2125..7ce0192 100644
--- a/src/main/resources/mapper/production/ProductBomMapper.xml
+++ b/src/main/resources/mapper/production/ProductBomMapper.xml
@@ -36,6 +36,7 @@
         <if test="c.version != null">
             and version = #{c.version}
         </if>
+        order by create_time desc
     </select>
     <select id="getById" resultType="com.ruoyi.production.dto.ProductBomDto">
         select pb.*,
diff --git a/src/main/resources/mapper/sales/SalesLedgerMapper.xml b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
index fe36cdc..243b400 100644
--- a/src/main/resources/mapper/sales/SalesLedgerMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -69,7 +69,7 @@
         T1.delivery_date,
         DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff,
         product_summary.model,
-        '' AS voltage,
+        product_summary.voltage,
         product_summary.qty,
         CASE
         WHEN shipping_status_counts.total_count = 0 THEN false
@@ -90,7 +90,8 @@
         SELECT
         sales_ledger_id,
         GROUP_CONCAT(IFNULL(specification_model, '') ORDER BY id SEPARATOR ',') AS model,
-        GROUP_CONCAT(IFNULL(CAST(quantity AS CHAR), '') ORDER BY id SEPARATOR ',') AS qty
+        GROUP_CONCAT(IFNULL(CAST(quantity AS CHAR), '') ORDER BY id SEPARATOR ',') AS qty,
+        GROUP_CONCAT(IFNULL(SUBSTRING_INDEX(specification_model, '-', -1), '') ORDER BY id SEPARATOR ',') AS voltage
         FROM sales_ledger_product
         WHERE type = 1
         GROUP BY sales_ledger_id
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 7f11d07..5d1232c 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -14,10 +14,9 @@
         END as has_sufficient_stock
         FROM
         sales_ledger_product T1
-        LEFT JOIN (
-        select product_model_id,SUM(qualitity) as qualitity,sum(locked_quantity) as locked_quantity from stock_inventory
-        group by product_model_id
-        )  t2 ON T1.product_model_id = t2.product_model_id
+        LEFT JOIN stock_inventory t2
+        ON T1.product_model_id = t2.product_model_id
+        AND t2.id = T1.stock_id
         LEFT JOIN product_model T3 ON T1.product_model_id = T3.id
         <where>
             <if test="salesLedgerProduct.salesLedgerId != null">
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index e23f2fd..72f6e6f 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -90,6 +90,7 @@
         <if test="ew.voltage != null and ew.voltage != ''">
             AND si.voltage = #{ew.voltage}
         </if>
+        order by si.create_time desc
     </select>
 
     <select id="pageListCombinedStockInventory" resultType="com.ruoyi.stock.dto.StockInventoryDto">
@@ -510,4 +511,36 @@
         order by p.id asc, pm.id asc, si.id asc
     </select>
 
+    <select id="selectFinishedProductList" resultType="com.ruoyi.stock.dto.FinishedProductTreeDto">
+        select si.id as stockId,
+               p.id as productId,
+               p.product_name as productName,
+               p.product_name as label,
+               pm.id as productModelId,
+               pm.model,
+               si.process_category as processCategory,
+               si.voltage,
+               pm.material_code as materialCode,
+               pm.unit
+        from stock_inventory si
+        inner join product_model pm on si.product_model_id = pm.id
+        inner join product p on pm.product_id = p.id
+        inner join product pp on p.parent_id = pp.id
+        <where>
+            pp.product_name = '鎴愬搧'
+            <if test="ew.productName != null and ew.productName != ''">
+                and (p.product_name like concat('%', #{ew.productName}, '%')
+                or pm.model like concat('%', #{ew.productName}, '%')
+                or pm.material_code like concat('%', #{ew.productName}, '%'))
+            </if>
+            <if test="ew.processCategory != null and ew.processCategory != ''">
+                and si.process_category = #{ew.processCategory}
+            </if>
+            <if test="ew.voltage != null and ew.voltage != ''">
+                and si.voltage = #{ew.voltage}
+            </if>
+        </where>
+        order by p.id asc, pm.id asc, si.id asc
+    </select>
+
 </mapper>
diff --git a/src/main/resources/mapper/stock/StockOutRecordMapper.xml b/src/main/resources/mapper/stock/StockOutRecordMapper.xml
index 3c21f33..782f525 100644
--- a/src/main/resources/mapper/stock/StockOutRecordMapper.xml
+++ b/src/main/resources/mapper/stock/StockOutRecordMapper.xml
@@ -35,11 +35,15 @@
         pm.model,
         pm.unit,
         pm.material_code as materialCode,
-        u.nick_name as createBy
+        u.nick_name as createBy,
+        pp.name as processName
         FROM stock_out_record as sor
         LEFT JOIN product_model as pm on sor.product_model_id = pm.id
         LEFT JOIN product as p on pm.product_id = p.id
         LEFT JOIN sys_user as u on sor.create_user = u.user_id
+        LEFT JOIN production_product_main as ppm on sor.record_type = '3' and ppm.id = sor.record_id
+        LEFT JOIN product_process_route_item as ppri on ppri.id = ppm.product_process_route_item_id
+        LEFT JOIN product_process as pp on pp.id = ppri.process_id
         <where>
             <if test="params.timeStr != null and params.timeStr != ''">
                 and sor.create_time like concat('%',#{params.timeStr},'%')
@@ -77,11 +81,15 @@
         pm.model,
         pm.unit,
         pm.material_code as materialCode,
-        u.nick_name as createBy
+        u.nick_name as createBy,
+        pp.name as processName
         FROM stock_out_record as sor
         LEFT JOIN product_model as pm on sor.product_model_id = pm.id
         LEFT JOIN product as p on pm.product_id = p.id
         LEFT JOIN sys_user as u on sor.create_user = u.user_id
+        LEFT JOIN production_product_main as ppm on sor.record_type = '3' and ppm.id = sor.record_id
+        LEFT JOIN product_process_route_item as ppri on ppri.id = ppm.product_process_route_item_id
+        LEFT JOIN product_process as pp on pp.id = ppri.process_id
         <where>
             <if test="params.timeStr != null and params.timeStr != ''">
                 and sor.create_time like concat('%',#{params.timeStr},'%')
@@ -102,4 +110,4 @@
         order by sor.id desc
     </select>
 
-</mapper>
\ No newline at end of file
+</mapper>

--
Gitblit v1.9.3