| | |
| | | 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; |
| | | } |
| | |
| | | private BigDecimal defaultDecimal(BigDecimal value) { |
| | | // 将空数量兜底为0,避免空指针异常 |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | /** |
| | | * 批次号按前缀日期升序排序(格式如 20260703-ed01-001,日期早的在前) |
| | | */ |
| | | private void sortBatchNoList(List<String> batchNoList) { |
| | | if (batchNoList == null || batchNoList.size() < 2) { |
| | | return; |
| | | } |
| | | batchNoList.sort(Comparator |
| | | .comparingLong(this::batchDateKey) |
| | | .thenComparing(batchNo -> batchNo == null ? "" : batchNo)); |
| | | } |
| | | |
| | | /** |
| | | * 提取批次号开头的数字作为排序键(yyyyMMdd),无数字时放到最后 |
| | | */ |
| | | private long batchDateKey(String batchNo) { |
| | | if (batchNo == null) { |
| | | return Long.MAX_VALUE; |
| | | } |
| | | String trimmed = batchNo.trim(); |
| | | int end = 0; |
| | | while (end < trimmed.length() && Character.isDigit(trimmed.charAt(end))) { |
| | | end++; |
| | | } |
| | | if (end == 0) { |
| | | return Long.MAX_VALUE; |
| | | } |
| | | try { |
| | | return Long.parseLong(trimmed.substring(0, end)); |
| | | } catch (NumberFormatException e) { |
| | | return Long.MAX_VALUE; |
| | | } |
| | | } |
| | | |
| | | private void validateAndFillOrder(ProductionOrder productionOrder, ProductionOrder oldOrder) { |
| | |
| | | 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()))); |
| | | } |
| | | } |
| | | |
| | |
| | | List<String> batchNoList = stockBatchNoMap.get(productModelId) == null |
| | | ? Collections.emptyList() |
| | | : new ArrayList<>(stockBatchNoMap.get(productModelId)); |
| | | sortBatchNoList(batchNoList); |
| | | vo.setBatchNoList(batchNoList); |
| | | vo.setStockQuantity(stockQuantityMap.getOrDefault(productModelId, BigDecimal.ZERO)); |
| | | vo.setBom(true); |