2026-06-30 24681c81c09022f584a57006f2534b5f74723414
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java
@@ -8,15 +8,10 @@
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
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.category.MdmItemCategoryApi;
import cn.iocoder.yudao.module.mdm.api.category.dto.MdmItemCategoryRespDTO;
import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -30,57 +25,46 @@
/**
 * ERP 产品 Service 实现类
 *
 * 改造说明:ERP 产品数据来源于 MDM 物料主数据
 * - 所有产品操作均调用 MDM API
 * - ERP 产品对应 MDM 物料类型 = 成品(itemType = 2)
 *
 * @author 芋道源码
 */
@Service
@Validated
public class ErpProductServiceImpl implements ErpProductService {
    /** ERP 产品对应的 MDM 物料类型:成品 */
    private static final int MDM_ITEM_TYPE_PRODUCT = 2;
    @Resource
    private ErpProductMapper productMapper;
    @Resource
    private MdmItemApi mdmItemApi;
    private ErpProductCategoryService productCategoryService;
    @Resource
    private MdmItemCategoryApi mdmItemCategoryApi;
    @Resource
    private MdmUnitMeasureApi mdmUnitMeasureApi;
    private ErpProductUnitService productUnitService;
    @Override
    public Long createProduct(ProductSaveReqVO createReqVO) {
        // 1. 校验条码唯一
        validateProductBarCodeUnique(null, createReqVO.getBarCode());
        // 2. 构建创建请求并调用 MDM API
        MdmItemCreateReqDTO createReqDTO = buildCreateReqDTO(createReqVO);
        return mdmItemApi.createItem(createReqDTO).getCheckedData();
        // TODO 芋艿:校验分类
        // 插入
        ErpProductDO product = BeanUtils.toBean(createReqVO, ErpProductDO.class);
        productMapper.insert(product);
        // 返回
        return product.getId();
    }
    @Override
    public void updateProduct(ProductSaveReqVO updateReqVO) {
        // 1. 校验存在
        // TODO 芋艿:校验分类
        // 校验存在
        validateProductExists(updateReqVO.getId());
        // 2. 校验条码唯一
        validateProductBarCodeUnique(updateReqVO.getId(), updateReqVO.getBarCode());
        // 3. 构建更新请求并调用 MDM API
        MdmItemUpdateReqDTO updateReqDTO = buildUpdateReqDTO(updateReqVO);
        mdmItemApi.updateItem(updateReqDTO);
        // 更新
        ErpProductDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductDO.class);
        productMapper.updateById(updateObj);
    }
    @Override
    public void deleteProduct(Long id) {
        // 校验存在
        validateProductExists(id);
        // ERP 产品删除实际为禁用(MDM 物料不能物理删除)
        mdmItemApi.updateItemStatus(id, CommonStatusEnum.DISABLE.getStatus());
        // 删除
        productMapper.deleteById(id);
    }
    @Override
