美团买菜系统优惠券设计:功能、架构、风控及性能优化全解析
分类:IT频道
时间:2026-02-01 12:00
浏览:30
概述
一、功能概述 美团买菜系统的优惠券通用功能需要实现以下核心能力: 1.支持多种类型优惠券(满减券、折扣券、无门槛券等) 2.跨品类商品通用(生鲜、日用品等) 3.灵活的发放与使用规则 4.有效的防刷与风控机制 5.清晰的用户展示与使用流程 二、系统架构设计 1.核
内容
一、功能概述
美团买菜系统的优惠券通用功能需要实现以下核心能力:
1. 支持多种类型优惠券(满减券、折扣券、无门槛券等)
2. 跨品类商品通用(生鲜、日用品等)
3. 灵活的发放与使用规则
4. 有效的防刷与风控机制
5. 清晰的用户展示与使用流程
二、系统架构设计
1. 核心模块划分
```
优惠券系统
├── 优惠券模板管理
├── 优惠券实例管理
├── 发放规则引擎
├── 使用规则引擎
├── 用户优惠券管理
├── 优惠券风控系统
└── 优惠券统计与分析
```
2. 数据库设计
优惠券模板表(coupon_template)
```sql
CREATE TABLE coupon_template (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL COMMENT 优惠券名称,
type TINYINT NOT NULL COMMENT 1-满减券 2-折扣券 3-无门槛券,
discount_value DECIMAL(10,2) NOT NULL COMMENT 优惠金额/折扣率,
min_order_amount DECIMAL(10,2) DEFAULT NULL COMMENT 最低订单金额(满减券用),
valid_days INT NOT NULL COMMENT 有效期天数,
scope TINYINT NOT NULL COMMENT 1-全品类 2-指定品类 3-指定商品,
total_count INT NOT NULL COMMENT 总发放量,
remaining_count INT NOT NULL COMMENT 剩余量,
status TINYINT NOT NULL COMMENT 1-有效 0-失效,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL
);
```
用户优惠券表(user_coupon)
```sql
CREATE TABLE user_coupon (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL COMMENT 用户ID,
template_id BIGINT NOT NULL COMMENT 模板ID,
coupon_no VARCHAR(32) NOT NULL COMMENT 优惠券编号,
status TINYINT NOT NULL COMMENT 1-未使用 2-已使用 3-已过期,
get_time DATETIME NOT NULL COMMENT 领取时间,
use_time DATETIME DEFAULT NULL COMMENT 使用时间,
order_id BIGINT DEFAULT NULL COMMENT 关联订单ID,
expire_time DATETIME NOT NULL COMMENT 过期时间,
INDEX idx_user (user_id),
INDEX idx_status (status),
INDEX idx_expire (expire_time)
);
```
三、核心功能实现
1. 优惠券发放实现
```java
// 发放优惠券服务
public class CouponDistributionService {
@Autowired
private CouponTemplateRepository templateRepository;
@Autowired
private UserCouponRepository userCouponRepository;
@Transactional
public void distributeCoupon(Long templateId, List userIds) {
// 1. 检查模板是否存在且有效
CouponTemplate template = templateRepository.findById(templateId)
.orElseThrow(() -> new RuntimeException("优惠券模板不存在"));
if (template.getRemainingCount() <= 0 || template.getStatus() != 1) {
throw new RuntimeException("优惠券模板不可用");
}
// 2. 为每个用户生成优惠券实例
Date now = new Date();
Date expireTime = new Date(now.getTime() + template.getValidDays() * 24 * 60 * 60 * 1000);
List coupons = userIds.stream().map(userId -> {
UserCoupon coupon = new UserCoupon();
coupon.setUserId(userId);
coupon.setTemplateId(templateId);
coupon.setCouponNo(generateCouponNo());
coupon.setStatus(1); // 未使用
coupon.setGetTime(now);
coupon.setExpireTime(expireTime);
return coupon;
}).collect(Collectors.toList());
// 3. 批量保存并更新模板剩余数量
userCouponRepository.saveAll(coupons);
template.setRemainingCount(template.getRemainingCount() - userIds.size());
templateRepository.save(template);
}
private String generateCouponNo() {
// 生成唯一优惠券编号
return UUID.randomUUID().toString().replace("-", "").substring(0, 16);
}
}
```
2. 优惠券使用规则校验
```java
// 优惠券使用规则校验服务
public class CouponUsageValidator {
@Autowired
private CouponTemplateRepository templateRepository;
@Autowired
private UserCouponRepository userCouponRepository;
public void validateCouponUsage(Long userId, Long couponId, BigDecimal orderAmount,
List categoryIds, List productIds) {
// 1. 检查优惠券是否存在且属于用户
UserCoupon userCoupon = userCouponRepository.findByIdAndUserId(couponId, userId)
.orElseThrow(() -> new RuntimeException("优惠券不存在或不属于当前用户"));
if (userCoupon.getStatus() != 1) { // 未使用
throw new RuntimeException("优惠券不可用");
}
if (userCoupon.getExpireTime().before(new Date())) {
throw new RuntimeException("优惠券已过期");
}
// 2. 检查优惠券模板规则
CouponTemplate template = templateRepository.findById(userCoupon.getTemplateId())
.orElseThrow(() -> new RuntimeException("优惠券模板不存在"));
// 检查最低订单金额
if (template.getMinOrderAmount() != null && orderAmount.compareTo(template.getMinOrderAmount()) < 0) {
throw new RuntimeException("订单金额不满足最低要求");
}
// 检查适用范围
switch (template.getScope()) {
case 1: // 全品类
break;
case 2: // 指定品类
// 需要查询模板关联的品类并校验
if (!isCategoriesMatch(template.getId(), categoryIds)) {
throw new RuntimeException("优惠券不适用于当前商品品类");
}
break;
case 3: // 指定商品
// 需要查询模板关联的商品并校验
if (!isProductsMatch(template.getId(), productIds)) {
throw new RuntimeException("优惠券不适用于当前商品");
}
break;
}
}
// 其他校验方法...
}
```
3. 优惠券计算服务
```java
// 优惠券计算服务
public class CouponCalculator {
public BigDecimal calculateDiscount(BigDecimal orderAmount, CouponTemplate template) {
switch (template.getType()) {
case 1: // 满减券
return template.getDiscountValue();
case 2: // 折扣券
return orderAmount.multiply(BigDecimal.valueOf(template.getDiscountValue()))
.setScale(2, RoundingMode.DOWN);
case 3: // 无门槛券
return template.getDiscountValue();
default:
return BigDecimal.ZERO;
}
}
public BigDecimal calculateFinalAmount(BigDecimal orderAmount, CouponTemplate template) {
BigDecimal discount = calculateDiscount(orderAmount, template);
return orderAmount.subtract(discount).max(BigDecimal.ZERO);
}
}
```
四、前端交互流程
1. 优惠券领取流程
- 用户进入优惠券中心 → 查看可领取优惠券 → 点击领取 → 后端生成优惠券实例 → 返回领取结果
2. 优惠券使用流程
- 用户选择商品加入购物车 → 进入结算页 → 系统自动匹配可用优惠券 → 用户选择优惠券 → 系统校验并计算最终金额 → 提交订单
3. 优惠券展示规则
- 未使用:按有效期倒序排列
- 已使用:展示使用时间和订单信息
- 已过期:展示过期时间
五、风控与防刷机制
1. 发放限制
- 同一用户同种优惠券领取上限
- 每日/每周领取总量限制
- 设备/IP限制
2. 使用限制
- 防止优惠券叠加使用(除非特别设计)
- 防止订单拆分使用
- 防止异常退款后重复使用
3. 监控与报警
- 实时监控优惠券领取和使用情况
- 异常行为自动报警(如短时间内大量领取)
- 定期审计优惠券使用数据
六、性能优化建议
1. 缓存策略
- 热门优惠券模板缓存
- 用户可用优惠券缓存
- 优惠券规则校验结果缓存
2. 异步处理
- 优惠券发放采用消息队列异步处理
- 优惠券使用统计异步更新
3. 数据库优化
- 用户优惠券表按状态和过期时间分区
- 热门查询字段添加索引
- 定期归档过期优惠券数据
七、测试用例示例
1. 正常场景
- 领取并使用满减券
- 领取并使用折扣券
- 领取并使用无门槛券
2. 边界场景
- 订单金额刚好等于满减门槛
- 订单金额略低于满减门槛
- 优惠券刚好过期时使用
3. 异常场景
- 使用已使用的优惠券
- 使用不存在的优惠券
- 使用其他用户的优惠券
- 叠加使用不可叠加的优惠券
通过以上设计,可以实现一个功能完善、性能优良的美团买菜系统优惠券通用功能,满足业务需求并保证系统稳定性。
评论