From 6d910029b6c81db0a2b66caa66952781397b153a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 29 八月 2026 13:45:52 +0800
Subject: [PATCH] feat(mes): 实现H5溯源页面与二维码内容集成

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java |  156 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 155 insertions(+), 1 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java
index efaf298..f1e8aa1 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java
@@ -2,16 +2,33 @@
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
+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.wm.stocktaking.task.vo.MesWmStockTakingTaskPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.MesWmStockTakingTaskSaveReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.MesWmStockTakingTaskScanReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.pallet.MesProPalletDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskLineDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskResultDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task.MesWmStockTakingTaskLineMapper;
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task.MesWmStockTakingTaskMapper;
+import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTaskStatusEnum;
+import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
+import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService;
+import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService;
 import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
 import cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan.MesWmStockTakingPlanService;
+import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
+import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import jakarta.annotation.Resource;
 import org.springframework.context.annotation.Lazy;
@@ -19,6 +36,7 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -28,7 +46,7 @@
 /**
  * MES 鐩樼偣浠诲姟 Service 瀹炵幇绫�
  *
- * @author 鑺嬮亾婧愮爜
+ * @author 瓒呯骇绠$悊鍛�
  */
 @Service
 @Validated
@@ -47,6 +65,20 @@
     @Lazy
     @Resource
     private MesWmStockTakingTaskResultService stockTakingTaskResultService;
+
+    @Resource
+    private MesWmTransactionService wmTransactionService;
+
+    @Resource
+    private MesWmStockTakingTaskLineMapper stockTakingTaskLineMapper;
+    @Resource
+    private MesWmBatchService mesWmBatchService;
+    @Resource
+    private MesProBatchService proBatchService;
+    @Resource
+    private MesProBagCodeMapper bagCodeMapper;
+    @Resource
+    private MesProPalletMapper palletMapper;
 
     @Resource
     private AdminUserApi adminUserApi;
