From e09f103259fa602382bb5ce2a03361a6397af46a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 15 十月 2026 11:49:15 +0800
Subject: [PATCH] feat(mes): 优化MES模块生产调度与数据管理功能
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java | 93 ++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 88 insertions(+), 5 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java
index b280225..43f415d 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.mes.service.pro.card;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -7,11 +8,14 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.card.MesProCardMapper;
import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum;
import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
+import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService;
import jakarta.annotation.Resource;
@@ -19,6 +23,12 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
@@ -44,33 +54,46 @@
private MesMdItemService itemService;
@Resource
private MesWmBarcodeService barcodeService;
+ @Resource
+ private MesProWorkOrderProcessService workOrderProcessService;
@Override
+ @Transactional(rollbackFor = Exception.class)
public Long createCard(MesProCardSaveReqVO createReqVO) {
// 1. 鏍¢獙鍏宠仈鏁版嵁
- validateCardSaveData(createReqVO);
+ MesProWorkOrderDO workOrder = validateCardSaveData(createReqVO);
// 2. 鎻掑叆
MesProCardDO card = BeanUtils.toBean(createReqVO, MesProCardDO.class)
.setStatus(MesProWorkOrderStatusEnum.PREPARE.getStatus());
cardMapper.insert(card);
- // 3. 鑷姩鐢熸垚鏉$爜
+ // 3. 鎸夊伐鍗曞伐搴� + 鏀剁巼鐢熸垚宸ュ簭璁板綍
+ generateCardProcesses(card.getId(), workOrder);
+
+ // 4. 鑷姩鐢熸垚鏉$爜
barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.PROCARD.getValue(),
card.getId(), card.getCode(), card.getCode());
return card.getId();
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public void updateCard(MesProCardSaveReqVO updateReqVO) {
// 1.1 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
- validateCardExistsAndPrepare(updateReqVO.getId());
+ MesProCardDO card = validateCardExistsAndPrepareInternal(updateReqVO.getId());
// 1.2 鏍¢獙鍏宠仈鏁版嵁
- validateCardSaveData(updateReqVO);
+ MesProWorkOrderDO workOrder = validateCardSaveData(updateReqVO);
// 2. 鏇存柊
MesProCardDO updateObj = BeanUtils.toBean(updateReqVO, MesProCardDO.class);
cardMapper.updateById(updateObj);
+
+ // 3. 鏇存崲浜嗙敓浜ц鍗曪細鍘熷伐搴忚褰曞凡澶辨晥锛屾寜鏂板伐鍗曢噸寤�
+ if (ObjUtil.notEqual(card.getWorkOrderId(), updateReqVO.getWorkOrderId())) {
+ cardProcessService.deleteCardProcessByCardId(card.getId());
+ generateCardProcesses(card.getId(), workOrder);
+ }
}
@Override
@@ -139,10 +162,15 @@
@Override
public void validateCardExistsAndPrepare(Long id) {
+ validateCardExistsAndPrepareInternal(id);
+ }
+
+ private MesProCardDO validateCardExistsAndPrepareInternal(Long id) {
MesProCardDO card = validateCardExistsInternal(id);
if (ObjUtil.notEqual(MesProWorkOrderStatusEnum.PREPARE.getStatus(), card.getStatus())) {
throw exception(PRO_CARD_NOT_PREPARE);
}
+ return card;
}
private MesProCardDO validateCardExistsInternal(Long id) {
@@ -174,7 +202,7 @@
}
}
- private void validateCardSaveData(MesProCardSaveReqVO reqVO) {
+ private MesProWorkOrderDO validateCardSaveData(MesProCardSaveReqVO reqVO) {
// 鏍¢獙缂栫爜鍞竴
validateCardCodeUnique(reqVO.getId(), reqVO.getCode());
// 鏍¢獙宸ュ崟瀛樺湪
@@ -184,6 +212,61 @@
if (ObjUtil.notEqual(workOrder.getProductId(), reqVO.getItemId())) {
throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH);
}
+ return workOrder;
+ }
+
+ /**
+ * 鎸夊伐鍗曞伐搴忎笌宸ュ簭鏀剁巼鐢熸垚娴佽浆鍗″伐搴忚褰�
+ *
+ * <p>鏁伴噺鍙e緞涓庝竴閿帓浜т竴鑷达紙瑙� MesProBatchScheduleService#calcTargetQuantities锛夛細
+ * 鏈亾宸ュ簭浜у嚭 = 宸ュ崟璁″垝鏁伴噺锛屽墠闈㈠悇閬撻�愮骇鏀惧ぇ鍚庡悜涓婂彇鏁达紱
+ * 鏈亾鎶曞叆 = 涓婇亾浜у嚭锛堥閬撴姇鍏� = 棣栭亾浜у嚭 / 鏀剁巼锛屽悜涓婂彇鏁达級锛屼笉鍚堟牸鍝� = 鎶曞叆 - 浜у嚭銆�
+ *
+ * <p>杩涘叆/鍑哄伐搴忔椂闂淬�佸伐浣嶃�佹搷浣滀汉鐣欑┖锛屽緟鐢熶骇瀹為檯鍙戠敓鏃跺~鍐欍��
+ */
+ private void generateCardProcesses(Long cardId, MesProWorkOrderDO workOrder) {
+ List<MesProWorkOrderProcessDO> processes = workOrderProcessService
+ .getWorkOrderProcessListByWorkOrderId(workOrder.getId());
+ if (CollUtil.isEmpty(processes) || workOrder.getQuantity() == null) {
+ return; // 宸ュ崟鏈淮鎶ゅ伐搴忔垨鏁伴噺缂哄け锛屽伐搴忚褰曠暀寰呮墜宸ョ淮鎶�
+ }
+ processes = new ArrayList<>(processes);
+ processes.sort(Comparator.comparing(MesProWorkOrderProcessDO::getSort,
+ Comparator.nullsLast(Comparator.naturalOrder())));
+
+ // 1. 鎸夋敹鐜囦粠鏈亾寰�鍓嶅�掓帹鍚勯亾浜у嚭閲忥紙鍚戜笂鍙栨暣涓烘暣鏁颁欢锛�
+ int size = processes.size();
+ BigDecimal[] outputs = new BigDecimal[size];
+ BigDecimal cumulativeYield = BigDecimal.ONE;
+ for (int i = size - 1; i >= 0; i--) {
+ outputs[i] = workOrder.getQuantity().divide(cumulativeYield, 0, RoundingMode.CEILING);
+ BigDecimal yieldRate = processes.get(i).getYieldRate();
+ if (yieldRate != null && yieldRate.signum() > 0) {
+ cumulativeYield = cumulativeYield.multiply(yieldRate);
+ }
+ }
+
+ // 2. 閫愰亾鐢熸垚璁板綍锛氭姇鍏� = 涓婇亾浜у嚭锛堥閬� = 鏈亾浜у嚭 / 鏀剁巼锛屽悜涓婂彇鏁达級
+ List<MesProCardProcessDO> cardProcesses = new ArrayList<>(size);
+ BigDecimal previousOutput = null;
+ for (int i = 0; i < size; i++) {
+ MesProWorkOrderProcessDO process = processes.get(i);
+ BigDecimal input;
+ if (previousOutput != null) {
+ input = previousOutput;
+ } else {
+ BigDecimal firstYield = process.getYieldRate();
+ input = firstYield == null || firstYield.signum() <= 0
+ ? outputs[i] : outputs[i].divide(firstYield, 0, RoundingMode.CEILING);
+ }
+ cardProcesses.add(MesProCardProcessDO.builder()
+ .cardId(cardId).sort(process.getSort()).processId(process.getProcessId())
+ .inputQuantity(input).outputQuantity(outputs[i])
+ .unqualifiedQuantity(BigDecimal.ZERO)
+ .build());
+ previousOutput = outputs[i];
+ }
+ cardProcessService.createCardProcessBatch(cardProcesses);
}
}
--
Gitblit v1.9.3