Commit 0a3a6825d5186ed252545ad1bea99b5157e416be

Authored by owen
1 parent a431bccc

优惠券:完善APP优惠券查询接口

Showing 17 changed files with 169 additions and 106 deletions
sql/mysql/ruoyi-vue-pro.sql
... ... @@ -1188,8 +1188,8 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
1188 1188 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1166, 2, '折扣', '2', 'promotion_discount_type', 0, 'primary', '', '优惠类型 - 折扣', '1', '2022-11-01 12:46:51', '1', '2022-11-01 12:50:08', b'0');
1189 1189 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1167, 1, '固定日期', '1', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 固定日期', '1', '2022-11-02 00:07:34', '1', '2022-11-04 00:07:49', b'0');
1190 1190 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1168, 2, '领取之后', '2', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 领取之后', '1', '2022-11-02 00:07:54', '1', '2022-11-04 00:07:52', b'0');
1191   -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1169, 1, '通用卷', '1', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 全部商品参与', '1', '2022-11-02 00:28:22', '1', '2023-09-01 23:42:49', b'0');
1192   -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1170, 2, '商品卷', '2', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 指定商品参与', '1', '2022-11-02 00:28:34', '1', '2023-09-01 23:42:54', b'0');
  1191 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1169, 1, '通用券', '1', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 全部商品参与', '1', '2022-11-02 00:28:22', '1', '2023-09-01 23:42:49', b'0');
  1192 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1170, 2, '商品券', '2', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 指定商品参与', '1', '2022-11-02 00:28:34', '1', '2023-09-01 23:42:54', b'0');
1193 1193 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1171, 1, '已领取', '1', 'promotion_coupon_status', 0, 'primary', '', '优惠劵的状态 - 已领取', '1', '2022-11-04 00:15:08', '1', '2022-11-04 19:16:04', b'0');
1194 1194 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1172, 2, '已使用', '2', 'promotion_coupon_status', 0, 'success', '', '优惠劵的状态 - 已使用', '1', '2022-11-04 00:15:21', '1', '2022-11-04 19:16:08', b'0');
1195 1195 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1173, 3, '已过期', '3', 'promotion_coupon_status', 0, 'info', '', '优惠劵的状态 - 已过期', '1', '2022-11-04 00:15:43', '1', '2022-11-04 19:16:12', b'0');
... ... @@ -1284,7 +1284,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
1284 1284 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1355, 5, '抽奖奖励', '5', 'member_experience_biz_type', 0, '', '', NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', b'0');
1285 1285 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1356, 1, '快递发货', '1', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:04:55', '1', '2023-08-23 00:04:55', b'0');
1286 1286 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1357, 2, '用户自提', '2', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:05:05', '1', '2023-08-23 00:05:05', b'0');
1287   -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1358, 3, '品类卷', '3', 'promotion_product_scope', 0, 'default', '', '', '1', '2023-09-01 23:43:07', '1', '2023-09-01 23:43:07', b'0');
  1287 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1358, 3, '品类券', '3', 'promotion_product_scope', 0, 'default', '', '', '1', '2023-09-01 23:43:07', '1', '2023-09-01 23:43:07', b'0');