@@ -220,4 +252,126 @@
         }
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long scanStockTakingTask(MesWmStockTakingTaskScanReqVO scanReqVO) {
+        // 1. 鏍¢獙浠诲姟瀛樺湪涓斿浜庣洏鐐逛腑鐘舵��
+        validateStockTakingTaskExistsAndApproving(scanReqVO.getTaskId());
+
+        // 2. 瑙f瀽杩芥函鐮佸畾浣嶄粨搴撴壒娆★紙鏀寔鎵规鍙�/琚嬬爜/鎵樼洏鐮侊紝璧扮敓浜ф壒娆℃ˉ鎺ワ級
+        MesWmBatchDO wmBatch = resolveWmBatchByScanCode(scanReqVO.getScanCode());
+        if (wmBatch == null) {
+            throw exception(WM_STOCK_TAKING_TASK_SCAN_BATCH_NOT_FOUND);
+        }
+
+        // 3. 鍦ㄤ换鍔¤寖鍥村唴瀹氫綅浠诲姟琛�
+        MesWmStockTakingTaskLineDO line = stockTakingTaskLineMapper
+                .selectByTaskIdAndBatchId(scanReqVO.getTaskId(), wmBatch.getId());
+        if (line == null) {
+            throw exception(WM_STOCK_TAKING_TASK_SCAN_BATCH_NOT_IN_TASK);
+        }
+
+        // 4. 鍐欏叆鐩樼偣缁撴灉锛堝鐢� createStockTakingTaskResult锛氬惈閲嶅鐩樼偣鏍¢獙锛岃仈鍔ㄦ洿鏂颁换鍔¤鐩樼偣鏁伴噺涓庣泩浜忕姸鎬侊級
+        MesWmStockTakingTaskResultSaveReqVO resultReqVO = new MesWmStockTakingTaskResultSaveReqVO()
+                .setTaskId(line.getTaskId()).setLineId(line.getId())
+                .setMaterialStockId(line.getMaterialStockId())
+                .setItemId(line.getItemId()).setBatchId(line.getBatchId()).setBatchCode(line.getBatchCode())
+                .setWarehouseId(line.getWarehouseId()).setLocationId(line.getLocationId()).setAreaId(line.getAreaId())
+                .setTakingQuantity(scanReqVO.getTakingQuantity())
+                .setRemark(scanReqVO.getRemark());
+        return stockTakingTaskResultService.createStockTakingTaskResult(resultReqVO);
+    }
+
+    /**
+     * 瑙f瀽杩芥函鐮佸畾浣嶄粨搴撴壒娆★細渚濇鍖归厤鎵规鍙枫�佽鐮併�佹墭鐩樼爜锛岀敓浜ф壒娆$粡妗ユ帴杩斿洖浠撳簱鎵规
+     */
+    private MesWmBatchDO resolveWmBatchByScanCode(String scanCode) {
+        if (StrUtil.isBlank(scanCode)) {
+            return null;
+        }
+        // 1. 鐩存帴鍛戒腑浠撳簱鎵规鍙�
+        MesWmBatchDO wmBatch = mesWmBatchService.getBatchByCode(scanCode);
+        if (wmBatch != null) {
+            return wmBatch;
+        }
+        // 2. 鍛戒腑琚嬬爜
+        MesProBagCodeDO bag = bagCodeMapper.selectByCode(scanCode);
+        if (bag != null && bag.getBatchId() != null) {
+            return bridgeProBatch(bag.getBatchId());
+        }
+        // 3. 鍛戒腑鎵樼洏鐮�
+        MesProPalletDO pallet = palletMapper.selectByCode(scanCode);
+        if (pallet != null && pallet.getBatchId() != null) {
+            return bridgeProBatch(pallet.getBatchId());
+        }
+        return null;
+    }
+
+    private MesWmBatchDO bridgeProBatch(Long proBatchId) {
+        MesProBatchDO proBatch = proBatchService.getBatch(proBatchId);
+        if (proBatch == null) {
+            return null;
+        }
+        return mesWmBatchService.getOrCreateByProBatch(proBatch);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void processStockTakingDifference(Long id) {
+        // 1. 鏍¢獙浠诲姟瀛樺湪涓斿凡瀹屾垚
+        MesWmStockTakingTaskDO task = validateStockTakingTaskExists(id);
+        if (!MesWmStockTakingTaskStatusEnum.FINISHED.getStatus().equals(task.getStatus())) {
+            throw exception(WM_STOCK_TAKING_TASK_NOT_FINISHED);
+        }
+
+        // 2. 鑾峰彇鐩樼偣缁撴灉鍒楄〃
+        List<MesWmStockTakingTaskResultDO> results = stockTakingTaskResultService.getStockTakingTaskResultListByTaskId(id);
+        if (CollUtil.isEmpty(results)) {
+            return; // 鏃犵洏鐐圭粨鏋滐紝鏃犻渶澶勭悊
+        }
+
+        // 3. 閬嶅巻缁撴灉锛屽鐞嗗樊寮�
+        for (MesWmStockTakingTaskResultDO result : results) {
+            BigDecimal bookQuantity = result.getQuantity();          // 璐﹂潰鏁伴噺
+            BigDecimal takingQuantity = result.getTakingQuantity(); // 鐩樼偣鏁伴噺
+
+            if (takingQuantity == null || bookQuantity == null) {
+                continue;
+            }
+
+            // 璁$畻宸紓锛氱洏鐐规暟閲� - 璐﹂潰鏁伴噺
+            BigDecimal difference = takingQuantity.subtract(bookQuantity);
+
+            if (difference.compareTo(BigDecimal.ZERO) == 0) {
+                continue; // 鏃犲樊寮傦紝璺宠繃
+            }
+
+            // 4. 鍒涘缓搴撳瓨璋冩暣浜嬪姟
+            MesWmTransactionSaveReqDTO transaction = new MesWmTransactionSaveReqDTO()
+                    .setItemId(result.getItemId())
+                    .setBatchId(result.getBatchId())
+                    .setBatchCode(result.getBatchCode())
+                    .setWarehouseId(result.getWarehouseId())
+                    .setLocationId(result.getLocationId())
+                    .setAreaId(result.getAreaId())
+                    .setBizId(task.getId())
+                    .setBizCode(task.getCode())
+                    .setBizLineId(result.getLineId());
+
+            if (difference.compareTo(BigDecimal.ZERO) > 0) {
+                // 鐩樼泩锛氬簱瀛樺鍔�
+                transaction.setType(MesWmTransactionTypeEnum.IN.getType())
+                        .setQuantity(difference)
+                        .setBizType(MesBizTypeConstants.WM_STOCK_TAKING);
+            } else {
+                // 鐩樹簭锛氬簱瀛樺噺灏�
+                transaction.setType(MesWmTransactionTypeEnum.OUT.getType())
+                        .setQuantity(difference.negate()) // 鍑哄簱鏁伴噺浼犳鏁帮紝浣嗗唴閮ㄤ細杞负璐熸暟
+                        .setBizType(MesBizTypeConstants.WM_STOCK_TAKING);
+            }
+
+            wmTransactionService.createTransaction(transaction);
+        }
+    }
+
 }

--
Gitblit v1.9.3