Commit 3fbce643ee6f4e1cdcc871dd3b2608d518e4c0c2

Authored by owen
1 parent 76f510f2

mall: 发送优惠券功能优化

Showing 11 changed files with 55 additions and 109 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTakeTypeEnum.java
@@ -15,11 +15,9 @@ import java.util.Arrays; @@ -15,11 +15,9 @@ import java.util.Arrays;
15 @Getter 15 @Getter
16 public enum CouponTakeTypeEnum implements IntArrayValuable { 16 public enum CouponTakeTypeEnum implements IntArrayValuable {
17 17
18 - COMMON(0, "通用"), // TODO @疯狂:要不去掉“通用"和“兑换”,保持和 crmeb 一致;就手动领取、指定发送、新人券  
19 BY_USER(1, "直接领取"), // 用户可在首页、每日领劵直接领取 18 BY_USER(1, "直接领取"), // 用户可在首页、每日领劵直接领取
20 BY_ADMIN(2, "指定发放"), // 后台指定会员赠送优惠劵 19 BY_ADMIN(2, "指定发放"), // 后台指定会员赠送优惠劵
21 BY_REGISTER(3, "新人券"), // 注册时自动领取 20 BY_REGISTER(3, "新人券"), // 注册时自动领取
22 - BY_EXCHANGE(4, "兑换"), // 一般渠道券通过兑换领取  
23 ; 21 ;
24 22
25 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTakeTypeEnum::getValue).toArray(); 23 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTakeTypeEnum::getValue).toArray();
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponController.java
@@ -76,8 +76,8 @@ public class CouponController { @@ -76,8 +76,8 @@ public class CouponController {
76 @Operation(summary = "发送优惠劵") 76 @Operation(summary = "发送优惠劵")
77 @PreAuthorize("@ss.hasPermission('promotion:coupon:send')") 77 @PreAuthorize("@ss.hasPermission('promotion:coupon:send')")
78 public CommonResult<Boolean> sendCoupon(@Valid @RequestBody CouponSendReqVO reqVO) { 78 public CommonResult<Boolean> sendCoupon(@Valid @RequestBody CouponSendReqVO reqVO) {
79 - Boolean result = couponService.sendCoupon(reqVO.getTemplateId(), reqVO.getUserIds());  
80 - return success(result); 79 + couponService.takeCouponByAdmin(reqVO.getTemplateId(), reqVO.getUserIds());
  80 + return success(true);
81 } 81 }
82 82
83 } 83 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponTemplateController.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.coupon; 1 package cn.iocoder.yudao.module.promotion.controller.admin.coupon;
2 2
3 -import cn.hutool.core.collection.ListUtil;  
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.*; 5 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.*;
7 import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert; 6 import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert;
8 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
9 -import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;  
10 import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; 8 import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService;
11 import io.swagger.v3.oas.annotations.Operation; 9 import io.swagger.v3.oas.annotations.Operation;
12 import io.swagger.v3.oas.annotations.Parameter; 10 import io.swagger.v3.oas.annotations.Parameter;
@@ -17,7 +15,6 @@ import org.springframework.web.bind.annotation.*; @@ -17,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
17 15
18 import javax.annotation.Resource; 16 import javax.annotation.Resource;
19 import javax.validation.Valid; 17 import javax.validation.Valid;
20 -import java.util.List;  
21 18
22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
23 20
@@ -78,15 +75,4 @@ public class CouponTemplateController { @@ -78,15 +75,4 @@ public class CouponTemplateController {
78 PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(pageVO); 75 PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(pageVO);
79 return success(CouponTemplateConvert.INSTANCE.convertPage(pageResult)); 76 return success(CouponTemplateConvert.INSTANCE.convertPage(pageResult));
80 } 77 }
81 -  
82 - // TODO @疯狂:是不是可以合并到 getCouponTemplatePage 接口,作为一个参数选择  
83 - @GetMapping("/can-take-page")  
84 - @Operation(summary = "获得可用于领取的优惠劵模板分页")  
85 - @PreAuthorize("@ss.hasPermission('promotion:coupon-template:query')")  
86 - public CommonResult<PageResult<CouponTemplateRespVO>> getCanTakeCouponTemplatePage(@Valid CouponTemplatePageReqVO pageVO) {  
87 - List<Integer> canTakeTypes = ListUtil.of(CouponTakeTypeEnum.COMMON.getValue(), CouponTakeTypeEnum.BY_ADMIN.getValue());  
88 - PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCanTakeCouponTemplatePage(pageVO, canTakeTypes);  
89 - return success(CouponTemplateConvert.INSTANCE.convertPage(pageResult));  
90 - }  
91 -  
92 } 78 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplatePageReqVO.java
@@ -8,6 +8,7 @@ import lombok.ToString; @@ -8,6 +8,7 @@ import lombok.ToString;
8 import org.springframework.format.annotation.DateTimeFormat; 8 import org.springframework.format.annotation.DateTimeFormat;
9 9
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
  11 +import java.util.List;
