美团买菜优惠券系统设计:功能、数据库、实现及扩展优化方案
分类:IT频道
时间:2026-02-22 00:15
浏览:15
概述
一、功能概述 美团买菜系统的优惠券通用功能需要实现以下核心能力: 1.支持多种优惠券类型(满减、折扣、无门槛等) 2.支持多品类通用或特定品类限制 3.支持多商户/平台级优惠券 4.支持有效期管理 5.支持使用条件限制(如最低消费金额) 6.支持用户领取、使用、查询等全生命
内容
一、功能概述
美团买菜系统的优惠券通用功能需要实现以下核心能力:
1. 支持多种优惠券类型(满减、折扣、无门槛等)
2. 支持多品类通用或特定品类限制
3. 支持多商户/平台级优惠券
4. 支持有效期管理
5. 支持使用条件限制(如最低消费金额)
6. 支持用户领取、使用、查询等全生命周期管理
二、数据库设计
1. 优惠券表(coupon)
```sql
CREATE TABLE `coupon` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 优惠券ID,
`coupon_type` tinyint NOT NULL COMMENT 优惠券类型(1:满减,2:折扣,3:无门槛),
`name` varchar(100) NOT NULL COMMENT 优惠券名称,
`description` varchar(500) DEFAULT NULL COMMENT 优惠券描述,
`discount_amount` decimal(10,2) DEFAULT NULL COMMENT 减免金额(满减/无门槛用),
`discount_rate` decimal(5,2) DEFAULT NULL COMMENT 折扣率(折扣用),
`min_order_amount` decimal(10,2) DEFAULT NULL COMMENT 最低使用金额,
`valid_start_time` datetime NOT NULL COMMENT 有效期开始时间,
`valid_end_time` datetime NOT NULL COMMENT 有效期结束时间,
`total_count` int NOT NULL COMMENT 总发放数量,
`remaining_count` int NOT NULL COMMENT 剩余数量,
`status` tinyint NOT NULL COMMENT 状态(1:有效,2:无效,3:已过期),
`create_time` datetime NOT NULL COMMENT 创建时间,
`update_time` datetime NOT NULL COMMENT 更新时间,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=优惠券表;
```
2. 优惠券范围表(coupon_scope)
```sql
CREATE TABLE `coupon_scope` (
`id` bigint NOT NULL AUTO_INCREMENT,
`coupon_id` bigint NOT NULL COMMENT 优惠券ID,
`scope_type` tinyint NOT NULL COMMENT 范围类型(1:全品类,2:指定品类,3:指定商品),
`scope_ids` varchar(1000) DEFAULT NULL COMMENT 范围ID(品类ID或商品ID列表,JSON格式),
PRIMARY KEY (`id`),
KEY `idx_coupon_id` (`coupon_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=优惠券范围表;
```
3. 用户优惠券表(user_coupon)
```sql
CREATE TABLE `user_coupon` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT 用户ID,
`coupon_id` bigint NOT NULL COMMENT 优惠券ID,
`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 过期时间,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_coupon_id` (`coupon_id`),
KEY `idx_user_status` (`user_id`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=用户优惠券表;
```
三、核心功能实现
1. 优惠券发放
```java
public class CouponService {
@Autowired
private CouponMapper couponMapper;
@Autowired
private UserCouponMapper userCouponMapper;
/
* 发放优惠券给用户
* @param couponId 优惠券ID
* @param userId 用户ID
* @param quantity 发放数量(1或多个)
* @return 发放结果
*/
public Result issueCoupon(Long couponId, Long userId, Integer quantity) {
// 1. 校验优惠券是否存在且有效
Coupon coupon = couponMapper.selectById(couponId);
if (coupon == null || coupon.getStatus() != 1) {
return Result.fail("优惠券不存在或已失效");
}
// 2. 检查剩余数量
if (coupon.getRemainingCount() < quantity) {
return Result.fail("优惠券数量不足");
}
// 3. 发放优惠券给用户
Date now = new Date();
Date expireTime = calculateExpireTime(coupon);
List userCoupons = new ArrayList<>();
for (int i = 0; i < quantity; i++) {
UserCoupon userCoupon = new UserCoupon();
userCoupon.setUserId(userId);
userCoupon.setCouponId(couponId);
userCoupon.setStatus(1); // 未使用
userCoupon.setGetTime(now);
userCoupon.setExpireTime(expireTime);
userCoupons.add(userCoupon);
}
// 批量插入
userCouponMapper.batchInsert(userCoupons);
// 4. 更新优惠券剩余数量
couponMapper.decreaseRemainingCount(couponId, quantity);
return Result.success("发放成功");
}
private Date calculateExpireTime(Coupon coupon) {
// 根据优惠券有效期计算过期时间
if (coupon.getValidEndTime().before(new Date())) {
throw new RuntimeException("优惠券已过期");
}
return coupon.getValidEndTime();
}
}
```
2. 优惠券查询(用户可用优惠券列表)
```java
public List getAvailableCoupons(Long userId, BigDecimal orderAmount, Long categoryId) {
// 1. 查询用户未使用且未过期的优惠券
List userCoupons = userCouponMapper.selectByUserIdAndStatus(userId, 1);
// 2. 过滤符合条件的优惠券
return userCoupons.stream()
.map(userCoupon -> {
Coupon coupon = couponMapper.selectById(userCoupon.getCouponId());
return new UserCouponDTO(userCoupon, coupon);
})
.filter(dto -> {
// 检查有效期
Date now = new Date();
if (dto.getExpireTime().before(now)) {
return false;
}
// 检查最低消费金额
if (dto.getMinOrderAmount() != null && orderAmount.compareTo(dto.getMinOrderAmount()) < 0) {
return false;
}
// 检查品类限制
if (categoryId != null) {
return checkCategoryScope(dto.getCouponId(), categoryId);
}
return true;
})
.collect(Collectors.toList());
}
private boolean checkCategoryScope(Long couponId, Long categoryId) {
CouponScope scope = couponScopeMapper.selectByCouponId(couponId);
if (scope == null) {
return true; // 无范围限制
}
if (scope.getScopeType() == 1) { // 全品类
return true;
}
if (scope.getScopeType() == 2) { // 指定品类
try {
List scopeIds = JSON.parseArray(scope.getScopeIds(), Long.class);
return scopeIds.contains(categoryId);
} catch (Exception e) {
return false;
}
}
return false;
}
```
3. 优惠券使用(订单结算时)
```java
public Result useCoupon(Long userId, Long orderId, Long userCouponId) {
// 1. 校验用户优惠券
UserCoupon userCoupon = userCouponMapper.selectById(userCouponId);
if (userCoupon == null || !userCoupon.getUserId().equals(userId) || userCoupon.getStatus() != 1) {
return Result.fail("优惠券不可用");
}
// 2. 校验优惠券是否过期
if (userCoupon.getExpireTime().before(new Date())) {
return Result.fail("优惠券已过期");
}
// 3. 获取优惠券详情
Coupon coupon = couponMapper.selectById(userCoupon.getCouponId());
// 4. 更新用户优惠券状态
userCoupon.setStatus(2); // 已使用
userCoupon.setUseTime(new Date());
userCoupon.setOrderId(orderId);
userCouponMapper.updateById(userCoupon);
// 5. 返回优惠券抵扣信息
CouponDiscountDTO discount = new CouponDiscountDTO();
discount.setCouponId(coupon.getId());
discount.setCouponName(coupon.getName());
switch (coupon.getCouponType()) {
case 1: // 满减
discount.setDiscountType(1);
discount.setDiscountAmount(coupon.getDiscountAmount());
break;
case 2: // 折扣
discount.setDiscountType(2);
discount.setDiscountRate(coupon.getDiscountRate());
break;
case 3: // 无门槛
discount.setDiscountType(3);
discount.setDiscountAmount(coupon.getDiscountAmount());
break;
}
return Result.success(discount);
}
```
4. 优惠券计算(订单金额计算)
```java
public BigDecimal calculateOrderAmount(BigDecimal originalAmount, CouponDiscountDTO couponDiscount) {
if (couponDiscount == null) {
return originalAmount;
}
BigDecimal finalAmount = originalAmount;
switch (couponDiscount.getDiscountType()) {
case 1: // 满减
finalAmount = originalAmount.subtract(couponDiscount.getDiscountAmount());
break;
case 2: // 折扣
finalAmount = originalAmount.multiply(couponDiscount.getDiscountRate().divide(new BigDecimal(100)));
break;
case 3: // 无门槛
finalAmount = originalAmount.subtract(couponDiscount.getDiscountAmount());
break;
}
return finalAmount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : finalAmount;
}
```
四、扩展功能考虑
1. 优惠券叠加使用:
- 添加规则表定义哪些优惠券可以叠加使用
- 在结算时检查并应用多张优惠券
2. 优惠券分享功能:
- 生成分享链接或二维码
- 记录分享关系链
3. 优惠券核销:
- 线下场景核销接口
- 核销记录查询
4. 优惠券统计与分析:
- 发放数量、使用数量、核销率等统计
- 用户领券行为分析
5. 优惠券防刷:
- 用户领券频率限制
- 设备指纹校验
五、性能优化建议
1. 缓存优化:
- 使用Redis缓存热门优惠券信息
- 缓存用户可用优惠券列表
2. 异步处理:
- 优惠券发放采用异步消息队列处理
- 优惠券过期检查使用定时任务批量处理
3. 数据库优化:
- 对常用查询字段添加索引
- 考虑分表策略应对大数据量
4. 接口限流:
- 对领券接口进行限流,防止恶意刷券
六、安全考虑
1. 优惠券代码生成采用唯一且不可预测的算法
2. 接口调用添加权限校验
3. 关键操作记录操作日志
4. 防止优惠券ID篡改(使用签名验证)
以上方案提供了美团买菜系统优惠券通用功能的核心实现思路,可根据实际业务需求进行调整和扩展。
评论