- IT频道
- 时间:2025-09-13 18:30
- 阅读:88
一、功能概述
优惠券通用功能是美团买菜系统中提升用户活跃度和促进消费的重要工具,需要实现以下核心能力:
- 支持多种优惠券类型(满减、折扣、无门槛等)
- 跨品类通用(蔬菜、水果、肉禽等)
- 灵活的发放与使用规则
- 实时计算与优惠叠加控制
二、系统架构设计
1. 核心模块划分
```
优惠券系统
├── 优惠券模板管理
├── 优惠券实例管理
├── 用户优惠券管理
├── 优惠券规则引擎
├── 优惠券核销服务
└── 优惠券统计与分析
```
2. 数据库设计
优惠券模板表(coupon_template)
```
id | template_name | coupon_type | discount_amount | min_order_amount
| start_time | end_time | total_count | available_count
| status | create_time | update_time | description
```
用户优惠券表(user_coupon)
```
id | user_id | coupon_template_id | coupon_code | status
| get_time | use_time | order_id | expire_time
```
优惠券使用范围表(coupon_scope)
```
id | template_id | scope_type | scope_id | category_id
```
三、核心功能实现
1. 优惠券发放
```java
// 发放优惠券服务
public class CouponDistributionService {
public boolean distributeCoupon(Long userId, Long templateId) {
// 1. 校验模板有效性
CouponTemplate template = couponTemplateRepository.findById(templateId)
.orElseThrow(() -> new RuntimeException("优惠券模板不存在"));
// 2. 校验发放条件
if (template.getAvailableCount() <= 0) {
throw new RuntimeException("优惠券已发放完毕");
}
// 3. 创建用户优惠券
UserCoupon userCoupon = new UserCoupon();
userCoupon.setUserId(userId);
userCoupon.setCouponTemplateId(templateId);
userCoupon.setCouponCode(generateCouponCode());
userCoupon.setExpireTime(calculateExpireTime(template));
userCoupon.setStatus(CouponStatus.UNUSED);
// 4. 保存并更新模板库存
userCouponRepository.save(userCoupon);
couponTemplateRepository.decreaseAvailableCount(templateId);
return true;
}
private String generateCouponCode() {
// 生成唯一优惠券码
return "MT" + System.currentTimeMillis() + RandomStringUtils.randomNumeric(4);
}
}
```
2. 优惠券使用规则引擎
```java
public class CouponRuleEngine {
public boolean isCouponApplicable(UserCoupon userCoupon, Order order) {
// 1. 校验有效期
if (LocalDateTime.now().isAfter(userCoupon.getExpireTime())) {
return false;
}
// 2. 校验使用状态
if (userCoupon.getStatus() != CouponStatus.UNUSED) {
return false;
}
// 3. 校验订单金额
CouponTemplate template = getTemplate(userCoupon.getCouponTemplateId());
if (template.getMinOrderAmount() > 0 &&
order.getTotalAmount().compareTo(template.getMinOrderAmount()) < 0) {
return false;
}
// 4. 校验商品范围
if (!checkProductScope(userCoupon.getCouponTemplateId(), order.getProductIds())) {
return false;
}
return true;
}
private boolean checkProductScope(Long templateId, Set productIds) {
// 查询优惠券适用的商品范围
List scopes = couponScopeRepository.findByTemplateId(templateId);
// 无范围限制则全部适用
if (scopes.isEmpty()) {
return true;
}
// 检查订单商品是否在适用范围内
return productIds.stream()
.anyMatch(productId -> scopes.stream()
.anyMatch(scope -> scope.getScopeType() == ScopeType.PRODUCT
&& scope.getScopeId().equals(productId)));
}
}
```
3. 订单优惠计算
```java
public class OrderDiscountCalculator {
public Order calculateDiscount(Order order, UserCoupon userCoupon) {
CouponTemplate template = getTemplate(userCoupon.getCouponTemplateId());
switch (template.getCouponType()) {
case FIXED_DISCOUNT:
// 满减券
if (order.getTotalAmount().compareTo(template.getMinOrderAmount()) >= 0) {
order.setDiscountAmount(template.getDiscountAmount());
}
break;
case PERCENTAGE_DISCOUNT:
// 折扣券
BigDecimal discount = order.getTotalAmount()
.multiply(template.getDiscountRate())
.setScale(2, RoundingMode.DOWN);
order.setDiscountAmount(discount);
break;
case NO_THRESHOLD:
// 无门槛券
order.setDiscountAmount(template.getDiscountAmount());
break;
}
// 更新最终金额
order.setFinalAmount(order.getTotalAmount().subtract(order.getDiscountAmount()));
return order;
}
}
```
四、关键技术实现
1. 优惠券码生成算法
```java
public class CouponCodeGenerator {
private static final String CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final int CODE_LENGTH = 12;
public static String generate() {
Random random = new SecureRandom();
StringBuilder sb = new StringBuilder();
// 前缀标识
sb.append("MT");
// 随机部分
for (int i = 0; i < CODE_LENGTH - 2; i++) {
int index = random.nextInt(CHARS.length());
sb.append(CHARS.charAt(index));
}
// 校验位(简单实现,实际可用更复杂的校验算法)
sb.append(calculateCheckDigit(sb.toString().substring(2)));
return sb.toString();
}
private static char calculateCheckDigit(String code) {
int sum = 0;
for (int i = 0; i < code.length(); i++) {
sum += code.charAt(i) - 0; // 简化处理
}
return CHARS.charAt(sum % CHARS.length());
}
}
```
2. 分布式锁防止超发
```java
public class CouponDistributionWithLock {
@Autowired
private RedisTemplate redisTemplate;
public boolean distributeWithLock(Long userId, Long templateId) {
String lockKey = "coupon:lock:" + templateId;
String requestId = UUID.randomUUID().toString();
try {
// 尝试获取锁,设置过期时间防止死锁
boolean locked = redisTemplate.opsForValue().setIfAbsent(
lockKey, requestId, 10, TimeUnit.SECONDS);
if (!locked) {
throw new RuntimeException("系统繁忙,请稍后再试");
}
// 获取模板信息
CouponTemplate template = couponTemplateRepository.findById(templateId)
.orElseThrow(() -> new RuntimeException("优惠券模板不存在"));
// 检查库存(双重检查)
if (template.getAvailableCount() <= 0) {
throw new RuntimeException("优惠券已发放完毕");
}
// 实际发放逻辑...
// ...
return true;
} finally {
// 释放锁(需校验持有者)
String currentValue = redisTemplate.opsForValue().get(lockKey);
if (requestId.equals(currentValue)) {
redisTemplate.delete(lockKey);
}
}
}
}
```
五、系统优化与扩展
1. 性能优化
- 缓存策略:
- 缓存优惠券模板信息(Redis)
- 缓存用户可用优惠券列表
- 设置合理的缓存过期时间
- 异步处理:
- 优惠券发放采用消息队列异步处理
- 优惠券使用记录异步写入数据库
2. 扩展功能
- 优惠券组合使用:
```java
public class CouponCombinationValidator {
public boolean validateCombination(List coupons, Order order) {
// 实现多张优惠券组合使用规则
// 例如:不能同时使用满减券和折扣券
// ...
}
}
```
- 优惠券分享功能:
```java
public class CouponShareService {
public String shareCoupon(Long userId, Long couponId) {
// 生成分享链接
// 设置分享有效期
// 记录分享关系
// ...
}
}
```
六、测试用例示例
1. 优惠券发放测试
```java
@Test
public void testCouponDistribution() {
// 准备测试数据
CouponTemplate template = new CouponTemplate();
template.setTotalCount(100);
template.setAvailableCount(100);
couponTemplateRepository.save(template);
// 执行发放
boolean result = couponDistributionService.distributeCoupon(1L, template.getId());
// 验证结果
assertTrue(result);
UserCoupon userCoupon = userCouponRepository.findByUserIdAndTemplateId(1L, template.getId());
assertNotNull(userCoupon);
assertEquals(99, couponTemplateRepository.findById(template.getId()).get().getAvailableCount());
}
```
2. 优惠券使用测试
```java
@Test
public void testCouponUsage() {
// 准备测试数据
CouponTemplate template = new CouponTemplate();
template.setCouponType(CouponType.FIXED_DISCOUNT);
template.setDiscountAmount(new BigDecimal("10.00"));
template.setMinOrderAmount(new BigDecimal("50.00"));
couponTemplateRepository.save(template);
UserCoupon userCoupon = new UserCoupon();
userCoupon.setUserId(1L);
userCoupon.setCouponTemplateId(template.getId());
userCoupon.setStatus(CouponStatus.UNUSED);
userCoupon.setExpireTime(LocalDateTime.now().plusDays(1));
userCouponRepository.save(userCoupon);
// 创建订单(满足条件)
Order order = new Order();
order.setUserId(1L);
order.setTotalAmount(new BigDecimal("60.00"));
// 验证优惠券是否可用
boolean applicable = couponRuleEngine.isCouponApplicable(userCoupon, order);
assertTrue(applicable);
// 计算优惠后金额
Order discountedOrder = orderDiscountCalculator.calculateDiscount(order, userCoupon);
assertEquals(new BigDecimal("50.00"), discountedOrder.getFinalAmount());
}
```
七、部署与监控
1. 监控指标:
- 优惠券发放成功率
- 优惠券使用率
- 优惠券核销失败率
- 系统响应时间
2. 告警机制:
- 优惠券库存不足告警
- 优惠券发放失败告警
- 优惠券使用异常告警
3. 日志记录:
- 优惠券发放日志
- 优惠券使用日志
- 优惠券状态变更日志
通过以上设计和实现,美团买菜系统可以构建一个灵活、高效、可扩展的优惠券通用功能,支持各种营销活动,提升用户购物体验和平台转化率。
全部评论(0)
推荐阅读
![]()
- IT频道
- 时间:2026-05-31 03:05
- 阅读:1
![]()
- IT频道
- 时间:2026-05-31 03:00
- 阅读:1
![]()
- IT频道
- 时间:2026-05-31 02:55
- 阅读:1
![]()
- IT频道
- 时间:2026-05-31 02:50
- 阅读:1
![]()
- IT频道
- 时间:2026-05-31 02:45
- 阅读:1