From 1ba0dbfde5634c8bf2ec20891d6b226b996f6b59 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 02 九月 2026 14:24:38 +0800
Subject: [PATCH] refactor(mes): 优化MES生产扫码入库功能支持多类型扫码
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/scan/MesProScanEventServiceImpl.java | 101 ++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 85 insertions(+), 16 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/scan/MesProScanEventServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/scan/MesProScanEventServiceImpl.java
index 6ee0402..4657035 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/scan/MesProScanEventServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/scan/MesProScanEventServiceImpl.java
@@ -5,11 +5,13 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.scan.vo.MesProScanEventPageReqVO;
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.pro.scan.MesProScanEventDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.scan.MesProScanEventMapper;
import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
import cn.iocoder.yudao.module.mes.enums.MesProScanEventStatusEnum;
@@ -20,47 +22,102 @@
import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService;
import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
+import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+@Slf4j
@Service
@Validated
public class MesProScanEventServiceImpl implements MesProScanEventService {
@Resource private MesProScanEventMapper eventMapper;
@Resource private MesProBagCodeMapper bagCodeMapper;
@Resource private MesProBatchMapper batchMapper;
+ @Resource private MesProPalletMapper palletMapper;
@Resource private MesWmTransactionService transactionService;
@Resource private MesWmWarehouseService warehouseService;
@Resource private MesWmBatchService mesWmBatchService;
+
+ /** 鎵爜绫诲瀷锛氳鐮侊紙榛樿锛� */
+ private static final String SCAN_TYPE_BAG = "BAG";
+ /** 鎵爜绫诲瀷锛氭墭鐩樼爜锛堟寜鎵樼洏宸茶琚嬫暟鏁存墭鍏ュ簱锛� */
+ private static final String SCAN_TYPE_PALLET = "PALLET";
+ /** 鎵爜绫诲瀷锛氭壒娆$爜锛堟寜鎵规琚嬫暟鏁存壒鍏ュ簱锛� */
+ private static final String SCAN_TYPE_BATCH = "BATCH";
@Override
@Transactional(rollbackFor = Exception.class)
public MesProScanEventDO createInbound(MesProScanEventCreateReqVO req) {
MesProScanEventDO existing = eventMapper.selectByEventIdForUpdate(req.getEventId());
if (existing != null) {
- if (!req.getBagCode().equals(existing.getBagCode()) || !req.getDeviceCode().equals(existing.getDeviceCode())) {
+ boolean contentMatch = req.getBagCode().equals(existing.getBagCode())
+ && (req.getDeviceCode() == null || req.getDeviceCode().equals(existing.getDeviceCode()));
+ if (!contentMatch) {
return failed(existing, "MES_SCAN_EVENT_ID_CONFLICT", "浜嬩欢鍙峰凡瀛樺湪浣嗗唴瀹逛笉涓�鑷�");
}
return existing;
}
+ String scanType = (req.getScanType() == null || req.getScanType().isBlank()) ? SCAN_TYPE_BAG : req.getScanType();
MesProScanEventDO event = new MesProScanEventDO();
- event.setEventId(req.getEventId()).setBagCode(req.getBagCode()).setQuantity(req.getQuantity())
- .setDeviceCode(req.getDeviceCode()).setLineCode(req.getLineCode()).setRemark(req.getRemark())
- .setStatus(MesProScanEventStatusEnum.FAILED).setReceivedTime(LocalDateTime.now());
+ event.setEventId(req.getEventId()).setBagCode(req.getBagCode()).setScanType(scanType)
+ .setQuantity(req.getQuantity()).setDeviceCode(req.getDeviceCode()).setLineCode(req.getLineCode())
+ .setRemark(req.getRemark()).setStatus(MesProScanEventStatusEnum.FAILED).setReceivedTime(LocalDateTime.now());
eventMapper.insert(event);
- MesProBagCodeDO bag = bagCodeMapper.selectByCodeForUpdate(req.getBagCode());
- if (bag == null) return failed(event, "MES_SCAN_BAG_NOT_EXISTS", "琚嬬爜涓嶅瓨鍦�");
- event.setBagCodeId(bag.getId());
- if (bag.getInboundEventId() != null) return failed(event, "MES_SCAN_BAG_ALREADY_INBOUND", "琚嬬爜宸插叆搴�");
- MesProBatchDO batch = batchMapper.selectByIdForUpdate(bag.getBatchId());
- if (batch == null) return failed(event, "MES_SCAN_BATCH_NOT_EXISTS", "鐢熶骇鎵规涓嶅瓨鍦�");
- event.setBatchId(batch.getId()).setBatchCode(batch.getCode()).setItemId(batch.getItemId());
+ // 1. 鎸夋壂鐮佺被鍨嬭В鏋愭壂鐮佺洰鏍囦笌鍏ュ簱鏁伴噺锛堟墭鐩樻寜宸茶琚嬫暟銆佹壒娆℃寜鎵规琚嬫暟鏁存壒/鏁存墭鍏ュ簱锛�
+ Long targetId;
+ Long batchId;
+ BigDecimal quantity;
+ MesProBatchDO batch;
+ // 鍗曡鎵爜鍏ュ簱鏃朵紶閫掕鐮侊紝渚涘簱瀛樿鐮佹槑缁嗗湪鍏ュ簱绗竴鏃堕棿寤虹珛锛涙墭鐩�/鎵规鏁存壒鍏ュ簱涓烘壒閲忥紝涓嶉�愯寤烘槑缁�
+ Long bagCodeId = null;
+ String bagCode = null;
+ if (SCAN_TYPE_PALLET.equals(scanType)) {
+ MesProPalletDO pallet = palletMapper.selectByCode(req.getBagCode());
+ if (pallet == null) {
+ pallet = palletMapper.selectByTempCode(req.getBagCode());
+ }
+ if (pallet == null) return failed(event, "MES_SCAN_PALLET_NOT_EXISTS", "鎵樼洏鐮佷笉瀛樺湪");
+ if (pallet.getInboundEventId() != null) return failed(event, "MES_SCAN_PALLET_ALREADY_INBOUND", "鎵樼洏宸插叆搴�");
+ batch = batchMapper.selectByIdForUpdate(pallet.getBatchId());
+ if (batch == null) return failed(event, "MES_SCAN_BATCH_NOT_EXISTS", "鐢熶骇鎵规涓嶅瓨鍦�");
+ batchId = batch.getId();
+ targetId = pallet.getId();
+ quantity = pallet.getBagCount() != null && pallet.getBagCount() > 0
+ ? BigDecimal.valueOf(pallet.getBagCount())
+ : BigDecimal.valueOf(bagCodeMapper.selectCountByPalletId(pallet.getId()));
+ } else if (SCAN_TYPE_BATCH.equals(scanType)) {
+ batch = batchMapper.selectByCode(req.getBagCode());
+ if (batch == null) {
+ batch = batchMapper.selectByTempCode(req.getBagCode());
+ }
+ if (batch == null) return failed(event, "MES_SCAN_BATCH_NOT_EXISTS", "鐢熶骇鎵规涓嶅瓨鍦�");
+ if (batch.getInboundEventId() != null) return failed(event, "MES_SCAN_BATCH_ALREADY_INBOUND", "鎵规宸叉暣鎵瑰叆搴�");
+ batchId = batch.getId();
+ targetId = batch.getId();
+ quantity = batch.getBagQuantity() != null && batch.getBagQuantity() > 0
+ ? BigDecimal.valueOf(batch.getBagQuantity())
+ : BigDecimal.valueOf(bagCodeMapper.selectCountByBatchId(batch.getId()));
+ } else {
+ MesProBagCodeDO bag = bagCodeMapper.selectByCodeForUpdate(req.getBagCode());
+ if (bag == null) return failed(event, "MES_SCAN_BAG_NOT_EXISTS", "琚嬬爜涓嶅瓨鍦�");
+ event.setBagCodeId(bag.getId());
+ bagCodeId = bag.getId();
+ bagCode = req.getBagCode();
+ if (bag.getInboundEventId() != null) return failed(event, "MES_SCAN_BAG_ALREADY_INBOUND", "琚嬬爜宸插叆搴�");
+ batch = batchMapper.selectByIdForUpdate(bag.getBatchId());
+ if (batch == null) return failed(event, "MES_SCAN_BATCH_NOT_EXISTS", "鐢熶骇鎵规涓嶅瓨鍦�");
+ batchId = batch.getId();
+ targetId = bag.getId();
+ quantity = req.getQuantity();
+ }
+ event.setBatchId(batchId).setBatchCode(batch.getCode()).setItemId(batch.getItemId());
MesWmWarehouseDO warehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE);
if (warehouse == null) return failed(event, "MES_SCAN_WIP_WAREHOUSE_NOT_EXISTS", "WIP铏氭嫙浠撲笉瀛樺湪");
event.setWarehouseId(warehouse.getId()).setLocationId(req.getLocationId()).setAreaId(req.getAreaId());
@@ -72,19 +129,31 @@
}
Long txId = transactionService.createTransaction(new MesWmTransactionSaveReqDTO()
.setType(MesWmTransactionTypeEnum.IN.getType()).setBizType(MesBizTypeConstants.WM_PRODUCT_PRODUCE)
- .setBizId(batch.getId()).setBizCode(batch.getCode()).setBizLineId(bag.getId())
- .setItemId(batch.getItemId()).setQuantity(req.getQuantity())
+ .setBizId(batchId).setBizCode(batch.getCode()).setBizLineId(targetId)
+ .setItemId(batch.getItemId()).setQuantity(quantity)
.setBatchId(wmBatch.getId()).setBatchCode(batch.getCode())
+ .setBagCodeId(bagCodeId).setBagCode(bagCode)
.setWarehouseId(warehouse.getId()).setLocationId(req.getLocationId()).setAreaId(req.getAreaId())
.setReceiptTime(LocalDateTime.now()).setCheckFlag(true)
.setStockState(MesWmStockStateEnum.TEMP.getState()));
event.setTransactionId(txId).setStatus(MesProScanEventStatusEnum.SUCCESS).setEventTime(LocalDateTime.now());
eventMapper.updateById(event);
- bagCodeMapper.markInbound(bag.getId(), event.getId(), req.getDeviceCode(), req.getLineCode());
- batchMapper.markInbound(batch.getId(), event.getId(), req.getDeviceCode(), req.getLineCode());
+ // 2. 鍥炲啓鍏ュ簱鏍囪锛堟墭鐩�/鎵规鏁存墭/鏁存壒鍏ュ簱鏃跺悓姝ユ爣璁板叾涓嬫湭鍏ュ簱琚嬬爜锛屼繚鎸佺姸鎬佷竴鑷达級
+ if (SCAN_TYPE_PALLET.equals(scanType)) {
+ palletMapper.markInbound(targetId, event.getId());
+ bagCodeMapper.markInboundByPalletId(targetId, event.getId(), req.getLineCode());
+ } else if (SCAN_TYPE_BATCH.equals(scanType)) {
+ batchMapper.markBatchInbound(targetId, event.getId(), req.getLineCode(), batch.getBagQuantity());
+ bagCodeMapper.markInboundByBatchId(targetId, event.getId(), req.getLineCode());
+ } else {
+ bagCodeMapper.markInbound(targetId, event.getId(), req.getDeviceCode(), req.getLineCode());
+ batchMapper.markInbound(batchId, event.getId(), req.getDeviceCode(), req.getLineCode());
+ }
return event;
} catch (Exception ex) {
- return failed(event, "MES_SCAN_TRANSACTION_FAILED", "搴撳瓨浜嬪姟澶勭悊澶辫触");
+ log.error("[createInbound] 搴撳瓨浜嬪姟澶勭悊澶辫触锛宔ventId={}, bagCode={}, batchId={}, itemId={}",
+ req.getEventId(), req.getBagCode(), batchId, batch.getItemId(), ex);
+ throw ex;
}
}
--
Gitblit v1.9.3