yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionServiceImpl.java
@@ -4,7 +4,9 @@
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.mes.controller.admin.wm.transaction.vo.MesWmTransactionPageReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transaction.MesWmTransactionDO;
@@ -13,7 +15,7 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO;
import cn.iocoder.yudao.module.mes.dal.mysql.wm.transaction.MesWmTransactionMapper;
import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
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.transaction.dto.MesWmTransactionSaveReqDTO;
@@ -47,7 +49,7 @@
    @Resource
    private MesWmBatchService batchService;
    @Resource
    private MesMdItemService itemService;
    private MesMdmItemService mdmItemService;
    @Resource
    private MesWmWarehouseService warehouseService;
    @Resource
@@ -75,10 +77,25 @@
        // 1.5 关联事务校验
        checkRelatedTransaction(reqDTO);
        // 2.1 获取或创建库存记录
        MesWmMaterialStockDO materialStock = materialStockService.getOrCreateMaterialStock(
                reqDTO.getItemId(), reqDTO.getWarehouseId(), reqDTO.getLocationId(), reqDTO.getAreaId(),
                reqDTO.getBatchId(), reqDTO.getBatchCode(), reqDTO.getVendorId(), reqDTO.getReceiptTime());
        // 2.1 获取或创建库存记录(如果传入了 materialStockId 则直接使用,避免重新匹配)
        MesWmMaterialStockDO materialStock;
        if (reqDTO.getMaterialStockId() != null) {
            materialStock = materialStockService.getMaterialStock(reqDTO.getMaterialStockId());
            if (materialStock == null) {
                throw exception(WM_MATERIAL_STOCK_NOT_EXISTS);
            }
            // 校验物料、批次、仓库等维度一致(防止传入错误的 materialStockId)
            if (ObjUtil.notEqual(materialStock.getItemId(), reqDTO.getItemId())
                    || ObjUtil.notEqual(materialStock.getWarehouseId(), reqDTO.getWarehouseId())
                    || ObjUtil.notEqual(materialStock.getLocationId(), reqDTO.getLocationId())
                    || ObjUtil.notEqual(materialStock.getAreaId(), reqDTO.getAreaId())) {
                throw exception(WM_MATERIAL_STOCK_SELECTION_MISMATCH);
            }
        } else {
            materialStock = materialStockService.getOrCreateMaterialStock(
                    reqDTO.getItemId(), reqDTO.getWarehouseId(), reqDTO.getLocationId(), reqDTO.getAreaId(),
                    reqDTO.getBatchId(), reqDTO.getBatchCode(), reqDTO.getVendorId(), reqDTO.getReceiptTime());
        }
        // 2.2 冻结校验(仓库、库区、库位、库存记录)
        checkFrozen(reqDTO, materialStock);
        // 2.3 更新库存数量
@@ -104,6 +121,11 @@
            throw exception(WM_TRANSACTION_LIST_EMPTY);
        }
        reqDTOs.forEach(this::createTransaction);
    }
    @Override
    public PageResult<MesWmTransactionDO> getTransactionPage(MesWmTransactionPageReqVO pageReqVO) {
        return transactionMapper.selectPage(pageReqVO);
    }
    // ==================== 私有校验方法 ====================
@@ -144,8 +166,8 @@
        }
        // 2. 入库时:启用批次管理的物料,必须传递批次号
        if (inbound) {
            MesMdItemDO item = itemService.validateItemExists(reqDTO.getItemId());
            if (Boolean.TRUE.equals(item.getBatchFlag())) {
            MesMdmItemDO item = mdmItemService.validateItemExists(reqDTO.getItemId());
            if (Boolean.TRUE.equals(item.getIsBatchManaged())) {
                if (StrUtil.isEmpty(reqDTO.getBatchCode()) && reqDTO.getBatchId() == null) {
                    throw exception(WM_TRANSACTION_BATCH_REQUIRED);
                }