From 704265308b1227dbada5a36b2027b588c062ded2 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 12 十月 2026 09:14:37 +0800
Subject: [PATCH] feat(mes): 新增业务码支持并优化追溯查询功能

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java |  224 +++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 151 insertions(+), 73 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
index 628720f..b72e8f0 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
@@ -52,7 +52,13 @@
 import org.springframework.validation.annotation.Validated;
 
 import java.math.BigDecimal;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
+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.pro.batch.MesProBatchMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstockbag.MesWmMaterialStockBagMapper;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstockbag.MesWmMaterialStockBagDO;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@@ -103,6 +109,10 @@
 
     @Resource
     private MesTraceIntegrityService integrityService;
+    @Resource private MesProBagCodeMapper pickingBagMapper;
+    @Resource private MesProPalletMapper pickingPalletMapper;
+    @Resource private MesProBatchMapper pickingBatchMapper;
+    @Resource private MesWmMaterialStockBagMapper pickingStockBagMapper;
 
     @Override
     public Long createProductSales(MesWmProductSalesSaveReqVO createReqVO) {
@@ -222,83 +232,150 @@
         return true;
     }
 
+    private record PickingScope(String type, Long id, MesProBatchDO batch, List<MesProBagCodeDO> bags) { }
+
+    private PickingScope pickingScope(String code, String type, boolean lock) {
+        if (type == null || type.isBlank()) {
+            type = palletService.getPalletByScanCode(code) != null ? "PALLET"
+                    : bagCodeService.getBagCodeByScanCode(code) != null ? "BAG" : "BATCH";
+        }
+        MesProBatchDO batch;
+        List<MesProBagCodeDO> bags;
+        Long id;
+        switch (type) {
+            case "BAG" -> {
+                MesProBagCodeDO bag = lock ? pickingBagMapper.selectByScanCodeForUpdate(code) : bagCodeService.getBagCodeByScanCode(code);
+                if (bag == null || Integer.valueOf(30).equals(bag.getStatus())) throw new IllegalArgumentException("琚嬬爜涓嶅瓨鍦ㄦ垨宸蹭綔搴�");
+                id = bag.getId(); batch = proBatchService.getBatch(bag.getBatchId()); bags = List.of(bag);
+            }
+            case "PALLET" -> {
+                MesProPalletDO pallet = lock ? pickingPalletMapper.selectByScanCodeForUpdate(code) : palletService.getPalletByScanCode(code);
+                if (pallet == null || Integer.valueOf(20).equals(pallet.getStatus())) throw new IllegalArgumentException("鎵樼洏涓嶅瓨鍦ㄦ垨宸蹭綔搴�");
+                if (pallet.getBatchId() == null) throw exception(PRO_PALLET_NOT_BIND_BATCH);
+                id = pallet.getId(); batch = proBatchService.getBatch(pallet.getBatchId());
+                bags = lock ? pickingBagMapper.selectListByPalletIdForUpdate(id) : bagCodeService.getBagCodeListByPalletId(id);
+            }
+            case "BATCH" -> {
+                batch = lock ? pickingBatchMapper.selectByScanCodeForUpdate(code) : proBatchService.getBatchByScanCode(code);
+                if (batch == null) throw new IllegalArgumentException("鐢熶骇鎵规鐮佷笉瀛樺湪");
+                id = batch.getId(); bags = lock ? pickingBagMapper.selectListByBatchIdForUpdate(id) : bagCodeService.getBagCodeListByBatchId(id);
+            }
+            default -> throw new IllegalArgumentException("涓嶆敮鎸佺殑鎷h揣鎵爜绫诲瀷");
+        }
+        if (batch == null || batch.getItemId() == null || Integer.valueOf(40).equals(batch.getStatus()))
+            throw new IllegalArgumentException("鏈粦瀹氭湁鏁堝搧绉嶆垨鐢熶骇鎵规宸蹭綔搴�");
+        return new PickingScope(type, id, batch, bags.stream().filter(b -> !Integer.valueOf(30).equals(b.getStatus()))
+                .sorted(Comparator.comparing(MesProBagCodeDO::getId)).toList());
+    }
+
+    private String unavailable(MesProBagCodeDO bag, MesWmMaterialStockBagDO stockBag,
+            Map<Long, MesWmMaterialStockDO> stocks, List<MesWmProductSalesDetailDO> occupied, MesProBatchDO batch) {
+        if (!Objects.equals(bag.getBatchId(), batch.getId())) return "琚嬬爜鎵规褰掑睘寮傚父";
+        if (bag.getItemId() != null && !Objects.equals(bag.getItemId(), batch.getItemId())) return "琚嬬爜鍝佺褰掑睘寮傚父";
+        if (!MesProBagCodeQcStatusEnum.QUALIFIED.getStatus().equals(bag.getQcStatus())) return "灏氭湭璐ㄦ鍚堟牸";
+        if (stockBag == null || !Integer.valueOf(1).equals(stockBag.getStatus())) return "涓嶅湪搴撴垨宸插嚭搴�";
+        if (Boolean.TRUE.equals(stockBag.getFrozen())) return "琚嬬爜宸插喕缁�";
+        if (!Integer.valueOf(20).equals(stockBag.getStockState()) || !Objects.equals(stockBag.getItemId(), batch.getItemId())
+                || !stocks.containsKey(stockBag.getMaterialStockId()) || stockBag.getQuantity() == null || BigDecimal.ONE.compareTo(stockBag.getQuantity()) != 0)
+            return "琚嬬爜涓嶅湪鏈夋晥鍚堟牸搴撳瓨涓�";
+        if (occupied.stream().anyMatch(d -> Objects.equals(d.getBagCodeId(), bag.getId())
+                || d.getBagCodeId() == null && bag.getPalletId() != null && Objects.equals(d.getPalletCodeId(), bag.getPalletId())))
+            return "宸插姞鍏ュ嚭搴撳崟鎷h揣";
+        return null;
+    }
+
+    @Override
+    public MesWmProductSalesScanRespVO previewScan(String code) { return previewScan(code, null, null); }
+
+    /** 鍙璇嗗埆锛屽苟杩斿洖姣忚鐨勫彲閫夌姸鎬侊紝涓嶅垱寤哄簱瀛樻壒娆℃垨鎷h揣璁板綍銆� */
+    @Override
+    public MesWmProductSalesScanRespVO previewScan(String code, String scanType, Long salesId) {
+        PickingScope scope = pickingScope(code, scanType, false);
+        if (salesId != null) {
+            MesWmProductSalesDO sales = validateProductSalesExists(salesId);
+            if (!Integer.valueOf(2).equals(sales.getStatus())) throw exception(WM_PRODUCT_SALES_CANNOT_PICK);
+            if (productSalesLineService.getProductSalesLineListBySalesId(salesId).stream()
+                    .noneMatch(l -> Objects.equals(l.getItemId(), scope.batch().getItemId()))) throw exception(WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH);
+        }
+        MesWmBatchDO wmBatch = mesWmBatchService.getBatchByCode(scope.batch().getCode());
+        Map<Long, MesWmMaterialStockDO> stocks = wmBatch == null ? Map.of() : materialStockService
+                .getQualifiedMaterialStockListByItemAndBatch(scope.batch().getItemId(), wmBatch.getId()).stream()
+                .collect(Collectors.toMap(MesWmMaterialStockDO::getId, x -> x));
+        Map<Long, MesWmMaterialStockBagDO> stockBags = pickingStockBagMapper.selectByBagIds(scope.bags().stream().map(MesProBagCodeDO::getId).toList(), false)
+                .stream().collect(Collectors.toMap(MesWmMaterialStockBagDO::getBagCodeId, x -> x));
+        List<MesWmProductSalesDetailDO> occupied = productSalesDetailMapper.selectPickingByBatchCode(scope.batch().getCode());
+        List<MesWmProductSalesScanRespVO.BagOption> options = scope.bags().stream().map(b -> {
+            String reason = unavailable(b, stockBags.get(b.getId()), stocks, occupied, scope.batch());
+            return new MesWmProductSalesScanRespVO.BagOption().setId(b.getId()).setCode(b.getCode()).setBusinessCode(b.getBusinessCode())
+                    .setPalletId(b.getPalletId()).setSelectable(reason == null).setUnavailableReason(reason);
+        }).toList();
+        return new MesWmProductSalesScanRespVO().setScanType(scope.type()).setCodeId(scope.id()).setScanContent(code)
+                .setBatchCode(scope.batch().getCode()).setItemId(scope.batch().getItemId()).setBagCount(options.size()).setBags(options)
+                .setScanQuantity(BigDecimal.valueOf(options.stream().filter(o -> Boolean.TRUE.equals(o.getSelectable())).count()));
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public MesWmProductSalesScanRespVO scanProductSales(MesWmProductSalesScanReqVO reqVO) {
-        MesWmProductSalesDO sales = validateProductSalesExists(reqVO.getSalesId());
-        if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.APPROVING.getStatus(), sales.getStatus())) {
-            throw exception(WM_PRODUCT_SALES_CANNOT_PICK);
+        MesWmProductSalesDO sales = productSalesMapper.selectByIdForUpdate(reqVO.getSalesId());
+        if (sales == null) throw exception(WM_PRODUCT_SALES_NOT_EXISTS);
+        if (!Integer.valueOf(2).equals(sales.getStatus())) throw exception(WM_PRODUCT_SALES_CANNOT_PICK);
+        PickingScope scope = pickingScope(reqVO.getScanContent(), reqVO.getScanType(), true);
+        List<Long> ids = reqVO.getBagIds();
+        if (ids == null && "BAG".equals(scope.type())) ids = List.of(scope.id());
+        if (ids == null || ids.isEmpty() || new HashSet<>(ids).size() != ids.size())
+            throw new IllegalArgumentException("璇烽�夋嫨鍏蜂綋琚嬬爜锛屼笉鍏佽閲嶅琚嬬爜");
+        BigDecimal quantity = BigDecimal.valueOf(ids.size());
+        if (reqVO.getQuantity() != null && quantity.compareTo(reqVO.getQuantity()) != 0)
+            throw new IllegalArgumentException("鎷h揣鏁伴噺蹇呴』涓庢墍閫夎鐮佹暟閲忎竴鑷�");
+        Set<Long> selectedIds = new HashSet<>(ids);
+        List<MesProBagCodeDO> selected = scope.bags().stream().filter(b -> selectedIds.contains(b.getId())).toList();
+        if (selected.size() != ids.size()) throw new IllegalArgumentException("鎵�閫夎鐮佷笉灞炰簬褰撳墠鎵爜瀵硅薄鎴栧凡浣滃簾锛岃閲嶆柊鏍稿");
+        // 閿佸畾瀹為檯琚嬬爜鍜屽簱瀛樿鏄庣粏锛岃法鍑哄簱鍗曠殑鎵爜涔熶笉鑳介噸澶嶆嫞閫夊悓涓�琚嬨��
+        List<MesWmMaterialStockBagDO> stockBagRows = pickingStockBagMapper.selectByBagIds(ids, true);
+        Map<Long, MesWmMaterialStockBagDO> stockBags = stockBagRows.stream().collect(Collectors.toMap(MesWmMaterialStockBagDO::getBagCodeId, x -> x));
+        List<MesWmProductSalesDetailDO> occupied = productSalesDetailMapper.selectPickingByBatchCodeForUpdate(scope.batch().getCode());
+        List<MesWmProductSalesDetailDO> own = occupied.stream().filter(d -> Objects.equals(d.getSalesId(), sales.getId())).toList();
+        long already = selected.stream().filter(b -> own.stream().anyMatch(d -> Objects.equals(d.getBagCodeId(), b.getId()))).count();
+        if (already == selected.size()) return new MesWmProductSalesScanRespVO().setScanType(scope.type()).setCodeId(scope.id())
+                .setScanContent(reqVO.getScanContent()).setSelectedBagIds(ids).setAlreadyScanned(true).setOutboundQuantity(quantity)
+                .setDetailId(own.stream().filter(d -> selectedIds.contains(d.getBagCodeId())).findFirst().orElseThrow().getId()).setMessage("鎵�閫夎鐮佸凡鍦ㄦ湰鍗曟嫞璐ф槑缁嗕腑");
+        if (already > 0) throw new IllegalArgumentException("鎵�閫夎鐮侀儴鍒嗗凡鍔犲叆鏈崟锛岃閲嶆柊閫夋嫨鏈嫞琚嬬爜");
+        MesWmBatchDO wmBatch = mesWmBatchService.getBatchByCode(scope.batch().getCode());
+        if (wmBatch == null) throw exception(WM_TRANSACTION_BATCH_NOT_EXISTS);
+        Map<Long, MesWmMaterialStockDO> stocks = materialStockService.getQualifiedMaterialStockListByItemAndBatch(scope.batch().getItemId(), wmBatch.getId())
+                .stream().collect(Collectors.toMap(MesWmMaterialStockDO::getId, x -> x));
+        for (MesProBagCodeDO bag : selected) {
+            String reason = unavailable(bag, stockBags.get(bag.getId()), stocks, occupied, scope.batch());
+            if (reason != null) throw new IllegalArgumentException("琚嬬爜 " + bag.getCode() + "锛�" + reason);
         }
-        MesProPalletDO pallet = palletService.getPalletByCode(reqVO.getScanContent());
-        MesProBagCodeDO bag = pallet == null ? bagCodeService.getBagCodeByCode(reqVO.getScanContent()) : null;
-        if (pallet == null && bag == null) {
-            throw exception(WM_MATERIAL_STOCK_NOT_EXISTS);
-        }
-        // 鏈粦瀹氱敓浜ф壒娆$殑涓存椂鎵樼洏涓嶅厑璁稿弬涓庨攢鍞嚭搴�
-        if (pallet != null && pallet.getBatchId() == null) {
-            throw exception(PRO_PALLET_NOT_BIND_BATCH);
-        }
-        // 绉嶅瓙璐ㄦ鎸夎鐮佺矑搴︽祦杞悗锛屽嚭搴撳彧鍏佽宸茶川妫�鍚堟牸鐨勮鐮�/鎵樼洏
-        if (pallet != null) {
-            List<MesProBagCodeDO> palletBags = bagCodeService.getBagCodeListByPalletId(pallet.getId());
-            if (palletBags.stream().anyMatch(b -> !MesProBagCodeQcStatusEnum.QUALIFIED.getStatus().equals(b.getQcStatus()))) {
-                throw exception(WM_PRODUCT_SALES_SCAN_PALLET_NOT_ALL_QUALIFIED);
-            }
-        } else if (!MesProBagCodeQcStatusEnum.QUALIFIED.getStatus().equals(bag.getQcStatus())) {
-            throw exception(WM_PRODUCT_SALES_SCAN_BAG_NOT_QUALIFIED);
-        }
-        Long codeId = pallet != null ? pallet.getId() : bag.getId();
-        MesWmProductSalesDetailDO existed = pallet != null
-                ? productSalesDetailMapper.selectBySalesIdAndPalletCodeId(reqVO.getSalesId(), codeId)
-                : productSalesDetailMapper.selectBySalesIdAndBagCodeId(reqVO.getSalesId(), codeId);
-        if (existed != null) {
-            return new MesWmProductSalesScanRespVO().setScanType(pallet != null ? "PALLET" : "BAG")
-                    .setCodeId(codeId).setScanContent(reqVO.getScanContent()).setAlreadyScanned(true)
-                    .setDetailId(existed.getId()).setOutboundQuantity(existed.getQuantity()).setMessage("璇ョ爜宸叉壂鎻�");
-        }
-        Long proBatchId = pallet != null ? pallet.getBatchId() : bag.getBatchId();
-        MesProBatchDO batch = proBatchService.getBatch(proBatchId);
-        if (batch == null) {
-            throw exception(WM_TRANSACTION_BATCH_NOT_EXISTS);
-        }
-        // 鐢熶骇鎵规妗ユ帴浠撳簱鎵规锛氭壂鐮佸叆搴撳啓鍏ョ殑鏄粨搴撴壒娆★紙mes_wm_batch锛夛紝姝ゅ蹇呴』鐢ㄤ粨搴撴壒娆� id 鏌ュ簱瀛�
-        MesWmBatchDO wmBatch = mesWmBatchService.getOrCreateByProBatch(batch);
-        if (wmBatch == null) {
-            throw exception(WM_TRANSACTION_BATCH_NOT_EXISTS);
-        }
-        List<MesWmProductSalesLineDO> lines = productSalesLineService.getProductSalesLineListBySalesId(reqVO.getSalesId());
-        MesWmProductSalesLineDO line = lines.stream().filter(item -> ObjUtil.equal(item.getItemId(), batch.getItemId())).findFirst().orElse(null);
-        if (line == null) {
-            throw exception(WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH);
-        }
-        BigDecimal quantity = reqVO.getQuantity();
-        if (quantity == null) {
-            quantity = line.getQuantity();
-        }
-        // 鍙粠鍚堟牸搴撹褰曚腑閫夊簱瀛橈紙鍚屾壒娆℃殏瀛樺簱璁板綍涓嶅彲鍑哄簱锛�
-        List<MesWmMaterialStockDO> stocks = materialStockService.getQualifiedMaterialStockListByItemAndBatch(batch.getItemId(), wmBatch.getId());
-        BigDecimal outboundQuantity = quantity;
-        MesWmMaterialStockDO stock = stocks.stream().filter(item -> item.getQuantity().compareTo(outboundQuantity) >= 0).findFirst().orElse(null);
-        if (stock == null) {
-            throw exception(WM_MATERIAL_STOCK_INSUFFICIENT);
-        }
+        MesWmProductSalesLineDO line = productSalesLineService.getProductSalesLineListBySalesId(sales.getId()).stream()
+                .filter(l -> Objects.equals(l.getItemId(), scope.batch().getItemId())).findFirst().orElse(null);
+        if (line == null) throw exception(WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH);
         BigDecimal scanned = productSalesDetailService.getProductSalesDetailListByLineId(line.getId()).stream()
                 .map(MesWmProductSalesDetailDO::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
-        if (scanned.add(quantity).compareTo(line.getQuantity()) > 0) {
-            throw exception(WM_PRODUCT_SALES_LINE_QUANTITY_INVALID);
+        if (line.getQuantity() == null || scanned.add(quantity).compareTo(line.getQuantity()) > 0) throw exception(WM_PRODUCT_SALES_LINE_QUANTITY_INVALID);
+        Map<Long, Long> byStock = selected.stream().collect(Collectors.groupingBy(b -> stockBags.get(b.getId()).getMaterialStockId(), Collectors.counting()));
+        for (var allocation : byStock.entrySet()) {
+            BigDecimal ownStockQty = own.stream().filter(d -> Objects.equals(d.getMaterialStockId(), allocation.getKey()))
+                    .map(MesWmProductSalesDetailDO::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
+            if (stocks.get(allocation.getKey()).getQuantity().compareTo(ownStockQty.add(BigDecimal.valueOf(allocation.getValue()))) < 0)
+                throw exception(WM_MATERIAL_STOCK_INSUFFICIENT);
         }
-        MesWmProductSalesDetailDO detail = new MesWmProductSalesDetailDO().setLineId(line.getId())
-                .setSalesId(reqVO.getSalesId()).setItemId(batch.getItemId()).setQuantity(quantity)
-                .setMaterialStockId(stock.getId()).setBatchId(wmBatch.getId()).setBatchCode(wmBatch.getCode())
-                .setWarehouseId(stock.getWarehouseId()).setLocationId(stock.getLocationId()).setAreaId(stock.getAreaId())
-                .setBagCodeId(pallet == null ? codeId : null).setPalletCodeId(pallet != null ? codeId : null);
-        productSalesDetailMapper.insert(detail);
-        return new MesWmProductSalesScanRespVO().setScanType(pallet != null ? "PALLET" : "BAG")
-                .setCodeId(codeId).setScanContent(reqVO.getScanContent()).setItemId(batch.getItemId())
-                .setBatchId(wmBatch.getId()).setBatchCode(wmBatch.getCode()).setMaterialStockId(stock.getId())
-                .setAvailableQuantity(stock.getQuantity()).setScanQuantity(quantity).setOutboundQuantity(quantity)
-                .setAlreadyScanned(false).setDetailId(detail.getId()).setWarehouseId(stock.getWarehouseId())
-                .setLocationId(stock.getLocationId()).setAreaId(stock.getAreaId()).setMessage("鎵爜鎴愬姛");
+        Long firstDetail = null;
+        for (MesProBagCodeDO bag : selected) {
+            MesWmMaterialStockDO stock = stocks.get(stockBags.get(bag.getId()).getMaterialStockId());
+            MesWmProductSalesDetailDO detail = new MesWmProductSalesDetailDO().setSalesId(sales.getId()).setLineId(line.getId())
+                    .setItemId(scope.batch().getItemId()).setQuantity(BigDecimal.ONE).setBagCodeId(bag.getId())
+                    .setPalletCodeId(bag.getPalletId()).setBatchId(wmBatch.getId()).setBatchCode(wmBatch.getCode()).setMaterialStockId(stock.getId())
+                    .setWarehouseId(stock.getWarehouseId()).setLocationId(stock.getLocationId()).setAreaId(stock.getAreaId())
+                    .setRemark("鎵爜绫诲瀷 " + scope.type() + "锛涙潵婧愮爜 " + reqVO.getScanContent() + "锛涜鐮� " + bag.getCode());
+            productSalesDetailMapper.insert(detail);
+            if (firstDetail == null) firstDetail = detail.getId();
+        }
+        return new MesWmProductSalesScanRespVO().setScanType(scope.type()).setCodeId(scope.id()).setScanContent(reqVO.getScanContent())
+                .setItemId(scope.batch().getItemId()).setBatchCode(wmBatch.getCode()).setSelectedBagIds(ids)
+                .setScanQuantity(quantity).setOutboundQuantity(quantity).setAlreadyScanned(false).setDetailId(firstDetail).setMessage("宸叉寜鎵�閫夎鐮佸姞鍏ユ嫞璐�");
     }
 
     @Override
@@ -398,7 +475,8 @@
             if (detail.getBagCodeId() != null) {
                 bagCodeService.markOutbound(detail.getBagCodeId(), id);
             }
-            if (detail.getPalletCodeId() != null) {
+            // 閮ㄥ垎鎵樼洏鎷h揣鍙兘鍒嗙粰澶氫釜缁忛攢鍟嗭紝涓嶈兘鎶婃暣涓墭鐩樻爣璁颁负鏈崟鍑哄簱銆�
+            if (detail.getPalletCodeId() != null && detail.getBagCodeId() == null) {
                 palletService.markOutbound(detail.getPalletCodeId(), id);
             }
         }
@@ -428,7 +506,7 @@
                 .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId())
                 .setQuantity(detail.getQuantity().negate()) // 鍑哄簱鏁伴噺涓鸿礋鏁�
                 .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode())
-                .setBagCodeId(detail.getBagCodeId()) // 琚嬬爜鍨嬫槑缁嗗嚭搴撴椂缃鐮佸凡鍑哄簱锛涙墭鐩樺瀷鏄庣粏涓嶉�愯澶勭悊
+                .setBagCodeId(detail.getBagCodeId()) // 鏂版壂鐮佹槑缁嗛�愯鍏宠仈锛屾墽琛屽嚭搴撻�愯鏇存柊搴撳瓨鐘舵��
                 .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId())
                 .setBizType(MesBizTypeConstants.WM_PRODUCT_SALES).setBizId(sales.getId())
                 .setBizCode(sales.getCode()).setBizLineId(detail.getLineId())

--
Gitblit v1.9.3