IT频道
美团买菜系统:优惠券功能设计与多场景规则实现
来源:     阅读:30
网站管理员
发布于 2025-12-22 05:50
查看主页
  
   一、功能概述
  
  美团买菜系统的优惠券通用功能需要支持多种类型的优惠券(满减券、折扣券、无门槛券等),能够在不同业务场景(商品购买、配送费减免等)下通用,并具备灵活的规则配置能力。
  
   二、系统架构设计
  
   1. 数据库设计
  
  ```sql
  -- 优惠券表
  CREATE TABLE `coupon` (
   `id` bigint NOT NULL AUTO_INCREMENT,
   `name` varchar(100) NOT NULL COMMENT 优惠券名称,
   `type` tinyint NOT NULL COMMENT 类型:1-满减券,2-折扣券,3-无门槛券,
   `amount` decimal(10,2) NOT NULL COMMENT 金额/折扣率,
   `min_order_amount` decimal(10,2) DEFAULT NULL COMMENT 最低订单金额,
   `valid_from` datetime NOT NULL COMMENT 有效期开始,
   `valid_to` datetime NOT NULL COMMENT 有效期结束,
   `scope` tinyint NOT NULL COMMENT 使用范围:1-全品类,2-指定品类,3-指定商品,
   `user_limit` int DEFAULT NULL COMMENT 每人限领数量,
   `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`)
  );
  
  -- 优惠券范围关联表(当scope=2或3时使用)
  CREATE TABLE `coupon_scope` (
   `id` bigint NOT NULL AUTO_INCREMENT,
   `coupon_id` bigint NOT NULL,
   `scope_type` tinyint NOT NULL COMMENT 范围类型:1-品类,2-商品,
   `scope_id` bigint NOT NULL COMMENT 品类ID或商品ID,
   PRIMARY KEY (`id`),
   KEY `idx_coupon_id` (`coupon_id`)
  );
  
  -- 用户优惠券表
  CREATE TABLE `user_coupon` (
   `id` bigint NOT NULL AUTO_INCREMENT,
   `user_id` bigint NOT NULL,
   `coupon_id` bigint NOT NULL,
   `status` tinyint NOT NULL COMMENT 状态:0-未使用,1-已使用,2-已过期,
   `get_time` datetime NOT NULL,
   `use_time` datetime DEFAULT NULL,
   `order_id` bigint DEFAULT NULL COMMENT 使用的订单ID,
   PRIMARY KEY (`id`),
   KEY `idx_user_coupon` (`user_id`,`coupon_id`)
  );
  ```
  
   2. 核心服务模块
  
  1. 优惠券模板服务:管理优惠券的创建、修改、查询等
  2. 优惠券发放服务:处理优惠券的领取逻辑
  3. 优惠券使用服务:验证优惠券是否可用并计算优惠
  4. 优惠券规则引擎:执行复杂的优惠规则判断
  
   三、核心功能实现
  
   1. 优惠券创建与配置
  
  ```java
  public class CouponTemplate {
   private Long id;
   private String name;
   private CouponType type; // 枚举:满减、折扣、无门槛
   private BigDecimal amount;
   private BigDecimal minOrderAmount;
   private Date validFrom;
   private Date validTo;
   private CouponScope scope; // 枚举:全品类、指定品类、指定商品
   private List scopeIds; // 范围ID列表
   private Integer userLimit;
   private Integer totalCount;
   // getters and setters
  }
  
  public interface CouponService {
   // 创建优惠券模板
   CouponTemplate createCoupon(CouponTemplate template);
  
   // 更新优惠券模板
   boolean updateCoupon(CouponTemplate template);
  
   // 查询可用优惠券
   List queryAvailableCoupons(Long userId, BigDecimal orderAmount);
  }
  ```
  
   2. 优惠券领取逻辑
  
  ```java
  @Transactional
  public boolean领取优惠券(Long userId, Long couponId) {
   CouponTemplate coupon = couponRepository.findById(couponId)
   .orElseThrow(() -> new RuntimeException("优惠券不存在"));
  
   // 检查优惠券状态
   if (coupon.getStatus() != CouponStatus.ONGOING) {
   throw new RuntimeException("优惠券不可用");
   }
  
   // 检查用户领取限制
   long userReceivedCount = userCouponRepository.countByUserIdAndCouponId(userId, couponId);
   if (userReceivedCount >= coupon.getUserLimit()) {
   throw new RuntimeException("已达到领取上限");
   }
  
   // 检查总量限制
   if (coupon.getRemainingCount() <= 0) {
   throw new RuntimeException("优惠券已领完");
   }
  
   // 创建用户优惠券记录
   UserCoupon userCoupon = new UserCoupon();
   userCoupon.setUserId(userId);
   userCoupon.setCouponId(couponId);
   userCoupon.setStatus(CouponStatus.UNUSED);
   userCoupon.setGetTime(new Date());
  
   userCouponRepository.save(userCoupon);
  
   // 更新优惠券剩余数量
   coupon.setRemainingCount(coupon.getRemainingCount() - 1);
   couponRepository.save(coupon);
  
   return true;
  }
  ```
  
   3. 优惠券使用验证
  
  ```java
  public CouponValidationResult validateCoupon(Long userId, Long couponId, BigDecimal orderAmount, List productIds) {
   UserCoupon userCoupon = userCouponRepository.findByUserIdAndCouponIdAndStatus(userId, couponId, CouponStatus.UNUSED);
   if (userCoupon == null) {
   return CouponValidationResult.fail("优惠券不可用");
   }
  
   CouponTemplate coupon = couponRepository.findById(couponId)
   .orElseThrow(() -> new RuntimeException("优惠券不存在"));
  
   // 检查有效期
   Date now = new Date();
   if (now.before(coupon.getValidFrom()) || now.after(coupon.getValidTo())) {
   return CouponValidationResult.fail("优惠券已过期");
   }
  
   // 检查使用范围
   if (coupon.getScope() == CouponScope.SPECIFIC_PRODUCTS) {
   List validProductIds = couponScopeRepository.findProductIdsByCouponId(couponId);
   boolean allProductsValid = productIds.stream()
   .allMatch(validProductIds::contains);
   if (!allProductsValid) {
   return CouponValidationResult.fail("部分商品不适用此优惠券");
   }
   }
  
   // 检查最低消费
   if (coupon.getMinOrderAmount() != null && orderAmount.compareTo(coupon.getMinOrderAmount()) < 0) {
   return CouponValidationResult.fail("订单金额未达到使用条件");
   }
  
   // 验证通过
   return CouponValidationResult.success(calculateDiscount(coupon, orderAmount));
  }
  
  private DiscountResult calculateDiscount(CouponTemplate coupon, BigDecimal orderAmount) {
   switch (coupon.getType()) {
   case FULL_REDUCTION:
   return new DiscountResult(
   coupon.getAmount(),
   orderAmount.subtract(coupon.getAmount())
   );
   case DISCOUNT:
   BigDecimal discountAmount = orderAmount.multiply(BigDecimal.valueOf(1 - coupon.getAmount().doubleValue()));
   return new DiscountResult(
   orderAmount.subtract(discountAmount),
   discountAmount
   );
   case NO_THRESHOLD:
   return new DiscountResult(
   coupon.getAmount(),
   orderAmount.subtract(coupon.getAmount())
   );
   default:
   throw new IllegalStateException("未知优惠券类型");
   }
  }
  ```
  
   4. 订单结算中使用优惠券
  
  ```java
  public Order结算(OrderCreateRequest request) {
   // 获取用户选择的优惠券
   Long couponId = request.getCouponId();
   BigDecimal originalAmount = calculateOriginalAmount(request.getProducts());
  
   CouponValidationResult validation = validateCoupon(
   request.getUserId(),
   couponId,
   originalAmount,
   request.getProductIds()
   );
  
   if (!validation.isSuccess()) {
   throw new RuntimeException(validation.getMessage());
   }
  
   // 应用优惠券
   DiscountResult discount = validation.getDiscount();
   BigDecimal finalAmount = discount.getFinalAmount();
  
   // 创建订单
   Order order = new Order();
   order.setUserId(request.getUserId());
   order.setOriginalAmount(originalAmount);
   order.setDiscountAmount(discount.getDiscountAmount());
   order.setFinalAmount(finalAmount);
   order.setCouponId(couponId);
   // 其他订单字段设置...
  
   // 更新优惠券状态为已使用
   userCouponRepository.updateStatusToUsed(request.getUserId(), couponId);
  
   return orderRepository.save(order);
  }
  ```
  
   四、关键业务规则实现
  
  1. 优惠券互斥规则:
  ```java
  public boolean checkCouponExclusion(Long userId, Long couponId, Set excludedCouponTypes) {
   List usedCoupons = userCouponRepository.findUsedCouponsByUser(userId);
   return usedCoupons.stream()
   .anyMatch(uc -> excludedCouponTypes.contains(getCouponType(uc.getCouponId())));
  }
  ```
  
  2. 优惠券叠加使用限制:
  ```java
  public boolean canStackCoupons(List couponIds) {
   // 查询这些优惠券是否允许叠加
   Map coupons = couponRepository.findByIds(couponIds);
   return coupons.values().stream()
   .allMatch(c -> c.getAllowStacking());
  }
  ```
  
  3. 品类/商品范围验证:
  ```java
  public boolean isProductValidForCoupon(Long productId, Long couponId) {
   CouponTemplate coupon = couponRepository.findById(couponId).orElse(null);
   if (coupon == null || coupon.getScope() == CouponScope.ALL) {
   return true;
   }
  
   List validProductIds = couponScopeRepository.findProductIdsByCouponId(couponId);
   return validProductIds.contains(productId);
  }
  ```
  
   五、性能优化考虑
  
  1. 缓存策略:
   - 缓存常用优惠券模板(Redis)
   - 缓存用户已领取优惠券列表
  
  2. 数据库优化:
   - 优惠券表按状态分区
   - 用户优惠券表按用户ID分片
  
  3. 异步处理:
   - 优惠券发放采用消息队列异步处理
   - 优惠券使用记录异步归档
  
   六、测试用例设计
  
  1. 正常流程测试:
   - 用户领取有效期内通用优惠券
   - 在满足条件下使用优惠券结算
  
  2. 异常流程测试:
   - 使用过期优惠券
   - 使用不满足最低金额的优惠券
   - 在不适用商品上使用限定品类优惠券
  
  3. 并发测试:
   - 多个用户同时领取限量优惠券
   - 同一用户同时使用多张优惠券
  
  4. 边界条件测试:
   - 刚好满足最低金额的订单
   - 优惠券有效期最后时刻使用
  
   七、部署与监控
  
  1. 监控指标:
   - 优惠券领取成功率
   - 优惠券使用率
   - 规则验证耗时
  
  2. 告警规则:
   - 优惠券领取失败率突增
   - 规则验证超时
  
  3. 日志收集:
   - 优惠券领取记录
   - 优惠券使用记录
   - 规则验证失败原因
  
  通过以上设计,美团买菜系统可以实现一个灵活、可扩展的优惠券通用功能,支持各种业务场景和复杂的优惠规则。
免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 IT频道
购买生鲜系统联系18310199838
广告
相关推荐
快驴生鲜技术栈解析:从架构到场景的全链路方案
悦厚生鲜配送系统:全流程数字化,降本增效,助力企业“数治”转型
生鲜平台:以溯源冷链直采破痛点,打造品质生活闭环
悦厚生鲜系统:数字化赋能,降本增效重塑供应链
菜东家系统:自动化+监控+数据,构建生鲜配送闭环纠错体系