11 12
12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 13 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
13 14
@@ -30,4 +31,6 @@ public class CouponTemplatePageReqVO extends PageParam { @@ -30,4 +31,6 @@ public class CouponTemplatePageReqVO extends PageParam {
30 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 31 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
31 private LocalDateTime[] createTime; 32 private LocalDateTime[] createTime;
32 33
  34 + @Schema(description = "可以领取的类型", example = "[1,2]")
  35 + private List<Integer> canTakeTypes;
33 } 36 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java
@@ -55,8 +55,7 @@ public interface CouponMapper extends BaseMapperX&lt;CouponDO&gt; { @@ -55,8 +55,7 @@ public interface CouponMapper extends BaseMapperX&lt;CouponDO&gt; {
55 .eq(CouponDO::getStatus, status)); 55 .eq(CouponDO::getStatus, status));
56 } 56 }
57 57
58 - // TODO @疯狂:要 selectList 哈;  
59 - default List<CouponDO> selectByTemplateIdAndUserId(Long templateId, Collection<Long> userIds) { 58 + default List<CouponDO> selectListByTemplateIdAndUserId(Long templateId, Collection<Long> userIds) {
60 return selectList(new LambdaQueryWrapperX<CouponDO>() 59 return selectList(new LambdaQueryWrapperX<CouponDO>()
61 .eq(CouponDO::getTemplateId, templateId) 60 .eq(CouponDO::getTemplateId, templateId)
62 .in(CouponDO::getUserId, userIds) 61 .in(CouponDO::getUserId, userIds)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
1 package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; 1 package cn.iocoder.yudao.module.promotion.dal.mysql.coupon;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
@@ -11,7 +12,6 @@ import org.apache.ibatis.annotations.Mapper; @@ -11,7 +12,6 @@ import org.apache.ibatis.annotations.Mapper;
11 import org.apache.ibatis.annotations.Param; 12 import org.apache.ibatis.annotations.Param;
12 13
13 import java.time.LocalDateTime; 14 import java.time.LocalDateTime;
14 -import java.util.Collection;  
15 import java.util.function.Consumer; 15 import java.util.function.Consumer;
16 16
17 /** 17 /**
@@ -23,27 +23,23 @@ import java.util.function.Consumer; @@ -23,27 +23,23 @@ import java.util.function.Consumer;
23 public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { 23 public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
24 24
25 default PageResult<CouponTemplateDO> selectPage(CouponTemplatePageReqVO reqVO) { 25 default PageResult<CouponTemplateDO> selectPage(CouponTemplatePageReqVO reqVO) {
26 - return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>()  
27 - .likeIfPresent(CouponTemplateDO::getName, reqVO.getName())  
28 - .eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus())  
29 - .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType())  
30 - .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime())  
31 - .orderByDesc(CouponTemplateDO::getId));  
32 - } 26 + Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = null;
  27 + if (CollUtil.isNotEmpty(reqVO.getCanTakeTypes())) {
  28 + // 构建可领取的查询条件, 好啰嗦 ( ╯-_-)╯┴—┴
  29 + canTakeConsumer = w ->
  30 + w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的
  31 + .in(CouponTemplateDO::getTakeType, reqVO.getCanTakeTypes()) // 2. 领取方式一致
  32 + .and(ww -> ww.isNull(CouponTemplateDO::getValidEndTime) // 3. 未过期
  33 + .or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now()))
  34 + .apply(" take_count < total_count "); // 4. 剩余数量大于 0
  35 + }
33 36
34 - default PageResult<CouponTemplateDO> selectCanTakePage(CouponTemplatePageReqVO reqVO, Collection<Integer> takeTypes) {  
35 - // 构建可领取的查询条件, 好啰嗦 ( ╯-_-)╯┴—┴  
36 - Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = w ->  
37 - w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的  
38 - .in(CouponTemplateDO::getTakeType, takeTypes) // 2. 领取方式一致  
39 - .and(ww -> ww.isNull(CouponTemplateDO::getValidEndTime) // 3. 未过期  
40 - .or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now()))  
41 - .apply(" take_count < total_count "); // 4. 剩余数量大于 0  
42 return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>() 37 return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>()
43 .likeIfPresent(CouponTemplateDO::getName, reqVO.getName()) 38 .likeIfPresent(CouponTemplateDO::getName, reqVO.getName())
  39 + .eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus())
44 .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType()) 40 .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType())
45 .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime()) 41 .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime())
46 - .and(canTakeConsumer) 42 + .and(canTakeConsumer != null, canTakeConsumer)
47 .orderByDesc(CouponTemplateDO::getId)); 43 .orderByDesc(CouponTemplateDO::getId));
48 } 44 }
49 45
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
@@ -78,27 +78,23 @@ public interface CouponService { @@ -78,27 +78,23 @@ public interface CouponService {
78 */ 78 */
79 Long getUnusedCouponCount(Long userId); 79 Long getUnusedCouponCount(Long userId);
80 80
81 - // TODO @疯狂:可以返回 void;因为都是 true = =  
82 /** 81 /**
83 * 领取优惠券 82 * 领取优惠券
84 * 83 *
85 * @param templateId 优惠券模板编号 84 * @param templateId 优惠券模板编号
86 * @param userIds 用户编号列表 85 * @param userIds 用户编号列表
87 - * @param takeType 领取方式  
88 - * @return 领取结果 86 + * @param takeType 领取方式
89 */ 87 */
90 - Boolean takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takeType); 88 + void takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takeType);
91 89
92 - // TODO @疯狂:感觉 3 个方法的命名,改成 takeCouponByAdmin;takeCouponByUser;takeCouponByRegister 会更容易理解哈;现在两个都叫 sendCoupon ,感觉不太好懂  
93 /** 90 /**
94 * 【管理员】给用户发送优惠券 91 * 【管理员】给用户发送优惠券
95 * 92 *
96 * @param templateId 优惠券模板编号 93 * @param templateId 优惠券模板编号
97 * @param userIds 用户编号列表 94 * @param userIds 用户编号列表
98 - * @return 发送结果  
99 */ 95 */
100 - default Boolean sendCoupon(Long templateId, Set<Long> userIds) {  
101 - return takeCoupon(templateId, userIds, CouponTakeTypeEnum.BY_ADMIN); 96 + default void takeCouponByAdmin(Long templateId, Set<Long> userIds) {
  97 + takeCoupon(templateId, userIds, CouponTakeTypeEnum.BY_ADMIN);
102 } 98 }
103 99
104 /** 100 /**
@@ -106,10 +102,9 @@ public interface CouponService { @@ -106,10 +102,9 @@ public interface CouponService {
106 * 102 *
107 * @param templateId 优惠券模板编号 103 * @param templateId 优惠券模板编号
108 * @param userId 用户编号 104 * @param userId 用户编号
109 - * @return 发送结果  
110 */ 105 */
111 - default Boolean receiveCoupon(Long templateId, Long userId) {  
112 - return takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_USER); 106 + default void takeCouponByUser(Long templateId, Long userId) {
  107 + takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_USER);
113 } 108 }
114 109
115 /** 110 /**
@@ -117,9 +112,8 @@ public interface CouponService { @@ -117,9 +112,8 @@ public interface CouponService {
117 * 112 *
118 * @param templateId 优惠券模板编号 113 * @param templateId 优惠券模板编号
119 * @param userId 用户编号列表 114 * @param userId 用户编号列表
120 - * @return 发送结果  
121 */ 115 */
122 - default Boolean sendCoupon(Long templateId, Long userId) {  
123 - return takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_REGISTER); 116 + default void takeCouponByRegister(Long templateId, Long userId) {
  117 + takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_REGISTER);
