一、功能概述
优惠券管理是电商平台重要的营销工具,叮咚买菜系统的优惠券功能应包含以下核心模块:
- 优惠券创建与配置
- 优惠券发放与领取
- 优惠券使用与核销
- 优惠券统计与分析
二、系统架构设计
1. 数据库设计
```sql
-- 优惠券表
CREATE TABLE `coupon` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT 优惠券名称,
`type` tinyint(4) NOT NULL COMMENT 类型:1-满减券 2-折扣券 3-无门槛券,
`amount` decimal(10,2) NOT NULL COMMENT 金额/折扣率,
`min_order_amount` decimal(10,2) DEFAULT NULL COMMENT 最低订单金额,
`total_count` int(11) DEFAULT NULL COMMENT 总数量,
`remaining_count` int(11) DEFAULT NULL COMMENT 剩余数量,
`start_time` datetime NOT NULL COMMENT 生效时间,
`end_time` datetime NOT NULL COMMENT 过期时间,
`status` tinyint(4) NOT NULL DEFAULT 1 COMMENT 状态:0-禁用 1-启用,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`id`)
);
-- 用户优惠券表
CREATE TABLE `user_coupon` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL COMMENT 用户ID,
`coupon_id` bigint(20) NOT NULL COMMENT 优惠券ID,
`status` tinyint(4) NOT NULL DEFAULT 0 COMMENT 状态:0-未使用 1-已使用 2-已过期,
`order_id` bigint(20) DEFAULT NULL COMMENT 使用订单ID,
`get_time` datetime NOT NULL COMMENT 领取时间,
`use_time` datetime DEFAULT NULL COMMENT 使用时间,
`expire_time` datetime NOT NULL COMMENT 过期时间,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_coupon` (`user_id`,`coupon_id`)
);
```
2. 核心服务模块
1. 优惠券模板服务
- 创建/编辑优惠券模板
- 查询可用优惠券模板
- 更新优惠券状态
2. 优惠券发放服务
- 批量发放优惠券
- 用户领取优惠券
- 优惠券过期处理
3. 优惠券使用服务
- 订单结算时优惠券选择
- 优惠券使用校验
- 优惠券核销
4. 数据分析服务
- 优惠券发放统计
- 优惠券使用率分析
- 优惠券ROI分析
三、核心功能实现
1. 优惠券创建功能
```java
public class CouponTemplate {
private Long id;
private String name;
private Integer type; // 1-满减 2-折扣 3-无门槛
private BigDecimal amount; // 金额或折扣率
private BigDecimal minOrderAmount; // 最低订单金额
private Integer totalCount; // 总数量
private Date startTime; // 生效时间
private Date endTime; // 过期时间
// getters and setters
}
@Service
public class CouponService {
@Autowired
private CouponRepository couponRepository;
@Transactional
public CouponTemplate createCoupon(CouponTemplate template) {
// 参数校验
validateTemplate(template);
// 保存优惠券模板
CouponEntity entity = new CouponEntity();
BeanUtils.copyProperties(template, entity);
entity.setCreateTime(new Date());
entity.setUpdateTime(new Date());
entity.setStatus(1); // 启用状态
CouponEntity saved = couponRepository.save(entity);
// 初始化优惠券库存
if (saved.getTotalCount() > 0) {
// 这里可以添加到Redis等缓存中实现高效发放
}
return convertToTemplate(saved);
}
private void validateTemplate(CouponTemplate template) {
// 校验逻辑
if (template.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("优惠券金额必须大于0");
}
if (template.getStartTime().after(template.getEndTime())) {
throw new IllegalArgumentException("结束时间不能早于开始时间");
}
// 其他校验...
}
}
```
2. 优惠券发放功能
```java
@Service
public class CouponDistributionService {
@Autowired
private UserCouponRepository userCouponRepository;
@Autowired
private CouponRepository couponRepository;
@Transactional
public void distributeCoupon(Long couponId, List userIds) {
CouponEntity coupon = couponRepository.findById(couponId)
.orElseThrow(() -> new RuntimeException("优惠券不存在"));
if (coupon.getRemainingCount() < userIds.size()) {
throw new RuntimeException("优惠券库存不足");
}
Date now = new Date();
List coupons = new ArrayList<>();
for (Long userId : userIds) {
UserCouponEntity userCoupon = new UserCouponEntity();
userCoupon.setUserId(userId);
userCoupon.setCouponId(couponId);
userCoupon.setStatus(0); // 未使用
userCoupon.setGetTime(now);
userCoupon.setExpireTime(coupon.getEndTime());
coupons.add(userCoupon);
}
userCouponRepository.saveAll(coupons);
// 更新优惠券剩余数量
coupon.setRemainingCount(coupon.getRemainingCount() - userIds.size());
couponRepository.save(coupon);
}
// 用户主动领取优惠券
public void userClaimCoupon(Long userId, Long couponId) {
// 类似实现,检查库存、用户是否已领取等
}
}
```
3. 优惠券使用功能
```java
@Service
public class CouponUsageService {
@Autowired
private UserCouponRepository userCouponRepository;
@Autowired
private OrderService orderService;
public BigDecimal applyCoupon(Long userId, Long couponId, BigDecimal orderAmount) {
UserCouponEntity userCoupon = userCouponRepository.findByUserIdAndCouponIdAndStatus(
userId, couponId, 0) // 未使用的优惠券
.orElseThrow(() -> new RuntimeException("优惠券不可用"));
CouponEntity coupon = couponRepository.findById(userCoupon.getCouponId())
.orElseThrow(() -> new RuntimeException("优惠券不存在"));
// 校验优惠券是否可用
validateCouponUsage(userCoupon, coupon, orderAmount);
// 计算优惠金额
BigDecimal discountAmount = calculateDiscount(coupon, orderAmount);
return discountAmount;
}
private void validateCouponUsage(UserCouponEntity userCoupon, CouponEntity coupon, BigDecimal orderAmount) {
Date now = new Date();
if (now.before(coupon.getStartTime()) || now.after(coupon.getEndTime())) {
throw new RuntimeException("优惠券不在有效期内");
}
if (coupon.getMinOrderAmount() != null &&
orderAmount.compareTo(coupon.getMinOrderAmount()) < 0) {
throw new RuntimeException("订单金额不满足最低要求");
}
// 其他校验...
}
private BigDecimal calculateDiscount(CouponEntity coupon, BigDecimal orderAmount) {
switch (coupon.getType()) {
case 1: // 满减券
return coupon.getAmount();
case 2: // 折扣券
return orderAmount.multiply(BigDecimal.ONE.subtract(coupon.getAmount()))
.setScale(2, RoundingMode.HALF_UP);
case 3: // 无门槛券
return coupon.getAmount();
default:
return BigDecimal.ZERO;
}
}
// 订单支付时核销优惠券
public void useCoupon(Long userId, Long couponId, Long orderId) {
UserCouponEntity userCoupon = userCouponRepository.findByUserIdAndCouponIdAndStatus(
userId, couponId, 0)
.orElseThrow(() -> new RuntimeException("优惠券不可用"));
userCoupon.setStatus(1); // 已使用
userCoupon.setUseTime(new Date());
userCoupon.setOrderId(orderId);
userCouponRepository.save(userCoupon);
}
}
```
四、前端交互设计
1. 优惠券管理后台
- 优惠券列表展示(名称、类型、金额、有效期、状态)
- 创建/编辑优惠券表单
- 优惠券发放记录查询
2. 用户端功能
- 我的优惠券列表(可用/已使用/已过期)
- 优惠券领取入口
- 订单结算时优惠券选择弹窗
五、关键技术点
1. 高并发处理
- 使用Redis实现优惠券库存的原子性操作
- 乐观锁或分布式锁防止超发
2. 过期处理
- 定时任务扫描过期优惠券
- 使用Redis的TTL机制自动过期
3. 性能优化
- 优惠券查询缓存
- 异步发放优惠券
4. 安全考虑
- 防止优惠券刷取
- 优惠券使用防重复
六、扩展功能
1. 优惠券组合使用
- 支持多张优惠券叠加使用
- 设置优惠券使用优先级
2. 分享裂变
- 用户分享优惠券链接获得奖励
- 优惠券裂变传播统计
3. 精准营销
- 基于用户画像的优惠券定向发放
- A/B测试不同优惠券效果
七、部署与监控
1. 监控指标
- 优惠券发放成功率
- 优惠券使用率
- 优惠券核销时效
2. 告警机制
- 优惠券库存不足告警
- 优惠券异常使用告警
以上是叮咚买菜系统优惠券管理功能的基本实现方案,可根据实际业务需求进行调整和扩展。