From 4d99e718536ac77dff26dde8da7a59cdc9b52de8 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期三, 20 五月 2026 10:13:57 +0800
Subject: [PATCH] fix:1.生产报工优化

---
 src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java      |   12 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |  578 ++++++++++++++++++++++++++++++++++------------------
 src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedMapper.java                  |   16 
 src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml                        |   25 +
 src/main/resources/mapper/production/ProductionProductMainMapper.xml                  |   13 
 src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java                        |    2 
 src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java            |   13 
 7 files changed, 420 insertions(+), 239 deletions(-)

diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
index f4be202..b1c41ac 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
@@ -19,14 +19,12 @@
     IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, @Param("c") ProductionProductMainDto productionProductMainDto);
 
     /**
-     * 鏍规嵁宸ュ崟ID鎵归噺鍒犻櫎鐢熶骇涓昏〃鏁版嵁
+     * 鏍规嵁宸ュ崟 ID 鎵归噺鍒犻櫎鎶ュ伐涓昏〃鏁版嵁銆�
      */
     int deleteByWorkOrderIds(@Param("workOrderIds") List<Long> workOrderIds);
 
     /**
-     * 鏍规嵁鎶ュ伐id鏌ヨ鐢熶骇璁㈠崟
-     * @param productMainId
-     * @return
+     * 鏍规嵁鎶ュ伐 ID 鏌ヨ鐢熶骇璁㈠崟銆�
      */
     ProductOrder getOrderByMainId(@Param("productMainId") Long productMainId);
 
@@ -37,10 +35,7 @@
     List<ProductionProductMainDto> getByProductWorkOrderId(Long productWorkOrderId);
 
     /**
-     * 妫�鏌ヤ箣鍓嶇殑宸ュ簭鏄惁鏈夎闅旂鐨勪笉鍚堟牸璁板綍
-     * @param productRouteId 褰撳墠宸ュ簭鐨勮矾鐢盜D
-     * @param currentDragSort 褰撳墠宸ュ簭鐨勬帓搴�
-     * @return 鏄惁鏈夐殧绂荤殑涓嶅悎鏍艰褰�
+     * 鏍¢獙鍚屼竴鐢熶骇璁㈠崟涓嬬殑涓婁竴閬撳伐搴忔槸鍚﹀凡缁忔姤宸ャ��
      */
-    boolean checkPreviousProcessReported(@Param("productRouteId") Long productRouteId, @Param("currentDragSort") Integer currentDragSort);
+    boolean checkPreviousProcessReported(@Param("workOrderId") Long workOrderId, @Param("currentDragSort") Integer currentDragSort);
 }
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 913280a..982009f 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
@@ -69,7 +69,7 @@
             } else {
                 // 涓婁竴涓伐搴忔槸鍚﹀凡鎶ュ伐
                 boolean isPreviousReported = productionProductMainMapper.checkPreviousProcessReported(
-                        record.getProductRouteId(),
+                        record.getId(),
                         currentDragSort
                 );
                 record.setIsCanReport(isPreviousReported);
@@ -94,7 +94,13 @@
                         }
 
                         // 妫�鏌ヤ箣鍓嶇殑宸ュ簭鏄惁鏈夎闅旂鐨勪笉鍚堟牸璁板綍
-                        List<QualityUnqualified> unqualifiedList = qualityUnqualifiedMapper.selectUnqualifiedByProcessNames(previousProcessNames);
+                        List<QualityUnqualified> unqualifiedList = Collections.emptyList();
+                        if (CollectionUtils.isNotEmpty(previousProcessNames)) {
+                            unqualifiedList = qualityUnqualifiedMapper.selectUnqualifiedByProductOrderAndProcessNames(
+                                    record.getProductOrderId(),
+                                    previousProcessNames
+                            );
+                        }
                         if (CollectionUtils.isNotEmpty(unqualifiedList)) {
                             record.setIsCanReport(false);
                         }
@@ -231,4 +237,4 @@
         }
         return productWorkOrderDtos;
     }
-}
\ No newline at end of file
+}
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 c2a22d4..47e7fcd 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -17,6 +17,7 @@
 import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.procurementrecord.utils.StockUtils;
 import com.ruoyi.production.dto.ProductStructureDto;
@@ -52,50 +53,29 @@
     private static final String PROCESS_VOLTAGE_SORT = "鐢靛帇鍒嗛��";
     private static final String PROCESS_OPTICAL_INSPECTION = "鍏夋澶栬";
     private static final String PROCESS_PACKAGING = "鍖呰";
+    private static final Object PRODUCT_MAIN_NO_LOCK = new Object();
 
     private IQualityInspectService qualityInspectService;
     private ProductionProductMainMapper productionProductMainMapper;
-
-
     private ProductWorkOrderMapper productWorkOrderMapper;
-
     private ProductProcessRouteItemMapper productProcessRouteItemMapper;
     private SysUserMapper userMapper;
-
     private ProductionProductOutputMapper productionProductOutputMapper;
-
-
     private ProductModelMapper productModelMapper;
-
     private QualityInspectMapper qualityInspectMapper;
     private QualityUnqualifiedMapper qualityUnqualifiedMapper;
-
     private ProductProcessMapper productProcessMapper;
     private ProductProcessRouteMapper productProcessRouteMapper;
-
     private ProductMapper productMapper;
-
-
     private QualityTestStandardParamMapper qualityTestStandardParamMapper;
     private QualityTestStandardMapper qualityTestStandardMapper;
-
     private QualityInspectParamMapper qualityInspectParamMapper;
-
     private ProductStructureMapper productStructureMapper;
-
     private ProductionProductInputMapper productionProductInputMapper;
-
     private ProductOrderMapper productOrderMapper;
-
     private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-
     private StockUtils stockUtils;
-
-    /**
-     * 瑙f瀽鐢熶骇鎶ュ伐瀵瑰簲鐨勬垚鍝佸叆搴撶淮搴︺��
-     */
     private FinishedProductStockDimensionResolver finishedProductStockDimensionResolver;
-
     private ISysNoticeService sysNoticeService;
 
     @Override
@@ -103,124 +83,246 @@
         return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
     }
 
