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); } } 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); } } 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); } } 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); } } 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); } } 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); } } 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 æ«ç 追溯 - ç¼ç ç±»åè§£æã * * <p>ç¼ç ç»ä¸ä¸ºã16 ä½çº¯æ°åãåï¼æ æ³åæåç¼å¤æç±»åï¼BAG-/PL-/PB- çåç¼å·²åæ¶ï¼ï¼ * å端æ«ç åå è°ç¨æ¬æ¥å£æç¼ç åæ¥å ¶æå±ç±»åï¼åè°ç¨å¯¹åºç±»åç追溯æ¥å£ã */ @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 = "æ ¹æ®ç¼ç è§£ææº¯æºç±»åï¼bag / 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); } } 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); } } 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); } /** 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åå ãï¼æ¯æçè£ 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()) 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()) 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)); 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 ç¼ºå¤±æ¶æ«æï¼æ£å¸¸å¯å¨æ é¢å¤å¼éï¼ï¼</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 ä¸åååç¼ç çåï¼no / 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; } }