feat(mes): 添加MES系统自动编码规则支持
- 在MesMdAutoCodeRuleCodeEnum中新增多个业务编码规则枚举值,包括工装夹具、生产计划、质检指标等
- 重构生产维护计划、生产计划、不合格品处理等服务中的编码生成功能
- 统一使用自动编码服务替代原有的时间戳+随机数编码方式
- 添加异常处理机制,在编码规则不可用时自动降级为时间戳编码
- 移除硬编码的MPS_CODE_RULE常量,统一通过枚举获取编码规则
- 更新NCR、委外检测等业务流程以使用新的自动编码机制
| | |
| | | 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", "采购退货单编码"), |
| | |
| | | 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", "盘点任务编码"), |
| | |
| | | } |
| | | |
| | | 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"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | 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; |
| | |
| | | @Validated |
| | | @Slf4j |
| | | public class MesProMpsServiceImpl implements MesProMpsService { |
| | | |
| | | /** |
| | | * MPS 编码规则 |
| | | */ |
| | | private static final String MPS_CODE_RULE = "MPS"; |
| | | |
| | | @Resource |
| | | private MesProMpsMapper mpsMapper; |
| | |
| | | */ |
| | | 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(); |
| | | } |
| | | } |
| | |
| | | */ |
| | | 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(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | 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()); |
| | |
| | | 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()); |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | */ |
| | | @Service |
| | | @Validated |
| | | @Slf4j |
| | | public class MesQcNcrServiceImpl implements MesQcNcrService { |
| | | |
| | | @Resource |
| | |
| | | |
| | | @Resource |
| | | private MesQcItemResolver qcItemResolver; |
| | | |
| | | @Resource |
| | | private MesMdAutoCodeRecordService autoCodeRecordService; |
| | | |
| | | @Resource |
| | | @Lazy |
| | |
| | | @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()); |
| | |
| | | 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) { |
| | |
| | | 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()); |
| | |
| | | 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; |
| | |
| | | private MesMdItemService itemService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private MesMdAutoCodeRecordService autoCodeRecordService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | } |
| | | |
| | | 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) { |
| | |
| | | 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()); |