fix:【MALL 商城管理】优惠劵扣减时,增加 WHERE 乐观锁

This commit is contained in:
YunaiV 2025-07-13 17:06:40 +08:00
parent a54e743a88
commit a9c7b584cc
4 changed files with 22 additions and 11 deletions

View File

@ -31,9 +31,13 @@ import java.util.List;
public class CouponTemplateDO extends BaseDO { public class CouponTemplateDO extends BaseDO {
/** /**
* 不限制领取数量 * 领取数量 - 不限制
*/ */
public static final Integer TIME_LIMIT_COUNT_MAX = -1; public static final Integer TAKE_LIMIT_COUNT_MAX = -1;
/**
* 发放数量 - 不限制
*/
public static final Integer TOTAL_COUNT_MAX = -1;
// ========== 基本信息 BEGIN ========== // ========== 基本信息 BEGIN ==========
/** /**

View File

@ -40,10 +40,16 @@ 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> updateWrapper = new LambdaUpdateWrapper<CouponTemplateDO>()
.eq(CouponTemplateDO::getId, id) .eq(CouponTemplateDO::getId, id)
.setSql("take_count = take_count + " + incrCount)); .setSql("take_count = take_count + " + incrCount);
// 增加已领取的数量incrCount 为正数需要考虑发放数量 totalCount 的限制
if (incrCount > 0) {
updateWrapper.and(i -> i.apply("take_count < total_count")
.or().eq(CouponTemplateDO::getTotalCount, CouponTemplateDO.TOTAL_COUNT_MAX));
}
return update(updateWrapper);
} }
default List<CouponTemplateDO> selectListByTakeType(Integer takeType) { default List<CouponTemplateDO> selectListByTakeType(Integer takeType) {

View File

@ -137,7 +137,6 @@ public class CouponServiceImpl implements CouponService {
// 4. 增加优惠劵模板的领取数量 // 4. 增加优惠劵模板的领取数量
couponTemplateService.updateCouponTemplateTakeCount(template.getId(), userIds.size()); couponTemplateService.updateCouponTemplateTakeCount(template.getId(), userIds.size());
return convertMultiMap(couponList, CouponDO::getUserId, CouponDO::getId); return convertMultiMap(couponList, CouponDO::getUserId, CouponDO::getId);
} }
@ -281,7 +280,7 @@ public class CouponServiceImpl implements CouponService {
} }
// 校验发放数量不能过小仅在 CouponTakeTypeEnum.USER 用户领取时 // 校验发放数量不能过小仅在 CouponTakeTypeEnum.USER 用户领取时
if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType())
&& ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 非不限制
&& couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
throw exception(COUPON_TEMPLATE_NOT_ENOUGH); throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
} }

View File

@ -22,8 +22,7 @@ import java.util.List;
import java.util.Objects; 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.*;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL;
/** /**
* 优惠劵模板 Service 实现类 * 优惠劵模板 Service 实现类
@ -60,7 +59,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
CouponTemplateDO couponTemplate = validateCouponTemplateExists(updateReqVO.getId()); CouponTemplateDO couponTemplate = validateCouponTemplateExists(updateReqVO.getId());
// 校验发放数量不能过小仅在 CouponTakeTypeEnum.USER 用户领取时 // 校验发放数量不能过小仅在 CouponTakeTypeEnum.USER 用户领取时
if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType())
&& ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 非不限制
&& updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) { && updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) {
throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount()); throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount());
} }
@ -116,7 +115,10 @@ 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 (updateCount == 0) {
throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
}
} }
@Override @Override