From 0857cf1830039d60ce73005f386f284cf575e511 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 26 十月 2026 14:00:19 +0800
Subject: [PATCH] feat(mes): 新增ERP销售订单生产状态枚举及MES工艺路线优化

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java |   99 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 93 insertions(+), 6 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 0692667..04f2b29 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
@@ -1,9 +1,10 @@
 package cn.iocoder.yudao.module.mes.service.pro.feedback;
 
 import cn.hutool.core.collection.CollUtil;
-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.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -31,6 +32,7 @@
 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.itemconsume.MesWmItemConsumeService;
+import cn.iocoder.yudao.module.mes.service.wm.productissue.MesWmProductIssueService;
 import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
 import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceService;
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
@@ -58,9 +60,11 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
 
 /**
@@ -89,6 +93,8 @@
     @Resource
     private MesWmItemConsumeService itemConsumeService;
     @Resource
+    private MesWmProductIssueService productIssueService;
+    @Resource
     private MesWmProductProduceService productProduceService;
     @Resource
     private MesWmProductProduceLineService produceLineService;
@@ -108,8 +114,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);
@@ -127,6 +134,63 @@
         MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class)
                 .setItemId(task.getItemId());
         feedbackMapper.updateById(updateObj);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public MesProFeedbackImportRespVO importFeedbackList(List<MesProFeedbackImportExcelVO> importList,
+                                                         boolean updateSupport) {
+        // 1. 鏍¢獙闈炵┖
+        if (CollUtil.isEmpty(importList)) {
+            throw exception(MES_PRO_FEEDBACK_IMPORT_LIST_IS_EMPTY);
+        }
+
+        // 2. 閫愯澶勭悊
+        MesProFeedbackImportRespVO respVO = MesProFeedbackImportRespVO.builder()
+                .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>())
+                .failureCodes(new LinkedHashMap<>()).build();
+        AtomicInteger index = new AtomicInteger(1);
+        importList.forEach(importItem -> {
+            int currentIndex = index.getAndIncrement();
+            String key = StrUtil.blankToDefault(importItem.getCode(), "绗� " + currentIndex + " 琛�");
+            if (StrUtil.isBlank(importItem.getCode())) {
+                respVO.getFailureCodes().put(key, "鎶ュ伐鍗曠紪鍙蜂笉鑳戒负绌�");
+                return;
+            }
+            if (StrUtil.isBlank(importItem.getTaskCode())) {
+                respVO.getFailureCodes().put(key, "鐢熶骇浠诲姟缂栫爜涓嶈兘涓虹┖");
+                return;
+            }
+            // 2.1 瑙f瀽鐢熶骇浠诲姟
+            MesProTaskDO task = taskService.getTaskByCode(importItem.getTaskCode().trim());
+            if (task == null) {
+                respVO.getFailureCodes().put(key, "鐢熶骇浠诲姟缂栫爜[" + importItem.getTaskCode() + "]涓嶅瓨鍦�");
+                return;
+            }
+            // 2.2 鏋勫缓璇锋眰骞跺垱寤�/鏇存柊锛堝鐢� create/update 鏈嶅姟锛屾姤宸ヤ汉/瀹℃牳浜哄彇褰撳墠鐧诲綍鐢ㄦ埛锛�
+            MesProFeedbackSaveReqVO reqVO = BeanUtils.toBean(importItem, MesProFeedbackSaveReqVO.class);
+            reqVO.setTaskId(task.getId());
+            Long loginUserId = getLoginUserId();
+            reqVO.setFeedbackUserId(ObjUtil.defaultIfNull(reqVO.getFeedbackUserId(), loginUserId));
+            reqVO.setApproveUserId(ObjUtil.defaultIfNull(reqVO.getApproveUserId(), loginUserId));
+            MesProFeedbackDO existFeedback = feedbackMapper.selectByCode(importItem.getCode());
+            try {
+                if (existFeedback == null) {
+                    reqVO.setId(null);
+                    createFeedback(reqVO);
+                    respVO.getCreateCodes().add(importItem.getCode());
+                } else if (updateSupport) {
+                    reqVO.setId(existFeedback.getId());
+                    updateFeedback(reqVO);
+                    respVO.getUpdateCodes().add(importItem.getCode());
+                } else {
+                    respVO.getFailureCodes().put(key, "鎶ュ伐鍗曠紪鍙峰凡瀛樺湪");
+                }
+            } catch (ServiceException e) {
+                respVO.getFailureCodes().put(key, e.getMessage());
+            }
+        });
+        return respVO;
     }
 
     @Override
@@ -174,7 +238,9 @@
     @Override
     public void rejectFeedback(Long id) {
         // 1. 鏍¢獙瀛樺湪 + 瀹℃壒涓姸鎬�
-        validateFeedbackStatusApproving(id);
+        MesProFeedbackDO feedback = validateFeedbackStatusApproving(id);
+        // 1.1 鏍¢獙褰撳墠鐧诲綍浜烘槸璇ユ姤宸ュ崟鐨勬寚瀹氬鏍镐汉
+        validateCurrentUserIsApprover(feedback);
 
         // 2. 鏇存柊鐘舵�佷负鑽夌
         feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
@@ -186,6 +252,8 @@
     public boolean approveFeedback(MesProFeedbackApproveReqVO reqVO) {
         // 1.1 鏍¢獙瀛樺湪 + 瀹℃壒涓姸鎬�
         MesProFeedbackDO feedback = validateFeedbackStatusApproving(reqVO.getId());
+        // 1.1.1 鏍¢獙褰撳墠鐧诲綍浜烘槸璇ユ姤宸ュ崟鐨勬寚瀹氬鏍镐汉
+        validateCurrentUserIsApprover(feedback);
         // 1.2 鏍¢獙鎶ュ伐鏁伴噺 > 0
         if (feedback.getFeedbackQuantity() == null
                 || feedback.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
@@ -209,9 +277,9 @@
         // 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枡
+            List<MesProWorkOrderBomDO> boms = workOrderBomService.getWorkOrderBomListByWorkOrderIdAndProcessId(
+                    feedback.getWorkOrderId(), feedback.getProcessId());
             if (CollUtil.isEmpty(boms)) {
                 throw exception(PRO_FEEDBACK_BACKFLUSH_BOM_REQUIRED);
             }
@@ -219,6 +287,8 @@
             MesWmItemConsumeDO itemConsume = itemConsumeService.generateItemConsume(feedback);
             if (itemConsume != null) {
                 itemConsumeService.finishItemConsume(itemConsume.getId());
+                // 娑堣�楀崟璐熻矗瀹為檯鎵e簱锛涢鏂欏崟浠呬綔涓哄�掑啿涓氬姟鍑瘉锛岄伩鍏嶉噸澶嶆墸鍑忓簱瀛�
+                productIssueService.generateBackflushProductIssue(feedback, itemConsume);
             }
         }
 
@@ -351,6 +421,23 @@
     }
 
     /**
+     * 鏍¢獙褰撳墠鐧诲綍鐢ㄦ埛鏄惁涓烘姤宸ュ崟鎸囧畾鐨勫鏍镐汉
+     *
+     * 鎶ュ伐鍗曞垱寤烘椂蹇呴』鎸囧畾 approveUserId锛屽鎵归�氳繃/椹冲洖鍙兘鐢辫瀹℃牳浜烘搷浣滐紝
+     * 閬垮厤浠绘剰鎷ユ湁鑿滃崟鏉冮檺鐨勭敤鎴疯秺鏉冨鎵广��
+     *
+     * @param feedback 鎶ュ伐鍗�
+     */
+    private void validateCurrentUserIsApprover(MesProFeedbackDO feedback) {
+        if (feedback.getApproveUserId() == null) {
+            throw exception(PRO_FEEDBACK_APPROVER_NOT_CONFIGURED);
+        }
+        if (!feedback.getApproveUserId().equals(getLoginUserId())) {
+            throw exception(PRO_FEEDBACK_NOT_APPROVER);
+        }
+    }
+
+    /**
      * 鏍¢獙鎶ュ伐鍗曠殑涓氬姟鏁版嵁锛堝垱寤� & 淇敼鍏辩敤锛�
      *
      * <p>浠ョ敓浜т换鍔′负鏍稿績锛氬墠绔彧闇�浼� taskId锛寃orkOrderId銆乺outeId銆乸rocessId銆乮temId銆亀orkstationId

--
Gitblit v1.9.3