xiaoyi
19 小时以前 4bec63c802692a402039f0d99eae068d26d63c55
完善物料颜色同步并保护数据
已添加1个文件
已修改15个文件
112 ■■■■■ 文件已修改
sql/mysql/mdm_item_color_20261107.sql 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemSyncApi.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemSyncApiImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemRespDTO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemSyncReqDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemExcelVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemImportExcelVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemPageReqVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemRespVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemSaveReqVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/item/MdmItemDO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/item/dto/MesMdItemSyncReqDTO.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/item/MesMdItemApiImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/mdm_item_color_20261107.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
-- MDM ç‰©æ–™è¡¥ã€Œé¢œè‰²ã€å­—段(需求:物料颜色在物料管理(mdm)页面同样可维护)
-- ä¸Ž mes_md_item.color ä¿æŒä¸€è‡´ï¼Œå¹¶æŒ‰ç‰©æ–™ç¼–码把 MES å·²æœ‰çš„颜色回填过来。
SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdm_item' AND COLUMN_NAME='color');
SET @s := IF(@c=0,
  'ALTER TABLE mdm_item ADD COLUMN color VARCHAR(64) DEFAULT NULL COMMENT ''颜色'' AFTER specification',
  'SELECT 1');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
-- å›žå¡«ï¼šæŒ‰ç‰©æ–™ç¼–码把 MES ä¾§å·²ç»´æŠ¤çš„颜色同步到 MDM(仅填充 MDM ä¸ºç©ºçš„记录)
UPDATE mdm_item m
JOIN mes_md_item s ON s.code = m.code AND CAST(s.deleted AS UNSIGNED)=0
SET m.color = s.color
WHERE CAST(m.deleted AS UNSIGNED)=0
  AND s.color IS NOT NULL AND s.color <> ''
  AND (m.color IS NULL OR m.color = '');
-- åå‘回填:MDM æœ‰é¢œè‰²è€Œ MES æ²¡æœ‰æ—¶ï¼ŒåŒæ­¥åˆ° MES(保持两边一致)
UPDATE mes_md_item s
JOIN mdm_item m ON m.code = s.code AND CAST(m.deleted AS UNSIGNED)=0
SET s.color = m.color
WHERE CAST(s.deleted AS UNSIGNED)=0
  AND m.color IS NOT NULL AND m.color <> ''
  AND (s.color IS NULL OR s.color = '');
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemSyncApi.java
@@ -22,4 +22,7 @@
     */
    CommonResult<Long> syncItemToMdm(MdmItemSyncReqDTO syncReqDTO);
}
    /** ä»…同步已有同编码物料的颜色,不创建物料或覆盖其他主数据。 */
    CommonResult<Boolean> syncExistingItemColor(String code, String color);
}
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/MdmItemSyncApiImpl.java
@@ -30,6 +30,16 @@
    private MdmItemBatchConfigMapper itemBatchConfigMapper;
    @Override
    public CommonResult<Boolean> syncExistingItemColor(String code, String color) {
        MdmItemDO existingItem = itemMapper.selectByCode(code);
        if (existingItem == null || color == null) {
            return success(false);
        }
        itemMapper.updateById(new MdmItemDO().setId(existingItem.getId()).setColor(color));
        return success(true);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Long> syncItemToMdm(MdmItemSyncReqDTO syncReqDTO) {
        // 1. æŒ‰ code æŸ¥è¯¢æ˜¯å¦å·²å­˜åœ¨
@@ -99,4 +109,4 @@
        }
    }
}
}
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemRespDTO.java
@@ -24,6 +24,9 @@
    @Schema(description = "规格型号", example = "M8*20")
    private String specification;
    @Schema(description = "颜色", example = "红")
    private String color;
    @Schema(description = "物料分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long categoryId;
@@ -72,4 +75,4 @@
    @Schema(description = "备注", example = "备注信息")
    private String remark;
}
}
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/api/item/dto/MdmItemSyncReqDTO.java
@@ -23,6 +23,9 @@
    @Schema(description = "规格型号", example = "M6*20")
    private String specification;
    @Schema(description = "颜色", example = "红")
    private String color;
    @Schema(description = "物料类型:1原料, 2半成品, 3成品, 4辅料", example = "1")
    private Long itemType;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemExcelVO.java
@@ -26,6 +26,9 @@
    @ExcelProperty("规格型号")
    private String specification;
    @ExcelProperty("颜色")
    private String color;
    @ExcelProperty("物料类型")
    private String itemTypeName;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemImportExcelVO.java
@@ -29,6 +29,9 @@
    @ExcelProperty("规格型号")
    private String specification;
    @ExcelProperty("颜色")
    private String color;
    @ExcelProperty("物料分类编码")
    private String categoryCode;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemPageReqVO.java
