code review:优惠劵发放

This commit is contained in:
YunaiV 2023-09-02 00:31:23 +08:00
parent c06d3c3d26
commit a6ec3fefcf
6 changed files with 34 additions and 21 deletions

View File

@ -15,8 +15,9 @@ import java.util.Arrays;
@AllArgsConstructor @AllArgsConstructor
public enum PromotionProductScopeEnum implements IntArrayValuable { public enum PromotionProductScopeEnum implements IntArrayValuable {
ALL(1, "全部商品参与"), ALL(1, "通用卷"), // 全部商品
SPU(2, "指定商品参与"), SPU(2, "商品卷"), // 指定商品
CATEGORY(3, "品类卷"), // 指定商品
; ;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray(); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray();

View File

@ -15,9 +15,9 @@ import java.util.Arrays;
@Getter @Getter
public enum CouponTakeTypeEnum implements IntArrayValuable { public enum CouponTakeTypeEnum implements IntArrayValuable {
BY_USER(1, "直接领取"), // 用户可在首页每日领劵直接领取 USER(1, "直接领取"), // 用户可在首页每日领劵直接领取
BY_ADMIN(2, "指定发放"), // 后台指定会员赠送优惠劵 ADMIN(2, "指定发放"), // 后台指定会员赠送优惠劵
BY_REGISTER(3, "新人券"), // 注册时自动领取 REGISTER(3, "新人券"), // 注册时自动领取
; ;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTakeTypeEnum::getValue).toArray(); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTakeTypeEnum::getValue).toArray();

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template; package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -31,6 +33,8 @@ public class CouponTemplatePageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "可以领取的类型", example = "[1,2]") @Schema(description = "可以领取的类型", example = "[1,2, 3]")
@InEnum(value = CouponTakeTypeEnum.class, message = "可以领取的类型,必须是 {value}")
private List<Integer> canTakeTypes; private List<Integer> canTakeTypes;
} }

View File

@ -23,9 +23,9 @@ import java.util.function.Consumer;
public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
default PageResult<CouponTemplateDO> selectPage(CouponTemplatePageReqVO reqVO) { default PageResult<CouponTemplateDO> selectPage(CouponTemplatePageReqVO reqVO) {
// 构建可领取的查询条件, 好啰嗦 ( -_-)
Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = null; Consumer<LambdaQueryWrapper<CouponTemplateDO>> canTakeConsumer = null;
if (CollUtil.isNotEmpty(reqVO.getCanTakeTypes())) { if (CollUtil.isNotEmpty(reqVO.getCanTakeTypes())) {
// 构建可领取的查询条件, 好啰嗦 ( -_-)
canTakeConsumer = w -> canTakeConsumer = w ->
w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的 w.eq(CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) // 1. 状态为可用的
.in(CouponTemplateDO::getTakeType, reqVO.getCanTakeTypes()) // 2. 领取方式一致 .in(CouponTemplateDO::getTakeType, reqVO.getCanTakeTypes()) // 2. 领取方式一致
@ -33,7 +33,7 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
.or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now())) .or().gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now()))
.apply(" take_count < total_count "); // 4. 剩余数量大于 0 .apply(" take_count < total_count "); // 4. 剩余数量大于 0
} }
// 执行分页查询
return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>() return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>()
.likeIfPresent(CouponTemplateDO::getName, reqVO.getName()) .likeIfPresent(CouponTemplateDO::getName, reqVO.getName())
.eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus()) .eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus())

View File

@ -94,7 +94,7 @@ public interface CouponService {
* @param userIds 用户编号列表 * @param userIds 用户编号列表
*/ */
default void takeCouponByAdmin(Long templateId, Set<Long> userIds) { default void takeCouponByAdmin(Long templateId, Set<Long> userIds) {
takeCoupon(templateId, userIds, CouponTakeTypeEnum.BY_ADMIN); takeCoupon(templateId, userIds, CouponTakeTypeEnum.ADMIN);
} }
/** /**
@ -104,7 +104,7 @@ public interface CouponService {
* @param userId 用户编号 * @param userId 用户编号
*/ */
default void takeCouponByUser(Long templateId, Long userId) { default void takeCouponByUser(Long templateId, Long userId) {
takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_USER); takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.USER);
} }
/** /**
@ -114,6 +114,6 @@ public interface CouponService {
* @param userId 用户编号列表 * @param userId 用户编号列表
*/ */
default void takeCouponByRegister(Long templateId, Long userId) { default void takeCouponByRegister(Long templateId, Long userId) {
takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.BY_REGISTER); takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER);
} }
} }

View File

@ -138,8 +138,8 @@ public class CouponServiceImpl implements CouponService {
public void takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takeType) { public void takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takeType) {
CouponTemplateDO template = couponTemplateService.getCouponTemplate(templateId); CouponTemplateDO template = couponTemplateService.getCouponTemplate(templateId);
// 1. 过滤掉达到领取限制的用户 // 1. 过滤掉达到领取限制的用户
removeTakeLimitUserId(template, userIds); removeTakeLimitUserId(userIds, template);
// 2. 校验用户 // 2. 校验优惠劵是否可以领取
validateCanTake(template, userIds, takeType); validateCanTake(template, userIds, takeType);
// 3. 批量保存优惠劵 // 3. 批量保存优惠劵
@ -158,7 +158,7 @@ public class CouponServiceImpl implements CouponService {
*/ */
private void validateCanTake(CouponTemplateDO couponTemplate, Set<Long> userIds, CouponTakeTypeEnum takeType) { private void validateCanTake(CouponTemplateDO couponTemplate, Set<Long> userIds, CouponTakeTypeEnum takeType) {
// 如果所有用户都领取过则抛出异常 // 如果所有用户都领取过则抛出异常
if (userIds.isEmpty()) { if (CollUtil.isEmpty(userIds)) {
throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE); throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE);
} }
@ -176,22 +176,30 @@ public class CouponServiceImpl implements CouponService {
throw exception(COUPON_TEMPLATE_EXPIRED); throw exception(COUPON_TEMPLATE_EXPIRED);
} }
} }
// 校验领取方式 // 校验领取方式
if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getValue())) { if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getValue())) {
throw exception(COUPON_TEMPLATE_CANNOT_TAKE); throw exception(COUPON_TEMPLATE_CANNOT_TAKE);
} }
} }
private void removeTakeLimitUserId(CouponTemplateDO couponTemplate, Set<Long> userIds) { /**
* 过滤掉达到领取上线的用户
*
* @param userIds 用户编号数组
* @param couponTemplate 优惠劵模版
*/
private void removeTakeLimitUserId(Set<Long> userIds, CouponTemplateDO couponTemplate) {
if (couponTemplate.getTakeLimitCount() <= 0) {
return;
}
// 查询已领过券的用户 // 查询已领过券的用户
List<CouponDO> alreadyTakeCoupons = couponMapper.selectListByTemplateIdAndUserId(couponTemplate.getId(), userIds); List<CouponDO> alreadyTakeCoupons = couponMapper.selectListByTemplateIdAndUserId(couponTemplate.getId(), userIds);
if (CollUtil.isEmpty(alreadyTakeCoupons)) {
// 移除达到领取限制的用户 return;
if (couponTemplate.getTakeLimitCount() > 0) {
Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(alreadyTakeCoupons, CouponDO::getUserId, Collectors.summingInt(c -> 1));
userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
} }
// 移除达到领取限制的用户
Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(alreadyTakeCoupons, CouponDO::getUserId, Collectors.summingInt(c -> 1));
userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
} }
} }