简介
本文件面向电商平台开发者,系统化梳理 DouPHP 电商系统订单管理模块的数据库表结构设计。重点围绕订单主表、订单商品明细表、订单状态流水表等核心表,结合订单生命周期、状态流转、拆分与合并、取消退款等业务场景,给出数据模型设计说明与查询优化建议。文档同时覆盖订单金额计算、优惠券使用、积分抵扣、运费计算等复杂业务的数据落点与关联方式,帮助读者在扩展或二次开发时具备完整参考。
项目结构
订单相关的数据模型集中在后台模型目录中,每个模型对应一张订单域内的核心表:
- 订单主表模型:Order(对应 order 表)
- 订单商品明细模型:OrderItem(对应 order_item 表)
- 订单收货地址快照模型:OrderAddress(对应 order_address 表)
- 订单优惠券记录模型:OrderCoupon(对应 order_coupon 表)
- 订单发票模型:OrderInvoice(对应 order_invoice 表)
- 订单退款单模型:OrderRefund(对应 order_refund 表)
- 订单状态流水模型:OrderStatusLog(对应 order_status_log 表)
此外,订单状态常量与迁移规则由 OrderStatus 定义,状态变更流程由 OrderStatusTransition 实现;支付成功回调与对账逻辑涉及 PaymentService,用于更新支付台账并联动订单时间字段。
graph TB
subgraph "订单域模型"
O["order<br/>订单主表"]
I["order_item<br/>订单商品明细"]
A["order_address<br/>收货地址快照"]
C["order_coupon<br/>订单优惠券"]
INV["order_invoice<br/>订单发票"]
R["order_refund<br/>订单退款单"]
L["order_status_log<br/>订单状态流水"]
end
O --> I
O --> A
O --> C
O --> INV
O --> R
O --> L
核心组件
本节从"表—字段—用途"的角度,概述各核心表的设计要点与职责边界。
-
订单主表(order)
- 关键字段:订单号、用户ID、下单人/直推/间推ID、业务模式与模块、类目ID、收件人信息ID、邮箱、支付方式ID、物流方式ID、运单号、运费、商品金额、订单金额、积分抵扣、分销奖励、付款时间、发货时间、售后开关、售后状态、评论开关、商品链接状态、订单状态、创建时间等。
- 职责:承载订单全局信息与金额汇总,作为订单生命周期与统计的核心锚点。
- 典型用法:按用户、订单号、状态、时间窗筛选;聚合成交额、订单数、支付方式分布、Top商品/分类/客户等。
-
订单商品明细(order_item)
- 关键字段:订单ID、用户ID、商品ID、商品数量、类目ID等。
- 职责:记录每笔订单包含的商品及购买数量,支撑销量、收入、类目构成等统计。
-
订单收货地址快照(order_address)
- 关键字段:订单ID、用户ID、创建时间等。
- 职责:冻结下单时的收货信息,避免后续地址本变更影响历史订单。
-
订单优惠券(order_coupon)
- 关键字段:订单ID、优惠券ID、优惠券日志ID、创建时间等。
- 职责:记录一单多券的使用情况,保留金额原值供展示。
-
订单发票(order_invoice)
- 关键字段:订单ID、是否已开具、开具时间、创建时间等。
- 职责:一单一行,记录发票申请与开具状态。
-
订单退款单(order_refund)
- 关键字段:订单ID、售后ID、原始支付ID、退款时间、创建时间等。
- 职责:每笔退款一行,支持混合支付下分渠道退款。
-
订单状态流水(order_status_log)
- 关键字段:订单ID、操作者ID、创建时间等。
- 职责:记录每次状态变更的时间线,包括来源状态、目标状态、原因、操作者类型与IP等。
架构总览
订单状态机以字符串枚举为核心,所有状态变更通过统一入口进行校验与落库,并在事务内同步更新订单主表、订单商品明细的状态以及写入状态流水。无物流插件或非商品模块时,付款后直接推进到已完成;完成时设置发货与完成时间、开启售后与评论;取消时记录关闭时间与原因。
sequenceDiagram
participant Client as "调用方"
participant Transition as "订单状态机(OrderStatusTransition)"
participant DB as "数据库(order, order_item, order_status_log)"
Client->>Transition : 请求变更订单状态(订单号, 新状态, 操作者, IP, 原因)
Transition->>DB : 读取订单当前状态
Transition->>Transition : 校验状态合法性与迁移规则
alt 合法且需要调整
Transition->>DB : 开始事务
Transition->>DB : 更新order.status
Transition->>DB : 更新order_item.order_status
Transition->>DB : 插入order_status_log(来源→目标, 原因, 操作者, IP)
alt 目标为已完成
Transition->>DB : 更新order.shipped_at/completed_at/allow_aftersale/allow_comment
else 目标为已取消
Transition->>DB : 更新order.closed_at/cancel_reason
end
Transition->>DB : 提交事务
else 非法或无需变更
Transition-->>Client : 返回错误/忽略
end
详细组件分析
订单主表(order)设计
- 字段分组
- 标识与归属:id、order_sn、user_id、direct_user_id、indirect_user_id
- 业务上下文:mode、module、category_id、contact_id、email
- 交易与履约:pay_id、shipping_id、tracking_no、shipping_fee、item_amount、order_amount、order_point、direct_reward、indirect_reward
- 时间戳:created_at、paid_at、shipped_at
- 控制位:allow_aftersale、aftersale_status、allow_comment、item_link_status
- 状态:status
- 设计要点
- 金额字段保留原值供格式化展示,不做强转,确保精度与显示一致。
- 时间字段用于统计口径:paid_at 用于销售统计(成交额、订单数、付费会员数),created_at 用于漏斗统计(下单流向)。
- 模块与类目维度支持按 module/category_id 做聚合分析。
- 常用查询能力
- 按用户、订单号、状态、时间窗筛选
- 聚合:成交额、订单数、支付方式分布、Top商品/分类/客户、新客 vs 复购客
- 趋势:按日/按月聚合 revenue 与 orders
订单商品明细(order_item)设计
- 字段分组
- 关联键:order_id、user_id、item_id
- 商品维度:name、module、category_id(用于统计 Top 商品与分类)
- 交易维度:sale_price、item_number(用于计算收入与销量)
- 设计要点
- 与订单主表一对多关联,支撑销量、收入、类目构成等统计。
- 状态随订单状态变更而级联更新,保证列表与报表一致性。
- 常用查询能力
- JOIN order 按 paid_at 窗口聚合销量与收入
- 按 category_id/module 维度拆解销售组成
订单状态流水(order_status_log)设计
- 字段分组
- 关联键:order_id
- 操作者:operator_type、operator_id、ip
- 内容:from_status、to_status、reason
- 时间:created_at
- 设计要点
- 每次状态变更写入一行,形成可追溯的时间线。
- 排序默认按 created_at ASC、id ASC,便于前端渲染时间轴。
- 常用查询能力
- 按订单筛选,获取状态变更历史
订单收货地址快照(order_address)设计
- 字段分组
- 关联键:order_id、user_id
- 时间:created_at
- 设计要点
- 下单瞬间冻结收货信息,与会员地址本解耦,保障历史订单地址不变。
- 常用查询能力
- 按订单筛选获取收货快照
订单优惠券(order_coupon)设计
- 字段分组
- 关联键:order_id、coupon_id、coupon_log_id
- 时间:created_at
- 设计要点
- 一单可叠加多张券(多行记录),金额字段保留原值供展示。
- 常用查询能力
- 按订单筛选查看使用的优惠券集合
订单发票(order_invoice)设计
- 字段分组
- 关联键:order_id
- 状态:is_issued
- 时间:issued_at、created_at
- 设计要点
- 一单一行,记录发票申请与开具状态。
- 常用查询能力
- 按订单筛选查看发票状态
订单退款单(order_refund)设计
- 字段分组
- 关联键:order_id、aftersale_id、order_payment_id
- 时间:refunded_at、created_at
- 设计要点
- 每笔退款一行,按原始支付ID指向具体支付腿,支持混合支付分渠道退款。
- 常用查询能力
- 按订单与状态筛选退款记录
订单状态机与生命周期
- 状态枚举
- pending、awaiting_confirmation、paid、completed、cancelled、refunding、refunded、partial_refunded
- 迁移规则
- pending → awaiting_confirmation/paid/cancelled
- awaiting_confirmation → paid/pending/cancelled
- paid → completed/refunding
- completed → refunding
- refunding → refunded/partial_refunded/paid
- partial_refunded → refunding
- refunded/cancelled 为终态
- 特殊处理
- 无物流插件或非商品模块时,paid 直接跨到 completed
- completed 时设置 shipped_at/completed_at,开启售后与评论
- cancelled 时记录 closed_at/cancel_reason
stateDiagram-v2
[*] --> pending
pending --> awaiting_confirmation : "上传凭证"
pending --> paid : "支付成功"
pending --> cancelled : "超时未付/主动取消"
awaiting_confirmation --> paid : "审核通过"
awaiting_confirmation --> pending : "审核驳回"
awaiting_confirmation --> cancelled : "取消"
paid --> completed : "发货完成/无物流"
paid --> refunding : "发起售后"
completed --> refunding : "发起售后"
refunding --> refunded : "全额退款"
refunding --> partial_refunded : "部分退款"
refunding --> paid : "售后驳回"
partial_refunded --> refunding : "继续退"
订单金额计算与优惠/积分/运费
- 金额字段
- item_amount:商品金额合计
- shipping_fee:运费
- order_amount:订单实付金额(含优惠、积分抵扣后的最终应付)
- order_point:积分抵扣
- direct_reward/indirect_reward:分销奖励
- 计算与落点
- 商品金额与数量来自 order_item(sale_price × item_number)
- 优惠券使用记录在 order_coupon,金额原值保留
- 积分抵扣在 order.order_point 体现
- 运费在 order.shipping_fee 体现
- 最终应付 order_amount 由结算链路计算并落库
- 支付与时间
- 支付成功后更新支付台账并设置 paid_at
- 完成时设置 shipped_at/completed_at,允许售后与评论
订单拆分与合并
- 拆分
- 通过 order_item 的多行记录自然表达一个订单包含多个商品,支持按商品维度统计与发货。
- 合并
- 若需将多个订单合并为一个,可在业务层创建新的 order 并重建 order_item 集合,保持历史订单不可变;必要时通过售后或重拍实现。
- 数据一致性
- 任何拆分/合并操作应伴随状态流水记录,确保可审计。
订单取消与退款
- 取消
- 状态迁移至 cancelled,记录 closed_at 与 cancel_reason
- 退款
- 进入 refunding,最终落定 refunded(全额)或 partial_refunded(部分)
- 每笔退款一行,按 order_payment_id 指向原始支付,支持分渠道退款
- 退款完成后,订单金额退减由退款表独立扣减,不影响 order_amount 的历史口径
依赖关系分析
- 订单主表与明细表:一对多关系,支撑销量与收入统计
- 订单与地址快照:一对一关系,冻结收货信息
- 订单与优惠券:一对多关系,支持多券叠加
- 订单与发票:一对一关系,记录发票状态
- 订单与退款单:一对多关系,支持分渠道退款
- 订单与状态流水:一对多关系,记录状态变更时间线
- 状态机与支付服务:支付成功后更新支付台账并联动订单时间字段
erDiagram
ORDER ||--o{ ORDER_ITEM : "包含"
ORDER ||--|| ORDER_ADDRESS : "收货快照"
ORDER ||--o{ ORDER_COUPON : "使用"
ORDER ||--|| ORDER_INVOICE : "发票"
ORDER ||--o{ ORDER_REFUND : "退款"
ORDER ||--o{ ORDER_STATUS_LOG : "状态流水"
性能考虑
- 索引建议
- order:order_sn(唯一)、user_id、status、paid_at、created_at、module、category_id
- order_item:order_id、item_id、category_id、module
- order_status_log:order_id、created_at
- order_address:order_id
- order_coupon:order_id、coupon_id
- order_invoice:order_id
- order_refund:order_id、order_payment_id、status
- 查询优化
- 使用 paid_at 时间窗进行销售统计,避免全表扫描
- 聚合查询尽量利用 GROUP BY 与 LIMIT,减少结果集
- 大表 JOIN 时优先过滤条件再连接,如先按 paid_at 过滤 order 再 JOIN order_item
- 分页与缓存
- 列表页采用游标或基于 id 的分页,避免深翻页
- 热点统计(如 Top 商品、支付方式分布)可缓存结果
- 归档策略
- 历史订单可按年/月归档到冷存储,主库仅保留近期活跃数据
- 状态流水可定期压缩或归档,降低热表体积
故障排查指南
- 状态异常
- 检查 OrderStatus::canTransit 是否允许该迁移
- 查看 order_status_log 最近一条记录,确认 from/to 与 reason
- 支付未到账
- 核对 payment 状态是否为成功,paid_at 是否设置
- 检查 order 状态是否处于可收款状态(pending/awaiting_confirmation/paid/completed)
- 退款不一致
- 核对 order_refund 的 order_payment_id 与退款金额
- 确认订单状态是否已落定为 refunded/partial_refunded
- 地址错乱
- 检查 order_address 是否按订单正确快照
- 确认后续地址本修改未影响历史订单
结论
DouPHP 订单模块通过清晰的表结构与状态机设计,实现了订单全生命周期的可追踪与可扩展。订单主表承载全局信息与金额汇总,明细表支撑销量与收入统计,地址快照、优惠券、发票、退款单与状态流水分别承担各自职责,共同构成完整的订单数据模型。配合合理的索引与查询策略,可满足大数据量下的性能需求。开发者在扩展功能时,应遵循现有模型约定,确保数据一致性与可审计性。
附录
- 常见统计口径
- 成交额:SUM(order_amount) WHERE paid_at ∈ [from, to)
- 订单数:COUNT(*) WHERE paid_at ∈ [from, to)
- 付费会员数:COUNT(DISTINCT user_id) WHERE paid_at ∈ [from, to) AND user_id > 0
- 新客 vs 复购:基于首次付款时间区分
- 关键方法路径
- 订单统计:Order::sumPaidRevenue / countPaidOrders / trendDaily / topProducts / categoryBreakdown / paymentGatewayBreakdown / topCustomers / newVsReturning
- 状态变更:OrderStatusTransition::changeStatus
- 支付回调:PaymentService 中标记支付成功并更新时间