1288 1288 COMMIT;
1289 1289  
1290 1290 -- ----------------------------
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java
... ... @@ -68,7 +68,7 @@ public class RewardActivityMatchRespDTO {
68 68 */
69 69 private List<Long> couponIds;
70 70 /**
71   - * 赠送的优惠卷数量的数组
  71 + * 赠送的优惠券数量的数组
72 72 */
73 73 private List<Integer> couponCounts;
74 74  
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionProductScopeEnum.java
... ... @@ -15,9 +15,9 @@ import java.util.Arrays;
15 15 @AllArgsConstructor
16 16 public enum PromotionProductScopeEnum implements IntArrayValuable {
17 17  
18   - ALL(1, "通用卷"), // 全部商品
19   - SPU(2, "商品卷"), // 指定商品
20   - CATEGORY(3, "品类卷"), // 指定商品
  18 + ALL(1, "通用券"), // 全部商品
  19 + SPU(2, "商品券"), // 指定商品
  20 + CATEGORY(3, "品类券"), // 指定品类
21 21 ;
22 22  
23 23 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray();
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplatePageReqVO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
5 6 import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
6 7 import io.swagger.v3.oas.annotations.media.Schema;
7 8 import lombok.Data;
... ... @@ -33,8 +34,14 @@ public class CouponTemplatePageReqVO extends PageParam {
33 34 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
34 35 private LocalDateTime[] createTime;
35 36  
36   - @Schema(description = "可以领取的类型", example = "[1,2, 3]")
  37 + @Schema(description = "可以领取的类型", example = "[1, 2, 3]")
37 38 @InEnum(value = CouponTakeTypeEnum.class, message = "可以领取的类型,必须是 {value}")
38 39 private List<Integer> canTakeTypes;
39 40  
  41 + @Schema(description = "商品范围", example = "1")
  42 + @InEnum(value = PromotionProductScopeEnum.class, message = "商品范围,必须是 {value}")
  43 + private Integer productScope;
  44 +
  45 + @Schema(description = "商品范围编号", example = "1")
  46 + private Long productScopeValue;
40 47 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/reward/vo/RewardActivityBaseVO.java
... ... @@ -84,7 +84,7 @@ public class RewardActivityBaseVO {
84 84 @Schema(description = "赠送的优惠劵编号的数组", example = "1,2,3")
85 85 private List<Long> couponIds;
86 86  
87   - @Schema(description = "赠送的优惠卷数量的数组", example = "1,2,3")
  87 + @Schema(description = "赠送的优惠券数量的数组", example = "1,2,3")
88 88 private List<Integer> couponCounts;
89 89  
90 90 @AssertTrue(message = "优惠劵和数量必须一一对应")
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java
1 1 package cn.iocoder.yudao.module.promotion.controller.app.coupon;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  7 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
5 8 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO;
6 9 import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplateRespVO;
  10 +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert;
  11 +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
  12 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
  13 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
  14 +import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
7 15 import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService;
8 16 import io.swagger.v3.oas.annotations.Operation;
9   -import io.swagger.v3.oas.annotations.Parameter;
10   -import io.swagger.v3.oas.annotations.Parameters;
11 17 import io.swagger.v3.oas.annotations.tags.Tag;
12 18 import org.springframework.validation.annotation.Validated;
13 19 import org.springframework.web.bind.annotation.GetMapping;
14 20 import org.springframework.web.bind.annotation.RequestMapping;
15   -import org.springframework.web.bind.annotation.RequestParam;
16 21 import org.springframework.web.bind.annotation.RestController;
17 22  
18 23 import javax.annotation.Resource;
19   -import java.time.LocalDateTime;
20   -import java.util.ArrayList;
21   -import java.util.List;
22   -import java.util.Random;
  24 +import java.util.*;
23 25  
24 26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  27 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  28 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
25 29  
26 30 @Tag(name = "用户 App - 优惠劵模板")
27 31 @RestController
... ... @@ -31,84 +35,45 @@ public class AppCouponTemplateController {
31 35  
32 36 @Resource
33 37 private CouponTemplateService couponTemplateService;
  38 + @Resource
  39 + private CouponService couponService;
34 40  
35   - // TODO 芋艿:待实现
36   - @GetMapping("/list")
37   - @Operation(summary = "获得优惠劵模版列表")
38   - @Parameters({
39   - @Parameter(name = "spuId", description = "商品 SPU 编号"), // 目前主要给商品详情使用
40   - @Parameter(name = "useType", description = "使用类型"),
41   - @Parameter(name = "count", description = "数量", required = true)
42   - })
43   - public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList(@RequestParam(value = "spuId", required = false) Long spuId,
44   - @RequestParam(value = "useType", required = false) Integer useType,
45   - @RequestParam(value = "count", required = false, defaultValue = "10") Integer count) {
46   - List<AppCouponTemplateRespVO> list = new ArrayList<>();
47   - Random random = new Random();
48   - for (int i = 0; i < 10; i++) {
49   - AppCouponTemplateRespVO vo = new AppCouponTemplateRespVO();
50   - vo.setId(i + 1L);
51   - vo.setName("优惠劵" + (i + 1));
52   - vo.setTakeLimitCount(random.nextInt(10) + 1);
53   - vo.setUsePrice(random.nextInt(100) * 100);
54   - vo.setValidityType(random.nextInt(2) + 1);
55   - if (vo.getValidityType() == 1) {
56   - vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10)));
57   - vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10));
58   - } else {
59   - vo.setFixedStartTerm(random.nextInt(10));
60   - vo.setFixedEndTerm(random.nextInt(10) + vo.getFixedStartTerm() + 1);
61   - }
62   - vo.setDiscountType(random.nextInt(2) + 1);
63   - if (vo.getDiscountType() == 1) {
64   - vo.setDiscountPercent(null);
65   - vo.setDiscountPrice(random.nextInt(50) * 100);
66   - vo.setDiscountLimitPrice(null);
67   - } else {
68   - vo.setDiscountPercent(random.nextInt(90) + 10);
69   - vo.setDiscountPrice(null);
70   - vo.setDiscountLimitPrice(random.nextInt(200) * 100);
71   - }
72   - vo.setTakeStatus(random.nextBoolean());
73   - list.add(vo);
74   - }
75   - return success(list);
76   - }
  41 + @Resource
  42 + private ProductSpuApi productSpuApi;
