Commit a9c7b584ccbf2ad377893c0316fd70df5bbbc40d

Authored by YunaiV
1 parent a54e743a

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

yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java
@@ -31,9 +31,13 @@ import java.util.List; @@ -31,9 +31,13 @@ import java.util.List;
31 public class CouponTemplateDO extends BaseDO { 31 public class CouponTemplateDO extends BaseDO {
32 32
33 /** 33 /**
34 - * 不限制领取数量 34 + * 领取数量 - 不限制
35 */ 35 */
36 - public static final Integer TIME_LIMIT_COUNT_MAX = -1; 36 + public static final Integer TAKE_LIMIT_COUNT_MAX = -1;
  37 + /**
  38 + * 发放数量 - 不限制
  39 + */
  40 + public static final Integer TOTAL_COUNT_MAX = -1;
37 41
38 // ========== 基本信息 BEGIN ========== 42 // ========== 基本信息 BEGIN ==========
39 /** 43 /**
yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
@@ -40,10 +40,16 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { @@ -40,10 +40,16 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
40 .orderByDesc(CouponTemplateDO::getId)); 40 .orderByDesc(CouponTemplateDO::getId));
41 } 41 }
42 42
43 - default void updateTakeCount(Long id, Integer incrCount) {  
44 - update(null, new LambdaUpdateWrapper<CouponTemplateDO>() 43 + default int updateTakeCount(Long id, Integer incrCount) {
  44 + LambdaUpdateWrapper<CouponTemplateDO> updateWrapper = new LambdaUpdateWrapper<CouponTemplateDO>()
45 .eq(CouponTemplateDO::getId, id) 45 .eq(CouponTemplateDO::getId, id)
46 - .setSql("take_count = take_count + " + incrCount)); 46 + .setSql("take_count = take_count + " + incrCount);
  47 + // 增加已领取的数量(incrCount 为正数),需要考虑发放数量 totalCount 的限制
  48 + if (incrCount > 0) {
  49 + updateWrapper.and(i -> i.apply("take_count < total_count")
  50 + .or().eq(CouponTemplateDO::getTotalCount, CouponTemplateDO.TOTAL_COUNT_MAX));
  51 + }
  52 + return update(updateWrapper);
47 } 53 }
48 54
49 default List<CouponTemplateDO> selectListByTakeType(Integer takeType) { 55 default List<CouponTemplateDO> selectListByTakeType(Integer takeType) {
yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
@@ -137,7 +137,6 @@ public class CouponServiceImpl implements CouponService { @@ -137,7 +137,6 @@ public class CouponServiceImpl implements CouponService {
137 137
138 // 4. 增加优惠劵模板的领取数量 138 // 4. 增加优惠劵模板的领取数量
139 couponTemplateService.updateCouponTemplateTakeCount(template.getId(), userIds.size()); 139 couponTemplateService.updateCouponTemplateTakeCount(template.getId(), userIds.size());
140 -  
141 return convertMultiMap(couponList, CouponDO::getUserId, CouponDO::getId); 140 return convertMultiMap(couponList, CouponDO::getUserId, CouponDO::getId);
142 } 141 }
143 142
@@ -281,7 +280,7 @@ public class CouponServiceImpl implements CouponService { @@ -281,7 +280,7 @@ public class CouponServiceImpl implements CouponService {
281 } 280 }
282 // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) 281 // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时)
283 if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) 282 if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType())
284 - && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 283 + && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 非不限制
285 && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { 284 && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
286 throw exception(COUPON_TEMPLATE_NOT_ENOUGH); 285 throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
287 } 286 }
yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
@@ -22,8 +22,7 @@ import java.util.List; @@ -22,8 +22,7 @@ import java.util.List;
22 import java.util.Objects; 22 import java.util.Objects;
23 23
24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
25 -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS;  
26 -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL; 25 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
27 26
28 /** 27 /**
29 * 优惠劵模板 Service 实现类 28 * 优惠劵模板 Service 实现类
@@ -60,7 +59,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { @@ -60,7 +59,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
60 CouponTemplateDO couponTemplate = validateCouponTemplateExists(updateReqVO.getId()); 59 CouponTemplateDO couponTemplate = validateCouponTemplateExists(updateReqVO.getId());
61 // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) 60 // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时)
62 if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) 61 if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType())
63 - && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 62 + && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 非不限制
64 && updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) { 63 && updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) {
65 throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount()); 64 throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount());
66 } 65 }
@@ -116,7 +115,10 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { @@ -116,7 +115,10 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
116 115
117 @Override 116 @Override
118 public void updateCouponTemplateTakeCount(Long id, int incrCount) { 117 public void updateCouponTemplateTakeCount(Long id, int incrCount) {
119 - couponTemplateMapper.updateTakeCount(id, incrCount); 118 + int updateCount = couponTemplateMapper.updateTakeCount(id, incrCount);
  119 + if (updateCount == 0) {
  120 + throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
  121 + }
120 } 122 }
121 123
122 @Override 124 @Override