mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 02:08:43 +08:00 
			
		
		
		
	promotion:完善的优惠卷的实体
This commit is contained in:
		| @@ -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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,11 +1,14 @@ | |||||||
| package cn.iocoder.yudao.module.promotion.dal.dataobject.coupon; | 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.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.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.KeySequence; | ||||||
| import com.baomidou.mybatisplus.annotation.TableField; | import com.baomidou.mybatisplus.annotation.TableField; | ||||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||||
| import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; |  | ||||||
| import lombok.Data; | import lombok.Data; | ||||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||||
|  |  | ||||||
| @@ -14,9 +17,11 @@ import java.util.List; | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 优惠劵 DO |  * 优惠劵 DO | ||||||
|  |  * | ||||||
|  |  * @author 芋道源码 | ||||||
|  */ |  */ | ||||||
| @TableName(value = "promotion_coupon", autoResultMap = true) | @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 | @Data | ||||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||||
| public class CouponDO extends BaseDO { | public class CouponDO extends BaseDO { | ||||||
| @@ -35,21 +40,13 @@ public class CouponDO extends BaseDO { | |||||||
|     /** |     /** | ||||||
|      * 优惠劵名 |      * 优惠劵名 | ||||||
|      * |      * | ||||||
|      * 冗余自 {@link CouponTemplateDO} 的 title |      * 冗余 {@link CouponTemplateDO#getName()} | ||||||
|      * |  | ||||||
|      * TODO 芋艿,暂时不考虑冗余的更新 |  | ||||||
|      */ |      */ | ||||||
|     private String title; |     private String name; | ||||||
| //    /** |  | ||||||
| //     * 核销码 |  | ||||||
| //     */ |  | ||||||
| //    private String verifyCode; |  | ||||||
|     /** |     /** | ||||||
|      * 优惠码状态 |      * 优惠码状态 | ||||||
|      * |      * | ||||||
|      * 1-未使用 |      * 枚举 {@link CouponStatusEnum} | ||||||
|      * 2-已使用 |  | ||||||
|      * 3-已失效 |  | ||||||
|      */ |      */ | ||||||
|     private Integer status; |     private Integer status; | ||||||
|  |  | ||||||
| @@ -58,13 +55,14 @@ public class CouponDO extends BaseDO { | |||||||
|     // ========== 领取情况 BEGIN ========== |     // ========== 领取情况 BEGIN ========== | ||||||
|     /** |     /** | ||||||
|      * 用户编号 |      * 用户编号 | ||||||
|  |      * | ||||||
|  |      * 关联 MemberUserDO 的 id 字段 | ||||||
|      */ |      */ | ||||||
|     private Integer userId; |     private Long userId; | ||||||
|     /** |     /** | ||||||
|      * 领取类型 |      * 领取类型 | ||||||
|      * |      * | ||||||
|      * 1 - 用户主动领取 |      * 枚举 {@link CouponTakeTypeEnum} | ||||||
|      * 2 - 后台自动发放 |  | ||||||
|      */ |      */ | ||||||
|     private Integer takeType; |     private Integer takeType; | ||||||
|     // ========== 领取情况 END ========== |     // ========== 领取情况 END ========== | ||||||
| @@ -72,8 +70,10 @@ public class CouponDO extends BaseDO { | |||||||
|     // ========== 使用规则 BEGIN ========== |     // ========== 使用规则 BEGIN ========== | ||||||
|     /** |     /** | ||||||
|      * 是否设置满多少金额可用,单位:分 |      * 是否设置满多少金额可用,单位:分 | ||||||
|  |      * | ||||||
|  |      * 冗余 {@link CouponTemplateDO#getUsePrice()} | ||||||
|      */ |      */ | ||||||
|     private Integer priceAvailable; |     private Integer usePrice; | ||||||
|     /** |     /** | ||||||
|      * 生效开始时间 |      * 生效开始时间 | ||||||
|      */ |      */ | ||||||
| @@ -90,50 +90,49 @@ public class CouponDO extends BaseDO { | |||||||
|     private Integer productScope; |     private Integer productScope; | ||||||
|     /** |     /** | ||||||
|      * 商品 SPU 编号的数组 |      * 商品 SPU 编号的数组 | ||||||
|  |      * | ||||||
|  |      * 冗余 {@link CouponTemplateDO#getProductSpuIds()} | ||||||
|      */ |      */ | ||||||
|     @TableField(typeHandler = JacksonTypeHandler.class) |     @TableField(typeHandler = LongListTypeHandler.class) | ||||||
|     private List<Long> spuIds; |     private List<Long> productSpuIds; | ||||||
|     // ========== 使用规则 END ========== |     // ========== 使用规则 END ========== | ||||||
|  |  | ||||||
|     // ========== 使用效果 BEGIN ========== |     // ========== 使用效果 BEGIN ========== | ||||||
|     /** |     /** | ||||||
|      * 优惠类型 |      * 折扣类型 | ||||||
|      * |      * | ||||||
|      * 1-代金卷 |      * 冗余 {@link CouponTemplateDO#getDiscountType()} | ||||||
|      * 2-折扣卷 |  | ||||||
|      */ |      */ | ||||||
|     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 ========== |     // ========== 使用效果 END ========== | ||||||
|  |  | ||||||
|     // ========== 使用情况 BEGIN ========== |     // ========== 使用情况 BEGIN ========== | ||||||
| //    /** |     /** | ||||||
| //     * 使用订单号 |      * 使用订单号 | ||||||
| //     */ |      */ | ||||||
| //    private Integer usedOrderId; // TODO 芋艿,暂时不考虑这个字段 |     private Long useOrderId; | ||||||
| //    /** |  | ||||||
| //     * 订单中优惠面值,单位:分 |  | ||||||
| //     */ |  | ||||||
| //    private Integer usedPrice; // TODO 芋艿,暂时不考虑这个字段 |  | ||||||
|     /** |     /** | ||||||
|      * 使用时间 |      * 使用时间 | ||||||
|      */ |      */ | ||||||
|     private Date usedTime; |     private Date useTime; | ||||||
|  |  | ||||||
|     // TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。 |  | ||||||
|  |  | ||||||
|     // ========== 使用情况 END ========== |     // ========== 使用情况 END ========== | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,6 +21,8 @@ import java.util.List; | |||||||
|  * 优惠劵模板 DO |  * 优惠劵模板 DO | ||||||
|  * |  * | ||||||
|  * 当用户领取时,会生成 {@link CouponDO} 优惠劵 |  * 当用户领取时,会生成 {@link CouponDO} 优惠劵 | ||||||
|  |  * | ||||||
|  |  * @author 芋道源码 | ||||||
|  */ |  */ | ||||||
| @TableName(value = "promotion_coupon_template", autoResultMap = true) | @TableName(value = "promotion_coupon_template", autoResultMap = true) | ||||||
| @KeySequence("promotion_coupon_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | @KeySequence("promotion_coupon_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | ||||||
|   | |||||||
| @@ -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.coupon.CouponDO; | ||||||
| import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; | 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.dal.dataobject.reward.RewardActivityDO; | ||||||
| import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; | import cn.iocoder.yudao.module.promotion.enums.common.*; | ||||||
| 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.service.coupon.CouponService; | 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.discount.DiscountService; | ||||||
| import cn.iocoder.yudao.module.promotion.service.reward.RewardService; | 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); |         Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); | ||||||
|         assert originPrice != null; |         assert originPrice != null; | ||||||
|         if (originPrice < coupon.getPriceAvailable()) { |         if (originPrice < coupon.getUsePrice()) { | ||||||
|             throw exception(COUPON_NO_MATCH_MIN_PRICE); |             throw exception(COUPON_NO_MATCH_MIN_PRICE); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -294,7 +291,7 @@ public class PriceServiceImpl implements PriceService { | |||||||
|         // TODO 芋艿:limit 不能超过最大价格 |         // TODO 芋艿:limit 不能超过最大价格 | ||||||
|         List<Integer> couponPartPrices = dividePrice(orderItems, couponPrice); |         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, |                 PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices, | ||||||
|                 true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice))); |                 true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice))); | ||||||
|         // 修改 SKU 的分摊 |         // 修改 SKU 的分摊 | ||||||
| @@ -309,19 +306,18 @@ public class PriceServiceImpl implements PriceService { | |||||||
|             return priceCalculate.getOrder().getItems(); |             return priceCalculate.getOrder().getItems(); | ||||||
|         } |         } | ||||||
|         return CollectionUtils.filterList(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) { |     private Integer getCouponPrice(CouponDO coupon, Integer originPrice) { | ||||||
|         // TODO 芋艿 getPreferentialType 的枚举判断 |         if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 | ||||||
|         if (coupon.getPreferentialType().equals(1)) { // 减价 |             return coupon.getDiscountPrice(); | ||||||
|             return coupon.getPriceOff(); |         } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折 | ||||||
|         } else if (coupon.getPreferentialType().equals(2)) { // 打折 |             int couponPrice = originPrice * coupon.getDiscountPercent() / 100; | ||||||
|             Integer couponPrice = originPrice * coupon.getPercentOff() / 100; |             return coupon.getDiscountLimitPrice() == null ? couponPrice | ||||||
|             return coupon.getDiscountPriceLimit() == null ? couponPrice |                     : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限 | ||||||
|                     : Math.min(couponPrice, coupon.getDiscountPriceLimit()); // 优惠上限 |  | ||||||
|         } |         } | ||||||
|         throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon.toString())); |         throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========== 其它相对通用的方法 ========== |     // ========== 其它相对通用的方法 ========== | ||||||
|   | |||||||
| @@ -373,7 +373,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { | |||||||
|         ProductSkuRespDTO productSku03 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(30L).setPrice(30).setSpuId(3L)); |         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)); |         when(productSkuApi.getSkuList(eq(asSet(10L, 20L, 30L)))).thenReturn(asList(productSku01, productSku02, productSku03)); | ||||||
|         // mock 方法(优惠劵 Coupon 信息) |         // 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)) |                 .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setSpuIds(asList(1L, 2L)) | ||||||
|                 .setPriceAvailable(350).setPreferentialType(2).setPercentOff(50).setDiscountPriceLimit(70)); |                 .setPriceAvailable(350).setPreferentialType(2).setPercentOff(50).setDiscountPriceLimit(70)); | ||||||
|         when(couponService.validCoupon(eq(1024L), eq(calculateReqDTO.getUserId()))).thenReturn(coupon); |         when(couponService.validCoupon(eq(1024L), eq(calculateReqDTO.getUserId()))).thenReturn(coupon); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV