From bd86068dd507b7ee076456ab71aa03394730076f Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期五, 15 五月 2026 17:25:46 +0800
Subject: [PATCH] fix:1.工单产出数量根据bom需求数量赋值
---
src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 204 insertions(+), 1 deletions(-)
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
index 35cdb27..2bded77 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
@@ -1,18 +1,29 @@
package com.ruoyi.production.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.production.bean.dto.ProductionBomStructureDto;
import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
import com.ruoyi.production.mapper.ProductionBomStructureMapper;
+import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
+import com.ruoyi.production.mapper.ProductionOrderBomMapper;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper;
import com.ruoyi.production.pojo.ProductionBomStructure;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionOrderBom;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
import com.ruoyi.production.service.ProductionBomStructureService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.math.BigDecimal;
import java.util.*;
+import java.util.stream.Collectors;
/**
* <p>
@@ -26,7 +37,11 @@
@RequiredArgsConstructor()
public class ProductionBomStructureServiceImpl extends ServiceImpl<ProductionBomStructureMapper, ProductionBomStructure> implements ProductionBomStructureService {
- private final ProductionBomStructureMapper productionBomStructureMapper;
+ private final ProductionBomStructureMapper productionBomStructureMapper;
+ private final ProductionOrderBomMapper productionOrderBomMapper;
+ private final ProductionOrderMapper productionOrderMapper;
+ private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
+ private final ProductionOperationTaskMapper productionOperationTaskMapper;
/**
* 鏍规嵁BOM鏌ヨ骞剁粍瑁呯粨鏋勬爲銆�
@@ -136,9 +151,197 @@
if (!updateList.isEmpty()) {
this.updateBatchById(updateList);
}
+ syncDemandedQuantityAndTaskPlanQuantity(orderBomId, dto.getProductionOrderId());
return true;
}
+ private void syncDemandedQuantityAndTaskPlanQuantity(Long orderBomId, Long productionOrderId) {
+ if (orderBomId == null) {
+ return;
+ }
+ ProductionOrderBom orderBom = productionOrderBomMapper.selectById(orderBomId);
+ if (orderBom == null) {
+ return;
+ }
+ Long currentProductionOrderId = productionOrderId != null ? productionOrderId : orderBom.getProductionOrderId();
+ if (currentProductionOrderId == null) {
+ return;
+ }
+ ProductionOrder productionOrder = productionOrderMapper.selectById(currentProductionOrderId);
+ if (productionOrder == null) {
+ return;
+ }
+
+ BigDecimal orderQuantity = defaultDecimal(productionOrder.getQuantity());
+ List<ProductionBomStructure> structureList = this.list(
+ Wrappers.<ProductionBomStructure>lambdaQuery()
+ .eq(ProductionBomStructure::getProductionOrderBomId, orderBomId)
+ .orderByAsc(ProductionBomStructure::getId));
+ syncStructureDemandedQuantity(structureList, orderQuantity);
+ syncTaskPlanQuantity(
+ currentProductionOrderId,
+ structureList,
+ orderQuantity,
+ orderBom.getProductModelId() != null ? orderBom.getProductModelId() : productionOrder.getProductModelId());
+ }
+
+ private void syncStructureDemandedQuantity(List<ProductionBomStructure> structureList, BigDecimal orderQuantity) {
+ if (structureList == null || structureList.isEmpty()) {
+ return;
+ }
+ List<ProductionBomStructure> updateList = new ArrayList<>();
+ for (ProductionBomStructure structure : structureList) {
+ if (structure == null || structure.getId() == null) {
+ continue;
+ }
+ BigDecimal demandedQuantity = defaultDecimal(structure.getUnitQuantity()).multiply(orderQuantity);
+ if (compareDecimal(structure.getDemandedQuantity(), demandedQuantity) == 0) {
+ continue;
+ }
+ ProductionBomStructure update = new ProductionBomStructure();
+ update.setId(structure.getId());
+ update.setDemandedQuantity(demandedQuantity);
+ updateList.add(update);
+ structure.setDemandedQuantity(demandedQuantity);
+ }
+ if (!updateList.isEmpty()) {
+ this.updateBatchById(updateList);
+ }
+ }
+
+ private void syncTaskPlanQuantity(Long productionOrderId,
+ List<ProductionBomStructure> structureList,
+ BigDecimal orderQuantity,
+ Long rootProductModelId) {
+ List<ProductionOperationTask> taskList = productionOperationTaskMapper.selectList(
+ Wrappers.<ProductionOperationTask>lambdaQuery()
+ .eq(ProductionOperationTask::getProductionOrderId, productionOrderId)
+ .orderByAsc(ProductionOperationTask::getId));
+ if (taskList == null || taskList.isEmpty()) {
+ return;
+ }
+ Set<Long> routingOperationIds = taskList.stream()
+ .map(ProductionOperationTask::getProductionOrderRoutingOperationId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ if (routingOperationIds.isEmpty()) {
+ return;
+ }
+ Map<Long, ProductionOrderRoutingOperation> routingOperationMap = productionOrderRoutingOperationMapper
+ .selectBatchIds(routingOperationIds)
+ .stream()
+ .filter(item -> item != null && item.getId() != null)
+ .collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, item -> item, (left, right) -> left));
+ // Keep task plan quantities aligned with the same order BOM snapshot demand used during snapshot creation.
+ Map<String, BigDecimal> demandedQuantityMap = buildOperationDemandedQuantityMap(structureList, rootProductModelId);
+ for (ProductionOperationTask task : taskList) {
+ if (task == null || task.getId() == null || task.getProductionOrderRoutingOperationId() == null) {
+ continue;
+ }
+ ProductionOrderRoutingOperation routingOperation = routingOperationMap.get(task.getProductionOrderRoutingOperationId());
+ if (routingOperation == null || routingOperation.getTechnologyRoutingOperationId() == null) {
+ continue;
+ }
+ BigDecimal planQuantity = resolveTaskPlanQuantity(
+ routingOperation,
+ demandedQuantityMap,
+ orderQuantity,
+ rootProductModelId);
+ if (compareDecimal(task.getPlanQuantity(), planQuantity) == 0) {
+ continue;
+ }
+ ProductionOperationTask update = new ProductionOperationTask();
+ update.setId(task.getId());
+ update.setPlanQuantity(planQuantity);
+ productionOperationTaskMapper.updateById(update);
+ }
+ }
+ private Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> structureList,
+ Long rootProductModelId) {
+ if (structureList == null || structureList.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map<Long, ProductionBomStructure> structureById = structureList.stream()
+ .filter(item -> item != null && item.getId() != null)
+ .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
+ Map<String, BigDecimal> demandedQuantityMap = new HashMap<>();
+ Set<String> mergedOutputNodeKeySet = new HashSet<>();
+ for (ProductionBomStructure bomStructure : structureList) {
+ if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) {
+ continue;
+ }
+ // Resolve the output node first, then read the output node demand for the task plan quantity.
+ ProductionBomStructure outputNode = resolveOperationOutputNode(bomStructure, structureById);
+ Long outputProductModelId = resolveOutputProductModelId(outputNode, rootProductModelId);
+ if (outputProductModelId == null) {
+ continue;
+ }
+ String mergedOutputNodeKey = buildOperationOutputNodeKey(
+ bomStructure.getTechnologyOperationId(),
+ outputNode == null ? null : outputNode.getId(),
+ outputProductModelId);
+ if (!mergedOutputNodeKeySet.add(mergedOutputNodeKey)) {
+ continue;
+ }
+ // Multiple input rows can point to the same output node, so only count that output demand once.
+ String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId);
+ demandedQuantityMap.merge(key, defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity()), BigDecimal::add);
+ }
+ return demandedQuantityMap;
+ }
+ private BigDecimal resolveTaskPlanQuantity(ProductionOrderRoutingOperation routingOperation,
+ Map<String, BigDecimal> demandedQuantityMap,
+ BigDecimal orderQuantity,
+ Long rootProductModelId) {
+ if (routingOperation == null || demandedQuantityMap == null || demandedQuantityMap.isEmpty()) {
+ return orderQuantity;
+ }
+ Long outputProductModelId = routingOperation.getProductModelId() != null
+ ? routingOperation.getProductModelId()
+ : rootProductModelId;
+ String key = buildOperationDemandedQuantityKey(
+ routingOperation.getTechnologyOperationId(),
+ outputProductModelId);
+ BigDecimal planQuantity = demandedQuantityMap.get(key);
+ return planQuantity != null ? planQuantity : orderQuantity;
+ }
+
+ private String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) {
+ return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId);
+ }
+
+ private String buildOperationOutputNodeKey(Long operationId, Long outputNodeId, Long outputProductModelId) {
+ return String.valueOf(operationId) + "#" + String.valueOf(outputNodeId) + "#" + String.valueOf(outputProductModelId);
+ }
+
+ private ProductionBomStructure resolveOperationOutputNode(ProductionBomStructure bomStructure,
+ Map<Long, ProductionBomStructure> structureById) {
+ if (bomStructure == null) {
+ return null;
+ }
+ // The root node is the first output node; other rows use their direct parent as the current operation output.
+ if (bomStructure.getParentId() == null) {
+ return bomStructure;
+ }
+ ProductionBomStructure parent = structureById.get(bomStructure.getParentId());
+ return parent != null ? parent : bomStructure;
+ }
+ private Long resolveOutputProductModelId(ProductionBomStructure outputNode,
+ Long rootProductModelId) {
+ if (outputNode == null) {
+ return rootProductModelId;
+ }
+ return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId;
+ }
+
+ private BigDecimal defaultDecimal(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
+ }
+
+ private int compareDecimal(BigDecimal left, BigDecimal right) {
+ return defaultDecimal(left).compareTo(defaultDecimal(right));
+ }
+
/**
* 灏嗘爲褰㈢粨鏋勬媿骞虫垚鍒楄〃锛屼究浜庣粺涓�淇濆瓨銆�
*/
--
Gitblit v1.9.3