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 jakarta.annotation.Resource;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.stereotype.Repository;
|
|
import java.time.Duration;
|
import java.time.LocalDateTime;
|
import java.util.function.Predicate;
|
|
|
/**
|
* Erp 订单序号的 Redis DAO
|
*
|
* @author HUIHUI
|
*/
|
@Repository
|
public class ErpNoRedisDAO {
|
|
/**
|
* 销售订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO}
|
*/
|
public static final String SALE_ORDER_NO_PREFIX = "XSDD";
|
|
/**
|
* 采购订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO}
|
*/
|
public static final String PURCHASE_ORDER_NO_PREFIX = "CGDD";
|
|
/**
|
* 采购申请 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseRequestDO}
|
*/
|
public static final String PURCHASE_REQUEST_NO_PREFIX = "CGSQ";
|
|
/**
|
* 采购来票 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO}
|
*/
|
public static final String PURCHASE_INVOICE_NO_PREFIX = "FPD";
|
|
/**
|
* 付款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO}
|
*/
|
public static final String FINANCE_PAYMENT_NO_PREFIX = "FKD";
|
/**
|
* 收款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO}
|
*/
|
public static final String FINANCE_RECEIPT_NO_PREFIX = "SKD";
|
|
@Resource
|
private StringRedisTemplate stringRedisTemplate;
|
|
/**
|
* 生成序号,使用当前日期,格式为 {PREFIX} + yyyyMMdd + 6 位自增
|
* 例如说:CGDD 202109 000001 (没有中间空格)
|
*
|
* @param prefix 前缀
|
* @return 序号
|
*/
|
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);
|
}
|
|
/**
|
* 生成序号,并跳过已存在的单号。
|
*
|
* Redis 中的自增计数一旦丢失(如 Redis 重启未持久化、手工清库),计数会从 1 重新开始,
|
* 而当天数据库中可能已有同日期后缀的单号,此时逐个递增重试直到取到未占用的序号。
|
*
|
* @param prefix 前缀
|
* @param isNoExists 单号是否已存在
|
* @return 未占用的序号
|
*/
|
public String generate(String prefix, Predicate<String> isNoExists) {
|
for (int i = 0; i < MAX_GENERATE_ATTEMPTS; i++) {
|
String no = generate(prefix);
|
if (!isNoExists.test(no)) {
|
return no;
|
}
|
}
|
throw new IllegalStateException("生成单号失败:连续 " + MAX_GENERATE_ATTEMPTS + " 次尝试均已被占用,请稍后重试");
|
}
|
|
private static final int MAX_GENERATE_ATTEMPTS = 10000;
|
|
}
|