From df6efd77578c8ba54d1ae3be9198c70fb5173399 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期六, 29 八月 2026 01:46:11 +0800
Subject: [PATCH] feat(mes): 报工只填写报工数量,合格/不良数量由质检确定;快速报工响应返回剩余可报工数量
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java | 171 ++++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 132 insertions(+), 39 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 d5401e9..016e10a 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
@@ -4,6 +4,7 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.*;
@@ -28,6 +29,7 @@
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService;
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.pro.workorder.MesProWorkOrderParamRecordService;
import cn.iocoder.yudao.module.mes.service.wm.itemconsume.MesWmItemConsumeService;
import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceService;
@@ -62,6 +64,7 @@
*/
@Service
@Validated
+@lombok.extern.slf4j.Slf4j
public class MesProFeedbackServiceImpl implements MesProFeedbackService {
@Resource
@@ -69,6 +72,9 @@
@Resource
private MesProWorkOrderService workOrderService;
+ @Resource
+ @Lazy
+ private MesProWorkOrderParamRecordService paramRecordService;
@Resource
private MesProRouteProcessService routeProcessService;
@Resource
@@ -94,8 +100,11 @@
private MesMdmItemService mdmItemService;
@Resource
private MdmItemBatchConfigApi itemBatchConfigApi;
+ @Resource
+ private cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi processInstanceApi;
@Override
+ @Transactional(rollbackFor = Exception.class)
public Long createFeedback(MesProFeedbackSaveReqVO createReqVO) {
// 1. 鏍¢獙
MesProTaskDO task = validateFeedbackData(createReqVO);
@@ -105,10 +114,13 @@
.setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus())
.setItemId(task.getItemId());
feedbackMapper.insert(feedback);
+ // 3. 淇濆瓨鍙傛暟鍊硷紱蹇呭~鍙傛暟鏍¢獙澶辫触鏃舵暣浣撳洖婊氾紝閬垮厤娈嬬暀鑽夌
+ saveParamValues(task.getId(), createReqVO.getParamValues());
return feedback.getId();
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public void updateFeedback(MesProFeedbackSaveReqVO updateReqVO) {
// 1.1 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
validateFeedbackStatusPrepare(updateReqVO.getId());
@@ -119,6 +131,19 @@
MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class)
.setItemId(task.getItemId());
feedbackMapper.updateById(updateObj);
+ // 3. 淇濆瓨鍙傛暟鍊硷紱蹇呭~鍙傛暟鏍¢獙澶辫触鏃舵暣浣撳洖婊�
+ saveParamValues(task.getId(), updateReqVO.getParamValues());
+ }
+
+ private void saveParamValues(Long taskId, List<MesProFeedbackSaveReqVO.ParamValue> paramValues) {
+ // 鍗充娇鍙傛暟涓虹┖涔熻皟鐢ㄦ洿鏂帮紝浠ヤ究瑙﹀彂蹇呭~鍙傛暟鏍¢獙锛堜换鍔$粦瀹氫簡鍙傛暟鏃跺繀椤诲~鍐欙級
+ if (CollUtil.isEmpty(paramValues)) {
+ paramRecordService.updateTaskParamValues(taskId, null, null);
+ return;
+ }
+ paramRecordService.updateTaskParamValues(taskId,
+ paramValues.stream().map(MesProFeedbackSaveReqVO.ParamValue::getDetailId).toList(),
+ paramValues.stream().map(MesProFeedbackSaveReqVO.ParamValue::getValue).toList());
}
@Override
@@ -154,13 +179,76 @@
}
@Override
- public void submitFeedback(Long id) {
+ @Transactional(rollbackFor = Exception.class)
+ public void submitFeedback(MesProFeedbackSubmitReqVO reqVO) {
+ Long id = reqVO.getId();
// 1. 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
- validateFeedbackStatusPrepare(id);
+ MesProFeedbackDO feedback = validateFeedbackStatusPrepare(id);
- // 2. 鏇存柊鐘舵�佷负瀹℃壒涓紙鎶ュ伐浜哄拰鎶ュ伐鏃堕棿鐢辫〃鍗曚繚瀛樻椂纭畾锛屾彁浜や笉瑕嗙洊锛�
- feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
- .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()));
+ MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(feedback.getWorkOrderId());
+
+ if (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()
+ .setProcessDefinitionKey(workOrder.getProcessDefinitionKey())
+ .setBusinessKey(String.valueOf(id)));
+
+ feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
+ .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus())
+ .setProcessDefinitionKey(workOrder.getProcessDefinitionKey())
+ .setProcessInstanceId(processInstanceId));
+ } else {
+ // 2. 鍒ゆ柇杩欎釜鎶ュ伐闇�涓嶉渶瑕佹壒娆″彿
+ MesProFeedbackBatchCheckRespVO mesProFeedbackBatchCheckRespVO = checkBatchRequirements(id);
+ if (mesProFeedbackBatchCheckRespVO.getNeedBatchInput()) {
+ if (StrUtil.isBlank(reqVO.getLotNumber())) {
+ throw exception(MD_ITEM_BATCH_CONFIG_AT_LEAST_ONE_APPROVE_FLAG);
+ }
+ }
+
+ // 3. 鏇存柊鐘舵�佷负瀹℃壒涓紝鐒跺悗鐩存帴閫氳繃瀹℃壒
+ feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
+ .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()));
+ MesProFeedbackApproveReqVO approveReqVO = cn.iocoder.yudao.framework.common.util.object.BeanUtils.toBean(reqVO, MesProFeedbackApproveReqVO.class);
+ approveFeedback(approveReqVO);
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void handleBpmProcessResult(Long id, Integer bpmResult,String reason) {
+ // 1. 鏌旀�ф牎楠岋細鑾峰彇鎶ュ伐鍗曞苟鍒ゆ柇鐘舵��
+ MesProFeedbackDO feedback = feedbackMapper.selectById(id);
+ if (feedback == null) {
+ log.warn("[handleBpmProcessResult] 鐢熶骇鎶ュ伐({}) 涓嶅瓨鍦�", id);
+ return;
+ }
+ if (!MesProFeedbackStatusEnum.APPROVING.getStatus().equals(feedback.getStatus())) {
+ log.warn("[handleBpmProcessResult] 鐢熶骇鎶ュ伐({}) 涓嶅浜庡鎵逛腑鐘舵�侊紝褰撳墠鐘舵�侊細{}", id, feedback.getStatus());
+ return;
+ }
+
+ // 2. 鏍规嵁瀹℃壒缁撴灉杩涜澶勭悊
+ if (cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum.APPROVE.getStatus().equals(bpmResult)) {
+ MesProFeedbackApproveReqVO reqVO = new MesProFeedbackApproveReqVO();
+ reqVO.setId(id);
+ // 鍒ゆ柇杩欎釜鎶ュ伐闇�涓嶉渶瑕佹壒娆″彿
+ MesProFeedbackBatchCheckRespVO mesProFeedbackBatchCheckRespVO = checkBatchRequirements(id);
+ if (mesProFeedbackBatchCheckRespVO.getNeedBatchInput()){
+ if (StrUtil.isBlank(reason)){
+ // 鎶ラ敊 璇峰湪瀹℃壒鎰忚閲屽~鍐欐壒娆″彿
+ throw exception(MD_ITEM_BATCH_CONFIG_AT_LEAST_ONE_APPROVE_FLAG);
+ }else {
+ BeanUtils.copyProperties(mesProFeedbackBatchCheckRespVO,reqVO);
+ reqVO.setLotNumber(reason);
+ }
+ }
+ approveFeedback(reqVO);
+ } else if (cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum.REJECT.getStatus().equals(bpmResult) ||
+ cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum.CANCEL.getStatus().equals(bpmResult)) {
+ rejectFeedback(id);
+ }
}
@Override
@@ -191,7 +279,17 @@
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 鏄甯哥姸鎬侊紝涓嶅仛鎷︽埅锛�
+ // 2.2 闈炶川妫�宸ュ簭锛氬悎鏍煎搧/涓嶈壇鍝佹暟閲忕敱璐ㄦ纭畾锛涙湰宸ュ簭涓嶇粡杩囪川妫�锛屾姤宸ユ湭濉啓鏃堕粯璁ゅ叏閮ㄤ负鍚堟牸鍝�
+ if (!checkFlag
+ && feedback.getQualifiedQuantity() == null
+ && feedback.getUnqualifiedQuantity() == null) {
+ feedback.setQualifiedQuantity(feedback.getFeedbackQuantity());
+ feedback.setUnqualifiedQuantity(BigDecimal.ZERO);
+ feedbackMapper.updateById(new MesProFeedbackDO().setId(feedback.getId())
+ .setQualifiedQuantity(feedback.getFeedbackQuantity())
+ .setUnqualifiedQuantity(BigDecimal.ZERO));
+ }
+ // 2.3 闈炶川妫�宸ュ簭锛氫粛鏈夊緟妫�鏁伴噺鏃朵笉鑳藉鎵癸紙璐ㄦ宸ュ簭鐨� uncheckQuantity > 0 鏄甯哥姸鎬侊紝涓嶅仛鎷︽埅锛�
if (!checkFlag
&& feedback.getUncheckQuantity() != null
&& feedback.getUncheckQuantity().compareTo(BigDecimal.ZERO) > 0) {
@@ -273,6 +371,12 @@
if (ObjUtil.equal(line.getQualityStatus(), MesWmQualityStatusEnum.PASS.getStatus())) {
qualifiedQty = qualifiedQty.add(line.getQuantity());
}
+ }
+ // 1.1 鍏滃簳锛氬叧閿潪璐ㄦ宸ュ簭瀹℃壒鏃朵骇鍑哄崟琛屽皻鏈敓鎴愶紝鐩存帴閲囩敤鎶ュ伐鍗曚笂鐨勫悎鏍�/涓嶈壇鏁伴噺
+ // 锛堥潪璐ㄦ宸ュ簭榛樿鍏ㄩ儴涓哄悎鏍煎搧锛涜川妫�宸ュ簭鐨勫悎鏍�/涓嶈壇鍦ㄨ川妫�鍥炶皟鍚庢寜浜у嚭琛岃仛鍚堬級
+ if (CollUtil.isEmpty(lines)) {
+ qualifiedQty = ObjectUtil.defaultIfNull(feedback.getQualifiedQuantity(), BigDecimal.ZERO);
+ unqualifiedQty = ObjectUtil.defaultIfNull(feedback.getUnqualifiedQuantity(), BigDecimal.ZERO);
}
// 2. 鏇存柊浠诲姟鐨勫凡鐢熶骇/鍚堟牸/涓嶅悎鏍兼暟閲�
@@ -373,21 +477,11 @@
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;
@@ -410,19 +504,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()
@@ -435,19 +520,29 @@
.setTaskId(reqVO.getTaskId())
.setItemId(task.getItemId())
.setFeedbackQuantity(reqVO.getFeedbackQuantity())
- .setQualifiedQuantity(reqVO.getQualifiedQuantity())
- .setUnqualifiedQuantity(reqVO.getUnqualifiedQuantity())
.setScheduledQuantity(task.getQuantity())
.setFeedbackTime(LocalDateTime.now())
.setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus())
.setRemark(reqVO.getRemark());
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())) {
+ 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
@@ -461,8 +556,6 @@
MesProFeedbackQuickCreateReqVO singleReq = new MesProFeedbackQuickCreateReqVO();
singleReq.setTaskId(taskId);
singleReq.setFeedbackQuantity(reqVO.getFeedbackQuantity());
- singleReq.setQualifiedQuantity(reqVO.getQualifiedQuantity());
- singleReq.setUnqualifiedQuantity(reqVO.getUnqualifiedQuantity());
singleReq.setRemark(reqVO.getRemark());
MesProFeedbackQuickCreateRespVO resp = quickCreateFeedback(singleReq);
results.add(new MesProFeedbackBatchCreateRespVO.BatchResult()
--
Gitblit v1.9.3