云
2026-10-25 bc1b16a708ca7bec89d2e1a435c023477f107a59
feat(mes): 添加MES系统自动编码规则支持

- 在MesMdAutoCodeRuleCodeEnum中新增多个业务编码规则枚举值,包括工装夹具、生产计划、质检指标等
- 重构生产维护计划、生产计划、不合格品处理等服务中的编码生成功能
- 统一使用自动编码服务替代原有的时间戳+随机数编码方式
- 添加异常处理机制,在编码规则不可用时自动降级为时间戳编码
- 移除硬编码的MPS_CODE_RULE常量,统一通过枚举获取编码规则
- 更新NCR、委外检测等业务流程以使用新的自动编码机制
已修改9个文件
85 ■■■■■ 文件已修改
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/maintenanceplan/MesProMaintenancePlanServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ncr/MesQcNcrServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/outsourcetest/MesQcOutsourceTestServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java
@@ -19,6 +19,7 @@
    MD_WORKSTATION_CODE("MD_WORKSTATION_CODE", "工作站编码"),
    MD_WORKSHOP_CODE("MD_WORKSHOP_CODE", "车间编码"),
    TM_TOOL_TYPE_CODE("TM_TOOL_TYPE_CODE", "工具类型编码"),
    TM_TOOL_CODE("TM_TOOL_CODE", "工装夹具编码"),
    WM_ARRIVAL_NOTICE_CODE("WM_ARRIVAL_NOTICE_CODE", "到货通知单编码"),
    WM_ITEM_RECEIPT_CODE("WM_ITEM_RECEIPT_CODE", "采购入库单编码"),
    WM_RETURN_VENDOR_CODE("WM_RETURN_VENDOR_CODE", "采购退货单编码"),
@@ -26,15 +27,23 @@
    WM_SN_CODE("WM_SN_CODE", "SN 码"),
    WM_PACKAGE_CODE("WM_PACKAGE_CODE", "装箱单编码"),
    WM_BATCH_CODE("WM_BATCH_CODE", "批次编码"),
    PRO_MPS_CODE("PRO_MPS_CODE", "生产计划编码"),
    PRO_MAINTENANCE_PLAN_CODE("PRO_MAINTENANCE_PLAN_CODE", "电力作业计划编码"),
    PRO_TASK_CODE("PRO_TASK_CODE", "生产任务编码"),
    QC_IQC_CODE("QC_IQC_CODE", "来料检验单编码"),
    QC_IPQC_CODE("QC_IPQC_CODE", "过程检验单编码"),
    QC_OQC_CODE("QC_OQC_CODE", "出货检验单编码"),
    QC_RQC_CODE("QC_RQC_CODE", "退货检验单编码"),
    QC_INDICATOR_CODE("QC_INDICATOR_CODE", "质检指标编码"),
    QC_TEMPLATE_CODE("QC_TEMPLATE_CODE", "质检方案编码"),
    QC_NCR_CODE("QC_NCR_CODE", "不合格品处理单编码"),
    QC_OUTSOURCE_TEST_CODE("QC_OUTSOURCE_TEST_CODE", "委外检测单编码"),
    WM_WAREHOUSE_CODE("WM_WAREHOUSE_CODE", "仓库编码"),
    WM_LOCATION_CODE("WM_LOCATION_CODE", "库区编码"),
    WM_AREA_CODE("WM_AREA_CODE", "库位编码"),
    WM_PRODUCT_SALES_CODE("WM_PRODUCT_SALES_CODE", "销售出库单编码"),
    WM_PRODUCT_ISSUE_CODE("WM_PRODUCT_ISSUE_CODE", "生产领料单编码"),
    WM_PRODUCT_RECEIPT_CODE("WM_PRODUCT_RECEIPT_CODE", "产品入库单编码"),
    WM_MISC_RECEIPT_CODE("WM_MISC_RECEIPT_CODE", "杂项入库单编码"),
    WM_STOCK_TAKING_PLAN_CODE("WM_STOCK_TAKING_PLAN_CODE", "盘点方案编码"),
    WM_STOCK_TAKING_CODE("WM_STOCK_TAKING_CODE", "盘点任务编码"),
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/maintenanceplan/MesProMaintenancePlanServiceImpl.java
@@ -340,8 +340,14 @@
    }
    private String generatePlanCode() {
        return "MP" + DateUtil.format(java.time.LocalDateTime.now(), "yyyyMMddHHmmss")
                + String.format("%03d", (int) (Math.random() * 1000));
        try {
            return autoCodeRecordService.generateAutoCode(
                    MesMdAutoCodeRuleCodeEnum.PRO_MAINTENANCE_PLAN_CODE.getCode());
        } catch (Exception e) {
            log.warn("[generatePlanCode] 编码规则 {} 不存在,使用时间戳生成",
                    MesMdAutoCodeRuleCodeEnum.PRO_MAINTENANCE_PLAN_CODE.getCode(), e);
            return "MP" + DateUtil.format(java.time.LocalDateTime.now(), "yyyyMMddHHmmssSSS");
        }
    }
    /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
