From d29080af4e965ba341cb85a5bc45ecd183c06783 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 14 八月 2026 17:45:45 +0800
Subject: [PATCH] Merge branch 'dev_New_pro' into dev_pro_山西_晋和园

---
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java |  160 +++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 129 insertions(+), 31 deletions(-)

diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
index 920188e..95c7344 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -44,6 +44,7 @@
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -59,6 +60,7 @@
     private final ProductionOperationTaskMapper productionOperationTaskMapper;
     private final ProductionOrderBomMapper productionOrderBomMapper;
     private final ProductionBomStructureMapper productionBomStructureMapper;
+    private final ProductionOrderMapper productionOrderMapper;
     private final ProductionProductMainMapper productionProductMainMapper;
     private final ProductionProductOutputMapper productionProductOutputMapper;
     private final ProductionOrderPickMapper productionOrderPickMapper;
@@ -114,7 +116,7 @@
         // 涓嬪崟鍏ュ彛缁熶竴琛ラ綈鏉ユ簮鍗曟嵁銆佽鍒掑拰宸ヨ壓淇℃伅锛岄伩鍏嶅墠绔垎鍒紶澶氬瀛楁銆�
         validateAndFillOrder(productionOrder, oldOrder);
         if (productionOrder.getNpsNo() == null || productionOrder.getNpsNo().trim().isEmpty()) {
-            productionOrder.setNpsNo(generateNextOrderNo());
+            productionOrder.setNpsNo(generateNextOrderNo(productionOrder.getCreateTime() != null ? productionOrder.getCreateTime() : LocalDateTime.now()));
         }
         if (productionOrder.getCompleteQuantity() == null) {
             productionOrder.setCompleteQuantity(BigDecimal.ZERO);
@@ -437,8 +439,54 @@
         productionOrderBomMapper.insert(orderBom);
 
         Map<Long, Long> idMap = new HashMap<>();
+        // 鏋勫缓 sourceId 鈫� sourceNode 鏄犲皠 鍜� parentId 鈫� children 鏄犲皠
+        Map<Long, TechnologyBomStructure> sourceById = new HashMap<>();
+        Map<Long, List<TechnologyBomStructure>> childrenMap = new LinkedHashMap<>();
         for (TechnologyBomStructure source : structureList) {
-            // 瀛愯妭鐐� parentId 闇�瑕佹槧灏勬垚鏂板揩鐓ц妭鐐� id锛屾墠鑳戒繚鐣欏師濮� BOM 灞傜骇銆�
+            if (source == null || source.getId() == null) {
+                continue;
+            }
+            sourceById.put(source.getId(), source);
+            Long parentId = source.getParentId();
+            childrenMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(source);
+        }
+
+        // BFS 浠庢牴鑺傜偣寮�濮嬶紝鐖惰妭鐐瑰厛浜庡瓙鑺傜偣澶勭悊
+        Deque<TechnologyBomStructure> queue = new ArrayDeque<>();
+        List<TechnologyBomStructure> rootNodes = childrenMap.get(null);
+        if (rootNodes != null) {
+            queue.addAll(rootNodes);
+        }
+        // parentId=0 鐨勪篃瑙嗕负鏍硅妭鐐�
+        List<TechnologyBomStructure> zeroParentNodes = childrenMap.get(0L);
+        if (zeroParentNodes != null) {
+            for (TechnologyBomStructure node : zeroParentNodes) {
+                if (!queue.contains(node)) {
+                    queue.add(node);
+                }
+            }
+        }
+
+        while (!queue.isEmpty()) {
+            TechnologyBomStructure source = queue.poll();
+            if (source == null || source.getId() == null) {
+                continue;
+            }
+            // 璁$畻闇�姹傞噺 = 鐖惰妭鐐归渶姹傞噺 脳 鑷韩 unitQuantity
+            BigDecimal parentDemandedQuantity = orderQuantity;
+            Long sourceParentId = source.getParentId();
+            if (sourceParentId != null && sourceParentId != 0L) {
+                Long parentTargetId = idMap.get(sourceParentId);
+                if (parentTargetId != null) {
+                    // 鐖惰妭鐐瑰凡缁忔彃鍏ワ紝鐢ㄧ埗鑺傜偣鐨� targetId 浠庡凡鎻掑叆鍒楄〃鎵�
+                    // 杩欓噷鎴戜滑鐩存帴鐢ㄥ瓨涓嬫潵鐨勭埗鑺傜偣闇�姹傞噺
+                    TechnologyBomStructure parentSource = sourceById.get(sourceParentId);
+                    if (parentSource != null && parentSource.getDemandedQuantity() != null) {
+                        parentDemandedQuantity = parentSource.getDemandedQuantity();
+                    }
+                }
+            }
+
             ProductionBomStructure target = new ProductionBomStructure();
             target.setProductionOrderId(productionOrder.getId());
             target.setProductionOrderBomId(orderBom.getId());
@@ -446,10 +494,20 @@
             target.setProductModelId(source.getProductModelId());
             target.setTechnologyOperationId(source.getOperationId());
             target.setUnitQuantity(source.getUnitQuantity());
-            target.setDemandedQuantity(source.getUnitQuantity().multiply(orderQuantity));
+            target.setDemandedQuantity(parentDemandedQuantity.multiply(defaultDecimal(source.getUnitQuantity())));
             target.setUnit(source.getUnit());
             productionBomStructureMapper.insert(target);
             idMap.put(source.getId(), target.getId());
+            // 灏嗗綋鍓嶈妭鐐圭殑 demandedQuantity 鍥炲啓鍒� source 瀵硅薄涓婏紝渚涘瓙鑺傜偣璁$畻浣跨敤
+            source.setDemandedQuantity(target.getDemandedQuantity());
+
+            // 灏嗗瓙鑺傜偣鍔犲叆闃熷垪
+            List<TechnologyBomStructure> children = childrenMap.get(source.getId());
+            if (children != null) {
+                for (TechnologyBomStructure child : children) {
+                    queue.add(child);
+                }
+            }
         }
         return orderBom;
     }
