From ac2e2b5af3726ee64dc37c3ebf26989a0346f22a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 07 十一月 2026 19:16:05 +0800
Subject: [PATCH] feat(feedback): 优化报工审批流程并增加报工人校验

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java |   83 +++++++++++++++++++++++++----------------
 1 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java
index b3c8697..b819493 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java
@@ -11,6 +11,7 @@
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptImportRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptSaveReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail.MesWmProductReceiptDetailSaveReqVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
@@ -102,7 +103,8 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long generateProductReceipt(MesWmProductProduceDO produce,
-                                       List<MesWmProductProduceLineDO> produceLines) {
+                                       List<MesWmProductProduceLineDO> produceLines,
+                                       boolean lastProcess) {
         List<MesWmProductProduceLineDO> qualifiedLines = produceLines.stream()
                 .filter(line -> ObjUtil.equal(line.getQualityStatus(), MesWmQualityStatusEnum.PASS.getStatus()))
                 .filter(line -> line.getQuantity() != null && line.getQuantity().compareTo(BigDecimal.ZERO) > 0)
@@ -128,22 +130,16 @@
 
         MesWmProductReceiptDO receipt = MesWmProductReceiptDO.builder()
                 .code(code)
-                .name("鐢熶骇瀹屾垚鑷姩鍏ュ簱-" + workOrderCode)
+                .name((lastProcess ? "鐢熶骇瀹屾垚鑷姩鍏ュ簱-" : "宸ュ簭浜у嚭鑷姩鍏ュ簱-") + workOrderCode)
                 .workOrderId(produce.getWorkOrderId())
                 .produceId(produce.getId())
                 .itemId(firstMdmItemId)
                 .receiptDate(LocalDateTime.now())
                 .status(MesWmProductReceiptStatusEnum.PREPARE.getStatus())
-                .remark("鏈亾宸ュ簭浜у嚭鑷姩鐢熸垚锛屼骇鍑哄崟ID锛�" + produce.getId())
+                .remark((lastProcess ? "鏈亾宸ュ簭浜у嚭鑷姩鐢熸垚锛屼骇鍑哄崟ID锛�" : "涓棿宸ュ簭浜у嚭鑷姩鐢熸垚锛堝崐鎴愬搧锛夛紝浜у嚭鍗旾D锛�")
+                        + produce.getId())
                 .build();
         productReceiptMapper.insert(receipt);
-
-        MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(
-                MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE);
-        MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(
-                MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION);
-        MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(
-                MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA);
 
         for (MesWmProductProduceLineDO produceLine : qualifiedLines) {
             MesMdItemDO item = mdItemService.getItem(produceLine.getItemId());
@@ -151,21 +147,35 @@
                     ? item.getMdmItemId() : produceLine.getItemId();
             List<cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO> details =
                     productProduceDetailService.getProductProduceDetailListByLineId(produceLine.getId());
-            Long warehouseId = CollUtil.isNotEmpty(details) ? details.get(0).getWarehouseId() : virtualWarehouse.getId();
-            Long locationId = CollUtil.isNotEmpty(details) ? details.get(0).getLocationId() : virtualLocation.getId();
-            Long areaId = CollUtil.isNotEmpty(details) ? details.get(0).getAreaId() : virtualArea.getId();
+            if (CollUtil.isEmpty(details)) throw exception(WM_PRODUCT_RECPT_NO_DETAIL);
+            Long warehouseId = details.get(0).getWarehouseId();
+            Long locationId = details.get(0).getLocationId();
+            Long areaId = details.get(0).getAreaId();
             MesWmMaterialStockDO stock = materialStockService.getMaterialStockByCompositeKey(
                     mdmItemId, warehouseId, locationId, areaId,
                     produceLine.getBatchId(), null);
-            productReceiptLineMapper.insert(MesWmProductReceiptLineDO.builder()
+            MesWmProductReceiptLineDO receiptLine = MesWmProductReceiptLineDO.builder()
                     .receiptId(receipt.getId())
                     .itemId(mdmItemId)
                     .materialStockId(stock != null ? stock.getId() : null)
                     .quantity(produceLine.getQuantity())
                     .batchId(produceLine.getBatchId())
                     .batchCode(produceLine.getBatchCode())
-                    .remark("鏈亾宸ュ簭鍚堟牸鍝佽嚜鍔ㄧ敓鎴�")
-                    .build());
+                    .remark(lastProcess ? "鏈亾宸ュ簭鍚堟牸鍝佽嚜鍔ㄧ敓鎴�" : "涓棿宸ュ簭鍚堟牸鍝佽嚜鍔ㄧ敓鎴�")
+                    .build();
+            productReceiptLineMapper.insert(receiptLine);
+            for (var detail : details) {
+                MesWmProductReceiptDetailSaveReqVO detailReq = new MesWmProductReceiptDetailSaveReqVO();
+                detailReq.setReceiptId(receipt.getId());
+                detailReq.setLineId(receiptLine.getId());
+                detailReq.setItemId(mdmItemId);
+                detailReq.setQuantity(detail.getQuantity());
+                detailReq.setBatchId(detail.getBatchId());
+                detailReq.setWarehouseId(detail.getWarehouseId());
+                detailReq.setLocationId(detail.getLocationId());
+                detailReq.setAreaId(detail.getAreaId());
+                productReceiptDetailService.createProductReceiptDetail(detailReq);
+            }
         }
         return receipt.getId();
     }
@@ -266,11 +276,8 @@
             throw exception(WM_PRODUCT_RECPT_NO_DETAIL);
         }
 
-        // 鑷姩鍏ュ簱鍗曟潵婧愪骇鍑哄崟宸叉寜宸ヨ壓璺嚎浠撳簱璁拌处锛屾澶勪粎瀹屾垚涓氬姟鍗曟嵁锛岄伩鍏嶅疄闄呬粨搴撻噸澶嶅叆搴撱��
-        // 鎵嬪伐鍒涘缓鐨勪骇鍝佸叆搴撳崟浠嶆墽琛屸�滆櫄鎷熺嚎杈瑰簱 OUT + 瀹為檯浠撳簱 IN鈥濄��
-        if (receipt.getProduceId() == null) {
-            createTransactionList(receipt, details);
-        }
+        // 鎵ц鍏ュ簱鏃舵墠鐧昏瀹為檯浠撳簱搴撳瓨锛屼繚璇佲�滄湭涓婃灦涓嶄笂璐︹��
+        createTransactionList(receipt, details);
 
         // 鏇存柊鏀惰揣鍗曠姸鎬�
         productReceiptMapper.updateById(new MesWmProductReceiptDO()
@@ -283,9 +290,17 @@
         MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION);
         MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA);
 
-        // 2. 閬嶅巻鏄庣粏锛屾瘡鏉℃槑缁嗕骇鐢� OUT锛堣櫄鎷熺嚎杈瑰簱鎵e噺锛�+ IN锛堝疄闄呬粨搴撳鍔狅級
+        // 2. 閬嶅巻鏄庣粏鐧昏搴撳瓨浜嬪姟
         for (MesWmProductReceiptDetailDO detail : details) {
-            // 2.1 鍏堜粠铏氭嫙绾胯竟搴撳嚭搴擄紙搴撳瓨鍑忓皯锛�
+            // 2.1 鑷姩鍏ュ簱鍗曪細浜у嚭鍗曞畬鎴愭椂宸叉妸铏氭嫙绾胯竟搴撲骇鍑鸿璐︼紝杩欓噷鍙櫥璁板疄闄呬粨搴撳叆搴�
+            if (receipt.getProduceId() != null) {
+                if (virtualWarehouse != null && ObjUtil.equal(detail.getWarehouseId(), virtualWarehouse.getId())) {
+                    continue;
+                }
+                createInTransaction(receipt, detail, null);
+                continue;
+            }
+            // 2.2 鎵嬪伐鍏ュ簱鍗曪細铏氭嫙绾胯竟搴撳嚭搴� + 瀹為檯浠撳簱鍏ュ簱
             Long outTransactionId = wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO()
                     .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId())
                     .setQuantity(detail.getQuantity().negate()) // 搴撳瓨鍑忓皯
@@ -294,18 +309,22 @@
                     .setCheckFlag(false) // 绾胯竟搴撳厑璁歌礋搴撳瓨
                     .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId())
                     .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId()));
-            // 2.2 鍐嶅叆瀹為檯浠撳簱锛堝簱瀛樺鍔狅級
-            wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO()
-                    .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId())
-                    .setQuantity(detail.getQuantity()) // 搴撳瓨澧炲姞
-                    .setBatchId(detail.getBatchId())
-                    .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId())
-                    .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId())
-                    .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId())
-                    .setRelatedTransactionId(outTransactionId)); // 鍏宠仈鍑哄簱浜嬪姟
+            createInTransaction(receipt, detail, outTransactionId);
         }
     }
 
+    private void createInTransaction(MesWmProductReceiptDO receipt, MesWmProductReceiptDetailDO detail,
+                                     Long relatedTransactionId) {
+        wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO()
+                .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId())
+                .setQuantity(detail.getQuantity()) // 搴撳瓨澧炲姞
+                .setBatchId(detail.getBatchId())
+                .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId())
+                .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId())
+                .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId())
+                .setRelatedTransactionId(relatedTransactionId)); // 鍏宠仈鍑哄簱浜嬪姟
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void cancelProductReceipt(Long id) {

--
Gitblit v1.9.3