From d39e4f7d839167c16425086dfa2f8747bccfdff9 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 05 十一月 2026 17:39:01 +0800
Subject: [PATCH] feat: 打通销售采购财务闭环并完成累计业务优化
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java | 248 ++++++++++++++++++++++++++++++++-----------------
1 files changed, 162 insertions(+), 86 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
index a7617dc..371a979 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
@@ -12,6 +12,7 @@
import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackTypeEnum;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO;
@@ -24,6 +25,7 @@
import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum;
import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
+import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService;
import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService;
@@ -52,6 +54,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -68,6 +71,9 @@
public class MesProFeedbackServiceImpl implements MesProFeedbackService {
@Resource
+ private MesProFeedbackEquipmentService equipmentService;
+
+ @Resource
private MesProFeedbackMapper feedbackMapper;
@Resource
@@ -77,6 +83,8 @@
private MesProWorkOrderParamRecordService paramRecordService;
@Resource
private MesProRouteProcessService routeProcessService;
+ @Resource
+ private MesProProcessService processService;
@Resource
private MesProWorkOrderBomService workOrderBomService;
@Resource
@@ -109,8 +117,9 @@
// 1. 鏍¢獙
MesProTaskDO task = validateFeedbackData(createReqVO);
- // 2. 鎻掑叆锛堣嚜鍔ㄥ~鍏� itemId锛�
+ // 2. 鎻掑叆锛堜富閿敱鏁版嵁搴撹嚜澧烇紝蹇界暐璇锋眰涓彲鑳芥畫鐣欑殑 id锛涜嚜鍔ㄥ~鍏� itemId锛�
MesProFeedbackDO feedback = BeanUtils.toBean(createReqVO, MesProFeedbackDO.class)
+ .setId(null)
.setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus())
.setItemId(task.getItemId());
feedbackMapper.insert(feedback);
@@ -122,6 +131,7 @@
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFeedback(MesProFeedbackSaveReqVO updateReqVO) {
+ equipmentService.lock();
// 1.1 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
validateFeedbackStatusPrepare(updateReqVO.getId());
// 1.2 鏍¢獙涓氬姟鏁版嵁
@@ -131,6 +141,7 @@
MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class)
.setItemId(task.getItemId());
feedbackMapper.updateById(updateObj);
+ equipmentService.resetSnapshot(updateReqVO.getId());
// 3. 淇濆瓨鍙傛暟鍊硷紱蹇呭~鍙傛暟鏍¢獙澶辫触鏃舵暣浣撳洖婊�
saveParamValues(task.getId(), updateReqVO.getParamValues());
}
@@ -147,7 +158,9 @@
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public void deleteFeedback(Long id) {
+ equipmentService.lock();
// 1. 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
validateFeedbackStatusPrepare(id);
@@ -181,13 +194,24 @@
@Override
@Transactional(rollbackFor = Exception.class)
public void submitFeedback(MesProFeedbackSubmitReqVO reqVO) {
+ equipmentService.lock();
Long id = reqVO.getId();
// 1. 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
MesProFeedbackDO feedback = validateFeedbackStatusPrepare(id);
+ equipmentService.validateSubmission(feedback);
+ // 1.1 椤哄簭鎶ュ伐鏍¢獙锛氬悓涓�鐢熶骇宸ュ崟鍐咃紝涓婁竴閬撳伐搴忓繀椤诲凡鎶ュ伐瀹屾垚锛屽惁鍒欎笉鍏佽鎻愪氦
+ if (feedback.getTaskId() != null) {
+ MesProTaskDO submitTask = taskService.getTask(feedback.getTaskId());
+ if (submitTask != null) {
+ validatePreviousProcessFinished(submitTask);
+ }
+ }
MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(feedback.getWorkOrderId());
- if (workOrder != null && Boolean.TRUE.equals(workOrder.getFeedbackApprove()) && cn.hutool.core.util.StrUtil.isNotBlank(workOrder.getProcessDefinitionKey())) {
+ if (!processInstanceApi.isGlobalAutoApprove() && workOrder != null
+ && Boolean.TRUE.equals(workOrder.getFeedbackApprove())
+ && cn.hutool.core.util.StrUtil.isNotBlank(workOrder.getProcessDefinitionKey())) {
// 2. 鏇存柊鐘舵�佷负瀹℃壒涓紝骞跺惎鍔ㄦ祦绋�
String processInstanceId = processInstanceApi.createProcessInstance(cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId(),
new cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO()
@@ -252,7 +276,9 @@
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public void rejectFeedback(Long id) {
+ equipmentService.lock();
// 1. 鏍¢獙瀛樺湪 + 瀹℃壒涓姸鎬�
validateFeedbackStatusApproving(id);
@@ -264,8 +290,16 @@
@Override
@Transactional(rollbackFor = Exception.class)
public boolean approveFeedback(MesProFeedbackApproveReqVO reqVO) {
+ equipmentService.lock();
// 1.1 鏍¢獙瀛樺湪 + 瀹℃壒涓姸鎬�
MesProFeedbackDO feedback = validateFeedbackStatusApproving(reqVO.getId());
+ equipmentService.validateApproval(feedback);
+ try (var equipmentScope = equipmentService.beginApproval(feedback)) {
+ return approveValidatedFeedback(reqVO, feedback);
+ }
+ }
+
+ private boolean approveValidatedFeedback(MesProFeedbackApproveReqVO reqVO, MesProFeedbackDO feedback) {
// 1.2 鏍¢獙鎶ュ伐鏁伴噺 > 0
if (feedback.getFeedbackQuantity() == null
|| feedback.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
@@ -274,38 +308,36 @@
// 1.3 鏍¢獙浠诲姟鏈畬鎴�
taskService.validateTaskNotFinished(feedback.getTaskId());
- // 2.1 鏌ヨ宸ュ簭鐨勫叧閿伐搴忔爣璇� + 妫�楠屾爣璇嗭紙闇�鍦� uncheckQuantity 鏍¢獙涔嬪墠锛屽洜涓鸿川妫�宸ュ簭鍏佽 uncheckQuantity > 0锛�
+ // 宸ュ簭妫�楠屾爣璇嗕笉鍐嶆帶鍒朵骇鍑哄叆搴擄細鎵�鏈夋柊鎶ュ伐浜у嚭鍧囬渶浜哄伐璐ㄦ銆�
MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId(
feedback.getRouteId(), feedback.getProcessId());
boolean keyFlag = routeProcess != null && Boolean.TRUE.equals(routeProcess.getKeyFlag());
- boolean checkFlag = routeProcess != null && Boolean.TRUE.equals(routeProcess.getCheckFlag());
- // 2.2 闈炶川妫�宸ュ簭锛氫粛鏈夊緟妫�鏁伴噺鏃朵笉鑳藉鎵癸紙璐ㄦ宸ュ簭鐨� uncheckQuantity > 0 鏄甯哥姸鎬侊紝涓嶅仛鎷︽埅锛�
- if (!checkFlag
- && feedback.getUncheckQuantity() != null
- && feedback.getUncheckQuantity().compareTo(BigDecimal.ZERO) > 0) {
- throw exception(PRO_FEEDBACK_UNCHECK_QUANTITY_EXISTS, feedback.getUncheckQuantity());
- }
- // 3. 鐗╂枡娑堣�楋細鍊掑啿宸ュ簭鎸� BOM 鑷姩鎵f枡锛涢潪鍊掑啿宸ュ簭璺宠繃锛堢墿鏂欒蛋鎵嬪伐棰嗘枡/鎶曟枡锛�
+ // 3. 鐗╂枡娑堣�楋細鍊掑啿宸ュ簭鎸夋湰宸ュ簭鎶曟枡 BOM 鑷姩鎵f枡锛涢潪鍊掑啿宸ュ簭璺宠繃锛堢墿鏂欒蛋鎵嬪伐棰嗘枡/鎶曟枡锛�
boolean backflushFlag = routeProcess != null && Boolean.TRUE.equals(routeProcess.getBackflushFlag());
if (backflushFlag) {
- // 3.1 鏍¢獙鍊掑啿宸ュ簭蹇呴』閰嶇疆 BOM 娑堣�楋紝閬垮厤闈欓粯涓嶆墸鏂�
- List<MesProWorkOrderBomDO> boms = workOrderBomService.getWorkOrderBomListByWorkOrderId(
- feedback.getWorkOrderId());
+ // 3.1 鏍¢獙鍊掑啿宸ュ簭蹇呴』閰嶇疆鏈伐搴忕殑鎶曟枡 BOM锛岄伩鍏嶉潤榛樹笉鎵f枡
+ // 锛堝彧鏍¢獙褰撳墠鎶ュ伐宸ュ簭鐨勬姇鏂欙紝鍏朵粬宸ュ簭鎶曟枡鐢卞悇鑷伐搴忔姤宸ユ椂鎵i櫎锛�
+ List<MesProWorkOrderBomDO> boms = workOrderBomService.getWorkOrderBomListByWorkOrderIdAndProcessId(
+ feedback.getWorkOrderId(), feedback.getProcessId());
if (CollUtil.isEmpty(boms)) {
throw exception(PRO_FEEDBACK_BACKFLUSH_BOM_REQUIRED);
}
- // 3.2 鐢熸垚娑堣�楄褰曞苟鎵ц鎵e噺锛圔OM 脳 鎶ュ伐鏁伴噺锛孎IFO 鎵g嚎杈瑰簱锛�
+ // 3.2 鐢熸垚娑堣�楄褰曞苟鎵ц鎵e噺锛堟湰宸ュ簭鎶曟枡鐢ㄩ噺姣斾緥 脳 鎶ュ伐鏁伴噺锛孎IFO 鎵g嚎杈瑰簱锛�
MesWmItemConsumeDO itemConsume = itemConsumeService.generateItemConsume(feedback);
if (itemConsume != null) {
itemConsumeService.finishItemConsume(itemConsume.getId());
}
}
- // 5. 鍏堟洿鏂版姤宸ョ姸鎬佷负宸插畬鎴愶紙纭繚 checkAndFinishMps 妫�鏌ユ椂褰撳墠鎶ュ伐宸叉爣璁板畬鎴愶級
+ // 鎶ュ伐涓庤川妫�鍒嗗紑锛氭姤宸ュ鎵瑰畬鎴愬嵆绱浜ч噺锛岃川閲忔暟閲忕敱璐ㄦ鍥炲~銆�
feedbackMapper.updateById(new MesProFeedbackDO().setId(reqVO.getId())
- .setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus())
- .setUncheckQuantity(BigDecimal.ZERO));
+ .setStatus(MesProFeedbackStatusEnum.UNCHECK.getStatus())
+ .setQualifiedQuantity(BigDecimal.ZERO)
+ .setUnqualifiedQuantity(BigDecimal.ZERO)
+ .setUncheckQuantity(feedback.getFeedbackQuantity()));
+ feedback.setQualifiedQuantity(BigDecimal.ZERO).setUnqualifiedQuantity(BigDecimal.ZERO);
+ productProduceService.generateProductProduce(feedback, true, reqVO);
// 6. 鏍规嵁鏄惁闇�瑕佹楠岋紝鍐冲畾浜у嚭鍜屽叆搴撴柟寮�
// 6.2 璋冩暣 鍙瀹℃壒鎴愬姛鐩存帴鏇存柊
@@ -320,21 +352,8 @@
checkAndPublishProductionFinished(feedback.getWorkOrderId());
}
- if (checkFlag) {
- // 6.1 闇�瑕佹楠岋細鐢熸垚浜у嚭鍗曪紙璐ㄩ噺鐘舵��=寰呮楠岋級锛屾洿鏂版姤宸ョ姸鎬佷负寰呮楠岋紝绛夎川妫�瀹屾垚鍥炶皟鍚庡啀鍏ュ簱
- // 瀹屾垚鏃跺洖璋冭锛歁esQcIpqcServiceImpl#finishIpqc 鈫� splitPendingAndFinishProduce + updateProFeedbackWhenIpqcFinish
- productProduceService.generateProductProduce(feedback, true, reqVO);
- feedbackMapper.updateById(new MesProFeedbackDO().setId(reqVO.getId())
- .setStatus(MesProFeedbackStatusEnum.UNCHECK.getStatus()));
- return false;
- } else {
- // 6.2 鏃犻渶妫�楠岋細鐢熸垚浜у嚭鍗曪紙鎸夊悎鏍�/涓嶅悎鏍兼媶琛岋級锛岀洿鎺ュ畬鎴愬叆搴�
- MesWmProductProduceDO produce = productProduceService.generateProductProduce(feedback, false, reqVO);
- productProduceService.finishProductProduce(produce.getId());
-
- }
-
- return true; // 宸插畬鎴�
+ equipmentService.afterApproved(feedback);
+ return false; // 浜у嚭绛夊緟璐ㄦ锛屾姤宸ヤ骇閲忓凡绱
}
/**
@@ -350,22 +369,9 @@
* @param feedback 鎶ュ伐鍗�
*/
private void updateTaskAndWorkOrderByFeedback(MesProFeedbackDO feedback) {
- // 1. 鏌ヨ璇ユ姤宸ュ崟鍏宠仈鐨勬墍鏈変骇鍑哄崟琛岋紝鎸夎川閲忕姸鎬佽仛鍚堟暟閲�
- BigDecimal qualifiedQty = BigDecimal.ZERO;
- BigDecimal unqualifiedQty = BigDecimal.ZERO;
- List<MesWmProductProduceLineDO> lines = produceLineService.getProductProduceLineListByFeedbackId(feedback.getId());
- for (MesWmProductProduceLineDO line : lines) {
- if (ObjUtil.equal(line.getQualityStatus(), MesWmQualityStatusEnum.FAIL.getStatus())) {
- unqualifiedQty = unqualifiedQty.add(line.getQuantity());
- }
- if (ObjUtil.equal(line.getQualityStatus(), MesWmQualityStatusEnum.PASS.getStatus())) {
- qualifiedQty = qualifiedQty.add(line.getQuantity());
- }
- }
-
- // 2. 鏇存柊浠诲姟鐨勫凡鐢熶骇/鍚堟牸/涓嶅悎鏍兼暟閲�
+ // 鎶ュ伐瀹℃壒鍙疮璁′骇閲忥紱鍚堟牸涓庝笉鍚堟牸鏁伴噺鍦ㄨ川妫�瀹屾垚鏃剁疮璁°��
taskService.updateProducedQuantity(feedback.getTaskId(),
- feedback.getFeedbackQuantity(), qualifiedQty, unqualifiedQty);
+ feedback.getFeedbackQuantity(), BigDecimal.ZERO, BigDecimal.ZERO);
// 3. 鏇存柊璁㈠崟鐨勫凡鐢熶骇鏁伴噺
// 鏂板閫昏緫锛氬彧鏈夊湪璇ョ瑪璁㈠崟鏈�鍚庝竴涓伐搴忔墠鏇存柊鐢熶骇璁㈠崟鐨勫凡鐢熶骇鏁伴噺
MesProWorkOrderProcessDO lastProcess = workOrderProcessService.getLastWorkOrderProcessByWorkOrderId(feedback.getWorkOrderId());
@@ -390,12 +396,16 @@
private void checkAndPublishProductionFinished(Long workOrderId) {
// 1. 鑾峰彇宸ュ崟鍏宠仈鐨� MPS
MesProMpsRespDTO mps = mpsApi.getMpsByWorkOrderId(workOrderId);
- if (mps == null || mps.getSaleOrderId() == null) {
+ if (mps == null || mps.getSaleOrderId() == null
+ || ObjUtil.equal(mps.getStatus(), cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum.FINISHED.getStatus())
+ || ObjUtil.equal(mps.getStatus(), cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum.CANCELED.getStatus())) {
return; // 闈為攢鍞鍗曟潵婧愮殑宸ュ崟锛岃烦杩�
}
// 2. 妫�鏌ュ苟鑷姩瀹屾垚 MPS锛堝鏋滄弧瓒虫潯浠讹級
- mpsApi.checkAndFinishMps(mps.getId());
+ if (!Boolean.TRUE.equals(mpsApi.checkAndFinishMps(mps.getId()))) {
+ return;
+ }
// 3. 妫�鏌ラ攢鍞鍗曟墍鏈夌敓浜ф槸鍚﹀畬鎴�
if (mpsApi.checkSaleOrderProductionFinished(mps.getSaleOrderId())) {
@@ -461,29 +471,85 @@
if (routeProcess == null) {
throw exception(PRO_FEEDBACK_ROUTE_PROCESS_INVALID);
}
- // 4.1 鏍¢獙鏁伴噺
- boolean checkFlag = Boolean.TRUE.equals(routeProcess.getCheckFlag());
- if (checkFlag) {
- // 闇�瑕佹楠岋細鍙渶濉姤宸ユ暟閲忥紝涓斿繀椤� > 0
- if (reqVO.getFeedbackQuantity() == null
- || reqVO.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
- throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE);
- }
- } else {
- // 涓嶉渶妫�楠岋細闇�濉悎鏍煎搧 + 涓嶈壇鍝佹暟閲忥紝鍚堣 > 0
- BigDecimal qualified = ObjectUtil.defaultIfNull(reqVO.getQualifiedQuantity(), BigDecimal.ZERO);
- BigDecimal unqualified = ObjectUtil.defaultIfNull(reqVO.getUnqualifiedQuantity(), BigDecimal.ZERO);
- if (qualified.add(unqualified).compareTo(BigDecimal.ZERO) <= 0) {
- throw exception(PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_REQUIRED);
- }
+ // 4.1 鏍¢獙鏁伴噺锛氭棤璁烘槸鍚﹂渶瑕佹楠岋紝鎶ュ伐鍙渶濉姤宸ユ暟閲忥紝涓斿繀椤� > 0
+ // 鍚堟牸鍝�/涓嶈壇鍝佹暟閲忕敱璐ㄦ纭畾銆�
+ if (reqVO.getFeedbackQuantity() == null
+ || reqVO.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+ throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE);
}
return task;
}
+ /**
+ * 椤哄簭鎶ュ伐鏍¢獙锛氬悓涓�鐢熶骇宸ュ崟鍐咃紝涓婁竴閬撳伐搴忓繀椤诲凡鎶ュ伐瀹屾垚锛屽惁鍒欎笉鍏佽鎶ユ湰閬撳伐搴�
+ *
+ * <p>鍒ゅ畾鍙e緞锛氫笂涓�閬撳伐搴忕殑鏈夋晥浠诲姟锛堟湭鍙栨秷锛夌疮璁″鎵归�氳繃鐨勪骇閲忓凡杈惧埌鍏舵帓浜ф暟閲忥紝
+ * 鍗充换涓�鏈夋晥浠诲姟 produced_quantity < quantity 閮借涓烘湭瀹屾垚骞舵嫤鎴��
+ * 涔嬫墍浠ヤ笉渚濊禆浠诲姟 status锛氫换鍔$姸鎬佸彧鏈夋暣鍗曞畬宸�/鍙栨秷鏃舵墠缃粓鎬�
+ * 锛坒inishTaskByOrderId / cancelTaskByOrderId锛夛紝鏃犳硶浣滀负"鍗曢亾宸ュ簭宸插畬鎴�"鐨勪緷鎹紝
+ * produced_quantity 鏄敮涓�瀹炴椂鍙潬鐨勮繘搴︿俊鍙枫��
+ *
+ * @param task 褰撳墠寰呮姤宸ヤ换鍔�
+ */
+ private void validatePreviousProcessFinished(MesProTaskDO task) {
+ if (task == null || task.getWorkOrderId() == null || task.getProcessId() == null) {
+ return; // 鏁版嵁涓嶅畬鏁达紝鏃犳硶鎺ㄥ椤哄簭锛屾斁琛�
+ }
+ // 1. 褰撳墠浠诲姟鎵�灞炲伐搴忓湪宸ュ崟宸ュ簭閾撅紙鎸� sort 鍗囧簭锛変腑鐨勪綅缃�
+ List<MesProWorkOrderProcessDO> processes = workOrderProcessService
+ .getWorkOrderProcessListByWorkOrderId(task.getWorkOrderId());
+ if (CollUtil.isEmpty(processes)) {
+ return; // 宸ュ崟鏈厤缃伐搴忥紝鏀捐
+ }
+ // 鎷疯礉鍚庡啀鎺掑簭锛岄伩鍏嶄慨鏀硅皟鐢ㄦ柟杩斿洖鐨勶紙鍙兘鏄笉鍙彉锛夐泦鍚�
+ processes = new ArrayList<>(processes);
+ processes.sort(Comparator.comparing(MesProWorkOrderProcessDO::getSort,
+ Comparator.nullsLast(Comparator.naturalOrder())));
+ int index = -1;
+ for (int i = 0; i < processes.size(); i++) {
+ if (ObjUtil.equal(processes.get(i).getProcessId(), task.getProcessId())) {
+ index = i;
+ break;
+ }
+ }
+ if (index <= 0) {
+ return; // 褰撳墠宸ュ簭涓嶅湪閾句腑锛堟暟鎹紓甯革紝鏀捐锛夋垨鏈韩灏辨槸绗竴閬撳伐搴忥紝鏃犻渶鍓嶇疆
+ }
+ Long prevProcessId = processes.get(index - 1).getProcessId();
+ if (prevProcessId == null) {
+ return;
+ }
+ // 2. 涓婁竴閬撳伐搴忕殑鏈夋晥浠诲姟锛堟帓闄ゅ凡鍙栨秷锛夌疮璁″緟瀹屾垚閲�
+ List<MesProTaskDO> prevTasks = taskService.getTaskListByWorkOrderIds(
+ Collections.singletonList(task.getWorkOrderId())).stream()
+ .filter(t -> ObjUtil.equal(t.getProcessId(), prevProcessId))
+ .filter(t -> !ObjUtil.equal(t.getStatus(), MesProTaskStatusEnum.CANCELED.getStatus()))
+ .toList();
+ if (CollUtil.isEmpty(prevTasks)) {
+ return; // 涓婁竴閬撳伐搴忔棤鏈夋晥鐢熶骇浠诲姟锛堝惈鍏ㄩ儴鍙栨秷锛夛紝瑙嗕负鏃犲墠缃姹傦紝鏀捐
+ }
+ BigDecimal remaining = BigDecimal.ZERO;
+ for (MesProTaskDO prevTask : prevTasks) {
+ BigDecimal qty = prevTask.getQuantity() == null ? BigDecimal.ZERO : prevTask.getQuantity();
+ BigDecimal produced = prevTask.getProducedQuantity() == null ? BigDecimal.ZERO : prevTask.getProducedQuantity();
+ if (produced.compareTo(qty) < 0) {
+ remaining = remaining.add(qty.subtract(produced));
+ }
+ }
+ if (remaining.compareTo(BigDecimal.ZERO) <= 0) {
+ return; // 涓婁竴閬撳伐搴忓凡鍏ㄩ儴鎶ユ弧锛屾斁琛�
+ }
+ // 3. 鎷︽埅骞舵彁绀轰笂涓�閬撳伐搴忓悕绉颁笌鍓╀綑寰呮姤鏁伴噺
+ MesProProcessDO prevProcess = processService.getProcess(prevProcessId);
+ String prevProcessName = prevProcess != null ? prevProcess.getName() : String.valueOf(prevProcessId);
+ throw exception(PRO_FEEDBACK_PREV_PROCESS_NOT_FINISHED, prevProcessName, remaining);
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
public MesProFeedbackQuickCreateRespVO quickCreateFeedback(MesProFeedbackQuickCreateReqVO reqVO) {
+ equipmentService.lock();
// 1. 鏍¢獙浠诲姟瀛樺湪涓旈潪缁堟��
MesProTaskDO task = taskService.validateTaskNotFinished(reqVO.getTaskId());
@@ -491,6 +557,8 @@
if (!MesProTaskStatusEnum.canFeedback(task.getStatus())) {
throw exception(PRO_FEEDBACK_CANNOT_CREATE_WHEN_PAUSED);
}
+ // 1.1 椤哄簭鎶ュ伐鏍¢獙锛氬悓涓�鐢熶骇宸ュ崟鍐咃紝涓婁竴閬撳伐搴忓繀椤诲凡鎶ュ伐瀹屾垚锛屽惁鍒欎笉鍏佽鎶ュ伐
+ validatePreviousProcessFinished(task);
// 2. 鏍¢獙宸ヨ壓璺嚎宸ュ簭閰嶇疆
MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId(
@@ -498,19 +566,10 @@
if (routeProcess == null) {
throw exception(PRO_FEEDBACK_ROUTE_PROCESS_INVALID);
}
- // 3. 鏍¢獙鏁伴噺
- boolean checkFlag = Boolean.TRUE.equals(routeProcess.getCheckFlag());
- if (checkFlag) {
- if (reqVO.getFeedbackQuantity() == null
- || reqVO.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
- throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE);
- }
- } else {
- BigDecimal qualified = ObjectUtil.defaultIfNull(reqVO.getQualifiedQuantity(), BigDecimal.ZERO);
- BigDecimal unqualified = ObjectUtil.defaultIfNull(reqVO.getUnqualifiedQuantity(), BigDecimal.ZERO);
- if (qualified.add(unqualified).compareTo(BigDecimal.ZERO) <= 0) {
- throw exception(PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_REQUIRED);
- }
+ // 3. 鏍¢獙鏁伴噺锛氬彧濉姤宸ユ暟閲忥紝涓斿繀椤� > 0锛堝悎鏍煎搧/涓嶈壇鍝佹暟閲忕敱璐ㄦ纭畾锛�
+ if (reqVO.getFeedbackQuantity() == null
+ || reqVO.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+ throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE);
}
// 4. 鏋勫缓鎶ュ伐DO
MesProFeedbackDO feedback = new MesProFeedbackDO()
@@ -523,20 +582,32 @@
.setTaskId(reqVO.getTaskId())
.setItemId(task.getItemId())
.setFeedbackQuantity(reqVO.getFeedbackQuantity())
- .setQualifiedQuantity(reqVO.getQualifiedQuantity())
- .setUnqualifiedQuantity(reqVO.getUnqualifiedQuantity())
.setScheduledQuantity(task.getQuantity())
- .setFeedbackTime(LocalDateTime.now())
+ .setFeedbackTime(reqVO.getFeedbackTime() != null ? reqVO.getFeedbackTime() : LocalDateTime.now())
+ .setMachineryIds(reqVO.getMachineryIds())
.setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus())
.setRemark(reqVO.getRemark());
+ equipmentService.validateSubmission(feedback);
feedbackMapper.insert(feedback);
saveParamValues(task.getId(), reqVO.getParamValues());
// 5. 杩斿洖缁撴灉
MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(task.getWorkOrderId());
+ // 5.1 鎶ュ伐鍚庡墿浣欏彲鎶ュ伐鏁伴噺 = 鎺掍骇 - 宸茬敓浜� - 鍦ㄩ�旓紙鍚湰娆℃姤宸ワ級
+ BigDecimal reportable = task.getQuantity() == null ? BigDecimal.ZERO : task.getQuantity();
+ BigDecimal produced = task.getProducedQuantity() == null ? BigDecimal.ZERO : task.getProducedQuantity();
+ BigDecimal inTransit = BigDecimal.ZERO;
+ for (MesProFeedbackDO fb : getFeedbackListByTaskId(task.getId())) {
+ if (!ObjUtil.equal(fb.getStatus(), MesProFeedbackStatusEnum.FINISHED.getStatus())
+ && !ObjUtil.equal(fb.getStatus(), MesProFeedbackStatusEnum.UNCHECK.getStatus())) {
+ inTransit = inTransit.add(fb.getFeedbackQuantity() == null ? BigDecimal.ZERO : fb.getFeedbackQuantity());
+ }
+ }
+ BigDecimal reportableQuantity = reportable.subtract(produced).subtract(inTransit).max(BigDecimal.ZERO);
return new MesProFeedbackQuickCreateRespVO()
.setFeedbackId(feedback.getId())
.setTaskStatus(task.getStatus())
- .setWorkOrderStatus(workOrder != null ? workOrder.getStatus() : null);
+ .setWorkOrderStatus(workOrder != null ? workOrder.getStatus() : null)
+ .setReportableQuantity(reportableQuantity);
}
@Override
@@ -550,8 +621,7 @@
MesProFeedbackQuickCreateReqVO singleReq = new MesProFeedbackQuickCreateReqVO();
singleReq.setTaskId(taskId);
singleReq.setFeedbackQuantity(reqVO.getFeedbackQuantity());
- singleReq.setQualifiedQuantity(reqVO.getQualifiedQuantity());
- singleReq.setUnqualifiedQuantity(reqVO.getUnqualifiedQuantity());
+ singleReq.setFeedbackTime(reqVO.getFeedbackTime());
singleReq.setRemark(reqVO.getRemark());
MesProFeedbackQuickCreateRespVO resp = quickCreateFeedback(singleReq);
results.add(new MesProFeedbackBatchCreateRespVO.BatchResult()
@@ -579,7 +649,10 @@
BigDecimal qualifiedQty, BigDecimal unqualifiedQty,
BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty) {
// 1. 鏍¢獙鎶ュ伐鍗曞瓨鍦ㄤ笖涓哄緟妫�楠岀姸鎬�
- MesProFeedbackDO feedback = validateFeedbackExists(feedbackId);
+ MesProFeedbackDO feedback = feedbackMapper.selectByIdForUpdate(feedbackId);
+ if (feedback == null) {
+ throw exception(PRO_FEEDBACK_NOT_EXISTS);
+ }
if (ObjUtil.notEqual(feedback.getStatus(), MesProFeedbackStatusEnum.UNCHECK.getStatus())) {
throw exception(PRO_FEEDBACK_NOT_UNCHECK);
}
@@ -597,8 +670,11 @@
.setOtherScrapQuantity(otherScrapQty)
.setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus()));
- // 4. 鏇存柊浠诲姟/宸ュ崟鐨勫凡鐢熶骇鏁伴噺
+ // 4. 浜ч噺宸插湪鎶ュ伐瀹℃壒鏃剁疮璁★紝姝ゅ鍙洖濉川閲忔暟閲忋��
feedback.setQualifiedQuantity(qualifiedQty).setUnqualifiedQuantity(unqualifiedQty);
+ taskService.updateQualityQuantity(feedback.getTaskId(),
+ ObjectUtil.defaultIfNull(qualifiedQty, BigDecimal.ZERO),
+ ObjectUtil.defaultIfNull(unqualifiedQty, BigDecimal.ZERO));
//5.妫�鏌ュ苟鍙戝竷鐢熶骇瀹屾垚浜嬩欢
checkAndPublishProductionFinished(feedback.getWorkOrderId());
}
--
Gitblit v1.9.3