云
8 小时以前 795bc269ba9acfae74620059c4ed64bd121aa288
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java
@@ -451,88 +451,18 @@
                .failureList(new LinkedHashMap<>()).build();
        // 1. 预热:分类编码 -> ID(MES 物料分类,与物料表单下拉数据源一致)、单位编码 -> ID
        Map<String, Long> categoryCodeIdMap = new HashMap<>();
        for (String categoryCode : importList.stream()
                .map(MdmItemImportExcelVO::getCategoryCode).filter(StrUtil::isNotBlank).distinct().toList()) {
            CommonResult<MesMdItemTypeRespDTO> categoryResult = mesMdItemTypeApi.getItemTypeByCode(categoryCode);
            if (categoryResult != null && categoryResult.getData() != null) {
                categoryCodeIdMap.put(categoryCode, categoryResult.getData().getId());
            }
        }
        Map<String, Long> unitCodeIdMap = new HashMap<>();
        for (MdmUnitMeasureDO unit : unitMeasureMapper.selectList()) {
            unitCodeIdMap.put(unit.getCode(), unit.getId());
        }
        MdmItemImportContext context = buildImportContext(importList);
        // 2. 遍历导入(每行一个独立事务:单行失败只回滚该行,不影响其余行)
        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), "物料编码和物料名称不能为空");
            // 2.1~2.6 校验必填项、解析分类与单位、组装 SaveReqVO
            MdmItemRowResolution resolution = resolveImportRow(importVO, context);
            if (!resolution.isSuccess()) {
                respVO.getFailureList().put(buildFailKey(importVO), resolution.failureMessage());
                continue;
            }
            // 2.2 解析分类
            Long categoryId = null;
            if (StrUtil.isNotBlank(importVO.getCategoryCode())) {
                categoryId = categoryCodeIdMap.get(importVO.getCategoryCode());
                if (categoryId == null) {
                    respVO.getFailureList().put(buildFailKey(importVO), "物料分类编码不存在:" + importVO.getCategoryCode());
                    continue;
                }
            }
            // 2.3 解析主单位
            Long unitMeasureId = null;
            if (StrUtil.isNotBlank(importVO.getUnitMeasureCode())) {
                unitMeasureId = unitCodeIdMap.get(importVO.getUnitMeasureCode());
                if (unitMeasureId == null) {
                    respVO.getFailureList().put(buildFailKey(importVO), "计量单位编码不存在:" + importVO.getUnitMeasureCode());
                    continue;
                }
            }
            // 2.4 解析辅单位1
            Long unitMeasureId2 = null;
            if (StrUtil.isNotBlank(importVO.getUnitMeasureCode2())) {
                unitMeasureId2 = unitCodeIdMap.get(importVO.getUnitMeasureCode2());
                if (unitMeasureId2 == null) {
                    respVO.getFailureList().put(buildFailKey(importVO), "辅单位1编码不存在:" + importVO.getUnitMeasureCode2());
                    continue;
                }
            }
            // 2.5 解析辅单位2
            Long unitMeasureId3 = null;
            if (StrUtil.isNotBlank(importVO.getUnitMeasureCode3())) {
                unitMeasureId3 = unitCodeIdMap.get(importVO.getUnitMeasureCode3());
                if (unitMeasureId3 == null) {
                    respVO.getFailureList().put(buildFailKey(importVO), "辅单位2编码不存在:" + importVO.getUnitMeasureCode3());
                    continue;
                }
            }
            // 2.6 组装 SaveReqVO(复用 create/update 逻辑)
            MdmItemSaveReqVO saveReqVO = new MdmItemSaveReqVO();
            saveReqVO.setCode(importVO.getCode());
            saveReqVO.setName(importVO.getName());
            saveReqVO.setBarCode(importVO.getBarCode());
            saveReqVO.setSpecification(importVO.getSpecification());
            saveReqVO.setCategoryId(categoryId);
            saveReqVO.setUnitMeasureId(unitMeasureId);
            saveReqVO.setUnitMeasureId2(unitMeasureId2);
            saveReqVO.setUnitMeasureRate1(importVO.getUnitMeasureRate1());
            saveReqVO.setUnitMeasureId3(unitMeasureId3);
            saveReqVO.setUnitMeasureRate2(importVO.getUnitMeasureRate2());
            saveReqVO.setPurchasePrice(importVO.getPurchasePrice());
            saveReqVO.setSalesPrice(importVO.getSalesPrice());
            saveReqVO.setCostPrice(importVO.getCostPrice());
            saveReqVO.setSafetyStock(importVO.getSafetyStock());
            saveReqVO.setMinStock(importVO.getMinStock());
            saveReqVO.setMaxStock(importVO.getMaxStock());
            saveReqVO.setIsBatchManaged(importVO.getIsBatchManaged());
            saveReqVO.setExpiryDay(importVO.getExpiryDay());
            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); // 默认物料类型:物料
            MdmItemSaveReqVO saveReqVO = resolution.saveReqVO();
            // 2.7 已存在(按编码判断)
            MdmItemDO existByCode = itemMapper.selectByCode(importVO.getCode());