-    /**
-     * 鏂板鎶ュ伐锛屽苟鏍规嵁褰撳墠宸ュ簭澶勭悊璐ㄦ鍜屽叆搴撻�昏緫銆�
-     */
+    // 鏂板鎶ュ伐锛屽苟鎸夌収鎶ュ伐涓绘祦绋嬪鐞嗘姇鍏ユ墸搴撱�佷骇鍑恒�佽川妫�銆佸叆搴撱�佸伐鍗曡鍗曡繘搴﹀拰鏍哥畻鏁版嵁
     @Override
     public Boolean addProductMain(ProductionProductMainDto dto) {
-        SysUser user = userMapper.selectUserById(dto.getUserId());
-        ProductionProductMain productionProductMain = new ProductionProductMain();
-        //褰撳墠宸ヨ壓璺嚎瀵瑰簲鐨勫伐搴忚鎯�
-        ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(dto.getProductProcessRouteItemId());
-        if (productProcessRouteItem == null) {
-            throw new RuntimeException("宸ヨ壓璺嚎宸ュ簭椤逛笉瀛樺湪");
+        // 绗竴姝ワ細鍏堟牎楠屾姤宸ュ叆鍙傦紝閬垮厤绌哄�煎拰闈炴硶鏁伴噺杩涘叆鍚庣画娴佺▼
+        if (dto == null) {
+            throw new ServiceException("鎶ュ伐鍙傛暟涓嶈兘涓虹┖");
         }
-        //妫�鏌ヤ笂涓�涓伐搴忔槸鍚﹀凡鎶ュ伐
+        if (dto.getProductProcessRouteItemId() == null) {
+            throw new ServiceException("宸ヨ壓璺嚎宸ュ簭椤逛笉鑳戒负绌�");
+        }
+        if (dto.getWorkOrderId() == null) {
+            throw new ServiceException("鐢熶骇宸ュ崟涓嶈兘涓虹┖");
+        }
+
+        BigDecimal reportQty = dto.getQuantity();
+        BigDecimal scrapQty = dto.getScrapQty() == null ? BigDecimal.ZERO : dto.getScrapQty();
+        if (reportQty == null || reportQty.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("鎶ュ伐鏁伴噺蹇呴』澶т簬0");
+        }
+        if (scrapQty.compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("鎶ュ簾鏁伴噺涓嶈兘灏忎簬0");
+        }
+        if (scrapQty.compareTo(reportQty) > 0) {
+            throw new ServiceException("鎶ュ簾鏁伴噺涓嶈兘澶т簬鎶ュ伐鏁伴噺");
+        }
+
+        // 绗簩姝ワ細鍔犺浇褰撳墠宸ュ簭銆佸伐鍗曘�佸伐鑹鸿矾绾垮拰璁㈠崟鏁版嵁锛屽苟鏍¢獙鍩虹鍏宠仈鍏崇郴
+        ProductProcessRouteItem productProcessRouteItem =
+                productProcessRouteItemMapper.selectById(dto.getProductProcessRouteItemId());
+        if (productProcessRouteItem == null) {
+            throw new ServiceException("宸ヨ壓璺嚎宸ュ簭椤逛笉瀛樺湪");
+        }
+
+        ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId());
+        if (productProcess == null) {
+            throw new ServiceException("褰撳墠宸ュ簭涓嶅瓨鍦�");
+        }
+
+        ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId());
+        if (productModel == null) {
+            throw new ServiceException("褰撳墠宸ュ簭瀵瑰簲鐨勪骇鍝佸瀷鍙蜂笉瀛樺湪");
+        }
+
+        ProductProcessRoute productProcessRoute =
+                productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId());
+        if (productProcessRoute == null) {
+            throw new ServiceException("宸ヨ壓璺嚎涓嶅瓨鍦�");
+        }
+
+        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
+        if (productWorkOrder == null) {
+            throw new ServiceException("鐢熶骇宸ュ崟涓嶅瓨鍦�");
+        }
+        if (!Objects.equals(productWorkOrder.getProductProcessRouteItemId(), productProcessRouteItem.getId())) {
+            throw new ServiceException("鐢熶骇宸ュ崟涓庡綋鍓嶅伐搴忎笉鍖归厤");
+        }
+
+        ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
+        if (productOrder == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+
+        // 绗笁姝ワ細鏍¢獙宸ュ簭娴佽浆閫昏緫锛屽繀椤绘槸鍚屼竴璁㈠崟鐨勪笂涓�閬撳伐搴忓凡鎶ュ伐涓斿墠搴忔棤鏈В闄ら殧绂昏褰�
         Integer currentDragSort = productProcessRouteItem.getDragSort();
         if (currentDragSort != null && currentDragSort > 1) {
             boolean isPreviousReported = productionProductMainMapper.checkPreviousProcessReported(
-                    productProcessRouteItem.getProductRouteId(),
+                    productWorkOrder.getId(),
                     currentDragSort
             );
             if (!isPreviousReported) {
-                throw new RuntimeException("涓婁竴閬撳伐搴忓皻鏈姤宸ワ紝褰撳墠宸ュ簭涓嶈兘鎶ュ伐");
+                throw new ServiceException("涓婁竴閬撳伐搴忓皻鏈姤宸ワ紝褰撳墠宸ュ簭涓嶈兘鎶ュ伐");
             }
 
-            // 鏌ヨ鎵�鏈変箣鍓嶇殑宸ュ簭锛堟帓搴忓彿灏忎簬褰撳墠宸ュ簭锛�
+            ProductProcessRouteItem previousRouteItem = productProcessRouteItemMapper.selectOne(
+                    Wrappers.<ProductProcessRouteItem>lambdaQuery()
+                            .eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())
+                            .eq(ProductProcessRouteItem::getDragSort, currentDragSort - 1)
+            );
+            if (previousRouteItem == null) {
+                throw new ServiceException("涓婁竴閬撳伐搴忎笉瀛樺湪");
+            }
+
+            ProductWorkOrder previousWorkOrder = productWorkOrderMapper.selectOne(
+                    Wrappers.<ProductWorkOrder>lambdaQuery()
+                            .eq(ProductWorkOrder::getProductOrderId, productOrder.getId())
+                            .eq(ProductWorkOrder::getProductProcessRouteItemId, previousRouteItem.getId())
+            );
+            if (previousWorkOrder == null) {
+                throw new ServiceException("涓婁竴閬撳伐搴忓伐鍗曚笉瀛樺湪");
+            }
+
+            BigDecimal currentReportedQty = BigDecimal.ZERO;
+            List<ProductionProductMain> currentMainList = productionProductMainMapper.selectList(
+                    Wrappers.<ProductionProductMain>lambdaQuery()
+                            .eq(ProductionProductMain::getWorkOrderId, productWorkOrder.getId())
+            );
+            if (CollectionUtils.isNotEmpty(currentMainList)) {
+                List<Long> currentMainIds = currentMainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+                List<ProductionProductOutput> currentOutputList = productionProductOutputMapper.selectList(
+                        Wrappers.<ProductionProductOutput>lambdaQuery()
+                                .in(ProductionProductOutput::getProductMainId, currentMainIds)
+                );
+                currentReportedQty = currentOutputList.stream()
+                        .map(ProductionProductOutput::getQuantity)
+                        .filter(Objects::nonNull)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+            }
+
+            BigDecimal previousCompleteQty =
+                    previousWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : previousWorkOrder.getCompleteQuantity();
+            if (currentReportedQty.add(reportQty).compareTo(previousCompleteQty) > 0) {
+                throw new ServiceException("鏈鎶ュ伐鏁伴噺瓒呰繃涓婇亾宸ュ簭鍙祦杞暟閲�");
+            }
+
             List<ProductProcessRouteItem> previousItems = productProcessRouteItemMapper.selectList(
                     Wrappers.<ProductProcessRouteItem>lambdaQuery()
                             .eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())
                             .lt(ProductProcessRouteItem::getDragSort, currentDragSort)
             );
