Commit af0771a17527f69aa8c0878b6da2d85451de3489

Authored by 芋道源码
Committed by Gitee
2 parents 28adfff1 530ec7ab

!597 优惠券

Merge pull request !597 from 疯狂的世界/owen_dev
Showing 14 changed files with 271 additions and 7 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
... ... @@ -27,8 +27,12 @@ public interface ErrorCodeConstants {
27 27 // ========== 优惠劵模板 1013004000 ==========
28 28 ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1013004000, "优惠劵模板不存在");
29 29 ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1013004001, "发放数量不能小于已领取数量({})");
  30 + ErrorCode COUPON_TEMPLATE_TASK_EMPTY = new ErrorCode(1013004002, "当前剩余数量不够领取");
  31 + ErrorCode COUPON_TEMPLATE_USER_TASKED = new ErrorCode(1013004003, "用户已领取过此优惠券");
  32 + ErrorCode COUPON_TEMPLATE_EXPIRED = new ErrorCode(1013004004, "优惠券已过期");
  33 + ErrorCode COUPON_TEMPLATE_CANNOT_TAKE = new ErrorCode(1013004005, "领取方式不正确");
30 34  
31   - // ========== 优惠劵模板 1013005000 ==========
  35 + // ========== 优惠劵 1013005000 ==========
