9.5 KiB
9.5 KiB
生产表说明:platform_express_*(第三方快递轨迹平台侧)
本文档对应生产迁移脚本:pages/mall/delivery/doc/需求文档/express_tracking_platform_upgrade.sql。
1. 设计目标与边界
- 目标:为第三方承运(韵达/圆通/中通等)提供统一的“运单 + 轨迹事件 + 原始回调留痕”入库模型,支撑用户端/商家端/平台后台同源展示。
- 边界:
- 仅覆盖第三方快递轨迹,不包含自营骑手/配送任务(
ml_delivery_*)。 - 生产仅使用
platform_express_*三表;不包含任何mock_*测试表。
- 仅覆盖第三方快递轨迹,不包含自营骑手/配送任务(
2. 表关系概览
platform_express_waybills(运单主表)- 1 条运单对应 N 条轨迹事件(
platform_express_tracking_events)。
- 1 条运单对应 N 条轨迹事件(
platform_express_tracking_events(轨迹事件事实表)- 时间线展示、状态判断、告警统计的主来源。
- 对同一运单使用
(waybill_id, dedupe_key)做幂等去重。
platform_express_event_raw(原始接收留痕表)- 记录每一次 webhook/轮询/人工补录的原始请求/响应内容与验签结果、解析错误,用于审计与排障。
3. 字段说明
3.1 public.platform_express_waybills(运单主表)
用途:
- 以
(carrier, tracking_no)为唯一键管理“运单实体”,可选关联订单;承载“当前状态/预计到达/最近同步时间”等运单级摘要信息。
约束/触发器/索引:
- 唯一约束:
uk_platform_express_waybill (carrier, tracking_no) - 外键:
order_id -> public.ml_orders(id),ON DELETE SET NULL updated_at触发器:trigger_platform_express_waybills_updated_at(UPDATE 时自动刷新)- 常用索引:
idx_platform_express_waybills_order_id (order_id)idx_platform_express_waybills_order_no (order_no)idx_platform_express_waybills_tracking_no (tracking_no)idx_platform_express_waybills_status (current_status_code)
字段表:
| 字段 | 类型 | 可空 | 默认/约束 | 含义 |
|---|---|---|---|---|
| id | UUID | 否 | PK,uuid_generate_v4() |
运单主键 |
| order_id | UUID | 是 | FK -> ml_orders(id),删除置空 |
关联订单主键(推荐) |
| order_no | VARCHAR(64) | 是 | 订单号(展示/兜底,用于无法拿到 order_id 的场景) |
|
| carrier | VARCHAR(32) | 否 | 参与唯一约束 | 承运方编码(如 YUNDA/YTO/ZTO 等;也可接入聚合方编码) |
| tracking_no | VARCHAR(64) | 否 | 参与唯一约束 | 运单号/快递单号 |
| source | VARCHAR(16) | 否 | 默认 'mock' |
运单数据来源:mock/carrier/aggregator 等 |
| current_status_code | VARCHAR(32) | 否 | 默认 'SHIPPED' |
运单当前平台状态(用于列表页/摘要),通常由最新事件映射得到 |
| current_status_text | TEXT | 是 | 运单当前状态文本(可为最新事件文本的“清洗版”或平台自定义) | |
| eta | TIMESTAMPTZ | 是 | 预计送达时间(可选;来自承运方/聚合方或平台预测) | |
| last_synced_at | TIMESTAMPTZ | 是 | 最近一次与承运方/聚合方同步时间(用于健康度与补偿轮询判断) | |
| created_at | TIMESTAMPTZ | 否 | 默认 NOW() |
创建时间 |
| updated_at | TIMESTAMPTZ | 否 | 默认 NOW();触发器维护 |
更新时间(UPDATE 自动刷新) |
3.2 public.platform_express_tracking_events(轨迹事件表)
用途:
- 存储每一个轨迹节点(揽收/到站/运输中/派送/签收/异常等),作为时间线展示与状态机判断的事实来源。
- 保留第三方原文(
event_code/event_text/raw_payload),同时写入平台统一状态(status_code)。 - 通过
dedupe_key实现幂等:重复回调/轮询不会重复插入。
约束/索引:
- 外键:
waybill_id -> platform_express_waybills(id),ON DELETE CASCADE - 唯一约束:
uk_platform_express_event_dedupe (waybill_id, dedupe_key) - 常用索引:
idx_platform_express_events_waybill_time (waybill_id, event_time)(按运单查时间线)idx_platform_express_events_tracking_time (tracking_no, event_time)(按运单号查)idx_platform_express_events_status (status_code)(按状态统计/筛选)idx_platform_express_events_received_at (received_at)(按接收时间排障)gin_platform_express_events_raw_payload(raw_payloadJSONB GIN,便于排障检索)
字段表:
| 字段 | 类型 | 可空 | 默认/约束 | 含义 |
|---|---|---|---|---|
| id | UUID | 否 | PK,uuid_generate_v4() |
事件主键 |
| waybill_id | UUID | 否 | FK,级联删除 | 所属运单 |
| carrier | VARCHAR(32) | 否 | 承运方编码(冗余字段,便于查询/对账) | |
| tracking_no | VARCHAR(64) | 否 | 运单号(冗余字段,便于查询/对账) | |
| event_id | VARCHAR(128) | 是 | 第三方事件唯一 ID(有些承运方会提供;优先用于幂等) | |
| event_time | TIMESTAMPTZ | 否 | 事件发生时间(时间线排序的主依据) | |
| event_code | VARCHAR(64) | 否 | 第三方事件码/节点码(保留原值) | |
| event_text | TEXT | 否 | 第三方事件文本(保留原值;展示前可做脱敏/清洗) | |
| status_code | VARCHAR(32) | 否 | 平台统一状态码(由 event_code/event_text 规则映射得出) |
|
| node_name | VARCHAR(128) | 是 | 节点/网点名称(如“xx转运中心”) | |
| location | TEXT | 是 | 地理位置文本(如省市区/网点地址;不建议存精确经纬度,除非明确需求) | |
| description | TEXT | 是 | 平台补充说明(如“疑似退回件,已通知商家”) | |
| evidence_urls | JSONB | 否 | 默认 [] |
证据/附件 URL 列表(签收图、面单、异常凭证等) |
| raw_payload | JSONB | 是 | 第三方原始事件载荷(用于审计/排障;注意权限控制) | |
| received_at | TIMESTAMPTZ | 否 | 默认 NOW() |
平台接收时间(用于排查延迟/乱序) |
| source | VARCHAR(16) | 否 | 默认 'webhook' |
数据进入平台的方式:webhook/poll/manual |
| dedupe_key | VARCHAR(256) | 否 | 参与唯一约束 | 幂等去重键(建议:有 event_id 用 event_id;否则构造 `tracking_no |
| created_at | TIMESTAMPTZ | 否 | 默认 NOW() |
入库时间 |
幂等与乱序建议:
- 幂等:插入事件时以
(waybill_id, dedupe_key)唯一约束兜底;遇到冲突可ON CONFLICT DO NOTHING。 - 乱序:允许旧事件晚到入库;前端展示按
event_time排序。 - 运单摘要(
platform_express_waybills.current_status_*)建议由“最新事件(按 event_time)映射结果”更新,避免用received_at作为最新依据。
3.3 public.platform_express_event_raw(原始接收留痕表)
用途:
- 记录每一次 webhook 回调或轮询结果的“原始内容 + 安全审计 + 解析结果”。
- 用于:验签问题定位、第三方字段变更回溯、解析失败重放、争议审计。
索引:
idx_platform_express_raw_received_at (received_at)idx_platform_express_raw_tracking_no (tracking_no)idx_platform_express_raw_signature_valid (signature_valid)gin_platform_express_raw_body(bodyJSONB GIN,便于按字段排障检索)
字段表:
| 字段 | 类型 | 可空 | 默认/约束 | 含义 |
|---|---|---|---|---|
| id | UUID | 否 | PK,uuid_generate_v4() |
原始接收记录主键 |
| received_at | TIMESTAMPTZ | 否 | 默认 NOW() |
平台收到请求/响应的时间 |
| source | VARCHAR(16) | 否 | 默认 'webhook' |
来源:webhook/poll/manual |
| client_id | VARCHAR(64) | 是 | 调用方/渠道标识(如回调应用 ID、聚合方商户号等) | |
| carrier | VARCHAR(32) | 是 | 承运方编码(可从路由/请求体解析;可能为空) | |
| tracking_no | VARCHAR(64) | 是 | 运单号(可能为空:如批量回调或解析失败) | |
| signature_valid | BOOLEAN | 是 | 验签是否通过(解析失败或未验签可为空) | |
| signature | TEXT | 是 | 签名原文(如 header 签名) | |
| ts_header | TEXT | 是 | 时间戳 header(用于防重放;字段名取决于对接规范) | |
| request_id | VARCHAR(64) | 是 | 请求追踪 ID(平台生成或对方传入) | |
| remote_ip | INET | 是 | 来源 IP(用于安全审计/黑白名单) | |
| headers | JSONB | 是 | 请求头(建议按需过滤敏感头再落库) | |
| body | JSONB | 是 | 原始请求体/响应体(用于回溯与重放) | |
| parse_error | TEXT | 是 | 解析错误信息(成功解析则为空) | |
| dedupe_key | VARCHAR(256) | 是 | 原始请求去重辅助键(可选:如 hash(headers+body)) |
权限与合规建议(实现侧):
raw_payload、platform_express_event_raw.body/headers可能包含敏感信息(手机号、地址、签名等),建议仅后台/运维具备读取权限,并记录审计日志。
4. 常见查询与写入路径(建议)
- 发货/绑定运单:
- Upsert
platform_express_waybills(按(carrier, tracking_no));有订单关联时写入order_id/order_no。
- Upsert
- 接收回调/轮询:
- 先插入
platform_express_event_raw做留痕(无论解析成功与否)。 - 解析出事件后写入
platform_express_tracking_events;用dedupe_key做幂等。 - 视需要更新
platform_express_waybills.current_status_*、last_synced_at。
- 先插入
- 订单详情页展示:
- 通过
order_id查platform_express_waybills。 - 再按
waybill_id查platform_express_tracking_events,按event_time升序组装时间线。
- 通过