+
             if (CollectionUtils.isNotEmpty(previousItems)) {
-                // 鎻愬彇涔嬪墠宸ュ簭鐨勫悕绉板垪琛�
                 List<String> previousProcessNames = new ArrayList<>();
                 for (ProductProcessRouteItem item : previousItems) {
                     ProductProcess process = productProcessMapper.selectById(item.getProcessId());
-                    if (process != null) {
-                        previousProcessNames.add(process.getName());
+                    if (process != null && StringUtils.isNotBlank(process.getName())) {
+                        previousProcessNames.add(process.getName().trim());
                     }
                 }
 
-                // 妫�鏌ヤ箣鍓嶇殑宸ュ簭鏄惁鏈夎闅旂鐨勪笉鍚堟牸璁板綍
-                List<QualityUnqualified> unqualifiedList = qualityUnqualifiedMapper.selectUnqualifiedByProcessNames(previousProcessNames);
-                if (CollectionUtils.isNotEmpty(unqualifiedList)) {
-                    throw new RuntimeException("鍓嶅簭宸ュ簭瀛樺湪闅旂璁板綍锛屽綋鍓嶅伐搴忎笉鑳芥姤宸�");
+                if (CollectionUtils.isNotEmpty(previousProcessNames)) {
+                    List<QualityUnqualified> unqualifiedList =
+                            qualityUnqualifiedMapper.selectUnqualifiedByProductOrderAndProcessNames(productOrder.getId(), previousProcessNames);
+                    if (CollectionUtils.isNotEmpty(unqualifiedList)) {
+                        throw new ServiceException("鍓嶅簭宸ュ簭瀛樺湪闅旂璁板綍锛屽綋鍓嶅伐搴忎笉鑳芥姤宸�");
+                    }
                 }
             }
         }
-        //褰撳墠鍏蜂綋宸ュ簭
-        ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId());
-        //宸ヨ壓璺嚎涓綋鍓嶅伐搴忓搴旂殑浜у嚭瑙勬牸鍨嬪彿
-        ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId());
-        //鏌ヨ璇ョ敓浜ц鍗曞搴旂殑bom
-        ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId());
-        /*鏂板鎶ュ伐涓昏〃*/
-        //鏌ヨ鏈�澶ф姤宸ョ紪鍙�
-        String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
-        QueryWrapper<ProductionProductMain> queryWrapper = new QueryWrapper<>();
-        queryWrapper.select("MAX(product_no) as maxNo")
-                .likeRight("product_no", datePrefix);
-        List<Map<String, Object>> resultList = productionProductMainMapper.selectMaps(queryWrapper);
-        int sequenceNumber = 1;
-        if (resultList != null && !resultList.isEmpty()) {
-            Map<String, Object> result = resultList.get(0);
-            if (result != null) {
-                Object maxNoObj = result.get("maxNo");
-                if (maxNoObj != null) {
-                    String lastNo = maxNoObj.toString();
+
+        // 绗洓姝ワ細鎺у埗褰撳墠宸ュ崟鎬绘姤宸ラ噺涓嶈兘瓒呰繃璁″垝閲�
+        BigDecimal currentWorkOrderReportedQty = BigDecimal.ZERO;
+        List<ProductionProductMain> workOrderMainList = productionProductMainMapper.selectList(
+                Wrappers.<ProductionProductMain>lambdaQuery()
+                        .eq(ProductionProductMain::getWorkOrderId, productWorkOrder.getId())
+        );
+        if (CollectionUtils.isNotEmpty(workOrderMainList)) {
+            List<Long> workOrderMainIds = workOrderMainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+            List<ProductionProductOutput> workOrderOutputList = productionProductOutputMapper.selectList(
+                    Wrappers.<ProductionProductOutput>lambdaQuery()
+                            .in(ProductionProductOutput::getProductMainId, workOrderMainIds)
+            );
+            currentWorkOrderReportedQty = workOrderOutputList.stream()
+                    .map(ProductionProductOutput::getQuantity)
+                    .filter(Objects::nonNull)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+        }
+        if (productWorkOrder.getPlanQuantity() != null
+                && currentWorkOrderReportedQty.add(reportQty).compareTo(productWorkOrder.getPlanQuantity()) > 0) {
+            throw new ServiceException("鏈鎶ュ伐鏁伴噺瓒呰繃宸ュ崟鍙姤鏁伴噺");
+        }
+
+        // 绗簲姝ワ細鐢熸垚鎶ュ伐鍗曞彿骞剁‘瀹氭姤宸ヤ汉淇℃伅
+        String productNo;
+        synchronized (PRODUCT_MAIN_NO_LOCK) {
+            String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
+            QueryWrapper<ProductionProductMain> queryWrapper = new QueryWrapper<>();
+            queryWrapper.select("MAX(product_no) as maxNo")
+                    .likeRight("product_no", datePrefix);
+            List<Map<String, Object>> resultList = productionProductMainMapper.selectMaps(queryWrapper);
+
+            int sequenceNumber = 1;
+            if (CollectionUtils.isNotEmpty(resultList)) {
+                Map<String, Object> result = resultList.get(0);
+                if (result != null && result.get("maxNo") != null) {
+                    String lastNo = result.get("maxNo").toString();
                     if (lastNo.startsWith(datePrefix)) {
                         try {
-                            String seqStr = lastNo.substring(datePrefix.length());
-                            sequenceNumber = Integer.parseInt(seqStr) + 1;
+                            sequenceNumber = Integer.parseInt(lastNo.substring(datePrefix.length())) + 1;
                         } catch (NumberFormatException e) {
                             sequenceNumber = 1;
                         }
                     }
                 }
             }
+            productNo = String.format("%s%03d", datePrefix, sequenceNumber);
         }
-        String productNo = String.format("%s%03d", datePrefix, sequenceNumber);
-        productionProductMain.setProductNo(productNo);
+
         Long userId = dto.getUserId();
         String userName = dto.getUserName();
         if (userId == null) {
             userId = SecurityUtils.getLoginUser().getUserId();
             userName = SecurityUtils.getLoginUser().getNickName();
+        } else if (StringUtils.isBlank(userName)) {
+            SysUser user = userMapper.selectUserById(userId);
+            userName = user == null ? null : user.getNickName();
         }
+
+        // 绗叚姝ワ細鍏堝啓鎶ュ伐涓昏〃
+        ProductionProductMain productionProductMain = new ProductionProductMain();
+        productionProductMain.setProductNo(productNo);
         productionProductMain.setUserId(userId);
         productionProductMain.setUserName(userName);
         productionProductMain.setProductProcessRouteItemId(dto.getProductProcessRouteItemId());
         productionProductMain.setWorkOrderId(dto.getWorkOrderId());
         productionProductMain.setStatus(0);
         productionProductMainMapper.insert(productionProductMain);
-        /*鏂板鎶ュ伐鎶曞叆琛�*/
-        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId());
-        if (productStructureDtos.isEmpty()) {
-            //濡傛灉璇ュ伐搴忔病鏈変骇鍝佺粨鏋勭殑鎶曞叆鍝�,閭h繖涓姇鍏ュ搧鍜屼骇鍑哄搧鏄悓涓�涓�
+
+        // 绗竷姝ワ細鏍规嵁 BOM 鐢熸垚鎶曞叆璁板綍骞舵墸鍑忓師鏂欏簱瀛�
+        List<ProductStructureDto> productStructureDtos =
+                productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId());
+
+        if (CollectionUtils.isEmpty(productStructureDtos)) {
             ProductStructureDto productStructureDto = new ProductStructureDto();
             productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId());
             productStructureDto.setUnitQuantity(BigDecimal.ONE);
             productStructureDtos.add(productStructureDto);
         }
+
         Set<Long> parentIds = productStructureDtos.stream()
                 .map(ProductStructureDto::getParentId)
                 .filter(Objects::nonNull)
                 .collect(Collectors.toSet());
+
         Map<Long, ProductStructureDto> parentMap = new HashMap<>();
-        if (!parentIds.isEmpty()) {
+        if (CollectionUtils.isNotEmpty(parentIds)) {
             parentMap = productStructureMapper.selectByIds(parentIds)
                     .stream()
-                    .collect(Collectors.toMap(
-                            ProductStructureDto::getId,
-                            Function.identity()
-                    ));
+                    .collect(Collectors.toMap(ProductStructureDto::getId, Function.identity(), (a, b) -> a));
         }
+
         for (ProductStructureDto productStructureDto : productStructureDtos) {
-            ProductionProductInput productionProductInput = new ProductionProductInput();
-            productionProductInput.setProductModelId(productStructureDto.getProductModelId());
-//            productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
+            if (productStructureDto.getProductModelId() == null) {
+                throw new ServiceException("鎶曞叆鐗╂枡浜у搧鍨嬪彿涓嶈兘涓虹┖");
+            }
+
             BigDecimal childQty = productStructureDto.getUnitQuantity();
+            if (childQty == null || childQty.compareTo(BigDecimal.ZERO) <= 0) {
+                throw new ServiceException("鎶曞叆鐗╂枡鐢ㄩ噺蹇呴』澶т簬0");
+            }
+
             BigDecimal parentQty = BigDecimal.ONE;
             if (productStructureDto.getParentId() != null) {
                 ProductStructureDto parent = parentMap.get(productStructureDto.getParentId());
@@ -229,104 +331,140 @@
                 }
             }
 
-            // 鏍稿績璁$畻
-            BigDecimal needQty = childQty.divide(parentQty, 6, RoundingMode.HALF_UP).multiply(dto.getQuantity());
+            if (parentQty == null || parentQty.compareTo(BigDecimal.ZERO) <= 0) {
+                throw new ServiceException("鐖剁骇鐗╂枡鐢ㄩ噺蹇呴』澶т簬0");
+            }
+
+            BigDecimal needQty = childQty
+                    .divide(parentQty, 6, RoundingMode.HALF_UP)
+                    .multiply(reportQty);
+
+            ProductionProductInput productionProductInput = new ProductionProductInput();
+            productionProductInput.setProductModelId(productStructureDto.getProductModelId());
             productionProductInput.setQuantity(needQty);
             productionProductInput.setProductMainId(productionProductMain.getId());
             productionProductInputMapper.insert(productionProductInput);
-            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(),
-                    StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId(), null);
+
+            stockUtils.substractStock(
+                    productStructureDto.getProductModelId(),
+                    needQty,
+                    StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(),
+                    productionProductMain.getId(),
+                    null
+            );
         }
