From bd86068dd507b7ee076456ab71aa03394730076f Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期五, 15 五月 2026 17:25:46 +0800
Subject: [PATCH] fix:1.工单产出数量根据bom需求数量赋值

---
 src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java |   76 +++++++++++++++++++++++++-------------
 1 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
index d0dab50..2bded77 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
@@ -220,7 +220,6 @@
         if (taskList == null || taskList.isEmpty()) {
             return;
         }
-
         Set<Long> routingOperationIds = taskList.stream()
                 .map(ProductionOperationTask::getProductionOrderRoutingOperationId)
                 .filter(Objects::nonNull)
@@ -228,14 +227,13 @@
         if (routingOperationIds.isEmpty()) {
             return;
         }
-
         Map<Long, ProductionOrderRoutingOperation> routingOperationMap = productionOrderRoutingOperationMapper
                 .selectBatchIds(routingOperationIds)
                 .stream()
                 .filter(item -> item != null && item.getId() != null)
                 .collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, item -> item, (left, right) -> left));
-        Map<String, BigDecimal> demandedQuantityMap = buildOperationDemandedQuantityMap(structureList, rootProductModelId, orderQuantity);
-
+        // Keep task plan quantities aligned with the same order BOM snapshot demand used during snapshot creation.
+        Map<String, BigDecimal> demandedQuantityMap = buildOperationDemandedQuantityMap(structureList, rootProductModelId);
         for (ProductionOperationTask task : taskList) {
             if (task == null || task.getId() == null || task.getProductionOrderRoutingOperationId() == null) {
                 continue;
@@ -244,7 +242,11 @@
             if (routingOperation == null || routingOperation.getTechnologyRoutingOperationId() == null) {
                 continue;
             }
-            BigDecimal planQuantity = resolveTaskPlanQuantity(routingOperation, demandedQuantityMap, orderQuantity);
+            BigDecimal planQuantity = resolveTaskPlanQuantity(
+                    routingOperation,
+                    demandedQuantityMap,
+                    orderQuantity,
+                    rootProductModelId);
             if (compareDecimal(task.getPlanQuantity(), planQuantity) == 0) {
                 continue;
             }
@@ -254,10 +256,8 @@
             productionOperationTaskMapper.updateById(update);
         }
     }
-
     private Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> structureList,
-                                                                      Long rootProductModelId,
-                                                                      BigDecimal orderQuantity) {
+                                                                      Long rootProductModelId) {
         if (structureList == null || structureList.isEmpty()) {
             return Collections.emptyMap();
         }
@@ -265,26 +265,43 @@
                 .filter(item -> item != null && item.getId() != null)
                 .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
         Map<String, BigDecimal> demandedQuantityMap = new HashMap<>();
+        Set<String> mergedOutputNodeKeySet = new HashSet<>();
         for (ProductionBomStructure bomStructure : structureList) {
-            if (bomStructure == null || bomStructure.getTechnologyOperationId() == null || bomStructure.getUnitQuantity() == null) {
+            if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) {
                 continue;
             }
-            Long outputProductModelId = resolveOutputProductModelId(bomStructure, structureById, rootProductModelId);
+            // Resolve the output node first, then read the output node demand for the task plan quantity.
+            ProductionBomStructure outputNode = resolveOperationOutputNode(bomStructure, structureById);
+            Long outputProductModelId = resolveOutputProductModelId(outputNode, rootProductModelId);
+            if (outputProductModelId == null) {
+                continue;
+            }
+            String mergedOutputNodeKey = buildOperationOutputNodeKey(
+                    bomStructure.getTechnologyOperationId(),
+                    outputNode == null ? null : outputNode.getId(),
+                    outputProductModelId);
+            if (!mergedOutputNodeKeySet.add(mergedOutputNodeKey)) {
+                continue;
+            }
+            // Multiple input rows can point to the same output node, so only count that output demand once.
             String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId);
-            demandedQuantityMap.merge(key, bomStructure.getUnitQuantity().multiply(orderQuantity), BigDecimal::add);
+            demandedQuantityMap.merge(key, defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity()), BigDecimal::add);
         }
         return demandedQuantityMap;
     }
-
     private BigDecimal resolveTaskPlanQuantity(ProductionOrderRoutingOperation routingOperation,
                                                Map<String, BigDecimal> demandedQuantityMap,
-                                               BigDecimal orderQuantity) {
+                                               BigDecimal orderQuantity,
+                                               Long rootProductModelId) {
         if (routingOperation == null || demandedQuantityMap == null || demandedQuantityMap.isEmpty()) {
             return orderQuantity;
         }
+        Long outputProductModelId = routingOperation.getProductModelId() != null
+                ? routingOperation.getProductModelId()
+                : rootProductModelId;
         String key = buildOperationDemandedQuantityKey(
                 routingOperation.getTechnologyOperationId(),
-                routingOperation.getProductModelId());
+                outputProductModelId);
         BigDecimal planQuantity = demandedQuantityMap.get(key);
         return planQuantity != null ? planQuantity : orderQuantity;
     }
@@ -293,21 +310,28 @@
         return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId);
     }
 
-    private Long resolveOutputProductModelId(ProductionBomStructure bomStructure,
-                                             Map<Long, ProductionBomStructure> structureById,
-                                             Long rootProductModelId) {
+    private String buildOperationOutputNodeKey(Long operationId, Long outputNodeId, Long outputProductModelId) {
+        return String.valueOf(operationId) + "#" + String.valueOf(outputNodeId) + "#" + String.valueOf(outputProductModelId);
+    }
+
+    private ProductionBomStructure resolveOperationOutputNode(ProductionBomStructure bomStructure,
+                                                              Map<Long, ProductionBomStructure> structureById) {
         if (bomStructure == null) {
+            return null;
+        }
+        // The root node is the first output node; other rows use their direct parent as the current operation output.
+        if (bomStructure.getParentId() == null) {
+            return bomStructure;
+        }
+        ProductionBomStructure parent = structureById.get(bomStructure.getParentId());
+        return parent != null ? parent : bomStructure;
+    }
+    private Long resolveOutputProductModelId(ProductionBomStructure outputNode,
+                                             Long rootProductModelId) {
+        if (outputNode == null) {
             return rootProductModelId;
         }
-        Long parentId = bomStructure.getParentId();
-        if (parentId == null) {
-            return rootProductModelId != null ? rootProductModelId : bomStructure.getProductModelId();
-        }
-        ProductionBomStructure parent = structureById.get(parentId);
-        if (parent != null && parent.getProductModelId() != null) {
-            return parent.getProductModelId();
-        }
-        return rootProductModelId != null ? rootProductModelId : bomStructure.getProductModelId();
+        return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId;
     }
 
     private BigDecimal defaultDecimal(BigDecimal value) {

--
Gitblit v1.9.3