@@ -574,6 +504,98 @@
        return respVO;
    }
    @Override
    public MdmItemImportContext buildImportContext(List<MdmItemImportExcelVO> importList) {
        Map<String, Long> categoryCodeIdMap = new HashMap<>();
        Map<String, String> categoryCodeNameMap = new HashMap<>();
        for (String categoryCode : importList.stream()
                .map(MdmItemImportExcelVO::getCategoryCode).filter(StrUtil::isNotBlank).distinct().toList()) {
            CommonResult<MesMdItemTypeRespDTO> categoryResult = mesMdItemTypeApi.getItemTypeByCode(categoryCode);
            if (categoryResult != null && categoryResult.getData() != null) {
                categoryCodeIdMap.put(categoryCode, categoryResult.getData().getId());
                categoryCodeNameMap.put(categoryCode, categoryResult.getData().getName());
            }
        }
        Map<String, Long> unitCodeIdMap = new HashMap<>();
        Map<String, String> unitCodeNameMap = new HashMap<>();
        for (MdmUnitMeasureDO unit : unitMeasureMapper.selectList()) {
            unitCodeIdMap.put(unit.getCode(), unit.getId());
            unitCodeNameMap.put(unit.getCode(), unit.getName());
        }
        return new MdmItemImportContext(categoryCodeIdMap, categoryCodeNameMap, unitCodeIdMap, unitCodeNameMap);
    }
    @Override
    public MdmItemRowResolution resolveImportRow(MdmItemImportExcelVO importVO, MdmItemImportContext context) {
        // 基础校验
        if (StrUtil.isBlank(importVO.getCode()) || StrUtil.isBlank(importVO.getName())) {
            return MdmItemRowResolution.failure("物料编码和物料名称不能为空");
        }
        // 解析分类
        Long categoryId = null;
        if (StrUtil.isNotBlank(importVO.getCategoryCode())) {
            categoryId = context.categoryCodeIdMap().get(importVO.getCategoryCode());
            if (categoryId == null) {
                return MdmItemRowResolution.failure("物料分类编码不存在:" + importVO.getCategoryCode());
            }
        }
        // 解析主单位
        Long unitMeasureId = null;
        if (StrUtil.isNotBlank(importVO.getUnitMeasureCode())) {
            unitMeasureId = context.unitCodeIdMap().get(importVO.getUnitMeasureCode());
            if (unitMeasureId == null) {
                return MdmItemRowResolution.failure("计量单位编码不存在:" + importVO.getUnitMeasureCode());
            }
        }
        // 解析辅单位1
        Long unitMeasureId2 = null;
        if (StrUtil.isNotBlank(importVO.getUnitMeasureCode2())) {
            unitMeasureId2 = context.unitCodeIdMap().get(importVO.getUnitMeasureCode2());
            if (unitMeasureId2 == null) {
                return MdmItemRowResolution.failure("辅单位1编码不存在:" + importVO.getUnitMeasureCode2());
            }
        }
        // 解析辅单位2
        Long unitMeasureId3 = null;
        if (StrUtil.isNotBlank(importVO.getUnitMeasureCode3())) {
            unitMeasureId3 = context.unitCodeIdMap().get(importVO.getUnitMeasureCode3());
            if (unitMeasureId3 == null) {
                return MdmItemRowResolution.failure("辅单位2编码不存在:" + importVO.getUnitMeasureCode3());
            }
        }
        // 组装 SaveReqVO(复用 create/update 逻辑)
        MdmItemSaveReqVO saveReqVO = new MdmItemSaveReqVO();
        saveReqVO.setCode(importVO.getCode());
        saveReqVO.setName(importVO.getName());
        saveReqVO.setBarCode(importVO.getBarCode());
        saveReqVO.setSpecification(importVO.getSpecification());
        saveReqVO.setCategoryId(categoryId);
        saveReqVO.setUnitMeasureId(unitMeasureId);
        saveReqVO.setUnitMeasureId2(unitMeasureId2);
        saveReqVO.setUnitMeasureRate1(importVO.getUnitMeasureRate1());
        saveReqVO.setUnitMeasureId3(unitMeasureId3);
        saveReqVO.setUnitMeasureRate2(importVO.getUnitMeasureRate2());
        saveReqVO.setPurchasePrice(importVO.getPurchasePrice());
        saveReqVO.setSalesPrice(importVO.getSalesPrice());
        saveReqVO.setCostPrice(importVO.getCostPrice());
        saveReqVO.setSafetyStock(importVO.getSafetyStock());
        saveReqVO.setMinStock(importVO.getMinStock());
        saveReqVO.setMaxStock(importVO.getMaxStock());
        saveReqVO.setIsBatchManaged(importVO.getIsBatchManaged());
        saveReqVO.setExpiryDay(importVO.getExpiryDay());
        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); // 默认物料类型:物料
        return MdmItemRowResolution.success(saveReqVO);
    }
    @Override
    public List<MdmItemDO> getItemListByCode(String code) {
        return itemMapper.selectListByCode(code);
    }
    /**
     * 失败清单的 key:用「编码 名称」,而不是单用名称。
     * 物料允许同名不同编码后,只按名称做 key 会让同名行互相覆盖、少报失败行;