-        /*鏂板鎶ュ伐浜у嚭琛�*/
+
+        // 绗叓姝ワ細鍐欎骇鍑鸿褰曞苟璁$畻鏈鍚堟牸鏁伴噺
         ProductionProductOutput productionProductOutput = new ProductionProductOutput();
         productionProductOutput.setProductMainId(productionProductMain.getId());
         productionProductOutput.setProductModelId(productProcessRouteItem.getProductModelId());
-        productionProductOutput.setQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO);
-        productionProductOutput.setScrapQty(dto.getScrapQty() != null ? dto.getScrapQty() : BigDecimal.ZERO);
-        productionProductOutput.setOtherData(dto.getOtherData() != null ? dto.getOtherData() : "");
+        productionProductOutput.setQuantity(reportQty);
+        productionProductOutput.setScrapQty(scrapQty);
+        productionProductOutput.setOtherData(dto.getOtherData() == null ? "" : dto.getOtherData());
         productionProductOutputMapper.insert(productionProductOutput);
 
-        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
-        ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
+        BigDecimal qualifiedQty = reportQty.subtract(scrapQty);
 
-        //鍚堟牸鏁伴噺=鎶ュ伐鏁伴噺-鎶ュ簾鏁伴噺
-        BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty());
         List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(
                 Wrappers.<ProductProcessRouteItem>lambdaQuery()
                         .eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())
         );
