优惠劵相关逻辑的迁移
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.activity;
|
||||
|
||||
/**
|
||||
* 促销活动状态枚举
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.activity;
|
||||
|
||||
/**
|
||||
* 推广活动类型枚举
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.coupon.card;
|
||||
|
||||
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.coupon.card;
|
||||
|
||||
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.coupon.template;
|
||||
|
||||
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.coupon.template;
|
||||
|
||||
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.coupon.template;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.mall.promotion.api.enums;
|
||||
package cn.iocoder.mall.promotion.api.enums.recommend;
|
||||
|
||||
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.activity.dto;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@@ -25,13 +27,13 @@ public class PromotionActivityRespDTO implements Serializable {
|
||||
/**
|
||||
* 活动类型
|
||||
*
|
||||
* 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum} 枚举
|
||||
* 参见 {@link PromotionActivityTypeEnum} 枚举
|
||||
*/
|
||||
private Integer activityType;
|
||||
/**
|
||||
* 活动状态
|
||||
*
|
||||
* 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityStatusEnum} 枚举
|
||||
* 参见 {@link PromotionActivityStatusEnum} 枚举
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵 Rpc 接口
|
||||
*/
|
||||
public interface CouponCardRpc {
|
||||
|
||||
/**
|
||||
* 获得优惠劵分页
|
||||
*
|
||||
* @param pageReqDTO 优惠劵分页查询
|
||||
* @return 优惠劵分页结果
|
||||
*/
|
||||
CommonResult<PageResult<CouponCardRespDTO>> pageCouponCard(CouponCardPageReqDTO pageReqDTO);
|
||||
|
||||
/**
|
||||
* 给用户添加优惠劵
|
||||
*
|
||||
* @param createReqDTO 创建信息
|
||||
* @return 优惠劵编号
|
||||
*/
|
||||
CommonResult<Integer> createCouponCard(CouponCardCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 用户使用优惠劵
|
||||
*
|
||||
* @param useReqDTO 使用信息
|
||||
* @return 成功
|
||||
*/
|
||||
CommonResult<Boolean> useCouponCard(CouponCardUseReqDTO useReqDTO);
|
||||
|
||||
/**
|
||||
* 用户取消使用优惠劵
|
||||
*
|
||||
* @param cancelUseReqDTO 取消使用信息
|
||||
* @return 成功
|
||||
*/
|
||||
CommonResult<Boolean> cancelUseCouponCard(CouponCardCancelUseReqDTO cancelUseReqDTO);
|
||||
|
||||
/**
|
||||
* 获得用户优惠劵的可用信息列表
|
||||
*
|
||||
* @param listReqDTO 查询信息
|
||||
* @return 优惠劵的可用信息列表
|
||||
*/
|
||||
CommonResult<List<CouponCardAvailableRespDTO>> listAvailableCouponCards(CouponCardAvailableListReqDTO listReqDTO);
|
||||
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.CouponTemplateStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
public interface CouponRpc {
|
||||
|
||||
// ========== 优惠劵(码)模板 ==========
|
||||
@@ -58,67 +55,4 @@ public interface CouponRpc {
|
||||
Boolean updateCouponTemplateStatus(Integer adminId, Integer couponTemplateId,
|
||||
@InEnum(value = CouponTemplateStatusEnum.class, message = "修改状态必须是 {value}") Integer status);
|
||||
|
||||
// ========== 优惠劵 ==========
|
||||
|
||||
CouponCardPageRespDTO getCouponCardPage(CouponCardPageReqDTO couponCardPageDTO);
|
||||
|
||||
/**
|
||||
* 基于优惠劵模板,领取优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponTemplateId 优惠劵模板
|
||||
* @return 优惠劵
|
||||
*/
|
||||
CouponCardReqDTO addCouponCard(Integer userId, Integer couponTemplateId);
|
||||
|
||||
/**
|
||||
* 使用优惠劵下单
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponCardId 优惠劵编号
|
||||
* @return 是否成功
|
||||
*/
|
||||
Boolean useCouponCard(Integer userId,
|
||||
@NotNull(message = "优惠劵编号不能为空") Integer couponCardId);
|
||||
|
||||
/**
|
||||
* 取消优惠劵的使用
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponCardId 优惠劵编号
|
||||
* @return 是否成功
|
||||
*/
|
||||
Boolean cancelUseCouponCard(Integer userId, Integer couponCardId);
|
||||
|
||||
/**
|
||||
* 获得指定优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponCardId 优惠劵编号
|
||||
* @return 优惠劵
|
||||
*/
|
||||
CouponCardDetailRespDTO getCouponCardDetail(Integer userId, Integer couponCardId);
|
||||
|
||||
/**
|
||||
* 获得用户所有优惠劵,并标明是否可用
|
||||
* <p>
|
||||
* 注意,spus 是作为条件,判断优惠劵是否可用
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param spus 匹配的商品/分类
|
||||
* @return 优惠劵列表
|
||||
*/
|
||||
List<CouponCardAvailableRespDTO> getCouponCardList(Integer userId, List<CouponCardSpuRespDTO> spus);
|
||||
|
||||
// ========== 优惠码 ==========
|
||||
|
||||
/**
|
||||
* 使用优惠码,兑换优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param code 优惠码
|
||||
* @return 优惠劵
|
||||
*/
|
||||
CouponCardReqDTO useCouponCode(Integer userId, String code);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵明细 BO 。
|
||||
*
|
||||
* 主要是,会带上 {@link CouponTemplateReqDTO} 的信息
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardDetailRespDTO implements Serializable {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 优惠劵(码)分组编号
|
||||
*/
|
||||
private Integer templateId;
|
||||
/**
|
||||
* 优惠劵名
|
||||
*/
|
||||
private String title;
|
||||
// /**
|
||||
// * 核销码
|
||||
// */
|
||||
// private String verifyCode;
|
||||
/**
|
||||
* 优惠码状态
|
||||
*
|
||||
* 1-未使用
|
||||
* 2-已使用
|
||||
* 3-已失效
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
// ========== 基本信息 END ==========
|
||||
|
||||
// ========== 领取情况 BEGIN ==========
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 领取类型
|
||||
*
|
||||
* 1 - 用户主动领取
|
||||
* 2 - 后台自动发放
|
||||
*/
|
||||
private Integer takeType;
|
||||
// ========== 领取情况 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
/**
|
||||
* 是否设置满多少金额可用,单位:分
|
||||
*/
|
||||
private Integer priceAvailable;
|
||||
/**
|
||||
* 生效开始时间
|
||||
*/
|
||||
private Date validStartTime;
|
||||
/**
|
||||
* 生效结束时间
|
||||
*/
|
||||
private Date validEndTime;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
/**
|
||||
* 优惠类型
|
||||
*
|
||||
* 1-代金卷
|
||||
* 2-折扣卷
|
||||
*/
|
||||
private Integer preferentialType;
|
||||
/**
|
||||
* 折扣
|
||||
*/
|
||||
private Integer percentOff;
|
||||
/**
|
||||
* 优惠金额,单位:分。
|
||||
*/
|
||||
private Integer priceOff;
|
||||
/**
|
||||
* 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。
|
||||
*
|
||||
* 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。
|
||||
*/
|
||||
private Integer discountPriceLimit;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 使用情况 BEGIN ==========
|
||||
/**
|
||||
* 是否使用
|
||||
*/
|
||||
private Boolean used;
|
||||
/**
|
||||
* 使用订单号
|
||||
*/
|
||||
private Integer usedOrderId;
|
||||
/**
|
||||
* 订单中优惠面值,单位:分
|
||||
*/
|
||||
private Integer usedPrice;
|
||||
/**
|
||||
* 使用时间
|
||||
*/
|
||||
private Date usedTime;
|
||||
|
||||
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
|
||||
|
||||
// ========== 使用情况 END ==========
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
// ========== FROM template 使用规则 BEGIN ==========
|
||||
/**
|
||||
* 可用范围的类型
|
||||
*
|
||||
* 10-全部(ALL):所有可用
|
||||
* 20-部分(PART):部分商品可用,或指定商品可用
|
||||
* 21-部分(PART):部分商品不可用,或指定商品可用
|
||||
* 30-部分(PART):部分分类可用,或指定商品可用
|
||||
* 31-部分(PART):部分分类不可用,或指定商品可用
|
||||
*/
|
||||
private Integer rangeType;
|
||||
/**
|
||||
* 指定商品 / 分类列表,使用逗号分隔商品编号
|
||||
*/
|
||||
private List<Integer> rangeValues;
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 优惠劵分页 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardPageReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
@NotNull(message = "页码不能为空")
|
||||
private Integer pageNo;
|
||||
@NotNull(message = "每页条数不能为空")
|
||||
private Integer pageSize;
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵分页 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardPageRespDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 优惠劵数组
|
||||
*/
|
||||
private List<CouponCardReqDTO> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 优惠劵 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardReqDTO implements Serializable {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 优惠劵(码)分组编号
|
||||
*/
|
||||
private Integer templateId;
|
||||
/**
|
||||
* 优惠劵名
|
||||
*/
|
||||
private String title;
|
||||
// /**
|
||||
// * 核销码
|
||||
// */
|
||||
// private String verifyCode;
|
||||
/**
|
||||
* 优惠码状态
|
||||
*
|
||||
* 1-未使用
|
||||
* 2-已使用
|
||||
* 3-已失效
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
// ========== 基本信息 END ==========
|
||||
|
||||
// ========== 领取情况 BEGIN ==========
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 领取类型
|
||||
*
|
||||
* 1 - 用户主动领取
|
||||
* 2 - 后台自动发放
|
||||
*/
|
||||
private Integer takeType;
|
||||
// ========== 领取情况 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
/**
|
||||
* 是否设置满多少金额可用,单位:分
|
||||
*/
|
||||
private Integer priceAvailable;
|
||||
/**
|
||||
* 生效开始时间
|
||||
*/
|
||||
private Date validStartTime;
|
||||
/**
|
||||
* 生效结束时间
|
||||
*/
|
||||
private Date validEndTime;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
/**
|
||||
* 优惠类型
|
||||
*
|
||||
* 1-代金卷
|
||||
* 2-折扣卷
|
||||
*/
|
||||
private Integer preferentialType;
|
||||
/**
|
||||
* 折扣
|
||||
*/
|
||||
private Integer percentOff;
|
||||
/**
|
||||
* 优惠金额,单位:分。
|
||||
*/
|
||||
private Integer priceOff;
|
||||
/**
|
||||
* 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。
|
||||
*
|
||||
* 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。
|
||||
*/
|
||||
private Integer discountPriceLimit;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 使用情况 BEGIN ==========
|
||||
/**
|
||||
* 使用时间
|
||||
*/
|
||||
private Date usedTime;
|
||||
|
||||
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
|
||||
|
||||
// ========== 使用情况 END ==========
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.CouponTemplateDateTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateDateTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.PreferentialTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.RangeTypeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto.card;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵可用信息列表 Request DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardAvailableListReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Integer userId;
|
||||
/**
|
||||
* 商品数组
|
||||
*/
|
||||
@NotEmpty(message = "商品数组不能为空")
|
||||
private List<Item> items;
|
||||
|
||||
/**
|
||||
* 商品
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Item implements Serializable {
|
||||
|
||||
/**
|
||||
* 商品 SPU 编号
|
||||
*/
|
||||
@NotNull(message = "商品 SPU 编号不能为空")
|
||||
private Integer spuId;
|
||||
/**
|
||||
* 商品 SKU 编号
|
||||
*/
|
||||
@NotNull(message = "商品 SKU 编号不能为空")
|
||||
private Integer skuId;
|
||||
/**
|
||||
* 商品 SKU 编号
|
||||
*/
|
||||
@NotNull(message = "商品 Category 编号不能为空")
|
||||
private Integer cid;
|
||||
/**
|
||||
* 商品数量
|
||||
*/
|
||||
@NotNull(message = "商品数量不能为空")
|
||||
@Min(value = 1L, message = "最小商品数量 1")
|
||||
private Integer quantity;
|
||||
/**
|
||||
* 商品价格,单位:分
|
||||
*
|
||||
* 为什么需要传递价格?因为商品的价格是经过计算,部署商品原始价格
|
||||
*/
|
||||
@NotNull(message = "商品价格不能为空")
|
||||
private Integer price;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto;
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto.card;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
@@ -9,8 +10,9 @@ import lombok.experimental.Accessors;
|
||||
* 注意,如果优惠劵不可用,标记 available = false ,并写明 unavailableReason 原因
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardAvailableRespDTO extends CouponCardReqDTO {
|
||||
public class CouponCardAvailableRespDTO extends CouponCardRespDTO {
|
||||
|
||||
/**
|
||||
* 是否可用
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto.card;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 优惠劵取消使用 Request DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardCancelUseReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Integer userId;
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
@NotNull(message = "优惠劵编号不能为空")
|
||||
private Integer couponCardId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto.card;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 优惠劵创建 Request DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardCreateReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Integer userId;
|
||||
/**
|
||||
* 优惠劵模板编号
|
||||
*/
|
||||
@NotNull(message = "优惠劵模板编号不能为空")
|
||||
private Integer couponTemplateId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto.card;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageParam;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 优惠劵分页 DTO
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardPageReqDTO extends PageParam {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.coupon.dto.card;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 优惠劵使用 Request DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardUseReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Integer userId;
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
@NotNull(message = "优惠劵编号不能为空")
|
||||
private Integer couponCardId;
|
||||
|
||||
}
|
||||
@@ -17,7 +17,6 @@ public class PriceProductCalcReqDTO implements Serializable {
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Integer userId;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.price.dto;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.recommend.dto;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.ProductRecommendTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.recommend.ProductRecommendTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.recommend.dto;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.enums.ProductRecommendTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.recommend.ProductRecommendTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.promotion.api.rpc.recommend.dto;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.ProductRecommendTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.recommend.ProductRecommendTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package cn.iocoder.mall.promotionservice.convert.coupon;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.CouponCardDetailRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.CouponCardReqDTO;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponCardDO;
|
||||
import cn.iocoder.mall.promotionservice.service.coupon.bo.CouponCardAvailableBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface CouponCardConvert {
|
||||
|
||||
CouponCardConvert INSTANCE = Mappers.getMapper(CouponCardConvert.class);
|
||||
|
||||
// @Mappings({})
|
||||
// CouponCardBO convertToBO(CouponCardDO banner);
|
||||
|
||||
|
||||
|
||||
List<CouponCardReqDTO> convertToDTO(List<CouponCardDO> cardList);
|
||||
|
||||
CouponCardReqDTO convertToSingleDTO(CouponCardDO card);
|
||||
|
||||
@Mappings({})
|
||||
CouponCardDetailRespDTO convert2(CouponCardDO card);
|
||||
|
||||
CouponCardAvailableBO convertAvailBO(CouponCardDO card,boolean x);
|
||||
|
||||
//@Mappings({})
|
||||
//CouponCardAvailableBO convert2(CouponCardDO card, boolean x); // TODO 芋艿,临时用来解决 mapstruct 无法正确匹配方法的问题
|
||||
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
package cn.iocoder.mall.promotionservice.convert.coupon.card;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardAvailableRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardRespDTO;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponCardDO;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Named;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
@@ -12,4 +17,10 @@ public interface CouponCardConvert {
|
||||
|
||||
CouponCardRespDTO convert(CouponCardDO bean);
|
||||
|
||||
@Mapping(source = "records", target = "list")
|
||||
PageResult<CouponCardRespDTO> convertPage(IPage<CouponCardDO> page);
|
||||
|
||||
@Named("convertCouponCardDOToCouponCardAvailableRespDTO") // 避免生成的方法名的冲突
|
||||
CouponCardAvailableRespDTO convert01(CouponCardDO bean);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package cn.iocoder.mall.promotionservice.dal.mysql.dataobject.activity;
|
||||
|
||||
import cn.iocoder.mall.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
|
||||
@@ -31,7 +33,7 @@ public class PromotionActivityDO extends BaseDO {
|
||||
/**
|
||||
* 活动类型
|
||||
*
|
||||
* 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum} 枚举
|
||||
* 参见 {@link PromotionActivityTypeEnum} 枚举
|
||||
*/
|
||||
private Integer activityType;
|
||||
// /**
|
||||
@@ -42,7 +44,7 @@ public class PromotionActivityDO extends BaseDO {
|
||||
/**
|
||||
* 活动状态
|
||||
*
|
||||
* 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityStatusEnum} 枚举
|
||||
* 参见 {@link PromotionActivityStatusEnum} 枚举
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon;
|
||||
|
||||
import cn.iocoder.mall.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -9,7 +11,9 @@ import java.util.Date;
|
||||
/**
|
||||
* 优惠劵 DO
|
||||
*/
|
||||
@TableName("coupon_card")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardDO extends BaseDO {
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon;
|
||||
|
||||
import cn.iocoder.mall.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -11,7 +14,9 @@ import java.util.Date;
|
||||
*
|
||||
* 当用户领取时,会生成 {@link CouponCardDO} 优惠劵(码)。
|
||||
*/
|
||||
@TableName("coupon_template")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class CouponTemplateDO extends BaseDO {
|
||||
|
||||
@@ -38,7 +43,7 @@ public class CouponTemplateDO extends BaseDO {
|
||||
/**
|
||||
* 优惠码状态
|
||||
*
|
||||
* {@link cn.iocoder.mall.promotion.api.enums.CouponTemplateStatusEnum}
|
||||
* {@link CouponTemplateStatusEnum}
|
||||
*
|
||||
* 当优惠劵(码)开启中,可以手动操作,设置禁用中。
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@ package cn.iocoder.mall.promotionservice.dal.mysql.dataobject.recommend;
|
||||
|
||||
|
||||
import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO;
|
||||
import cn.iocoder.mall.promotion.api.enums.ProductRecommendTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.recommend.ProductRecommendTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
|
||||
@@ -1,36 +1,38 @@
|
||||
package cn.iocoder.mall.promotionservice.dal.mysql.mapper.coupon;
|
||||
|
||||
import cn.iocoder.mall.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardPageReqDTO;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponCardDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface CouponCardMapper {
|
||||
public interface CouponCardMapper extends BaseMapper<CouponCardDO> {
|
||||
|
||||
CouponCardDO selectById(@Param("id") Integer id);
|
||||
default List<CouponCardDO> selectListByUserIdAndStatus(Integer userId, Integer status) {
|
||||
return selectList(new QueryWrapper<CouponCardDO>().eq("user_id", userId)
|
||||
.eq("status", status));
|
||||
}
|
||||
|
||||
List<CouponCardDO> selectListByUserIdAndStatus(@Param("userId") Integer userId,
|
||||
@Param("status") Integer status);
|
||||
default int selectCountByUserIdAndTemplateId(Integer userId, Integer templateId) {
|
||||
return selectCount(new QueryWrapper<CouponCardDO>().eq("user_id", userId)
|
||||
.eq("template_id", templateId));
|
||||
}
|
||||
|
||||
List<CouponCardDO> selectListByPage(@Param("userId") Integer userId,
|
||||
@Param("status") Integer status,
|
||||
@Param("offset") Integer offset,
|
||||
@Param("limit") Integer limit);
|
||||
default int updateByIdAndStatus(Integer id, Integer status, CouponCardDO updateObj) {
|
||||
return update(updateObj, new QueryWrapper<CouponCardDO>().eq("id", id)
|
||||
.eq("status", status));
|
||||
}
|
||||
|
||||
Integer selectCountByPage(@Param("userId") Integer userId,
|
||||
@Param("status") Integer status);
|
||||
|
||||
int selectCountByUserIdAndTemplateId(@Param("userId") Integer userId,
|
||||
@Param("templateId") Integer templateId);
|
||||
|
||||
void insert(CouponCardDO couponCardDO);
|
||||
|
||||
int update(CouponCardDO couponCardDO);
|
||||
|
||||
int updateByIdAndStatus(@Param("id") Integer id,
|
||||
@Param("status") Integer status,
|
||||
@Param("updateObj") CouponCardDO updateObj);
|
||||
default IPage<CouponCardDO> selectPage(CouponCardPageReqDTO pageReqDTO) {
|
||||
return selectPage(new Page<>(pageReqDTO.getPageNo(), pageReqDTO.getPageSize()),
|
||||
new QueryWrapperX<CouponCardDO>().eqIfPresent("user_id", pageReqDTO.getUserId())
|
||||
.eqIfPresent("status", pageReqDTO.getStatus()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
package cn.iocoder.mall.promotionservice.dal.mysql.mapper.coupon;
|
||||
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponTemplateDO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface CouponTemplateMapper {
|
||||
|
||||
CouponTemplateDO selectById(@Param("id") Integer id);
|
||||
|
||||
List<CouponTemplateDO> selectListByIds(@Param("ids") Collection<Integer> ids);
|
||||
public interface CouponTemplateMapper extends BaseMapper<CouponTemplateDO> {
|
||||
|
||||
List<CouponTemplateDO> selectListByPage(@Param("type") Integer type,
|
||||
@Param("title") String title,
|
||||
@@ -26,10 +22,14 @@ public interface CouponTemplateMapper {
|
||||
@Param("status") Integer status,
|
||||
@Param("preferentialType") Integer preferentialType);
|
||||
|
||||
void insert(CouponTemplateDO couponTemplate);
|
||||
|
||||
int update(CouponTemplateDO couponTemplate);
|
||||
|
||||
/**
|
||||
* 更新优惠劵模板已领取的数量
|
||||
*
|
||||
* 如果超过领取上限,则返回 0
|
||||
*
|
||||
* @param id 优惠劵模板编号
|
||||
* @return 更新数量
|
||||
*/
|
||||
int updateStatFetchNumIncr(@Param("id") Integer id);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.mall.promotionservice.manager.coupon.card;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.*;
|
||||
import cn.iocoder.mall.promotionservice.service.coupon.CouponCardService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Validated
|
||||
public class CouponCardManager {
|
||||
|
||||
@Autowired
|
||||
private CouponCardService couponCardService;
|
||||
|
||||
public PageResult<CouponCardRespDTO> pageCouponCard(CouponCardPageReqDTO pageReqDTO) {
|
||||
return couponCardService.pageCouponCard(pageReqDTO);
|
||||
}
|
||||
|
||||
public Integer createCouponCard(CouponCardCreateReqDTO createReqDTO) {
|
||||
return couponCardService.createCouponCard(createReqDTO.getUserId(), createReqDTO.getCouponTemplateId());
|
||||
}
|
||||
|
||||
public Boolean useCouponCard(CouponCardUseReqDTO useReqDTO) {
|
||||
couponCardService.useCouponCard(useReqDTO.getUserId(), useReqDTO.getCouponCardId());
|
||||
return true;
|
||||
}
|
||||
|
||||
public Boolean cancelUseCouponCard(CouponCardCancelUseReqDTO cancelUseReqDTO) {
|
||||
couponCardService.cancelUseCouponCard(cancelUseReqDTO.getUserId(), cancelUseReqDTO.getCouponCardId());
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<CouponCardAvailableRespDTO> listAvailableCouponCards(CouponCardAvailableListReqDTO listReqDTO) {
|
||||
return couponCardService.listAvailableCouponCards(listReqDTO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.ProductSpuRpc;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.enums.*;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.template.CouponTemplateRespDTO;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package cn.iocoder.mall.promotionservice.rpc.coupon;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.CouponCardRpc;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.*;
|
||||
import cn.iocoder.mall.promotionservice.manager.coupon.card.CouponCardManager;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@DubboService
|
||||
public class CouponCardRpcImpl implements CouponCardRpc {
|
||||
|
||||
@Autowired
|
||||
private CouponCardManager couponCardManager;
|
||||
|
||||
@Override
|
||||
public CommonResult<PageResult<CouponCardRespDTO>> pageCouponCard(CouponCardPageReqDTO pageReqDTO) {
|
||||
return success(couponCardManager.pageCouponCard(pageReqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Integer> createCouponCard(CouponCardCreateReqDTO createReqDTO) {
|
||||
return success(couponCardManager.createCouponCard(createReqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> useCouponCard(CouponCardUseReqDTO useReqDTO) {
|
||||
return success(couponCardManager.useCouponCard(useReqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> cancelUseCouponCard(CouponCardCancelUseReqDTO cancelUseReqDTO) {
|
||||
return success(couponCardManager.cancelUseCouponCard(cancelUseReqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<CouponCardAvailableRespDTO>> listAvailableCouponCards(CouponCardAvailableListReqDTO listReqDTO) {
|
||||
return success(couponCardManager.listAvailableCouponCards(listReqDTO));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.mall.promotionservice.service.activity;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.RangeTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package cn.iocoder.mall.promotionservice.service.activity.bo;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@@ -22,13 +24,13 @@ public class PromotionActivityBO implements Serializable {
|
||||
/**
|
||||
* 活动类型
|
||||
*
|
||||
* 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum} 枚举
|
||||
* 参见 {@link PromotionActivityTypeEnum} 枚举
|
||||
*/
|
||||
private Integer activityType;
|
||||
/**
|
||||
* 活动状态
|
||||
*
|
||||
* 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityStatusEnum} 枚举
|
||||
* 参见 {@link PromotionActivityStatusEnum} 枚举
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
|
||||
@@ -1,14 +1,34 @@
|
||||
package cn.iocoder.mall.promotionservice.service.coupon;
|
||||
|
||||
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.util.CollectionUtils;
|
||||
import cn.iocoder.common.framework.util.DateUtil;
|
||||
import cn.iocoder.common.framework.util.StringUtils;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.enums.PromotionErrorCodeConstants;
|
||||
import cn.iocoder.mall.promotion.api.enums.RangeTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.card.CouponCardStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.card.CouponCardTakeTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateDateTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardAvailableListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardAvailableRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardPageReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardRespDTO;
|
||||
import cn.iocoder.mall.promotionservice.convert.coupon.card.CouponCardConvert;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponCardDO;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.mapper.coupon.CouponCardMapper;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.mapper.coupon.CouponTemplateMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 优惠劵 Service
|
||||
@@ -19,6 +39,8 @@ public class CouponCardService {
|
||||
|
||||
@Autowired
|
||||
private CouponCardMapper couponCardMapper;
|
||||
@Autowired
|
||||
private CouponTemplateMapper couponTemplateMapper;
|
||||
|
||||
public CouponCardRespDTO getCouponCard(Integer userId, Integer couponCardId) {
|
||||
CouponCardDO card = couponCardMapper.selectById(couponCardId);
|
||||
@@ -31,4 +53,199 @@ public class CouponCardService {
|
||||
return CouponCardConvert.INSTANCE.convert(card);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得优惠劵分页
|
||||
*
|
||||
* @param pageReqDTO 优惠劵分页查询
|
||||
* @return 优惠劵分页结果
|
||||
*/
|
||||
public PageResult<CouponCardRespDTO> pageCouponCard(CouponCardPageReqDTO pageReqDTO) {
|
||||
IPage<CouponCardDO> couponCardDOPage = couponCardMapper.selectPage(pageReqDTO);
|
||||
return CouponCardConvert.INSTANCE.convertPage(couponCardDOPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给用户添加优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponTemplateId 优惠劵模板编号
|
||||
* @return 优惠劵编号
|
||||
*/
|
||||
@Transactional
|
||||
public Integer createCouponCard(Integer userId, Integer couponTemplateId) {
|
||||
// 校验 CouponCardTemplate 存在
|
||||
CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId);
|
||||
if (template == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS.getCode());
|
||||
}
|
||||
// 校验 CouponCardTemplate 是 CARD
|
||||
if (!CouponTemplateTypeEnum.CARD.getValue().equals(template.getType())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_NOT_CARD.getCode());
|
||||
}
|
||||
// 校验 CouponCardTemplate 状态是否开启
|
||||
if (!CouponTemplateStatusEnum.ENABLE.getValue().equals(template.getStatus())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_STATUS_NOT_ENABLE.getCode());
|
||||
}
|
||||
// 校验 CouponCardTemplate 是否到达可领取的上限
|
||||
if (template.getStatFetchNum() > template.getTotal()) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_TOTAL_NOT_ENOUGH.getCode());
|
||||
}
|
||||
// 校验单人可领取优惠劵是否到达上限
|
||||
if (couponCardMapper.selectCountByUserIdAndTemplateId(userId, couponTemplateId) > template.getQuota()) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
|
||||
}
|
||||
// 增加优惠劵已领取量
|
||||
int updateTemplateCount = couponTemplateMapper.updateStatFetchNumIncr(couponTemplateId);
|
||||
if (updateTemplateCount == 0) { // 超过 CouponCardTemplate 发放量
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
|
||||
}
|
||||
// 创建优惠劵
|
||||
// 1. 基本信息 + 领取情况
|
||||
CouponCardDO card = new CouponCardDO()
|
||||
.setTemplateId(couponTemplateId)
|
||||
.setTitle(template.getTitle())
|
||||
.setStatus(CouponCardStatusEnum.UNUSED.getValue())
|
||||
.setUserId(userId)
|
||||
.setTakeType(CouponCardTakeTypeEnum.BY_USER.getValue()); // TODO 需要改
|
||||
// 2. 使用规则
|
||||
card.setPriceAvailable(template.getPriceAvailable());
|
||||
setCouponCardValidTime(card, template);
|
||||
// 3. 使用效果
|
||||
card.setPreferentialType(template.getPreferentialType())
|
||||
.setPriceOff(template.getPriceOff())
|
||||
.setPercentOff(template.getPercentOff()).setDiscountPriceLimit(template.getDiscountPriceLimit());
|
||||
// 保存优惠劵模板到数据库
|
||||
couponCardMapper.insert(card);
|
||||
// 返回成功
|
||||
return card.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户使用优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponCardId 优惠劵编号
|
||||
*/
|
||||
public void useCouponCard(Integer userId, Integer couponCardId) {
|
||||
// 查询优惠劵
|
||||
CouponCardDO card = couponCardMapper.selectById(couponCardId);
|
||||
if (card == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_NOT_EXISTS.getCode());
|
||||
}
|
||||
if (!userId.equals(card.getUserId())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_ERROR_USER.getCode());
|
||||
}
|
||||
if (!CouponCardStatusEnum.UNUSED.getValue().equals(card.getStatus())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_UNUSED.getCode());
|
||||
}
|
||||
if (DateUtil.isBetween(card.getValidStartTime(), card.getValidEndTime())) { // 为避免定时器没跑,实际优惠劵已经过期
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_UNUSED.getCode());
|
||||
}
|
||||
// 更新优惠劵已使用
|
||||
int updateCount = couponCardMapper.updateByIdAndStatus(card.getId(), CouponCardStatusEnum.UNUSED.getValue(),
|
||||
new CouponCardDO().setStatus(CouponCardStatusEnum.USED.getValue()).setUsedTime(new Date()));
|
||||
if (updateCount == 0) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_UNUSED.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户取消使用优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponCardId 优惠劵编号
|
||||
*/
|
||||
public void cancelUseCouponCard(Integer userId, Integer couponCardId) {
|
||||
// 查询优惠劵
|
||||
CouponCardDO card = couponCardMapper.selectById(couponCardId);
|
||||
if (card == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_NOT_EXISTS.getCode());
|
||||
}
|
||||
if (!userId.equals(card.getUserId())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_ERROR_USER.getCode());
|
||||
}
|
||||
if (!CouponCardStatusEnum.USED.getValue().equals(card.getStatus())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_USED.getCode());
|
||||
}
|
||||
// 更新优惠劵已使用
|
||||
int updateCount = couponCardMapper.updateByIdAndStatus(card.getId(), CouponCardStatusEnum.USED.getValue(),
|
||||
new CouponCardDO().setStatus(CouponCardStatusEnum.UNUSED.getValue())); // TODO 芋艿,usedTime 未设置空,后面处理。
|
||||
if (updateCount == 0) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_USED.getCode());
|
||||
}
|
||||
// 有一点要注意,更新会未使用时,优惠劵可能已经过期了,直接让定时器跑过期,这里不做处理。
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得用户优惠劵的可用信息列表
|
||||
*
|
||||
* @param listReqDTO 查询信息
|
||||
* @return 优惠劵的可用信息列表
|
||||
*/
|
||||
public List<CouponCardAvailableRespDTO> listAvailableCouponCards(CouponCardAvailableListReqDTO listReqDTO) {
|
||||
// 查询用户未使用的优惠劵列表
|
||||
List<CouponCardDO> cards = couponCardMapper.selectListByUserIdAndStatus(listReqDTO.getUserId(), CouponCardStatusEnum.UNUSED.getValue());
|
||||
if (cards.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 查询优惠劵模板集合
|
||||
Map<Integer, CouponTemplateDO> templates = CollectionUtils.convertMap(
|
||||
couponTemplateMapper.selectBatchIds(CollectionUtils.convertSet(cards, CouponCardDO::getTemplateId)),
|
||||
CouponTemplateDO::getId);
|
||||
// 逐个判断是否可用
|
||||
return cards.stream().map(card -> {
|
||||
CouponCardAvailableRespDTO availableCard = CouponCardConvert.INSTANCE.convert01(card);
|
||||
availableCard.setUnavailableReason(isMatch(card, templates.get(card.getTemplateId()), listReqDTO.getItems()));
|
||||
availableCard.setAvailable(availableCard.getUnavailableReason() == null);
|
||||
return availableCard;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配商品是否可以使用指定优惠劵
|
||||
*
|
||||
* @param card 优惠劵
|
||||
* @param template 优惠劵模板
|
||||
* @param items 商品 SKU 数组
|
||||
* @return 如果不匹配,返回原因
|
||||
*/
|
||||
private String isMatch(CouponCardDO card, CouponTemplateDO template, List<CouponCardAvailableListReqDTO.Item> items) {
|
||||
int totalPrice = 0;
|
||||
if (RangeTypeEnum.ALL.getValue().equals(template.getRangeType())) {
|
||||
totalPrice = items.stream().mapToInt(spu -> spu.getPrice() * spu.getQuantity()).sum();
|
||||
} else if (RangeTypeEnum.PRODUCT_INCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = items.stream().mapToInt(spu -> spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
} else if (RangeTypeEnum.PRODUCT_EXCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = items.stream().mapToInt(spu -> !spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
} else if (RangeTypeEnum.CATEGORY_INCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = items.stream().mapToInt(spu -> spuIds.contains(spu.getCid()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
} else if (RangeTypeEnum.CATEGORY_EXCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = items.stream().mapToInt(spu -> !spuIds.contains(spu.getCid()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
}
|
||||
// 总价为 0 时,说明优惠劵丫根不匹配
|
||||
if (totalPrice == 0) {
|
||||
return "优惠劵不匹配";
|
||||
}
|
||||
// 如果不满足金额
|
||||
if (totalPrice < card.getPriceAvailable()) {
|
||||
return String.format("差 %1$,.2f 元可用优惠劵", (card.getPriceAvailable() - totalPrice) / 100D);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setCouponCardValidTime(CouponCardDO card, CouponTemplateDO template) {
|
||||
if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) {
|
||||
card.setValidStartTime(template.getValidStartTime()).setValidEndTime(template.getValidEndTime());
|
||||
} else if (CouponTemplateDateTypeEnum.FIXED_TERM.getValue().equals(template.getDateType())) {
|
||||
Date validStartTime = DateUtil.getDayBegin(new Date());
|
||||
card.setValidStartTime(DateUtil.addDate(validStartTime, Calendar.DAY_OF_YEAR, template.getFixedStartTerm()));
|
||||
Date validEndTime = DateUtil.getDayEnd(card.getValidStartTime());
|
||||
card.setValidEndTime(DateUtil.addDate(validEndTime, Calendar.DAY_OF_YEAR, template.getFixedEndTerm() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
package cn.iocoder.mall.promotionservice.service.coupon;
|
||||
|
||||
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.util.DateUtil;
|
||||
import cn.iocoder.mall.promotion.api.enums.*;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.*;
|
||||
import cn.iocoder.mall.promotionservice.convert.coupon.CouponCardConvert;
|
||||
import cn.iocoder.mall.promotion.api.enums.PromotionErrorCodeConstants;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.CouponTemplatePageReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.CouponTemplatePageRespDTO;
|
||||
import cn.iocoder.mall.promotionservice.convert.coupon.card.CouponTemplateConvert;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponCardDO;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.mapper.coupon.CouponCardMapper;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.mapper.coupon.CouponTemplateMapper;
|
||||
import cn.iocoder.mall.promotionservice.service.coupon.bo.*;
|
||||
import cn.iocoder.common.framework.util.*;
|
||||
import cn.iocoder.mall.promotionservice.service.coupon.bo.CouponCardTemplateAddBO;
|
||||
import cn.iocoder.mall.promotionservice.service.coupon.bo.CouponCardTemplateUpdateBO;
|
||||
import cn.iocoder.mall.promotionservice.service.coupon.bo.CouponCodeTemplateUpdateBO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Date;
|
||||
|
||||
@Service
|
||||
@Validated
|
||||
@@ -86,7 +85,7 @@ public class CouponService {
|
||||
}
|
||||
// 更新优惠劵模板到数据库
|
||||
CouponTemplateDO updateTemplateDO = CouponTemplateConvert.INSTANCE.convert(couponCardTemplateUpdateDTO);
|
||||
couponTemplateMapper.update(updateTemplateDO);
|
||||
couponTemplateMapper.updateById(updateTemplateDO);
|
||||
// 返回成功
|
||||
return true;
|
||||
}
|
||||
@@ -99,7 +98,7 @@ public class CouponService {
|
||||
}
|
||||
// 更新到数据库
|
||||
CouponTemplateDO updateTemplateDO = new CouponTemplateDO().setId(couponTemplateId).setStatus(status);
|
||||
couponTemplateMapper.update(updateTemplateDO);
|
||||
couponTemplateMapper.updateById(updateTemplateDO);
|
||||
// 返回成功
|
||||
return true;
|
||||
}
|
||||
@@ -149,200 +148,6 @@ public class CouponService {
|
||||
|
||||
// ========== 优惠劵 ==========
|
||||
|
||||
public CouponCardPageRespDTO getCouponCardPage(CouponCardPageReqDTO couponCardPageDTO) {
|
||||
CouponCardPageRespDTO pageBO = new CouponCardPageRespDTO();
|
||||
// 查询分页数据
|
||||
int offset = (couponCardPageDTO.getPageNo() - 1) * couponCardPageDTO.getPageSize();
|
||||
pageBO.setList(CouponCardConvert.INSTANCE.convertToDTO(couponCardMapper.selectListByPage(
|
||||
couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus(),
|
||||
offset, couponCardPageDTO.getPageSize())));
|
||||
// 查询分页总数
|
||||
pageBO.setTotal(couponCardMapper.selectCountByPage(
|
||||
couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus()));
|
||||
return pageBO;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CouponCardReqDTO addCouponCard(Integer userId, Integer couponTemplateId) {
|
||||
// 校验 CouponCardTemplate 存在
|
||||
CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId);
|
||||
if (template == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS.getCode());
|
||||
}
|
||||
// 校验 CouponCardTemplate 是 CARD
|
||||
if (!CouponTemplateTypeEnum.CARD.getValue().equals(template.getType())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_NOT_CARD.getCode());
|
||||
}
|
||||
// 校验 CouponCardTemplate 状态是否开启
|
||||
if (!CouponTemplateStatusEnum.ENABLE.getValue().equals(template.getStatus())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_STATUS_NOT_ENABLE.getCode());
|
||||
}
|
||||
// 校验 CouponCardTemplate 是否到达可领取的上限
|
||||
if (template.getStatFetchNum() > template.getTotal()) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_TOTAL_NOT_ENOUGH.getCode());
|
||||
}
|
||||
// 校验单人可领取优惠劵是否到达上限
|
||||
if (couponCardMapper.selectCountByUserIdAndTemplateId(userId, couponTemplateId) > template.getQuota()) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
|
||||
}
|
||||
// 增加优惠劵已领取量
|
||||
int updateTemplateCount = couponTemplateMapper.updateStatFetchNumIncr(couponTemplateId);
|
||||
if (updateTemplateCount == 0) { // 超过 CouponCardTemplate 发放量
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
|
||||
}
|
||||
// 创建优惠劵
|
||||
// 1. 基本信息 + 领取情况
|
||||
CouponCardDO card = new CouponCardDO()
|
||||
.setTemplateId(couponTemplateId)
|
||||
.setTitle(template.getTitle())
|
||||
.setStatus(CouponCardStatusEnum.UNUSED.getValue())
|
||||
.setUserId(userId)
|
||||
.setTakeType(CouponCardTakeTypeEnum.BY_USER.getValue()); // TODO 需要改
|
||||
// 2. 使用规则
|
||||
card.setPriceAvailable(template.getPriceAvailable());
|
||||
setCouponCardValidTime(card, template);
|
||||
// 3. 使用效果
|
||||
card.setPreferentialType(template.getPreferentialType())
|
||||
.setPriceOff(template.getPriceOff())
|
||||
.setPercentOff(template.getPercentOff()).setDiscountPriceLimit(template.getDiscountPriceLimit());
|
||||
// 保存优惠劵模板到数据库
|
||||
card.setCreateTime(new Date());
|
||||
couponCardMapper.insert(card);
|
||||
// 返回成功
|
||||
return CouponCardConvert.INSTANCE.convertToSingleDTO(card);
|
||||
}
|
||||
|
||||
public Boolean useCouponCard(Integer userId, Integer couponCardId) {
|
||||
// 查询优惠劵
|
||||
CouponCardDO card = couponCardMapper.selectById(couponCardId);
|
||||
if (card == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_NOT_EXISTS.getCode());
|
||||
}
|
||||
if (!userId.equals(card.getUserId())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_ERROR_USER.getCode());
|
||||
}
|
||||
if (!CouponCardStatusEnum.UNUSED.getValue().equals(card.getStatus())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_UNUSED.getCode());
|
||||
}
|
||||
if (DateUtil.isBetween(card.getValidStartTime(), card.getValidEndTime())) { // 为避免定时器没跑,实际优惠劵已经过期
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_UNUSED.getCode());
|
||||
}
|
||||
// 更新优惠劵已使用
|
||||
int updateCount = couponCardMapper.updateByIdAndStatus(card.getId(), CouponCardStatusEnum.UNUSED.getValue(),
|
||||
new CouponCardDO().setStatus(CouponCardStatusEnum.USED.getValue()).setUsedTime(new Date()));
|
||||
if (updateCount == 0) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_UNUSED.getCode());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Boolean cancelUseCouponCard(Integer userId, Integer couponCardId) {
|
||||
// 查询优惠劵
|
||||
CouponCardDO card = couponCardMapper.selectById(couponCardId);
|
||||
if (card == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_NOT_EXISTS.getCode());
|
||||
}
|
||||
if (!userId.equals(card.getUserId())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_ERROR_USER.getCode());
|
||||
}
|
||||
if (!CouponCardStatusEnum.USED.getValue().equals(card.getStatus())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_USED.getCode());
|
||||
}
|
||||
// 更新优惠劵已使用
|
||||
int updateCount = couponCardMapper.updateByIdAndStatus(card.getId(), CouponCardStatusEnum.USED.getValue(),
|
||||
new CouponCardDO().setStatus(CouponCardStatusEnum.UNUSED.getValue())); // TODO 芋艿,usedTime 未设置空,后面处理。
|
||||
if (updateCount == 0) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_STATUS_NOT_USED.getCode());
|
||||
}
|
||||
// 有一点要注意,更新会未使用时,优惠劵可能已经过期了,直接让定时器跑过期,这里不做处理。
|
||||
return true;
|
||||
}
|
||||
|
||||
public CouponCardDetailRespDTO getCouponCardDetail(Integer userId, Integer couponCardId) {
|
||||
// 查询优惠劵
|
||||
CouponCardDO card = couponCardMapper.selectById(couponCardId);
|
||||
if (card == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_NOT_EXISTS.getCode());
|
||||
}
|
||||
if (!userId.equals(card.getUserId())) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_CARD_ERROR_USER.getCode());
|
||||
}
|
||||
// 查询优惠劵模板
|
||||
CouponTemplateDO template = couponTemplateMapper.selectById(card.getTemplateId());
|
||||
if (template == null) {
|
||||
throw ServiceExceptionUtil.exception(PromotionErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS.getCode());
|
||||
}
|
||||
// 拼接结果
|
||||
CouponCardDetailRespDTO detail = CouponCardConvert.INSTANCE.convert2(card);
|
||||
detail.setRangeType(template.getRangeType());
|
||||
detail.setRangeValues(StringUtils.splitToInt(template.getRangeValues(), ","));
|
||||
return detail;
|
||||
}
|
||||
|
||||
public List<CouponCardAvailableBO> getCouponCardList(Integer userId, List<CouponCardSpuBO> spus) {
|
||||
// 查询用户未使用的优惠劵列表
|
||||
List<CouponCardDO> cards = couponCardMapper.selectListByUserIdAndStatus(userId, CouponCardStatusEnum.UNUSED.getValue());
|
||||
if (cards.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 查询优惠劵模板集合
|
||||
Map<Integer, CouponTemplateDO> templates = couponTemplateMapper.selectListByIds(cards.stream().map(CouponCardDO::getTemplateId).collect(Collectors.toSet()))
|
||||
.stream().collect(Collectors.toMap(CouponTemplateDO::getId, template -> template));
|
||||
// 逐个判断是否可用
|
||||
List<CouponCardAvailableBO> availableCards = cards.stream().map(card -> {
|
||||
CouponCardAvailableBO availableCard = CouponCardConvert.INSTANCE.convertAvailBO(card, true);
|
||||
availableCard.setUnavailableReason(isMatch(card, templates.get(card.getTemplateId()), spus));
|
||||
availableCard.setAvailable(availableCard.getUnavailableReason() == null);
|
||||
return availableCard;
|
||||
}).collect(Collectors.toList());
|
||||
// 返回结果
|
||||
return availableCards;
|
||||
}
|
||||
|
||||
private void setCouponCardValidTime(CouponCardDO card, CouponTemplateDO template) {
|
||||
if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) {
|
||||
card.setValidStartTime(template.getValidStartTime()).setValidEndTime(template.getValidEndTime());
|
||||
} else if (CouponTemplateDateTypeEnum.FIXED_TERM.getValue().equals(template.getDateType())) {
|
||||
Date validStartTime = DateUtil.getDayBegin(new Date());
|
||||
card.setValidStartTime(DateUtil.addDate(validStartTime, Calendar.DAY_OF_YEAR, template.getFixedStartTerm()));
|
||||
Date validEndTime = DateUtil.getDayEnd(card.getValidStartTime());
|
||||
card.setValidEndTime(DateUtil.addDate(validEndTime, Calendar.DAY_OF_YEAR, template.getFixedEndTerm() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// 如果匹配,则返回 null 即可。
|
||||
private String isMatch(CouponCardDO card, CouponTemplateDO template, List<CouponCardSpuBO> spus) {
|
||||
int totalPrice = 0;
|
||||
if (RangeTypeEnum.ALL.getValue().equals(template.getRangeType())) {
|
||||
totalPrice = spus.stream().mapToInt(spu -> spu.getPrice() * spu.getQuantity()).sum();
|
||||
} else if (RangeTypeEnum.PRODUCT_INCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = spus.stream().mapToInt(spu -> spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
} else if (RangeTypeEnum.PRODUCT_EXCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = spus.stream().mapToInt(spu -> !spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
} else if (RangeTypeEnum.CATEGORY_INCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = spus.stream().mapToInt(spu -> spuIds.contains(spu.getCategoryId()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
} else if (RangeTypeEnum.CATEGORY_EXCLUDE_PART.getValue().equals(template.getRangeType())) {
|
||||
List<Integer> spuIds = StringUtils.splitToInt(template.getRangeValues(), ",");
|
||||
totalPrice = spus.stream().mapToInt(spu -> !spuIds.contains(spu.getCategoryId()) ? spu.getPrice() * spu.getQuantity() : 0).sum();
|
||||
}
|
||||
// 总价为 0 时,说明优惠劵丫根不匹配
|
||||
if (totalPrice == 0) {
|
||||
return "优惠劵不匹配";
|
||||
}
|
||||
// 如果不满足金额
|
||||
if (totalPrice < card.getPriceAvailable()) {
|
||||
return String.format("差 %1$,.2f 元可用优惠劵", (card.getPriceAvailable() - totalPrice) / 100D);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ========== 优惠码 ==========
|
||||
|
||||
public CouponCardReqDTO useCouponCode(Integer userId, String code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package cn.iocoder.mall.promotionservice.service.coupon.bo;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.CouponCardReqDTO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 可用优惠劵 BO
|
||||
*
|
||||
* 注意,如果优惠劵不可用,标记 available = false ,并写明 unavailableReason 原因
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardAvailableBO extends CouponCardReqDTO {
|
||||
|
||||
/**
|
||||
* 是否可用
|
||||
*/
|
||||
private Boolean available;
|
||||
/**
|
||||
* 不可用原因
|
||||
*/
|
||||
private String unavailableReason;
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
package cn.iocoder.mall.promotionservice.service.coupon.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵明细 BO 。
|
||||
*
|
||||
* 主要是,会带上 {@link CouponTemplateBO} 的信息
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardDetailBO implements Serializable {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 优惠劵(码)分组编号
|
||||
*/
|
||||
private Integer templateId;
|
||||
/**
|
||||
* 优惠劵名
|
||||
*/
|
||||
private String title;
|
||||
// /**
|
||||
// * 核销码
|
||||
// */
|
||||
// private String verifyCode;
|
||||
/**
|
||||
* 优惠码状态
|
||||
*
|
||||
* 1-未使用
|
||||
* 2-已使用
|
||||
* 3-已失效
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
// ========== 基本信息 END ==========
|
||||
|
||||
// ========== 领取情况 BEGIN ==========
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 领取类型
|
||||
*
|
||||
* 1 - 用户主动领取
|
||||
* 2 - 后台自动发放
|
||||
*/
|
||||
private Integer takeType;
|
||||
// ========== 领取情况 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
/**
|
||||
* 是否设置满多少金额可用,单位:分
|
||||
*/
|
||||
private Integer priceAvailable;
|
||||
/**
|
||||
* 生效开始时间
|
||||
*/
|
||||
private Date validStartTime;
|
||||
/**
|
||||
* 生效结束时间
|
||||
*/
|
||||
private Date validEndTime;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
/**
|
||||
* 优惠类型
|
||||
*
|
||||
* 1-代金卷
|
||||
* 2-折扣卷
|
||||
*/
|
||||
private Integer preferentialType;
|
||||
/**
|
||||
* 折扣
|
||||
*/
|
||||
private Integer percentOff;
|
||||
/**
|
||||
* 优惠金额,单位:分。
|
||||
*/
|
||||
private Integer priceOff;
|
||||
/**
|
||||
* 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。
|
||||
*
|
||||
* 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。
|
||||
*/
|
||||
private Integer discountPriceLimit;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 使用情况 BEGIN ==========
|
||||
/**
|
||||
* 是否使用
|
||||
*/
|
||||
private Boolean used;
|
||||
/**
|
||||
* 使用订单号
|
||||
*/
|
||||
private Integer usedOrderId;
|
||||
/**
|
||||
* 订单中优惠面值,单位:分
|
||||
*/
|
||||
private Integer usedPrice;
|
||||
/**
|
||||
* 使用时间
|
||||
*/
|
||||
private Date usedTime;
|
||||
|
||||
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
|
||||
|
||||
// ========== 使用情况 END ==========
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
// ========== FROM template 使用规则 BEGIN ==========
|
||||
/**
|
||||
* 可用范围的类型
|
||||
*
|
||||
* 10-全部(ALL):所有可用
|
||||
* 20-部分(PART):部分商品可用,或指定商品可用
|
||||
* 21-部分(PART):部分商品不可用,或指定商品可用
|
||||
* 30-部分(PART):部分分类可用,或指定商品可用
|
||||
* 31-部分(PART):部分分类不可用,或指定商品可用
|
||||
*/
|
||||
private Integer rangeType;
|
||||
/**
|
||||
* 指定商品 / 分类列表,使用逗号分隔商品编号
|
||||
*/
|
||||
private List<Integer> rangeValues;
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package cn.iocoder.mall.promotionservice.service.coupon.bo;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.CouponCardReqDTO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵分页 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardPageBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 优惠劵数组
|
||||
*/
|
||||
private List<CouponCardReqDTO> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package cn.iocoder.mall.promotionservice.service.coupon.bo;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.CouponRpc;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵商品 DTO
|
||||
*
|
||||
* 主要用于 {@link CouponRpc#getCouponCardList(Integer, List)}
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponCardSpuBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 商品 SPU 编号
|
||||
*/
|
||||
private Integer spuId;
|
||||
/**
|
||||
* 商品 SKU 编号
|
||||
*/
|
||||
private Integer skuId;
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer categoryId;
|
||||
/**
|
||||
* 价格
|
||||
*/
|
||||
private Integer price;
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.promotionservice.service.coupon.bo;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.CouponTemplateDateTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.coupon.template.CouponTemplateDateTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.PreferentialTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.RangeTypeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.promotionservice.service.recommend.bo;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.ProductRecommendTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.recommend.ProductRecommendTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.mall.promotionservice.service.recommend.bo;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.enums.ProductRecommendTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.recommend.ProductRecommendTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.promotionservice.service.recommend.bo;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.ProductRecommendTypeEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.recommend.ProductRecommendTypeEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="cn.iocoder.mall.promotionservice.dal.mysql.mapper.coupon.CouponTemplateMapper">
|
||||
|
||||
<update id="updateStatFetchNumIncr" parameterType="Integer">
|
||||
UPDATE coupon_template
|
||||
SET stat_fetch_Num = stat_fetch_Num + 1
|
||||
WHERE id = #{id}
|
||||
AND total > stat_fetch_Num
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.mall.promotionservice.dal.mysql.mapper.activity;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.enums.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.mall.promotion.api.enums.activity.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.activity.PromotionActivityDO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
Reference in New Issue
Block a user