Compare commits

...

1 Commits

Author SHA1 Message Date
Cursor Agent
c796623148 Improve coupon template take count with stock validation logic
Co-authored-by: zhijiantianya <zhijiantianya@gmail.com>
2025-07-08 15:18:11 +00:00
3 changed files with 20 additions and 11 deletions

View File

@@ -40,10 +40,18 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
.orderByDesc(CouponTemplateDO::getId)); .orderByDesc(CouponTemplateDO::getId));
} }
default void updateTakeCount(Long id, Integer incrCount) { default int updateTakeCount(Long id, Integer incrCount) {
update(null, new LambdaUpdateWrapper<CouponTemplateDO>() LambdaUpdateWrapper<CouponTemplateDO> wrapper = new LambdaUpdateWrapper<CouponTemplateDO>()
.eq(CouponTemplateDO::getId, id) .eq(CouponTemplateDO::getId, id);
.setSql("take_count = take_count + " + incrCount));
// 只在增加数量时检查库存incrCount > 0
if (incrCount > 0) {
// 添加库存判断:剩余数量 >= 领取的数量,或者总数量为-1无限库存
wrapper.and(w -> w.apply("total_count = -1 OR (total_count - take_count) >= {0}", incrCount));
}
wrapper.setSql("take_count = take_count + " + incrCount);
return update(null, wrapper);
} }
default List<CouponTemplateDO> selectListByTakeType(Integer takeType) { default List<CouponTemplateDO> selectListByTakeType(Integer takeType) {

View File

@@ -279,12 +279,8 @@ public class CouponServiceImpl implements CouponService {
if (ObjUtil.notEqual(couponTemplate.getTakeType(), takeType.getType())) { if (ObjUtil.notEqual(couponTemplate.getTakeType(), takeType.getType())) {
throw exception(COUPON_TEMPLATE_CANNOT_TAKE); throw exception(COUPON_TEMPLATE_CANNOT_TAKE);
} }
// 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) // 注意:库存检查现在在数据库层面的 updateCouponTemplateTakeCount 方法中进行
if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) // 如果库存不足,该方法会抛出 COUPON_TEMPLATE_NOT_ENOUGH 异常
&& ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制
&& couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
}
// 校验"固定日期"的有效期类型是否过期 // 校验"固定日期"的有效期类型是否过期
if (CouponTemplateValidityTypeEnum.DATE.getType().equals(couponTemplate.getValidityType())) { if (CouponTemplateValidityTypeEnum.DATE.getType().equals(couponTemplate.getValidityType())) {
if (LocalDateTimeUtils.beforeNow(couponTemplate.getValidEndTime())) { if (LocalDateTimeUtils.beforeNow(couponTemplate.getValidEndTime())) {

View File

@@ -23,6 +23,7 @@ import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_ENOUGH;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL;
/** /**
@@ -116,7 +117,11 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
@Override @Override
public void updateCouponTemplateTakeCount(Long id, int incrCount) { public void updateCouponTemplateTakeCount(Long id, int incrCount) {
couponTemplateMapper.updateTakeCount(id, incrCount); int updateCount = couponTemplateMapper.updateTakeCount(id, incrCount);
// 只在增加数量且更新失败时,说明库存不足,抛出异常
if (incrCount > 0 && updateCount == 0) {
throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
}
} }
@Override @Override