promotion:完善的优惠卷的实体
parent
8ae8a4a652
commit
2c39405bce
|
@ -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;
|
||||
|
||||
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;
|
||||
/**
|
||||
* 折扣
|
||||
*/
|
||||
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 ==========
|
||||
|
||||
|
|
|
@ -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 等数据库,可不写。
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ========== 其它相对通用的方法 ==========
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue