You've already forked FrameTour-BE
refactor(pricing): 优化优惠券配置实体和领取逻辑
- 将时间字段类型从 LocalDateTime 改为 Date - 为优惠券领取数量更新添加无条件增加方法 - 区分有限量和无限量优惠券的领取处理逻辑 - 实现有总量限制优惠券的库存检查机制 - 统一更新已领取数量的计数逻辑
This commit is contained in:
@@ -3,7 +3,7 @@ package com.ycwl.basic.pricing.dto.resp;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 场景下可领取优惠券响应
|
* 场景下可领取优惠券响应
|
||||||
@@ -44,12 +44,12 @@ public class SceneCouponAvailableResp {
|
|||||||
/**
|
/**
|
||||||
* 有效期起始
|
* 有效期起始
|
||||||
*/
|
*/
|
||||||
private LocalDateTime validFrom;
|
private Date validFrom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 有效期结束
|
* 有效期结束
|
||||||
*/
|
*/
|
||||||
private LocalDateTime validUntil;
|
private Date validUntil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户可领取数量限制(每人最多可领,null或0表示无限制)
|
* 用户可领取数量限制(每人最多可领,null或0表示无限制)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.ycwl.basic.pricing.dto.resp;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,10 +54,10 @@ public class SceneCouponConfigResp {
|
|||||||
/**
|
/**
|
||||||
* 优惠券有效期起始
|
* 优惠券有效期起始
|
||||||
*/
|
*/
|
||||||
private LocalDateTime couponValidFrom;
|
private Date couponValidFrom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠券有效期结束
|
* 优惠券有效期结束
|
||||||
*/
|
*/
|
||||||
private LocalDateTime couponValidUntil;
|
private Date couponValidUntil;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import com.ycwl.basic.pricing.enums.CouponType;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,12 +79,12 @@ public class PriceCouponConfig {
|
|||||||
/**
|
/**
|
||||||
* 生效时间
|
* 生效时间
|
||||||
*/
|
*/
|
||||||
private LocalDateTime validFrom;
|
private Date validFrom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 失效时间
|
* 失效时间
|
||||||
*/
|
*/
|
||||||
private LocalDateTime validUntil;
|
private Date validUntil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否启用
|
* 是否启用
|
||||||
|
|||||||
@@ -40,13 +40,20 @@ public interface PriceCouponConfigMapper extends BaseMapper<PriceCouponConfig> {
|
|||||||
int incrementUsedQuantity(Long couponId);
|
int incrementUsedQuantity(Long couponId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 原子性增加已领取数量(仅对有限库存的优惠券生效)
|
* 原子性增加已领取数量(仅对有限库存的优惠券生效,带库存检查)
|
||||||
*/
|
*/
|
||||||
@Update("UPDATE price_coupon_config SET claimed_quantity = COALESCE(claimed_quantity, 0) + 1, " +
|
@Update("UPDATE price_coupon_config SET claimed_quantity = COALESCE(claimed_quantity, 0) + 1, " +
|
||||||
"update_time = NOW() WHERE id = #{couponId} AND total_quantity IS NOT NULL AND total_quantity > 0 " +
|
"update_time = NOW() WHERE id = #{couponId} AND total_quantity IS NOT NULL AND total_quantity > 0 " +
|
||||||
"AND COALESCE(claimed_quantity, 0) < total_quantity")
|
"AND COALESCE(claimed_quantity, 0) < total_quantity")
|
||||||
int incrementClaimedQuantityIfAvailable(@Param("couponId") Long couponId);
|
int incrementClaimedQuantityIfAvailable(@Param("couponId") Long couponId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无条件增加已领取数量(用于无限量优惠券的领取统计)
|
||||||
|
*/
|
||||||
|
@Update("UPDATE price_coupon_config SET claimed_quantity = COALESCE(claimed_quantity, 0) + 1, " +
|
||||||
|
"update_time = NOW() WHERE id = #{couponId}")
|
||||||
|
int incrementClaimedQuantity(@Param("couponId") Long couponId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插入优惠券配置
|
* 插入优惠券配置
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -316,11 +315,11 @@ public class CouponServiceImpl implements ICouponService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. 检查优惠券有效期
|
// 4. 检查优惠券有效期
|
||||||
LocalDateTime now = LocalDateTime.now();
|
Date now = new Date();
|
||||||
if (coupon.getValidFrom() != null && now.isBefore(coupon.getValidFrom())) {
|
if (coupon.getValidFrom() != null && now.before(coupon.getValidFrom())) {
|
||||||
return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_EXPIRED, "优惠券尚未生效");
|
return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_EXPIRED, "优惠券尚未生效");
|
||||||
}
|
}
|
||||||
if (coupon.getValidUntil() != null && now.isAfter(coupon.getValidUntil())) {
|
if (coupon.getValidUntil() != null && now.after(coupon.getValidUntil())) {
|
||||||
return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_EXPIRED, "优惠券已过期");
|
return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_EXPIRED, "优惠券已过期");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,17 +365,20 @@ public class CouponServiceImpl implements ICouponService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 9. 更新优惠券已领取数量(区分于已使用数量)
|
// 9. 更新优惠券已领取数量(区分于已使用数量)
|
||||||
// 仅在有总量限制时才更新claimedQuantity(totalQuantity为正整数)
|
|
||||||
if (coupon.getTotalQuantity() != null && coupon.getTotalQuantity() > 0) {
|
if (coupon.getTotalQuantity() != null && coupon.getTotalQuantity() > 0) {
|
||||||
|
// 有总量限制:使用带库存检查的原子更新
|
||||||
int affected = couponConfigMapper.incrementClaimedQuantityIfAvailable(coupon.getId());
|
int affected = couponConfigMapper.incrementClaimedQuantityIfAvailable(coupon.getId());
|
||||||
if (affected == 0) {
|
if (affected == 0) {
|
||||||
throw new CouponInvalidException(
|
throw new CouponInvalidException(
|
||||||
CouponClaimResult.ERROR_COUPON_OUT_OF_STOCK,
|
CouponClaimResult.ERROR_COUPON_OUT_OF_STOCK,
|
||||||
"优惠券已被领取完,请稍后重试");
|
"优惠券已被领取完,请稍后重试");
|
||||||
}
|
}
|
||||||
int updatedClaimedQuantity = (coupon.getClaimedQuantity() == null ? 0 : coupon.getClaimedQuantity()) + 1;
|
} else {
|
||||||
coupon.setClaimedQuantity(updatedClaimedQuantity);
|
// 无总量限制:无条件增加已领取数量(用于统计)
|
||||||
|
couponConfigMapper.incrementClaimedQuantity(coupon.getId());
|
||||||
}
|
}
|
||||||
|
int updatedClaimedQuantity = (coupon.getClaimedQuantity() == null ? 0 : coupon.getClaimedQuantity()) + 1;
|
||||||
|
coupon.setClaimedQuantity(updatedClaimedQuantity);
|
||||||
|
|
||||||
log.info("优惠券领取成功: userId={}, couponId={}, claimRecordId={}",
|
log.info("优惠券领取成功: userId={}, couponId={}, claimRecordId={}",
|
||||||
request.getUserId(), request.getCouponId(), claimRecord.getId());
|
request.getUserId(), request.getCouponId(), claimRecord.getId());
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.springframework.dao.DuplicateKeyException;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -301,11 +300,11 @@ public class SceneCouponServiceImpl implements ISceneCouponService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. 检查有效期
|
// 2. 检查有效期
|
||||||
LocalDateTime now = LocalDateTime.now();
|
Date now = new Date();
|
||||||
if (coupon.getValidFrom() != null && now.isBefore(coupon.getValidFrom())) {
|
if (coupon.getValidFrom() != null && now.before(coupon.getValidFrom())) {
|
||||||
return "优惠券尚未生效";
|
return "优惠券尚未生效";
|
||||||
}
|
}
|
||||||
if (coupon.getValidUntil() != null && now.isAfter(coupon.getValidUntil())) {
|
if (coupon.getValidUntil() != null && now.after(coupon.getValidUntil())) {
|
||||||
return "优惠券已过期";
|
return "优惠券已过期";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user