@@ -23,6 +23,7 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO;
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.service.md.item.MesMdItemTypeService;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
@@ -69,11 +70,6 @@
@Validated
@Slf4j
public class MesProMpsServiceImpl implements MesProMpsService {
    /**
     * MPS 编码规则
     */
    private static final String MPS_CODE_RULE = "MPS";
    @Resource
    private MesProMpsMapper mpsMapper;
@@ -534,10 +530,11 @@
     */
    private String generateMpsCode() {
        try {
            return autoCodeRecordService.generateAutoCode(MPS_CODE_RULE);
            return autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.PRO_MPS_CODE.getCode());
        } catch (Exception e) {
            // 如果编码规则不存在,使用时间戳生成
            log.warn("[generateMpsCode] 编码规则 {} 不存在,使用时间戳生成", MPS_CODE_RULE);
            log.warn("[generateMpsCode] 编码规则 {} 不存在,使用时间戳生成",
                    MesMdAutoCodeRuleCodeEnum.PRO_MPS_CODE.getCode(), e);
            return "MPS" + System.currentTimeMillis();
        }
    }
@@ -681,11 +678,13 @@
     */
    private String generateWorkOrderCode() {
        try {
            return autoCodeRecordService.generateAutoCode("WO");
            return autoCodeRecordService.generateAutoCode(
                    MesMdAutoCodeRuleCodeEnum.PRO_WORK_ORDER_CODE.getCode());
        } catch (Exception e) {
            log.warn("[generateWorkOrderCode] 编码规则 WO 不存在,使用时间戳生成");
            log.warn("[generateWorkOrderCode] 编码规则 {} 不存在,使用时间戳生成",
                    MesMdAutoCodeRuleCodeEnum.PRO_WORK_ORDER_CODE.getCode(), e);
            return "WO" + System.currentTimeMillis();
        }
    }
}
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
@@ -253,10 +253,7 @@
        if (unqualifiedQty == null || unqualifiedQty.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        String ncrCode = "NCR" + java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        MesQcNcrSaveReqVO saveReqVO = new MesQcNcrSaveReqVO();
        saveReqVO.setCode(ncrCode);
        saveReqVO.setName("不合格品处理单");
        saveReqVO.setQcType(MesQcTypeEnum.IPQC.getType());
        saveReqVO.setQcId(ipqc.getId());
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java
@@ -183,10 +183,7 @@
        if (unqualifiedQty == null || unqualifiedQty.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        String ncrCode = "NCR" + java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        MesQcNcrSaveReqVO saveReqVO = new MesQcNcrSaveReqVO();
        saveReqVO.setCode(ncrCode);
        saveReqVO.setName("不合格品处理单");
        saveReqVO.setQcType(MesQcTypeEnum.IQC.getType());
        saveReqVO.setQcId(iqc.getId());
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ncr/MesQcNcrServiceImpl.java
@@ -9,6 +9,8 @@
import cn.iocoder.yudao.module.mes.dal.mysql.qc.ncr.MesQcNcrMapper;
import cn.iocoder.yudao.module.mes.enums.qc.MesNcrStatusEnum;
import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService;
import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService;
import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService;
@@ -20,6 +22,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.util.Collection;
@@ -48,6 +51,7 @@
 */
@Service
@Validated
@Slf4j
public class MesQcNcrServiceImpl implements MesQcNcrService {
    @Resource
@@ -61,6 +65,9 @@
    @Resource
    private MesQcItemResolver qcItemResolver;
    @Resource
    private MesMdAutoCodeRecordService autoCodeRecordService;
    @Resource
    @Lazy
@@ -78,6 +85,9 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createNcr(MesQcNcrSaveReqVO createReqVO) {
        if (StrUtil.isBlank(createReqVO.getCode())) {
            createReqVO.setCode(generateNcrCode());
        }
        // 1. 校验数据
        validateNcrCodeUnique(null, createReqVO.getCode());
        validateItemExists(createReqVO.getItemId());
@@ -93,6 +103,17 @@
        return ncr.getId();
    }
    private String generateNcrCode() {
        try {
            return autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.QC_NCR_CODE.getCode());
        } catch (Exception e) {
            log.warn("NCR 编码规则 {} 不可用,降级使用时间戳编码",
                    MesMdAutoCodeRuleCodeEnum.QC_NCR_CODE.getCode(), e);
            return "NCR" + LocalDateTime.now()
                    .format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNcr(MesQcNcrSaveReqVO updateReqVO) {
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
@@ -179,10 +179,7 @@
        if (unqualifiedQty == null || unqualifiedQty.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        String ncrCode = "NCR" + java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        MesQcNcrSaveReqVO saveReqVO = new MesQcNcrSaveReqVO();
        saveReqVO.setCode(ncrCode);
        saveReqVO.setName("不合格品处理单");
        saveReqVO.setQcType(MesQcTypeEnum.OQC.getType());
        saveReqVO.setQcId(oqc.getId());
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/outsourcetest/MesQcOutsourceTestServiceImpl.java
@@ -9,6 +9,8 @@
import cn.iocoder.yudao.module.mes.controller.admin.qc.outsourcetest.vo.MesQcOutsourceTestSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.outsourcetest.MesQcOutsourceTestDO;
import cn.iocoder.yudao.module.mes.dal.mysql.qc.outsourcetest.MesQcOutsourceTestMapper;
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
import jakarta.annotation.Resource;
@@ -68,6 +70,8 @@
    private MesMdItemService itemService;
    @Resource
    private StorageAttachmentApi storageAttachmentApi;
    @Resource
    private MesMdAutoCodeRecordService autoCodeRecordService;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -155,8 +159,14 @@
    }
    private String generateCode() {
        return "WT" + DateUtil.format(java.time.LocalDateTime.now(), "yyyyMMddHHmmss")
                + String.format("%03d", (int) (Math.random() * 1000));
        try {
            return autoCodeRecordService.generateAutoCode(
                    MesMdAutoCodeRuleCodeEnum.QC_OUTSOURCE_TEST_CODE.getCode());
        } catch (Exception e) {
            log.warn("委外检测编码规则 {} 不可用,降级使用时间戳编码",
                    MesMdAutoCodeRuleCodeEnum.QC_OUTSOURCE_TEST_CODE.getCode(), e);
            return "WT" + DateUtil.format(java.time.LocalDateTime.now(), "yyyyMMddHHmmssSSS");
        }
    }
    private MesQcOutsourceTestDO validateTestExists(Long id) {
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java
@@ -190,10 +190,7 @@
        if (unqualifiedQty == null || unqualifiedQty.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        String ncrCode = "NCR" + java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        MesQcNcrSaveReqVO saveReqVO = new MesQcNcrSaveReqVO();
        saveReqVO.setCode(ncrCode);
        saveReqVO.setName("不合格品处理单");
        saveReqVO.setQcType(MesQcTypeEnum.RQC.getType());
        saveReqVO.setQcId(rqc.getId());