| | |
| | | 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.erp.dal.dataobject.product.ErpProductUnitDO; |
| | | import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; |
| | | 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 jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | |
| | | /** |
| | | * ERP 产品 Service 实现类 |
| | | * |
| | | * 改造说明:ERP 产品数据来源于 MDM 物料主数据 |
| | | * - 所有产品操作均调用 MDM API |
| | | * - ERP 产品对应 MDM 物料类型 = 成品(itemType = 2) |
| | | * |
| | | * @author 芋道源码 |
| | | */ |
| | | @Service |
| | | @Validated |
| | | public class ErpProductServiceImpl implements ErpProductService { |
| | | |
| | | @Resource |
| | | private ErpProductMapper productMapper; |
| | | /** ERP 产品对应的 MDM 物料类型:成品 */ |
| | | private static final int MDM_ITEM_TYPE_PRODUCT = 2; |
| | | |
| | | @Resource |
| | | private ErpProductCategoryService productCategoryService; |
| | | private MdmItemApi mdmItemApi; |
| | | |
| | | @Resource |
| | | private ErpProductUnitService productUnitService; |
| | | private MdmItemCategoryApi mdmItemCategoryApi; |
| | | |
| | | @Resource |
| | | private MdmUnitMeasureApi mdmUnitMeasureApi; |
| | | |
| | | @Override |
| | | public Long createProduct(ProductSaveReqVO createReqVO) { |
| | | // TODO 芋艿:校验分类 |
| | | // 插入 |
| | | ErpProductDO product = BeanUtils.toBean(createReqVO, ErpProductDO.class); |
| | | productMapper.insert(product); |
| | | // 返回 |
| | | return product.getId(); |
| | | // 1. 校验条码唯一 |
| | | validateProductBarCodeUnique(null, createReqVO.getBarCode()); |
| | | |
| | | // 2. 构建创建请求并调用 MDM API |
| | | MdmItemCreateReqDTO createReqDTO = buildCreateReqDTO(createReqVO); |
| | | return mdmItemApi.createItem(createReqDTO).getCheckedData(); |
| | | } |
| | | |
| | | @Override |
| | | public void updateProduct(ProductSaveReqVO updateReqVO) { |
| | | // TODO 芋艿:校验分类 |
| | | // 校验存在 |
| | | // 1. 校验存在 |
| | | validateProductExists(updateReqVO.getId()); |
| | | // 更新 |
| | | ErpProductDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductDO.class); |
| | | productMapper.updateById(updateObj); |
| | | |
| | | // 2. 校验条码唯一 |
| | | validateProductBarCodeUnique(updateReqVO.getId(), updateReqVO.getBarCode()); |
| | | |
| | | // 3. 构建更新请求并调用 MDM API |
| | | MdmItemUpdateReqDTO updateReqDTO = buildUpdateReqDTO(updateReqVO); |
| | | mdmItemApi.updateItem(updateReqDTO); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteProduct(Long id) { |
| | | // 校验存在 |
| | | validateProductExists(id); |
| | | // 删除 |
| | | productMapper.deleteById(id); |
| | | // ERP 产品删除实际为禁用(MDM 物料不能物理删除) |
| | | mdmItemApi.updateItemStatus(id, CommonStatusEnum.DISABLE.getStatus()); |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (CollUtil.isEmpty(ids)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | List<ErpProductDO> list = productMapper.selectByIds(ids); |
| | | Map<Long, ErpProductDO> productMap = convertMap(list, ErpProductDO::getId); |
| | | |
| | | // 1. 调用 MDM API 获取物料列表 |
| | | List<MdmItemRespDTO> itemList = mdmItemApi.getItemList(ids).getCheckedData(); |
| | | Map<Long, MdmItemRespDTO> itemMap = convertMap(itemList, MdmItemRespDTO::getId); |
| | | |
| | | // 2. 校验每个产品 |
| | | for (Long id : ids) { |
| | | ErpProductDO product = productMap.get(id); |
| | | if (productMap.get(id) == null) { |
| | | MdmItemRespDTO item = itemMap.get(id); |
| | | if (item == null) { |
| | | throw exception(PRODUCT_NOT_EXISTS); |
| | | } |
| | | if (CommonStatusEnum.isDisable(product.getStatus())) { |
| | | throw exception(PRODUCT_NOT_ENABLE, product.getName()); |
| | | if (CommonStatusEnum.isDisable(item.getStatus())) { |
| | | throw exception(PRODUCT_NOT_ENABLE, item.getName()); |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private void validateProductExists(Long id) { |
| | | if (productMapper.selectById(id) == null) { |
| | | throw exception(PRODUCT_NOT_EXISTS); |
| | | } |
| | | // 3. 转换为 ERP Product DO(手动映射字段) |
| | | return convertToErpProductDOList(itemList); |
| | | } |
| | | |
| | | @Override |
| | | public ErpProductDO getProduct(Long id) { |
| | | return productMapper.selectById(id); |
| | | MdmItemRespDTO item = mdmItemApi.getItem(id).getCheckedData(); |
| | | return convertToErpProductDO(item); |
| | | } |
| | | |
| | | @Override |
| | | public List<ErpProductRespVO> getProductVOListByStatus(Integer status) { |
| | | List<ErpProductDO> list = productMapper.selectListByStatus(status); |
| | | return buildProductVOList(list); |
| | | List<MdmItemRespDTO> itemList = mdmItemApi.getItemListByStatus(status).getCheckedData(); |
| | | return buildProductVOList(itemList); |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (CollUtil.isEmpty(ids)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | List<ErpProductDO> list = productMapper.selectByIds(ids); |
| | | return buildProductVOList(list); |
| | | List<MdmItemRespDTO> itemList = mdmItemApi.getItemList(ids).getCheckedData(); |
| | | return buildProductVOList(itemList); |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<ErpProductRespVO> getProductVOPage(ErpProductPageReqVO pageReqVO) { |
| | | PageResult<ErpProductDO> pageResult = productMapper.selectPage(pageReqVO); |
| | | return new PageResult<>(buildProductVOList(pageResult.getList()), pageResult.getTotal()); |
| | | } |
| | | // 调用 MDM API 分页查询 |
| | | PageResult<MdmItemRespDTO> mdmPageResult = mdmItemApi.getItemPage( |
| | | MDM_ITEM_TYPE_PRODUCT, |
| | | pageReqVO.getStatus(), |
| | | pageReqVO.getPageNo(), |
| | | pageReqVO.getPageSize() |
| | | ).getCheckedData(); |
| | | |
| | | 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())); |
| | | }); |
| | | List<ErpProductRespVO> productVOList = buildProductVOList(mdmPageResult.getList()); |
| | | return new PageResult<>(productVOList, mdmPageResult.getTotal()); |
| | | } |
| | | |
| | | @Override |
| | | public Long getProductCountByCategoryId(Long categoryId) { |
| | | return productMapper.selectCountByCategoryId(categoryId); |
| | | return mdmItemApi.getItemCountByCategoryId(categoryId).getCheckedData(); |
| | | } |
| | | |
| | | @Override |
| | | public Long getProductCountByUnitId(Long unitId) { |
| | | return productMapper.selectCountByUnitId(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; |
| | | } |
| | | |
| | | } |