124 } 118 }
125 } 119 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
@@ -30,6 +30,7 @@ import java.util.Set; @@ -30,6 +30,7 @@ import java.util.Set;
30 import java.util.stream.Collectors; 30 import java.util.stream.Collectors;
31 31
32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  33 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
33 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 34 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
34 import static java.util.Arrays.asList; 35 import static java.util.Arrays.asList;
35 36
@@ -134,74 +135,63 @@ public class CouponServiceImpl implements CouponService { @@ -134,74 +135,63 @@ public class CouponServiceImpl implements CouponService {
134 } 135 }
135 136
136 @Override 137 @Override
137 - public Boolean takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takeType) {  
138 - // 1. 校验并过滤用户 138 + public void takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takeType) {
139 CouponTemplateDO template = couponTemplateService.getCouponTemplate(templateId); 139 CouponTemplateDO template = couponTemplateService.getCouponTemplate(templateId);
140 - userIds = validateAndFilterTakeUserId(template, userIds, takeType); 140 + // 1. 过滤掉达到领取限制的用户
  141 + removeTakeLimitUserId(template, userIds);
  142 + // 2. 校验用户
  143 + validateCanTake(template, userIds, takeType);
141 144
142 - // 2. 批量保存优惠劵  
143 - // TODO @疯狂:这里可以使用 CollectionUtils.convertList 更简洁;stream 可以简化很多代码,常用的 stream 操作,使用 util 可以进一步简洁,同时提升可读性  
144 - List<CouponDO> couponList = userIds.stream()  
145 - .map(userId -> CouponConvert.INSTANCE.convert(template, userId))  
146 - .collect(Collectors.toList());  
147 - couponMapper.insertBatch(couponList); 145 + // 3. 批量保存优惠劵
  146 + couponMapper.insertBatch(convertList(userIds, userId -> CouponConvert.INSTANCE.convert(template, userId)));
148 147
149 // 3. 增加优惠劵模板的领取数量 148 // 3. 增加优惠劵模板的领取数量
150 couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size()); 149 couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size());
151 - return true;  
152 } 150 }
153 151
154 /** 152 /**
155 - * 校验优惠券模板, 并过滤不可以领取的用户 153 + * 校验优惠券是否可以领取
156 * 154 *
157 * @param couponTemplate 优惠券模板 155 * @param couponTemplate 优惠券模板
158 * @param userIds 领取人列表 156 * @param userIds 领取人列表
159 * @param takeType 领取方式 157 * @param takeType 领取方式
160 - * @return 可领取此券的用户列表  
161 */ 158 */
162 - // TODO @疯狂:我建议哈,校验模版,和过滤用户分成两个方法;混在一起,有点小重,后续单测可能也比较难写哈;  
163 - private Set<Long> validateAndFilterTakeUserId(CouponTemplateDO couponTemplate, Set<Long> userIds, CouponTakeTypeEnum takeType) {  
164 - // 1.1 校验模板 159 + private void validateCanTake(CouponTemplateDO couponTemplate, Set<Long> userIds, CouponTakeTypeEnum takeType) {
  160 + // 如果所有用户都领取过,则抛出异常
  161 + if (userIds.isEmpty()) {
  162 + throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE);
  163 + }
  164 +
  165 + // 校验模板
