From 8817c6ab14348b360db70ad748dccb4aef692552 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期五, 23 一月 2026 16:13:40 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New' into dev_New

---
 src/main/java/com/ruoyi/production/pojo/ProductStructure.java                    |    5 +
 src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java       |   45 +++++++++-
 src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java |  152 ++++++++++++++++++++++++++++++++-----
 src/main/java/com/ruoyi/production/dto/ProductStructureDto.java                  |   14 +++
 4 files changed, 184 insertions(+), 32 deletions(-)

diff --git a/src/main/java/com/ruoyi/production/dto/ProductStructureDto.java b/src/main/java/com/ruoyi/production/dto/ProductStructureDto.java
index 24b783c..ec43eef 100644
--- a/src/main/java/com/ruoyi/production/dto/ProductStructureDto.java
+++ b/src/main/java/com/ruoyi/production/dto/ProductStructureDto.java
@@ -1,22 +1,34 @@
 package com.ruoyi.production.dto;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.ruoyi.production.pojo.ProductStructure;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.util.List;
 
 @Data
+@EqualsAndHashCode(callSuper = true)
 public class ProductStructureDto extends ProductStructure {
 
     @ApiModelProperty(value = "宸ヨ壓鍚嶇О")
     private String processName;
+
     @ApiModelProperty(value = "浜у搧鍚嶇О")
     private String productName;
+
     @ApiModelProperty(value = "浜у搧id")
     private Long productId;
 
     private String model;
 
-    private List<ProductStructure> productStructureList;
+    @TableField(exist = false)
+    private String tempId;
+
+    @TableField(exist = false)
+    private String parentTempId;
+
+    @TableField(exist = false)
+    private List<ProductStructureDto> children;
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductStructure.java b/src/main/java/com/ruoyi/production/pojo/ProductStructure.java
index de0d605..34a3ee3 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductStructure.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductStructure.java
@@ -52,5 +52,8 @@
      */
     private Long bomId;
 
-
+    /**
+     * 鐖惰妭鐐笽D
+     */
+    private Long parentId;
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
index d519593..06d4d09 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
@@ -1,19 +1,23 @@
 package com.ruoyi.production.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.pojo.ProductModel;
+import com.ruoyi.basic.service.IProductModelService;
+import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.production.dto.ProductBomDto;
-import com.ruoyi.production.dto.ProductProcessDto;
-import com.ruoyi.production.pojo.ProductBom;
 import com.ruoyi.production.mapper.ProductBomMapper;
-import com.ruoyi.production.pojo.ProductProcess;
+import com.ruoyi.production.mapper.ProductStructureMapper;
+import com.ruoyi.production.pojo.ProductBom;
+import com.ruoyi.production.pojo.ProductStructure;
 import com.ruoyi.production.service.ProductBomService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
 
 /**
  * <p>
@@ -29,12 +33,19 @@
     @Autowired
     private ProductBomMapper productBomMapper;
 
+    @Autowired
+    private IProductModelService productModelService;
+
+    @Autowired
+    private ProductStructureMapper productStructureMapper;
+
     @Override
     public IPage<ProductBomDto> listPage(Page page, ProductBomDto productBomDto) {
-        return productBomMapper.listPage(page,productBomDto);
+        return productBomMapper.listPage(page, productBomDto);
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(ProductBom productBom) {
         boolean save = productBomMapper.insert(productBom) > 0;
         if (save) {
@@ -42,6 +53,26 @@
             String no = "BM." + String.format("%05d", productBom.getId());
             productBom.setBomNo(no);
             productBomMapper.updateById(productBom);
+
+            //  鏌ヨ鍑轰骇鍝佹ā鍨嬩俊鎭�
+            if (productBom.getProductModelId() == null) {
+                throw new ServiceException("璇烽�夋嫨浜у搧妯″瀷");
+            }
+
+            ProductModel productModel = productModelService.getById(productBom.getProductModelId());
+            if (productModel == null) {
+                throw new ServiceException("閫夋嫨鐨勪骇鍝佹ā鍨嬩笉瀛樺湪");
+            }
+
+            //  娣诲姞鍒濆鐨勪骇鍝佺粨鏋�
+            ProductStructure productStructure = new ProductStructure();
+            productStructure.setProductModelId(productBom.getProductModelId());
+            productStructure.setUnit(productModel.getUnit());
+            productStructure.setUnitQuantity(BigDecimal.valueOf(1));
+            productStructure.setBomId(Long.valueOf(productBom.getId()));
+
+            productStructureMapper.insert(productStructure);
+
             return AjaxResult.success();
         }
         return AjaxResult.error();
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
index 310a723..6b43c18 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
@@ -1,51 +1,157 @@
 package com.ruoyi.production.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.dto.ProductModelDto;
-import com.ruoyi.basic.dto.ProductTreeDto;
-import com.ruoyi.basic.mapper.ProductMapper;
-import com.ruoyi.basic.mapper.ProductModelMapper;
-import com.ruoyi.basic.pojo.Product;
-import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.mapper.ProductBomMapper;
 import com.ruoyi.production.mapper.ProductStructureMapper;
 import com.ruoyi.production.pojo.ProductStructure;
 import com.ruoyi.production.service.ProductStructureService;
-import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
-@Service
-@RequiredArgsConstructor
 @Slf4j
+@Service
 public class ProductStructureServiceImpl extends ServiceImpl<ProductStructureMapper, ProductStructure> implements ProductStructureService {
 
     @Autowired
-    private  ProductStructureMapper productStructureMapper;
-
+    private ProductStructureMapper productStructureMapper;
 
 
     @Override
-    public Boolean addProductStructureDto(ProductStructureDto productStructureDto) {
-        this.remove(new QueryWrapper<ProductStructure>().lambda().eq(ProductStructure::getBomId, productStructureDto.getBomId()));
-        productStructureDto.getProductStructureList().forEach(productStructure -> {
-            productStructure.setBomId(productStructureDto.getBomId());
-        });
-        return this.saveBatch(productStructureDto.getProductStructureList());
+    @Transactional
+    public Boolean addProductStructureDto(ProductStructureDto dto) {
+
+        Long bomId = dto.getBomId();
+
+        //  灏嗘爲鎵佸钩鍖�
+        List<ProductStructureDto> flatDtoList = new ArrayList<>();
+        flattenTree(dto.getChildren(), flatDtoList);
+
+        //  鏌ヨ鏁版嵁搴撲腑宸叉湁鐨� BOM 鏁版嵁
+        List<ProductStructure> dbList = this.list(new LambdaQueryWrapper<ProductStructure>().eq(ProductStructure::getBomId, bomId));
+
+        //  鏌ユ壘宸插瓨鍦ㄧ殑鑺傜偣 - ID
+        Set<Long> frontendIds = flatDtoList.stream()
+                .map(ProductStructureDto::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+
+        //  闇�瑕佸垹闄ょ殑鑺傜偣 - ID
+        Set<Long> deleteIds = dbList.stream()
+                .map(ProductStructure::getId)
+                .filter(id -> !frontendIds.contains(id))
+                .collect(Collectors.toSet());
+
+        if (!deleteIds.isEmpty()) {
+            this.removeByIds(deleteIds);
+        }
+
+        //  鏂板 / 鏇存柊
+        List<ProductStructure> insertList = new ArrayList<>();
+        List<ProductStructure> updateList = new ArrayList<>();
+
+        // 鐢ㄤ簬鍥炲啓 parentId
+        Map<String, ProductStructure> tempEntityMap = new HashMap<>();
+
+        for (ProductStructureDto psDto : flatDtoList) {
+            ProductStructure entity = new ProductStructure();
+            BeanUtils.copyProperties(psDto, entity);
+            entity.setBomId(bomId);
+
+            if (psDto.getId() == null) {
+                // 鏂板
+                entity.setId(null);
+                entity.setParentId(null);
+                insertList.add(entity);
+                tempEntityMap.put(psDto.getTempId(), entity);
+            } else {
+                // 鏇存柊
+                updateList.add(entity);
+            }
+        }
+
+        //  鎻掑叆鏂拌妭鐐�
+        if (!insertList.isEmpty()) {
+            this.saveBatch(insertList);
+        }
+
+        //  鍥炲啓鏂板鑺傜偣 parentId
+        List<ProductStructure> parentFixList = new ArrayList<>();
+        //  鐪熷疄鐨勭埗鑺傜偣 ID
+        Long realParentId;
+        for (ProductStructureDto psDto : flatDtoList) {
+            if (psDto.getId() == null && psDto.getParentTempId() != null) {
+                ProductStructure child = tempEntityMap.get(psDto.getTempId());
+                if (tempEntityMap.containsKey(psDto.getParentTempId())) {
+                    // 鐖惰妭鐐规槸鏂拌妭鐐�
+                    realParentId = tempEntityMap.get(psDto.getParentTempId()).getId();
+                } else {
+                    // 鐖惰妭鐐规槸鑰佽妭鐐�
+                    realParentId = Long.valueOf(psDto.getParentTempId());
+                }
+
+                child.setParentId(realParentId);
+                parentFixList.add(child);
+            }
+        }
+
+        if (!parentFixList.isEmpty()) {
+            this.updateBatchById(parentFixList);
+        }
+
+        if (!updateList.isEmpty()) {
+            this.updateBatchById(updateList);
+        }
+
+        return true;
     }
+
+    /**
+     * 灏嗗墠绔紶鍏ョ殑鏍戣繘琛屾墎骞冲寲
+     *
+     * @param source 鏁版嵁鏍�
+     * @param result 鎵佸钩鍖栨暟鎹�
+     */
+    private void flattenTree(List<ProductStructureDto> source, List<ProductStructureDto> result) {
+        if (source == null) {
+            return;
+        }
+        for (ProductStructureDto node : source) {
+            result.add(node);
+            flattenTree(node.getChildren(), result);
+        }
+    }
+
 
     @Override
     public List<ProductStructureDto> listBybomId(Long bomId) {
-        List<ProductStructureDto> tree = productStructureMapper.listBybomId(bomId);
-        return tree;
+        List<ProductStructureDto> list = productStructureMapper.listBybomId(bomId);
 
+        Map<Long, ProductStructureDto> map = new HashMap<>();
+        for (ProductStructureDto node : list) {
+            node.setChildren(new ArrayList<>());
+            map.put(node.getId(), node);
+        }
+
+        List<ProductStructureDto> tree = new ArrayList<>();
+        for (ProductStructureDto node : list) {
+            Long parentId = node.getParentId();
+            if (parentId == null || parentId == 0) {
+                tree.add(node);
+            } else {
+                ProductStructureDto parent = map.get(parentId);
+                if (parent != null) {
+                    parent.getChildren().add(node);
+                }
+            }
+        }
+        return tree;
     }
+
 }

--
Gitblit v1.9.3