From 7580d02bd3f9399143a6a388732658bea2610bc4 Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期二, 29 九月 2026 15:05:19 +0800
Subject: [PATCH] feat: 业务编码统一为16位纯数字并保证全系统唯一
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/MesCodeRedisDAO.java | 30 +++
yudao-server/src/main/java/cn/iocoder/yudao/server/framework/bizno/BizNoSeqInitializer.java | 102 ++++++++++++
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java | 26 +--
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/batch/MesProBatchServiceImpl.java | 6
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java | 8
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/BizNoUtils.java | 43 +++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/trace/MesProTraceResolveController.java | 53 ++++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java | 26 +--
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/pallet/MesProPalletServiceImpl.java | 11 +
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java | 26 +--
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/redis/HrmNoRedisDAO.java | 23 +-
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java | 45 +----
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/redis/no/AfterSaleNoRedisDAO.java | 23 +-
13 files changed, 300 insertions(+), 122 deletions(-)
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/BizNoUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/BizNoUtils.java
new file mode 100644
index 0000000..c1045ac
--- /dev/null
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/BizNoUtils.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.framework.common.util.number;
+
+/**
+ * 涓氬姟缂栫爜锛堝崟鎹彿 / 涓绘暟鎹紪鐮侊級鐢熸垚鐨勫叕鍏辩害瀹氥��
+ *
+ * <p>闇�姹傦細绯荤粺涓墍鏈夎嚜鍔ㄧ敓鎴愮殑涓氬姟缂栫爜缁熶竴涓恒��16 浣嶇函鏁板瓧銆嶏紝涓斿叏绯荤粺鍞竴锛堜换鎰忎袱鏉$紪鐮侀兘涓嶉噸澶嶏級銆�
+ *
+ * <p>瀹炵幇绾﹀畾锛氬叏绯荤粺鍏辩敤鍚屼竴涓� Redis 鑷 KEY锛坽@link #GLOBAL_SEQ_KEY}锛夛紝
+ * 姣忔鐢熸垚鏃跺鍏舵墽琛� INCR 寰楀埌鍗曡皟閫掑鐨勫簭鍒楀彿锛屽啀宸﹁ˉ '0' 鍒� {@link #CODE_LENGTH} 浣嶃��
+ * 鐢变簬鎵�鏈夌紪鐮侀兘鏉ヨ嚜鍚屼竴鏉¢�掑搴忓垪锛屾晠澶╃劧淇濊瘉銆屽叏绯荤粺鍞竴銆嶃��
+ *
+ * <p>娉ㄦ剰锛�
+ * <ul>
+ * <li>璇� KEY 涓嶈缃繃鏈熸椂闂达紝閬垮厤杩囨湡褰掗浂瀵艰嚧閲嶅彿锛�</li>
+ * <li>Redis 鑻ュ彂鐢熸暟鎹涪澶� / 娓呯┖锛岄渶瑕佷粠鏁版嵁搴撶幇鏈夌紪鐮佺殑鏈�澶у�兼仮澶嶈鏁板櫒锛屽惁鍒欏彲鑳介噸鍙枫��</li>
+ * </ul>
+ */
+public class BizNoUtils {
+
+ /**
+ * 鍏ㄧ郴缁熶笟鍔$紪鐮佺粺涓�浣跨敤鐨� Redis 鑷 KEY銆�
+ *
+ * <p>鎵�鏈夋ā鍧楋紙erp / crm / trade / aftersales / hrm / bpm / mes锛夊叡鐢ㄦ KEY锛�
+ * 浠ヤ繚璇併�屽叏绯荤粺鍞竴銆嶃��
+ */
+ public static final String GLOBAL_SEQ_KEY = "biz:seq_no:global";
+
+ /**
+ * 涓氬姟缂栫爜鐨勬�婚暱搴︼細16 浣�
+ */
+ public static final int CODE_LENGTH = 16;
+
+ /**
+ * 灏嗚嚜澧炲簭鍒楀彿鏍煎紡鍖栦负 16 浣嶇函鏁板瓧缂栫爜锛堝乏渚цˉ '0'锛�
+ *
+ * @param seq 鑷搴忓垪鍙�
+ * @return 16 浣嶇函鏁板瓧缂栫爜
+ */
+ public static String format(Long seq) {
+ return String.format("%0" + CODE_LENGTH + "d", seq);
+ }
+
+}
diff --git a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/redis/no/AfterSaleNoRedisDAO.java b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/redis/no/AfterSaleNoRedisDAO.java
index 856c862..f945f06 100644
--- a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/redis/no/AfterSaleNoRedisDAO.java
+++ b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/redis/no/AfterSaleNoRedisDAO.java
@@ -1,14 +1,9 @@
package cn.iocoder.yudao.module.aftersales.dal.redis.no;
-import cn.hutool.core.date.DatePattern;
-import cn.hutool.core.date.DateUtil;
-import cn.iocoder.yudao.module.aftersales.dal.redis.RedisKeyConstants;
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
-
-import java.time.Duration;
-import java.time.LocalDateTime;
/**
* 鍞悗妯″潡鍗曞彿 Redis DAO
@@ -30,17 +25,17 @@
private StringRedisTemplate stringRedisTemplate;
/**
- * 鐢熸垚搴忓彿锛屼娇鐢ㄥ綋鍓嶆棩鏈燂紝鏍煎紡涓� {PREFIX} + yyyyMMdd + 6 浣嶈嚜澧�
+ * 鐢熸垚 16 浣嶇函鏁板瓧涓氬姟缂栫爜锛堝叏绯荤粺鍞竴锛夈��
*
- * @param prefix 鍓嶇紑
- * @return 搴忓彿
+ * <p>涓哄吋瀹规棦鏈夎皟鐢ㄦ柟锛屼繚鐣� {@code prefix} 鍏ュ弬锛屼絾涓嶅啀鍙備笌缂栫爜鎷兼帴銆�
+ *
+ * @param prefix 鍗曟嵁绫诲瀷鍓嶇紑锛堝凡涓嶅啀鍙備笌缂栫爜鎷兼帴锛�
+ * @return 16 浣嶇函鏁板瓧缂栫爜
*/
public String generate(String prefix) {
- String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);
- String key = RedisKeyConstants.NO + noPrefix;
- Long no = stringRedisTemplate.opsForValue().increment(key);
- stringRedisTemplate.expire(key, Duration.ofDays(1L));
- return noPrefix + String.format("%06d", no);
+ // 鍏ㄧ郴缁熷叡鐢ㄥ悓涓�鑷搴忓垪锛屼繚璇佺紪鐮併��16 浣嶇函鏁板瓧銆嶄笖鍏ㄧ郴缁熷敮涓�
+ Long no = stringRedisTemplate.opsForValue().increment(BizNoUtils.GLOBAL_SEQ_KEY);
+ return BizNoUtils.format(no);
}
}
diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java
index 2a14f51..4f4fcb1 100644
--- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java
+++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java
@@ -1,16 +1,10 @@
package cn.iocoder.yudao.module.bpm.dal.redis;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
-
-import java.time.Duration;
-import java.time.LocalDateTime;
-
-import static cn.hutool.core.date.DatePattern.*;
/**
* BPM 娴佺▼ Id 缂栫爜鐨� Redis DAO
@@ -24,38 +18,17 @@
private StringRedisTemplate stringRedisTemplate;
/**
- * 鐢熸垚搴忓彿锛屼娇鐢ㄥ畾涔夌殑 processIdRule 瑙勫垯鐢熸垚
+ * 鐢熸垚 16 浣嶇函鏁板瓧涓氬姟缂栫爜锛堝叏绯荤粺鍞竴锛夈��
*
- * @param processIdRule 瑙勫垯
- * @return 搴忓彿
+ * <p>涓哄吋瀹规棦鏈夎皟鐢ㄦ柟锛屼繚鐣� {@code processIdRule} 鍏ュ弬锛屼絾涓嶅啀鍙備笌缂栫爜鎷兼帴銆�
+ *
+ * @param processIdRule 娴佺▼ Id 瑙勫垯锛堝凡涓嶅啀鍙備笌缂栫爜鎷兼帴锛�
+ * @return 16 浣嶇函鏁板瓧缂栫爜
*/
public String generate(BpmModelMetaInfoVO.ProcessIdRule processIdRule) {
- // 鐢熸垚鏃ユ湡鍓嶇紑
- String infix = "";
- switch (processIdRule.getInfix()) {
- case "DAY":
- infix = DateUtil.format(LocalDateTime.now(), PURE_DATE_PATTERN);
- break;
- case "HOUR":
- infix = DateUtil.format(LocalDateTime.now(), PURE_DATE_PATTERN + "HH");
- break;
- case "MINUTE":
- infix = DateUtil.format(LocalDateTime.now(), PURE_DATE_PATTERN + "HHmm");
- break;
- case "SECOND":
- infix = DateUtil.format(LocalDateTime.now(), PURE_DATETIME_PATTERN);
- break;
- }
-
- // 鐢熸垚搴忓彿
- String noPrefix = processIdRule.getPrefix() + infix + processIdRule.getPostfix();
- String key = RedisKeyConstants.BPM_PROCESS_ID + noPrefix;
- Long no = stringRedisTemplate.opsForValue().increment(key);
- if (StrUtil.isEmpty(infix)) {
- // 鐗规畩锛氭病鏈夊墠缂�锛屽垯涓嶈兘杩囨湡锛屼笉鑳芥瘡娆¢兘鏄粠 0 寮�濮嬨�傚彲瑙� https://t.zsxq.com/MU1E2 璁ㄨ
- stringRedisTemplate.expire(key, Duration.ofDays(1L));
- }
- return noPrefix + String.format("%0" + processIdRule.getLength() + "d", no);
+ // 鍏ㄧ郴缁熷叡鐢ㄥ悓涓�鑷搴忓垪锛屼繚璇佺紪鐮併��16 浣嶇函鏁板瓧銆嶄笖鍏ㄧ郴缁熷敮涓�
+ Long no = stringRedisTemplate.opsForValue().increment(BizNoUtils.GLOBAL_SEQ_KEY);
+ return BizNoUtils.format(no);
}
}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java
index 7303e0c..23dc84f 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java
@@ -1,14 +1,9 @@
package cn.iocoder.yudao.module.crm.dal.redis.no;
-import cn.hutool.core.date.DatePattern;
-import cn.hutool.core.date.DateUtil;
-import cn.iocoder.yudao.module.crm.dal.redis.RedisKeyConstants;
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
-
-import java.time.Duration;
-import java.time.LocalDateTime;
/**
@@ -43,20 +38,17 @@
private StringRedisTemplate stringRedisTemplate;
/**
- * 鐢熸垚搴忓彿锛屼娇鐢ㄥ綋鍓嶆棩鏈燂紝鏍煎紡涓� {PREFIX} + yyyyMMdd + 6 浣嶈嚜澧�
- * 渚嬪璇达細QTRK 202109 000001 锛堟病鏈変腑闂寸┖鏍硷級
+ * 鐢熸垚 16 浣嶇函鏁板瓧涓氬姟缂栫爜锛堝叏绯荤粺鍞竴锛夈��
*
- * @param prefix 鍓嶇紑
- * @return 搴忓彿
+ * <p>涓哄吋瀹规棦鏈夎皟鐢ㄦ柟锛屼繚鐣� {@code prefix} 鍏ュ弬锛屼絾涓嶅啀鍙備笌缂栫爜鎷兼帴銆�
+ *
+ * @param prefix 鍗曟嵁绫诲瀷鍓嶇紑锛堝凡涓嶅啀鍙備笌缂栫爜鎷兼帴锛�
+ * @return 16 浣嶇函鏁板瓧缂栫爜
*/
public String generate(String prefix) {
- // 閫掑搴忓彿
- String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);
- String key = RedisKeyConstants.NO + noPrefix;
- Long no = stringRedisTemplate.opsForValue().increment(key);
- // 璁剧疆杩囨湡鏃堕棿
- stringRedisTemplate.expire(key, Duration.ofDays(1L));
- return noPrefix + String.format("%06d", no);
+ // 鍏ㄧ郴缁熷叡鐢ㄥ悓涓�鑷搴忓垪锛屼繚璇佺紪鐮併��16 浣嶇函鏁板瓧銆嶄笖鍏ㄧ郴缁熷敮涓�
+ Long no = stringRedisTemplate.opsForValue().increment(BizNoUtils.GLOBAL_SEQ_KEY);
+ return BizNoUtils.format(no);
}
}
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java
index bdce48c..1c332a1 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java
@@ -1,14 +1,9 @@
package cn.iocoder.yudao.module.erp.dal.redis.no;
-import cn.hutool.core.date.DatePattern;
-import cn.hutool.core.date.DateUtil;
-import cn.iocoder.yudao.module.erp.dal.redis.RedisKeyConstants;
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
-
-import java.time.Duration;
-import java.time.LocalDateTime;
/**
@@ -52,20 +47,17 @@
private StringRedisTemplate stringRedisTemplate;
/**
- * 鐢熸垚搴忓彿锛屼娇鐢ㄥ綋鍓嶆棩鏈燂紝鏍煎紡涓� {PREFIX} + yyyyMMdd + 6 浣嶈嚜澧�
- * 渚嬪璇达細CGDD 202109 000001 锛堟病鏈変腑闂寸┖鏍硷級
+ * 鐢熸垚 16 浣嶇函鏁板瓧涓氬姟缂栫爜锛堝叏绯荤粺鍞竴锛夈��
*
- * @param prefix 鍓嶇紑
- * @return 搴忓彿
+ * <p>涓哄吋瀹规棦鏈夎皟鐢ㄦ柟锛屼繚鐣� {@code prefix} 鍏ュ弬锛屼絾涓嶅啀鍙備笌缂栫爜鎷兼帴銆�
+ *
+ * @param prefix 鍗曟嵁绫诲瀷鍓嶇紑锛堝凡涓嶅啀鍙備笌缂栫爜鎷兼帴锛�
+ * @return 16 浣嶇函鏁板瓧缂栫爜
*/
public String generate(String prefix) {
- // 閫掑搴忓彿
- String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);
- String key = RedisKeyConstants.NO + noPrefix;
- Long no = stringRedisTemplate.opsForValue().increment(key);
- // 璁剧疆杩囨湡鏃堕棿
- stringRedisTemplate.expire(key, Duration.ofDays(1L));
- return noPrefix + String.format("%06d", no);
+ // 鍏ㄧ郴缁熷叡鐢ㄥ悓涓�鑷搴忓垪锛屼繚璇佺紪鐮併��16 浣嶇函鏁板瓧銆嶄笖鍏ㄧ郴缁熷敮涓�
+ Long no = stringRedisTemplate.opsForValue().increment(BizNoUtils.GLOBAL_SEQ_KEY);
+ return BizNoUtils.format(no);
}
}
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/redis/HrmNoRedisDAO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/redis/HrmNoRedisDAO.java
index 44009fd..fe10bb3 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/redis/HrmNoRedisDAO.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/redis/HrmNoRedisDAO.java
@@ -1,13 +1,9 @@
package cn.iocoder.yudao.module.hrm.dal.redis;
-import cn.hutool.core.date.DatePattern;
-import cn.hutool.core.date.DateUtil;
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
-
-import java.time.Duration;
-import java.time.LocalDateTime;
/**
* HRM 缂栧彿鐢熸垚鐨� Redis DAO
@@ -131,19 +127,16 @@
}
/**
- * 鐢熸垚缂栧彿
+ * 鐢熸垚 16 浣嶇函鏁板瓧涓氬姟缂栫爜锛堝叏绯荤粺鍞竴锛夈��
*
- * @param prefix 鍓嶇紑
- * @param digits 浣嶆暟
- * @return 缂栧彿
+ * <p>涓哄吋瀹规棦鏈夎皟鐢ㄦ柟锛屼繚鐣欏叆鍙傦紝浣嗕笉鍐嶅弬涓庣紪鐮佹嫾鎺ャ��
+ *
+ * @return 16 浣嶇函鏁板瓧缂栫爜
*/
public String generate(String prefix, int digits) {
- String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);
- String key = HrmRedisKeyConstants.NO + noPrefix;
- Long no = stringRedisTemplate.opsForValue().increment(key);
- // 璁剧疆杩囨湡鏃堕棿 1 澶�
- stringRedisTemplate.expire(key, Duration.ofDays(1L));
- return noPrefix + String.format("%0" + digits + "d", no);
+ // 鍏ㄧ郴缁熷叡鐢ㄥ悓涓�鑷搴忓垪锛屼繚璇佺紪鐮併��16 浣嶇函鏁板瓧銆嶄笖鍏ㄧ郴缁熷敮涓�
+ Long no = stringRedisTemplate.opsForValue().increment(BizNoUtils.GLOBAL_SEQ_KEY);
+ return BizNoUtils.format(no);
}
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/trace/MesProTraceResolveController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/trace/MesProTraceResolveController.java
new file mode 100644
index 0000000..0061b4b
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/trace/MesProTraceResolveController.java
@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.trace;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.mes.service.pro.bagcode.MesProBagCodeService;
+import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService;
+import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+/**
+ * MES 鎵爜杩芥函 - 缂栫爜绫诲瀷瑙f瀽銆�
+ *
+ * <p>缂栫爜缁熶竴涓恒��16 浣嶇函鏁板瓧銆嶅悗锛屾棤娉曞啀鎸夊墠缂�鍒ゆ柇绫诲瀷锛圔AG-/PL-/PB- 绛夊墠缂�宸插彇娑堬級锛�
+ * 鍓嶇鎵爜鍚庡厛璋冪敤鏈帴鍙f寜缂栫爜鍙嶆煡鍏舵墍灞炵被鍨嬶紝鍐嶈皟鐢ㄥ搴旂被鍨嬬殑杩芥函鎺ュ彛銆�
+ */
+@Tag(name = "绠$悊鍚庡彴 - MES 鎵爜婧簮锛堢被鍨嬭В鏋愶級")
+@RestController
+@RequestMapping("/mes/pro/trace")
+@Validated
+public class MesProTraceResolveController {
+
+ @Resource
+ private MesProBagCodeService bagCodeService;
+ @Resource
+ private MesProPalletService palletService;
+ @Resource
+ private MesProBatchService batchService;
+
+ @GetMapping("/resolve-type")
+ @Operation(summary = "鏍规嵁缂栫爜瑙f瀽婧簮绫诲瀷锛歜ag / pallet / batch锛涘潎涓嶅尮閰嶈繑鍥炵┖")
+ @Parameter(name = "code", description = "缂栫爜锛堜簩缁寸爜鍐呭锛�", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:pro-bag-code:query')")
+ public CommonResult<String> resolveType(@RequestParam("code") String code) {
+ if (bagCodeService.getBagCodeByCode(code) != null) {
+ return success("bag");
+ }
+ if (palletService.getPalletByCode(code) != null) {
+ return success("pallet");
+ }
+ if (batchService.getBatchByCode(code) != null) {
+ return success("batch");
+ }
+ return success(null);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/MesCodeRedisDAO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/MesCodeRedisDAO.java
new file mode 100644
index 0000000..41564e1
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/MesCodeRedisDAO.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.mes.dal.redis;
+
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
+import jakarta.annotation.Resource;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Repository;
+
+/**
+ * MES 涓氬姟缂栫爜鐢熸垚鐨� Redis DAO锛堝疄渚嬬爜锛氳鐮� / 鎵樼洏鐮� / 涓存椂鐮佺瓑锛夈��
+ *
+ * <p>闇�姹傦細鎵�鏈変笟鍔$紪鐮佺粺涓�涓恒��16 浣嶇函鏁板瓧銆嶏紝涓斿叏绯荤粺鍞竴銆�
+ * 杩欓噷澶嶇敤鍏ㄧ郴缁熺粺涓�鐨� Redis 鑷 KEY锛屼繚璇佷笌鍏跺畠妯″潡鐨勭紪鐮佷篃涓嶉噸澶嶃��
+ */
+@Repository
+public class MesCodeRedisDAO {
+
+ @Resource
+ private StringRedisTemplate stringRedisTemplate;
+
+ /**
+ * 鐢熸垚涓�涓� 16 浣嶇函鏁板瓧涓氬姟缂栫爜锛堝叏绯荤粺鍞竴锛�
+ *
+ * @return 16 浣嶇函鏁板瓧缂栫爜
+ */
+ public String generate() {
+ Long no = stringRedisTemplate.opsForValue().increment(BizNoUtils.GLOBAL_SEQ_KEY);
+ return BizNoUtils.format(no);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java
index 983dff0..c4daea0 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java
@@ -4,6 +4,7 @@
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRecordDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO;
@@ -13,6 +14,7 @@
import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
+import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -41,6 +43,9 @@
private MesMdAutoCodeRuleService ruleService;
@Resource
private MesMdAutoCodePartService partService;
+
+ @Resource
+ private StringRedisTemplate stringRedisTemplate;
@Resource
private List<MesMdAutoCodePartStrategy> strategyList;
@@ -93,23 +98,10 @@
*/
private String generateCode(MesMdAutoCodeRuleDO rule, List<MesMdAutoCodePartDO> parts,
MesMdAutoCodeContext context) {
- StringBuilder codeBuilder = new StringBuilder();
- for (MesMdAutoCodePartDO part : parts) {
- MesMdAutoCodePartStrategy strategy = strategyMap.get(part.getType());
- Assert.notNull(strategy, () -> exception(AUTO_CODE_GENERATE_FAILED));
- // 鐢熸垚鍒嗘缂栫爜
- String partCode = strategy.generate(part, context);
- // 缁熶竴鎴彇鎸囧畾闀垮害
- partCode = StrUtil.sub(partCode, 0, part.getLength());
- // 鎷兼帴鍒嗘缂栫爜
- codeBuilder.append(partCode);
- }
- // 琛ラ綈澶勭悊
- String result = codeBuilder.toString();
- if (Boolean.TRUE.equals(rule.getPadded()) && rule.getMaxLength() != null) {
- result = padCode(result, rule);
- }
- return result;
+ // 闇�姹傦細鎵�鏈変笟鍔$紪鐮佺粺涓�涓恒��16 浣嶇函鏁板瓧銆嶏紝涓斿叏绯荤粺鍞竴銆�
+ // 鍥犳涓嶅啀鎸夎鍒欏垎娈垫嫾瑁咃紙鍥哄畾瀛楃/鏃ユ湡娈典細甯﹀叆瀛楁瘝锛夛紝鏀逛负鍙栧叏绯荤粺缁熶竴鑷搴忓垪銆�
+ Long no = stringRedisTemplate.opsForValue().increment(BizNoUtils.GLOBAL_SEQ_KEY);
+ return BizNoUtils.format(no);
}
/**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java
index c8f11c4..591eaf2 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/bagcode/MesProBagCodeServiceImpl.java
@@ -25,6 +25,7 @@
import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeReplaceMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper;
+import cn.iocoder.yudao.module.mes.dal.redis.MesCodeRedisDAO;
import cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProPalletStatusEnum;
@@ -85,6 +86,9 @@
* 璁¢噺鍗曚綅绫诲瀷銆孨鍗冨厠銆嶏細姣忔墭鐩樿 N 涓鐮�
*/
private static final Pattern KG_TYPE_PATTERN = Pattern.compile("^(\\d{1,5})鍗冨厠$");
+
+ @Resource
+ private MesCodeRedisDAO codeRedisDao;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -163,7 +167,7 @@
int bagNo = startNo + i;
bagCodes.add(new MesProBagCodeDO()
.setUuid(uuid)
- .setCode("BAG-" + StrUtil.padPre(String.valueOf(bagNo), 8, '0'))
+ .setCode(codeRedisDao.generate())
.setBagNo(bagNo)
.setItemId(item.getId())
.setItemCode(item.getCode())
@@ -339,7 +343,7 @@
MesProPalletDO pallet = oldBagCode.getPalletId() == null ? null : palletMap.get(oldBagCode.getPalletId());
MesProBagCodeDO newBagCode = new MesProBagCodeDO()
.setUuid(replaceUuid)
- .setCode(batch.getCode() + "-" + StrUtil.padPre(String.valueOf(newBagNo), 4, '0'))
+ .setCode(codeRedisDao.generate())
.setBagNo(newBagNo)
.setBatchId(batch.getId())
.setBatchCode(batch.getCode())
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/batch/MesProBatchServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/batch/MesProBatchServiceImpl.java
index 7b63e97..a5d4fbe 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/batch/MesProBatchServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/batch/MesProBatchServiceImpl.java
@@ -15,6 +15,7 @@
import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchWorkerMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper;
+import cn.iocoder.yudao.module.mes.dal.redis.MesCodeRedisDAO;
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchStatusEnum;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
@@ -60,6 +61,9 @@
@Resource
private MesProPalletService palletService;
+
+ @Resource
+ private MesCodeRedisDAO codeRedisDao;
@Resource
private MesMdAutoCodeRecordService autoCodeRecordService;
@@ -109,7 +113,7 @@
List<MesProBatchDO> list = new ArrayList<>(reqVO.getCount());
for (int i = 0; i < reqVO.getCount(); i++) {
list.add(new MesProBatchDO()
- .setTempCode("PB-" + StrUtil.padPre(String.valueOf(startSeq + i), 8, '0'))
+ .setTempCode(codeRedisDao.generate())
.setBagQuantity(0)
.setPalletQuantity(0)
.setStatus(MesProBatchStatusEnum.DRAFT.getStatus())
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/pallet/MesProPalletServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/pallet/MesProPalletServiceImpl.java
index 50385bb..65d8be9 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/pallet/MesProPalletServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/pallet/MesProPalletServiceImpl.java
@@ -13,6 +13,7 @@
import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper;
+import cn.iocoder.yudao.module.mes.dal.redis.MesCodeRedisDAO;
import cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProPalletStatusEnum;
@@ -48,6 +49,9 @@
@Resource
private MesProBatchMapper batchMapper;
+ @Resource
+ private MesCodeRedisDAO codeRedisDao;
+
@Override
@Transactional(rollbackFor = Exception.class)
public List<Long> batchCreatePallet(MesProPalletBatchCreateReqVO createReqVO) {
@@ -71,7 +75,7 @@
for (int i = 0; i < createReqVO.getCount(); i++) {
int palletNo = startNo + i;
pallets.add(new MesProPalletDO()
- .setCode(batch.getCode() + "-P" + StrUtil.padPre(String.valueOf(palletNo), 2, '0'))
+ .setCode(codeRedisDao.generate())
.setBatchId(batch.getId())
.setBatchCode(batch.getCode())
.setPalletNo(palletNo)
@@ -97,7 +101,8 @@
List<MesProPalletDO> list = new ArrayList<>(reqVO.getCount());
for (int i = 0; i < reqVO.getCount(); i++) {
list.add(new MesProPalletDO()
- .setTempCode("PL-" + StrUtil.padPre(String.valueOf(startSeq + i), 8, '0'))
+ .setTempCode(codeRedisDao.generate())
+ .setCapacity(reqVO.getCapacity())
.setBagCount(0)
.setAutoGenerated(false)
.setStatus(MesProPalletStatusEnum.IN_USE.getStatus())
@@ -164,7 +169,7 @@
int palletNo = startNo + i;
palletMapper.updateById(new MesProPalletDO()
.setId(pallets.get(i).getId())
- .setCode(batch.getCode() + "-P" + StrUtil.padPre(String.valueOf(palletNo), 2, '0'))
+ .setCode(codeRedisDao.generate())
.setBatchId(batch.getId())
.setBatchCode(batch.getCode())
.setPalletNo(palletNo));
diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/bizno/BizNoSeqInitializer.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/bizno/BizNoSeqInitializer.java
new file mode 100644
index 0000000..826b58d
--- /dev/null
+++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/bizno/BizNoSeqInitializer.java
@@ -0,0 +1,102 @@
+package cn.iocoder.yudao.server.framework.bizno;
+
+import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.sql.DataSource;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 涓氬姟缂栫爜璁℃暟鍣ㄥ厹搴曞垵濮嬪寲銆�
+ *
+ * <p>鍏ㄧ郴缁熺紪鐮佺粺涓�鐢� Redis 鐨勫叏灞�鑷 KEY锛坽@link BizNoUtils#GLOBAL_SEQ_KEY}锛夌敓鎴愶紝
+ * 鐢ㄤ簬淇濊瘉銆�16 浣嶇函鏁板瓧 + 鍏ㄧ郴缁熷敮涓�銆嶃�備絾 Redis 鏄唴瀛樺瓨鍌紝鑻ヨ娓呯┖ / 涓㈠け锛�
+ * 璇� KEY 浼氬綊闆讹紝浠� 1 閲嶆柊寮�濮嬶紝瀵艰嚧涓庡巻鍙茬紪鐮侀噸澶嶃��
+ *
+ * <p>鍥犳锛氬綋鍚姩鏃跺彂鐜拌 KEY **涓嶅瓨鍦�**锛堣鏄� Redis 涓㈠け杩囪鏁帮級锛�
+ * 浠庢暟鎹簱涓壂鎻忔墍鏈変笟鍔$紪鐮佸垪鐨勬渶澶у�硷紝鎶婅鏁板櫒鎭㈠鍒拌鏈�澶у�硷紝閬垮厤閲嶅彿銆�
+ *
+ * <p>璇存槑锛�
+ * <ul>
+ * <li>浠呭湪 KEY 缂哄け鏃舵壂鎻忥紙姝e父鍚姩鏃犻澶栧紑閿�锛夛紱</li>
+ * <li>鎵弿鏄� best-effort锛屽け璐ュ彧鍛婅銆佷笉褰卞搷鍚姩锛�</li>
+ * <li>鍙粺璁°��16 浣嶇函鏁板瓧銆嶇殑缂栫爜锛屾棫鐨勫甫瀛楁瘝缂栫爜浼氳蹇界暐銆�</li>
+ * </ul>
+ */
+@Component
+@Slf4j
+public class BizNoSeqInitializer implements ApplicationRunner {
+
+ private final StringRedisTemplate stringRedisTemplate;
+ private final JdbcTemplate jdbcTemplate;
+
+ public BizNoSeqInitializer(StringRedisTemplate stringRedisTemplate, DataSource dataSource) {
+ this.stringRedisTemplate = stringRedisTemplate;
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public void run(ApplicationArguments args) {
+ String current = stringRedisTemplate.opsForValue().get(BizNoUtils.GLOBAL_SEQ_KEY);
+ if (current != null) {
+ log.info("[run][涓氬姟缂栫爜璁℃暟鍣ㄥ厹搴昡 Redis 璁℃暟宸插瓨鍦�({})锛岃烦杩囧簱鍐呮壂鎻�", current);
+ return;
+ }
+ long start = System.currentTimeMillis();
+ try {
+ long maxDb = computeMaxCodeInDb();
+ stringRedisTemplate.opsForValue().set(BizNoUtils.GLOBAL_SEQ_KEY, String.valueOf(maxDb));
+ log.info("[run][涓氬姟缂栫爜璁℃暟鍣ㄥ厹搴昡 Redis 璁℃暟缂哄け锛屽凡浠庡簱鍐呮渶澶х紪鐮佹仮澶嶄负 {}", maxDb);
+ } catch (Exception e) {
+ log.warn("[run][涓氬姟缂栫爜璁℃暟鍣ㄥ厹搴昡 鍒濆鍖栧け璐ワ紙涓嶅奖鍝嶅惎鍔級锛岃鎺掓煡", e);
+ } finally {
+ log.info("[run][涓氬姟缂栫爜璁℃暟鍣ㄥ厹搴昡 搴撳唴鎵弿鑰楁椂 {} ms", System.currentTimeMillis() - start);
+ }
+ }
+
+ /**
+ * 鎵弿搴撳唴鎵�鏈夊彲鑳藉瓨鏀句笟鍔$紪鐮佺殑鍒楋紝杩斿洖銆�16 浣嶇函鏁板瓧銆嶇紪鐮佺殑鏈�澶у�笺��
+ */
+ private long computeMaxCodeInDb() {
+ String schema = jdbcTemplate.queryForObject("SELECT DATABASE()", String.class);
+ // 鎵惧嚭鎵�鏈� varchar/char 涓斿悕瀛楀儚缂栫爜鐨勫垪锛坣o / code / *_no / *_code / temp_code锛�
+ List<Map<String, Object>> columns = jdbcTemplate.queryForList(
+ "SELECT table_name, column_name FROM information_schema.columns " +
+ "WHERE table_schema = ? AND data_type IN ('varchar', 'char') " +
+ "AND (column_name = 'no' OR column_name = 'code' OR column_name = 'temp_code' " +
+ " OR column_name LIKE '%\\_no' OR column_name LIKE '%\\_code')",
+ schema);
+ if (columns.isEmpty()) {
+ return 0L;
+ }
+ StringBuilder sql = new StringBuilder("SELECT MAX(v) FROM (");
+ boolean first = true;
+ for (Map<String, Object> column : columns) {
+ String table = String.valueOf(column.get("table_name"));
+ String col = String.valueOf(column.get("column_name"));
+ // 璺宠繃 Quartz 妗嗘灦琛紝閬垮厤鏃犲叧鎵弿
+ if (table.toLowerCase().startsWith("qrtz_") || table.toLowerCase().startsWith("act_")) {
+ continue;
+ }
+ if (!first) {
+ sql.append(" UNION ALL ");
+ }
+ first = false;
+ sql.append("SELECT MAX(CAST(`").append(col).append("` AS UNSIGNED)) AS v FROM `").append(table)
+ .append("` WHERE `").append(col).append("` REGEXP '^[0-9]{").append(BizNoUtils.CODE_LENGTH).append("}$'");
+ }
+ if (first) {
+ return 0L;
+ }
+ sql.append(") t");
+ Long max = jdbcTemplate.queryForObject(sql.toString(), Long.class);
+ return max == null ? 0L : max;
+ }
+
+}
--
Gitblit v1.9.3