From 0083c99ddae4d50c51b27353b622804a1d7b26e4 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 23 一月 2026 16:02:08 +0800
Subject: [PATCH] refactor: BOM产品结构保存与查看进行树形处理
---
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