You've already forked FrameTour-BE
feat(pricing): 支持发放多个首次打印优惠券
- 修改自动发券逻辑,支持发放多个符合条件的首次优惠券 - 更新查找优惠券方法,返回所有匹配的优惠券ID列表 - 添加发券过程中的异常处理,确保部分失败不影响其他券发放 - 记录详细的发券日志,包括成功、跳过和失败的数量 - 优化日志输出,提供更清晰的调试信息
This commit is contained in:
@@ -36,26 +36,37 @@ public class AutoCouponServiceImpl implements IAutoCouponService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查找该景区、该商品类型的首次打印优惠券配置
|
// 2. 查找该景区、该商品类型的所有首次打印优惠券配置
|
||||||
Long couponId = findFirstCouponId(scenicId, productType);
|
List<Long> couponIds = findFirstCouponIds(scenicId, productType);
|
||||||
if (couponId == null) {
|
if (couponIds == null || couponIds.isEmpty()) {
|
||||||
log.debug("景区未配置首次打印优惠券: scenicId={}, productType={}", scenicId, productType);
|
log.debug("景区未配置首次打印优惠券: scenicId={}, productType={}", scenicId, productType);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 检查用户是否已领取过该券(领券即消耗首次资格)
|
log.info("找到{}张首次优惠券待发放: scenicId={}, productType={}, couponIds={}",
|
||||||
|
couponIds.size(), scenicId, productType, couponIds);
|
||||||
|
|
||||||
|
// 3. 遍历所有优惠券,逐一检查并发放
|
||||||
|
int successCount = 0;
|
||||||
|
int skipCount = 0;
|
||||||
|
int failCount = 0;
|
||||||
|
|
||||||
|
for (Long couponId : couponIds) {
|
||||||
|
try {
|
||||||
|
// 检查用户是否已领取过该券(领券即消耗首次资格)
|
||||||
PriceCouponClaimRecord existingRecord = couponClaimRecordMapper.selectUserCouponRecord(
|
PriceCouponClaimRecord existingRecord = couponClaimRecordMapper.selectUserCouponRecord(
|
||||||
memberId,
|
memberId,
|
||||||
couponId
|
couponId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existingRecord != null) {
|
if (existingRecord != null) {
|
||||||
log.debug("用户已领取过首次优惠券,不重复发券: memberId={}, couponId={}, claimTime={}",
|
log.debug("用户已领取过优惠券,跳过: memberId={}, couponId={}, claimTime={}",
|
||||||
memberId, couponId, existingRecord.getClaimTime());
|
memberId, couponId, existingRecord.getClaimTime());
|
||||||
return false;
|
skipCount++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 自动发券
|
// 自动发券
|
||||||
CouponClaimRequest request = new CouponClaimRequest(
|
CouponClaimRequest request = new CouponClaimRequest(
|
||||||
memberId,
|
memberId,
|
||||||
couponId,
|
couponId,
|
||||||
@@ -64,11 +75,23 @@ public class AutoCouponServiceImpl implements IAutoCouponService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
couponService.claimCoupon(request);
|
couponService.claimCoupon(request);
|
||||||
|
successCount++;
|
||||||
|
|
||||||
log.info("成功自动发放首次打印优惠券: memberId={}, faceId={}, scenicId={}, productType={}, couponId={}",
|
log.info("成功自动发放首次优惠券: memberId={}, faceId={}, scenicId={}, productType={}, couponId={}",
|
||||||
memberId, faceId, scenicId, productType, couponId);
|
memberId, faceId, scenicId, productType, couponId);
|
||||||
|
|
||||||
return true;
|
} catch (Exception e) {
|
||||||
|
failCount++;
|
||||||
|
log.error("单张优惠券发放失败,继续处理其他券: memberId={}, couponId={}, error={}",
|
||||||
|
memberId, couponId, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("自动发券完成: memberId={}, 成功{}张, 跳过{}张, 失败{}张",
|
||||||
|
memberId, successCount, skipCount, failCount);
|
||||||
|
|
||||||
|
// 只要有一张成功就返回true
|
||||||
|
return successCount > 0;
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("自动发券失败: memberId={}, faceId={}, scenicId={}, productType={}",
|
log.error("自动发券失败: memberId={}, faceId={}, scenicId={}, productType={}",
|
||||||
@@ -78,14 +101,15 @@ public class AutoCouponServiceImpl implements IAutoCouponService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查找指定景区、指定商品类型的首次打印优惠券ID
|
* 查找指定景区、指定商品类型的所有首次打印优惠券ID
|
||||||
* 规则:优惠券名称包含 "首次" 且 适用商品类型包含目标类型
|
* 规则:优惠券名称包含 "首次" 且 适用商品类型包含目标类型
|
||||||
*
|
*
|
||||||
* @param scenicId 景区ID
|
* @param scenicId 景区ID
|
||||||
* @param productType 商品类型
|
* @param productType 商品类型
|
||||||
* @return 优惠券ID,未找到返回null
|
* @return 优惠券ID列表,未找到返回空列表
|
||||||
*/
|
*/
|
||||||
private Long findFirstCouponId(Long scenicId, ProductType productType) {
|
private List<Long> findFirstCouponIds(Long scenicId, ProductType productType) {
|
||||||
|
List<Long> couponIds = new java.util.ArrayList<>();
|
||||||
try {
|
try {
|
||||||
// 查询该景区的有效优惠券
|
// 查询该景区的有效优惠券
|
||||||
List<PriceCouponConfig> coupons = couponConfigMapper.selectValidCouponsByScenicId(
|
List<PriceCouponConfig> coupons = couponConfigMapper.selectValidCouponsByScenicId(
|
||||||
@@ -100,17 +124,22 @@ public class AutoCouponServiceImpl implements IAutoCouponService {
|
|||||||
String applicableProducts = coupon.getApplicableProducts();
|
String applicableProducts = coupon.getApplicableProducts();
|
||||||
if (applicableProducts != null &&
|
if (applicableProducts != null &&
|
||||||
applicableProducts.contains(productType.getCode())) {
|
applicableProducts.contains(productType.getCode())) {
|
||||||
return coupon.getId();
|
couponIds.add(coupon.getId());
|
||||||
|
log.debug("找到匹配的首次优惠券: couponId={}, couponName={}, scenicId={}, productType={}",
|
||||||
|
coupon.getId(), coupon.getCouponName(), scenicId, productType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (couponIds.isEmpty()) {
|
||||||
log.debug("未找到匹配的首次打印优惠券: scenicId={}, productType={}", scenicId, productType);
|
log.debug("未找到匹配的首次打印优惠券: scenicId={}, productType={}", scenicId, productType);
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
return couponIds;
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("查找首次打印优惠券失败: scenicId={}, productType={}", scenicId, productType, e);
|
log.error("查找首次打印优惠券失败: scenicId={}, productType={}", scenicId, productType, e);
|
||||||
return null;
|
return couponIds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user