叮咚买菜优惠券系统设计:涵盖功能、数据库、逻辑及前端交互设计
分类:IT频道
时间:2026-02-21 19:20
浏览:16
概述
一、功能概述 优惠券管理是电商系统中重要的营销工具,叮咚买菜系统的优惠券管理功能应包括优惠券创建、发放、使用、统计等全生命周期管理,支持多种优惠券类型和发放方式。 二、核心功能模块 1.优惠券类型管理 -满减券:满X元减Y元 -折扣券:订单享受X折优惠 -免运费券:免
内容
一、功能概述
优惠券管理是电商系统中重要的营销工具,叮咚买菜系统的优惠券管理功能应包括优惠券创建、发放、使用、统计等全生命周期管理,支持多种优惠券类型和发放方式。
二、核心功能模块
1. 优惠券类型管理
- 满减券:满X元减Y元
- 折扣券:订单享受X折优惠
- 免运费券:免除配送费用
- 品类专用券:针对特定商品类别的优惠券
- 新人专享券:仅限新用户使用
- 限时特惠券:指定时间段内有效
2. 优惠券创建与配置
```java
// 优惠券实体类示例
public class CouponTemplate {
private Long id;
private String name; // 优惠券名称
private String description; // 描述
private Integer type; // 类型(1:满减,2:折扣,3:免运费...)
private BigDecimal discountAmount; // 优惠金额
private BigDecimal minOrderAmount; // 最低订单金额
private BigDecimal discountRate; // 折扣率(仅折扣券使用)
private Date startTime; // 生效时间
private Date endTime; // 失效时间
private Integer totalCount; // 发放总量
private Integer remainingCount; // 剩余数量
private Integer usageLimit; // 每人限领数量
private String适用范围; // ALL/CATEGORY/PRODUCT
private List categoryIds; // 适用品类ID
private List productIds; // 适用商品ID
// getters and setters...
}
```
3. 优惠券发放方式
- 系统自动发放:
- 新用户注册赠送
- 用户生日赠送
- 特定节日发放
- 用户主动领取:
- 优惠券中心领取
- 活动页面领取
- 分享链接领取
- 后台手动发放:
- 针对特定用户发放
- 批量导入发放
4. 优惠券使用流程
1. 用户选择商品加入购物车
2. 进入结算页面时系统自动匹配可用优惠券
3. 用户选择使用或放弃使用优惠券
4. 系统验证优惠券有效性
5. 计算最终订单金额
6. 更新优惠券状态为已使用
5. 优惠券状态管理
- 未使用:用户已领取但未使用
- 已使用:订单结算时已使用
- 已过期:超过有效期未使用
- 已作废:管理员手动作废
三、数据库设计
```sql
-- 优惠券模板表
CREATE TABLE coupon_template (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
description VARCHAR(500),
type TINYINT NOT NULL COMMENT 1:满减,2:折扣,3:免运费,
discount_amount DECIMAL(10,2),
min_order_amount DECIMAL(10,2),
discount_rate DECIMAL(5,2),
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
total_count INT NOT NULL,
remaining_count INT NOT NULL,
usage_limit INT DEFAULT 1,
scope VARCHAR(20) NOT NULL COMMENT ALL/CATEGORY/PRODUCT,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL
);
-- 优惠券模板关联品类表
CREATE TABLE coupon_template_category (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
template_id BIGINT NOT NULL,
category_id BIGINT NOT NULL,
FOREIGN KEY (template_id) REFERENCES coupon_template(id)
);
-- 优惠券模板关联商品表
CREATE TABLE coupon_template_product (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
template_id BIGINT NOT NULL,
product_id BIGINT NOT NULL,
FOREIGN KEY (template_id) REFERENCES coupon_template(id)
);
-- 用户优惠券表
CREATE TABLE user_coupon (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
template_id BIGINT NOT NULL,
coupon_code VARCHAR(50) NOT NULL UNIQUE,
status TINYINT NOT NULL COMMENT 0:未使用,1:已使用,2:已过期,3:已作废,
order_id BIGINT COMMENT 关联订单ID,
get_time DATETIME NOT NULL,
use_time DATETIME,
expire_time DATETIME NOT NULL,
FOREIGN KEY (template_id) REFERENCES coupon_template(id)
);
```
四、关键业务逻辑实现
1. 优惠券发放服务
```java
@Service
public class CouponService {
@Autowired
private CouponTemplateRepository templateRepository;
@Autowired
private UserCouponRepository userCouponRepository;
@Transactional
public void distributeCoupon(Long templateId, List userIds) {
CouponTemplate template = templateRepository.findById(templateId)
.orElseThrow(() -> new RuntimeException("优惠券模板不存在"));
if (template.getRemainingCount() <= 0) {
throw new RuntimeException("优惠券已发放完毕");
}
Date now = new Date();
List coupons = new ArrayList<>();
for (Long userId : userIds) {
// 检查用户是否已达到领取上限
long usedCount = userCouponRepository.countByUserIdAndTemplateIdAndStatus(
userId, templateId, 0); // 0表示未使用
if (usedCount >= template.getUsageLimit()) {
continue; // 跳过已达上限的用户
}
UserCoupon coupon = new UserCoupon();
coupon.setUserId(userId);
coupon.setTemplateId(templateId);
coupon.setCouponCode(generateCouponCode());
coupon.setStatus(0); // 未使用
coupon.setGetTime(now);
coupon.setExpireTime(template.getEndTime());
coupons.add(coupon);
}
if (!coupons.isEmpty()) {
userCouponRepository.saveAll(coupons);
template.setRemainingCount(template.getRemainingCount() - coupons.size());
templateRepository.save(template);
}
}
private String generateCouponCode() {
// 生成唯一优惠券码逻辑
return UUID.randomUUID().toString().replace("-", "").substring(0, 10).toUpperCase();
}
}
```
2. 优惠券匹配与使用服务
```java
@Service
public class OrderService {
@Autowired
private UserCouponRepository userCouponRepository;
@Autowired
private CouponTemplateRepository templateRepository;
public List findAvailableCoupons(Long userId, BigDecimal orderAmount, List categoryIds) {
Date now = new Date();
// 查询用户所有未使用且未过期的优惠券
List availableCoupons = userCouponRepository.findByUserIdAndStatusAndExpireTimeAfter(
userId, 0, now);
return availableCoupons.stream()
.filter(coupon -> {
CouponTemplate template = templateRepository.findById(coupon.getTemplateId())
.orElse(null);
if (template == null) return false;
// 检查最低订单金额
if (template.getMinOrderAmount() != null &&
orderAmount.compareTo(template.getMinOrderAmount()) < 0) {
return false;
}
// 检查适用范围
if ("ALL".equals(template.getScope())) {
return true;
} else if ("CATEGORY".equals(template.getScope())) {
// 检查订单中是否包含适用品类的商品
// 这里简化处理,实际应根据订单商品品类判断
return !template.getCategoryIds().isEmpty();
} else if ("PRODUCT".equals(template.getScope())) {
// 检查订单中是否包含适用商品
// 这里简化处理,实际应根据订单商品判断
return !template.getProductIds().isEmpty();
}
return false;
})
.collect(Collectors.toList());
}
@Transactional
public Order createOrderWithCoupon(OrderCreateRequest request, Long couponId) {
// 验证优惠券有效性
UserCoupon userCoupon = userCouponRepository.findByIdAndUserIdAndStatus(
couponId, request.getUserId(), 0) // 0表示未使用
.orElseThrow(() -> new RuntimeException("优惠券无效或已使用"));
CouponTemplate template = templateRepository.findById(userCoupon.getTemplateId())
.orElseThrow(() -> new RuntimeException("优惠券模板不存在"));
// 验证最低订单金额
if (template.getMinOrderAmount() != null &&
request.getTotalAmount().compareTo(template.getMinOrderAmount()) < 0) {
throw new RuntimeException("订单金额不满足优惠券使用条件");
}
// 计算优惠后金额
BigDecimal finalAmount = request.getTotalAmount();
if (template.getType() == 1) { // 满减券
finalAmount = finalAmount.subtract(template.getDiscountAmount());
} else if (template.getType() == 2) { // 折扣券
finalAmount = finalAmount.multiply(template.getDiscountRate().divide(new BigDecimal("100")));
} else if (template.getType() == 3) { // 免运费券
// 假设运费在totalAmount中包含,实际应根据运费计算
// 这里简化处理
}
// 创建订单...
Order order = new Order();
// 设置订单属性...
order.setTotalAmount(request.getTotalAmount());
order.setDiscountAmount(request.getTotalAmount().subtract(finalAmount));
order.setFinalAmount(finalAmount);
// 更新优惠券状态
userCoupon.setStatus(1); // 已使用
userCoupon.setUseTime(new Date());
userCoupon.setOrderId(order.getId());
userCouponRepository.save(userCoupon);
return order;
}
}
```
五、前端交互设计
1. 优惠券中心页面
- 展示用户所有可用、已使用、已过期优惠券
- 支持按优惠券类型筛选
- 显示优惠券有效期和使用条件
- 提供"立即使用"按钮跳转到购物车
2. 结算页面优惠券选择
- 自动匹配并显示可用的优惠券
- 支持手动输入优惠券码
- 显示使用优惠券后的优惠金额和最终支付金额
- 优惠券不可叠加使用时的提示
3. 优惠券领取弹窗
- 活动页面或商品详情页的优惠券领取入口
- 领取成功/失败提示
- 优惠券详情展示
六、安全与性能考虑
1. 并发控制:
- 优惠券发放时使用数据库乐观锁防止超发
- 高并发场景下考虑使用Redis分布式锁
2. 防刷机制:
- 限制单个用户领取优惠券的频率
- 识别并阻止机器人领取
3. 性能优化:
- 优惠券匹配时使用缓存减少数据库查询
- 批量发放优惠券时使用异步处理
4. 数据一致性:
- 使用事务确保优惠券发放和库存更新的原子性
- 订单创建和优惠券状态更新的原子性
七、扩展功能建议
1. 优惠券分享功能:用户可分享优惠券链接给好友
2. 优惠券组合使用:支持特定优惠券组合使用
3. 优惠券数据分析:统计优惠券领取、使用情况,分析营销效果
4. AB测试:不同用户群体发放不同优惠券测试效果
5. 优惠券预览:在发放前预览优惠券样式和效果
以上方案可根据叮咚买菜的实际业务需求和技术栈进行调整和优化。
评论