Commit 2c39405bcea22737be3a49beb23cc67fa7a99c7d
1 parent
8ae8a4a6
promotion:完善的优惠卷的实体
Showing
5 changed files
with
93 additions
and
57 deletions
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 | 1 | package cn.iocoder.yudao.module.promotion.dal.dataobject.coupon; |
| 2 | 2 | |
| 3 | 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 | 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 | 9 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 6 | 10 | import com.baomidou.mybatisplus.annotation.TableField; |
| 7 | 11 | import com.baomidou.mybatisplus.annotation.TableName; |
| 8 | -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | |
| 9 | 12 | import lombok.Data; |
| 10 | 13 | import lombok.EqualsAndHashCode; |
| 11 | 14 | |
| ... | ... | @@ -14,9 +17,11 @@ import java.util.List; |
| 14 | 17 | |
| 15 | 18 | /** |
| 16 | 19 | * 优惠劵 DO |
| 20 | + * | |
| 21 | + * @author 芋道源码 | |
| 17 | 22 | */ |
| 18 | 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 | 25 | @Data |
| 21 | 26 | @EqualsAndHashCode(callSuper = true) |
| 22 | 27 | 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 | 51 | private Integer status; |
| 55 | 52 | |
| ... | ... | @@ -58,13 +55,14 @@ public class CouponDO extends BaseDO { |
| 58 | 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 | 67 | private Integer takeType; |
| 70 | 68 | // ========== 领取情况 END ========== |
| ... | ... | @@ -72,8 +70,10 @@ public class CouponDO extends BaseDO { |
| 72 | 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 | 90 | private Integer productScope; |
| 91 | 91 | /** |
| 92 | 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 | 98 | // ========== 使用规则 END ========== |
| 97 | 99 | |
| 98 | 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 | 125 | // ========== 使用效果 END ========== |
| 121 | 126 | |
| 122 | 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 | 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 | 21 | * 优惠劵模板 DO |
| 22 | 22 | * |
| 23 | 23 | * 当用户领取时,会生成 {@link CouponDO} 优惠劵 |
| 24 | + * | |
| 25 | + * @author 芋道源码 | |
| 24 | 26 | */ |
| 25 | 27 | @TableName(value = "promotion_coupon_template", autoResultMap = true) |
| 26 | 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 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 11 | 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 12 | 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 | 14 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; |
| 18 | 15 | import cn.iocoder.yudao.module.promotion.service.discount.DiscountService; |
| 19 | 16 | import cn.iocoder.yudao.module.promotion.service.reward.RewardService; |
| ... | ... | @@ -283,7 +280,7 @@ public class PriceServiceImpl implements PriceService { |
| 283 | 280 | // 计算是否满足优惠劵的使用金额 |
| 284 | 281 | Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); |
| 285 | 282 | assert originPrice != null; |
| 286 | - if (originPrice < coupon.getPriceAvailable()) { | |
| 283 | + if (originPrice < coupon.getUsePrice()) { | |
| 287 | 284 | throw exception(COUPON_NO_MATCH_MIN_PRICE); |
| 288 | 285 | } |
| 289 | 286 | |
| ... | ... | @@ -294,7 +291,7 @@ public class PriceServiceImpl implements PriceService { |
| 294 | 291 | // TODO 芋艿:limit 不能超过最大价格 |
| 295 | 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 | 295 | PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices, |
| 299 | 296 | true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice))); |
| 300 | 297 | // 修改 SKU 的分摊 |
| ... | ... | @@ -309,19 +306,18 @@ public class PriceServiceImpl implements PriceService { |
| 309 | 306 | return priceCalculate.getOrder().getItems(); |
| 310 | 307 | } |
| 311 | 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 | 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 | 373 | ProductSkuRespDTO productSku03 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(30L).setPrice(30).setSpuId(3L)); |
| 374 | 374 | when(productSkuApi.getSkuList(eq(asSet(10L, 20L, 30L)))).thenReturn(asList(productSku01, productSku02, productSku03)); |
| 375 | 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 | 377 | .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setSpuIds(asList(1L, 2L)) |
| 378 | 378 | .setPriceAvailable(350).setPreferentialType(2).setPercentOff(50).setDiscountPriceLimit(70)); |
| 379 | 379 | when(couponService.validCoupon(eq(1024L), eq(calculateReqDTO.getUserId()))).thenReturn(coupon); | ... | ... |