@@ -23,6 +23,9 @@
    @Schema(description = "物料条码", example = "12345678")
    private String barCode;
    @Schema(description = "颜色(模糊匹配)", example = "红")
    private String color;
    @Schema(description = "物料分类编号", example = "1")
    private Long categoryId;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemRespVO.java
@@ -25,6 +25,9 @@
    @Schema(description = "规格型号", example = "M8*20")
    private String specification;
    @Schema(description = "颜色", example = "红")
    private String color;
    @Schema(description = "物料分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long categoryId;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/item/vo/MdmItemSaveReqVO.java
@@ -24,6 +24,9 @@
    @Schema(description = "规格型号", example = "M8*20")
    private String specification;
    @Schema(description = "颜色", example = "红")
    private String color;
    @Schema(description = "物料分类编号(关联 MES ç‰©æ–™åˆ†ç±» mes_md_item_type)", example = "1")
    private Long categoryId;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/item/MdmItemDO.java
@@ -56,6 +56,13 @@
    private String specification;
    /**
     * é¢œè‰²
     *
     * ç”¨äºŽåŒºåˆ†åŒåž‹å·ä¸åŒé¢œè‰²çš„物料
     */
    private String color;
    /**
     * ç‰©æ–™åˆ†ç±»ç¼–号
     *
     * å…³è” {@link MdmItemCategoryDO#getId()}
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java
@@ -25,6 +25,7 @@
                .likeIfPresent(MdmItemDO::getCode, reqVO.getCode())
                .likeIfPresent(MdmItemDO::getName, reqVO.getName())
                .likeIfPresent(MdmItemDO::getBarCode, reqVO.getBarCode())
                .likeIfPresent(MdmItemDO::getColor, reqVO.getColor())
                .inIfPresent(MdmItemDO::getCategoryId, categoryIds)
                .eqIfPresent(MdmItemDO::getItemType, reqVO.getItemType())
                .eqIfPresent(MdmItemDO::getBrandId, reqVO.getBrandId())
@@ -38,6 +39,7 @@
        return selectList(new LambdaQueryWrapperX<MdmItemDO>()
                .likeIfPresent(MdmItemDO::getCode, reqVO.getCode())
                .likeIfPresent(MdmItemDO::getName, reqVO.getName())
                .likeIfPresent(MdmItemDO::getColor, reqVO.getColor())
                .inIfPresent(MdmItemDO::getCategoryId, categoryIds)
                .eqIfPresent(MdmItemDO::getItemType, reqVO.getItemType())
                .eqIfPresent(MdmItemDO::getStatus, reqVO.getStatus())
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java
@@ -107,7 +107,7 @@
    @Transactional(rollbackFor = Exception.class)
    public void updateItem(MdmItemSaveReqVO updateReqVO) {
        // æ ¡éªŒå­˜åœ¨
        validateItemExists(updateReqVO.getId());
        MdmItemDO previousItem = validateItemExists(updateReqVO.getId());
        // æ ¡éªŒæ•°æ®
        validateItemSaveData(updateReqVO);
@@ -120,7 +120,7 @@
        // æ ¹æ®åŒæ­¥å¼€å…³å†³å®šï¼šæ‰“开则同步到 MES,关闭则取消同步(从 MES åˆ é™¤ï¼‰
        if (Boolean.TRUE.equals(updateReqVO.getSyncMes())) {
            syncItemToMes(updateReqVO);
            syncItemToMes(updateReqVO, previousItem.getCode());
        } else {
            mesMdItemApi.deleteItem(updateReqVO.getId());
        }
@@ -139,6 +139,10 @@
     * åŒæ­¥å¤±è´¥å°†æŠ›å‡ºå¼‚常,回滚本行事务(本行的 MDM æ“ä½œä¸€å¹¶å›žæ»šï¼Œä¸å½±å“å…¶å®ƒè¡Œï¼‰ã€‚
     */
    private void syncItemToMes(MdmItemSaveReqVO reqVO) {
        syncItemToMes(reqVO, null);
    }
    private void syncItemToMes(MdmItemSaveReqVO reqVO, String previousCode) {
        // è§£æžè®¡é‡å•位 id -> code
        String unitCode = null;
        if (reqVO.getUnitMeasureId() != null) {
@@ -157,9 +161,11 @@
        // ç»„装同步 DTO
        MesMdItemSyncReqDTO syncReqDTO = new MesMdItemSyncReqDTO();
        syncReqDTO.setCode(reqVO.getCode());
        syncReqDTO.setPreviousCode(previousCode);
        syncReqDTO.setMdmItemId(reqVO.getId());
        syncReqDTO.setName(reqVO.getName());
        syncReqDTO.setSpecification(reqVO.getSpecification());
        syncReqDTO.setColor(reqVO.getColor());
        syncReqDTO.setUnitCode(unitCode);
        syncReqDTO.setItemTypeCode(itemTypeCode);
        syncReqDTO.setSafeStockFlag(Boolean.TRUE); // ä¿ç•™ MDM çš„ minStock/maxStock,避免被 MES æ¸…é›¶
@@ -515,6 +521,7 @@
            saveReqVO.setName(importVO.getName());
            saveReqVO.setBarCode(importVO.getBarCode());
            saveReqVO.setSpecification(importVO.getSpecification());
            saveReqVO.setColor(importVO.getColor());
            saveReqVO.setCategoryId(categoryId);
            saveReqVO.setUnitMeasureId(unitMeasureId);
            saveReqVO.setUnitMeasureId2(unitMeasureId2);
@@ -587,4 +594,4 @@
                StrUtil.blankToDefault(importVO.getName(), "(名称和编码为空的行)"));
    }
}
}
yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/item/dto/MesMdItemSyncReqDTO.java
@@ -12,12 +12,18 @@
    @Schema(description = "物料编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM001")
    private String code;
    @Schema(description = "修改前的物料编码,用于安全识别已关联的生产物料")
    private String previousCode;
    @Schema(description = "物料名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "螺丝")
    private String name;
    @Schema(description = "规格型号", example = "M6*20")
    private String specification;
    @Schema(description = "颜色", example = "红")
    private String color;
    @Schema(description = "计量单位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PCS")
    private String unitCode;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/api/item/MesMdItemApiImpl.java
@@ -18,9 +18,11 @@
import org.springframework.validation.annotation.Validated;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
/**
@@ -50,6 +52,7 @@
    @Override
    public Long createItem(MesMdItemSyncReqDTO syncReqDTO) {
        log.info("[createItem] åŒæ­¥åˆ›å»º MES ç‰©æ–™äº§å“ï¼Œcode={}, mdmItemId={}", syncReqDTO.getCode(), syncReqDTO.getMdmItemId());
        validateSharedId(syncReqDTO);
        MesMdItemSaveReqVO saveReqVO = buildSaveReqVO(syncReqDTO);
        // ä½¿ç”¨ MDM ç‰©æ–™ ID ä½œä¸º MES ç‰©æ–™ ID
        if (syncReqDTO.getMdmItemId() != null) {
@@ -64,6 +67,7 @@
    @Override
    public void updateItem(MesMdItemSyncReqDTO syncReqDTO) {
        log.info("[updateItem] åŒæ­¥æ›´æ–° MES ç‰©æ–™äº§å“ï¼Œcode={}, mdmItemId={}", syncReqDTO.getCode(), syncReqDTO.getMdmItemId());
        validateSharedId(syncReqDTO);
        MesMdItemSaveReqVO saveReqVO = buildSaveReqVO(syncReqDTO);
        // ä½¿ç”¨ MDM ç‰©æ–™ ID ä½œä¸º MES ç‰©æ–™ ID
        if (syncReqDTO.getMdmItemId() != null) {
@@ -91,6 +95,17 @@
//        saveBatchConfig(itemId, syncReqDTO);
    }
    private void validateSharedId(MesMdItemSyncReqDTO syncReqDTO) {
        if (syncReqDTO.getMdmItemId() == null) {
            return;
        }
        MesMdItemDO existing = itemMapper.selectAnyById(syncReqDTO.getMdmItemId());
        if (existing != null && !Objects.equals(existing.getCode(), syncReqDTO.getCode())
                && !Objects.equals(existing.getCode(), syncReqDTO.getPreviousCode())) {
            throw invalidParamException("同步失败:生产物料编号已被其他编码占用,请核对两套物料数据后再操作");
        }
    }
    /**
     * å°†åŒæ­¥ DTO è½¬æ¢ä¸º MES ç‰©æ–™äº§å“ SaveReqVO,并按 code è§£æžå•位/分类 id
     */
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java
@@ -133,6 +133,9 @@
        if (Boolean.TRUE.equals(updateReqVO.getSyncMdm())) {
            MesMdItemDO item = itemMapper.selectById(updateReqVO.getId());
            syncItemToMdm(item, updateReqVO);
        } else if (updateReqVO.getMdmItemId() == null && updateReqVO.getColor() != null) {
            // MES é¡µé¢ç¼–辑时只同步已有同编码物料的颜色,避免覆盖 MDM å…¶ä»–字段或循环同步。
            mdmItemSyncApi.syncExistingItemColor(updateReqVO.getCode(), updateReqVO.getColor()).checkError();
        }
    }
@@ -342,6 +345,7 @@
        syncReqDTO.setCode(item.getCode());
        syncReqDTO.setName(item.getName());
        syncReqDTO.setSpecification(item.getSpecification());
        syncReqDTO.setColor(item.getColor());
        syncReqDTO.setItemType(itemType);
        syncReqDTO.setUnitMeasureId(unitMeasureId);
        syncReqDTO.setCategoryId(item.getItemTypeId());