32 36 ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1013005000, "优惠券不存在");
33 37 ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用");
34 38 ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态");
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTakeTypeEnum.java
... ... @@ -14,9 +14,11 @@ import java.util.Arrays;
14 14 @AllArgsConstructor
15 15 @Getter
16 16 public enum CouponTakeTypeEnum implements IntArrayValuable {
17   -
  17 + COMMON(0, "通用"),
18 18 BY_USER(1, "直接领取"), // 用户可在首页、每日领劵直接领取
19 19 BY_ADMIN(2, "指定发放"), // 后台指定会员赠送优惠劵
  20 + BY_REGISTER(3, "新人券"), // 注册时自动领取
  21 + BY_EXCHANGE(4, "兑换"), // 一般渠道券通过兑换领取
20 22 ;
21 23  
22 24 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
... ... @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
8 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
9 9 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO;
10 10 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
  11 +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponSendReqVO;
11 12 import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
12 13 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
13 14 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
... ... @@ -72,4 +73,11 @@ public class CouponController {
72 73 return success(pageResulVO);
73 74 }
74 75  
  76 + @PostMapping("/send")
  77 + @Operation(summary = "发送优惠劵")
  78 + @PreAuthorize("@ss.hasPermission('promotion:coupon:send')")
  79 + public CommonResult<Boolean> sendCoupon(@Valid @RequestBody CouponSendReqVO reqVO) {
  80 + Boolean result = couponService.sendCoupon(reqVO.getTemplateId(), reqVO.getUserIds());
  81 + return success(result);
  82 + }
75 83 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponTemplateController.java
1 1 package cn.iocoder.yudao.module.promotion.controller.admin.coupon;
2 2  
  3 +import cn.hutool.core.collection.ListUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.*;
6 7 import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert;
7 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
  9 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
8 10 import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService;
9 11 import io.swagger.v3.oas.annotations.Operation;
10 12 import io.swagger.v3.oas.annotations.Parameter;
... ... @@ -15,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
15 17  
16 18 import javax.annotation.Resource;
17 19 import javax.validation.Valid;
  20 +import java.util.List;
18 21  
19 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
20 23  
... ... @@ -76,4 +79,13 @@ public class CouponTemplateController {
76 79 return success(CouponTemplateConvert.INSTANCE.convertPage(pageResult));
77 80 }
78 81  
  82 + @GetMapping("/can-take-page")
  83 + @Operation(summary = "获得可用于领取的优惠劵模板分页")
  84 + @PreAuthorize("@ss.hasPermission('promotion:coupon-template:query')")
  85 + public CommonResult<PageResult<CouponTemplateRespVO>> getCanTakeCouponTemplatePage(@Valid CouponTemplatePageReqVO pageVO) {
  86 + List<Integer> canTakeTypes = ListUtil.of(CouponTakeTypeEnum.COMMON.getValue(), CouponTakeTypeEnum.BY_ADMIN.getValue());
  87 + PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCanTakeCouponTemplatePage(pageVO, canTakeTypes);
  88 + return success(CouponTemplateConvert.INSTANCE.convertPage(pageResult));
  89 + }
  90 +
79 91 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/coupon/CouponBaseVO.java
... ... @@ -26,7 +26,7 @@ public class CouponBaseVO {
26 26 // ========== 基本信息 BEGIN ==========
27 27 @Schema(description = "优惠劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
28 28 @NotNull(message = "优惠劵模板编号不能为空")
29   - private Integer templateId;
  29 + private Long templateId;
30 30  
31 31 @Schema(description = "优惠劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "春节送送送")
32 32 @NotNull(message = "优惠劵名不能为空")
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/coupon/CouponSendReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.ToString;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +import javax.validation.constraints.NotNull;
  9 +import java.util.Set;
  10 +
  11 +@Schema(description = "管理后台 - 优惠劵发放 Request VO")
  12 +@Data
  13 +@ToString(callSuper = true)
  14 +public class CouponSendReqVO {
  15 +
  16 + @Schema(description = "优惠劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  17 + @NotNull(message = "优惠劵模板编号不能为空")
  18 + private Long templateId;
  19 +
  20 + @Schema(description = "用户编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
  21 + @NotEmpty(message = "用户编号列表不能为空")
  22 + private Set<Long> userIds;
  23 +
  24 +}
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java
1 1 package cn.iocoder.yudao.module.promotion.convert.coupon;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO;
5 6 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO;
6 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
  9 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
  10 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
7 11 import org.mapstruct.Mapper;
8 12 import org.mapstruct.factory.Mappers;
9 13  
  14 +import java.time.LocalDateTime;
  15 +
10 16 /**
11 17 * 优惠劵 Convert
12 18 *
... ... @@ -21,4 +27,27 @@ public interface CouponConvert {
21 27  
22 28 CouponRespDTO convert(CouponDO bean);
23 29  
  30 + default CouponDO convert(CouponTemplateDO template, Long userId) {
  31 + CouponDO couponDO = new CouponDO()
  32 + .setTemplateId(template.getId())
  33 + .setName(template.getName())
  34 + .setTakeType(template.getTakeType())
  35 + .setUsePrice(template.getUsePrice())
  36 + .setProductScope(template.getProductScope())
  37 + .setProductSpuIds(template.getProductSpuIds())
  38 + .setDiscountType(template.getDiscountType())
  39 + .setDiscountPercent(template.getDiscountPercent())
  40 + .setDiscountPrice(template.getDiscountPrice())
  41 + .setDiscountLimitPrice(template.getDiscountLimitPrice())
  42 + .setStatus(CouponStatusEnum.UNUSED.getStatus())
  43 + .setUserId(userId);
  44 + if (CouponTemplateValidityTypeEnum.DATE.getType().equals(template.getValidityType())) {
  45 + couponDO.setValidStartTime(template.getValidStartTime());
  46 + couponDO.setValidEndTime(template.getValidEndTime());
  47 + } else if (CouponTemplateValidityTypeEnum.TERM.getType().equals(template.getValidityType())) {
  48 + couponDO.setValidStartTime(LocalDateTime.now().plusDays(template.getFixedStartTerm()));
  49 + couponDO.setValidEndTime(LocalDateTime.now().plusDays(template.getFixedEndTerm()));
  50 + }
  51 + return couponDO;
  52 + }
24 53 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java
... ... @@ -36,7 +36,7 @@ public class CouponDO extends BaseDO {
36 36 *
37 37 * 关联 {@link CouponTemplateDO#getId()}
38 38 */
39   - private Integer templateId;
  39 + private Long templateId;
40 40 /**
41 41 * 优惠劵名
42 42 *
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java
... ... @@ -55,4 +55,11 @@ public interface CouponMapper extends BaseMapperX&lt;CouponDO&gt; {
55 55 .eq(CouponDO::getStatus, status));
56 56 }
57 57  
  58 + default List<CouponDO> selectByTemplateIdAndUserId(Long templateId, Collection<Long> userIds) {
  59 + return selectList(new LambdaQueryWrapperX<CouponDO>()
  60 + .eq(CouponDO::getTemplateId, templateId)
  61 + .in(CouponDO::getUserId, userIds)
  62 + );
  63 + }
  64 +
58 65 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
1 1 package cn.iocoder.yudao.module.promotion.dal.mysql.coupon;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 7 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO;
7 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
  9 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8 10 import org.apache.ibatis.annotations.Mapper;
9 11 import org.apache.ibatis.annotations.Param;
10 12  
  13 +import java.time.LocalDateTime;
  14 +import java.util.Collection;
  15 +import java.util.function.Consumer;
  16 +
11 17 /**
12 18 * 优惠劵模板 Mapper
13 19 *
... ... @@ -25,6 +31,28 @@ public interface CouponTemplateMapper extends BaseMapperX&lt;CouponTemplateDO&gt; {
25 31 .orderByDesc(CouponTemplateDO::getId));
26 32 }
27 33  
  34 + default PageResult<CouponTemplateDO> selectCanTakePage(CouponTemplatePageReqVO reqVO, Collection<Integer> takeTypes) {
  35 + // 构建可领取的查询条件, 好啰嗦 ( ╯-_-)╯┴—┴
  36 + Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = w ->
  37 + // 1.状态为可用的
  38 + w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
  39 + // 2.领取方式一致
  40 + .in(CouponTemplateDO::getTakeType, takeTypes)
  41 + // 3.未过期
  42 + .and(ww -> ww.isNull(CouponTemplateDO::getValidEndTime)
  43 + .or()
  44 + .gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now()))
  45 + // 4.剩余数量大于0
  46 + .apply(" take_count < total_count ");
  47 +
  48 + return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>()
  49 + .likeIfPresent(CouponTemplateDO::getName, reqVO.getName())
  50 + .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType())
  51 + .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime())
  52 + .and(canTakeConsumer)
  53 + .orderByDesc(CouponTemplateDO::getId));
  54 + }
  55 +
28 56 void updateTakeCount(@Param("id") Long id, @Param("incrCount") Integer incrCount);
29 57  
30 58 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
1 1 package cn.iocoder.yudao.module.promotion.service.coupon;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
5 6 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
  7 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
6 8  
7 9 import java.util.List;
  10 +import java.util.Set;
8 11  
9 12 /**
10 13 * 优惠劵 Service 接口
... ... @@ -75,4 +78,46 @@ public interface CouponService {
75 78 */
76 79 Long getUnusedCouponCount(Long userId);
77 80  
  81 + /**
  82 + * 领取优惠券
  83 + *
  84 + * @param templateId 优惠券模板编号
  85 + * @param userIds 用户编号列表
  86 + * @param takType 领取方式
  87 + * @return 领取结果
  88 + */
  89 + Boolean takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takType);
  90 +
  91 + /**
  92 + * 【管理员】 给用户发送优惠券
  93 + *
  94 + * @param templateId 优惠券模板编号
  95 + * @param userIds 用户编号列表
  96 + * @return 发送结果
  97 + */
  98 + default Boolean sendCoupon(Long templateId, Set<Long> userIds) {
  99 + return takeCoupon(templateId, userIds, CouponTakeTypeEnum.BY_ADMIN);
  100 + }
  101 +
  102 + /**
  103 + * 【会员】 领取优惠券
  104 + *
  105 + * @param templateId 优惠券模板编号
  106 + * @param userId 用户编号
  107 + * @return 发送结果
  108 + */
  109 + default Boolean receiveCoupon(Long templateId, Long userId) {
  110 + return takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_USER);
  111 + }
  112 +
  113 + /**
  114 + * 【系统】 给用户发送新人券
  115 + *
  116 + * @param templateId 优惠券模板编号
  117 + * @param userId 用户编号列表
  118 + * @return 发送结果
  119 + */
  120 + default Boolean sendCoupon(Long templateId, Long userId) {
  121 + return takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_REGISTER);
  122 + }
78 123 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
1 1 package cn.iocoder.yudao.module.promotion.service.coupon;
2 2  
  3 +import cn.hutool.core.collection.CollStreamUtil;
3 4 import cn.hutool.core.collection.CollUtil;
  5 +import cn.hutool.core.map.MapUtil;
4 6 import cn.hutool.core.util.ObjectUtil;
5 7 import cn.hutool.core.util.StrUtil;
6 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
... ... @@ -9,9 +11,13 @@ import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
9 11 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
10 12 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
11 13 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
  14 +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
12 15 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
  16 +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
13 17 import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper;
14 18 import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
  19 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
  20 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
15 21 import org.springframework.stereotype.Service;
16 22 import org.springframework.transaction.annotation.Transactional;
17 23 import org.springframework.validation.annotation.Validated;
... ... @@ -19,7 +25,9 @@ import org.springframework.validation.annotation.Validated;
19 25 import javax.annotation.Resource;
20 26 import java.time.LocalDateTime;
21 27 import java.util.List;
  28 +import java.util.Map;
22 29 import java.util.Set;
  30 +import java.util.stream.Collectors;
23 31  
24 32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
25 33 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
... ... @@ -125,4 +133,82 @@ public class CouponServiceImpl implements CouponService {
125 133 return couponMapper.selectCountByUserIdAndStatus(userId, CouponStatusEnum.UNUSED.getStatus());
126 134 }
127 135  
  136 + @Override
  137 + public Boolean takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takType) {
  138 + CouponTemplateDO template = couponTemplateService.getCouponTemplate(templateId);
  139 + // 校验并过滤用户
  140 + userIds = validateAndFilterTakeUserId(template, userIds, takType);
  141 +
  142 + List<CouponDO> couponList = userIds.stream()
  143 + .map(userId -> CouponConvert.INSTANCE.convert(template, userId))
  144 + .collect(Collectors.toList());
  145 + // 批量保存
  146 + couponMapper.insertBatch(couponList);
  147 +
  148 + // 增加优惠劵模板的领取数量
  149 + couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size());
  150 +
  151 + return true;
  152 + }
  153 +
  154 + /**
  155 + * 校验优惠券模板, 并过滤不可以领取的用户
  156 + *
  157 + * @param couponTemplate 优惠券模板
  158 + * @param userIds 领取人列表
  159 + * @param takeType 领取方式
  160 + * @return 可领取此券的用户列表
  161 + */
  162 + private Set<Long> validateAndFilterTakeUserId(CouponTemplateDO couponTemplate, Set<Long> userIds, CouponTakeTypeEnum takeType) {
  163 + // 校验模板
  164 + if (couponTemplate == null) {
  165 + throw exception(COUPON_TEMPLATE_NOT_EXISTS);
  166 + }
  167 +
  168 + if (couponTemplate.getTotalCount() > 0) {
  169 + // 校验剩余数量
  170 + if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
  171 + throw exception(COUPON_TEMPLATE_TASK_EMPTY);
  172 + }
  173 + }
  174 +
  175 + // 校验"固定日期"的有效期类型是否过期
  176 + if (CouponTemplateValidityTypeEnum.DATE.getType().equals(couponTemplate.getValidityType())) {
  177 + if (LocalDateTimeUtils.beforeNow(couponTemplate.getValidEndTime())) {
  178 + throw exception(COUPON_TEMPLATE_EXPIRED);
  179 + }
  180 + }
  181 +
  182 + // 校验领取方式
  183 + if (!CouponTakeTypeEnum.COMMON.getValue().equals(couponTemplate.getTakeType())) {
  184 + if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getValue())) {
  185 + throw exception(COUPON_TEMPLATE_CANNOT_TAKE);
  186 + }
  187 + }
  188 +
  189 + // 获取领取过此券的用户
  190 + List<CouponDO> takedList = couponMapper.selectByTemplateIdAndUserId(couponTemplate.getId(), userIds);
  191 +
  192 + // 校验新人券
  193 + if (CouponTakeTypeEnum.BY_REGISTER.equals(takeType)) {
  194 + if (!takedList.isEmpty()) {
  195 + throw exception(COUPON_TEMPLATE_USER_TASKED);
  196 + }
  197 + }
  198 +
  199 + // 校验领取数量限制
  200 + if (couponTemplate.getTakeLimitCount() > 0) {
  201 + // 统计用户的领取数量
  202 + Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(takedList, CouponDO::getUserId, Collectors.summingInt(c -> 1));
  203 + //过滤掉达到领取数量限制的用户
  204 + userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
  205 + // 用户全部领取过此优惠券
  206 + if (userIds.isEmpty()) {
  207 + throw exception(COUPON_TEMPLATE_USER_TASKED);
  208 + }
  209 + }
  210 +
  211 + return userIds;
  212 + }
  213 +
128 214 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java
... ... @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou
7 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
8 8  
9 9 import javax.validation.Valid;
  10 +import java.util.List;
10 11  
11 12 /**
12 13 * 优惠劵模板 Service 接口
... ... @@ -33,7 +34,7 @@ public interface CouponTemplateService {
33 34 /**
34 35 * 更新优惠劵模板的状态
35 36 *
36   - * @param id 编号
  37 + * @param id 编号
37 38 * @param status 状态
38 39 */
39 40 void updateCouponTemplateStatus(Long id, Integer status);
... ... @@ -61,10 +62,21 @@ public interface CouponTemplateService {
61 62 */
62 63 PageResult<CouponTemplateDO> getCouponTemplatePage(CouponTemplatePageReqVO pageReqVO);
63 64  
  65 +
  66 + /**
  67 + * 获得优惠劵模板分页
  68 + *
  69 + * @param pageReqVO 分页查询
  70 + * @param canTakeTypes 可领取的方式
  71 + * @return 优惠劵模板分页
  72 + */
  73 + PageResult<CouponTemplateDO> getCanTakeCouponTemplatePage(CouponTemplatePageReqVO pageReqVO,
  74 + List<Integer> canTakeTypes);
  75 +
64 76 /**
65 77 * 更新优惠劵模板的领取数量
66 78 *
67   - * @param id 优惠劵模板编号
  79 + * @param id 优惠劵模板编号
68 80 * @param incrCount 增加数量
69 81 */
70 82 void updateCouponTemplateTakeCount(Long id, int incrCount);
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
... ... @@ -12,9 +12,11 @@ import org.springframework.stereotype.Service;
12 12 import org.springframework.validation.annotation.Validated;
13 13  
14 14 import javax.annotation.Resource;
  15 +import java.util.List;
15 16  
16 17 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
17   -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
  18 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS;
  19 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL;
18 20  
19 21 /**
20 22 * 优惠劵模板 Service 实现类
... ... @@ -87,6 +89,11 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
87 89 }
88 90  
89 91 @Override
  92 + public PageResult<CouponTemplateDO> getCanTakeCouponTemplatePage(CouponTemplatePageReqVO pageReqVO, List<Integer> canTakeTypes) {
  93 + return couponTemplateMapper.selectCanTakePage(pageReqVO, canTakeTypes);
  94 + }
  95 +
  96 + @Override
90 97 public void updateCouponTemplateTakeCount(Long id, int incrCount) {
91 98 couponTemplateMapper.updateTakeCount(id, incrCount);
92 99 }
... ...