From 97f048ce14db07ee41ca05f9c7010dfe132150e4 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 03 十一月 2026 11:06:59 +0800
Subject: [PATCH] feat(mes): 补生产准备检查与仓储收发存汇总接口,附 CFWJ 演示数据种子脚本
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java | 124 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 124 insertions(+), 0 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
index f766ccf..4584c96 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
@@ -15,9 +15,11 @@
import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderItemRespDTO;
import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseRequestCreateReqDTO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsPreparationCheckRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.mps.vo.MesProMpsSaveReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderItemRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsMergeItemDO;
@@ -29,14 +31,18 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
+import cn.iocoder.yudao.module.mes.enums.dv.MesDvMachineryStatusEnum;
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderSourceTypeEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.service.pro.material.MesProMaterialRequirementService;
+import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService;
import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService;
@@ -110,6 +116,10 @@
private MesProWorkOrderProcessService workOrderProcessService;
@Resource
private MesProMaterialRequirementService materialRequirementService;
+ @Resource
+ private MesProProcessService processService;
+ @Resource
+ private MesDvMachineryService machineryService;
@Resource
private ErpPurchaseOrderApi purchaseOrderApi;
@Resource
@@ -305,6 +315,120 @@
}
@Override
+ public MesProMpsPreparationCheckRespVO getPreparationCheck(Long id) {
+ MesProMpsDO mps = validateMpsExists(id);
+ MesProMpsPreparationCheckRespVO result = new MesProMpsPreparationCheckRespVO();
+ result.setMpsId(mps.getId());
+ result.setMpsCode(mps.getCode());
+ result.setProductId(mps.getProductId());
+ result.setQuantity(mps.getQuantity());
+ MesMdItemDO product = itemService.getItem(mps.getProductId());
+ result.setProductName(product != null ? product.getName() : String.valueOf(mps.getProductId()));
+
+ // 1. 鐗╂枡妫�鏌ワ細闇�姹� - 鍙敤搴撳瓨 - 鍦ㄩ�旈噰璐�
+ List<MesProWorkOrderItemRespVO> materialItems = getMpsItemList(id);
+ int materialShortageCount = 0;
+ for (MesProWorkOrderItemRespVO item : materialItems) {
+ MesProMpsPreparationCheckRespVO.MaterialCheck check = new MesProMpsPreparationCheckRespVO.MaterialCheck();
+ check.setItemId(item.getItemId());
+ check.setItemCode(item.getItemCode());
+ check.setItemName(item.getItemName());
+ check.setSpecification(item.getItemSpecification());
+ check.setUnitMeasureName(item.getUnitMeasureName());
+ check.setRequiredQuantity(nullToZero(item.getQuantity()));
+ check.setStockQuantity(nullToZero(item.getStockQuantity()));
+ check.setPurchaseOrderQuantity(nullToZero(item.getPurchaseOrderQuantity()));
+ BigDecimal supply = nullToZero(item.getStockQuantity()).add(nullToZero(item.getPurchaseOrderQuantity()));
+ BigDecimal shortage = nullToZero(item.getQuantity()).subtract(supply);
+ if (shortage.compareTo(BigDecimal.ZERO) < 0) {
+ shortage = BigDecimal.ZERO;
+ }
+ check.setShortageQuantity(shortage);
+ check.setSufficient(shortage.compareTo(BigDecimal.ZERO) <= 0);
+ if (!Boolean.TRUE.equals(check.getSufficient())) {
+ materialShortageCount++;
+ }
+ result.getMaterials().add(check);
+ }
+ result.setMaterialReady(materialShortageCount == 0);
+
+ // 2. 璁惧妫�鏌ワ細鎸変骇鍝佺殑宸ヨ壓璺嚎閫愬伐搴忔煡鎵剧粦瀹氳澶�
+ List<MesProRouteProcessDO> routeProcesses = routeProcessService.getRouteProcessListByProductId(mps.getProductId());
+ int equipmentUnavailableCount = 0;
+ if (CollUtil.isEmpty(routeProcesses)) {
+ MesProMpsPreparationCheckRespVO.EquipmentCheck check = new MesProMpsPreparationCheckRespVO.EquipmentCheck();
+ check.setProcessName("宸ヨ壓璺嚎");
+ check.setAvailable(false);
+ check.setReason("浜у搧鏈厤缃伐鑹鸿矾绾匡紝鏃犳硶纭畾鎵�闇�璁惧锛涜鍏堝湪銆屽伐鑹鸿矾绾裤�嶄腑缁存姢璇ヤ骇鍝佺殑宸ヨ壓璺嚎鍚庡啀妫�鏌�");
+ result.getEquipments().add(check);
+ equipmentUnavailableCount++;
+ } else {
+ Map<Long, MesProRouteProcessDO> processIdMap = routeProcesses.stream()
+ .filter(rp -> rp.getProcessId() != null)
+ .collect(Collectors.toMap(MesProRouteProcessDO::getProcessId, rp -> rp, (a, b) -> a));
+ Map<Long, MesProProcessDO> processMap = processService.getProcessMap(processIdMap.keySet());
+ // 璁惧涓庡伐搴�/宸ヤ綅鐨勭粦瀹氾細浼樺厛鍙栬澶囦笂鐨勫伐搴� ID锛屽叾娆″洖閫�宸ヤ綅 ID锛堝巻鍙叉暟鎹腑涓よ�呬竴鑷达級
+ List<MesDvMachineryDO> machineries = machineryService.getMachineryList();
+ Map<Long, List<MesDvMachineryDO>> machineryMap = machineries.stream()
+ .filter(m -> m.getProcessId() != null || m.getWorkstationId() != null)
+ .collect(Collectors.groupingBy(m -> m.getProcessId() != null ? m.getProcessId() : m.getWorkstationId()));
+ for (MesProRouteProcessDO rp : routeProcesses) {
+ MesProProcessDO process = processMap.get(rp.getProcessId());
+ String processName = process != null ? process.getName() : String.valueOf(rp.getProcessId());
+ List<MesDvMachineryDO> boundMachineries = machineryMap.get(rp.getProcessId());
+ if (CollUtil.isEmpty(boundMachineries)) {
+ MesProMpsPreparationCheckRespVO.EquipmentCheck check = new MesProMpsPreparationCheckRespVO.EquipmentCheck();
+ check.setProcessId(rp.getProcessId());
+ check.setProcessName(processName);
+ check.setAvailable(false);
+ check.setReason("璇ュ伐搴忔湭缁戝畾璁惧锛岃鍒般�岃澶囧熀纭�淇℃伅绠$悊銆嶄负璇ュ伐搴忕粦瀹氳澶�");
+ result.getEquipments().add(check);
+ equipmentUnavailableCount++;
+ continue;
+ }
+ for (MesDvMachineryDO machinery : boundMachineries) {
+ MesProMpsPreparationCheckRespVO.EquipmentCheck check = new MesProMpsPreparationCheckRespVO.EquipmentCheck();
+ check.setProcessId(rp.getProcessId());
+ check.setProcessName(processName);
+ check.setMachineryId(machinery.getId());
+ check.setMachineryCode(machinery.getCode());
+ check.setMachineryName(machinery.getName());
+ check.setStatus(machinery.getStatus());
+ MesDvMachineryStatusEnum statusEnum = MesDvMachineryStatusEnum.valueOfStatus(machinery.getStatus());
+ check.setStatusName(statusEnum != null ? statusEnum.getName() : "鏈煡");
+ boolean available = statusEnum != MesDvMachineryStatusEnum.MAINTENANCE;
+ check.setAvailable(available);
+ if (available) {
+ check.setReason(statusEnum == MesDvMachineryStatusEnum.PRODUCING ? "璁惧鍗犵敤涓紝鎺掍骇鏃堕渶纭鍙敤鏃舵" : null);
+ } else {
+ check.setReason("璁惧澶勪簬缁存姢涓紝璇风瓑寰呯淮鎶ゅ畬鎴愭垨鏀规淳鍏朵粬璁惧");
+ equipmentUnavailableCount++;
+ }
+ result.getEquipments().add(check);
+ }
+ }
+ }
+ result.setEquipmentReady(equipmentUnavailableCount == 0);
+ boolean ready = Boolean.TRUE.equals(result.getMaterialReady()) && Boolean.TRUE.equals(result.getEquipmentReady());
+ result.setReady(ready);
+ StringBuilder summary = new StringBuilder();
+ if (materialShortageCount > 0) {
+ summary.append(materialShortageCount).append(" 椤圭墿鏂欑煭缂�");
+ }
+ if (equipmentUnavailableCount > 0) {
+ if (summary.length() > 0) {
+ summary.append("锛�");
+ }
+ summary.append(equipmentUnavailableCount).append(" 椤硅澶囦笉鍙敤");
+ }
+ if (summary.length() == 0) {
+ summary.append("鐗╂枡銆佽澶囧潎宸插榻愶紝鍙互瀹夋帓鐢熶骇");
+ }
+ result.setSummary(summary.toString());
+ return result;
+ }
+
+ @Override
@Transactional(rollbackFor = Exception.class)
public Long generatePurchaseRequest(Long id) {
MesProMpsDO mps = validateMpsExists(id);
--
Gitblit v1.9.3