物流业务流程设计
本文以 WinTradeCloudService 后端物流接口、ops 运营小程序页面和现有 doc/API/物流履约.md 为准,梳理从商户发货、国内仓作业、跨仓中转、海外仓入库、海外仓派送到配送员签收的完整物流流程。本文用于指导后端、ops、admin 和 client 的联调,不替代 API 分类文档。
范围和端别
| 端别 | 主要职责 | 对应代码 |
|---|---|---|
ops |
商户发货、国内仓快速作业、海外仓入库、海外仓派送、配送员任务 | ops/pages/*、ops/api/logistics.js |
admin |
物流基础资料、仓库、路线、车次、批次、运单、报关、平台查询和人工处理 | admin/src/api/*、WinTradeCloudService/wt-admin |
client |
消费者订单物流查询、物流轨迹展示、收货和售后入口 | client/api/* |
| 后端 | 物流状态机、单据关系、库存流水、轨迹、权限和业务校验 | WinTradeCloudService/wt-admin、wt-client、wt-business、wt-logistics |
后端组件分工
物流流程由 wt-logistics 维护核心单据和状态,订单、商户库存和消息等副作用由其他模块协同。
| 后端能力 | 职责 |
|---|---|
| 发货单组件 | 承接订单支付后的履约需求,记录发货单和明细 |
| 包裹组件 | 创建包裹、维护包裹状态、关联包裹类型和件级单元 |
| 运单组件 | 创建内部运单、第三方运单号、运单段和轨迹 |
| 仓入库组件 | 处理到仓确认、入库预查询、正式入库和回退 |
| 仓库存组件 | 维护包裹所在仓库、库位、复核状态和库存流水 |
| 仓中转组件 | 创建中转上下文、批次加包、封批、封车和出库 |
| 仓派送组件 | 创建派送上下文、分拣加包、完成分拣、分配配送员 |
| 配送员组件 | 限制配送员只能查询和操作本人任务 |
| 订单联动组件 | 签收或退货后推进订单确认、售后和结算条件 |
联调时不要只看包裹表状态。一次作业可能同时更新包裹、仓库存、运单轨迹、分拣任务、派送任务和订单状态。
核心对象
| 对象 | 说明 | 关键字段 |
|---|---|---|
| 履约单 | 订单支付后生成的物流履约单 | deliveryOrderId、deliveryNo、deliveryStatus |
| 履约明细 | 单个订单商品或发货项 | deliveryOrderItemId、plannedQty、actualShipTime |
| 包裹 | 物流流转核心实体 | packageId、packageNo、packageStatus、currentWarehouseId、currentStorageId |
| 运单 | 对内或对外物流单据,承载多段运输和轨迹 | waybillId、waybillNo、currentWaybillItemId、waybillStatus |
| 运单段 | 一段物流运输或仓作业节点 | waybillItemNo、segmentSeq、stageType、segmentBizCode |
| 车次 | 仓间运输计划 | shipmentId、shipmentNo、shipmentStatus |
| 批次 | 车次下的包裹集合 | batchId、batchNo、batchStatus |
| 分拣任务 | 仓内中转或派送前的包裹处理任务 | sortingTaskId、sortingTaskStatus |
| 派送任务 | 仓库创建并分配给配送员的末端任务 | dispatchTaskId、dispatchTaskStatus、employeeAccountId |
| 派送明细 | 派送任务下的单个包裹 | dispatchTaskItemId、dispatchTaskItemStatus、packageId |
总体流程
总体原则:
- 前端不保存流程关键状态作为事实来源。用户退出应用后,重新进入应通过
shipmentNo、waybillNo、packageNo或任务列表重新查询后端,恢复当前可继续操作的步骤。 warehouseId、warehouseStorageId、shipmentId、batchId、sortingTaskId、dispatchTaskId必须来自后端查询结果或用户明确选择,不能传undefined、空字符串或前端猜测值。- 入库、复核、中转、派送都是后端状态机动作。前端只展示可执行按钮和接口错误原因,不绕过后端状态校验。
- 物流轨迹展示面向消费者时优先使用业务编号,例如
waybillNo、packageNo、externalWaybillNo,不要把纯数据库ID当作用户可识别编号。
状态模型
包裹状态
| 状态 | 中文含义 | 进入方式 | 后续动作 |
|---|---|---|---|
CREATED |
已创建 | 商户发货或包裹建档 | 交承运或进入仓流程 |
INBOUND |
已入库 | 仓入库执行、国内快速流程入库 | 仓内复核 |
STORED |
已上架 | 复核通过后从 INBOUND 变更 |
中转或派送 |
SORTED |
已分拣 | 加入中转批次并完成分拣 | 封批、封车 |
BATCHED |
已分批 | 批次绑定 | 封批或调整 |
LOADED |
已装车 | 车次封车 | 发车出库 |
IN_TRANSIT |
运输中 | 中转发车出库 | 到仓确认 |
ARRIVED |
已到仓 | 车次到达目标仓或派送失败退仓 | 入库、复核或派送 |
DISPATCHED |
已派送 | 完成派送分拣并出库 | 配送员签收或失败 |
SIGNED |
已签收 | 配送员签收 | 订单完成条件检查 |
ERROR |
异常 | 派送失败或异常处理 | 退仓、人工处理 |
运单状态
| 状态 | 中文含义 | 说明 |
|---|---|---|
WAITING |
待揽收 | 运单创建后等待承运或仓作业启动 |
SHIPPED |
已揽收 | 首段或当前段已交接 |
TRANSPORTING |
运输中 | 干线、中转或承运运输中 |
DELIVERING |
派送中 | 末端配送中 |
COMPLETED |
已签收 | 当前运单完成,可能表示运输段完成,也可能表示全部签收完成 |
ERROR |
异常 | 当前运单异常 |
CANCELLED |
已取消 | 运单取消 |
注意:waybillStatus = COMPLETED 不一定代表包裹已完成末端派送。跨仓运输段完成时,运单可能已经 COMPLETED,但包裹仍可能处于 INBOUND、STORED 或 ARRIVED,仍需海外仓继续处理。
车次、批次和任务状态
| 对象 | 状态 | 中文含义 | 联调关注点 |
|---|---|---|---|
| 车次 | WAITING |
待发货 | 可创建批次、加包、封车 |
| 车次 | SHIPPED |
已发货 | 运输中,目标仓可查询待到仓车次 |
| 车次 | COMPLETED |
已签收 | 车次到达完成,后续进入仓入库 |
| 批次 | CREATED |
已创建 | 可加包 |
| 批次 | SORTING |
分拣中 | 可继续扫码加包 |
| 批次 | SORTED |
已分拣 | 可封车或发运 |
| 批次 | LOADED |
已装车 | 可发车出库 |
| 批次 | SHIPPED |
已发运 | 等待目标仓到达 |
| 批次 | ARRIVED |
已到达 | 可入库 |
| 批次 | COMPLETED |
已完成 | 入库已完成 |
| 分拣任务 | CREATED |
已创建 | 待开始 |
| 分拣任务 | SORTING |
分拣中 | 可加包、移除包裹 |
| 分拣任务 | COMPLETED |
已完成 | 不可继续加包,除非回退 |
| 派送任务 | CREATED |
已创建 | 可分配配送员或继续加包 |
| 派送任务 | ASSIGNED |
已分派 | 已有配送员,可完成分拣出库 |
| 派送任务 | DISPATCHED |
配送中 | 配送员可签收或失败 |
| 派送任务 | COMPLETED |
已完成 | 所有明细完成 |
商户发货流程
商户发货是物流链路起点,ops 的商户发货页负责展示待发货履约明细,并提交发货动作。后端会创建包裹、运单和首段运单段,后续仓库和配送流程围绕包裹继续推进。
联调要点:
- 发货明细必须来自后端履约单,不应由前端自行构造商品数量。
- 包裹创建后至少要能通过
packageNo或waybillNo查到后续物流链。 - 第三方运单号
externalWaybillNo只作为识别输入之一,不应替代平台内部waybillNo。
国内仓快速流程
国内仓当前有快速入库出库流程,用于把商户发来的包裹快速整理成中转车次,发往海外仓。该流程在 ops 的 warehouse-operation 页面承载。
联调要点:
- 快速流程中车次、批次、分拣任务、包裹状态由后端统一维护。
- 扫码识别顺序以后端为准,通常支持
packageNo、waybillNo和externalWaybillNo。 - 封批后不应继续加包;如需调整,必须走重开批次或回退接口。
- 发车出库后包裹进入
IN_TRANSIT,目标海外仓后续通过车次号或待入库车次列表继续操作。
仓间中转流程
仓中转用于任意两个仓库之间的标准运输,不限于国内仓到海外仓。后端入口为 /api/v1/logistics/warehouse/transfer。
可中断恢复:
- 如果已创建中转上下文但没有加包,下次进入通过中转车次分页或任务分页查询上下文,继续创建批次或加包。
- 如果已封批但未封车,下次通过车次详情查到
SORTED批次,继续封车。 - 如果已封车但未发车,下次通过车次详情查到
LOADED批次或车次状态,继续出库。 - 如果已发车,则起始仓不能继续调整包裹,目标仓通过入库查询接手。
海外仓到仓、入库和复核
海外仓目前没有独立的 /api/v1/logistics/overseas-warehouse/... Controller,使用通用仓接口 /api/v1/logistics/warehouse/... 和 /api/v1/logistics/warehouse-inventory/...。后端场景组件会校验仓库是否为海外仓。
关键规则:
- 查询车次时不能传
warehouseId=undefined。未选择仓库时应省略warehouseId参数,或先要求用户选择仓库。 - 用户退出应用不影响流程。重新进入后输入
shipmentNo,前端重新查询待入库车次、中转车次和车次详情,判断应从到仓确认、入库预查询、正式入库还是复核继续。 - 包裹
INBOUND表示已经入库但未完成复核。复核后包裹通常变为STORED。 - 如果运单段已经
COMPLETED,但仓库存包裹仍是INBOUND且reviewed = false,下一步仍应执行仓内复核,而不是认为末端流程已经结束。
海外仓派送流程
海外仓派送负责把已到达或已上架包裹转成派送任务,完成分拣出库并分配配送员。后端入口为 /api/v1/logistics/warehouse/dispatch。
当前联调约定:
- 派送加包允许同仓
ARRIVED或STORED包裹,但必须满足reviewed = true,并通过库位和目的地区校验。INBOUND包裹必须先复核。 - 如果加包失败,应优先检查当前仓库、当前库位、目的地区、复核状态和是否存在其他未完成的分拣或派送任务。
- 分配配送员可以在完成分拣前或后执行,但配送员任务页只有在任务归属到当前配送员后才能查到本人任务。
- 完成分拣会把包裹从仓内状态推进到
DISPATCHED,这是配送员签收或失败的前置条件。
配送员任务流程
配送员通过 ops 的 courier-tasks 页面查询本人任务,只能操作分配给自己的派送明细。
联调要点:
sign、fail和return-to-warehouse使用配送员专用接口/api/v1/logistics/dispatcher/task。- 配送员查询使用
/api/v1/logistics/dispatcher/query,后端根据当前登录用户限制数据范围。 - 派送失败退仓后,包裹不是完成态,应回到仓内可重新派送状态。
运单查询和继续处理
运单查询不能只看 waybillStatus,必须同时看包裹状态、当前仓库、当前库位、运单段和派送任务。一个典型情况是:运单和国际段已经 COMPLETED,但包裹在海外仓库存中仍是 INBOUND,说明国际运输完成,但海外仓还没有复核和派送。
查询恢复建议:
- 先按
waybillNo查询运单分页,确认唯一运单。 - 用返回的
packageId或waybillNo查询仓库存包裹列表,拿到packageStatus、currentWarehouseId、currentStorageId、destCountryId、destProvinceId、destCityId和destDistrictId。 - 查询运单详情,读取
waybillItems和tracks,判断当前运输段是否已完成。 - 如果包裹是
INBOUND且reviewed = false,执行复核。 - 如果包裹是
STORED或ARRIVED,创建派送上下文、分拣加包、完成分拣、分配配送员。 - 如果包裹是
DISPATCHED,进入配送员任务查询和签收处理。
流程中断恢复
前端不应该依赖本地缓存恢复流程。每个可中断点都应有后端查询方式恢复现场。
| 中断位置 | 重新进入输入 | 恢复查询 | 判断逻辑 | 下一步 |
|---|---|---|---|---|
| 已创建车次但未封批 | shipmentNo |
中转车次详情 | 有车次、批次未 SORTED |
继续加包或封批 |
| 已封批但未封车 | shipmentNo |
中转车次详情、批次详情 | 批次 SORTED,车次未发运 |
封车 |
| 已封车但未出库 | shipmentNo |
中转车次详情 | 车次可出库 | 发车出库 |
| 车次已发出但目标仓未确认 | shipmentNo |
入库车次分页、中转车次分页 | 车次 SHIPPED 或目标仓待入库 |
到仓确认 |
| 车次到仓但未入库 | shipmentNo 或 batchNo |
入库详情、入库预查询 | 包裹 ARRIVED |
执行入库 |
| 已入库但未复核 | waybillNo 或 packageNo |
仓库存包裹列表 | 包裹 INBOUND、reviewed = false |
执行复核 |
| 已复核但未派送 | waybillNo 或 packageNo |
仓库存包裹列表 | 包裹 STORED 或 ARRIVED |
创建派送上下文并加包 |
| 已创建派送上下文但未完成分拣 | dispatchTaskId 或任务分页 |
派送任务详情 | 分拣任务 SORTING |
继续加包或完成分拣 |
| 已完成分拣但未分配配送员 | dispatchTaskId |
派送任务详情、配送员列表 | 派送任务未归属或待分派 | 分配配送员 |
| 已派送但未签收 | 配送员登录 | 我的派送任务和明细 | 明细 DISPATCHED |
签收、失败或退仓 |
| 派送失败待退仓 | 配送员登录或平台查询 | 派送任务明细 | 明细失败,包裹异常 | 退回仓库后重新派送 |
恢复流程通用规则:
- 先用业务编号查主对象,例如车次、运单或包裹。
- 再查当前仓库存记录,确认当前仓库、库位、包裹状态和复核状态。
- 再查是否存在未完成分拣任务或派送任务,避免重复创建任务。
- 最后根据状态选择下一步动作。
如果多个查询结果互相矛盾,例如运单已完成但包裹未签收,应以后端包裹状态和仓库存状态作为下一步作业依据。
关键接口索引
详细接口表维护在 doc/API/物流履约.md,本文只列联调主链路接口。
| 场景 | 方法 | 路径 | 主要用途 |
|---|---|---|---|
| 运单分页 | GET |
/api/v1/logistics/waybill/page |
按 waybillNo 查询运单 |
| 运单详情 | GET |
/api/v1/logistics/waybill/{waybillId} |
查询运单段和轨迹 |
| 包裹物流链 | GET |
/api/v1/logistics/waybill/package-no/{packageNo} |
按包裹号查询物流链 |
| 待入库车次 | GET |
/api/v1/logistics/warehouse/inbound/shipment/page |
海外仓按车次查询待入库数据 |
| 入库详情 | GET |
/api/v1/logistics/warehouse/inbound/detail/{shipmentId} |
查询车次入库上下文 |
| 到仓确认 | PUT |
/api/v1/logistics/warehouse/inbound/shipment/{shipmentId}/arrive-confirm |
确认车次到达目标仓 |
| 入库预查询 | POST |
/api/v1/logistics/warehouse/inbound/preview |
按批次号、包裹号或运单号预查询可入库包裹 |
| 执行入库 | POST |
/api/v1/logistics/warehouse/inbound/execute |
正式入库 |
| 仓库存包裹 | GET |
/api/v1/logistics/warehouse-inventory/package/list |
查询包裹当前仓、库位和状态 |
| 包裹复核 | POST |
/api/v1/logistics/warehouse-inventory/package/review |
入库后复核,上架为 STORED |
| 中转上下文 | POST |
/api/v1/logistics/warehouse/transfer/context |
创建中转车次和分拣任务 |
| 中转车次分页 | GET |
/api/v1/logistics/warehouse/transfer/shipment/page |
查询中转车次 |
| 中转车次详情 | GET |
/api/v1/logistics/warehouse/transfer/shipment/detail/{shipmentId} |
查询中转上下文 |
| 创建中转批次 | POST |
/api/v1/logistics/warehouse/transfer/shipment/{shipmentId}/batch |
在车次下创建批次 |
| 中转批次加包 | POST |
/api/v1/logistics/warehouse/transfer/batch/{batchId}/package |
扫码加包 |
| 封中转批次 | PUT |
/api/v1/logistics/warehouse/transfer/batch/{batchId}/seal |
完成批次分拣 |
| 封中转车次 | PUT |
/api/v1/logistics/warehouse/transfer/shipment/{shipmentId}/seal |
装车 |
| 中转出库 | POST |
/api/v1/logistics/warehouse/transfer/shipment/{shipmentId}/outbound |
发车出库 |
| 派送上下文 | POST |
/api/v1/logistics/warehouse/dispatch/context |
创建分拣任务和派送任务 |
| 派送任务分页 | GET |
/api/v1/logistics/warehouse/dispatch/task/page |
仓库查询派送任务 |
| 派送任务详情 | GET |
/api/v1/logistics/warehouse/dispatch/task/detail/{dispatchTaskId} |
查询派送任务和明细 |
| 派送加包 | POST |
/api/v1/logistics/warehouse/dispatch/sorting-task/{sortingTaskId}/package |
分拣任务加包并创建派送明细 |
| 完成派送分拣 | PUT |
/api/v1/logistics/warehouse/dispatch/sorting-task/{sortingTaskId}/complete |
包裹出库并进入配送中 |
| 分配配送员 | PUT |
/api/v1/logistics/warehouse/dispatch/dispatch-task/{dispatchTaskId}/assign-employee |
派送任务改派或分派 |
| 配送员任务 | GET |
/api/v1/logistics/dispatcher/query/task/page |
配送员查询本人任务 |
| 配送员任务详情 | GET |
/api/v1/logistics/dispatcher/query/task/{dispatchTaskId}/detail |
配送员查询任务详情 |
| 配送员签收 | PUT |
/api/v1/logistics/dispatcher/task/item/{itemId}/sign |
配送员确认签收 |
| 配送员失败 | PUT |
/api/v1/logistics/dispatcher/task/item/{itemId}/fail |
配送员标记派送失败 |
| 失败件退仓 | PUT |
/api/v1/logistics/dispatcher/task/item/{itemId}/return-to-warehouse |
派送失败件退回仓库 |
海外仓联调主链路
下面流程用于当前 ops 海外仓页面按运单号继续处理到可派送。
异常和限制
| 场景 | 表现 | 处理方式 |
|---|---|---|
warehouseId=undefined |
后端报实体 LogisticsWarehouse 的 Id [undefined] 不存在 |
前端构建参数时过滤 undefined,未选择仓库则不传或提示选择 |
| 运单完成但包裹未派送 | waybillStatus = COMPLETED,packageStatus = INBOUND 或 STORED |
继续海外仓复核和派送流程 |
包裹 INBOUND 直接派送失败 |
后端拒绝派送加包 | 先调用仓库存复核,复核后再派送 |
包裹 STORED 派送失败 |
常见原因是未复核、仓库或库位不匹配、目的地区不匹配、已有未完成任务 | 按接口错误定位对应条件,必要时回到库存和派送任务查询核对 |
| 车次已到达后用户退出 | 页面状态丢失 | 重新输入 shipmentNo 查询车次和批次,按后端状态继续 |
| 批次已入库后用户退出 | 页面状态丢失 | 重新按 shipmentNo、batchNo、waybillNo 或 packageNo 查包裹状态 |
| 派送任务创建后用户退出 | 页面状态丢失 | 查询派送任务分页或详情,继续加包、完成分拣或分配配送员 |
| 配送员看不到任务 | 当前用户不是任务配送员或任务未分配 | 仓库端查询派送任务,确认 employeeAccountId 并分配 |
| 失败件已退仓 | 包裹回到 ARRIVED |
海外仓重新创建派送任务 |
前后端联调检查清单
- 商户发货后,可以通过
waybillNo和packageNo查询到包裹与运单。 - 国内仓发车后,包裹状态进入
IN_TRANSIT,目标仓可以按shipmentNo找到待入库车次。 - 海外仓到仓确认后,入库预查询能识别批次号、包裹号或运单号。
- 正式入库后,仓库存包裹列表能查到
INBOUND包裹和当前库位。 - 复核后,包裹从
INBOUND变为STORED,reviewed = true。 STORED或ARRIVED包裹可以加入派送分拣任务。- 完成派送分拣后,包裹进入
DISPATCHED,配送员任务可查到明细。 - 配送员签收后,包裹进入
SIGNED,当前运单段进入COMPLETED。 - 配送失败后,可以退回仓库,包裹回到
ARRIVED并可重新派送。 - 任意一步退出
ops后,重新输入业务编号能通过后端查询恢复流程。
数据审计清单
物流问题排查时建议同时保留以下数据截图或接口响应:
| 数据 | 用途 |
|---|---|
| 发货单和明细 | 判断订单是否已经进入履约 |
| 包裹详情 | 判断包裹状态、当前仓和当前库位 |
| 运单详情和轨迹 | 判断运输段是否完成 |
| 仓库存流水 | 判断入库、复核、移库、出库是否有记录 |
| 中转车次和批次 | 判断是否封批、封车、出库 |
| 分拣任务和明细 | 判断包裹是否被任务占用 |
| 派送任务和明细 | 判断配送员归属和签收结果 |
| 订单状态 | 判断物流结果是否同步到交易链路 |