| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportExcelVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO; |
| | | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; |
| | | |
| | | import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; |
| | | import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.*; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | |
| | | * |
| | | * 支持 MES 和 MDM 物料数据双向同步 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Service |
| | | @Validated |
| | |
| | | // 校验数据 |
| | | validateItemSaveData(createReqVO); |
| | | |
| | | // 如果指定了 ID,检查该 ID 是否已存在(用于 MDM 同步时保持 ID 一致) |
| | | if (createReqVO.getId() != null) { |
| | | MesMdItemDO existItem = itemMapper.selectById(createReqVO.getId()); |
| | | if (existItem != null) { |
| | | // ID 已存在,转为更新 |
| | | updateItem(createReqVO); |
| | | return createReqVO.getId(); |
| | | } |
| | | } |
| | | |
| | | // 插入 |
| | | MesMdItemDO item = BeanUtils.toBean(createReqVO, MesMdItemDO.class); |
| | | item.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 默认禁用。信息完成后,再启用 |
| | | // 状态只能由基础数据(MDM)控制:MDM 同步时沿用其状态;MES 本地新增默认禁用 |
| | | item.setStatus(createReqVO.getMdmItemId() != null && createReqVO.getStatus() != null |
| | | ? createReqVO.getStatus() : CommonStatusEnum.DISABLE.getStatus()); |
| | | clearStockIfNotSafe(item); // 如果未启用安全库存,清零库存上下限 |
| | | itemMapper.insert(item); |
| | | |
| | |
| | | // 更新 |
| | | MesMdItemDO updateObj = BeanUtils.toBean(updateReqVO, MesMdItemDO.class); |
| | | clearStockIfNotSafe(updateObj); // 如果未启用安全库存,清零库存上下限 |
| | | // 状态只能由基础数据(MDM)控制,MES 本地更新不允许修改状态 |
| | | if (updateReqVO.getMdmItemId() == null) { |
| | | updateObj.setStatus(null); |
| | | } |
| | | itemMapper.updateById(updateObj); |
| | | |
| | | // 同步到 MDM(勾选 syncMdm 时) |
| | |
| | | if (itemTypeService.getItemType(itemTypeId) == null) { |
| | | throw exception(MD_ITEM_TYPE_NOT_EXISTS); |
| | | } |
| | | // 校验必须是叶子分类(没有子分类) |
| | | List<MesMdItemTypeDO> children = itemTypeService.getItemTypeChildrenList(itemTypeId); |
| | | if (CollUtil.isNotEmpty(children)) { |
| | | throw exception(MD_ITEM_TYPE_NOT_LEAF); |
| | | } |
| | | } |
| | | |
| | | private void validateUnitMeasureExists(Long unitMeasureId) { |
| | |
| | | @Override |
| | | public Long getItemCountByUnitMeasureId(Long unitMeasureId) { |
| | | return itemMapper.selectCountByUnitMeasureId(unitMeasureId); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public MesMdItemImportRespVO importItemList(List<MesMdItemImportExcelVO> importItems, boolean updateSupport) { |
| | | // 1. 参数校验 |
| | | if (CollUtil.isEmpty(importItems)) { |
| | | throw exception(MD_ITEM_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | |
| | | // 2. 遍历,逐个创建 or 更新 |
| | | MesMdItemImportRespVO respVO = MesMdItemImportRespVO.builder() |
| | | .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>()) |
| | | .failureCodes(new LinkedHashMap<>()).build(); |
| | | AtomicInteger index = new AtomicInteger(1); |
| | | importItems.forEach(importItem -> { |
| | | int currentIndex = index.getAndIncrement(); |
| | | // 2.1 校验字段 |
| | | if (StrUtil.isBlank(importItem.getCode())) { |
| | | // 空编码时自动生成 |
| | | importItem.setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.MD_ITEM_CODE.getCode())); |
| | | } |
| | | String key = importItem.getCode(); |
| | | if (StrUtil.isBlank(importItem.getName())) { |
| | | respVO.getFailureCodes().put(key, "物料名称不能为空"); |
| | | return; |
| | | } |
| | | if (StrUtil.isBlank(importItem.getUnitMeasureCode())) { |
| | | respVO.getFailureCodes().put(key, "单位编码不能为空"); |
| | | return; |
| | | } |
| | | // 将单位编码转换为单位 ID |
| | | MesMdUnitMeasureDO unitMeasure = unitMeasureService.getUnitMeasureByCode(importItem.getUnitMeasureCode()); |
| | | if (unitMeasure == null) { |
| | | respVO.getFailureCodes().put(key, "单位编码[" + importItem.getUnitMeasureCode() + "]不存在"); |
| | | return; |
| | | } |
| | | if (importItem.getItemTypeId() == null) { |
| | | respVO.getFailureCodes().put(key, "物料分类编号不能为空"); |
| | | return; |
| | | } |
| | | // 2.2 校验分类是否存在 |
| | | try { |
| | | validateItemTypeExists(importItem.getItemTypeId()); |
| | | } catch (ServiceException ex) { |
| | | respVO.getFailureCodes().put(key, ex.getMessage()); |
| | | return; |
| | | } |
| | | |
| | | // 2.3 判断:创建 or 更新 |
| | | MesMdItemDO existItem = itemMapper.selectByCode(importItem.getCode()); |
| | | if (existItem == null) { |
| | | // 2.3.1 创建 |
| | | try { |
| | | validateItemNameUnique(null, importItem.getName()); |
| | | } catch (ServiceException ex) { |
| | | respVO.getFailureCodes().put(key, ex.getMessage()); |
| | | return; |
| | | } |
| | | MesMdItemDO item = BeanUtils.toBean(importItem, MesMdItemDO.class); |
| | | item.setUnitMeasureId(unitMeasure.getId()); |
| | | item.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 默认禁用。信息完成后,再启用 |
| | | clearStockIfNotSafe(item); |
| | | itemMapper.insert(item); |
| | | // 自动生成条码 |
| | | barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.ITEM.getValue(), |
| | | item.getId(), item.getCode(), item.getName()); |
| | | respVO.getCreateCodes().add(importItem.getCode()); |
| | | } else if (updateSupport) { |
| | | // 2.3.2 更新 |
| | | try { |
| | | validateItemNameUnique(existItem.getId(), importItem.getName()); |
| | | } catch (ServiceException ex) { |
| | | respVO.getFailureCodes().put(key, ex.getMessage()); |
| | | return; |
| | | } |
| | | MesMdItemDO updateObj = BeanUtils.toBean(importItem, MesMdItemDO.class); |
| | | updateObj.setId(existItem.getId()); |
| | | updateObj.setUnitMeasureId(unitMeasure.getId()); |
| | | clearStockIfNotSafe(updateObj); |
| | | itemMapper.updateById(updateObj); |
| | | respVO.getUpdateCodes().add(importItem.getCode()); |
| | | } else { |
| | | // 不支持更新 |
| | | respVO.getFailureCodes().put(key, "物料编码已存在"); |
| | | } |
| | | }); |
| | | return respVO; |
| | | } |
| | | |
| | | /** |
| | |
| | | return 1; // 默认原料 |
| | | } |
| | | |
| | | @Override |
| | | public MesMdItemDO getItemByMdmItemId(Long mdmItemId) { |
| | | if (mdmItemId == null) { |
| | | return null; |
| | | } |
| | | return itemMapper.selectByMdmItemId(mdmItemId); |
| | | } |
| | | |
| | | @Override |
| | | public MesMdItemDO validateItemExistsByMdmItemId(Long mdmItemId) { |
| | | MesMdItemDO item = getItemByMdmItemId(mdmItemId); |
| | | if (item == null) { |
| | | throw exception(MD_ITEM_NOT_EXISTS); |
| | | } |
| | | return item; |
| | | } |
| | | |
| | | } |