From a8188d1675594d7756eddccc3eda60601325942a Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期二, 20 十月 2026 15:22:35 +0800
Subject: [PATCH] feat: 工序添加是否领料,用于后续生产订单领料
---
src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java | 322 +++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 237 insertions(+), 85 deletions(-)
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
index ad20fe5..43a89a6 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -22,6 +22,8 @@
import com.ruoyi.production.bean.vo.ProductionOrderVo;
import com.ruoyi.production.bean.vo.ProductionPlanVo;
import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo;
+import com.ruoyi.production.bean.vo.ProcessRouteStatusVo;
+import com.ruoyi.production.bean.vo.ProductionOrderProcessTaskVo;
import com.ruoyi.production.enums.ProductOrderStatusEnum;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
@@ -32,6 +34,7 @@
import com.ruoyi.quality.pojo.QualityInspectFile;
import com.ruoyi.quality.pojo.QualityInspectParam;
import com.ruoyi.production.service.ProductionOrderService;
+import com.ruoyi.production.util.TaskPlanQuantityUtil;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.stock.mapper.StockInventoryMapper;
@@ -59,6 +62,7 @@
private final ProductionOperationTaskMapper productionOperationTaskMapper;
private final ProductionOrderBomMapper productionOrderBomMapper;
private final ProductionBomStructureMapper productionBomStructureMapper;
+ private final ProductionOrderMapper productionOrderMapper;
private final ProductionProductMainMapper productionProductMainMapper;
private final ProductionProductOutputMapper productionProductOutputMapper;
private final ProductionOrderPickMapper productionOrderPickMapper;
@@ -85,6 +89,7 @@
// 鍒嗛〉鏌ヨ鐢熶骇璁㈠崟
Page<ProductionOrderVo> result = (Page<ProductionOrderVo>) baseMapper.pageProductionOrder(page, dto);
fillProductImages(result.getRecords());
+ fillProcessRouteStatus(result.getRecords());
return result;
}
@@ -93,6 +98,7 @@
// 鏌ヨ鐢熶骇璁㈠崟鍒楄〃
List<ProductionOrderVo> records = baseMapper.listProductionOrder(dto);
fillProductImages(records);
+ fillProcessRouteStatus(records);
return records;
}
@@ -132,7 +138,7 @@
|| !Objects.equals(oldOrder.getProductModelId(), productionOrder.getProductModelId())
|| compareDecimal(oldOrder.getQuantity(), productionOrder.getQuantity()) != 0
|| productionOrderRoutingMapper.selectCount(Wrappers.<ProductionOrderRouting>lambdaQuery()
- .eq(ProductionOrderRouting::getProductionOrderId, productionOrder.getId())) == 0);
+ .eq(ProductionOrderRouting::getProductionOrderId, productionOrder.getId())) == 0);
if (needSync) {
syncProductionOrderSnapshot(productionOrder.getId());
}
@@ -245,9 +251,22 @@
.eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId())
.orderByDesc(TechnologyRoutingOperation::getDragSort)
.orderByDesc(TechnologyRoutingOperation::getId));
- Map<String, BigDecimal> operationDemandedQuantityMap = buildOperationDemandedQuantityMap(technologyRouting, productionOrder);
+ // 宸ュ崟璁″垝鏁伴噺鐩存帴浣跨敤璁㈠崟 BOM 蹇収涓殑闇�姹傞噺锛岄伩鍏嶄笌 BOM 椤甸潰灞曠ず鍙e緞涓嶄竴鑷淬��
+ Long rootProductModelId = orderBom != null && orderBom.getProductModelId() != null
+ ? orderBom.getProductModelId()
+ : productionOrder.getProductModelId();
+ List<ProductionBomStructure> orderBomStructureList = orderBom == null || orderBom.getId() == null
+ ? Collections.emptyList()
+ : productionBomStructureMapper.selectList(
+ Wrappers.<ProductionBomStructure>lambdaQuery()
+ .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId())
+ .orderByAsc(ProductionBomStructure::getId));
+ Map<String, BigDecimal> operationDemandedQuantityMap =
+ TaskPlanQuantityUtil.buildOperationDemandedQuantityMap(orderBomStructureList, rootProductModelId);
+ Map<Long, Set<Long>> operationOutputProductModelMap =
+ TaskPlanQuantityUtil.buildOperationOutputProductModelMap(orderBomStructureList, rootProductModelId);
Map<Long, String> operationNameMap = technologyOperationMapper.selectBatchIds(
- // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
+ // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
routingOperations.stream()
.map(TechnologyRoutingOperation::getTechnologyOperationId)
.filter(Objects::nonNull)
@@ -265,7 +284,12 @@
targetOperation.setProductionOrderId(productionOrder.getId());
targetOperation.setTechnologyRoutingOperationId(sourceOperation.getId());
targetOperation.setOrderRoutingId(orderRouting.getId());
- targetOperation.setProductModelId(sourceOperation.getProductModelId());
+ Long outputProductModelId = TaskPlanQuantityUtil.resolveOperationOutputProductModelId(
+ sourceOperation.getTechnologyOperationId(),
+ sourceOperation.getProductModelId(),
+ operationOutputProductModelMap,
+ rootProductModelId);
+ targetOperation.setProductModelId(outputProductModelId);
targetOperation.setDragSort(sourceOperation.getDragSort());
targetOperation.setIsProduction(sourceOperation.getIsProduction());
targetOperation.setIsQuality(sourceOperation.getIsQuality());
@@ -279,7 +303,11 @@
ProductionOperationTask task = new ProductionOperationTask();
task.setProductionOrderRoutingOperationId(targetOperation.getId());
task.setProductionOrderId(productionOrder.getId());
- task.setPlanQuantity(resolveTaskPlanQuantity(sourceOperation, operationDemandedQuantityMap, productionOrder));
+ task.setPlanQuantity(TaskPlanQuantityUtil.resolveTaskPlanQuantity(
+ targetOperation,
+ operationDemandedQuantityMap,
+ productionOrder.getQuantity(),
+ rootProductModelId));
task.setCompleteQuantity(BigDecimal.ZERO);
task.setWorkOrderNo(generateNextTaskNo());
task.setStatus(2);
@@ -314,72 +342,6 @@
return syncedParamCount;
}
- private Map<String, BigDecimal> buildOperationDemandedQuantityMap(TechnologyRouting technologyRouting,
- ProductionOrder productionOrder) {
- if (technologyRouting == null || technologyRouting.getBomId() == null) {
- return Collections.emptyMap();
- }
- BigDecimal orderQuantity = defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity());
- List<TechnologyBomStructure> bomStructures = technologyBomStructureMapper.selectList(
- Wrappers.<TechnologyBomStructure>lambdaQuery()
- .eq(TechnologyBomStructure::getBomId, technologyRouting.getBomId())
- .isNotNull(TechnologyBomStructure::getOperationId)
- .orderByAsc(TechnologyBomStructure::getId));
- if (bomStructures.isEmpty()) {
- return Collections.emptyMap();
- }
-
- Map<Long, TechnologyBomStructure> structureById = bomStructures.stream()
- .filter(item -> item != null && item.getId() != null)
- .collect(Collectors.toMap(TechnologyBomStructure::getId, item -> item, (left, right) -> left));
- Map<String, BigDecimal> demandedQuantityMap = new HashMap<>();
- for (TechnologyBomStructure bomStructure : bomStructures) {
- if (bomStructure == null || bomStructure.getOperationId() == null) {
- continue;
- }
- BigDecimal unitQuantity = bomStructure.getUnitQuantity();
- if (unitQuantity == null) {
- continue;
- }
- Long outputProductModelId = resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId());
- String key = buildOperationDemandedQuantityKey(bomStructure.getOperationId(), outputProductModelId);
- demandedQuantityMap.merge(key, unitQuantity.multiply(orderQuantity), BigDecimal::add);
- }
- return demandedQuantityMap;
- }
-
- private BigDecimal resolveTaskPlanQuantity(TechnologyRoutingOperation sourceOperation,
- Map<String, BigDecimal> operationDemandedQuantityMap,
- ProductionOrder productionOrder) {
- if (sourceOperation == null || operationDemandedQuantityMap == null || operationDemandedQuantityMap.isEmpty()) {
- return defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity());
- }
- String key = buildOperationDemandedQuantityKey(sourceOperation.getTechnologyOperationId(), sourceOperation.getProductModelId());
- BigDecimal planQuantity = operationDemandedQuantityMap.get(key);
- return planQuantity != null ? planQuantity : defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity());
- }
-
- private String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) {
- return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId);
- }
-
- private Long resolveOutputProductModelId(TechnologyBomStructure bomStructure,
- Map<Long, TechnologyBomStructure> structureById,
- Long routingProductModelId) {
- if (bomStructure == null) {
- return routingProductModelId;
- }
- Long parentId = bomStructure.getParentId();
- if (parentId == null) {
- return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
- }
- TechnologyBomStructure parent = structureById.get(parentId);
- if (parent != null && parent.getProductModelId() != null) {
- return parent.getProductModelId();
- }
- return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
- }
-
private ProductionOrderBom syncProductionOrderBomSnapshot(ProductionOrder productionOrder, TechnologyRouting technologyRouting) {
// 鍚屾璁㈠崟BOM蹇収缁撴瀯
if (technologyRouting.getBomId() == null) {
@@ -409,6 +371,9 @@
productionOrderBomMapper.insert(orderBom);
Map<Long, Long> idMap = new HashMap<>();
+ Map<Long, Boolean> operationPickMap = loadOperationPickMap(structureList.stream()
+ .map(TechnologyBomStructure::getOperationId)
+ .collect(Collectors.toList()));
for (TechnologyBomStructure source : structureList) {
// 瀛愯妭鐐� parentId 闇�瑕佹槧灏勬垚鏂板揩鐓ц妭鐐� id锛屾墠鑳戒繚鐣欏師濮� BOM 灞傜骇銆�
ProductionBomStructure target = new ProductionBomStructure();
@@ -417,8 +382,10 @@
target.setParentId(source.getParentId() == null ? null : idMap.get(source.getParentId()));
target.setProductModelId(source.getProductModelId());
target.setTechnologyOperationId(source.getOperationId());
+ target.setIsPick(operationPickMap.getOrDefault(source.getOperationId(), Boolean.FALSE));
target.setUnitQuantity(source.getUnitQuantity());
- target.setDemandedQuantity(source.getUnitQuantity().multiply(orderQuantity));
+ target.setDemandedQuantity(defaultDecimal(orderQuantity)
+ .multiply(defaultDecimal(source.getUnitQuantity())));
target.setUnit(source.getUnit());
productionBomStructureMapper.insert(target);
idMap.put(source.getId(), target.getId());
@@ -426,10 +393,30 @@
return orderBom;
}
+ /**
+ * 鎵归噺璇诲彇宸ュ簭鐨勨�滄槸鍚﹂鏂欌�濇爣璁帮紝閬垮厤BOM蹇収閫愯鏌ヨ宸ュ簭琛ㄣ��
+ */
+ private Map<Long, Boolean> loadOperationPickMap(List<Long> technologyOperationIds) {
+ if (technologyOperationIds == null || technologyOperationIds.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Set<Long> operationIdSet = technologyOperationIds.stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ if (operationIdSet.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ return technologyOperationMapper.selectBatchIds(operationIdSet).stream()
+ .filter(item -> item != null && item.getId() != null)
+ .collect(Collectors.toMap(TechnologyOperation::getId,
+ item -> Boolean.TRUE.equals(item.getIsPick()),
+ (left, right) -> left));
+ }
+
private void clearProductionSnapshot(Long productionOrderId) {
// 娓呯悊璁㈠崟宸茬敓鎴愮殑宸ヨ壓涓嶣OM蹇収鏁版嵁
boolean hasPickRecord = productionOrderPickRecordMapper.selectCount(
- // 鏌ヨ骞跺噯澶囦笟鍔℃暟鎹�
+ // 鏌ヨ骞跺噯澶囦笟鍔℃暟鎹�
Wrappers.<ProductionOrderPickRecord>lambdaQuery()
.eq(ProductionOrderPickRecord::getProductionOrderId, productionOrderId)) > 0;
// 鍙傛暟涓庡墠缃潯浠舵牎楠�
@@ -439,7 +426,7 @@
List<Long> taskIds = productionOperationTaskMapper.selectList(
Wrappers.<ProductionOperationTask>lambdaQuery()
.eq(ProductionOperationTask::getProductionOrderId, productionOrderId))
- // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
+ // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
.stream().map(ProductionOperationTask::getId).collect(Collectors.toList());
if (!taskIds.isEmpty()) {
// 宸叉湁鎶ュ伐璁板綍璇存槑璁㈠崟宸插紑宸ワ紝姝ゆ椂涓嶅厑璁稿啀閲嶅缓蹇収銆�
@@ -519,6 +506,40 @@
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) {
@@ -781,6 +802,43 @@
}
}
+ private void fillProcessRouteStatus(List<ProductionOrderVo> records) {
+ if (records == null || records.isEmpty()) {
+ return;
+ }
+ List<Long> orderIds = records.stream()
+ .map(ProductionOrderVo::getId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+ if (orderIds.isEmpty()) {
+ return;
+ }
+
+ List<ProductionOrderProcessTaskVo> tasks = productionOperationTaskMapper.listProcessStatusByOrderIds(orderIds);
+ Map<Long, List<ProcessRouteStatusVo>> statusMap = new LinkedHashMap<>();
+ if (tasks != null) {
+ for (ProductionOrderProcessTaskVo task : tasks) {
+ if (task == null || task.getProductionOrderId() == null) {
+ continue;
+ }
+ ProcessRouteStatusVo status = new ProcessRouteStatusVo();
+ status.setName(task.getOperationName() != null && !task.getOperationName().isBlank()
+ ? task.getOperationName()
+ : "鏈煡宸ュ簭");
+ BigDecimal percentage = task.getCompletionStatus() == null
+ ? BigDecimal.ZERO
+ : task.getCompletionStatus();
+ status.setPercentage(percentage);
+ statusMap.computeIfAbsent(task.getProductionOrderId(), key -> new ArrayList<>()).add(status);
+ }
+ }
+
+ for (ProductionOrderVo record : records) {
+ record.setProcessRouteStatus(statusMap.getOrDefault(record.getId(), Collections.emptyList()));
+ }
+ }
+
private StorageBlobVO toStorageBlobVO(StorageBlob blob) {
// 灏嗗瓨鍌ㄦ枃浠跺璞¤浆鎹负VO
StorageBlobVO vo = BeanUtil.copyProperties(blob, StorageBlobVO.class);
@@ -808,11 +866,20 @@
new Page<ProductionOperationTaskVo>(1, -1), taskQuery);
List<ProductionOperationTaskVo> workOrderList = workOrderPage == null || workOrderPage.getRecords() == null
? Collections.emptyList()
- // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
+ // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
: workOrderPage.getRecords().stream()
.filter(Objects::nonNull)
- .sorted(Comparator.comparing(ProductionOperationTaskVo::getId, Comparator.nullsLast(Comparator.naturalOrder())))
.toList();
+ if (!workOrderList.isEmpty()) {
+ // 宸ュ簭杩涘害闇�瑕佹寜宸ヨ壓璺嚎宸ュ簭椤哄簭锛坉rag_sort 鍗囧簭锛変粠宸﹀埌鍙冲睍绀猴紝浠诲姟 id 浠呬綔涓哄厹搴曟帓搴�
+ Map<Long, Integer> routingOperationDragSortMap = loadRoutingOperationDragSortMap(workOrderList);
+ Comparator<ProductionOperationTaskVo> workOrderComparator = Comparator
+ .comparing((ProductionOperationTaskVo task) -> routingOperationDragSortMap.get(task.getProductionOrderRoutingOperationId()),
+ Comparator.nullsLast(Comparator.<Integer>naturalOrder()))
+ .thenComparing(ProductionOperationTaskVo::getId,
+ Comparator.nullsLast(Comparator.<Long>naturalOrder()));
+ workOrderList = workOrderList.stream().sorted(workOrderComparator).toList();
+ }
if (workOrderList.isEmpty()) {
detailVo.setWorkOrderList(Collections.emptyList());
return detailVo;
@@ -824,7 +891,7 @@
.collect(Collectors.toList());
List<ProductionProductMain> reportMainList = workOrderIdList.isEmpty()
? Collections.emptyList()
- // 鏌ヨ骞跺噯澶囦笟鍔℃暟鎹�
+ // 鏌ヨ骞跺噯澶囦笟鍔℃暟鎹�
: productionProductMainMapper.selectList(
Wrappers.<ProductionProductMain>lambdaQuery()
.in(ProductionProductMain::getProductionOperationTaskId, workOrderIdList)
@@ -855,12 +922,10 @@
if (reportOutput == null) {
continue;
}
- Long reportMainId = reportOutput.getProductionProductMainId() != null
- ? reportOutput.getProductionProductMainId()
- : reportOutput.getProductMainId();
- if (reportMainId == null) {
+ if (reportOutput.getProductionProductMainId() == null) {
continue;
}
+ Long reportMainId = reportOutput.getProductionProductMainId();
reportOutputMap.computeIfAbsent(reportMainId, k -> new ArrayList<>()).add(reportOutput);
}
@@ -963,6 +1028,23 @@
return detailVo;
}
+ /**
+ * 鏌ヨ宸ュ崟瀵瑰簲宸ヨ壓璺嚎宸ュ簭鐨勬嫋鍔ㄦ帓搴忥紝鐢ㄤ簬鎸夊伐搴忓厛鍚庨『搴忓睍绀哄伐搴忚繘搴�
+ */
+ private Map<Long, Integer> loadRoutingOperationDragSortMap(List<ProductionOperationTaskVo> workOrderList) {
+ Set<Long> routingOperationIds = workOrderList.stream()
+ .map(ProductionOperationTaskVo::getProductionOrderRoutingOperationId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ if (routingOperationIds.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ return productionOrderRoutingOperationMapper.selectBatchIds(routingOperationIds).stream()
+ .filter(Objects::nonNull)
+ .filter(operation -> operation.getId() != null && operation.getDragSort() != null)
+ .collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, ProductionOrderRoutingOperation::getDragSort, (a, b) -> a));
+ }
+
private Long resolveProductionOrderId(ProductionOrderDto dto) {
// 浠庡叆鍙備腑瑙f瀽鐢熶骇璁㈠崟ID骞舵牎楠�
if (dto == null) {
@@ -1001,13 +1083,81 @@
return Collections.emptyList();
}
- List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.pickByBomId(orderBom.getId());
+ // 鏌ヨ瀹屾暣鐨凚OM缁撴瀯锛堝寘鎷牴鑺傜偣锛夛紝姣忎釜鑺傜偣鐙珛璁$畻闇�姹傛暟閲�
+ 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;
+
+ for (ProductionBomStructureVo structure : bomStructureList) {
+ if (structure != null) {
+ structure.setDemandedQuantity(orderQuantity
+ .multiply(defaultDecimal(structure.getUnitQuantity())));
+ }
+ }
+
+ // production_bom_structure.is_pick 鏄敓浜ц鍒掍笅鍙戞椂鐨勫伐搴忛鏂欐爣璁板揩鐓э紱
+ // 棰嗘枡鍙拌处璇诲彇鏃朵互宸ュ簭涓绘暟鎹殑鏈�鏂版爣璁颁负鍑嗭紝淇濊瘉宸ュ簭涓婄殑鈥滄槸鍚﹂鏂欌�濊皟鏁村悗鏃犻渶閲嶆柊涓嬪彂鍗冲彲鐢熸晥锛�
+ // 宸ュ簭宸茶鍒犻櫎鏃朵繚鐣欏揩鐓у�硷紝閬垮厤鍘嗗彶璁㈠崟鐨勯鏂欒寖鍥翠涪澶便��
+ Map<Long, Boolean> operationPickMap = loadOperationPickMap(bomStructureList.stream()
+ .filter(Objects::nonNull)
+ .map(ProductionBomStructureVo::getTechnologyOperationId)
+ .collect(Collectors.toList()));
+ for (ProductionBomStructureVo structure : bomStructureList) {
+ if (structure == null || structure.getTechnologyOperationId() == null) {
+ continue;
+ }
+ Boolean latestPick = operationPickMap.get(structure.getTechnologyOperationId());
+ if (latestPick != null) {
+ structure.setIsPick(latestPick);
+ }
+ }
+
+ // 鏀堕泦璁㈠崟鎴愬搧瑙勬牸ID锛氱敓浜ц鍗曟垚鍝佽鏍� + 璁㈠崟BOM蹇収鐨勬牴鑺傜偣瑙勬牸锛岀敤浜庢帓闄も�滆嚜宸扁�濊繖涓�鐗╂枡銆�
+ // 娉ㄦ剰锛欱OM缁撴瀯閲岄鏂欑墿鏂欐湰韬篃鍙兘鏄� parent_id 涓虹┖鐨勭嫭绔嬭妭鐐癸紝杩欓噷涓嶈兘鍐嶆妸鎵�鏈夋牴鑺傜偣閮藉綋鎴愭垚鍝佹帓闄わ紝
+ // 鍚﹀垯鈥滈鏂欌�濆伐搴忎笅鐨勭墿鏂欎細琚暣浣撹繃婊ゆ帀銆�
+ Set<Long> finishedProductModelIds = new HashSet<>();
+ if (productionOrder != null && productionOrder.getProductModelId() != null) {
+ finishedProductModelIds.add(productionOrder.getProductModelId());
+ }
+ if (orderBom.getProductModelId() != null) {
+ finishedProductModelIds.add(orderBom.getProductModelId());
+ }
+
+ // 鏀堕泦鎵�鏈夎寮曠敤涓虹埗绾х殑鑺傜偣ID锛欱OM浠庢渶鍚庝竴閬撳伐搴忓線閲岄厤缃墠涓�閬撳伐搴忥紝
+ // 涓棿鑺傜偣鏄笂涓�閬撳伐搴忕殑浜у嚭锛堣嚜鍒讹級锛屾棫鍙e緞鍙湁姣忔潯鍒嗘敮鏈�閲屽眰鐨勫彾瀛愯妭鐐规墠鏄湡姝i渶瑕侀鐢ㄧ殑鐗╂枡銆�
+ Set<Long> parentNodeIds = bomStructureList.stream()
+ .filter(s -> s != null && s.getParentId() != null && s.getParentId() != 0)
+ .map(ProductionBomStructureVo::getParentId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ // 棰嗘枡鑼冨洿浠ュ伐搴忕殑鈥滄槸鍚﹂鏂欌�濇爣璁颁负鍑嗭細鍙湁鏍囪浜嗛鏂欑殑宸ュ簭锛屽叾娑堣�楃殑鐗╂枡鎵嶈繘鍏ラ鏂欏彴璐︺��
+ // 娉ㄦ剰锛氶鏂欑墿鏂欏湪BOM缁撴瀯涓彲鑳芥槸鐙珛鑺傜偣锛坧arent_id 涓虹┖锛夛紝鎵�浠ヨ繖閲屼笉闄愬埗灞傜骇锛屽彧鐪嬪伐搴忔爣璁帮紱
+ // 鍙帓闄や笌璁㈠崟鎴愬搧鍚岃鏍肩殑鐗╂枡锛堟垚鍝佹湰韬棤闇�棰嗘枡锛夈��
+ List<ProductionBomStructureVo> markedPickStructureList = bomStructureList.stream()
+ .filter(s -> s != null && Boolean.TRUE.equals(s.getIsPick()))
+ .filter(s -> s.getProductModelId() == null || !finishedProductModelIds.contains(s.getProductModelId()))
+ .collect(Collectors.toList());
+
+ // 瀹為檯棰嗘枡椤癸細浼樺厛浣跨敤宸ュ簭棰嗘枡鏍囪锛�
+ // 鍏煎鍘嗗彶鏁版嵁锛氬綋璇ヨ鍗旴OM缁撴瀯閲屾病鏈変换浣曞伐搴忔爣璁伴鏂欐椂锛屽洖閫�涓哄師鏉ョ殑鈥滃彾瀛愯妭鐐归鏂欌�濊鍒欙紝
+ // 閬垮厤灏氭湭鍚敤鈥滄槸鍚﹂鏂欌�濇爣璁扮殑瀹㈡埛鎵撳紑棰嗘枡鍙拌处鏃舵暟鎹獊鐒朵负绌恒��
+ List<ProductionBomStructureVo> childStructureList = markedPickStructureList;
+ if (childStructureList.isEmpty()) {
+ 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());
+ }
+
// 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
- List<Long> productModelIds = bomStructureList.stream()
+ List<Long> productModelIds = childStructureList.stream()
.map(ProductionBomStructureVo::getProductModelId)
.filter(Objects::nonNull)
.distinct()
@@ -1017,7 +1167,8 @@
if (!productModelIds.isEmpty()) {
List<StockInventory> stockList = stockInventoryMapper.selectList(
Wrappers.<StockInventory>lambdaQuery()
- .in(StockInventory::getProductModelId, productModelIds));
+ .in(StockInventory::getProductModelId, productModelIds)
+ .gt(StockInventory::getQualitity, BigDecimal.ZERO));
for (StockInventory stockItem : stockList) {
if (stockItem == null || stockItem.getProductModelId() == null) {
continue;
@@ -1032,7 +1183,7 @@
}
Map<String, ProductionOrderPickVo> mergedPickMap = new LinkedHashMap<>();
- for (ProductionBomStructureVo structure : bomStructureList) {
+ for (ProductionBomStructureVo structure : childStructureList) {
if (structure == null || structure.getProductModelId() == null) {
continue;
}
@@ -1051,6 +1202,7 @@
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);
--
Gitblit v1.9.3