feat(pricing): 添加优惠券用户领取数量限制功能

- 新增用户领取数量限制字段 userClaimLimit
- 区分已领取数量 claimedQuantity 和已使用数量 usedQuantity
- 添加用户领取次数统计方法 countUserCouponClaims
- 实现领取上限检查逻辑和错误码 CLAIM_LIMIT_REACHED
- 更新数据库表结构和索引优化建议
- 完善文档说明和版本更新记录
This commit is contained in:
2025-11-17 00:26:15 +08:00
parent 9ee466bd5e
commit 7835283f0f
6 changed files with 148 additions and 23 deletions

View File

@@ -194,6 +194,7 @@ public class CouponServiceImpl implements ICouponService {
info.setDiscountType(coupon.getCouponType());
info.setDiscountValue(coupon.getDiscountValue());
info.setActualDiscountAmount(actualDiscountAmount);
info.setUserClaimLimit(coupon.getUserClaimLimit());
return info;
}
@@ -230,20 +231,31 @@ public class CouponServiceImpl implements ICouponService {
}
// 5. 检查库存(如果有总量限制)
if (coupon.getTotalQuantity() != null && coupon.getUsedQuantity() != null) {
if (coupon.getUsedQuantity() >= coupon.getTotalQuantity()) {
if (coupon.getTotalQuantity() != null && coupon.getClaimedQuantity() != null) {
if (coupon.getClaimedQuantity() >= coupon.getTotalQuantity()) {
return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_OUT_OF_STOCK, "优惠券已领完");
}
}
// 6. 检查用户是否已经领取过该优惠券
// 6. 检查用户领取数量限制
if (coupon.getUserClaimLimit() != null && coupon.getUserClaimLimit() > 0) {
int userClaimCount = couponClaimRecordMapper.countUserCouponClaims(
request.getUserId(), request.getCouponId());
if (userClaimCount >= coupon.getUserClaimLimit()) {
return CouponClaimResult.failure(
CouponClaimResult.ERROR_CLAIM_LIMIT_REACHED,
"您已达到该优惠券的领取上限(" + coupon.getUserClaimLimit() + "张)");
}
}
// 7. 检查用户是否已经领取过该优惠券(兼容旧逻辑,双重保护)
PriceCouponClaimRecord existingRecord = couponClaimRecordMapper.selectUserCouponRecord(
request.getUserId(), request.getCouponId());
if (existingRecord != null) {
return CouponClaimResult.failure(CouponClaimResult.ERROR_ALREADY_CLAIMED, "您已经领取过该优惠券");
}
// 7. 创建领取记录
// 8. 创建领取记录
Date claimTime = new Date();
PriceCouponClaimRecord claimRecord = new PriceCouponClaimRecord();
claimRecord.setCouponId(request.getCouponId());
@@ -254,26 +266,26 @@ public class CouponServiceImpl implements ICouponService {
claimRecord.setCreateTime(claimTime);
claimRecord.setUpdateTime(claimTime);
claimRecord.setDeleted(0);
// 8. 插入领取记录
// 9. 插入领取记录
int insertResult = couponClaimRecordMapper.insert(claimRecord);
if (insertResult <= 0) {
log.error("插入优惠券领取记录失败: userId={}, couponId={}",
log.error("插入优惠券领取记录失败: userId={}, couponId={}",
request.getUserId(), request.getCouponId());
return CouponClaimResult.failure(CouponClaimResult.ERROR_SYSTEM_ERROR, "领取失败,请稍后重试");
}
// 9. 更新优惠券已使用数量(如果有总量限制
// 10. 更新优惠券已领取数量(区分于已使用数量
if (coupon.getTotalQuantity() != null) {
int updatedUsedQuantity = (coupon.getUsedQuantity() == null ? 0 : coupon.getUsedQuantity()) + 1;
coupon.setUsedQuantity(updatedUsedQuantity);
int updatedClaimedQuantity = (coupon.getClaimedQuantity() == null ? 0 : coupon.getClaimedQuantity()) + 1;
coupon.setClaimedQuantity(updatedClaimedQuantity);
couponConfigMapper.updateById(coupon);
}
log.info("优惠券领取成功: userId={}, couponId={}, claimRecordId={}",
log.info("优惠券领取成功: userId={}, couponId={}, claimRecordId={}",
request.getUserId(), request.getCouponId(), claimRecord.getId());
// 10. 返回成功结果
// 11. 返回成功结果
return CouponClaimResult.success(claimRecord, coupon);
} catch (Exception e) {