feat(pricing): 添加券码管理和使用功能

- 新增券码批次配置和券码实体
- 实现券码创建、领取、使用等接口
- 添加券码状态和优惠类型枚举
- 优化价格计算逻辑,支持券码优惠
- 新增优惠检测和应用相关功能
This commit is contained in:
2025-08-21 09:35:08 +08:00
parent e9035af542
commit eb327723cd
52 changed files with 2572 additions and 455 deletions

View File

@@ -3,7 +3,7 @@ package com.ycwl.basic.pricing.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 优惠券使用结果DTO
@@ -29,7 +29,7 @@ public class CouponUseResult {
/**
* 使用时间
*/
private LocalDateTime useTime;
private Date useTime;
/**
* 优惠金额

View File

@@ -0,0 +1,53 @@
package com.ycwl.basic.pricing.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* 优惠组合结果
*/
@Data
public class DiscountCombinationResult {
/**
* 原始金额
*/
private BigDecimal originalAmount;
/**
* 最终金额
*/
private BigDecimal finalAmount;
/**
* 总优惠金额
*/
private BigDecimal totalDiscountAmount;
/**
* 应用的优惠列表(按优先级排序)
*/
private List<DiscountResult> appliedDiscounts;
/**
* 可用但未应用的优惠列表
*/
private List<DiscountInfo> availableDiscounts;
/**
* 优惠详情列表(用于展示)
*/
private List<DiscountDetail> discountDetails;
/**
* 计算是否成功
*/
private Boolean success;
/**
* 错误信息(如果success为false)
*/
private String errorMessage;
}

View File

@@ -44,7 +44,7 @@ public class DiscountDetail {
detail.setDiscountName("限时立减");
detail.setDiscountAmount(discountAmount);
detail.setDescription("限时优惠,立即享受");
detail.setSortOrder(1); // 限时立减排在最前
detail.setSortOrder(2); // 限时立减排在券码后
return detail;
}
@@ -57,7 +57,20 @@ public class DiscountDetail {
detail.setDiscountName(couponName);
detail.setDiscountAmount(discountAmount);
detail.setDescription("优惠券减免");
detail.setSortOrder(2); // 优惠券排在限时立减后面
detail.setSortOrder(3); // 优惠券排在限时立减后面
return detail;
}
/**
* 创建券码折扣明细
*/
public static DiscountDetail createVoucherDiscount(String voucherCode, String discountTypeName, BigDecimal discountAmount) {
DiscountDetail detail = new DiscountDetail();
detail.setDiscountType("VOUCHER");
detail.setDiscountName("券码优惠");
detail.setDiscountAmount(discountAmount);
detail.setDescription(String.format("券码 %s - %s", voucherCode, discountTypeName));
detail.setSortOrder(1); // 券码优先级最高,排在最前面
return detail;
}
@@ -70,7 +83,7 @@ public class DiscountDetail {
detail.setDiscountName("一口价优惠");
detail.setDiscountAmount(discountAmount);
detail.setDescription("一口价购买更优惠");
detail.setSortOrder(3); // 一口价排在最后
detail.setSortOrder(4); // 一口价排在最后
return detail;
}
}

View File

@@ -0,0 +1,53 @@
package com.ycwl.basic.pricing.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* 优惠检测上下文
*/
@Data
public class DiscountDetectionContext {
/**
* 用户ID
*/
private Long userId;
/**
* 用户faceId
*/
private Long faceId;
/**
* 景区ID
*/
private Long scenicId;
/**
* 商品列表
*/
private List<ProductItem> products;
/**
* 当前金额
*/
private BigDecimal currentAmount;
/**
* 用户主动输入的券码
*/
private String voucherCode;
/**
* 是否自动使用优惠券
*/
private Boolean autoUseCoupon;
/**
* 是否自动使用券码
*/
private Boolean autoUseVoucher;
}

View File

@@ -0,0 +1,82 @@
package com.ycwl.basic.pricing.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
* 优惠信息DTO
*/
@Data
public class DiscountInfo {
/**
* 优惠ID
*/
private Long discountId;
/**
* 优惠类型(COUPON, VOUCHER等)
*/
private String discountType;
/**
* 优惠名称
*/
private String discountName;
/**
* 优惠描述
*/
private String discountDescription;
/**
* 优惠金额
*/
private BigDecimal discountAmount;
/**
* 原始优惠值(用于百分比折扣等)
*/
private BigDecimal originalValue;
/**
* 优惠值类型(PERCENTAGE, FIXED_AMOUNT等)
*/
private String valueType;
/**
* 最小消费金额限制
*/
private BigDecimal minAmount;
/**
* 最大优惠金额限制
*/
private BigDecimal maxDiscount;
/**
* 优惠提供者类型
*/
private String providerType;
/**
* 优惠优先级
*/
private Integer priority;
/**
* 是否可与其他优惠叠加
*/
private Boolean stackable;
/**
* 券码(如果是voucher类型)
*/
private String voucherCode;
/**
* 优惠券ID(如果是coupon类型)
*/
private Long couponId;
}

View File

