liu
6 天以前 381e02b9eccbe953b31d09f2af1c2ce77c816140
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionServiceImpl.java
@@ -4,6 +4,9 @@
import cn.hutool.core.lang.Assert;
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.mybatis.core.query.LambdaQueryWrapperX;
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;
@@ -12,6 +15,8 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
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.dal.mysql.wm.materialstock.MesWmMaterialStockMapper;
import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService;
@@ -45,6 +50,8 @@
    @Resource
    private MesWmMaterialStockService materialStockService;
    @Resource
    private MesWmMaterialStockMapper materialStockMapper;
    @Resource
    private MesWmBatchService batchService;
    @Resource
    private MesMdmItemService mdmItemService;
@@ -69,16 +76,57 @@
        // 1.3 入库事务:批次号校验 + batchId/batchCode 互补
        checkBatch(reqDTO, inbound);
        // 1.4 入库事务:库位混放规则校验
        if (inbound) {
        if (inbound && !ObjUtil.equal(reqDTO.getBizType(), MesBizTypeConstants.WM_STOCK_IMPORT_IN)) {
            materialStockService.checkAreaMixingRule(reqDTO.getAreaId(), reqDTO.getItemId(), reqDTO.getBatchId());
        }
        // 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 获取库存记录
        MesWmMaterialStockDO materialStock;
        MesWmTransactionTypeEnum transactionType = MesWmTransactionTypeEnum.valueOf(reqDTO.getType());
        boolean isInbound = transactionType != null && transactionType.isInbound();
        if (reqDTO.getMaterialStockId() != null) {
            // 传入了 materialStockId,直接使用
            materialStock = ObjUtil.equal(reqDTO.getBizType(), MesBizTypeConstants.WM_STOCK_IMPORT_IN)
                    ? materialStockMapper.selectOne(new LambdaQueryWrapperX<MesWmMaterialStockDO>()
                            .eq(MesWmMaterialStockDO::getId, reqDTO.getMaterialStockId()).last("FOR UPDATE"))
                    : 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 if (isInbound) {
            // 入库事务:找不到则自动创建库存记录
            materialStock = materialStockService.getOrCreateMaterialStock(
                    reqDTO.getItemId(), reqDTO.getWarehouseId(), reqDTO.getLocationId(), reqDTO.getAreaId(),
                    reqDTO.getBatchId(), reqDTO.getBatchCode(), reqDTO.getVendorId(), reqDTO.getReceiptTime());
        } else {
            // 出库事务:库存记录必须已存在,不允许自动创建(除非 checkFlag=false 允许负库存)
            materialStock = materialStockService.getMaterialStockByCompositeKey(
                    reqDTO.getItemId(), reqDTO.getWarehouseId(), reqDTO.getLocationId(), reqDTO.getAreaId(),
                    reqDTO.getBatchId(), reqDTO.getVendorId());
            if (materialStock == null) {
                // checkFlag=false 时允许负库存,自动创建库存记录(数量将从 0 扣减为负数)
                boolean allowNegative = !ObjUtil.defaultIfNull(reqDTO.getCheckFlag(), true);
                if (allowNegative) {
                    materialStock = materialStockService.getOrCreateMaterialStock(
                            reqDTO.getItemId(), reqDTO.getWarehouseId(), reqDTO.getLocationId(), reqDTO.getAreaId(),
                            reqDTO.getBatchId(), reqDTO.getBatchCode(), reqDTO.getVendorId(), reqDTO.getReceiptTime());
                } else {
                    throw exception(WM_MATERIAL_STOCK_NOT_EXISTS);
                }
            }
        }
        if (materialStock == null || materialStock.getId() == null) {
            throw exception(WM_MATERIAL_STOCK_NOT_EXISTS);
        }
        // 2.2 冻结校验(仓库、库区、库位、库存记录)
        checkFrozen(reqDTO, materialStock);
        // 2.3 更新库存数量
@@ -88,7 +136,7 @@
        // 3. 插入事务流水
        MesWmTransactionDO transaction = MesWmTransactionDO.builder()
                .type(reqDTO.getType()).quantity(reqDTO.getQuantity()).transactionTime(LocalDateTime.now())
                .itemId(reqDTO.getItemId()).batchId(reqDTO.getBatchId()).batchCode(reqDTO.getBatchCode())
                .itemId(reqDTO.getItemId()).batchId(reqDTO.getBatchId()).batchCode(reqDTO.getBatchCode()).snCode(reqDTO.getSnCode())
                .warehouseId(reqDTO.getWarehouseId()).locationId(reqDTO.getLocationId()).areaId(reqDTO.getAreaId())
                .bizType(reqDTO.getBizType()).bizId(reqDTO.getBizId()).bizCode(reqDTO.getBizCode()).bizLineId(reqDTO.getBizLineId())
                .materialStockId(materialStock.getId()).relatedTransactionId(reqDTO.getRelatedTransactionId())
@@ -106,6 +154,11 @@
        reqDTOs.forEach(this::createTransaction);
    }
    @Override
    public PageResult<MesWmTransactionDO> getTransactionPage(MesWmTransactionPageReqVO pageReqVO) {
        return transactionMapper.selectPage(pageReqVO);
    }
    // ==================== 私有校验方法 ====================
    /**