文档目录
优惠券系统表

简介

本文件面向电商平台开发者,系统化梳理 DouPHP 电商系统的优惠券数据模型,重点围绕以下目标:

  • 明确优惠券主表 dou_coupon、使用记录表 dou_coupon_log、订单关联表 dou_order_coupon 的字段设计与业务含义
  • 解释优惠券类型、发放规则、使用条件、有效期管理、库存控制等关键业务在表结构中的体现
  • 描述优惠券与用户、订单、商品的关联关系及状态流转机制
  • 给出并发控制、防刷机制与性能优化的可落地方案
  • 提供基于现有代码与SQL的完整参考,便于二次开发与扩展

项目结构

与优惠券相关的核心数据定义集中在以下位置:

  • 系统级表结构文档:_'\doc\开发手册\系统表结构.sql(包含历史/兼容版本的表结构)
  • 模块级备份脚本:_'\module\coupon\storage\backup\coupon.sql(当前模块使用的表结构)
  • 订单模块关联表:_'\module\order\storage\backup\order.sql(订单与优惠券的关联表)
  • 管理端模型:admin\model\coupon\Coupon.php、admin\model\coupon\CouponLog.php(ORM映射与查询封装)
graph TB
A["优惠券主表<br/>dou_coupon"] --> B["领取/使用日志表<br/>dou_coupon_log"]
A --> C["订单-优惠券关联表<br/>dou_order_coupon"]
B --> C
D["订单主表<br/>dou_order"] -.-> C
E["用户表<br/>dou_user"] -.-> B

核心组件

本节聚焦三张核心表的设计要点与字段语义。

  • 优惠券主表 dou_coupon

    • 标识与名称:id、name、coupon_sn(唯一券码)
    • 优惠策略:type(类型)、face_value(面值)、max_discount(封顶折扣,部分版本存在)、condition(使用门槛金额)
    • 范围与限制:scope_type、scope_value(适用范围,如全店/指定类目/指定商品)、limit_per_user(每人限领数量)、is_stackable(是否可叠加)、is_first_order_only(是否仅限首单)
    • 库存与生命周期:total_quantity(总量)、issued_quantity(已发放量)、start_at/end_at(有效期)
    • 展示与排序:brief、image、sort、status(启用/禁用)、created_at
  • 优惠券使用记录表 dou_coupon_log

    • 主体信息:user_id、coupon_id
    • 时间戳:claimed_at(领取时间)、used_at(使用时间)、created_at
    • 使用上下文:order_sn(使用时的订单号)、ip(操作IP)
    • 状态:status(如未使用/已使用/已过期等)
  • 订单-优惠券关联表 dou_order_coupon

    • 关联键:order_id、coupon_id、coupon_log_id
    • 优惠明细:amount(本次抵扣金额)、type(优惠类型)
    • 时间:created_at

架构总览

从数据流角度,优惠券的核心流程包括“创建/配置 → 发放 → 使用 → 结算”。

sequenceDiagram
participant Admin as "管理员"
participant Coupon as "优惠券主表<br/>dou_coupon"
participant Log as "使用记录表<br/>dou_coupon_log"
participant Order as "订单-优惠券关联表<br/>dou_order_coupon"
participant User as "用户"
participant OrderMain as "订单主表<br/>dou_order"
Admin->>Coupon : 创建/编辑优惠券
User->>Log : 领取优惠券(写入领取记录)
User->>Order : 下单并选择优惠券
Order->>Log : 校验并标记使用(更新状态/时间)
Order->>Order : 计算实付金额(应用优惠)
Order->>Order : 保存订单-优惠券关联(记录抵扣金额)

详细组件分析

优惠券主表 dou_coupon

  • 设计要点
    • 唯一性:coupon_sn 作为对外唯一券码,建议加唯一索引
    • 范围控制:scope_type/scope_value 支持灵活限定(全店/类目/商品),通过文本或JSON存储
    • 库存控制:total_quantity 与 issued_quantity 配合,发放时原子递增,避免超发
    • 有效期:start_at/end_at 精确到分钟,便于活动期控制
    • 叠加与限制:is_stackable、is_first_order_only、limit_per_user 控制使用策略
  • 典型索引建议
    • 唯一索引:coupon_sn
    • 查询索引:status、start_at、end_at、scope_type
  • 与业务的关系
    • 与用户:通过 dou_coupon_log.user_id 建立“谁领了哪张券”
    • 与订单:通过 dou_order_coupon.order_id/coupon_id 建立“哪个订单用了哪张券”
    • 与商品:通过 scope_value 间接限定适用商品范围

