| | |
| | | productionOrderBomMapper.insert(orderBom); |
| | | |
| | | Map<Long, Long> idMap = new HashMap<>(); |
| | | BigDecimal lastProcessDemandedQuantity = orderQuantity; |
| | | for (TechnologyBomStructure source : structureList) { |
| | | // 子节点 parentId 需要映射成新快照节点 id,才能保留原始 BOM 层级。 |
| | | ProductionBomStructure target = new ProductionBomStructure(); |
| | |
| | | target.setProductModelId(source.getProductModelId()); |
| | | target.setTechnologyOperationId(source.getOperationId()); |
| | | target.setUnitQuantity(source.getUnitQuantity()); |
| | | target.setDemandedQuantity(lastProcessDemandedQuantity.multiply(source.getUnitQuantity())); |
| | | target.setDemandedQuantity(defaultDecimal(orderQuantity) |
| | | .multiply(defaultDecimal(source.getUnitQuantity()))); |
| | | target.setUnit(source.getUnit()); |
| | | productionBomStructureMapper.insert(target); |
| | | idMap.put(source.getId(), target.getId()); |
| | | lastProcessDemandedQuantity = target.getDemandedQuantity(); |
| | | } |
| | | return orderBom; |
| | | } |
| | |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | // 查询完整的BOM结构(包括根节点),用于计算层级需求数量 |
| | | // 查询完整的BOM结构(包括根节点),每个节点独立计算需求数量 |
| | | 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)); |
| | | } |
| | | if (structure != null) { |
| | | structure.setDemandedQuantity(orderQuantity |
| | | .multiply(defaultDecimal(structure.getUnitQuantity()))); |
| | | } |
| | | } |
| | | |
| | |
| | | .filter(Objects::nonNull) |
| | | .forEach(finishedProductModelIds::add); |
| | | |
| | | // 过滤出非根节点(实际领料项),并排除与订单成品同规格的物料(自制成品无需领料) |
| | | // 收集所有被引用为父级的节点ID:BOM从最后一道工序往里配置前一道工序, |
| | | // 中间节点是上一道工序的产出(自制),只有每条分支最里层的叶子节点才是真正需要领用的物料。 |
| | | Set<Long> parentNodeIds = bomStructureList.stream() |
| | | .filter(s -> s != null && s.getParentId() != null && s.getParentId() != 0) |
| | | .map(ProductionBomStructureVo::getParentId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | // 过滤出叶子节点(实际领料项):非根节点、非中间节点,并排除与订单成品同规格的物料(自制成品无需领料) |
| | | List<ProductionBomStructureVo> childStructureList = bomStructureList.stream() |
| | | .filter(s -> s != null && s.getParentId() != null && s.getParentId() != 0) |
| | | .filter(s -> s.getId() == null || !parentNodeIds.contains(s.getId())) |
| | | .filter(s -> s.getProductModelId() == null || !finishedProductModelIds.contains(s.getProductModelId())) |
| | | .collect(Collectors.toList()); |
| | | |