@@ -0,0 +1,43 @@
package com.ycwl.basic.pricing.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* 优惠应用结果
*/
@Data
public class DiscountResult {
/**
* 应用的优惠信息
*/
private DiscountInfo discountInfo;
/**
* 实际优惠金额
*/
private BigDecimal actualDiscountAmount;
/**
* 应用后的金额
*/
private BigDecimal finalAmount;
/**
* 是否成功应用
*/
private Boolean success;
/**
* 失败原因(如果success为false)
*/
private String failureReason;
/**
* 影响的商品项(用于商品级别的优惠)
*/
private List<ProductItem> affectedProducts;
}

View File

@@ -24,4 +24,29 @@ public class PriceCalculationRequest {
* 是否自动使用优惠券
*/
private Boolean autoUseCoupon = true;
/**
* 用户输入的券码
*/
private String voucherCode;
/**
* 景区ID(用于券码验证)
*/
private Long scenicId;
/**
* 用户faceId(用于券码领取资格验证)
*/
private Long faceId;
/**
* 是否自动使用券码优惠
*/
private Boolean autoUseVoucher = true;
/**
* 是否仅预览优惠(不实际使用)
*/
private Boolean previewOnly = false;
}

View File

@@ -37,10 +37,20 @@ public class PriceCalculationResult {
private CouponInfo usedCoupon;
/**
* 折扣明细列表(包含限时立减、优惠券、一口价等)
* 使用的券码信息
*/
private VoucherInfo usedVoucher;
/**
* 折扣明细列表(包含限时立减、优惠券、券码、一口价等)
*/
private List<DiscountDetail> discountDetails;
/**
* 可用但未使用的优惠列表(预览时使用)
*/
private List<DiscountInfo> availableDiscounts;
/**
* 商品明细列表
*/

View File

@@ -0,0 +1,84 @@
package com.ycwl.basic.pricing.dto;
import com.ycwl.basic.pricing.enums.VoucherDiscountType;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 券码信息DTO
*/
@Data
public class VoucherInfo {
/**
* 券码ID
*/
private Long voucherId;
/**
* 券码
*/
private String voucherCode;
/**
* 批次ID
*/
private Long batchId;
/**
* 批次名称
*/
private String batchName;
/**
* 景区ID
*/
private Long scenicId;
/**
* 推客ID
*/
private Long brokerId;
/**
* 优惠类型
*/
private VoucherDiscountType discountType;
/**
* 优惠值
*/
private BigDecimal discountValue;
/**
* 实际优惠金额
*/
private BigDecimal actualDiscountAmount;
/**
* 状态
*/
private Integer status;
/**
* 领取时间
*/
private Date claimedTime;
/**
* 使用时间
*/
private Date usedTime;
/**
* 是否可用
*/
private Boolean available;
/**
* 不可用原因
*/
private String unavailableReason;
}

View File

@@ -0,0 +1,15 @@
package com.ycwl.basic.pricing.dto.req;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class VoucherBatchCreateReq {
private String batchName;
private Long scenicId;
private Long brokerId;
private Integer discountType;
private BigDecimal discountValue;
private Integer totalCount;
}

View File

@@ -0,0 +1,14 @@
package com.ycwl.basic.pricing.dto.req;
import com.ycwl.basic.model.common.BaseQueryParameterReq;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class VoucherBatchQueryReq extends BaseQueryParameterReq {
private Long scenicId;
private Long brokerId;
private Integer status;
private String batchName;
}

View File

@@ -0,0 +1,10 @@
package com.ycwl.basic.pricing.dto.req;
import lombok.Data;
@Data
public class VoucherClaimReq {
private Long scenicId;
private Long brokerId;
private Long faceId;
}

View File

@@ -0,0 +1,15 @@
package com.ycwl.basic.pricing.dto.req;
import com.ycwl.basic.model.common.BaseQueryParameterReq;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class VoucherCodeQueryReq extends BaseQueryParameterReq {
private Long batchId;
private Long scenicId;
private Long faceId;
private Integer status;
private String code;
}

View File

@@ -0,0 +1,25 @@
package com.ycwl.basic.pricing.dto.resp;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class VoucherBatchResp {
private Long id;
private String batchName;
private Long scenicId;
private Long brokerId;
private Integer discountType;
private String discountTypeName;
private BigDecimal discountValue;
private Integer totalCount;
private Integer usedCount;
private Integer claimedCount;
private Integer availableCount;
private Integer status;
private String statusName;
private Date createTime;
private Long createBy;
}

View File

@@ -0,0 +1,15 @@
package com.ycwl.basic.pricing.dto.resp;
import lombok.Data;
@Data
public class VoucherBatchStatsResp {
private Long batchId;
private String batchName;
private Integer totalCount;
private Integer claimedCount;
private Integer usedCount;
private Integer availableCount;
private Double claimedRate;
private Double usedRate;
}

View File

@@ -0,0 +1,27 @@
package com.ycwl.basic.pricing.dto.resp;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class VoucherCodeResp {
private Long id;
private Long batchId;
private String batchName;
private Long scenicId;
private String code;
private Integer status;
private String statusName;
private Long faceId;
private Date claimedTime;
private Date usedTime;
private String remark;
private Date createTime;
private Integer discountType;
private String discountTypeName;
private String discountDescription;
private BigDecimal discountValue;
}