diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java index a8d42da33..bc146dffc 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon; -import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; @@ -25,11 +24,9 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; -import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; @Tag(name = "用户 App - 优惠劵模板") @@ -46,7 +43,6 @@ public class AppCouponTemplateController { @Resource private ProductSpuApi productSpuApi; - // TODO 疯狂:这里应该还有个 list 接口哈;获得优惠劵模版列表,用于首页、商品页的优惠劵 @GetMapping("/list") @Operation(summary = "获得优惠劵模版列表") @Parameters({ @@ -56,46 +52,28 @@ public class AppCouponTemplateController { }) public CommonResult> getCouponTemplateList( @RequestParam(value = "spuId", required = false) Long spuId, - @RequestParam(value = "useType", required = false) Integer useType, + @RequestParam(value = "productScope", required = false) Integer productScope, @RequestParam(value = "count", required = false, defaultValue = "10") Integer count) { - List list = new ArrayList<>(); - Random random = new Random(); - for (int i = 0; i < 10; i++) { - AppCouponTemplateRespVO vo = new AppCouponTemplateRespVO(); - vo.setId(i + 1L); - vo.setName("优惠劵" + (i + 1)); - vo.setTakeLimitCount(random.nextInt(10) + 1); - vo.setUsePrice(random.nextInt(100) * 100); - vo.setValidityType(random.nextInt(2) + 1); - if (vo.getValidityType() == 1) { - vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10))); - vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10)); - } else { - vo.setFixedStartTerm(random.nextInt(10)); - vo.setFixedEndTerm(random.nextInt(10) + vo.getFixedStartTerm() + 1); - } - vo.setDiscountType(random.nextInt(2) + 1); - if (vo.getDiscountType() == 1) { - vo.setDiscountPercent(null); - vo.setDiscountPrice(random.nextInt(50) * 100); - vo.setDiscountLimitPrice(null); - } else { - vo.setDiscountPercent(random.nextInt(90) + 10); - vo.setDiscountPrice(null); - vo.setDiscountLimitPrice(random.nextInt(200) * 100); - } - // TODO @疯狂:是否已领取,要不在 TemplateService 搞个 static 方法,让它基于 countMap 这种去计算,这样好点? - vo.setTakeStatus(random.nextBoolean()); - list.add(vo); - } - return success(list); + // 1.1 处理查询条件:商品范围编号 + Long productScopeValue = getProductScopeValue(productScope, spuId); + // 1.2 处理查询条件:领取方式 = 直接领取 + List canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue()); + + // 2. 查询 + List list = couponTemplateService.getCouponTemplateList(canTakeTypes, productScope, + productScopeValue, count); + + // 3.1 领取数量 + Map canCanTakeMap = couponService.getUserCanCanTakeMap(getLoginUserId(), list); + // 3.2 拼接返回 + return success(CouponTemplateConvert.INSTANCE.convertAppList(list, canCanTakeMap)); } @GetMapping("/page") @Operation(summary = "获得优惠劵模版分页") public CommonResult> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) { // 1.1 处理查询条件:商品范围编号 - Long productScopeValue = getProductScopeValue(pageReqVO); + Long productScopeValue = getProductScopeValue(pageReqVO.getProductScope(), pageReqVO.getSpuId()); // 1.2 处理查询条件:领取方式 = 直接领取 List canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue()); @@ -104,35 +82,30 @@ public class AppCouponTemplateController { CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue)); // 3.1 领取数量 - Map couponTakeCountMap = new HashMap<>(0); - Long userId = getLoginUserId(); - if (userId != null) { - List templateIds = convertList(pageResult.getList(), CouponTemplateDO::getId, - t -> ObjUtil.notEqual(t.getTakeLimitCount(), -1)); // 只查有设置“每人限领个数”的 - couponTakeCountMap = couponService.getTakeCountMapByTemplateIds(templateIds, userId); - } + Map canCanTakeMap = couponService.getUserCanCanTakeMap(getLoginUserId(), pageResult.getList()); // 3.2 拼接返回 - return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, couponTakeCountMap)); + return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, canCanTakeMap)); } /** - * 获得分页查询的商品范围 + * 获得商品的使用范围编号 * - * @param pageReqVO 分页查询 - * @return 商品范围 + * @param productScope 商品范围 + * @param spuId 商品 SPU 编号 + * @return 商品范围编号 */ - private Long getProductScopeValue(AppCouponTemplatePageReqVO pageReqVO) { - // 通用券:清除商品范围 - if (pageReqVO.getProductScope() == null || ObjectUtils.equalsAny(pageReqVO.getProductScope(), PromotionProductScopeEnum.ALL.getScope(), null)) { + private Long getProductScopeValue(Integer productScope, Long spuId) { + // 通用券:没有商品范围 + if (productScope == null || ObjectUtils.equalsAny(productScope, PromotionProductScopeEnum.ALL.getScope(), null)) { return null; } - // 品类券:查询商品的品类 - if (Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope()) && pageReqVO.getSpuId() != null) { - return Optional.ofNullable(productSpuApi.getSpu(pageReqVO.getSpuId())) + // 品类券:查询商品的品类编号 + if (Objects.equals(productScope, PromotionProductScopeEnum.CATEGORY.getScope()) && spuId != null) { + return Optional.ofNullable(productSpuApi.getSpu(spuId)) .map(ProductSpuRespDTO::getCategoryId).orElse(null); } // 商品卷:直接返回 - return pageReqVO.getSpuId(); + return spuId; } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java index be4a0c1f0..83b879acc 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java @@ -55,7 +55,7 @@ public class AppCouponTemplateRespVO { // ========== 用户相关字段 ========== - @Schema(description = "是否已领取", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean takeStatus; + @Schema(description = "是否可以领取", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean canTake; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java index 009a639a8..e09d0f013 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java @@ -37,21 +37,25 @@ public interface CouponTemplateConvert { PageResult convertAppPage(PageResult pageResult); - default PageResult convertAppPage(PageResult pageResult, Map couponTakeCountMap) { + List convertAppList(List list); + + default PageResult convertAppPage(PageResult pageResult, Map userCanTakeMap) { PageResult result = convertAppPage(pageResult); - if (MapUtil.isEmpty(couponTakeCountMap)) { - return result; - } - for (AppCouponTemplateRespVO template : result.getList()) { - // 每人领取数量无限制 - if (template.getTakeLimitCount() == -1) { - template.setTakeStatus(false); - continue; - } - // 检查已领取数量是否超过限领数量 - template.setTakeStatus(MapUtil.getInt(couponTakeCountMap, template.getId(), 0) >= template.getTakeLimitCount()); - } + copyTo(result.getList(), userCanTakeMap); return result; } + default List convertAppList(List list, Map userCanTakeMap) { + List result = convertAppList(list); + copyTo(result, userCanTakeMap); + return result; + } + + default void copyTo(List list, Map userCanTakeMap) { + for (AppCouponTemplateRespVO template : list) { + // 检查已领取数量是否超过限领数量 + template.setCanTake(MapUtil.getBool(userCanTakeMap, template.getId(), false)); + } + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java index 05b0f0607..f5715298d 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java @@ -24,16 +24,8 @@ import java.util.function.Consumer; public interface CouponTemplateMapper extends BaseMapperX { default PageResult selectPage(CouponTemplatePageReqVO reqVO) { - // 构建可领取的查询条件, 好啰嗦 ( ╯-_-)╯┴—┴ - Consumer> canTakeConsumer = null; - if (CollUtil.isNotEmpty(reqVO.getCanTakeTypes())) { - canTakeConsumer = w -> - w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的 - .in(CouponTemplateDO::getTakeType, reqVO.getCanTakeTypes()) // 2. 领取方式一致 - .and(ww -> ww.isNull(CouponTemplateDO::getValidEndTime) // 3. 未过期 - .or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now())) - .apply(" take_count < total_count "); // 4. 剩余数量大于 0 - } + // 构建可领取的查询条件 + Consumer> canTakeConsumer = buildCanTakeQueryConsumer(reqVO.getCanTakeTypes()); // 执行分页查询 return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(CouponTemplateDO::getName, reqVO.getName()) @@ -52,4 +44,30 @@ public interface CouponTemplateMapper extends BaseMapperX { default List selectListByTakeType(Integer takeType) { return selectList(CouponTemplateDO::getTakeType, takeType); } + + default List selectList(List canTakeTypes, Integer productScope, Long productScopeValue, Integer count) { + // 构建可领取的查询条件 + Consumer> canTakeConsumer = buildCanTakeQueryConsumer(canTakeTypes); + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(CouponTemplateDO::getProductScope, productScope) + .and(productScopeValue != null, w -> w.apply("FIND_IN_SET({0}, product_scope_values)", + productScopeValue)) + .and(canTakeConsumer != null, canTakeConsumer) + .last(" LIMIT " + count) + .orderByDesc(CouponTemplateDO::getId)); + } + + static Consumer> buildCanTakeQueryConsumer(List canTakeTypes) { + Consumer> canTakeConsumer = null; + if (CollUtil.isNotEmpty(canTakeTypes)) { + canTakeConsumer = w -> + w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的 + .in(CouponTemplateDO::getTakeType, canTakeTypes) // 2. 领取方式一致 + .and(ww -> ww.isNull(CouponTemplateDO::getValidEndTime) // 3. 未过期 + .or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now())) + .apply(" take_count < total_count "); // 4. 剩余数量大于 0 + } + return canTakeConsumer; + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java index ca3d4bd1a..7b7d1e1d9 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO; @@ -175,4 +176,13 @@ public interface CouponService { */ int expireCoupon(); + /** + * 获取用户是否可以领取优惠券 + * + * @param userId 用户编号 + * @param templates 优惠券列表 + * @return 是否可以领取 + */ + Map getUserCanCanTakeMap(Long userId, List templates); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index 07d1f9e2c..68f5c53f8 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -36,7 +36,7 @@ import java.util.Set; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static java.util.Arrays.asList; @@ -229,6 +229,29 @@ public class CouponServiceImpl implements CouponService { return count; } + @Override + public Map getUserCanCanTakeMap(Long userId, List templates) { + Map userCanTakeMap = convertMap(templates, CouponTemplateDO::getId, templateId -> true); + // 未登录时,都显示可以领取 + if (userId == null) { + return userCanTakeMap; + } + + // 过滤领取数量无限制的 + Set templateIds = convertSet(templates, CouponTemplateDO::getId, template -> template.getTakeLimitCount() != -1); + + // 检查用户领取的数量是否超过限制 + if (CollUtil.isNotEmpty(templateIds)) { + Map couponTakeCountMap = this.getTakeCountMapByTemplateIds(templateIds, userId); + for (CouponTemplateDO template : templates) { + Integer takeCount = couponTakeCountMap.get(template.getId()); + userCanTakeMap.put(template.getId(), takeCount == null || takeCount < template.getTakeLimitCount()); + } + } + + return userCanTakeMap; + } + /** * 过期单个优惠劵 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java index c8f2accb7..cd16e3e54 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java @@ -78,4 +78,17 @@ public interface CouponTemplateService { * @return 优惠券模板列表 */ List getCouponTemplateByTakeType(CouponTakeTypeEnum takeType); + + /** + * 获得优惠券模板列表 + * + * @param canTakeTypes 可领取的类型列表 + * @param productScope 商品使用范围类型 + * @param productScopeValue 商品使用范围编号 + * @param count 查询数量 + * @return 优惠券模板列表 + */ + List getCouponTemplateList(List canTakeTypes, Integer productScope, + Long productScopeValue, Integer count); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java index 7a76e08d2..3f4c8ba76 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java @@ -120,4 +120,10 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { return couponTemplateMapper.selectListByTakeType(takeType.getValue()); } + @Override + public List getCouponTemplateList(List canTakeTypes, Integer productScope, + Long productScopeValue, Integer count) { + return couponTemplateMapper.selectList(canTakeTypes, productScope, productScopeValue, count); + } + }