Commit 2c39405bcea22737be3a49beb23cc67fa7a99c7d

Authored by YunaiV
1 parent 8ae8a4a6

promotion:完善的优惠卷的实体

yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.enums.coupon;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * 优惠劵状态枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@AllArgsConstructor
  15 +@Getter
  16 +public enum CouponStatusEnum implements IntArrayValuable {
  17 +
  18 + UNUSED(1, "未使用"),
  19 + USED(2, "已使用"),
  20 + EXPIRE(3, "已过期"),
  21 + ;
  22 +
  23 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponStatusEnum::getValue).toArray();
  24 +
  25 + /**
  26 + * 值
  27 + */
  28 + private final Integer value;
  29 + /**
  30 + * 名字
  31 + */
  32 + private final String name;
  33 +
  34 + @Override
  35 + public int[] array() {
  36 + return ARRAYS;
  37 + }
  38 +
  39 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java
1 package cn.iocoder.yudao.module.promotion.dal.dataobject.coupon; 1 package cn.iocoder.yudao.module.promotion.dal.dataobject.coupon;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
  5 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
4 import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; 6 import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
  7 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
  8 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 9 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableField; 10 import com.baomidou.mybatisplus.annotation.TableField;
7 import com.baomidou.mybatisplus.annotation.TableName; 11 import com.baomidou.mybatisplus.annotation.TableName;
8 -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;  
9 import lombok.Data; 12 import lombok.Data;
10 import lombok.EqualsAndHashCode; 13 import lombok.EqualsAndHashCode;
11 14
@@ -14,9 +17,11 @@ import java.util.List; @@ -14,9 +17,11 @@ import java.util.List;
14 17
15 /** 18 /**
16 * 优惠劵 DO 19 * 优惠劵 DO
  20 + *
  21 + * @author 芋道源码
17 */ 22 */
18 @TableName(value = "promotion_coupon", autoResultMap = true) 23 @TableName(value = "promotion_coupon", autoResultMap = true)
19 -@KeySequence("promotion_coupo_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 24 +@KeySequence("promotion_coupon_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
20 @Data 25 @Data
21 @EqualsAndHashCode(callSuper = true) 26 @EqualsAndHashCode(callSuper = true)
22 public class CouponDO extends BaseDO { 27 public class CouponDO extends BaseDO {
@@ -35,21 +40,13 @@ public class CouponDO extends BaseDO { @@ -35,21 +40,13 @@ public class CouponDO extends BaseDO {
35 /** 40 /**
36 * 优惠劵名 41 * 优惠劵名
37 * 42 *
38 - * 冗余自 {@link CouponTemplateDO} 的 title  
39 - *  
40 - * TODO 芋艿,暂时不考虑冗余的更新 43 + * 冗余 {@link CouponTemplateDO#getName()}
41 */ 44 */
42 - private String title;  
43 -// /**  
44 -// * 核销码  
45 -// */  
46 -// private String verifyCode; 45 + private String name;
47 /** 46 /**
48 * 优惠码状态 47 * 优惠码状态
49 * 48 *
50 - * 1-未使用  
51 - * 2-已使用  
52 - * 3-已失效 49 + * 枚举 {@link CouponStatusEnum}
53 */ 50 */
54 private Integer status; 51 private Integer status;
55 52
@@ -58,13 +55,14 @@ public class CouponDO extends BaseDO { @@ -58,13 +55,14 @@ public class CouponDO extends BaseDO {
58 // ========== 领取情况 BEGIN ========== 55 // ========== 领取情况 BEGIN ==========
59 /** 56 /**
60 * 用户编号 57 * 用户编号
  58 + *
  59 + * 关联 MemberUserDO 的 id 字段
61 */ 60 */
62 - private Integer userId; 61 + private Long userId;
63 /** 62 /**
64 * 领取类型 63 * 领取类型
65 * 64 *
66 - * 1 - 用户主动领取  
67 - * 2 - 后台自动发放 65 + * 枚举 {@link CouponTakeTypeEnum}
68 */ 66 */
69 private Integer takeType; 67 private Integer takeType;
70 // ========== 领取情况 END ========== 68 // ========== 领取情况 END ==========
@@ -72,8 +70,10 @@ public class CouponDO extends BaseDO { @@ -72,8 +70,10 @@ public class CouponDO extends BaseDO {
72 // ========== 使用规则 BEGIN ========== 70 // ========== 使用规则 BEGIN ==========
73 /** 71 /**
74 * 是否设置满多少金额可用,单位:分 72 * 是否设置满多少金额可用,单位:分
  73 + *
  74 + * 冗余 {@link CouponTemplateDO#getUsePrice()}
75 */ 75 */
76 - private Integer priceAvailable; 76 + private Integer usePrice;
77 /** 77 /**
78 * 生效开始时间 78 * 生效开始时间
79 */ 79 */
@@ -90,50 +90,49 @@ public class CouponDO extends BaseDO { @@ -90,50 +90,49 @@ public class CouponDO extends BaseDO {
90 private Integer productScope; 90 private Integer productScope;
91 /** 91 /**
92 * 商品 SPU 编号的数组 92 * 商品 SPU 编号的数组
  93 + *
  94 + * 冗余 {@link CouponTemplateDO#getProductSpuIds()}
93 */ 95 */
94 - @TableField(typeHandler = JacksonTypeHandler.class)  
95 - private List<Long> spuIds; 96 + @TableField(typeHandler = LongListTypeHandler.class)
  97 + private List<Long> productSpuIds;
96 // ========== 使用规则 END ========== 98 // ========== 使用规则 END ==========
97 99
98 // ========== 使用效果 BEGIN ========== 100 // ========== 使用效果 BEGIN ==========
99 /** 101 /**
100 - * 优惠类型 102 + * 折扣类型
101 * 103 *
102 - * 1-代金卷  
103 - * 2-折扣卷 104 + * 冗余 {@link CouponTemplateDO#getDiscountType()}
104 */ 105 */
105 - private Integer preferentialType; 106 + private Integer discountType;
106 /** 107 /**
107 - * 折扣 108 + * 折扣百分比
  109 + *
  110 + * 冗余 {@link CouponTemplateDO#getDiscountPercent()}
108 */ 111 */
109 - private Integer percentOff; 112 + private Integer discountPercent;
110 /** 113 /**
111 - * 优惠金额,单位:分。 114 + * 优惠金额,单位:分
  115 + *
  116 + * 冗余 {@link CouponTemplateDO#getDiscountPrice()}
112 */ 117 */
113 - private Integer priceOff; 118 + private Integer discountPrice;
114 /** 119 /**
115 - * 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。 120 + * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效
116 * 121 *
117 - * 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。 122 + * 冗余 {@link CouponTemplateDO#getDiscountLimitPrice()}
118 */ 123 */
119 - private Integer discountPriceLimit; 124 + private Integer discountLimitPrice;
120 // ========== 使用效果 END ========== 125 // ========== 使用效果 END ==========
121 126
122 // ========== 使用情况 BEGIN ========== 127 // ========== 使用情况 BEGIN ==========
123 -// /**  
124 -// * 使用订单号  
125 -// */  
126 -// private Integer usedOrderId; // TODO 芋艿,暂时不考虑这个字段  
127 -// /**  
128 -// * 订单中优惠面值,单位:分  
129 -// */  
130 -// private Integer usedPrice; // TODO 芋艿,暂时不考虑这个字段 128 + /**
  129 + * 使用订单号
  130 + */
  131 + private Long useOrderId;
131 /** 132 /**
132 * 使用时间 133 * 使用时间
133 */ 134 */
134 - private Date usedTime;  
135 -  
136 - // TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。 135 + private Date useTime;
137 136
138 // ========== 使用情况 END ========== 137 // ========== 使用情况 END ==========
139 138
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java
@@ -21,6 +21,8 @@ import java.util.List; @@ -21,6 +21,8 @@ import java.util.List;
21 * 优惠劵模板 DO 21 * 优惠劵模板 DO
22 * 22 *
23 * 当用户领取时,会生成 {@link CouponDO} 优惠劵 23 * 当用户领取时,会生成 {@link CouponDO} 优惠劵
  24 + *
  25 + * @author 芋道源码
24 */ 26 */
25 @TableName(value = "promotion_coupon_template", autoResultMap = true) 27 @TableName(value = "promotion_coupon_template", autoResultMap = true)
26 @KeySequence("promotion_coupon_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 28 @KeySequence("promotion_coupon_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java
@@ -10,10 +10,7 @@ import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert; @@ -10,10 +10,7 @@ import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert;
10 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; 10 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
11 import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; 11 import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
12 import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; 12 import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
13 -import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;  
14 -import cn.iocoder.yudao.module.promotion.enums.common.PromotionLevelEnum;  
15 -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;  
16 -import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; 13 +import cn.iocoder.yudao.module.promotion.enums.common.*;
17 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; 14 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
18 import cn.iocoder.yudao.module.promotion.service.discount.DiscountService; 15 import cn.iocoder.yudao.module.promotion.service.discount.DiscountService;
19 import cn.iocoder.yudao.module.promotion.service.reward.RewardService; 16 import cn.iocoder.yudao.module.promotion.service.reward.RewardService;
@@ -283,7 +280,7 @@ public class PriceServiceImpl implements PriceService { @@ -283,7 +280,7 @@ public class PriceServiceImpl implements PriceService {
283 // 计算是否满足优惠劵的使用金额 280 // 计算是否满足优惠劵的使用金额
284 Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); 281 Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
285 assert originPrice != null; 282 assert originPrice != null;
286 - if (originPrice < coupon.getPriceAvailable()) { 283 + if (originPrice < coupon.getUsePrice()) {
287 throw exception(COUPON_NO_MATCH_MIN_PRICE); 284 throw exception(COUPON_NO_MATCH_MIN_PRICE);
288 } 285 }
289 286
@@ -294,7 +291,7 @@ public class PriceServiceImpl implements PriceService { @@ -294,7 +291,7 @@ public class PriceServiceImpl implements PriceService {
294 // TODO 芋艿:limit 不能超过最大价格 291 // TODO 芋艿:limit 不能超过最大价格
295 List<Integer> couponPartPrices = dividePrice(orderItems, couponPrice); 292 List<Integer> couponPartPrices = dividePrice(orderItems, couponPrice);
296 // 记录优惠明细 293 // 记录优惠明细
297 - addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getTitle(), 294 + addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getName(),
298 PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices, 295 PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices,
299 true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice))); 296 true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice)));
300 // 修改 SKU 的分摊 297 // 修改 SKU 的分摊
@@ -309,19 +306,18 @@ public class PriceServiceImpl implements PriceService { @@ -309,19 +306,18 @@ public class PriceServiceImpl implements PriceService {
309 return priceCalculate.getOrder().getItems(); 306 return priceCalculate.getOrder().getItems();
310 } 307 }
311 return CollectionUtils.filterList(priceCalculate.getOrder().getItems(), 308 return CollectionUtils.filterList(priceCalculate.getOrder().getItems(),
312 - orderItem -> coupon.getSpuIds().contains(orderItem.getSpuId())); 309 + orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId()));
313 } 310 }
314 311
315 private Integer getCouponPrice(CouponDO coupon, Integer originPrice) { 312 private Integer getCouponPrice(CouponDO coupon, Integer originPrice) {
316 - // TODO 芋艿 getPreferentialType 的枚举判断  
317 - if (coupon.getPreferentialType().equals(1)) { // 减价  
318 - return coupon.getPriceOff();  
319 - } else if (coupon.getPreferentialType().equals(2)) { // 打折  
320 - Integer couponPrice = originPrice * coupon.getPercentOff() / 100;  
321 - return coupon.getDiscountPriceLimit() == null ? couponPrice  
322 - : Math.min(couponPrice, coupon.getDiscountPriceLimit()); // 优惠上限 313 + if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价
  314 + return coupon.getDiscountPrice();
  315 + } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折
  316 + int couponPrice = originPrice * coupon.getDiscountPercent() / 100;
  317 + return coupon.getDiscountLimitPrice() == null ? couponPrice
  318 + : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限
323 } 319 }
324 - throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon.toString())); 320 + throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon));
325 } 321 }
326 322
327 // ========== 其它相对通用的方法 ========== 323 // ========== 其它相对通用的方法 ==========
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java
@@ -373,7 +373,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { @@ -373,7 +373,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest {
373 ProductSkuRespDTO productSku03 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(30L).setPrice(30).setSpuId(3L)); 373 ProductSkuRespDTO productSku03 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(30L).setPrice(30).setSpuId(3L));
374 when(productSkuApi.getSkuList(eq(asSet(10L, 20L, 30L)))).thenReturn(asList(productSku01, productSku02, productSku03)); 374 when(productSkuApi.getSkuList(eq(asSet(10L, 20L, 30L)))).thenReturn(asList(productSku01, productSku02, productSku03));
375 // mock 方法(优惠劵 Coupon 信息) 375 // mock 方法(优惠劵 Coupon 信息)
376 - CouponDO coupon = randomPojo(CouponDO.class, o -> o.setId(1024L).setTitle("程序员节") 376 + CouponDO coupon = randomPojo(CouponDO.class, o -> o.setId(1024L).setName("程序员节")
377 .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setSpuIds(asList(1L, 2L)) 377 .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setSpuIds(asList(1L, 2L))
378 .setPriceAvailable(350).setPreferentialType(2).setPercentOff(50).setDiscountPriceLimit(70)); 378 .setPriceAvailable(350).setPreferentialType(2).setPercentOff(50).setDiscountPriceLimit(70));
379 when(couponService.validCoupon(eq(1024L), eq(calculateReqDTO.getUserId()))).thenReturn(coupon); 379 when(couponService.validCoupon(eq(1024L), eq(calculateReqDTO.getUserId()))).thenReturn(coupon);