165 if (couponTemplate == null) { 166 if (couponTemplate == null) {
166 throw exception(COUPON_TEMPLATE_NOT_EXISTS); 167 throw exception(COUPON_TEMPLATE_NOT_EXISTS);
167 } 168 }
168 - // 1.2 校验剩余数量 169 + // 校验剩余数量
169 if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { 170 if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
170 throw exception(COUPON_TEMPLATE_NOT_ENOUGH); 171 throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
171 } 172 }
172 - // 1.3 校验"固定日期"的有效期类型是否过期 173 + // 校验"固定日期"的有效期类型是否过期
173 if (CouponTemplateValidityTypeEnum.DATE.getType().equals(couponTemplate.getValidityType())) { 174 if (CouponTemplateValidityTypeEnum.DATE.getType().equals(couponTemplate.getValidityType())) {
174 if (LocalDateTimeUtils.beforeNow(couponTemplate.getValidEndTime())) { 175 if (LocalDateTimeUtils.beforeNow(couponTemplate.getValidEndTime())) {
175 throw exception(COUPON_TEMPLATE_EXPIRED); 176 throw exception(COUPON_TEMPLATE_EXPIRED);
176 } 177 }
177 } 178 }
178 - // 1.4 校验领取方式  
179 - // TODO @疯狂:如果要做这样的判断,使用 !ObjectUtils.equalsAny() 会更简洁  
180 - if (!CouponTakeTypeEnum.COMMON.getValue().equals(couponTemplate.getTakeType())) {  
181 - if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getValue())) {  
182 - throw exception(COUPON_TEMPLATE_CANNOT_TAKE);  
183 - }  
184 - }  
185 179
186 - // 2.1 过滤掉,已经领取到上限的用户  
187 - List<CouponDO> alreadyTakeCoupons = couponMapper.selectByTemplateIdAndUserId(couponTemplate.getId(), userIds);  
188 - // 校验新人券  
189 - // TODO @疯狂:我在想,这个判断,是不是和下面的 couponTemplate.getTakeLimitCount() > 0 冗余了;可以先都过滤,然后最终去判断 userIds 是不是空了;  
190 - if (CouponTakeTypeEnum.BY_REGISTER.equals(takeType)) {  
191 - if (!alreadyTakeCoupons.isEmpty()) {  
192 - throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE);  
193 - } 180 + // 校验领取方式
  181 + if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getValue())) {
  182 + throw exception(COUPON_TEMPLATE_CANNOT_TAKE);
194 } 183 }
195 - // 校验领取数量限制 184 + }
  185 +
  186 + private void removeTakeLimitUserId(CouponTemplateDO couponTemplate, Set<Long> userIds) {
  187 + // 查询已领过券的用户
  188 + List<CouponDO> alreadyTakeCoupons = couponMapper.selectListByTemplateIdAndUserId(couponTemplate.getId(), userIds);
  189 +
  190 + // 移除达到领取限制的用户
196 if (couponTemplate.getTakeLimitCount() > 0) { 191 if (couponTemplate.getTakeLimitCount() > 0) {
197 Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(alreadyTakeCoupons, CouponDO::getUserId, Collectors.summingInt(c -> 1)); 192 Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(alreadyTakeCoupons, CouponDO::getUserId, Collectors.summingInt(c -> 1));
198 userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount()); 193 userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
199 - // 2.2 如果所有用户都领取过,则抛出异常  
200 - if (userIds.isEmpty()) {  
201 - throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE);  
202 - }  
203 } 194 }
204 - return userIds;  
205 } 195 }
206 196
207 } 197 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java
@@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou
7 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
8 8
9 import javax.validation.Valid; 9 import javax.validation.Valid;
10 -import java.util.List;  
11 10
12 /** 11 /**
13 * 优惠劵模板 Service 接口 12 * 优惠劵模板 Service 接口
@@ -62,17 +61,6 @@ public interface CouponTemplateService { @@ -62,17 +61,6 @@ public interface CouponTemplateService {
62 */ 61 */
63 PageResult<CouponTemplateDO> getCouponTemplatePage(CouponTemplatePageReqVO pageReqVO); 62 PageResult<CouponTemplateDO> getCouponTemplatePage(CouponTemplatePageReqVO pageReqVO);
64 63
65 -  
66 - /**  
67 - * 获得优惠劵模板分页  
68 - *  
69 - * @param pageReqVO 分页查询  
70 - * @param canTakeTypes 可领取的方式  
71 - * @return 优惠劵模板分页  
72 - */  
73 - PageResult<CouponTemplateDO> getCanTakeCouponTemplatePage(CouponTemplatePageReqVO pageReqVO,  
74 - List<Integer> canTakeTypes);  
75 -  
76 /** 64 /**
77 * 更新优惠劵模板的领取数量 65 * 更新优惠劵模板的领取数量
78 * 66 *
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
@@ -12,7 +12,6 @@ import org.springframework.stereotype.Service; @@ -12,7 +12,6 @@ import org.springframework.stereotype.Service;
12 import org.springframework.validation.annotation.Validated; 12 import org.springframework.validation.annotation.Validated;
13 13
14 import javax.annotation.Resource; 14 import javax.annotation.Resource;
15 -import java.util.List;  
16 15
17 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 16 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
18 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS; 17 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS;
@@ -89,11 +88,6 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { @@ -89,11 +88,6 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
89 } 88 }
90 89
91 @Override 90 @Override
92 - public PageResult<CouponTemplateDO> getCanTakeCouponTemplatePage(CouponTemplatePageReqVO pageReqVO, List<Integer> canTakeTypes) {  
93 - return couponTemplateMapper.selectCanTakePage(pageReqVO, canTakeTypes);  
94 - }  
95 -  
96 - @Override  
97 public void updateCouponTemplateTakeCount(Long id, int incrCount) { 91 public void updateCouponTemplateTakeCount(Long id, int incrCount) {
98 couponTemplateMapper.updateTakeCount(id, incrCount); 92 couponTemplateMapper.updateTakeCount(id, incrCount);
99 } 93 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -217,8 +217,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -217,8 +217,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
217 217
218 // TODO @puhui999:订单超时,自动取消; 218 // TODO @puhui999:订单超时,自动取消;
219 219
220 - // TODO @疯狂:用户手动取消订单;  
221 -  
222 /** 220 /**
223 * 校验收件地址是否存在 221 * 校验收件地址是否存在
224 * 222 *