@@ -505,9 +563,10 @@
                 .orderByDesc(ProductionOrder::getId);
     }
 
-    private String generateNextOrderNo() {
+    private String generateNextOrderNo(LocalDateTime createTime) {
         // 鐢熸垚涓嬩竴涓敓浜ц鍗曞彿
-        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        LocalDate localDate = createTime.toLocalDate();
+        String datePrefix = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
         String prefix = "SC" + datePrefix;
         ProductionOrder latestOrder = this.getOne(Wrappers.<ProductionOrder>lambdaQuery()
                 .likeRight(ProductionOrder::getNpsNo, prefix)
@@ -1027,13 +1086,57 @@
             return Collections.emptyList();
         }
 
-        List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.pickByBomId(orderBom.getId());
+        // 鏌ヨ瀹屾暣鐨凚OM缁撴瀯锛堝寘鎷牴鑺傜偣锛夛紝鐢ㄤ簬璁$畻灞傜骇闇�姹傛暟閲�
+        List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.listByBomId(orderBom.getId());
         if (bomStructureList == null || bomStructureList.isEmpty()) {
             return Collections.emptyList();
         }
 
+        // 鏌ヨ鐢熶骇璁㈠崟鑾峰彇璁㈠崟鏁伴噺
+        ProductionOrder productionOrder = productionOrderMapper.selectById(productionOrderId);
+        BigDecimal orderQuantity = productionOrder != null ? defaultDecimal(productionOrder.getQuantity()) : BigDecimal.ZERO;
+
+        // 鏋勫缓鏍戝舰缁撴瀯骞惰绠楀眰绾ч渶姹傛暟閲�
+        Map<Long, ProductionBomStructureVo> structureByIdMap = bomStructureList.stream()
+                .filter(s -> s != null && s.getId() != null)
+                .collect(Collectors.toMap(ProductionBomStructureVo::getId, s -> s));
+
+        // 鎸夊眰绾ц绠楅渶姹傛暟閲忥細瀛愮骇闇�姹傛暟閲� = 鐖剁骇闇�姹傛暟閲� 脳 瀛愮骇鍗曚綅浜у嚭鎵�闇�鏁伴噺
+        for (ProductionBomStructureVo structure : bomStructureList) {
+            if (structure == null) continue;
+
+            if (structure.getParentId() == null || structure.getParentId() == 0) {
+                // 鏍硅妭鐐癸細闇�姹傛暟閲� = 璁㈠崟鏁伴噺
+                structure.setDemandedQuantity(orderQuantity);
+            } else {
+                // 瀛愯妭鐐癸細闇�姹傛暟閲� = 鐖剁骇闇�姹傛暟閲� 脳 瀛愮骇鍗曚綅浜у嚭鎵�闇�鏁伴噺
+                ProductionBomStructureVo parent = structureByIdMap.get(structure.getParentId());
+                if (parent != null) {
+                    BigDecimal parentDemandedQty = defaultDecimal(parent.getDemandedQuantity());
+                    BigDecimal unitQuantity = defaultDecimal(structure.getUnitQuantity());
+                    structure.setDemandedQuantity(parentDemandedQty.multiply(unitQuantity));
+                }
+            }
+        }
+
+        // 杩囨护鍑洪潪鏍硅妭鐐癸紙瀹為檯棰嗘枡椤癸級
+        // 鎺掗櫎鎶曞叆鍝佷笌浜у嚭鍝佺浉鍚屼笖姣斾緥涓�1鐨勬儏鍐碉紙鑷韩鍔犲伐锛屼笉闇�瑕侀鏂欙級
+        List<ProductionBomStructureVo> childStructureList = bomStructureList.stream()
+                .filter(s -> s != null && s.getParentId() != null && s.getParentId() != 0)
+                .filter(s -> {
+                    ProductionBomStructureVo parent = structureByIdMap.get(s.getParentId());
+                    if (parent == null) {
+                        return true;
+                    }
+                    // 鎶曞叆鍝佷笌浜у嚭鍝佺浉鍚屼笖姣斾緥涓�1鏃讹紝涓嶉渶瑕侀鏂�
+                    boolean sameProduct = Objects.equals(s.getProductModelId(), parent.getProductModelId());
+                    boolean unitRatio = BigDecimal.ONE.compareTo(defaultDecimal(s.getUnitQuantity())) == 0;
+                    return !(sameProduct && unitRatio);
+                })
+                .collect(Collectors.toList());
+
         // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
-        List<Long> productModelIds = bomStructureList.stream()
+        List<Long> productModelIds = childStructureList.stream()
                 .map(ProductionBomStructureVo::getProductModelId)
                 .filter(Objects::nonNull)
                 .distinct()
@@ -1057,40 +1160,35 @@
             }
         }
 
