电商履约与发货系统怎么设计?一次讲清拆单、配仓、发货单、物流回传与状态联动
大家好,我是一名有 4 年工作经验的 Java 后端开发。
订单创建出来以后,真正把货送到用户手里,这中间其实还有一整段很容易被低估的履约链路。
这篇文章我想系统聊一聊电商履约与发货系统到底应该怎么设计。
🦅个人主页
🐼
文章目录
- 电商履约与发货系统怎么设计?一次讲清拆单、配仓、发货单、物流回传与状态联动
- 一、履约系统到底在做什么
- 二、为什么订单状态和履约状态不能混成一个字段
- 三、推荐的核心模型
- 3.1 订单表
- 3.2 发货单表
- 3.3 发货单明细表
- 3.4 物流轨迹表
- 四、典型流程怎么走
- 4.1 支付成功
- 4.2 配仓
- 4.3 生成发货单
- 4.4 推物流
- 4.5 回传物流状态
- 五、最关键的几个设计点
- 5.1 拆单能力
- 5.2 部分发货能力
- 5.3 发货动作幂等
- 5.4 物流状态回传不要直接覆盖订单状态
- 六、数据库示例
- 6.1 发货单表
- 6.2 发货单明细表
- 6.3 物流轨迹表
- 七、最容易踩的坑
- 7.1 订单状态和发货状态混成一个字段
- 7.2 没有发货单模型
- 7.3 物流回调直接改订单状态
- 7.4 人工补发和系统发货不统一
- 八、面试中怎么回答
- 九、总结
- 十、结尾
一、履约系统到底在做什么
很多人会简单理解成:
- 支付后发货
但真实履约链路通常包含:
- 订单拆单
- 仓库分配
- 发货单生成
- 物流面单
- 物流状态回传
- 签收 / 失败 / 拒收处理
所以履约系统本质上是在解决:
订单如何从“支付成功”变成“真实发货并可追踪履约过程”。
二、为什么订单状态和履约状态不能混成一个字段
很多系统一开始只在订单表里放一个status。
但很快就会发现不够:
- 订单状态是
PAID - 履约可能还在“待配仓”
- 也可能已经“部分发货”
- 也可能“物流已签收”
所以我更建议至少拆两层:
订单状态履约 / 发货状态
必要时再拆:
物流状态
三、推荐的核心模型
我建议至少拆这些表:
3.1 订单表
表示交易本身。
3.2 发货单表
表示一次真实发货动作。
3.3 发货单明细表
表示这次发货发了哪些 SKU。
3.4 物流轨迹表
表示物流回传节点。
这样做的好处是:
- 一个订单可拆多次发货
- 一个订单可部分发货
- 物流状态单独维护
四、典型流程怎么走
4.1 支付成功
- 订单状态改为
PAID - 进入履约待处理队列
4.2 配仓
- 根据仓库库存、地区、运费、时效选择仓库
4.3 生成发货单
- 生成履约单 / 发货单
- 扣减真实库存
4.4 推物流
- 调快递接口
- 生成运单号
4.5 回传物流状态
- 已揽件
- 运输中
- 派送中
- 已签收
五、最关键的几个设计点
5.1 拆单能力
比如一个订单有多个商品:
- 来自不同仓库
- 或一个仓库缺货
这时一个订单就可能拆成多张发货单。
5.2 部分发货能力
不是所有订单都能一次发完。
所以履约系统要支持:
- 部分发货
- 剩余待发货
5.3 发货动作幂等
物流接口、仓库回调、人工补发都可能重复触发,所以发货动作本身也要有幂等控制。
5.4 物流状态回传不要直接覆盖订单状态
物流状态更新应该先更新物流 / 发货单层,再根据规则决定是否联动订单状态。
六、数据库示例
6.1 发货单表
CREATETABLEshipment_order(idBIGINTPRIMARYKEYAUTO_INCREMENT,order_idBIGINTNOTNULL,warehouse_idBIGINTNOTNULL,shipment_statusVARCHAR(32)NOTNULL,express_companyVARCHAR(64)DEFAULTNULL,express_noVARCHAR(64)DEFAULTNULL,shipped_atDATETIMEDEFAULTNULL,created_atDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMP);6.2 发货单明细表
CREATETABLEshipment_order_item(idBIGINTPRIMARYKEYAUTO_INCREMENT,shipment_order_idBIGINTNOTNULL,order_item_idBIGINTNOTNULL,sku_idBIGINTNOTNULL,quantityINTNOTNULL);6.3 物流轨迹表
CREATETABLElogistics_trace(idBIGINTPRIMARYKEYAUTO_INCREMENT,shipment_order_idBIGINTNOTNULL,trace_statusVARCHAR(32)NOTNULL,trace_contentVARCHAR(255)NOTNULL,trace_timeDATETIMENOTNULL);七、最容易踩的坑
7.1 订单状态和发货状态混成一个字段
后面很难支持部分发货和多次发货。
7.2 没有发货单模型
很多物流、仓库、售后逻辑都没法稳定承接。
7.3 物流回调直接改订单状态
中间缺少履约层,后面会非常乱。
7.4 人工补发和系统发货不统一
很容易导致状态、日志、库存对不上。
八、面试中怎么回答
如果面试官问你:
电商履约和发货系统一般怎么设计?
你可以这样回答:
第一,我不会把履约简单理解成订单支付后直接发货,而是会把它拆成配仓、发货单生成、物流推送、轨迹回传几个阶段。
第二,我一般不会只在订单表里维护一个发货状态,而是会单独设计发货单和发货单明细表,这样才能支持拆单、部分发货和多次发货。
第三,物流状态和订单状态我会尽量解耦,物流回传先更新履约层,再根据规则去联动订单状态,而不是直接在物流回调里改订单状态。
第四,发货动作本身要做幂等,人工补发、仓库回调、重复通知都不能把状态搞乱。
九、总结
履约系统真正难的不是“发货”两个字,而是如何把:
- 订单
- 仓库
- 发货单
- 物流轨迹
- 状态联动
真正拆清楚。
如果只记一句结论,我觉得可以记住这句:
电商履约最稳的设计不是订单表里多加几个字段,而是把订单层、发货单层、物流层真正拆开。
十、结尾
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注。
后面我会继续整理一些更偏实战的 Java 后端和电商系统设计文章。