-        boolean isRouteLastProcess = productProcessRouteItem.getDragSort() == productProcessRouteItems.size();
-        ReportStockRule reportStockRule = resolveReportStockRule(productProcessRouteItem, productProcess, productProcessRouteItems);
 
-        String processCategory = null;
-        String voltage = null;
-        if (productQty.compareTo(BigDecimal.ZERO) > 0 && reportStockRule.isFinishedGoodsStockIn()) {
-            processCategory = finishedProductStockDimensionResolver.resolveProcessCategory(productionProductMain.getId());
-            voltage = finishedProductStockDimensionResolver.resolveVoltage(productionProductMain.getId());
-        }
+        Integer maxDragSort = productProcessRouteItems.stream()
+                .map(ProductProcessRouteItem::getDragSort)
+                .filter(Objects::nonNull)
+                .max(Integer::compareTo)
+                .orElse(null);
 
-        if (productQty.compareTo(BigDecimal.ZERO) > 0) {
-            /*鏂板璐ㄦ*/
-            if (productProcessRouteItem.getIsQuality()) {
-                //瀵瑰簲鐨勮繃绋嬫鎴栬�呭嚭鍘傛
+        boolean isRouteLastProcess = Objects.equals(productProcessRouteItem.getDragSort(), maxDragSort);
+        ReportStockRule reportStockRule =
+                resolveReportStockRule(productProcessRouteItem, productProcess, productProcessRouteItems);
+
+        // 绗節姝ワ細濡傛灉鏈夊悎鏍兼暟閲忥紝鍒欐牴鎹槸鍚﹁川妫�鍐冲畾璧拌川妫�鎴栫洿鎺ュ叆搴�
+        if (qualifiedQty.compareTo(BigDecimal.ZERO) > 0) {
+            if (Boolean.TRUE.equals(productProcessRouteItem.getIsQuality())) {
+                Product product = productMapper.selectById(productModel.getProductId());
+                if (product == null) {
+                    throw new ServiceException("璐ㄦ浜у搧涓嶅瓨鍦�");
+                }
+
                 int inspectType = 1;
                 String process = productProcess.getName();
-                if (reportStockRule.isFinishedGoodsStockIn()) {
+
+                if (reportStockRule.finishedGoodsStockIn) {
                     inspectType = 2;
                     process = null;
                 }
-                Product product = productMapper.selectById(productModel.getProductId());
+
                 QualityInspect qualityInspect = new QualityInspect();
                 qualityInspect.setProductId(product.getId());
                 qualityInspect.setProductName(product.getProductName());
                 qualityInspect.setModel(productModel.getModel());
                 qualityInspect.setUnit(productModel.getUnit());
-                qualityInspect.setQuantity(productionProductOutput.getQuantity());
+                qualityInspect.setQuantity(reportQty);
                 qualityInspect.setProcess(process);
                 qualityInspect.setInspectState(0);
                 qualityInspect.setInspectType(inspectType);
-                qualityInspect.setDefectiveQuantity(productionProductOutput.getScrapQty());
+                qualityInspect.setDefectiveQuantity(scrapQty);
                 qualityInspect.setProductMainId(productionProductMain.getId());
                 qualityInspect.setProductModelId(productModel.getId());
                 qualityInspectMapper.insert(qualityInspect);
-                List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
-                if (qualityTestStandard.size() > 0) {
-                    qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
+
+                List<QualityTestStandard> qualityTestStandardList =
+                        qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
+
+                if (CollectionUtils.isNotEmpty(qualityTestStandardList)) {
+                    QualityTestStandard qualityTestStandard = qualityTestStandardList.get(0);
+                    qualityInspect.setTestStandardId(qualityTestStandard.getId());
                     qualityInspectMapper.updateById(qualityInspect);
+
                     qualityTestStandardParamMapper.selectList(
-                                    Wrappers.<QualityTestStandardParam>lambdaQuery()
-                                            .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId())
-                            )
-                            .forEach(qualityTestStandardParam -> {
-                                QualityInspectParam param = new QualityInspectParam();
-                                BeanUtils.copyProperties(qualityTestStandardParam, param);
-                                param.setId(null);
-                                param.setInspectId(qualityInspect.getId());
-                                qualityInspectParamMapper.insert(param);
-                            });
+                            Wrappers.<QualityTestStandardParam>lambdaQuery()
+                                    .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.getId())
+                    ).forEach(qualityTestStandardParam -> {
+                        QualityInspectParam param = new QualityInspectParam();
+                        BeanUtils.copyProperties(qualityTestStandardParam, param);
+                        param.setId(null);
+                        param.setInspectId(qualityInspect.getId());
+                        qualityInspectParamMapper.insert(param);
+                    });
                 }
-            } else {
-                if (reportStockRule.shouldCreateStockIn()) {
-                    if (reportStockRule.isFinishedGoodsStockIn()) {
-                        stockUtils.addStock(productProcessRouteItem.getProductModelId(), productQty,
-                                StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId(),
-                                processCategory, voltage);
-                    } else {
-                        stockUtils.addStockNoReview(productProcessRouteItem.getProductModelId(), productQty,
-                                StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
-                    }
-                }
-                if (productionProductOutput.getScrapQty().compareTo(BigDecimal.ZERO) > 0) {
-                    stockUtils.addUnStockNoReview(productProcessRouteItem.getProductModelId(), productionProductOutput.getScrapQty(),
-                            StockInUnQualifiedRecordTypeEnum.QUALITYINSPECT_UNSTOCK_IN.getCode(), productionProductMain.getId());
+            } else if (reportStockRule.createStockIn) {
+                //鎴愬搧鍏ュ簱闇�瑕佺數鍘嬶紝宸ュ簭绫诲埆锛堥摐锛岄摱锛�
+                if (reportStockRule.finishedGoodsStockIn) {
+                    String processCategory =
+                            finishedProductStockDimensionResolver.resolveProcessCategory(productionProductMain.getId());
+                    String voltage =
+                            finishedProductStockDimensionResolver.resolveVoltage(productionProductMain.getId());
+
+                    stockUtils.addStock(
+                            productProcessRouteItem.getProductModelId(),
+                            qualifiedQty,
+                            StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(),
+                            productionProductMain.getId(),
+                            processCategory,
+                            voltage
+                    );
+                } else {
+                    stockUtils.addStockNoReview(
+                            productProcessRouteItem.getProductModelId(),
+                            qualifiedQty,
+                            StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(),
+                            productionProductMain.getId()
+                    );
                 }
             }
 
-            productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty));
+            // 绗崄姝ワ細鏇存柊宸ュ崟銆佽鍗曞畬鎴愯繘搴﹀拰璁′欢鏍哥畻鏁版嵁
+            BigDecimal workOrderCompleteQuantity =
+                    productWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productWorkOrder.getCompleteQuantity();
+            productWorkOrder.setCompleteQuantity(workOrderCompleteQuantity.add(qualifiedQty));
+
             if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) {
                 productWorkOrder.setActualStartTime(LocalDate.now());
             }
-            if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0) {
+            if (productWorkOrder.getPlanQuantity() != null
+                    && productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) >= 0) {
                 productWorkOrder.setActualEndTime(LocalDate.now());
             }
             productWorkOrderMapper.updateById(productWorkOrder);
