简介
本设计文档围绕 DouPHP 电商系统的订单主表(dou_order)展开,系统梳理订单主表的核心字段、订单号生成规则、用户关联、商品快照、金额计算、状态管理等关键业务设计;并给出订单生命周期状态流转、拆分合并、优惠券使用、积分抵扣、运费计算等复杂场景的数据模型与处理流程。同时提供面向查询优化与大数据量处理的实践建议,帮助开发者在现有代码基础上进行扩展与维护。
项目结构
订单相关数据模型与核心逻辑分布在以下位置:
- 数据库定义:模块备份 SQL 中定义了 dou_order 及关联表(地址、条目、发票、支付、退款、状态日志等)。
- 后台模型:admin/model/order 下为各表的 ORM 模型与常用筛选器。
- 核心服务:core/service/order 与 core/foundation/order 提供订单状态机、状态迁移、订单号生成、付款后联动等能力。
- 支付服务:core/service/payment 负责支付回调与幂等处理。
graph TB
subgraph "数据层"
O["dou_order"]
OA["dou_order_address"]
OI["dou_order_item"]
OC["dou_order_coupon"]
OP["dou_order_payment"]
ORF["dou_order_refund"]
OS["dou_order_status_log"]
end
subgraph "领域服务"
OST["OrderStatusTransition"]
PS["PaymentService"]
OSN["OrderStatus(枚举)"]
end
subgraph "模型层"
MOrder["Order(后台模型)"]
MItem["OrderItem"]
MAddr["OrderAddress"]
MCoupon["OrderCoupon"]
MInv["OrderInvoice"]
MRef["OrderRefund"]
end
MOrder --> O
MItem --> OI
MAddr --> OA
MCoupon --> OC
MRef --> ORF
MInv --> O
OST --> O
OST --> OI
OST --> OS
PS --> OP
OST --> OSN
核心组件
- 订单主表(dou_order):承载订单全局信息,包括订单号、用户、模块、分类、收货地址、支付方式、物流方式、金额、时间戳、售后与评价开关、父订单、取消原因、退款状态、来源、状态等。
- 订单条目(dou_order_item):记录每个商品的快照(名称、原价、实付价、数量、属性、是否锁定库存、售后与评价标记、自定义字段等)。
- 订单地址快照(dou_order_address):下单瞬间冻结的收件人信息,独立于用户地址本。
- 订单优惠券(dou_order_coupon):一单可叠加多张券,记录券ID、券流水、减免金额与类型。
- 订单发票(dou_order_invoice):一单一行,记录发票类型、抬头、税号、邮箱、是否已开具等。
- 订单支付(dou_order_payment):记录每笔支付流水、网关、金额、状态、第三方交易号、凭证、原始报文、支付时间等。
- 订单退款(dou_order_refund):按支付腿分别退款,记录退款单号、渠道、金额、状态、回调、退款时间等。
- 订单状态日志(dou_order_status_log):记录每次状态变更的前后状态、原因、操作者、IP、时间等。
架构总览
订单主表处于订单域的核心,向上承接前端/管理端请求,向下通过状态机与服务编排完成状态迁移、金额结算、库存扣减、积分与分销联动、发票与退款等。
sequenceDiagram
participant C as "调用方"
participant S as "OrderStatusTransition"
participant DB as "数据库"
participant P as "PaymentService"
participant L as "日志/事件"
C->>S : "变更订单状态(新状态, 原因)"
S->>DB : "校验状态合法性 & 读取当前状态"
S->>DB : "更新 order.status / order_item.order_status"
S->>DB : "写入 order_status_log"
alt "状态=PAID"
S->>DB : "设置 paid_at"
S->>DB : "扣减库存/销售统计(若启用)"
S->>DB : "解锁库存标记"
S->>L : "派发 ORDER_PAID 场景事件(事务外)"
S->>S : "发放积分/分销奖励(幂等)"
else "状态=COMPLETED"
S->>DB : "设置 shipped_at/completed_at/允许售后/允许评价"
else "状态=CANCELLED"
S->>DB : "设置 closed_at/cancel_reason"
end
Note over S,P : "支付回调由 PaymentService 维护支付腿状态"
详细组件分析
订单主表(dou_order)字段设计与业务含义
- 标识与关联
- id:自增主键
- order_sn:唯一订单号(用于对外展示与对账)
- user_id:下单会员ID(支持游客单时可为0)
- direct_user_id / indirect_user_id:直推/间推推荐人ID(用于分销奖励)
- 业务上下文
- mode:支付模式(如 money)
- module:所属模块(product/vip 等),影响后续联动策略
- category_id:商品分类ID(便于统计)
- contact_id:收货地址ID(快照在 order_address)
- email:下单时邮箱
- 支付与物流
- pay_id:支付方式标识
- shipping_id:配送方式标识
- tracking_no:物流单号
- shipping_fee:配送费
- 金额与优惠
- item_amount:商品总金额
- order_amount:订单总金额(含运费、优惠后的应付)
- wallet_paid / gateway_paid:钱包支付与网关支付金额(混合支付)
- order_point:订单赠送积分(用于统计或展示)
- 分销与奖励
- direct_reward / indirect_reward:直推/间推奖励金额
- 时间与状态
- paid_at / shipped_at / closed_at / completed_at:关键时间点
- allow_aftersale / aftersale_status:是否允许售后与售后状态
- allow_comment:是否允许评价
- item_link_status:是否联动模块商品状态
- parent_order_id:父订单ID(拆分/合并场景)
- cancel_reason:取消原因
- refund_status:退款状态
- buyer_message / seller_message:买家/卖家留言
- source:来源(web/app 等)
- status:订单状态(字符串枚举,见 OrderStatus)
订单号生成规则
- 生成算法:采用“年月日时分秒 + 2位随机数 + 用户编号后缀”的组合,冲突时重试最多5次,仍冲突则用微秒高熵兜底,确保唯一性且不超过 varchar(20) 长度限制。
- 幂等与并发:通过唯一索引 order_sn 保证最终一致性;生成过程在写订单前执行,避免重复。
用户关联与商品快照
- 用户关联:通过 user_id 关联用户表;direct_user_id / indirect_user_id 用于分销链路追踪。
- 商品快照:order_item 记录下单时的商品名称、原价、实付价、数量、属性、属性名、是否锁定库存、售后与评价标记、自定义字段等,确保历史可追溯。
金额计算与优惠/积分/运费
- 金额口径
- item_amount:商品合计
- shipping_fee:运费
- order_amount:订单应付总额(包含运费与优惠后的最终应付)
- wallet_paid / gateway_paid:混合支付拆分
- 优惠券:order_coupon 记录每张券的减免金额与类型,支持一单多券叠加。
- 积分:order_point 记录订单赠送积分;付款后根据配置按比例发放到用户积分账户(幂等守卫)。
- 运费:shipping_fee 作为独立字段参与订单总额计算,便于报表与对账。
状态管理与生命周期流转
- 状态集合:pending、awaiting_confirmation、paid、completed、cancelled、refunding、partial_refunded、refunded。
- 合法迁移:通过 OrderStatus::canTransit 表驱动校验,防止非法跳转。
- 关键路径
- 待付款 → 已付款:支付成功后进入 paid;若无物流插件或非 product 模块,自动推进至 completed。
- 已付款 → 已完成:有物流业务在发货完成后进入 completed;无物流直接跨到 completed。
- 已付款/已完成 → 退款中:售后审核通过后进入 refunding;退款落定后进入 refunded(全额)或 partial_refunded(部分)。
- 待付款 → 已取消:超时未付或主动取消进入 cancelled,并记录关闭时间与原因。
- 付款后联动:扣减库存、解锁库存标记、派发场景事件、发放积分与分销奖励、会员等级升级检查(均在事务提交后执行,失败不回滚状态)。
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 : "部分退款"
partial_refunded --> refunding : "继续退款"
订单拆分与合并
- 拆分:通过 parent_order_id 建立父子订单关系,子订单可独立支付、发货与售后;主订单聚合子订单状态与金额。
- 合并:可在业务层将多个子订单合并为一个主订单进行统一结算与发货(需结合模块实现)。
- 注意:拆分/合并需保证金额分摊、优惠分摊、库存扣减与状态同步的一致性。
优惠券使用与金额分摊
- 一单多券:order_coupon 支持多行记录,便于叠加优惠。
- 分摊策略:建议在订单创建时按商品金额比例分摊优惠券减免,并在 order_item 中记录分摊结果,便于售后与退款精确处理。
积分抵扣与发放
- 积分发放:付款成功后按订单金额与配置比例发放积分,具备幂等保护(基于 from=order_sn 去重)。
- 积分抵扣:可在下单阶段选择使用积分抵扣部分金额,需在 order_amount 与 wallet_paid/gateway_paid 中体现抵扣与剩余支付。
运费计算
- 运费字段:shipping_fee 独立存储,便于报表统计与对账。
- 计算时机:下单时根据收货地址、商品重量/体积、活动规则计算并写入;修改地址或商品时需重新计算。
支付与退款
- 支付:order_payment 记录每笔支付流水、网关、金额、状态、第三方交易号、凭证、原始报文、支付时间;支付回调幂等更新状态。
- 退款:order_refund 按支付腿分别退款,记录退款单号、渠道、金额、状态、回调、退款时间;支持部分退款与全额退款。
依赖关系分析
- 状态机依赖:OrderStatusTransition 依赖 OrderStatus 枚举与数据库表,负责状态迁移与副作用。
- 支付服务依赖:PaymentService 依赖 order_payment 表与订单状态,确保支付回调幂等与一致性。
- 模型层依赖:各后台模型封装了常用筛选与类型转换,提升可读性与复用性。
classDiagram
class OrderStatus {
+PENDING
+AWAITING_CONFIRMATION
+PAID
+COMPLETED
+CANCELLED
+REFUNDING
+REFUNDED
+PARTIAL_REFUNDED
+canTransit(from,to) bool
+all() array
+isValid(status) bool
}
class OrderStatusTransition {
+changeStatus(order_sn,new_status,...) void
+createOrderSn(user_sn) string
+writePayId(order_sn,pay_id) bool
+retryPaidEffects(order_sn) bool
}
class PaymentService {
+handleCallback(payment,transactionId,callback) bool
}
OrderStatusTransition --> OrderStatus : "使用"
PaymentService --> OrderStatus : "校验订单可收款状态"
性能与大数据方案
- 索引设计
- 唯一索引:order_sn(订单号唯一)
- 复合索引:user_id+status、status+created_at、paid_at、status+paid_at、pay_id+status+paid_at(覆盖常见查询与统计)
- 查询优化
- 使用 paid_at 时间窗进行成交额与订单数统计,减少全表扫描
- 列表页按 created_at 倒序分页,避免深分页
- 预加载关联(如 user)减少 N+1 查询
- 大数据处理
- 按月/年归档历史订单(按 paid_at 或 created_at 分区)
- 读写分离:报表走只读库,交易走主库
- 异步化:付款后联动(积分、分销、等级升级)在事务外执行,降低主流程延迟
- 缓存策略
- 热点订单详情可缓存短时(如支付状态)
- 统计指标(日/月趋势)可定时刷新至缓存
故障排查指南
- 状态异常
- 检查 OrderStatus::canTransit 是否允许该迁移
- 查看 order_status_log 获取前后状态与原因
- 支付问题
- 核对 order_payment 的状态与 transaction_id
- 确认订单状态是否为可收款状态(pending/awaiting_confirmation/paid/completed)
- 取消与退款
- 关注 closed_at 与 cancel_reason
- 检查 order_refund 的 channel、amount、status 与 raw_callback
- 库存与售后
- 检查 order_item.stock_lock 与 aftersale 标记
- 确认模块是否启用库存功能
结论
DouPHP 的订单主表以简洁而完备的字段设计支撑了电商订单的全生命周期管理。通过字符串状态枚举与表驱动迁移校验,保证了状态流转的可控性与可审计性;配合独立的支付与退款表、地址与发票快照、订单条目明细,实现了金额、优惠、运费、积分与分销的精细化处理。借助合理的索引与统计方法,以及事务外联动的异步化设计,系统在可扩展性与性能方面具备良好的基础。
附录
- 常用统计接口参考
- 实付订单额、订单数、付费会员数、新付费会员数
- 日/月趋势、状态漏斗、Top 商品、分类组成、支付方式组成、Top 客户、新客 vs 复购客
- 模型筛选器参考
- 按用户、订单号、状态、时间范围、模块筛选
- 预加载用户、默认排序