promotion:完善的优惠卷的实体

This commit is contained in:
YunaiV 2022-11-03 00:05:13 +08:00
parent 8ae8a4a652
commit 2c39405bce
5 changed files with 97 additions and 61 deletions

View File

@ -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;
}
}

View File

@ -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") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@KeySequence("promotion_coupon_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 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 ==========

View File

@ -21,6 +21,8 @@ import java.util.List;
* 优惠劵模板 DO
*
* 当用户领取时会生成 {@link CouponDO} 优惠劵
*
* @author 芋道源码
*/
@TableName(value = "promotion_coupon_template", autoResultMap = true)
@KeySequence("promotion_coupon_template_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写

View File

@ -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));
}
// ========== 其它相对通用的方法 ==========

View File

@ -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);