77 43  
78   - // TODO 芋艿:待实现;和 getCouponTemplateList 类似
79 44 @GetMapping("/page")
80 45 @Operation(summary = "获得优惠劵模版分页")
81 46 public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) {
82   - List<AppCouponTemplateRespVO> list = new ArrayList<>();
83   - Random random = new Random();
84   - for (int i = 0; i < 10; i++) {
85   - AppCouponTemplateRespVO vo = new AppCouponTemplateRespVO();
86   - vo.setId(i + 1L);
87   - vo.setName("优惠劵" + (i + 1));
88   - vo.setTakeLimitCount(random.nextInt(10) + 1);
89   - vo.setUsePrice(random.nextInt(100) * 100);
90   - vo.setValidityType(random.nextInt(2) + 1);
91   - if (vo.getValidityType() == 1) {
92   - vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10)));
93   - vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10));
94   - } else {
95   - vo.setFixedStartTerm(random.nextInt(10));
96   - vo.setFixedEndTerm(random.nextInt(10) + vo.getFixedStartTerm() + 1);
97   - }
98   - vo.setDiscountType(random.nextInt(2) + 1);
99   - if (vo.getDiscountType() == 1) {
100   - vo.setDiscountPercent(null);
101   - vo.setDiscountPrice(random.nextInt(50) * 100);
102   - vo.setDiscountLimitPrice(null);
103   - } else {
104   - vo.setDiscountPercent(random.nextInt(90) + 10);
105   - vo.setDiscountPrice(null);
106   - vo.setDiscountLimitPrice(random.nextInt(200) * 100);
107   - }
108   - vo.setTakeStatus(random.nextBoolean());
109   - list.add(vo);
  47 + // 1.1 处理查询条件:商品范围编号
  48 + Long productScopeValue = getaProductScopeValue(pageReqVO);
  49 + // 1.2 处理查询条件:领取方式=直接领取
  50 + List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue());
  51 + // 2. 分页查询
  52 + PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(
  53 + CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue));
  54 + // 3.1 领取数量
  55 + Map<Long, Integer> couponTakeCountMap = new HashMap<>(0);
  56 + Long userId = getLoginUserId();
  57 + if (userId != null) {
  58 + List<Long> templateIds = convertList(pageResult.getList(), CouponTemplateDO::getId,
  59 + t -> ObjUtil.notEqual(t.getTakeLimitCount(), -1)); // 只查有设置“每人限领个数”的
  60 + couponTakeCountMap = couponService.getTakeCountMapByTemplateIds(templateIds, userId);
  61 + }
  62 + // 3.2 拼接返回
  63 + return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, couponTakeCountMap));
  64 + }
  65 +
  66 + private Long getaProductScopeValue(AppCouponTemplatePageReqVO pageReqVO) {
  67 + Long productScopeValue = pageReqVO.getSpuId();
  68 + if (pageReqVO.getProductScope() == null || Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.ALL.getScope())) {
  69 + // 通用券:清除商品范围
  70 + productScopeValue = null;
  71 + } else if (Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope()) && pageReqVO.getSpuId() != null) {
  72 + // 品类券:查询商品的品类
  73 + productScopeValue = Optional.ofNullable(productSpuApi.getSpu(pageReqVO.getSpuId()))
  74 + .map(ProductSpuRespDTO::getCategoryId).orElse(null);
110 75 }
111   - return success(new PageResult<>(list, 20L));
  76 + return productScopeValue;
112 77 }
113 78  
114 79 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java
... ... @@ -15,15 +15,15 @@ public class AppCouponMatchReqVO {
15 15 @NotNull(message = "商品金额不能为空")
16 16 private Integer price;
17 17  
18   - @Schema(description = "商品 SPU 编号的数组", required = true, example = "[1, 2]")
  18 + @Schema(description = "商品 SPU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
19 19 @NotEmpty(message = "商品 SPU 编号不能为空")
20 20 private List<Long> spuIds;
21 21  
22   - @Schema(description = "商品 SKU 编号的数组", required = true, example = "[1, 2]")
  22 + @Schema(description = "商品 SKU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
23 23 @NotEmpty(message = "商品 SKU 编号不能为空")
24 24 private List<Long> skuIds;
25 25  
26   - @Schema(description = "分类编号的数组", required = true, example = "[10, 20]")
  26 + @Schema(description = "分类编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[10, 20]")
27 27 @NotEmpty(message = "分类编号不能为空")
28 28 private List<Long> categoryIds;
29 29  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplatePageReqVO.java
1 1 package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
4 6 import io.swagger.v3.oas.annotations.media.Schema;
5 7 import lombok.Data;
6 8 import lombok.EqualsAndHashCode;
... ... @@ -12,8 +14,10 @@ import lombok.ToString;
12 14 @ToString(callSuper = true)
13 15 public class AppCouponTemplatePageReqVO extends PageParam {
14 16  
15   - @Schema(description = "使用类型", example = "1")
16   - // TODO 芋艿:这里要限制下枚举的使用
17   - private Integer useType;
  17 + @Schema(description = "商品范围", example = "1")
  18 + @InEnum(value = PromotionProductScopeEnum.class, message = "商品范围,必须是 {value}")
  19 + private Integer productScope;
18 20  
  21 + @Schema(description = "商品标号", example = "1")
  22 + private Long spuId;
19 23 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java
... ... @@ -26,4 +26,25 @@ public interface CouponTemplateConvert {
26 26  
27 27 PageResult<CouponTemplateRespVO> convertPage(PageResult<CouponTemplateDO> page);
28 28  
  29 + CouponTemplatePageReqVO convert(AppCouponTemplatePageReqVO pageReqVO, List<Integer> canTakeTypes, Integer productScope, Long productScopeValue);
  30 +
  31 + PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult);
  32 +
  33 + default PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult, Map<Long, Integer> couponTakeCountMap) {
  34 + PageResult<AppCouponTemplateRespVO> result = convertAppPage(pageResult);
  35 + if (MapUtil.isEmpty(couponTakeCountMap)) {
  36 + return result;
  37 + }
  38 +
  39 + for (AppCouponTemplateRespVO vo : result.getList()) {
  40 + // 每人领取数量无限制
  41 + if (vo.getTakeLimitCount() == -1) {
  42 + vo.setTakeStatus(false);
  43 + continue;
  44 + }
  45 + // 检查已领取数量是否超过限领数量
  46 + vo.setTakeStatus(MapUtil.getInt(couponTakeCountMap, vo.getId(), 0) >= vo.getTakeLimitCount());
  47 + }
  48 + return result;
  49 + }
29 50 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java
... ... @@ -110,7 +110,7 @@ public class RewardActivityDO extends BaseDO {
110 110 */
111 111 private List<Long> couponIds;
112 112 /**
113   - * 赠送的优惠卷数量的数组
  113 + * 赠送的优惠券数量的数组
114 114 */
115 115 private List<Integer> couponCounts;
116 116  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java
1 1 package cn.iocoder.yudao.module.promotion.dal.mysql.coupon;
2 2  
  3 +import cn.hutool.core.bean.BeanUtil;
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.coupon.CouponPageReqVO;
7 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
  9 +import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO;
8 10 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  11 +import com.github.yulichang.toolkit.MPJWrappers;
9 12 import org.apache.ibatis.annotations.Mapper;
10 13  
11 14 import java.util.Collection;
... ... @@ -62,4 +65,12 @@ public interface CouponMapper extends BaseMapperX&lt;CouponDO&gt; {
62 65 );
63 66 }
64 67  
  68 + default List<CouponTakeCountBO> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) {
  69 + return BeanUtil.copyToList(selectMaps(MPJWrappers.lambdaJoin(CouponDO.class)
  70 + .select(CouponDO::getTemplateId)
  71 + .selectCount(CouponDO::getId, CouponTakeCountBO::getCount)
  72 + .eq(CouponDO::getUserId, userId)
  73 + .in(CouponDO::getTemplateId, templateIds)
  74 + .groupBy(CouponDO::getTemplateId)), CouponTakeCountBO.class);
  75 + }
65 76 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
... ... @@ -39,6 +39,9 @@ public interface CouponTemplateMapper extends BaseMapperX&lt;CouponTemplateDO&gt; {
39 39 .eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus())
40 40 .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType())
41 41 .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime())
  42 + .eqIfPresent(CouponTemplateDO::getProductScope, reqVO.getProductScope())
  43 + .and(reqVO.getProductScopeValue() != null, w -> w.apply("FIND_IN_SET({0}, product_scope_values)",
  44 + reqVO.getProductScopeValue()))
42 45 .and(canTakeConsumer != null, canTakeConsumer)
43 46 .orderByDesc(CouponTemplateDO::getId));
44 47 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
... ... @@ -5,10 +5,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
6 6 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
7 7 import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
  8 +import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO;
8 9  
  10 +import java.util.Collection;
9 11 import java.util.List;
  12 +import java.util.Map;
10 13 import java.util.Set;
11 14  
  15 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  16 +
12 17 /**
13 18 * 优惠劵 Service 接口
14 19 *
... ... @@ -18,11 +23,11 @@ public interface CouponService {
18 23  
19 24 /**
20 25 * 校验优惠劵,包括状态、有限期
21   - *
  26 + * <p>
22 27 * 1. 如果校验通过,则返回优惠劵信息
23 28 * 2. 如果校验不通过,则直接抛出业务异常
24 29 *
25   - * @param id 优惠劵编号
  30 + * @param id 优惠劵编号
26 31 * @param userId 用户编号
27 32 * @return 优惠劵信息
28 33 */
... ... @@ -31,9 +36,8 @@ public interface CouponService {
31 36 /**
32 37 * 校验优惠劵,包括状态、有限期
33 38 *
34   - * @see #validCoupon(Long, Long) 逻辑相同,只是入参不同
35   - *
36 39 * @param coupon 优惠劵
  40 + * @see #validCoupon(Long, Long) 逻辑相同,只是入参不同
37 41 */
38 42 void validCoupon(CouponDO coupon);
39 43  
... ... @@ -124,4 +128,23 @@ public interface CouponService {
124 128 takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER);
125 129 }
126 130  
  131 + /**
  132 + * 统计会员领取优惠券的数量
  133 + *
  134 + * @param templateIds 优惠券模板编号列表
  135 + * @param userId 用户编号
  136 + * @return 领取优惠券的数量
  137 + */
  138 + default Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId) {
  139 + return convertMap(getTakeCountListByTemplateIds(templateIds, userId), CouponTakeCountBO::getTemplateId, CouponTakeCountBO::getCount);
  140 + }
  141 +
  142 + /**
  143 + * 统计会员领取优惠券的数量
  144 + *
  145 + * @param templateIds 优惠券模板编号列表
  146 + * @param userId 用户编号
  147 + * @return 领取优惠券的数量
  148 + */
  149 + List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId);
127 150 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.coupon;
2 2  
3 3 import cn.hutool.core.collection.CollStreamUtil;
4 4 import cn.hutool.core.collection.CollUtil;
  5 +import cn.hutool.core.collection.ListUtil;
5 6 import cn.hutool.core.map.MapUtil;
6 7 import cn.hutool.core.util.ObjectUtil;
7 8 import cn.hutool.core.util.StrUtil;
... ... @@ -18,12 +19,14 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper;
18 19 import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
19 20 import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
20 21 import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
  22 +import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO;
21 23 import org.springframework.stereotype.Service;
22 24 import org.springframework.transaction.annotation.Transactional;
23 25 import org.springframework.validation.annotation.Validated;
24 26  
25 27 import javax.annotation.Resource;
26 28 import java.time.LocalDateTime;
  29 +import java.util.Collection;
27 30 import java.util.List;
28 31 import java.util.Map;
29 32 import java.util.Set;
... ... @@ -175,6 +178,14 @@ public class CouponServiceImpl implements CouponService {
175 178 couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size());
176 179 }
177 180  
  181 + @Override
  182 + public List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId) {
  183 + if (CollUtil.isEmpty(templateIds)) {
  184 + return ListUtil.empty();
  185 + }
  186 + return couponMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds);
  187 + }
  188 +
178 189 /**
179 190 * 校验优惠券是否可以领取
180 191 *
... ... @@ -211,7 +222,7 @@ public class CouponServiceImpl implements CouponService {
211 222 /**
212 223 * 过滤掉达到领取上线的用户
213 224 *
214   - * @param userIds 用户编号数组
  225 + * @param userIds 用户编号数组
215 226 * @param couponTemplate 优惠劵模版
216 227 */
217 228 private void removeTakeLimitUser(Set<Long> userIds, CouponTemplateDO couponTemplate) {
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/bo/CouponTakeCountBO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.coupon.bo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * 优惠券领取数量 BO
  7 + *
  8 + * @author owen
  9 + */
  10 +@Data
  11 +public class CouponTakeCountBO {
  12 + /**
  13 + * 优惠劵模板编号
  14 + */
  15 + private Long templateId;
  16 + /**
  17 + * 领取数量
  18 + */
  19 + private Integer count;
  20 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageRecordMapper.java
... ... @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
10 10 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
11 11 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
12 12 import com.baomidou.mybatisplus.core.metadata.IPage;
13   -import com.github.yulichang.toolkit.LambdaUtils;
14 13 import com.github.yulichang.toolkit.MPJWrappers;
15 14 import org.apache.ibatis.annotations.Mapper;
16 15 import org.apache.ibatis.annotations.Param;
... ... @@ -62,7 +61,7 @@ public interface BrokerageRecordMapper extends BaseMapperX&lt;BrokerageRecordDO&gt; {
62 61 Integer status) {
63 62 List<Map<String, Object>> list = selectMaps(MPJWrappers.lambdaJoin(BrokerageRecordDO.class)
64 63 .select(BrokerageRecordDO::getUserId)
65   - .selectCount(BrokerageRecordDO::getId, LambdaUtils.getName(UserBrokerageSummaryBO::getCount))
  64 + .selectCount(BrokerageRecordDO::getId, UserBrokerageSummaryBO::getCount)
66 65 .selectSum(BrokerageRecordDO::getPrice)
67 66 .in(BrokerageRecordDO::getUserId, userIds)
68 67 .eq(BrokerageRecordDO::getBizId, bizType)
... ... @@ -71,7 +70,7 @@ public interface BrokerageRecordMapper extends BaseMapperX&lt;BrokerageRecordDO&gt; {
71 70 return BeanUtil.copyToList(list, UserBrokerageSummaryBO.class);
72 71 // return selectJoinList(UserBrokerageSummaryBO.class, MPJWrappers.lambdaJoin(BrokerageRecordDO.class)
73 72 // .select(BrokerageRecordDO::getUserId)
74   -// .selectCount(BrokerageRecordDO::getId, LambdaUtils.getName(UserBrokerageSummaryBO::getCount))
  73 +// .selectCount(BrokerageRecordDO::getId, UserBrokerageSummaryBO::getCount)
75 74 // .selectSum(BrokerageRecordDO::getPrice)
76 75 // .in(BrokerageRecordDO::getUserId, userIds)
77 76 // .eq(BrokerageRecordDO::getBizId, bizType)
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageWithdrawMapper.java
... ... @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.Brok
8 8 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
9 9 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
10 10 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
11   -import com.github.yulichang.toolkit.LambdaUtils;
12 11 import com.github.yulichang.wrapper.MPJLambdaWrapper;
13 12 import org.apache.ibatis.annotations.Mapper;
14 13  
... ... @@ -45,7 +44,7 @@ public interface BrokerageWithdrawMapper extends BaseMapperX&lt;BrokerageWithdrawDO
45 44 default List<UserWithdrawSummaryBO> selectCountAndSumPriceByUserIdAndStatus(Collection<Long> userIds, Integer status) {
46 45 List<Map<String, Object>> list = selectMaps(new MPJLambdaWrapper<BrokerageWithdrawDO>()
47 46 .select(BrokerageWithdrawDO::getUserId)
48   - .selectCount(BrokerageWithdrawDO::getId, LambdaUtils.getName(UserWithdrawSummaryBO::getCount))
  47 + .selectCount(BrokerageWithdrawDO::getId, UserWithdrawSummaryBO::getCount)
49 48 .selectSum(BrokerageWithdrawDO::getPrice)
50 49 .in(BrokerageWithdrawDO::getUserId, userIds)
51 50 .eq(BrokerageWithdrawDO::getStatus, status)
... ... @@ -54,7 +53,7 @@ public interface BrokerageWithdrawMapper extends BaseMapperX&lt;BrokerageWithdrawDO
54 53 // selectJoinList有BUG,会与租户插件冲突:解析SQL时,发生异常 https://gitee.com/best_handsome/mybatis-plus-join/issues/I84GYW
55 54 // return selectJoinList(UserWithdrawSummaryBO.class, new MPJLambdaWrapper<BrokerageWithdrawDO>()
56 55 // .select(BrokerageWithdrawDO::getUserId)
57   -// .selectCount(BrokerageWithdrawDO::getId, LambdaUtils.getName(UserWithdrawSummaryBO::getCount))
  56 +// .selectCount(BrokerageWithdrawDO::getId, UserWithdrawSummaryBO::getCount)
58 57 // .selectSum(BrokerageWithdrawDO::getPrice)
59 58 // .in(BrokerageWithdrawDO::getUserId, userIds)
60 59 // .eq(BrokerageWithdrawDO::getStatus, status)
... ...