!604 优惠券优化

Merge pull request !604 from 疯狂的世界/coupon
This commit is contained in:
芋道源码 2023-09-03 09:48:21 +00:00 committed by Gitee
commit e67b62f2f6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 65 additions and 20 deletions

View File

@ -17,7 +17,7 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = InEnumValidator.class
validatedBy = {InEnumValidator.class, InEnumCollectionValidator.class}
)
public @interface InEnum {

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.framework.common.validation;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class InEnumCollectionValidator implements ConstraintValidator<InEnum, Collection<Integer>> {
private List<Integer> values;
@Override
public void initialize(InEnum annotation) {
IntArrayValuable[] values = annotation.value().getEnumConstants();
if (values.length == 0) {
this.values = Collections.emptyList();
} else {
this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
}
}
@Override
public boolean isValid(Collection<Integer> list, ConstraintValidatorContext context) {
// 校验通过
if (CollUtil.containsAll(values, list)) {
return true;
}
// 校验不通过自定义提示语句因为注解上的 value 是枚举类无法获得枚举类的实际值
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()
.replaceAll("\\{value}", CollUtil.join(list, ","))).addConstraintViolation(); // 重新添加错误提示语句
return false;
}
}

View File

@ -71,9 +71,9 @@ public class CouponRespDTO {
*/
private Integer productScope;
/**
* 商品 SPU 编号的数组
* 商品范围编号的数组
*/
private List<Long> productSpuIds;
private List<Long> productScopeValues;
// ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ==========

View File

@ -67,8 +67,8 @@ public class CouponBaseVO {
@InEnum(PromotionProductScopeEnum.class)
private Integer productScope;
@Schema(description = "商品 SPU 编号的数组", example = "1,3")
private List<Long> productSpuIds;
@Schema(description = "商品范围编号的数组", example = "1,3")
private List<Long> productScopeValues;
// ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ==========

View File

@ -54,8 +54,8 @@ public class CouponTemplateBaseVO {
@InEnum(PromotionProductScopeEnum.class)
private Integer productScope;
@Schema(description = "商品 SPU 编号的数组", example = "1,3")
private List<Long> productSpuIds;
@Schema(description = "商品范围编号的数组", example = "1,3")
private List<Long> productScopeValues;
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "生效日期类型不能为空")
@ -95,11 +95,11 @@ public class CouponTemplateBaseVO {
@Schema(description = "折扣上限", example = "100") // 单位仅在 discountType PERCENT 使用
private Integer discountLimitPrice;
@AssertTrue(message = "商品 SPU 编号的数组不能为空")
@AssertTrue(message = "商品范围编号的数组不能为空")
@JsonIgnore
public boolean isProductSpuIdsValid() {
public boolean isProductScopeValuesValid() {
return Objects.equals(productScope, PromotionProductScopeEnum.ALL.getScope()) // 全部范围时可以为空
|| CollUtil.isNotEmpty(productSpuIds);
|| CollUtil.isNotEmpty(productScopeValues);
}
@AssertTrue(message = "生效开始时间不能为空")

View File

@ -28,8 +28,8 @@ public class AppCouponTemplateRespVO {
// @InEnum(PromotionProductScopeEnum.class)
// private Integer productScope;
//
// @Schema(description = "商品 SPU 编号的数组", example = "1,3")
// private List<Long> productSpuIds;
// @Schema(description = "商品范围编号的数组", example = "1,3")
// private List<Long> productScopeValues;
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer validityType;

View File

@ -33,7 +33,7 @@ public interface CouponConvert {
.setTakeType(template.getTakeType())
.setUsePrice(template.getUsePrice())
.setProductScope(template.getProductScope())
.setProductSpuIds(template.getProductSpuIds())
.setProductScopeValues(template.getProductScopeValues())
.setDiscountType(template.getDiscountType())
.setDiscountPercent(template.getDiscountPercent())
.setDiscountPrice(template.getDiscountPrice())

View File

@ -89,12 +89,12 @@ public class CouponDO extends BaseDO {
*/
private Integer productScope;
/**
* 商品 SPU 编号的数组
* 商品范围编号的数组
*
* 冗余 {@link CouponTemplateDO#getProductSpuIds()}
* 冗余 {@link CouponTemplateDO#getProductScopeValues()}
*/
@TableField(typeHandler = LongListTypeHandler.class)
private List<Long> productSpuIds;
private List<Long> productScopeValues;
// ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ==========

View File

@ -85,10 +85,10 @@ public class CouponTemplateDO extends BaseDO {
*/
private Integer productScope;
/**
* 商品 SPU 编号的数组
* 商品范围编号的数组
*/
@TableField(typeHandler = LongListTypeHandler.class)
private List<Long> productSpuIds;
private List<Long> productScopeValues;
/**
* 生效日期类型
*

View File

@ -102,7 +102,10 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator {
Predicate<TradePriceCalculateRespBO.OrderItem> matchPredicate = TradePriceCalculateRespBO.OrderItem::getSelected;
if (PromotionProductScopeEnum.SPU.getScope().equals(coupon.getProductScope())) {
matchPredicate = matchPredicate // 额外加如下条件
.and(orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId()));
.and(orderItem -> coupon.getProductScopeValues().contains(orderItem.getSpuId()));
} else if (PromotionProductScopeEnum.CATEGORY.getScope().equals(coupon.getProductScope())) {
matchPredicate = matchPredicate // 额外加如下条件
.and(orderItem -> coupon.getProductScopeValues().contains(orderItem.getCategoryId()));
}
return filterList(result.getItems(), matchPredicate);
}

View File

@ -65,7 +65,7 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest {
// mock 方法优惠劵 Coupon 信息
CouponRespDTO coupon = randomPojo(CouponRespDTO.class, o -> o.setId(1024L).setName("程序员节")
.setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductSpuIds(asList(1L, 2L))
.setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L))
.setUsePrice(350).setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType())
.setDiscountPercent(50).setDiscountLimitPrice(70));
when(couponApi.validateCoupon(eq(new CouponValidReqDTO().setId(1024L).setUserId(233L)))).thenReturn(coupon);