美团买菜优惠券系统设计:功能、架构与实现全解

分类:IT频道 时间:2026-01-22 05:40 浏览:9
概述
    一、功能概述    优惠券通用功能是电商系统(包括美团买菜这类生鲜电商)的核心营销工具之一,主要实现以下目标:  -支持多种优惠券类型(满减券、折扣券、无门槛券等)  -实现优惠券的发放、领取、使用、核销全流程管理  -支持通用优惠券(全平台可用)和定向优惠券(特定商品/品类可用)  -提供
内容
  
   一、功能概述
  
  优惠券通用功能是电商系统(包括美团买菜这类生鲜电商)的核心营销工具之一,主要实现以下目标:
  - 支持多种优惠券类型(满减券、折扣券、无门槛券等)
  - 实现优惠券的发放、领取、使用、核销全流程管理
  - 支持通用优惠券(全平台可用)和定向优惠券(特定商品/品类可用)
  - 提供优惠券有效期、使用条件等灵活配置
  
   二、系统架构设计
  
   1. 数据库设计
  
  ```sql
  -- 优惠券模板表
  CREATE TABLE `coupon_template` (
   `id` bigint NOT NULL AUTO_INCREMENT,
   `name` varchar(100) NOT NULL COMMENT 优惠券名称,
   `type` tinyint NOT NULL COMMENT 类型:1满减券 2折扣券 3无门槛券,
   `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_days` int DEFAULT NULL COMMENT 有效天数(从领取算起),
   `expire_time` datetime DEFAULT NULL COMMENT 固定过期时间,
   `scope_type` tinyint NOT NULL COMMENT 使用范围:1全平台 2指定品类 3指定商品,
   `scope_ids` varchar(1000) DEFAULT NULL COMMENT 适用范围ID(品类或商品ID列表),
   `total_count` int NOT NULL COMMENT 发放总量,
   `remaining_count` int NOT NULL COMMENT 剩余数量,
   `status` tinyint NOT NULL COMMENT 状态:0未启用 1启用 2停用,
   `create_time` datetime NOT NULL,
   `update_time` datetime NOT NULL,
   PRIMARY KEY (`id`)
  );
  
  -- 用户优惠券表
  CREATE TABLE `user_coupon` (
   `id` bigint NOT NULL AUTO_INCREMENT,
   `user_id` bigint NOT NULL COMMENT 用户ID,
   `template_id` bigint NOT NULL COMMENT 优惠券模板ID,
   `coupon_code` varchar(32) NOT NULL COMMENT 优惠券码,
   `status` tinyint NOT NULL COMMENT 状态:0未使用 1已使用 2已过期 3已冻结,
   `get_time` datetime NOT NULL COMMENT 领取时间,
   `start_time` datetime NOT NULL COMMENT 生效时间,
   `end_time` datetime NOT NULL COMMENT 过期时间,
   `order_id` bigint DEFAULT NULL COMMENT 关联订单ID,
   `use_time` datetime DEFAULT NULL COMMENT 使用时间,
   PRIMARY KEY (`id`),
   UNIQUE KEY `uk_coupon_code` (`coupon_code`)
  );
  ```
  
   2. 核心服务模块
  
  1. 优惠券模板服务:管理优惠券的创建、修改、查询等
  2. 优惠券发放服务:处理优惠券的发放逻辑(主动领取、系统发放等)
  3. 优惠券使用服务:验证优惠券是否可用,计算优惠金额
  4. 优惠券核销服务:标记优惠券为已使用状态
  
   三、核心功能实现
  
   1. 优惠券发放实现
  
  ```java
  public class CouponService {
  
   // 用户领取优惠券
   public UserCouponDTO receiveCoupon(Long userId, Long templateId) {
   // 1. 验证优惠券模板是否存在且可领取
   CouponTemplate template = couponTemplateRepository.findById(templateId)
   .orElseThrow(() -> new BusinessException("优惠券不存在"));
  
   if (template.getRemainingCount() <= 0) {
   throw new BusinessException("优惠券已领完");
   }
  
   // 2. 检查用户是否已领取过该类型优惠券(根据业务需求)
   // ...
  
   // 3. 创建用户优惠券记录
   UserCoupon userCoupon = new UserCoupon();
   userCoupon.setUserId(userId);
   userCoupon.setTemplateId(templateId);
   userCoupon.setCouponCode(generateCouponCode());
   userCoupon.setStatus(CouponStatus.UNUSED);
   userCoupon.setStartTime(calculateStartTime(template));
   userCoupon.setEndTime(calculateEndTime(template, userCoupon.getStartTime()));
  
   // 4. 更新模板剩余数量
   couponTemplateRepository.decreaseRemainingCount(templateId);
  
   // 5. 保存用户优惠券
   userCoupon = userCouponRepository.save(userCoupon);
  
   return convertToDTO(userCoupon);
   }
  
   private String generateCouponCode() {
   // 生成唯一优惠券码
   return "CPN" + System.currentTimeMillis() + RandomStringUtils.randomNumeric(6);
   }
  
   private Date calculateStartTime(CouponTemplate template) {
   // 根据模板配置计算生效时间(立即生效或指定时间)
   // ...
   }
  
   private Date calculateEndTime(CouponTemplate template, Date startTime) {
   // 根据模板配置计算过期时间(固定日期或领取后N天)
   if (template.getExpireTime() != null) {
   return template.getExpireTime();
   } else {
   Calendar calendar = Calendar.getInstance();
   calendar.setTime(startTime);
   calendar.add(Calendar.DAY_OF_MONTH, template.getValidDays());
   return calendar.getTime();
   }
   }
  }
  ```
  
   2. 优惠券使用验证实现
  
  ```java
  public class CouponValidator {
  
   public CouponValidateResult validateCoupon(Long userId, String couponCode,
   BigDecimal orderAmount, List orderItemIds) {
  
   CouponValidateResult result = new CouponValidateResult();
  
   // 1. 查询用户优惠券
   UserCoupon userCoupon = userCouponRepository.findByUserIdAndCouponCode(userId, couponCode)
   .orElseThrow(() -> new BusinessException("优惠券不存在"));
  
   if (userCoupon.getStatus() != CouponStatus.UNUSED) {
   throw new BusinessException("优惠券不可用");
   }
  
   if (userCoupon.getEndTime().before(new Date())) {
   throw new BusinessException("优惠券已过期");
   }
  
   // 2. 查询优惠券模板
   CouponTemplate template = couponTemplateRepository.findById(userCoupon.getTemplateId())
   .orElseThrow(() -> new BusinessException("优惠券模板不存在"));
  
   // 3. 验证使用条件
   // 验证最低消费金额
   if (template.getMinOrderAmount() != null &&
   orderAmount.compareTo(template.getMinOrderAmount()) < 0) {
   throw new BusinessException("订单金额不满足最低消费要求");
   }
  
   // 验证适用范围(如果是定向优惠券)
   if (template.getScopeType() != ScopeType.ALL) {
   List scopeIds = Arrays.asList(template.getScopeIds().split(","))
   .stream().map(Long::valueOf).collect(Collectors.toList());
  
   // 检查订单商品是否在适用范围内
   boolean allMatch = orderItemIds.stream()
   .allMatch(itemId -> scopeIds.contains(itemId));
  
   if (!allMatch) {
   throw new BusinessException("该优惠券不适用于订单中的商品");
   }
   }
  
   // 4. 计算优惠金额
   BigDecimal discountAmount = calculateDiscountAmount(template, orderAmount);
  
   result.setValid(true);
   result.setDiscountAmount(discountAmount);
   result.setCouponId(userCoupon.getId());
   result.setTemplateId(template.getId());
  
   return result;
   }
  
   private BigDecimal calculateDiscountAmount(CouponTemplate template, BigDecimal orderAmount) {
   switch (template.getType()) {
   case CouponType.FIXED_DISCOUNT:
   return template.getDiscountAmount();
   case CouponType.PERCENTAGE_DISCOUNT:
   return orderAmount.multiply(template.getDiscountRate().divide(new BigDecimal(100)));
   case CouponType.NO_THRESHOLD:
   return template.getDiscountAmount();
   default:
   return BigDecimal.ZERO;
   }
   }
  }
  ```
  
   3. 优惠券核销实现
  
  ```java
  public class CouponUsageService {
  
   @Transactional
   public void useCoupon(Long userId, Long couponId, Long orderId) {
   // 1. 查询用户优惠券
   UserCoupon userCoupon = userCouponRepository.findById(couponId)
   .orElseThrow(() -> new BusinessException("优惠券不存在"));
  
   if (userCoupon.getUserId().longValue() != userId.longValue()) {
   throw new BusinessException("无权使用该优惠券");
   }
  
   if (userCoupon.getStatus() != CouponStatus.UNUSED) {
   throw new BusinessException("优惠券状态异常");
   }
  
   if (userCoupon.getEndTime().before(new Date())) {
   throw new BusinessException("优惠券已过期");
   }
  
   // 2. 更新优惠券状态为已使用
   userCoupon.setStatus(CouponStatus.USED);
   userCoupon.setOrderId(orderId);
   userCoupon.setUseTime(new Date());
   userCouponRepository.save(userCoupon);
  
   // 3. 记录优惠券使用日志(可选)
   // ...
   }
  }
  ```
  
   四、前端交互设计
  
   1. 优惠券领取页面
  - 展示可领取的优惠券列表
  - 显示优惠券面额、使用条件、有效期等信息
  - 提供"立即领取"按钮
  
   2. 订单结算页面
  - 展示用户持有的可用优惠券
  - 支持按优惠券类型、面额等筛选
  - 显示使用优惠券后的实付金额
  - 提供"使用"按钮
  
   3. 我的优惠券页面
  - 分类展示未使用、已使用、已过期的优惠券
  - 显示优惠券详细信息和使用条件
  - 已过期优惠券提供"查看详情"功能
  
   五、性能优化考虑
  
  1. 缓存策略:
   - 缓存热门优惠券模板信息
   - 缓存用户可用优惠券列表
  
  2. 数据库优化:
   - 对优惠券模板表和用户优惠券表进行适当分表
   - 对常用查询字段建立索引
  
  3. 异步处理:
   - 优惠券发放可考虑异步队列处理,避免高并发时数据库压力过大
  
  4. 限流措施:
   - 对优惠券领取接口进行限流,防止恶意刷券
  
   六、安全考虑
  
  1. 防刷机制:
   - 同一用户对同一优惠券的领取频率限制
   - IP限制防止批量领取
  
  2. 数据校验:
   - 严格校验优惠券码格式
   - 防止SQL注入和XSS攻击
  
  3. 审计日志:
   - 记录优惠券的发放、使用等关键操作
  
   七、扩展功能建议
  
  1. 优惠券分享功能:支持用户将优惠券分享给好友
  2. 优惠券组合使用:支持多张优惠券叠加使用(需设计复杂规则)
  3. 优惠券任务系统:用户完成特定任务后获得优惠券
  4. 优惠券数据分析:统计优惠券的领取、使用情况,优化营销策略
  
  通过以上设计,可以实现一个功能完善、性能良好的美团买菜系统优惠券通用功能,支持各种营销场景和业务需求。
评论
  • 下一篇

  • Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 8192 bytes) in /www/wwwroot/www.sjwxsc.com/config/function.php on line 274