优惠券使用记录表 dou_coupon_log

  • 设计要点
    • 领取与使用分离:claimed_at 与 used_at 分别记录,便于统计与审计
    • 使用上下文:order_sn 用于回溯具体订单;ip 用于风控
    • 状态机:status 表示当前状态(未使用/已使用/已过期/已取消等)
  • 典型索引建议
    • 复合索引:(user_id, coupon_id) 用于查询某用户某券的使用情况
    • 复合索引:(coupon_id, status) 用于统计可用券
    • 时间索引:(used_at) 用于按使用时间统计
  • 与业务的关系
    • 与用户:user_id 指向用户
    • 与订单:order_sn 指向订单号(需结合订单表)
    • 与主券:coupon_id 指向 dou_coupon.id

订单-优惠券关联表 dou_order_coupon

  • 设计要点
    • 多对多桥接:order_id + coupon_id + coupon_log_id 共同定位一次使用
    • 优惠明细:amount 记录实际抵扣金额,type 区分优惠类型(满减/折扣等)
  • 典型索引建议
    • 索引:order_id(订单维度查询)
    • 复合索引:(coupon_id, order_id)(券维度查询)
  • 与业务的关系
    • 与订单:order_id 指向订单主表
    • 与券:coupon_id 指向优惠券主表
    • 与日志:coupon_log_id 指向使用记录,形成闭环

优惠券类型与使用条件

  • 类型 type
    • 常见值:满减、折扣、无门槛等(具体枚举由业务层定义)
  • 使用条件 condition
    • 最低消费门槛,满足后方可使用
  • 其他限制
    • is_first_order_only:仅首单可用
    • limit_per_user:每人限领数量
    • is_stackable:是否可与其他优惠叠加
    • scope_type/scope_value:适用范围(全店/类目/商品)

有效期管理与库存控制

  • 有效期
    • start_at/end_at 控制活动窗口,使用前校验是否在有效期内
  • 库存控制
    • total_quantity 为总量,issued_quantity 为已发放量
    • 发放时需原子递增 issued_quantity,防止超发
    • 使用时无需再扣减库存(以使用次数/状态为准)

状态流转机制

  • 主要状态
    • 未使用:领取后尚未使用
    • 已使用:成功用于订单支付
    • 已过期:超过 end_at 仍未使用
    • 已取消:主动取消或回滚
  • 流转约束
    • 未使用 → 已使用:需满足条件(有效期、门槛、范围、叠加规则)
    • 未使用 → 已过期:时间到达 end_at
    • 已使用 → 已取消:订单退款/撤销时回滚
stateDiagram-v2
[*] --> 未使用 : "领取"
未使用 --> 已使用 : "满足条件并使用"
未使用 --> 已过期 : "超过有效期"
已使用 --> 已取消 : "订单退款/撤销"
已过期 --> [*]
已取消 --> [*]

[此图为概念图,不直接映射具体代码文件]

依赖关系分析

  • 表间关系
    • dou_coupon 与 dou_coupon_log:一对多(一张券可被多次领取/使用)
    • dou_coupon_log 与 dou_order_coupon:一对多(一条使用记录对应一次订单使用)
    • dou_order_coupon 与 dou_order:多对一(一个订单可使用多张券)
  • ORM 映射
    • admin/model/coupon/Coupon.php 映射 dou_coupon
    • admin/model/coupon/CouponLog.php 映射 dou_coupon_log