@@ -88,36 +72,35 @@
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        // 1. 调用 MDM API 获取物料列表
        List<MdmItemRespDTO> itemList = mdmItemApi.getItemList(ids).getCheckedData();
        Map<Long, MdmItemRespDTO> itemMap = convertMap(itemList, MdmItemRespDTO::getId);
        // 2. 校验每个产品
        List<ErpProductDO> list = productMapper.selectByIds(ids);
        Map<Long, ErpProductDO> productMap = convertMap(list, ErpProductDO::getId);
        for (Long id : ids) {
            MdmItemRespDTO item = itemMap.get(id);
            if (item == null) {
            ErpProductDO product = productMap.get(id);
            if (productMap.get(id) == null) {
                throw exception(PRODUCT_NOT_EXISTS);
            }
            if (CommonStatusEnum.isDisable(item.getStatus())) {
                throw exception(PRODUCT_NOT_ENABLE, item.getName());
            if (CommonStatusEnum.isDisable(product.getStatus())) {
                throw exception(PRODUCT_NOT_ENABLE, product.getName());
            }
        }
        return list;
        }
        // 3. 转换为 ERP Product DO(手动映射字段)
        return convertToErpProductDOList(itemList);
    private void validateProductExists(Long id) {
        if (productMapper.selectById(id) == null) {
            throw exception(PRODUCT_NOT_EXISTS);
        }
    }
    @Override
    public ErpProductDO getProduct(Long id) {
        MdmItemRespDTO item = mdmItemApi.getItem(id).getCheckedData();
        return convertToErpProductDO(item);
        return productMapper.selectById(id);
    }
    @Override
    public List<ErpProductRespVO> getProductVOListByStatus(Integer status) {
        List<MdmItemRespDTO> itemList = mdmItemApi.getItemListByStatus(status).getCheckedData();
        return buildProductVOList(itemList);
        List<ErpProductDO> list = productMapper.selectListByStatus(status);
        return buildProductVOList(list);
    }
    @Override
@@ -125,188 +108,40 @@
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<MdmItemRespDTO> itemList = mdmItemApi.getItemList(ids).getCheckedData();
        return buildProductVOList(itemList);
        List<ErpProductDO> list = productMapper.selectByIds(ids);
        return buildProductVOList(list);
    }
    @Override
    public PageResult<ErpProductRespVO> getProductVOPage(ErpProductPageReqVO pageReqVO) {
        // 调用 MDM API 分页查询
        PageResult<MdmItemRespDTO> mdmPageResult = mdmItemApi.getItemPage(
                MDM_ITEM_TYPE_PRODUCT,
                pageReqVO.getStatus(),
                pageReqVO.getPageNo(),
                pageReqVO.getPageSize()
        ).getCheckedData();
        PageResult<ErpProductDO> pageResult = productMapper.selectPage(pageReqVO);
        return new PageResult<>(buildProductVOList(pageResult.getList()), pageResult.getTotal());
    }
        List<ErpProductRespVO> productVOList = buildProductVOList(mdmPageResult.getList());
        return new PageResult<>(productVOList, mdmPageResult.getTotal());
    private List<ErpProductRespVO> buildProductVOList(List<ErpProductDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<Long, ErpProductCategoryDO> categoryMap = productCategoryService.getProductCategoryMap(
                convertSet(list, ErpProductDO::getCategoryId));
        Map<Long, ErpProductUnitDO> unitMap = productUnitService.getProductUnitMap(
                convertSet(list, ErpProductDO::getUnitId));
        return BeanUtils.toBean(list, ErpProductRespVO.class, product -> {
            MapUtils.findAndThen(categoryMap, product.getCategoryId(),
                    category -> product.setCategoryName(category.getName()));
            MapUtils.findAndThen(unitMap, product.getUnitId(),
                    unit -> product.setUnitName(unit.getName()));
        });
    }
    @Override
    public Long getProductCountByCategoryId(Long categoryId) {
        return mdmItemApi.getItemCountByCategoryId(categoryId).getCheckedData();
        return productMapper.selectCountByCategoryId(categoryId);
    }
    @Override
    public Long getProductCountByUnitId(Long unitId) {
        return mdmItemApi.getItemCountByUnitMeasureId(unitId).getCheckedData();
    }
    // ==================== 私有方法 ====================
    /**
     * 校验产品存在
     */
    private void validateProductExists(Long id) {
        mdmItemApi.validateItemExists(id).getCheckedData();
    }
    /**
     * 校验产品条码唯一
     */
    private void validateProductBarCodeUnique(Long id, String barCode) {
        if (barCode == null) {
            return;
        }
        MdmItemRespDTO existItem = mdmItemApi.getItemByBarCode(barCode).getCheckedData();
        if (existItem != null && !existItem.getId().equals(id)) {
            throw exception(PRODUCT_BAR_CODE_EXISTS);
        }
    }
    /**
     * 构建创建请求 DTO
     * 注意:ProductSaveReqVO 使用 standard 字段作为规格,MDM 使用 specification
     */
    private MdmItemCreateReqDTO buildCreateReqDTO(ProductSaveReqVO saveReqVO) {
        MdmItemCreateReqDTO createReqDTO = new MdmItemCreateReqDTO();
        createReqDTO.setCode(saveReqVO.getBarCode()); // 使用条码作为编码
        createReqDTO.setName(saveReqVO.getName());
        createReqDTO.setBarCode(saveReqVO.getBarCode());
        createReqDTO.setSpecification(saveReqVO.getStandard()); // standard -> specification
        createReqDTO.setCategoryId(saveReqVO.getCategoryId());
        createReqDTO.setUnitMeasureId(saveReqVO.getUnitId()); // unitId -> unitMeasureId
        createReqDTO.setItemType(MDM_ITEM_TYPE_PRODUCT);
        createReqDTO.setStatus(saveReqVO.getStatus() != null ? saveReqVO.getStatus() : CommonStatusEnum.ENABLE.getStatus());
        createReqDTO.setPurchasePrice(saveReqVO.getPurchasePrice());
        createReqDTO.setSalesPrice(saveReqVO.getSalePrice());
        createReqDTO.setCostPrice(saveReqVO.getMinPrice()); // minPrice -> costPrice
        createReqDTO.setExpiryDay(saveReqVO.getExpiryDay());
        createReqDTO.setWeight(saveReqVO.getWeight());
        createReqDTO.setRemark(saveReqVO.getRemark());
        return createReqDTO;
    }
    /**
     * 构建更新请求 DTO
     */
    private MdmItemUpdateReqDTO buildUpdateReqDTO(ProductSaveReqVO saveReqVO) {
        MdmItemUpdateReqDTO updateReqDTO = new MdmItemUpdateReqDTO();
        updateReqDTO.setId(saveReqVO.getId());
        updateReqDTO.setCode(saveReqVO.getBarCode());
        updateReqDTO.setName(saveReqVO.getName());
        updateReqDTO.setBarCode(saveReqVO.getBarCode());
        updateReqDTO.setSpecification(saveReqVO.getStandard()); // standard -> specification
        updateReqDTO.setCategoryId(saveReqVO.getCategoryId());
        updateReqDTO.setUnitMeasureId(saveReqVO.getUnitId()); // unitId -> unitMeasureId
        updateReqDTO.setStatus(saveReqVO.getStatus());
        updateReqDTO.setPurchasePrice(saveReqVO.getPurchasePrice());
        updateReqDTO.setSalesPrice(saveReqVO.getSalePrice());
        updateReqDTO.setCostPrice(saveReqVO.getMinPrice());
        updateReqDTO.setExpiryDay(saveReqVO.getExpiryDay());
        updateReqDTO.setWeight(saveReqVO.getWeight());
        updateReqDTO.setRemark(saveReqVO.getRemark());
        return updateReqDTO;
    }
    /**
     * 构建产品 VO 列表(包含分类和单位名称)
     * 注意:MDM 和 ERP 字段名有差异,需要手动映射
     */
    private List<ErpProductRespVO> buildProductVOList(List<MdmItemRespDTO> itemList) {
        if (CollUtil.isEmpty(itemList)) {
            return Collections.emptyList();
        }
        // 1. 获取分类和单位信息
        Set<Long> categoryIds = convertSet(itemList, MdmItemRespDTO::getCategoryId);
        Set<Long> unitIds = convertSet(itemList, MdmItemRespDTO::getUnitMeasureId);
        Map<Long, MdmItemCategoryRespDTO> categoryMap = CollUtil.isEmpty(categoryIds)
                ? Collections.emptyMap()
                : convertMap(mdmItemCategoryApi.getItemCategoryList(categoryIds).getCheckedData(), MdmItemCategoryRespDTO::getId);
        Map<Long, MdmUnitMeasureRespDTO> unitMap = CollUtil.isEmpty(unitIds)
                ? Collections.emptyMap()
                : convertMap(mdmUnitMeasureApi.getUnitMeasureList(unitIds).getCheckedData(), MdmUnitMeasureRespDTO::getId);
        // 2. 手动转换并填充关联信息(处理字段名差异)
        List<ErpProductRespVO> result = new ArrayList<>();
        for (MdmItemRespDTO mdmItem : itemList) {
            ErpProductRespVO product = new ErpProductRespVO();
            product.setId(mdmItem.getId());
            product.setName(mdmItem.getName());
            product.setBarCode(mdmItem.getBarCode());
            product.setStandard(mdmItem.getSpecification()); // specification -> standard
            product.setCategoryId(mdmItem.getCategoryId());
            product.setUnitId(mdmItem.getUnitMeasureId()); // unitMeasureId -> unitId
            product.setStatus(mdmItem.getStatus());
            product.setPurchasePrice(mdmItem.getPurchasePrice());
            product.setSalePrice(mdmItem.getSalesPrice()); // salesPrice -> salePrice
            product.setMinPrice(mdmItem.getCostPrice()); // costPrice -> minPrice
            product.setExpiryDay(mdmItem.getExpiryDay());
            product.setWeight(mdmItem.getWeight());
            product.setRemark(mdmItem.getRemark());
            // 设置分类和单位名称
            MapUtils.findAndThen(categoryMap, mdmItem.getCategoryId(),
                    category -> product.setCategoryName(category.getName()));
            MapUtils.findAndThen(unitMap, mdmItem.getUnitMeasureId(),
                    unit -> product.setUnitName(unit.getName()));
            result.add(product);
        }
        return result;
    }
    /**
     * 转换 MDM 物料为 ERP 产品 DO
     * 注意:字段名差异需要手动映射
     */
    private ErpProductDO convertToErpProductDO(MdmItemRespDTO mdmItem) {
        if (mdmItem == null) {
            return null;
        }
        ErpProductDO product = new ErpProductDO();
        product.setId(mdmItem.getId());
        product.setName(mdmItem.getName());
        product.setBarCode(mdmItem.getBarCode());
        product.setStandard(mdmItem.getSpecification()); // specification -> standard
        product.setCategoryId(mdmItem.getCategoryId());
        product.setUnitId(mdmItem.getUnitMeasureId()); // unitMeasureId -> unitId
        product.setStatus(mdmItem.getStatus());
        product.setPurchasePrice(mdmItem.getPurchasePrice());
        product.setSalePrice(mdmItem.getSalesPrice()); // salesPrice -> salePrice
        product.setMinPrice(mdmItem.getCostPrice()); // costPrice -> minPrice
        product.setExpiryDay(mdmItem.getExpiryDay());
        product.setWeight(mdmItem.getWeight());
        product.setRemark(mdmItem.getRemark());
        return product;
    }
    /**
     * 批量转换 MDM 物料列表为 ERP 产品列表
     */
    private List<ErpProductDO> convertToErpProductDOList(List<MdmItemRespDTO> mdmItemList) {
        if (CollUtil.isEmpty(mdmItemList)) {
            return Collections.emptyList();
        }
        List<ErpProductDO> result = new ArrayList<>();
        for (MdmItemRespDTO mdmItem : mdmItemList) {
            result.add(convertToErpProductDO(mdmItem));
        }
        return result;
        return productMapper.selectCountByUnitId(unitId);
    }
}