2 天以前 111270df037596a04df97f787ca8b9199dd99866
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,369 @@
package cn.iocoder.yudao.module.mdm.service.item;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemPageReqVO;
import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemSaveReqVO;
import cn.iocoder.yudao.module.mdm.dal.dataobject.category.MdmItemCategoryDO;
import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemDO;
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.service.brand.MdmBrandService;
import cn.iocoder.yudao.module.mdm.service.category.MdmItemCategoryService;
import cn.iocoder.yudao.module.mdm.service.unit.MdmUnitMeasureService;
import cn.iocoder.yudao.module.mes.api.item.MesMdItemApi;
import cn.iocoder.yudao.module.mes.api.item.MesMdItemTypeApi;
import cn.iocoder.yudao.module.mes.api.item.dto.MesMdItemSyncReqDTO;
import cn.iocoder.yudao.module.mes.api.item.dto.MesMdItemTypeRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
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.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.mdm.enums.ErrorCodeConstants.*;
/**
 * MDM ç‰©æ–™ä¸»æ•°æ® Service å®žçŽ°ç±»
 *
 * @author èŠ‹é“æºç 
 */
@Service
@Validated
public class MdmItemServiceImpl implements MdmItemService {
    @Resource
    private MdmItemMapper itemMapper;
    @Resource
    private MdmItemCategoryService itemCategoryService;
    @Resource
    private MdmUnitMeasureService unitMeasureService;
    @Resource
    private MdmBrandService brandService;
    @Resource
    @Lazy
    private MesMdItemApi mesMdItemApi;
    @Resource
    private MdmItemBatchConfigMapper itemBatchConfigMapper;
    @Resource
    private MesMdItemTypeApi mesMdItemTypeApi;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createItem(MdmItemSaveReqVO createReqVO) {
        // æ ¡éªŒæ•°æ®
        validateItemSaveData(createReqVO);
        // æ’å…¥ MDM ç‰©æ–™
        MdmItemDO item = BeanUtils.toBean(createReqVO, MdmItemDO.class);
        itemMapper.insert(item);
        // ä¿å­˜æ‰¹æ¬¡é…ç½®ï¼ˆå¦‚果有)
        saveBatchConfig(item.getId(), createReqVO);
        // åŒæ­¥åˆ° MES(勾选 syncMes æ—¶ï¼‰
        createReqVO.setId(item.getId());
        if (Boolean.TRUE.equals(createReqVO.getSyncMes())) {
            syncItemToMes(createReqVO);
        }
        return item.getId();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateItem(MdmItemSaveReqVO updateReqVO) {
        // æ ¡éªŒå­˜åœ¨
        validateItemExists(updateReqVO.getId());
        // æ ¡éªŒæ•°æ®
        validateItemSaveData(updateReqVO);
        // æ›´æ–° MDM ç‰©æ–™
        MdmItemDO updateObj = BeanUtils.toBean(updateReqVO, MdmItemDO.class);
        itemMapper.updateById(updateObj);
        // ä¿å­˜æ‰¹æ¬¡é…ç½®ï¼ˆå¦‚果有)
        saveBatchConfig(updateReqVO.getId(), updateReqVO);
        // åŒæ­¥åˆ° MES(勾选 syncMes æ—¶ï¼‰
        if (Boolean.TRUE.equals(updateReqVO.getSyncMes())) {
            syncItemToMes(updateReqVO);
        }
    }
    private void validateItemSaveData(MdmItemSaveReqVO reqVO) {
        // æ ¡éªŒç‰©æ–™ç¼–码的唯一性
        validateItemCodeUnique(reqVO.getId(), reqVO.getCode());
    }
    /**
     * åŒæ­¥ç‰©æ–™åˆ° MES(单位/分类按 code æ˜ å°„)
     *
     * MDM çš„ unitMeasureId/categoryId ä¸Ž MES çš„ unitMeasureId/itemTypeId åˆ†å±žä¸¤å¥—主数据,
     * è¿™é‡Œå…ˆåœ¨ MDM ä¾§è§£æžå‡º code,再交由 MesMdItemApi åœ¨ MES ä¾§è§£æžä¸ºå¯¹åº” id。
     * åŒæ­¥å¤±è´¥å°†æŠ›å‡ºå¼‚常,触发外层 @Transactional æ•´ä½“回滚(MDM æ“ä½œä¸€å¹¶å›žæ»šï¼‰ã€‚
     */
    private void syncItemToMes(MdmItemSaveReqVO reqVO) {
        // è§£æžè®¡é‡å•位 id -> code
        String unitCode = null;
        if (reqVO.getUnitMeasureId() != null) {
            MdmUnitMeasureDO unitMeasure = unitMeasureService.getUnitMeasure(reqVO.getUnitMeasureId());
            if (unitMeasure == null) {
                throw exception(MDM_UNIT_MEASURE_NOT_EXISTS);
            }
            unitCode = unitMeasure.getCode();
        }
        // è§£æžåˆ†ç±» id -> code(使用 MDM æœ¬åœ°åˆ†ç±»æœåŠ¡ï¼‰
        String itemTypeCode = null;
        if (reqVO.getCategoryId() != null) {
            CommonResult<MesMdItemTypeRespDTO> itemType = mesMdItemTypeApi.getItemType(reqVO.getCategoryId());
            itemTypeCode = itemType.getData().getCode();
        }
        // ç»„装同步 DTO
        MesMdItemSyncReqDTO syncReqDTO = new MesMdItemSyncReqDTO();
        syncReqDTO.setCode(reqVO.getCode());
        syncReqDTO.setMdmItemId(reqVO.getId());
        syncReqDTO.setName(reqVO.getName());
        syncReqDTO.setSpecification(reqVO.getSpecification());
        syncReqDTO.setUnitCode(unitCode);
        syncReqDTO.setItemTypeCode(itemTypeCode);
        syncReqDTO.setSafeStockFlag(Boolean.TRUE); // ä¿ç•™ MDM çš„ minStock/maxStock,避免被 MES æ¸…é›¶
        syncReqDTO.setMinStock(reqVO.getMinStock());
        syncReqDTO.setMaxStock(reqVO.getMaxStock());
        syncReqDTO.setHighValue(reqVO.getIsHighValue());
        syncReqDTO.setBatchFlag(reqVO.getIsBatchManaged());
        syncReqDTO.setRemark(reqVO.getRemark());
        // æ‰¹æ¬¡é…ç½®å­—段
        syncReqDTO.setProduceDateFlag(reqVO.getProduceDateFlag());
        syncReqDTO.setExpireDateFlag(reqVO.getExpireDateFlag());
        syncReqDTO.setReceiptDateFlag(reqVO.getReceiptDateFlag());
        syncReqDTO.setVendorFlag(reqVO.getVendorFlag());
        syncReqDTO.setPurchaseOrderCodeFlag(reqVO.getPurchaseOrderCodeFlag());
        syncReqDTO.setLotNumberFlag(reqVO.getLotNumberFlag());
        syncReqDTO.setQualityStatusFlag(reqVO.getQualityStatusFlag());
        // create èµ° createItem,update èµ° updateItem(MES ä¾§æŒ‰ code upsert)
        if (reqVO.getId() == null) {
            mesMdItemApi.createItem(syncReqDTO);
        } else {
            mesMdItemApi.updateItem(syncReqDTO);
        }
    }
    @Override
    public void updateItemStatus(Long id, Integer status) {
        // æ ¡éªŒå­˜åœ¨
        validateItemExists(id);
        // æ›´æ–°çŠ¶æ€
        itemMapper.updateById(new MdmItemDO().setId(id).setStatus(status));
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteItem(Long id) {
        // æ ¡éªŒå­˜åœ¨
        MdmItemDO item = validateItemExists(id);
        // è§£å†³è½¯åˆ é™¤å”¯ä¸€é”®å†²çªï¼šå¦‚果已存在相同 code ä¸”已软删除的记录,先物理删除它
//        MdmItemDO existingDeleted = itemMapper.selectByCodeAndDeleted(item.getCode(), true);
//        if (existingDeleted != null && !existingDeleted.getId().equals(id)) {
//            itemMapper.physicalDeleteById(existingDeleted.getId());
//        }
        // è½¯åˆ é™¤å½“前记录
        itemMapper.deleteById(id);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteItemList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        // é€ä¸ªåˆ é™¤ï¼ˆå¤ç”¨å•条删除逻辑,保持校验)
        ids.forEach(this::deleteItem);
    }
    @Override
    public MdmItemDO validateItemExists(Long id) {
        MdmItemDO item = itemMapper.selectById(id);
        if (item == null) {
            throw exception(MDM_ITEM_NOT_EXISTS);
        }
        return item;
    }
    @Override
    public MdmItemDO validateItemExistsAndEnable(Long id) {
        MdmItemDO item = validateItemExists(id);
        if (ObjUtil.notEqual(cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus(), item.getStatus())) {
            throw exception(MDM_ITEM_IS_DISABLE);
        }
        return item;
    }
    private void validateItemCodeUnique(Long id, String code) {
        MdmItemDO item = itemMapper.selectByCode(code);
        if (item == null) {
            return;
        }
        if (ObjUtil.notEqual(item.getId(), id)) {
            throw exception(MDM_ITEM_CODE_DUPLICATE);
        }
    }
    private void validateCategoryExists(Long categoryId) {
        if (categoryId == null) {
            return;
        }
        // ä½¿ç”¨ MDM æœ¬åœ°åˆ†ç±»æœåŠ¡æ ¡éªŒ
        MdmItemCategoryDO category = itemCategoryService.getItemCategory(categoryId);
        if (category == null) {
            throw exception(MDM_ITEM_CATEGORY_NOT_EXISTS);
        }
    }
    private void validateUnitMeasureExists(Long unitMeasureId) {
        if (unitMeasureService.getUnitMeasure(unitMeasureId) == null) {
            throw exception(MDM_UNIT_MEASURE_NOT_EXISTS);
        }
    }
    private void validateBrandExists(Long brandId) {
        if (brandService.getBrand(brandId) == null) {
            throw exception(MDM_BRAND_NOT_EXISTS);
        }
    }
    /**
     * å°† itemType è½¬æ¢ä¸ºä¸­æ–‡åç§°
     *
     * @param itemType ç‰©æ–™ç±»åž‹ï¼š1原料, 2半成品, 3成品, 4辅料
     * @return ä¸­æ–‡åç§°
     */
    private String convertItemTypeToName(Integer itemType) {
        if (itemType == null) {
            return null;
        }
        switch (itemType) {
            case 1:
                return "原料";
            case 2:
                return "半成品";
            case 3:
                return "成品";
            case 4:
                return "辅料";
            default:
                return null;
        }
    }
    @Override
    public MdmItemDO getItem(Long id) {
        return itemMapper.selectById(id);
    }
    @Override
    public PageResult<MdmItemDO> getItemPage(MdmItemPageReqVO pageReqVO) {
        // æŸ¥æ‰¾æ—¶ï¼Œå¦‚果查找某个分类编号,则包含它的子分类
        Set<Long> categoryIds = null;
        if (pageReqVO.getCategoryId() != null) {
            categoryIds = new HashSet<>();
            categoryIds.add(pageReqVO.getCategoryId());
            List<cn.iocoder.yudao.module.mdm.dal.dataobject.category.MdmItemCategoryDO> children =
                    itemCategoryService.getItemCategoryChildrenList(pageReqVO.getCategoryId());
            categoryIds.addAll(convertSet(children, cn.iocoder.yudao.module.mdm.dal.dataobject.category.MdmItemCategoryDO::getId));
        }
        // åˆ†é¡µæŸ¥è¯¢
        return itemMapper.selectPage(pageReqVO, categoryIds);
    }
    @Override
    public List<MdmItemDO> getItemList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return itemMapper.selectBatchIds(ids);
    }
    @Override
    public Long getItemCountByCategoryId(Long categoryId) {
        return itemMapper.selectCountByCategoryId(categoryId);
    }
    @Override
    public Long getItemCountByUnitMeasureId(Long unitMeasureId) {
        return itemMapper.selectCountByUnitMeasureId(unitMeasureId);
    }
    @Override
    public Long getItemCountByBrandId(Long brandId) {
        return itemMapper.selectCountByBrandId(brandId);
    }
    @Override
    public MdmItemDO getItemByCode(String code) {
        return itemMapper.selectByCode(code);
    }
    /**
     * ä¿å­˜æ‰¹æ¬¡é…ç½®ï¼ˆåˆ° MDM æœ¬åœ°è¡¨ï¼‰
     */
    private void saveBatchConfig(Long itemId, MdmItemSaveReqVO reqVO) {
        // æ£€æŸ¥æ˜¯å¦æœ‰æ‰¹æ¬¡é…ç½®æ•°æ®
        if (reqVO.getProduceDateFlag() == null
                && reqVO.getExpireDateFlag() == null
                && reqVO.getReceiptDateFlag() == null
                && reqVO.getVendorFlag() == null
                && reqVO.getPurchaseOrderCodeFlag() == null
                && reqVO.getLotNumberFlag() == null
                && reqVO.getQualityStatusFlag() == null) {
            return;
        }
        // æŸ¥è¯¢å·²æœ‰é…ç½®
        cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemBatchConfigDO existing =
                itemBatchConfigMapper.selectOne(
                        cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemBatchConfigDO::getItemId, itemId);
        cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemBatchConfigDO config =
                new cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemBatchConfigDO();
        config.setItemId(itemId);
        config.setProduceDateFlag(Boolean.TRUE.equals(reqVO.getProduceDateFlag()));
        config.setExpireDateFlag(Boolean.TRUE.equals(reqVO.getExpireDateFlag()));
        config.setReceiptDateFlag(Boolean.TRUE.equals(reqVO.getReceiptDateFlag()));
        config.setVendorFlag(Boolean.TRUE.equals(reqVO.getVendorFlag()));
        config.setPurchaseOrderCodeFlag(Boolean.TRUE.equals(reqVO.getPurchaseOrderCodeFlag()));
        config.setLotNumberFlag(Boolean.TRUE.equals(reqVO.getLotNumberFlag()));
        config.setQualityStatusFlag(Boolean.TRUE.equals(reqVO.getQualityStatusFlag()));
        // æ¸…空不需要的字段
        config.setClientFlag(false);
        config.setSalesOrderCodeFlag(false);
        config.setWorkOrderFlag(false);
        config.setTaskFlag(false);
        config.setWorkstationFlag(false);
        config.setToolFlag(false);
        config.setMoldFlag(false);
        if (existing != null) {
            config.setId(existing.getId());
            itemBatchConfigMapper.updateById(config);
        } else {
            itemBatchConfigMapper.insert(config);
        }
    }
}