From 2c39405bcea22737be3a49beb23cc67fa7a99c7d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 3 Nov 2022 00:05:13 +0800 Subject: [PATCH] =?UTF-8?q?promotion=EF=BC=9A=E5=AE=8C=E5=96=84=E7=9A=84?= =?UTF-8?q?=E4=BC=98=E6=83=A0=E5=8D=B7=E7=9A=84=E5=AE=9E=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/coupon/CouponStatusEnum.java | 39 ++++++++ .../dal/dataobject/coupon/CouponDO.java | 89 +++++++++---------- .../dataobject/coupon/CouponTemplateDO.java | 2 + .../service/price/PriceServiceImpl.java | 26 +++--- .../service/price/PriceServiceTest.java | 2 +- 5 files changed, 97 insertions(+), 61 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponStatusEnum.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponStatusEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponStatusEnum.java new file mode 100644 index 000000000..25d2fc9ee --- /dev/null +++ b/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; + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java index 9bf41f317..89f7cbfb9 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java +++ b/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 spuIds; + @TableField(typeHandler = LongListTypeHandler.class) + private List productSpuIds; // ========== 使用规则 END ========== // ========== 使用效果 BEGIN ========== /** - * 优惠类型 + * 折扣类型 * - * 1-代金卷 - * 2-折扣卷 + * 冗余 {@link CouponTemplateDO#getDiscountType()} */ - private Integer preferentialType; + private Integer discountType; /** - * 折扣 - */ - private Integer percentOff; - /** - * 优惠金额,单位:分。 - */ - private Integer priceOff; - /** - * 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。 + * 折扣百分比 * - * 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。 + * 冗余 {@link CouponTemplateDO#getDiscountPercent()} */ - private Integer discountPriceLimit; + private Integer discountPercent; + /** + * 优惠金额,单位:分 + * + * 冗余 {@link CouponTemplateDO#getDiscountPrice()} + */ + private Integer discountPrice; + /** + * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效 + * + * 冗余 {@link CouponTemplateDO#getDiscountLimitPrice()} + */ + private Integer discountLimitPrice; // ========== 使用效果 END ========== // ========== 使用情况 BEGIN ========== -// /** -// * 使用订单号 -// */ -// private Integer usedOrderId; // TODO 芋艿,暂时不考虑这个字段 -// /** -// * 订单中优惠面值,单位:分 -// */ -// private Integer usedPrice; // TODO 芋艿,暂时不考虑这个字段 + /** + * 使用订单号 + */ + private Long useOrderId; /** * 使用时间 */ - private Date usedTime; - - // TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。 + private Date useTime; // ========== 使用情况 END ========== diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java index 543289c63..f3d545b3e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java +++ b/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 等数据库,可不写。 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java index 7fa111d26..88d5c5fa5 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java +++ b/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 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)); } // ========== 其它相对通用的方法 ========== diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java index 4e4a72738..96b0a2350 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java +++ b/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);