Commit 4efcf911 by zhangxingmin

push

parent 72070e82
......@@ -125,16 +125,19 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
String billingYearMonth = actualPayoutDate != null
? actualPayoutDate.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMM"))
: "";
// 本地缓存,key=prefix, value=当前已分配给该prefix的最大流水号数值
Map<String, Integer> prefixSerialCache = new HashMap<>();
for (FortuneAccountExportDTO accountExportDTO : accountExportDTOList) {
FortuneAccount fortuneAccount = new FortuneAccount();
fortuneAccount.setFortuneAccountBizId(RandomStringGenerator.generateBizId16("fortune_account"));
String internalCode = map.get(accountExportDTO.getBrokerBizId());
// LocalDate payoutDate = accountExportDTO.getActualPayoutDate();
// String billingYearMonth = payoutDate != null
// ? actualPayoutDate.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMM"))
// : "";
String businessNo = BusinessNoUtils.generate(billingYearMonth, internalCode);
//出账业务编号(出账年月 + 转介人内部编号(后6位)(如无,用0补齐)+流水号(6位))
String prefix = BusinessNoUtils.getPrefix(billingYearMonth, internalCode);
// 业务编号生成
String businessNo = generateBusinessNoWithCache(prefix, billingYearMonth, internalCode, prefixSerialCache);
fortuneAccount.setBusinessNo(businessNo);
fortuneAccount.setBroker(accountExportDTO.getBroker());
fortuneAccount.setBrokerBizId(accountExportDTO.getBrokerBizId());
......@@ -143,7 +146,6 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
fortuneAccount.setCurrency(accountExportDTO.getCurrency());
fortuneAccount.setHkdAmount(accountExportDTO.getAmount());
fortuneAccount.setFortuneAccountDate(this.getActualPayoutDate(actualPayoutDate));
// 出账状态默认待出账
fortuneAccount.setStatus(FortuneStatusEnum.CHECKED.getItemValue());
// 转换为List<Map<String, Object>>
......@@ -219,6 +221,50 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
}
/**
* 带本地缓存的业务编号生成(解决同一批次内相同 prefix 的流水号重复问题)
* @param prefix 业务编号前缀(出账年月 + 转介人内部编号后6位)
* @param billingYearMonth 出账年月
* @param internalCode 转介人内部编号
* @param prefixSerialCache 本地缓存(Map<prefix, 当前已使用的最大流水号数值>)
* @return 完整的业务编号
*/
private String generateBusinessNoWithCache(String prefix, String billingYearMonth,
String internalCode, Map<String, Integer> prefixSerialCache) {
// 从缓存中获取当前 prefix 已分配的最大流水号,若不存在则查询数据库
Integer currentMaxSerial = prefixSerialCache.get(prefix);
if (currentMaxSerial == null) {
String maxSerialFromDb = getMaxSerialNoByPrefix(prefix); // 返回如 "000000"
currentMaxSerial = Integer.parseInt(maxSerialFromDb);
}
int nextSerial = currentMaxSerial + 1;
String serialPart = String.format("%06d", nextSerial);
String businessNo = BusinessNoUtils.generate(billingYearMonth, internalCode, serialPart);
// 更新缓存
prefixSerialCache.put(prefix, nextSerial);
return businessNo;
}
/**
* 根据前缀查询当前最大流水号(后6位)
* @param prefix 业务编号前缀(出账年月+转介人内部编号后6位,共12位)
* @return 最大流水号(6位字符串),如果没有记录则返回 "000000"
*/
private String getMaxSerialNoByPrefix(String prefix) {
// 查询 business_no 以指定前缀开头的记录,按业务编号降序取第一条
LambdaQueryWrapper<FortuneAccount> wrapper = new LambdaQueryWrapper<>();
wrapper.likeRight(FortuneAccount::getBusinessNo, prefix)
.orderByDesc(FortuneAccount::getBusinessNo)
.last("limit 1");
FortuneAccount account = this.getOne(wrapper, false);
if (account == null) {
return "000000";
}
String businessNo = account.getBusinessNo();
// 取最后6位作为流水号
return businessNo.substring(businessNo.length() - 6);
}
private Date getActualPayoutDate(LocalDate actualPayoutDate) {
if (actualPayoutDate == null) {
return null;
......
package com.yd.csf.service.utils;
import java.util.concurrent.ThreadLocalRandom;
/**
* 业务编号生成工具类
* <p>格式:出账年月 + 转介人内部编号后6位(无则补0) + 6位随机数字</p>
* 格式:出账年月(6) + 转介人内部编号后6位 + 6位流水号(从000001开始递增)
*/
public class BusinessNoUtils {
/**
* 生成业务编号
*
* 生成业务编号(流水号由调用方传入)
* @param billingYearMonth 出账年月,如 "202604"
* @param referrerInnerNo 转介人内部编号,可为 null 或空字符串
* @return 完整的业务编号字符串
* @param referrerInnerNo 转介人内部编号,可为null或空
* @param serialPart 6位流水号(如 "000001")
* @return 完整业务编号
*/
public static String generate(String billingYearMonth, String referrerInnerNo) {
public static String generate(String billingYearMonth, String referrerInnerNo, String serialPart) {
String referrerPart = formatReferrerInnerNo(referrerInnerNo);
String serialPart = generateRandomSerial();
return billingYearMonth + referrerPart + serialPart;
}
......@@ -33,9 +30,13 @@ public class BusinessNoUtils {
return String.format("%6s", no).replace(' ', '0');
}
// 生成6位随机数字(000000~999999)
private static String generateRandomSerial() {
int random = ThreadLocalRandom.current().nextInt(1000000);
return String.format("%06d", random);
/**
* 获取业务编号中的前缀部分(用于数据库查询)
* @param billingYearMonth 出账年月
* @param referrerInnerNo 转介人内部编号
* @return 前缀字符串(12位)
*/
public static String getPrefix(String billingYearMonth, String referrerInnerNo) {
return billingYearMonth + formatReferrerInnerNo(referrerInnerNo);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment