From 0d7d874912d0147376826b55667a1deb6547ed91 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 21 五月 2026 15:25:27 +0800
Subject: [PATCH] Merge branch 'dev_New_pro' into dev_宁夏_英泽防锈

---
 src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java |   91 ++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 77 insertions(+), 14 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 6a30baf..40dd74c 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
@@ -23,6 +23,7 @@
 import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
 import com.ruoyi.production.pojo.ProductionProductMain;
 import com.ruoyi.production.service.ProductionBomStructureService;
+import com.ruoyi.production.util.TaskPlanQuantityUtil;
 import com.ruoyi.technology.mapper.TechnologyOperationMapper;
 import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
 import com.ruoyi.technology.mapper.TechnologyParamMapper;
@@ -216,19 +217,22 @@
             return;
         }
         List<ProductionBomStructure> updateList = new ArrayList<>();
+        BigDecimal lastProcessDemandedQuantity = orderQuantity;
         for (ProductionBomStructure structure : structureList) {
             if (structure == null || structure.getId() == null) {
                 continue;
             }
-            BigDecimal demandedQuantity = defaultDecimal(structure.getUnitQuantity()).multiply(orderQuantity);
-            if (compareDecimal(structure.getDemandedQuantity(), demandedQuantity) == 0) {
-                continue;
-            }
+
+            BigDecimal demandedQuantity = lastProcessDemandedQuantity.multiply(defaultDecimal(structure.getUnitQuantity()));
+//            if (compareDecimal(structure.getDemandedQuantity(), demandedQuantity) == 0) {
+//                continue;
+//            }
             ProductionBomStructure update = new ProductionBomStructure();
             update.setId(structure.getId());
             update.setDemandedQuantity(demandedQuantity);
             updateList.add(update);
             structure.setDemandedQuantity(demandedQuantity);
+            lastProcessDemandedQuantity = demandedQuantity;
         }
         if (!updateList.isEmpty()) {
             this.updateBatchById(updateList);
@@ -259,7 +263,7 @@
                 .filter(item -> item != null && item.getId() != null)
                 .collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, item -> item, (left, right) -> left));
         // Keep task plan quantities aligned with the same order BOM snapshot demand used during snapshot creation.
-        Map<String, BigDecimal> demandedQuantityMap = buildOperationDemandedQuantityMap(structureList, rootProductModelId);
+        Map<String, BigDecimal> demandedQuantityMap = TaskPlanQuantityUtil.buildOperationDemandedQuantityMap(structureList, rootProductModelId);
         for (ProductionOperationTask task : taskList) {
             if (task == null || task.getId() == null || task.getProductionOrderRoutingOperationId() == null) {
                 continue;
@@ -288,8 +292,15 @@
                                             ProductionOrderBom orderBom,
                                             List<ProductionBomStructure> structureList,
                                             Long rootProductModelId) {
+        // 閲嶆柊鏌ヨBOM缁撴瀯锛屾寜瀛愯妭鐐逛紭鍏堟帓搴�
+        List<ProductionBomStructure> routingStructureList = this.list(
+                Wrappers.<ProductionBomStructure>lambdaQuery()
+                        .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId())
+                        .orderByDesc(ProductionBomStructure::getParentId)
+                        .orderByAsc(ProductionBomStructure::getId));
+
         ProductionOrderRouting orderRouting = getOrCreateOrderRoutingSnapshot(productionOrderId, productionOrder, orderBom, rootProductModelId);
-        List<ProductionOrderRoutingOperation> desiredOperationList = buildDesiredRoutingOperationList(structureList, rootProductModelId);
+        List<ProductionOrderRoutingOperation> desiredOperationList = buildDesiredRoutingOperationList(routingStructureList, rootProductModelId);
         List<ProductionOrderRoutingOperation> existingOperationList = productionOrderRoutingOperationMapper.selectList(
                 Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
                         .eq(ProductionOrderRoutingOperation::getOrderRoutingId, orderRouting.getId())
@@ -378,14 +389,14 @@
         Map<Long, ProductionBomStructure> structureById = structureList.stream()
                 .filter(item -> item != null && item.getId() != null)
                 .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
+
+        // 鏋勫缓鐖�-瀛愭槧灏勫叧绯�
+        Map<Long, List<ProductionBomStructure>> treeMap = buildParentChildMap(structureList);
+
+        // 浣跨敤鍚庡簭閬嶅巻鏋勫缓鎿嶄綔鍒楄〃锛堝厛瀛愬悗鐖讹紝纭繚宸ヨ壓璺嚎椤哄簭姝g‘锛�
         Map<String, ProductionBomStructure> uniqueOperationMap = new LinkedHashMap<>();
-        for (ProductionBomStructure bomStructure : structureList) {
-            if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) {
-                continue;
-            }
-            Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(bomStructure, structureById), rootProductModelId);
-            uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure);
-        }
+        buildOperationListPostOrder(null, treeMap, uniqueOperationMap, structureById, rootProductModelId);
+
         List<ProductionOrderRoutingOperation> desiredOperationList = new ArrayList<>();
         int dragSort = 1;
         for (ProductionBomStructure bomStructure : uniqueOperationMap.values()) {
@@ -402,6 +413,52 @@
             desiredOperationList.add(routingOperation);
         }
         return desiredOperationList;