erDiagram
DOU_COUPON {
int id PK
varchar name
varchar coupon_sn UK
varchar type
decimal face_value
decimal max_discount
smallint limit_per_user
int total_quantity
int issued_quantity
tinyint is_stackable
tinyint is_first_order_only
decimal condition
varchar scope_type
text scope_value
datetime start_at
datetime end_at
varchar brief
varchar image
tinyint sort
tinyint status
datetime created_at
}
DOU_COUPON_LOG {
int id PK
mediumint user_id
mediumint coupon_id FK
datetime claimed_at
datetime used_at
varchar order_sn
varchar ip
tinyint status
datetime created_at
}
DOU_ORDER_COUPON {
int id PK
int order_id FK
mediumint coupon_id FK
int coupon_log_id FK
decimal amount
varchar type
datetime created_at
}
DOU_COUPON ||--o{ DOU_COUPON_LOG : "被领取/使用"
DOU_COUPON_LOG ||--o{ DOU_ORDER_COUPON : "用于订单"
DOU_ORDER ||--o{ DOU_ORDER_COUPON : "包含"

性能与并发优化

  • 数据库层面
    • 索引优化
      • dou_coupon:唯一索引(coupon_sn),复合索引(status, start_at, end_at)
      • dou_coupon_log:复合索引(user_id, coupon_id)、(coupon_id, status)、(used_at)
      • dou_order_coupon:索引(order_id)、复合索引(coupon_id, order_id)
    • 事务与锁
      • 发放与使用使用事务包裹,必要时使用行级锁或乐观锁(版本号)
      • 库存控制使用原子更新(如 UPDATE ... SET issued_quantity = issued_quantity + 1 WHERE id = ? AND issued_quantity &lt; total_quantity)
  • 应用层
    • 防刷机制
      • 接口限频:同一用户/IP短时间领取/使用次数限制
      • 幂等设计:基于 coupon_sn + user_id + order_sn 的唯一键或分布式锁
      • 风控校验:设备指纹、验证码、黑名单
    • 缓存与预取
      • 热点券信息(如活动券)缓存至内存,减少DB压力
      • 使用资格校验结果短期缓存,降低重复计算
    • 异步化
      • 非关键路径(如发送通知、写日志)采用消息队列异步处理
    • 读写分离
      • 读多写少场景下,将统计类查询路由到从库

故障排查指南

  • 常见问题定位
    • 无法领取:检查库存(total_quantity > issued_quantity)、有效期(当前时间在 start_at/end_at 之间)、每人限领(limit_per_user)
    • 无法使用:检查使用条件(condition)、适用范围(scope_type/scope_value)、叠加规则(is_stackable)、首单限制(is_first_order_only)
    • 重复使用:检查 dou_coupon_log 中是否存在相同 user_id + coupon_id + order_sn 的记录
  • 排查步骤
    • 查看 dou_coupon_log 的状态与时间戳,确认领取/使用是否成功
    • 核对 dou_order_coupon 的 amount 与 type,确认优惠是否生效
    • 检查 dou_coupon 的 status、start_at、end_at 与 scope 配置
  • 日志与审计
    • 利用 ip、order_sn、user_id 进行溯源
    • 结合订单状态变更日志,定位异常订单

结论

  • 数据模型清晰:dou_coupon 定义优惠策略与限制,dou_coupon_log 记录领取与使用轨迹,dou_order_coupon 沉淀订单维度的优惠明细
  • 业务可扩展:通过 scope_type/scope_value、type、is_stackable 等字段支撑多样化营销场景
  • 并发与安全:结合索引、事务、锁与接口限频,保障高并发下的正确性与安全性
  • 建议持续完善:根据业务演进补充更细粒度的范围控制、风控策略与监控指标

附录

  • 字段字典(节选)
    • dou_coupon
      • id:自增主键
      • name:优惠券名称
      • coupon_sn:唯一券码
      • type:优惠券类型
      • face_value:面值
      • max_discount:封顶折扣(部分版本)
      • limit_per_user:每人限领数量
      • total_quantity:总量
      • issued_quantity:已发放量
      • is_stackable:是否可叠加
      • is_first_order_only:是否仅限首单
      • condition:使用门槛金额
      • scope_type:适用范围类型
      • scope_value:适用范围值(类目/商品ID列表等)
      • start_at:开始时间
      • end_at:结束时间
      • brief:简介
      • image:图片
      • sort:排序
      • status:状态(启用/禁用)
      • created_at:创建时间
    • dou_coupon_log
      • id:自增主键
      • user_id:会员ID
      • coupon_id:优惠券ID
      • claimed_at:领取时间
      • used_at:使用时间
      • order_sn:订单号
      • ip:操作IP
      • status:状态
      • created_at:创建时间
    • dou_order_coupon
      • id:自增主键
      • order_id:订单ID
      • coupon_id:优惠券ID
      • coupon_log_id:使用记录ID
      • amount:抵扣金额
      • type:优惠类型
      • created_at:创建时间
添加日期:2026-10-05