feat(ticket): 实现水票分期释放功能支持
- 新增 releasePeriods 配置支持,可按总数量分期平均释放 - 修改原有逻辑:购买量立即可用,赠送量冻结按计划释放 - 当配置期数时按总票数生成每期释放计划,否则保持原逻辑 - 支持首期释放时机控制,支付成功当刻可立即释放首期票数 - 更新水票释放计划生成逻辑,期号从0开始计数 - 修正水票日志记录中的数量统计逻辑
This commit is contained in:
@@ -258,7 +258,7 @@ public class GltTicketIssueService {
|
||||
int giftMultiplier = template.getGiftMultiplier() != null ? template.getGiftMultiplier() : 0;
|
||||
int giftQty = buyQty * Math.max(giftMultiplier, 0);
|
||||
|
||||
// 购买量(buyQty)应立即可用;赠送量(giftQty)进入冻结并按计划释放。
|
||||
// 总票数(购买量 + 赠送量)
|
||||
int totalQty = buyQty + giftQty;
|
||||
|
||||
if (totalQty <= 0) {
|
||||
@@ -269,6 +269,15 @@ public class GltTicketIssueService {
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
boolean useReleasePeriods = template.getReleasePeriods() != null && template.getReleasePeriods() > 0;
|
||||
|
||||
// 释放期数(releasePeriods)为高优先级:
|
||||
// - 配置了期数:按期数平均分摊 totalQty,每期释放;不再“先把购买桶数一次性释放”。
|
||||
// - 未配置期数:保持原逻辑(购买量立即可用,赠送量冻结并按计划释放)。
|
||||
int initAvailableQty = useReleasePeriods ? 0 : buyQty;
|
||||
int initFrozenQty = useReleasePeriods ? totalQty : giftQty;
|
||||
int initReleasedQty = useReleasePeriods ? 0 : buyQty;
|
||||
|
||||
GltUserTicket userTicket = new GltUserTicket();
|
||||
userTicket.setTemplateId(template.getId());
|
||||
userTicket.setGoodsId(og.getGoodsId());
|
||||
@@ -276,11 +285,10 @@ public class GltTicketIssueService {
|
||||
userTicket.setOrderNo(order.getOrderNo());
|
||||
userTicket.setOrderGoodsId(og.getId());
|
||||
userTicket.setTotalQty(totalQty);
|
||||
userTicket.setAvailableQty(buyQty);
|
||||
userTicket.setFrozenQty(giftQty);
|
||||
userTicket.setAvailableQty(initAvailableQty);
|
||||
userTicket.setFrozenQty(initFrozenQty);
|
||||
userTicket.setUsedQty(0);
|
||||
// 初始可用量来自“购买量”,视为已释放
|
||||
userTicket.setReleasedQty(buyQty);
|
||||
userTicket.setReleasedQty(initReleasedQty);
|
||||
userTicket.setOrderGoodsQty(og.getTotalNum());
|
||||
userTicket.setUserId(order.getUserId());
|
||||
userTicket.setSortNumber(0);
|
||||
@@ -293,12 +301,36 @@ public class GltTicketIssueService {
|
||||
|
||||
gltUserTicketService.save(userTicket);
|
||||
|
||||
// 生成释放计划(按月)
|
||||
// 生成释放计划:
|
||||
// - 配置 releasePeriods:按 totalQty 生成每期释放量(periods 优先)
|
||||
// - 未配置 releasePeriods:按 giftQty 生成每期释放量
|
||||
LocalDateTime baseTime = order.getPayTime() != null ? order.getPayTime() : order.getCreateTime();
|
||||
if (baseTime == null) {
|
||||
baseTime = now;
|
||||
}
|
||||
List<GltUserTicketRelease> releases = buildReleasePlan(template, userTicket, baseTime, giftQty, now);
|
||||
int planQty = useReleasePeriods ? totalQty : giftQty;
|
||||
List<GltUserTicketRelease> releases = buildReleasePlan(template, userTicket, baseTime, planQty, now);
|
||||
|
||||
// 若启用了 releasePeriods 且首期释放时机为“支付成功当刻”,则将首期释放量直接计入可用,
|
||||
// 避免用户刚购买后短时间内无可用水票;后续期数仍由自动释放任务按 release_time 释放。
|
||||
if (useReleasePeriods && !releases.isEmpty() && !Objects.equals(template.getFirstReleaseMode(), 1)) {
|
||||
GltUserTicketRelease first = releases.get(0);
|
||||
Integer firstQtyObj = first.getReleaseQty();
|
||||
LocalDateTime firstTime = first.getReleaseTime();
|
||||
int firstQty = firstQtyObj != null ? firstQtyObj : 0;
|
||||
if (firstQty > 0 && (firstTime == null || !firstTime.isAfter(now))) {
|
||||
first.setStatus(1);
|
||||
first.setUpdateTime(now);
|
||||
|
||||
userTicket.setAvailableQty((userTicket.getAvailableQty() != null ? userTicket.getAvailableQty() : 0) + firstQty);
|
||||
userTicket.setFrozenQty((userTicket.getFrozenQty() != null ? userTicket.getFrozenQty() : 0) - firstQty);
|
||||
userTicket.setReleasedQty((userTicket.getReleasedQty() != null ? userTicket.getReleasedQty() : 0) + firstQty);
|
||||
userTicket.setUpdateTime(now);
|
||||
if (!gltUserTicketService.updateById(userTicket)) {
|
||||
throw new IllegalStateException("首期释放:更新用户水票失败 userTicketId=" + userTicket.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!releases.isEmpty()) {
|
||||
gltUserTicketReleaseService.saveBatch(releases);
|
||||
}
|
||||
@@ -307,11 +339,11 @@ public class GltTicketIssueService {
|
||||
GltUserTicketLog issueLog = new GltUserTicketLog();
|
||||
issueLog.setUserTicketId(userTicket.getId());
|
||||
issueLog.setChangeType(CHANGE_TYPE_ISSUE);
|
||||
issueLog.setChangeAvailable(buyQty);
|
||||
issueLog.setChangeFrozen(giftQty);
|
||||
issueLog.setChangeAvailable(userTicket.getAvailableQty() != null ? userTicket.getAvailableQty() : 0);
|
||||
issueLog.setChangeFrozen(userTicket.getFrozenQty() != null ? userTicket.getFrozenQty() : 0);
|
||||
issueLog.setChangeUsed(0);
|
||||
issueLog.setAvailableAfter(buyQty);
|
||||
issueLog.setFrozenAfter(giftQty);
|
||||
issueLog.setAvailableAfter(userTicket.getAvailableQty() != null ? userTicket.getAvailableQty() : 0);
|
||||
issueLog.setFrozenAfter(userTicket.getFrozenQty() != null ? userTicket.getFrozenQty() : 0);
|
||||
issueLog.setUsedAfter(0);
|
||||
issueLog.setOrderId(order.getOrderId());
|
||||
issueLog.setOrderNo(order.getOrderNo());
|
||||
@@ -402,12 +434,13 @@ public class GltTicketIssueService {
|
||||
if (releasePeriods != null && releasePeriods > 0) {
|
||||
int base = totalQty / releasePeriods;
|
||||
int remainder = totalQty % releasePeriods;
|
||||
for (int i = 1; i <= releasePeriods; i++) {
|
||||
int qty = base + (i <= remainder ? 1 : 0);
|
||||
// periodNo 从 0 开始:第0期、第1期……(更贴近任务执行计数)
|
||||
for (int i = 0; i < releasePeriods; i++) {
|
||||
int qty = base + (i < remainder ? 1 : 0);
|
||||
if (qty <= 0) {
|
||||
continue;
|
||||
}
|
||||
list.add(buildRelease(userTicket, i, qty, firstReleaseTime.plusMonths(i - 1), now));
|
||||
list.add(buildRelease(userTicket, i, qty, firstReleaseTime.plusMonths(i), now));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -417,13 +450,14 @@ public class GltTicketIssueService {
|
||||
: 10;
|
||||
int periods = (totalQty + monthlyReleaseQty - 1) / monthlyReleaseQty;
|
||||
int remaining = totalQty;
|
||||
for (int i = 1; i <= periods; i++) {
|
||||
// periodNo 从 0 开始:第0期、第1期……
|
||||
for (int i = 0; i < periods; i++) {
|
||||
int qty = Math.min(monthlyReleaseQty, remaining);
|
||||
if (qty <= 0) {
|
||||
break;
|
||||
}
|
||||
remaining -= qty;
|
||||
list.add(buildRelease(userTicket, i, qty, firstReleaseTime.plusMonths(i - 1), now));
|
||||
list.add(buildRelease(userTicket, i, qty, firstReleaseTime.plusMonths(i), now));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
Reference in New Issue
Block a user