refactor(glt): 优化套票发放服务逻辑

- 引入 IssueOutcome 枚举替代布尔返回值,提高代码可读性
- 恢复并完善订单时间条件查询逻辑
- 移除调试用的 System.out.println 语句
- 实现订单状态更新机制,发放完成后将订单置为已完成
- 增强幂等性处理,支持已处理订单的跳过逻辑
- 统一异常情况处理,各类失败场景返回对应枚举值
- 添加详细的注释说明业务逻辑和处理流程
This commit is contained in:
2026-02-04 10:12:55 +08:00
parent 9a79aff47d
commit 937e707890

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.glt.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.glt.entity.GltTicketTemplate;
import com.gxwebsoft.glt.entity.GltUserTicket;
import com.gxwebsoft.glt.entity.GltUserTicketLog;
@@ -36,6 +37,13 @@ public class GltTicketIssueService {
public static final int CHANGE_TYPE_ISSUE = 10;
private enum IssueOutcome {
ISSUED,
ALREADY_ISSUED,
SKIPPED,
NO_TEMPLATE
}
private final ShopOrderService shopOrderService;
private final ShopOrderGoodsService shopOrderGoodsService;
@@ -59,17 +67,15 @@ public class GltTicketIssueService {
.eq(ShopOrder::getPayStatus, true)
.eq(ShopOrder::getOrderStatus, 0)
// 今日订单(兼容:以 create_time 或 pay_time 任一落在今日即可)
// .and(w -> w
// .ge(ShopOrder::getCreateTime, todayStart).lt(ShopOrder::getCreateTime, tomorrowStart)
// .or()
// .ge(ShopOrder::getPayTime, todayStart).lt(ShopOrder::getPayTime, tomorrowStart)
// )
.and(w -> w
.ge(ShopOrder::getCreateTime, todayStart).lt(ShopOrder::getCreateTime, tomorrowStart)
.or()
.ge(ShopOrder::getPayTime, todayStart).lt(ShopOrder::getPayTime, tomorrowStart)
)
.orderByAsc(ShopOrder::getPayTime)
.orderByAsc(ShopOrder::getOrderId)
);
System.out.println("orders = " + orders.size());
if (orders.isEmpty()) {
log.debug("套票发放扫描:今日无符合条件的订单 tenantId={}, formId={}", tenantId, formId);
return;
@@ -104,29 +110,48 @@ public class GltTicketIssueService {
return 0;
}
int issuedCount = 0;
int issuedCount = 0; // 本轮新增发放数量(用于统计)
boolean shouldCompleteOrder = false;
for (ShopOrderGoods og : goodsList) {
if (!Objects.equals(og.getGoodsId(), formId)) {
continue;
}
boolean issued = Boolean.TRUE.equals(transactionTemplate.execute(status -> doIssueOne(tenantId, order, og)));
if (issued) {
IssueOutcome outcome = transactionTemplate.execute(status -> doIssueOne(tenantId, order, og));
if (outcome == IssueOutcome.ISSUED) {
issuedCount++;
shouldCompleteOrder = true;
} else if (outcome == IssueOutcome.ALREADY_ISSUED) {
// 幂等:已处理过也应视为完成,避免重复扫描
shouldCompleteOrder = true;
}
}
if (shouldCompleteOrder) {
LocalDateTime now = LocalDateTime.now();
// 任务执行完后将订单置为“已完成”order_status=1
shopOrderService.update(
new LambdaUpdateWrapper<ShopOrder>()
.eq(ShopOrder::getOrderId, order.getOrderId())
.eq(ShopOrder::getTenantId, tenantId)
.set(ShopOrder::getOrderStatus, 1)
.set(ShopOrder::getHasTakeGift, true)
.set(ShopOrder::getUpdateTime, now)
);
}
return issuedCount;
}
private boolean doIssueOne(Integer tenantId, ShopOrder order, ShopOrderGoods og) {
private IssueOutcome doIssueOne(Integer tenantId, ShopOrder order, ShopOrderGoods og) {
if (order.getUserId() == null) {
log.warn("套票发放跳过:订单缺少 userId - tenantId={}, orderNo={}", tenantId, order.getOrderNo());
return false;
return IssueOutcome.SKIPPED;
}
if (og.getId() == null) {
log.warn("套票发放跳过:订单商品缺少 id - tenantId={}, orderNo={}", tenantId, order.getOrderNo());
return false;
return IssueOutcome.SKIPPED;
}
GltTicketTemplate template = gltTicketTemplateService.getOne(
@@ -140,12 +165,12 @@ public class GltTicketIssueService {
if (template == null) {
log.warn("套票发放跳过:未配置套票模板 - tenantId={}, goodsId={}, orderNo={}",
tenantId, og.getGoodsId(), order.getOrderNo());
return false;
return IssueOutcome.NO_TEMPLATE;
}
if (!Boolean.TRUE.equals(template.getEnabled())) {
log.info("套票发放跳过:套票模板未启用 - tenantId={}, templateId={}, goodsId={}",
tenantId, template.getId(), template.getGoodsId());
return false;
return IssueOutcome.SKIPPED;
}
// 幂等:同一 orderNo + orderGoodsId 只发放一次
@@ -161,21 +186,21 @@ public class GltTicketIssueService {
if (existing != null) {
log.debug("套票已发放,跳过 - tenantId={}, orderNo={}, orderGoodsId={}, userTicketId={}",
tenantId, order.getOrderNo(), og.getId(), existing.getId());
return false;
return IssueOutcome.ALREADY_ISSUED;
}
int buyQty = og.getTotalNum() != null ? og.getTotalNum() : 0;
if (buyQty <= 0) {
log.warn("套票发放跳过:购买数量无效 - tenantId={}, orderNo={}, orderGoodsId={}, totalNum={}",
tenantId, order.getOrderNo(), og.getId(), og.getTotalNum());
return false;
return IssueOutcome.SKIPPED;
}
Integer minBuyQty = template.getMinBuyQty();
if (minBuyQty != null && minBuyQty > 0 && buyQty < minBuyQty) {
log.info("套票发放跳过:未达到最小购买数量 - tenantId={}, orderNo={}, buyQty={}, minBuyQty={}",
tenantId, order.getOrderNo(), buyQty, minBuyQty);
return false;
return IssueOutcome.SKIPPED;
}
int giftMultiplier = template.getGiftMultiplier() != null ? template.getGiftMultiplier() : 0;
@@ -189,7 +214,7 @@ public class GltTicketIssueService {
if (totalQty <= 0) {
log.info("套票发放跳过计算结果为0 - tenantId={}, orderNo={}, buyQty={}, giftMultiplier={}, includeBuyQty={}",
tenantId, order.getOrderNo(), buyQty, giftMultiplier, template.getIncludeBuyQty());
return false;
return IssueOutcome.SKIPPED;
}
LocalDateTime now = LocalDateTime.now();
@@ -251,7 +276,7 @@ public class GltTicketIssueService {
log.info("套票发放成功 - tenantId={}, orderNo={}, orderGoodsId={}, templateId={}, userTicketId={}, totalQty={}",
tenantId, order.getOrderNo(), og.getId(), template.getId(), userTicket.getId(), totalQty);
return true;
return IssueOutcome.ISSUED;
}
private List<GltUserTicketRelease> buildReleasePlan(GltTicketTemplate template,