@@ -334,98 +472,139 @@
             if (ObjectUtils.isNull(productOrder.getStartTime())) {
                 productOrder.setStartTime(LocalDateTime.now());
             }
+
             if (isRouteLastProcess) {
-                productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty));
-                if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) {
+                BigDecimal orderCompleteQuantity =
+                        productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity();
+                productOrder.setCompleteQuantity(orderCompleteQuantity.add(qualifiedQty));
+
+                if (productOrder.getQuantity() != null
+                        && productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) >= 0) {
                     productOrder.setEndTime(LocalDateTime.now());
                 }
             }
             productOrderMapper.updateById(productOrder);
 
-            SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder()
-                    .productMainId(productionProductMain.getId())
-                    .schedulingUserId(userId)
-                    .schedulingUserName(userName)
-                    .finishedNum(productQty)
-                    .workHours(productProcess.getSalaryQuota())
-                    .process(productProcess.getName())
-                    .schedulingDate(LocalDate.now())
-                    .tenantId(dto.getTenantId())
-                    .build();
+            SalesLedgerProductionAccounting salesLedgerProductionAccounting =
+                    SalesLedgerProductionAccounting.builder()
+                            .productMainId(productionProductMain.getId())
+                            .schedulingUserId(userId)
+                            .schedulingUserName(userName)
+                            .finishedNum(qualifiedQty)
+                            .workHours(productProcess.getSalaryQuota())
+                            .process(productProcess.getName())
+                            .schedulingDate(LocalDate.now())
+                            .tenantId(dto.getTenantId())
+                            .build();
             salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting);
         }
+
+        // 绗崄涓�姝ワ細缁熶竴澶勭悊鎶ュ簾鏁伴噺鍏ヤ笉鍚堟牸搴撳瓨锛岄伩鍏嶅湪涓绘祦绋嬩腑閲嶅鍏ュ簱
+        handleScrapStock(productModel.getId(), scrapQty, isRouteLastProcess, productionProductMain.getId());
+
         return true;
     }
 
-    /**
-     * 鍒ゆ柇褰撳墠鎶ュ伐鏄惁闇�瑕佸叆搴擄紝浠ュ強鏄惁鎸夋垚鍝佸叆搴撳鐞嗐��
-     */
+    // 鍒ゆ柇褰撳墠鎶ュ伐鏄惁闇�瑕佸叆搴擄紝浠ュ強鏄惁鎸夋垚鍝佸叆搴撳鐞�
     private ReportStockRule resolveReportStockRule(ProductProcessRouteItem currentRouteItem,
                                                    ProductProcess currentProcess,
                                                    List<ProductProcessRouteItem> routeItems) {
-        boolean isRouteLastProcess = currentRouteItem.getDragSort() != null
-                && CollectionUtils.isNotEmpty(routeItems)
-                && currentRouteItem.getDragSort().equals(routeItems.size());
-        String currentProcessName = normalizeProcessName(currentProcess == null ? null : currentProcess.getName());
+        Integer maxDragSort = CollectionUtils.isEmpty(routeItems)
+                ? null
+                : routeItems.stream()
+                .map(ProductProcessRouteItem::getDragSort)
+                .filter(Objects::nonNull)
+                .max(Integer::compareTo)
+                .orElse(null);
+
+        boolean isRouteLastProcess = Objects.equals(currentRouteItem.getDragSort(), maxDragSort);
+        String currentProcessName = currentProcess == null || currentProcess.getName() == null
+                ? ""
+                : currentProcess.getName().trim();
+
         if (PROCESS_VOLTAGE_SORT.equals(currentProcessName)) {
             return new ReportStockRule(false, false);
         }
 
-        Map<Long, String> processNameMap = loadRouteProcessNameMap(routeItems);
-        boolean hasVoltageSort = containsProcess(routeItems, processNameMap, PROCESS_VOLTAGE_SORT);
-        boolean hasOpticalInspection = containsProcess(routeItems, processNameMap, PROCESS_OPTICAL_INSPECTION);
-        boolean hasPackaging = containsProcess(routeItems, processNameMap, PROCESS_PACKAGING);
+        Set<Long> processIds = CollectionUtils.isEmpty(routeItems)
+                ? Collections.emptySet()
+                : routeItems.stream()
+                .map(ProductProcessRouteItem::getProcessId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+
+        Map<Long, String> processNameMap = new HashMap<>();
+        if (CollectionUtils.isNotEmpty(processIds)) {
+            processNameMap = productProcessMapper.selectBatchIds(processIds)
+                    .stream()
+                    .collect(Collectors.toMap(
+                            ProductProcess::getId,
+                            process -> process.getName() == null ? "" : process.getName().trim(),
+                            (a, b) -> a
+                    ));
+        }
+
+        Set<String> routeProcessNames = CollectionUtils.isEmpty(routeItems)
+                ? Collections.emptySet()
+                : routeItems.stream()
+                .map(ProductProcessRouteItem::getProcessId)
+                .map(processNameMap::get)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toSet());
+
+        boolean hasVoltageSort = routeProcessNames.contains(PROCESS_VOLTAGE_SORT);
+        boolean hasOpticalInspection = routeProcessNames.contains(PROCESS_OPTICAL_INSPECTION);
+        boolean hasPackaging = routeProcessNames.contains(PROCESS_PACKAGING);
 
         if (hasPackaging && PROCESS_PACKAGING.equals(currentProcessName)) {
             return new ReportStockRule(true, true);
         }
+
         if (hasPackaging && PROCESS_OPTICAL_INSPECTION.equals(currentProcessName)) {
             return new ReportStockRule(false, false);
         }
-        if (!hasPackaging && hasVoltageSort && hasOpticalInspection && PROCESS_OPTICAL_INSPECTION.equals(currentProcessName)) {
+
+        if (!hasPackaging
+                && hasVoltageSort
+                && hasOpticalInspection
+                && PROCESS_OPTICAL_INSPECTION.equals(currentProcessName)) {
             return new ReportStockRule(true, true);
         }
+
         return new ReportStockRule(true, isRouteLastProcess);
     }
 
-    /**
-     * 鎵归噺鍔犺浇宸ヨ壓璺嚎涓殑宸ュ簭鍚嶇О銆�
-     */
-    private Map<Long, String> loadRouteProcessNameMap(List<ProductProcessRouteItem> routeItems) {
-        if (CollectionUtils.isEmpty(routeItems)) {
-            return Collections.emptyMap();
+    // 缁熶竴澶勭悊鎶ュ簾鏁伴噺鍏ヤ笉鍚堟牸搴撳瓨锛岄伩鍏嶉噸澶嶅叆搴�
+    private void handleScrapStock(Long productModelId,
+                                  BigDecimal scrapQty,
+                                  boolean isRouteLastProcess,
+                                  Long productMainId) {
+        if (productModelId == null) {
+            throw new ServiceException("鎶ュ簾浜у搧鍨嬪彿涓嶈兘涓虹┖");
         }
-        Set<Long> processIds = routeItems.stream()
-                .map(ProductProcessRouteItem::getProcessId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        if (processIds.isEmpty()) {
-            return Collections.emptyMap();
+
+        if (scrapQty == null || scrapQty.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
         }
-        return productProcessMapper.selectBatchIds(processIds).stream()
-                .collect(Collectors.toMap(ProductProcess::getId, process -> normalizeProcessName(process.getName())));
+
+        if (isRouteLastProcess) {
+            stockUtils.addUnStock(
+                    productModelId,
+                    scrapQty,
+                    StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(),
+                    productMainId
+            );
+        } else {
+            stockUtils.addUnStockNoReview(
+                    productModelId,
+                    scrapQty,
+                    StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(),
+                    productMainId
+            );
+        }
     }
 
-    /**
-     * 鍒ゆ柇宸ヨ壓璺嚎涓槸鍚﹀寘鍚寚瀹氬伐搴忋��
-     */
-    private boolean containsProcess(List<ProductProcessRouteItem> routeItems, Map<Long, String> processNameMap, String processName) {
-        return routeItems.stream()
-                .map(ProductProcessRouteItem::getProcessId)
-                .map(processNameMap::get)
-                .anyMatch(processName::equals);
-    }
-
-    /**
-     * 缁熶竴宸ュ簭鍚嶇О鏍煎紡锛岄伩鍏嶈鍒欏尮閰嶆椂鍙楃┖鐧藉瓧绗﹀奖鍝嶃��
-     */
-    private String normalizeProcessName(String processName) {
-        return processName == null ? "" : processName.trim();
-    }
-
-    /**
-     * 鍗曟鎶ュ伐瀵瑰簲鐨勫叆搴撹鍒欍��
-     */
+    // 鍗曟鎶ュ伐瀵瑰簲鐨勫叆搴撹鍒�
     private static final class ReportStockRule {
         private final boolean createStockIn;
         private final boolean finishedGoodsStockIn;
@@ -434,27 +613,20 @@
             this.createStockIn = createStockIn;
             this.finishedGoodsStockIn = finishedGoodsStockIn;
         }
-
-        private boolean shouldCreateStockIn() {
-            return createStockIn;
-        }
-
-        private boolean isFinishedGoodsStockIn() {
-            return finishedGoodsStockIn;
-        }
     }
 
     @Override
     public Boolean removeProductMain(Long id) {
+        // 鍒犻櫎鎶ュ伐鍓嶅厛妫�鏌ユ槸鍚﹀凡缁忓畬鎴愪笉鍚堟牸澶勭悊
         List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(
                 Wrappers.<QualityInspect>lambdaQuery().eq(QualityInspect::getProductMainId, id)
         );
-        if (qualityInspects.size() > 0) {
+        if (!qualityInspects.isEmpty()) {
             List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.selectList(
                     Wrappers.<QualityUnqualified>lambdaQuery()
                             .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList()))
             );
-            if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState() == 1) {
+            if (!qualityUnqualifieds.isEmpty() && qualityUnqualifieds.get(0).getInspectState() == 1) {
                 throw new ServiceException("璇ユ姤宸ュ凡瀹屾垚涓嶅悎鏍煎鐞嗭紝涓嶈兘鍒犻櫎");
             }
         }
diff --git a/src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedMapper.java b/src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedMapper.java
index b9f462f..4401332 100644
--- a/src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedMapper.java
+++ b/src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedMapper.java
@@ -3,7 +3,6 @@
 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.quality.pojo.QualityInspect;
 import com.ruoyi.quality.pojo.QualityUnqualified;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -13,22 +12,21 @@
 @Mapper
 public interface QualityUnqualifiedMapper extends BaseMapper<QualityUnqualified> {
 
-
     IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, @Param("qualityUnqualified") QualityUnqualified qualityUnqualified);
 
     List<QualityUnqualified> qualityUnqualifiedExport(@Param("qualityUnqualified") QualityUnqualified qualityUnqualified);
 
     QualityUnqualified getUnqualified(@Param("id") Integer id);
 
-    //鎵嬪姩鏂板涓嶅悎鏍肩殑鏃跺��,鏍规嵁浜у搧鍚嶇О鍜岃鏍煎瀷鍙锋煡鍑哄搴旂殑瑙勬牸鍨嬪彿id
+    // 鎵嬪姩鏂板涓嶅悎鏍兼椂锛屾牴鎹骇鍝佸悕绉板拰瑙勬牸鍨嬪彿鏌ヨ瀵瑰簲鐨勪骇鍝佸瀷鍙� ID
     Long getModelId(@Param("productName") String productName, @Param("model") String model);
-    
-    //鏍规嵁宸ュ簭鍚嶇О鍒楄〃鏌ヨ琚殧绂荤殑涓嶅悎鏍艰褰�
-    List<QualityUnqualified> selectUnqualifiedByProcessNames(@Param("processNames") List<String> processNames);
+
+    // 鏍规嵁鐢熶骇璁㈠崟鍜屽墠搴忓伐搴忓悕绉板垪琛ㄦ煡璇㈡湭瑙i櫎闅旂鐨勪笉鍚堟牸璁板綍
+    List<QualityUnqualified> selectUnqualifiedByProductOrderAndProcessNames(@Param("productOrderId") Long productOrderId,
+                                                                            @Param("processNames") List<String> processNames);
 
     /**
-     * 鏌ヨ涓嶅悎鏍艰褰曠殑鐢熶骇璁㈠崟淇℃伅
-     * @return
+     * 鏌ヨ涓嶅悎鏍艰褰曞叧鑱旂殑鐢熶骇璁㈠崟淇℃伅銆�
      */
     List<QualityUnqualified> selectUnqualifiedWithProductionOrder();
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index 87a7a89..ff5567e 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -38,7 +38,7 @@
 
     List<MonthlyAmountDto> getAmountHalfYear(Integer type);
 
-    IPage<SalesLedger> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto);
+    IPage<SalesLedgerDto> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto);
 
     AjaxResult importData(MultipartFile file);
 
diff --git a/src/main/resources/mapper/production/ProductionProductMainMapper.xml b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
index 5ea73fa..691accc 100644
--- a/src/main/resources/mapper/production/ProductionProductMainMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -154,10 +154,13 @@
 
     <select id="checkPreviousProcessReported" resultType="java.lang.Boolean">
         SELECT CASE WHEN COUNT(*) > 0 THEN TRUE ELSE FALSE END
-        FROM production_product_main ppm
-        JOIN product_work_order pwo ON ppm.work_order_id = pwo.id
-        JOIN product_process_route_item ppri ON pwo.product_process_route_item_id = ppri.id
-        WHERE ppri.product_route_id = #{productRouteId}
-        AND ppri.drag_sort = #{currentDragSort} - 1
+        FROM product_work_order current_pwo
+        JOIN product_process_route_item current_ppri ON current_pwo.product_process_route_item_id = current_ppri.id
+        JOIN product_work_order previous_pwo ON previous_pwo.product_order_id = current_pwo.product_order_id
+        JOIN product_process_route_item previous_ppri ON previous_pwo.product_process_route_item_id = previous_ppri.id
+        JOIN production_product_main ppm ON ppm.work_order_id = previous_pwo.id
+        WHERE current_pwo.id = #{workOrderId}
+        AND previous_ppri.product_route_id = current_ppri.product_route_id
+        AND previous_ppri.drag_sort = #{currentDragSort} - 1
     </select>
 </mapper>
diff --git a/src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml b/src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml
index cca93fc..ec00fa0 100644
--- a/src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml
+++ b/src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml
@@ -40,9 +40,10 @@
             AND check_time &gt;= DATE_FORMAT(#{qualityUnqualified.entryDateStart},'%Y-%m-%d')
         </if>
         <if test="qualityUnqualified.entryDateEnd != null and qualityUnqualified.entryDateEnd != '' ">
-            AND  check_time &lt;= DATE_FORMAT(#{qualityUnqualified.entryDateEnd},'%Y-%m-%d')
+            AND check_time &lt;= DATE_FORMAT(#{qualityUnqualified.entryDateEnd},'%Y-%m-%d')
         </if>
     </select>
+
     <select id="qualityUnqualifiedExport" resultType="com.ruoyi.quality.pojo.QualityUnqualified">
         SELECT
         qu.*,
@@ -61,6 +62,7 @@
             AND product_name = #{qualityUnqualified.productName}
         </if>
     </select>
+
     <select id="getUnqualified" resultType="com.ruoyi.quality.pojo.QualityUnqualified">
         SELECT
             qu.id,
@@ -84,27 +86,32 @@
                 ELSE false
                 END AS method
         FROM quality_unqualified qu
-                 LEFT JOIN product_model pm ON qu.model = pm.model AND pm.product_id = qu.product_id
-                 LEFT JOIN quality_inspect qi ON qu.inspect_id = qi.id
+        LEFT JOIN product_model pm ON qu.model = pm.model AND pm.product_id = qu.product_id
+        LEFT JOIN quality_inspect qi ON qu.inspect_id = qi.id
         where
             1=1
-        and qu.id = #{id}
+            and qu.id = #{id}
     </select>
+
     <select id="getModelId" resultType="java.lang.Long">
         select pm.id
         from product_model pm
-        left join product p on pm.product_id=p.id
-        where pm.model=#{model}
-          and  p.product_name=#{productName}
+        left join product p on pm.product_id = p.id
+        where pm.model = #{model}
+          and p.product_name = #{productName}
     </select>
-    <select id="selectUnqualifiedByProcessNames" resultType="com.ruoyi.quality.pojo.QualityUnqualified">
+
+    <select id="selectUnqualifiedByProductOrderAndProcessNames" resultType="com.ruoyi.quality.pojo.QualityUnqualified">
         SELECT DISTINCT qu.*
         FROM quality_unqualified qu
         JOIN quality_inspect qi ON qu.inspect_id = qi.id
+        JOIN production_product_main ppm ON qi.product_main_id = ppm.id
+        JOIN product_work_order pwo ON ppm.work_order_id = pwo.id
         WHERE qi.process IN
         <foreach collection="processNames" item="processName" open="(" separator="," close=")">
             #{processName}
         </foreach>
+        AND pwo.product_order_id = #{productOrderId}
         AND qu.deal_result = '闅旂'
         AND qu.quarantine_lifted = false
     </select>
@@ -121,4 +128,4 @@
         WHERE po.id IS NOT NULL
         GROUP BY po.id
     </select>
-</mapper>
\ No newline at end of file
+</mapper>

--
Gitblit v1.9.3