+    }
+
+    private Map<Long, List<ProductionBomStructure>> buildParentChildMap(List<ProductionBomStructure> structureList) {
+        Map<Long, List<ProductionBomStructure>> treeMap = new LinkedHashMap<>();
+        Map<Long, Integer> childCountMap = new HashMap<>();
+
+        // 绗竴閬嶏細缁熻姣忎釜鑺傜偣鐨勫瓙鑺傜偣鏁伴噺锛屽悓鏃舵瀯寤哄垵濮嬫槧灏�
+        for (ProductionBomStructure structure : structureList) {
+            if (structure == null) continue;
+            Long parentId = structure.getParentId();
+            childCountMap.merge(parentId, 1, Integer::sum);  // 缁熻姣忎釜鐖惰妭鐐规湁澶氬皯涓瓙鑺傜偣
+            treeMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(structure);
+        }
+
+        // 绗簩閬嶏細瀵规瘡涓埗鑺傜偣涓嬬殑瀛愯妭鐐规寜瀛愯妭鐐规暟閲忓�掑簭鎺掑簭锛堟湁瀛愯妭鐐圭殑浼樺厛锛�
+        for (Map.Entry<Long, List<ProductionBomStructure>> entry : treeMap.entrySet()) {
+            List<ProductionBomStructure> children = entry.getValue();
+            children.sort((a, b) -> {
+                int countA = childCountMap.getOrDefault(a.getId(), 0);
+                int countB = childCountMap.getOrDefault(b.getId(), 0);
+                return Integer.compare(countB, countA);  // 瀛愯妭鐐瑰鐨勬帓鍓嶉潰
+            });
+        }
+
+        return treeMap;
+    }
+
+    private void buildOperationListPostOrder(Long parentId,
+                                             Map<Long, List<ProductionBomStructure>> treeMap,
+                                             Map<String, ProductionBomStructure> uniqueOperationMap,
+                                             Map<Long, ProductionBomStructure> structureById,
+                                             Long rootProductModelId) {
+        List<ProductionBomStructure> children = treeMap.get(parentId);
+        if (children == null || children.isEmpty()) {
+            return;
+        }
+        for (ProductionBomStructure child : children) {
+            // 鍏堥�掑綊澶勭悊瀛愯妭鐐�
+            buildOperationListPostOrder(child.getId(), treeMap, uniqueOperationMap, structureById, rootProductModelId);
+
+            // 鍐嶅鐞嗗綋鍓嶈妭鐐�
+            if (child.getTechnologyOperationId() != null) {
+                Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(child, structureById), rootProductModelId);
+                uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(child, outputProductModelId), child);
+            }
+        }
     }
 
     private Map<String, Deque<ProductionOrderRoutingOperation>> buildExistingRoutingOperationBucketMap(List<ProductionOrderRoutingOperation> existingOperationList) {
@@ -479,6 +536,12 @@
         if (!Objects.equals(currentOperation.getIsProduction(), desiredOperation.getIsProduction())) {
             update.setIsProduction(desiredOperation.getIsProduction());
             currentOperation.setIsProduction(desiredOperation.getIsProduction());
+            changed = true;
+        }
+        // 鏇存柊 dragSort 瀛楁锛岀‘淇濆伐鑹鸿矾绾块『搴忔纭�
+        if (!Objects.equals(currentOperation.getDragSort(), desiredOperation.getDragSort())) {
+            update.setDragSort(desiredOperation.getDragSort());
+            currentOperation.setDragSort(desiredOperation.getDragSort());
             changed = true;
         }
         if (!Objects.equals(currentOperation.getType(), desiredOperation.getType())) {
@@ -741,8 +804,8 @@
             return;
         }
         for (ProductionBomStructureDto node : source) {
+            flattenTree(node.getChildren(), result);  // 鍏堥�掑綊娣诲姞瀛愯妭鐐�
             result.add(node);
-            flattenTree(node.getChildren(), result);
         }
     }
 

--
Gitblit v1.9.3