2026-06-29 940c8481d2fdcf51341db4ccd6fd6fcc2d43debb
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/item/WmsItemServiceImpl.java
@@ -1,23 +1,24 @@
package cn.iocoder.yudao.module.wms.service.md.item;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemCreateReqDTO;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemUpdateReqDTO;
import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item.WmsItemListReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item.WmsItemPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item.WmsItemSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.mysql.md.item.WmsItemMapper;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.*;
@@ -25,129 +26,91 @@
/**
 * WMS 商品 Service 实现类
 *
 * 改造说明:WMS 商品数据来源于 MDM 物料主数据
 * - 所有操作调用 MDM API
 * - WMS 商品对应 MDM 物料类型 = 物料(itemType = 1)
 * - 字段映射:WmsItemDO.unit <- MDM 计量单位名称
 *
 * @author 芋道源码
 */
@Service
@Validated
public class WmsItemServiceImpl implements WmsItemService {
    /** WMS 商品对应的 MDM 物料类型:物料 */
    private static final int MDM_ITEM_TYPE_MATERIAL = 1;
    @Resource
    private WmsItemMapper itemMapper;
    private MdmItemApi mdmItemApi;
    @Resource
    @Lazy // 延迟加载,避免循环依赖
    private WmsItemCategoryService categoryService;
    @Resource
    @Lazy // 延迟加载,避免循环依赖
    private WmsItemBrandService brandService;
    @Resource
    private WmsItemSkuService itemSkuService;
    private MdmUnitMeasureApi mdmUnitMeasureApi;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createItem(WmsItemSaveReqVO createReqVO) {
        // 校验数据
        validateItemSaveData(createReqVO);
        // 插入商品
        WmsItemDO item = BeanUtils.toBean(createReqVO, WmsItemDO.class);
        itemMapper.insert(item);
        // 插入 SKU
        itemSkuService.createItemSkuList(item.getId(), createReqVO.getSkus());
        return item.getId();
        // 构建创建请求并调用 MDM API
        MdmItemCreateReqDTO createReqDTO = buildCreateReqDTO(createReqVO);
        return mdmItemApi.createItem(createReqDTO).getCheckedData();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateItem(WmsItemSaveReqVO updateReqVO) {
        // 校验存在
        validateItemExists(updateReqVO.getId());
        // 校验数据
        validateItemSaveData(updateReqVO);
        // 更新商品
        WmsItemDO updateObj = BeanUtils.toBean(updateReqVO, WmsItemDO.class);
        itemMapper.updateById(updateObj);
        // 更新 SKU
        itemSkuService.updateItemSkuList(updateReqVO.getId(), updateReqVO.getSkus());
    }
    private void validateItemSaveData(WmsItemSaveReqVO reqVO) {
        // 校验商品编号唯一
        validateItemCodeUnique(reqVO.getId(), reqVO.getCode());
        // 校验商品名称唯一
        validateItemNameUnique(reqVO.getId(), reqVO.getName());
        // 校验商品分类存在
        validateCategoryExists(reqVO.getCategoryId());
        // 校验商品品牌存在
        validateBrandExists(reqVO.getBrandId());
    }
    private void validateItemCodeUnique(Long id, String code) {
        WmsItemDO item = itemMapper.selectByCode(code);
        if (item == null) {
            return;
        }
        if (id == null || ObjectUtil.notEqual(item.getId(), id)) {
            throw exception(ITEM_CODE_DUPLICATE);
        }
    }
    private void validateItemNameUnique(Long id, String name) {
        WmsItemDO item = itemMapper.selectByName(name);
        if (item == null) {
            return;
        }
        if (id == null || ObjectUtil.notEqual(item.getId(), id)) {
            throw exception(ITEM_NAME_DUPLICATE);
        }
    }
    private void validateCategoryExists(Long categoryId) {
        categoryService.validateItemCategoryExists(categoryId);
    }
    private void validateBrandExists(Long brandId) {
        if (brandId == null) {
            return;
        }
        brandService.validateItemBrandExists(brandId);
        // 构建更新请求并调用 MDM API
        MdmItemUpdateReqDTO updateReqDTO = buildUpdateReqDTO(updateReqVO);
        mdmItemApi.updateItem(updateReqDTO);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteItem(Long id) {
        // 校验存在
        validateItemExists(id);
        // 删除商品和 SKU
        itemSkuService.deleteItemSkuListByItemId(id);
        itemMapper.deleteById(id);
        // WMS 商品删除实际为禁用(MDM 物料不能物理删除)
        mdmItemApi.updateItemStatus(id, CommonStatusEnum.DISABLE.getStatus());
    }
    @Override
    public WmsItemDO validateItemExists(Long id) {
        WmsItemDO item = itemMapper.selectById(id);
        if (item == null) {
            throw exception(ITEM_NOT_EXISTS);
        }
        return item;
        MdmItemRespDTO item = mdmItemApi.validateItemExists(id).getCheckedData();
        return convertToWmsItemDO(item);
    }
    @Override
    public WmsItemDO getItem(Long id) {
        return itemMapper.selectById(id);
        MdmItemRespDTO item = mdmItemApi.getItem(id).getCheckedData();
        if (item == null) {
            return null;
        }
        return convertToWmsItemDO(item);
    }
    @Override
    public PageResult<WmsItemDO> getItemPage(WmsItemPageReqVO pageReqVO) {
        return itemMapper.selectPage(pageReqVO,
                categoryService.getSelfAndChildItemCategoryIdList(pageReqVO.getCategoryId()));
        // 调用 MDM API 分页查询
        PageResult<MdmItemRespDTO> mdmPageResult = mdmItemApi.getItemPage(
                MDM_ITEM_TYPE_MATERIAL,
                pageReqVO.getStatus(),
                pageReqVO.getPageNo(),
                pageReqVO.getPageSize()
        ).getCheckedData();
        // 转换结果
        List<WmsItemDO> itemList = convertToWmsItemDOList(mdmPageResult.getList());
        return new PageResult<>(itemList, mdmPageResult.getTotal());
    }
    @Override
    public List<WmsItemDO> getItemList(WmsItemListReqVO listReqVO) {
        return itemMapper.selectList(listReqVO,
                categoryService.getSelfAndChildItemCategoryIdList(listReqVO.getCategoryId()));
        // 调用 MDM API 获取列表
        List<MdmItemRespDTO> itemList = mdmItemApi.getItemListByStatus(listReqVO.getStatus()).getCheckedData();
        return convertToWmsItemDOList(itemList);
    }
    @Override
@@ -155,17 +118,140 @@
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return itemMapper.selectByIds(ids);
        List<MdmItemRespDTO> itemList = mdmItemApi.getItemList(ids).getCheckedData();
        return convertToWmsItemDOList(itemList);
    }
    @Override
    public long getItemCountByCategoryId(Long categoryId) {
        return itemMapper.selectCountByCategoryId(categoryId);
        return mdmItemApi.getItemCountByCategoryId(categoryId).getCheckedData();
    }
    @Override
    public long getItemCountByBrandId(Long brandId) {
        return itemMapper.selectCountByBrandId(brandId);
        // MDM 暂无按品牌统计方法,返回 0
        return 0L;
    }
}
    // ==================== 私有方法 ====================
    /**
     * 校验商品保存数据
     */
    private void validateItemSaveData(WmsItemSaveReqVO reqVO) {
        // 校验商品编码唯一
        if (reqVO.getCode() != null) {
            MdmItemRespDTO existItem = mdmItemApi.getItemByCode(reqVO.getCode()).getCheckedData();
            if (existItem != null && !existItem.getId().equals(reqVO.getId())) {
                throw exception(ITEM_CODE_DUPLICATE);
            }
        }
        // 校验商品名称唯一
        if (reqVO.getName() != null) {
            // MDM 暂无按名称查询方法,跳过此校验
        }
    }
    /**
     * 构建创建请求 DTO
     */
    private MdmItemCreateReqDTO buildCreateReqDTO(WmsItemSaveReqVO saveReqVO) {
        MdmItemCreateReqDTO createReqDTO = new MdmItemCreateReqDTO();
        createReqDTO.setCode(saveReqVO.getCode());
        createReqDTO.setName(saveReqVO.getName());
        createReqDTO.setCategoryId(saveReqVO.getCategoryId());
        createReqDTO.setBrandId(saveReqVO.getBrandId());
        createReqDTO.setUnitMeasureId(saveReqVO.getUnitMeasureId());
        createReqDTO.setItemType(MDM_ITEM_TYPE_MATERIAL);
        createReqDTO.setStatus(CommonStatusEnum.ENABLE.getStatus());
        createReqDTO.setRemark(saveReqVO.getRemark());
        return createReqDTO;
    }
    /**
     * 构建更新请求 DTO
     */
    private MdmItemUpdateReqDTO buildUpdateReqDTO(WmsItemSaveReqVO saveReqVO) {
        MdmItemUpdateReqDTO updateReqDTO = new MdmItemUpdateReqDTO();
        updateReqDTO.setId(saveReqVO.getId());
        updateReqDTO.setCode(saveReqVO.getCode());
        updateReqDTO.setName(saveReqVO.getName());
        updateReqDTO.setCategoryId(saveReqVO.getCategoryId());
        updateReqDTO.setBrandId(saveReqVO.getBrandId());
        updateReqDTO.setUnitMeasureId(saveReqVO.getUnitMeasureId());
        updateReqDTO.setStatus(CommonStatusEnum.ENABLE.getStatus());
        updateReqDTO.setRemark(saveReqVO.getRemark());
        return updateReqDTO;
    }
    /**
     * 转换 MDM 物料为 WMS 商品
     */
    private WmsItemDO convertToWmsItemDO(MdmItemRespDTO mdmItem) {
        if (mdmItem == null) {
            return null;
        }
        WmsItemDO item = new WmsItemDO();
        item.setId(mdmItem.getId());
        item.setCode(mdmItem.getCode());
        item.setName(mdmItem.getName());
        item.setCategoryId(mdmItem.getCategoryId());
        item.setBrandId(mdmItem.getBrandId());
        item.setRemark(mdmItem.getRemark());
        // 获取计量单位名称
        if (mdmItem.getUnitMeasureId() != null) {
            MdmUnitMeasureRespDTO unit = mdmUnitMeasureApi.getUnitMeasure(mdmItem.getUnitMeasureId()).getCheckedData();
            if (unit != null) {
                item.setUnit(unit.getName());
            }
        }
        return item;
    }
    /**
     * 批量转换 MDM 物料列表为 WMS 商品列表
     */
    private List<WmsItemDO> convertToWmsItemDOList(List<MdmItemRespDTO> mdmItemList) {
        if (CollUtil.isEmpty(mdmItemList)) {
            return Collections.emptyList();
        }
        // 批量获取计量单位
        Set<Long> unitIds = mdmItemList.stream()
                .map(MdmItemRespDTO::getUnitMeasureId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, MdmUnitMeasureRespDTO> unitMap = new HashMap<>();
        if (!unitIds.isEmpty()) {
            List<MdmUnitMeasureRespDTO> units = mdmUnitMeasureApi.getUnitMeasureList(unitIds).getCheckedData();
            for (MdmUnitMeasureRespDTO unit : units) {
                unitMap.put(unit.getId(), unit);
            }
        }
        // 转换列表
        List<WmsItemDO> result = new ArrayList<>();
        for (MdmItemRespDTO mdmItem : mdmItemList) {
            WmsItemDO item = new WmsItemDO();
            item.setId(mdmItem.getId());
            item.setCode(mdmItem.getCode());
            item.setName(mdmItem.getName());
            item.setCategoryId(mdmItem.getCategoryId());
            item.setBrandId(mdmItem.getBrandId());
            item.setRemark(mdmItem.getRemark());
            // 设置单位名称
            if (mdmItem.getUnitMeasureId() != null) {
                MdmUnitMeasureRespDTO unit = unitMap.get(mdmItem.getUnitMeasureId());
                if (unit != null) {
                    item.setUnit(unit.getName());
                }
            }
            result.add(item);
        }
        return result;
    }
}