Explorar o código

promotion:完善的优惠卷的实体

YunaiV %!s(int64=2) %!d(string=hai) anos
pai
achega
2c39405bce

+ 39 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponStatusEnum.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.promotion.enums.coupon;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 优惠劵状态枚举
+ *
+ * @author 芋道源码
+ */
+@AllArgsConstructor
+@Getter
+public enum CouponStatusEnum implements IntArrayValuable {
+
+    UNUSED(1, "未使用"),
+    USED(2, "已使用"),
+    EXPIRE(3, "已过期"),
+    ;
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponStatusEnum::getValue).toArray();
+
+    /**
+     * 值
+     */
+    private final Integer value;
+    /**
+     * 名字
+     */
+    private final String name;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+}

+ 40 - 41
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java

@@ -1,11 +1,14 @@
 package cn.iocoder.yudao.module.promotion.dal.dataobject.coupon;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
+import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
 import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
+import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
+import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
@@ -14,9 +17,11 @@ import java.util.List;
 
 /**
  * 优惠劵 DO
+ *
+ * @author 芋道源码
  */
 @TableName(value = "promotion_coupon", autoResultMap = true)
-@KeySequence("promotion_coupo_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@KeySequence("promotion_coupon_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class CouponDO extends BaseDO {
@@ -35,21 +40,13 @@ public class CouponDO extends BaseDO {
     /**
      * 优惠劵名
      *
-     * 冗余自 {@link CouponTemplateDO} 的 title
-     *
-     * TODO 芋艿,暂时不考虑冗余的更新
+     * 冗余 {@link CouponTemplateDO#getName()}
      */
-    private String title;
-//    /**
-//     * 核销码
-//     */
-//    private String verifyCode;
+    private String name;
     /**
      * 优惠码状态
      *
-     * 1-未使用
-     * 2-已使用
-     * 3-已失效
+     * 枚举 {@link CouponStatusEnum}
      */
     private Integer status;
 
@@ -58,13 +55,14 @@ public class CouponDO extends BaseDO {
     // ========== 领取情况 BEGIN ==========
     /**
      * 用户编号
+     *
+     * 关联 MemberUserDO 的 id 字段
      */
-    private Integer userId;
+    private Long userId;
     /**
      * 领取类型
      *
-     * 1 - 用户主动领取
-     * 2 - 后台自动发放
+     * 枚举 {@link CouponTakeTypeEnum}
      */
     private Integer takeType;
     // ========== 领取情况 END ==========
@@ -72,8 +70,10 @@ public class CouponDO extends BaseDO {
     // ========== 使用规则 BEGIN ==========
     /**
      * 是否设置满多少金额可用,单位:分
+     *
+     * 冗余 {@link CouponTemplateDO#getUsePrice()}
      */
-    private Integer priceAvailable;
+    private Integer usePrice;
     /**
      * 生效开始时间
      */
@@ -90,50 +90,49 @@ public class CouponDO extends BaseDO {
     private Integer productScope;
     /**
      * 商品 SPU 编号的数组
+     *
+     * 冗余 {@link CouponTemplateDO#getProductSpuIds()}
      */
-    @TableField(typeHandler = JacksonTypeHandler.class)
-    private List<Long> spuIds;
+    @TableField(typeHandler = LongListTypeHandler.class)
+    private List<Long> productSpuIds;
     // ========== 使用规则 END ==========
 
     // ========== 使用效果 BEGIN ==========
     /**
-     * 优惠类型
+     * 折扣类型
      *
-     * 1-代金卷
-     * 2-折扣卷
+     * 冗余 {@link CouponTemplateDO#getDiscountType()}
      */
-    private Integer preferentialType;
+    private Integer discountType;
     /**
-     * 折扣
+     * 折扣百分比
+     *
+     * 冗余 {@link CouponTemplateDO#getDiscountPercent()}
      */
-    private Integer percentOff;
+    private Integer discountPercent;
     /**
-     * 优惠金额,单位:分。
+     * 优惠金额,单位:分
+     *
+     * 冗余 {@link CouponTemplateDO#getDiscountPrice()}
      */
-    private Integer priceOff;
+    private Integer discountPrice;
     /**
-     * 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。
+     * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效
      *
-     * 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80  元。
+     * 冗余 {@link CouponTemplateDO#getDiscountLimitPrice()}
      */
-    private Integer discountPriceLimit;
+    private Integer discountLimitPrice;
     // ========== 使用效果 END ==========
 
     // ========== 使用情况 BEGIN ==========
-//    /**
-//     * 使用订单号
-//     */
-//    private Integer usedOrderId; // TODO 芋艿,暂时不考虑这个字段
-//    /**
-//     * 订单中优惠面值,单位:分
-//     */
-//    private Integer usedPrice; // TODO 芋艿,暂时不考虑这个字段
+    /**
+     * 使用订单号
+     */
+    private Long useOrderId;
     /**
      * 使用时间
      */
-    private Date usedTime;
-
-    // TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
+    private Date useTime;
 
     // ========== 使用情况 END ==========
 

+ 2 - 0
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;
  * 优惠劵模板 DO
  *
  * 当用户领取时,会生成 {@link CouponDO} 优惠劵
+ *
+ * @author 芋道源码
  */
 @TableName(value = "promotion_coupon_template", autoResultMap = true)
 @KeySequence("promotion_coupon_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。

+ 11 - 15
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;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
-import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
-import cn.iocoder.yudao.module.promotion.enums.common.PromotionLevelEnum;
-import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
-import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
+import cn.iocoder.yudao.module.promotion.enums.common.*;
 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
 import cn.iocoder.yudao.module.promotion.service.discount.DiscountService;
 import cn.iocoder.yudao.module.promotion.service.reward.RewardService;
@@ -283,7 +280,7 @@ public class PriceServiceImpl implements PriceService {
         // 计算是否满足优惠劵的使用金额
         Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
         assert originPrice != null;
-        if (originPrice < coupon.getPriceAvailable()) {
+        if (originPrice < coupon.getUsePrice()) {
             throw exception(COUPON_NO_MATCH_MIN_PRICE);
         }
 
@@ -294,7 +291,7 @@ public class PriceServiceImpl implements PriceService {
         // TODO 芋艿:limit 不能超过最大价格
         List<Integer> couponPartPrices = dividePrice(orderItems, couponPrice);
         // 记录优惠明细
-        addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getTitle(),
+        addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getName(),
                 PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices,
                 true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice)));
         // 修改 SKU 的分摊
@@ -309,19 +306,18 @@ public class PriceServiceImpl implements PriceService {
             return priceCalculate.getOrder().getItems();
         }
         return CollectionUtils.filterList(priceCalculate.getOrder().getItems(),
-                orderItem -> coupon.getSpuIds().contains(orderItem.getSpuId()));
+                orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId()));
     }
 
     private Integer getCouponPrice(CouponDO coupon, Integer originPrice) {
-        // TODO 芋艿 getPreferentialType 的枚举判断
-        if (coupon.getPreferentialType().equals(1)) { // 减价
-            return coupon.getPriceOff();
-        } else if (coupon.getPreferentialType().equals(2)) { // 打折
-            Integer couponPrice = originPrice * coupon.getPercentOff() / 100;
-            return coupon.getDiscountPriceLimit() == null ? couponPrice
-                    : Math.min(couponPrice, coupon.getDiscountPriceLimit()); // 优惠上限
+        if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价
+            return coupon.getDiscountPrice();
+        } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折
+            int couponPrice = originPrice * coupon.getDiscountPercent() / 100;
+            return coupon.getDiscountLimitPrice() == null ? couponPrice
+                    : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限
         }
-        throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon.toString()));
+        throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon));
     }
 
     // ========== 其它相对通用的方法 ==========

+ 1 - 1
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 {
         ProductSkuRespDTO productSku03 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(30L).setPrice(30).setSpuId(3L));
         when(productSkuApi.getSkuList(eq(asSet(10L, 20L, 30L)))).thenReturn(asList(productSku01, productSku02, productSku03));
         // mock 方法(优惠劵 Coupon 信息)
-        CouponDO coupon = randomPojo(CouponDO.class, o -> o.setId(1024L).setTitle("程序员节")
+        CouponDO coupon = randomPojo(CouponDO.class, o -> o.setId(1024L).setName("程序员节")
                 .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setSpuIds(asList(1L, 2L))
                 .setPriceAvailable(350).setPreferentialType(2).setPercentOff(50).setDiscountPriceLimit(70));
         when(couponService.validCoupon(eq(1024L), eq(calculateReqDTO.getUserId()))).thenReturn(coupon);