gaoluyang
2026-10-26 48ee7c963f29f5614a8f86c08608620cc6310793
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java
@@ -19,6 +19,7 @@
import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO;
import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemBatchConfigMapper;
import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemMapper;
import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemCodeSequenceMapper;
import cn.iocoder.yudao.module.mdm.dal.mysql.unit.MdmUnitMeasureMapper;
import cn.iocoder.yudao.module.mdm.service.brand.MdmBrandService;
import cn.iocoder.yudao.module.mdm.service.category.MdmItemCategoryService;
@@ -60,6 +61,9 @@
    private MdmItemMapper itemMapper;
    @Resource
    private MdmItemCodeSequenceMapper itemCodeSequenceMapper;
    @Resource
    private MdmItemCategoryService itemCategoryService;
    @Resource
    private MdmUnitMeasureService unitMeasureService;
@@ -85,6 +89,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createItem(MdmItemSaveReqVO createReqVO) {
        createReqVO.setCode(generateItemCode(createReqVO.getItemType()));
        // 校验数据
        validateItemSaveData(createReqVO);
@@ -107,7 +112,10 @@
    @Transactional(rollbackFor = Exception.class)
    public void updateItem(MdmItemSaveReqVO updateReqVO) {
        // 校验存在
        validateItemExists(updateReqVO.getId());
        MdmItemDO existingItem = validateItemExists(updateReqVO.getId());
        // 编号由系统生成,修改产品时保持原编号不变。
        updateReqVO.setCode(existingItem.getCode());
        updateReqVO.setItemType(existingItem.getItemType());
        // 校验数据
        validateItemSaveData(updateReqVO);
@@ -127,8 +135,41 @@
    }
    private void validateItemSaveData(MdmItemSaveReqVO reqVO) {
        if (reqVO.getItemType() == null || reqVO.getItemType() < 1 || reqVO.getItemType() > 5) {
            throw exception(MDM_ITEM_TYPE_INVALID);
        }
        // 校验物料编码的唯一性
        validateItemCodeUnique(reqVO.getId(), reqVO.getCode());
    }
    /** 生成四位类型前缀 + 五位流水号,共九位。流水行在事务内加锁,避免并发重复。 */
    private String generateItemCode(Integer itemType) {
        String prefix = switch (itemType == null ? 0 : itemType) {
            case 1 -> "1001";
            case 2 -> "1002";
            case 3 -> "1003";
            case 4 -> "1004";
            case 5 -> "1005";
            default -> throw exception(MDM_ITEM_TYPE_INVALID);
        };
        itemCodeSequenceMapper.insertIfAbsent(prefix);
        Integer current = itemCodeSequenceMapper.selectCurrentValueForUpdate(prefix);
        if (current == null) {
            current = itemMapper.selectMaxSequenceByPrefix(prefix);
            itemCodeSequenceMapper.insertIfAbsent(prefix);
            itemCodeSequenceMapper.updateCurrentValue(prefix, current);
        }
        int maxExisting = itemMapper.selectMaxSequenceByPrefix(prefix);
        if (current < maxExisting) {
            current = maxExisting;
            itemCodeSequenceMapper.updateCurrentValue(prefix, current);
        }
        if (current >= 99_999) {
            throw exception(MDM_ITEM_CODE_SEQUENCE_EXHAUSTED);
        }
        itemCodeSequenceMapper.increment(prefix);
        int next = current + 1;
        return prefix + String.format("%05d", next);
    }
    /**
@@ -468,8 +509,8 @@
        TransactionTemplate importTxTemplate = new TransactionTemplate(transactionManager);
        for (MdmItemImportExcelVO importVO : importList) {
            // 2.1 基础校验
            if (StrUtil.isBlank(importVO.getCode()) || StrUtil.isBlank(importVO.getName())) {
                respVO.getFailureList().put(buildFailKey(importVO), "物料编码和物料名称不能为空");
            if (StrUtil.isBlank(importVO.getName())) {
                respVO.getFailureList().put(buildFailKey(importVO), "物料名称不能为空");
                continue;
            }
            // 2.2 解析分类
@@ -511,10 +552,12 @@
            // 2.6 组装 SaveReqVO(复用 create/update 逻辑)
            MdmItemSaveReqVO saveReqVO = new MdmItemSaveReqVO();
            // 新增时忽略 Excel 中的物料编码,由 MDM 按产品类型自动生成。
            saveReqVO.setCode(importVO.getCode());
            saveReqVO.setName(importVO.getName());
            saveReqVO.setBarCode(importVO.getBarCode());
            saveReqVO.setSpecification(importVO.getSpecification());
            saveReqVO.setTechnicalParameters(importVO.getTechnicalParameters());
            saveReqVO.setCategoryId(categoryId);
            saveReqVO.setUnitMeasureId(unitMeasureId);
            saveReqVO.setUnitMeasureId2(unitMeasureId2);
@@ -532,10 +575,10 @@
            saveReqVO.setStatus(importVO.getStatus() != null ? importVO.getStatus() : cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus());
            saveReqVO.setSyncMes(importVO.getSyncMes() != null ? importVO.getSyncMes() : false);
            saveReqVO.setRemark(importVO.getRemark());
            saveReqVO.setItemType(1); // 默认物料类型:物料
            saveReqVO.setItemType(importVO.getItemType() != null ? importVO.getItemType() : 1); // 未提供类型时默认为原材料
            // 2.7 已存在(按编码判断)
            MdmItemDO existByCode = itemMapper.selectByCode(importVO.getCode());
            MdmItemDO existByCode = StrUtil.isBlank(importVO.getCode()) ? null : itemMapper.selectByCode(importVO.getCode());
            if (existByCode != null && !Boolean.TRUE.equals(isUpdateSupport)) {
                respVO.getFailureList().put(buildFailKey(importVO), "物料编码已存在");
                continue;