-        Map<String, ProductionOrderPickVo> mergedPickMap = new LinkedHashMap<>();
-        for (ProductionBomStructureVo structure : bomStructureList) {
+        List<ProductionOrderPickVo> pickList = new ArrayList<>();
+        for (ProductionBomStructureVo structure : childStructureList) {
             if (structure == null || structure.getProductModelId() == null) {
                 continue;
             }
             Long productModelId = structure.getProductModelId();
-            String mergeKey = String.valueOf(structure.getTechnologyOperationId()) + "#" + productModelId;
-            ProductionOrderPickVo vo = mergedPickMap.get(mergeKey);
-            if (vo == null) {
-                vo = new ProductionOrderPickVo();
-                vo.setProductModelId(productModelId);
-                vo.setOperationName(structure.getOperationName());
-                vo.setTechnologyOperationId(structure.getTechnologyOperationId());
-                vo.setProductName(structure.getProductName());
-                vo.setModel(structure.getModel());
-                vo.setDemandedQuantity(BigDecimal.ZERO);
-                vo.setUnit(structure.getUnit());
-                List<String> batchNoList = stockBatchNoMap.get(productModelId) == null
-                        ? Collections.emptyList()
-                        : new ArrayList<>(stockBatchNoMap.get(productModelId));
-                vo.setBatchNoList(batchNoList);
-                vo.setStockQuantity(stockQuantityMap.getOrDefault(productModelId, BigDecimal.ZERO));
-                vo.setBom(true);
-                mergedPickMap.put(mergeKey, vo);
-            }
-            vo.setDemandedQuantity(defaultDecimal(vo.getDemandedQuantity()).add(defaultDecimal(structure.getDemandedQuantity())));
+            ProductionOrderPickVo vo = new ProductionOrderPickVo();
+            vo.setProductModelId(productModelId);
+            vo.setOperationName(structure.getOperationName());
+            vo.setTechnologyOperationId(structure.getTechnologyOperationId());
+            vo.setProductName(structure.getProductName());
+            vo.setModel(structure.getModel());
+            vo.setDemandedQuantity(defaultDecimal(structure.getDemandedQuantity()));
+            vo.setUnit(structure.getUnit());
+            List<String> batchNoList = stockBatchNoMap.get(productModelId) == null
+                    ? Collections.emptyList()
+                    : new ArrayList<>(stockBatchNoMap.get(productModelId));
+            vo.setBatchNoList(batchNoList);
+            vo.setStockQuantity(stockQuantityMap.getOrDefault(productModelId, BigDecimal.ZERO));
+            vo.setBom(true);
+            pickList.add(vo);
         }
-        return new ArrayList<>(mergedPickMap.values());
+        return pickList;
     }
 
     @Override
     public int updateOrder(ProductionOrderDto productionOrderDto) {
         // 鏇存柊鐢熶骇璁㈠崟涓绘暟鎹�
-        productionOrderDto.setStatus(5);
+        productionOrderDto.setStatus(ProductOrderStatusEnum.END.getCode());
         return baseMapper.updateById(productionOrderDto);
     }
 }

--
Gitblit v1.9.3