| | |
| | | import com.ruoyi.technology.pojo.TechnologyOperationParam; |
| | | import com.ruoyi.technology.pojo.TechnologyParam; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | * @author 芯导软件(江苏)有限公司 |
| | | * @since 2026-04-21 03:55:52 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | @RequiredArgsConstructor() |
| | | public class ProductionBomStructureServiceImpl extends ServiceImpl<ProductionBomStructureMapper, ProductionBomStructure> implements ProductionBomStructureService { |
| | |
| | | entity.setProductionOrderBomId(orderBomId); |
| | | if (item.getId() == null) { |
| | | entity.setParentId(null); |
| | | // 新增节点的需求量由后端按BOM树形结构重新计算,不清空可能导致前端传的值溢出 |
| | | entity.setDemandedQuantity(null); |
| | | entity.setId(null); |
| | | insertList.add(entity); |
| | | tempEntityMap.put(item.getTempId(), entity); |
| | | } else { |
| | |
| | | |
| | | // 批量新增,拿到数据库生成的真实ID |
| | | if (!insertList.isEmpty()) { |
| | | for (ProductionBomStructure entity : insertList) { |
| | | log.info("准备新增BOM结构节点: productModelId={}, technologyOperationId={}, unitQuantity={}, demandedQuantity={}, unit={}", |
| | | entity.getProductModelId(), entity.getTechnologyOperationId(), |
| | | entity.getUnitQuantity(), entity.getDemandedQuantity(), entity.getUnit()); |
| | | } |
| | | this.saveBatch(insertList); |
| | | } |
| | | |
| | |
| | | if (structureList == null || structureList.isEmpty()) { |
| | | return; |
| | | } |
| | | List<ProductionBomStructure> updateList = new ArrayList<>(); |
| | | BigDecimal lastProcessDemandedQuantity = orderQuantity; |
| | | log.info("开始按BOM树形结构计算需求量,订单数量={}, BOM节点总数={}", orderQuantity, structureList.size()); |
| | | // 构建 id → structure 映射和 parentId → children 映射 |
| | | Map<Long, ProductionBomStructure> structureById = new HashMap<>(); |
| | | Map<Long, List<ProductionBomStructure>> childrenMap = new LinkedHashMap<>(); |
| | | for (ProductionBomStructure structure : structureList) { |
| | | if (structure == null || structure.getId() == null) { |
| | | continue; |
| | | } |
| | | structureById.put(structure.getId(), structure); |
| | | Long parentId = structure.getParentId(); |
| | | childrenMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(structure); |
| | | } |
| | | |
| | | BigDecimal demandedQuantity = lastProcessDemandedQuantity.multiply(defaultDecimal(structure.getUnitQuantity())); |
| | | // if (compareDecimal(structure.getDemandedQuantity(), demandedQuantity) == 0) { |
| | | // continue; |
| | | // } |
| | | List<ProductionBomStructure> updateList = new ArrayList<>(); |
| | | // 从根节点开始,按树形层级逐层计算需求量 |
| | | // 根节点 parentId 为 null 或 0 |
| | | Deque<Long> queue = new ArrayDeque<>(); |
| | | List<ProductionBomStructure> rootNodes = childrenMap.get(null); |
| | | if (rootNodes != null) { |
| | | for (ProductionBomStructure root : rootNodes) { |
| | | queue.add(root.getId()); |
| | | } |
| | | } |
| | | // parentId=0 的也视为根节点 |
| | | List<ProductionBomStructure> zeroParentNodes = childrenMap.get(0L); |
| | | if (zeroParentNodes != null) { |
| | | for (ProductionBomStructure root : zeroParentNodes) { |
| | | if (!queue.contains(root.getId())) { |
| | | queue.add(root.getId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | while (!queue.isEmpty()) { |
| | | Long nodeId = queue.poll(); |
| | | ProductionBomStructure node = structureById.get(nodeId); |
| | | if (node == null) { |
| | | continue; |
| | | } |
| | | // 计算当前节点的需求数量 = 父节点需求量 × 自身 unitQuantity |
| | | // 根节点:需求量 = 订单数量 × unitQuantity |
| | | BigDecimal parentDemandedQuantity = orderQuantity; |
| | | Long parentId = node.getParentId(); |
| | | if (parentId != null && parentId != 0L) { |
| | | ProductionBomStructure parent = structureById.get(parentId); |
| | | if (parent != null && parent.getDemandedQuantity() != null) { |
| | | parentDemandedQuantity = parent.getDemandedQuantity(); |
| | | } |
| | | } |
| | | BigDecimal demandedQuantity = parentDemandedQuantity.multiply(defaultDecimal(node.getUnitQuantity())); |
| | | |
| | | log.info("BOM需求量计算: nodeId={}, parentId={}, parentDemandedQuantity={}, unitQuantity={}, demandedQuantity={}", |
| | | node.getId(), node.getParentId(), parentDemandedQuantity, |
| | | defaultDecimal(node.getUnitQuantity()), demandedQuantity); |
| | | |
| | | ProductionBomStructure update = new ProductionBomStructure(); |
| | | update.setId(structure.getId()); |
| | | update.setId(node.getId()); |
| | | update.setDemandedQuantity(demandedQuantity); |
| | | updateList.add(update); |
| | | structure.setDemandedQuantity(demandedQuantity); |
| | | lastProcessDemandedQuantity = demandedQuantity; |
| | | node.setDemandedQuantity(demandedQuantity); |
| | | |
| | | // 将子节点加入队列 |
| | | List<ProductionBomStructure> children = childrenMap.get(nodeId); |
| | | if (children != null) { |
| | | for (ProductionBomStructure child : children) { |
| | | queue.add(child.getId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!updateList.isEmpty()) { |
| | | this.updateBatchById(updateList); |
| | | } |