Files
docs/头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md

20 KiB
Raw Permalink Blame History

阶段四:海运、目的港与尾程入仓计划

对应全景流程:F24~F27。
阶段起点:柜次已完成送港/进港或甩柜处理,并产生承运船舶实际 VESSEL_DEPARTED/DEPARTED_ORIGIN_PORT 节点;真实 DEPARTED_WAREHOUSE 和 PORT_RECEIVED 属于阶段三送港线事实。
阶段终点:跨区尾程订单完整生成,整柜每票入仓计划及托盘/库位资源已生成或有明确资源失败待办,订单进入 INBOUND_PLANNED。
本阶段同时维护船舶/货柜轨迹和尾程业务准备,但两类状态不得互相冒充。

1. 阶段目标和边界

本阶段完成四条相互关联但独立的链路:

  1. 从承运船舶实际开航开始查询并保存十个标准船节点;
  2. 管理目的港清关、海外码头车队、提柜、预计到仓和还空;
  3. 将国内最终实装快照可靠投递到海外区域并创建尾程订单;
  4. 按整柜维护每票计划并转换为可执行的海外入仓计划和资源。

阶段四不执行海外仓实收、库存入账、库内服务、排车或出库。PICKUP_READY 只表示货柜已清关可提,并开放海外 PDA 待收柜候选;它不表示已经到仓或已经产生库存。

2. 角色、终端和系统边界

角色/系统 终端 主要职责
船期操作员 Admin 查看查询任务、标准节点、异常与查询历史,必要时人工补录
目的港操作员 Admin 维护清关/DO/PU、选择海外车队、发提柜邮件、确认提柜和还柜
海外仓计划员 Admin 维护整柜预计到仓、每票托数与作业属性、执行柜级转换
企业成员 Client 查看本企业尾程订单和允许展示的船期/计划进度
Firstleg 后端 拥有查询任务、标准节点、目的港码头拖车和装柜完成 Outbox
Integration Service 后端 调用船司/轨迹供应商,解析并返回标准化结果,不保存业务主数据
Event Bridge 跨区通道 版本化、认证地投递业务事件
Lastleg 海外后端 Inbox 幂等消费、尾程订单、计划、在途库存和海外业务状态
Warehouse 国内主数据 海外共享仓、FBA 目的仓和供应商主档权威
Warehouse Overseas 海外资源 海外库位、实物托盘和资源锁

所有浏览器海外接口经 gateway-overseas/。国内 Auth 仍是账号和 Token 签发方;跨区业务写入通过内部身份、Inbox/Outbox 和事件契约完成,不允许浏览器伪造跨区事件。

3. 阶段前置检查

  • 柜次存在真实集装箱号、订舱、提单号、送港/进港事实和实际开船节点;
  • 装柜完成事件包含最终实装订单、入仓单、目的类型、箱数及必要托盘/SKU/箱唛快照;
  • 国内五类装柜证据和锁码文本已经冻结;
  • 接柜海外仓是 Warehouse 中 ACTIVE + OVERSEAS + RECEIVING 的平台共享物理仓;
  • FBA 目的仓是 Warehouse 有效公共主档,不能用接柜仓或国内仓代替;
  • 船司/轨迹查询标识足以唯一指向目标订舱和柜次;
  • 同柜订单的预计到仓事实必须能够收敛为一个柜级日期。

4. F24 海运十节点

4.1 查询任务创建

承运船舶实际开航事务幂等创建 CarrierScheduleQuery。任务必须绑定真实订舱、柜次以及可用的船司、船名航次、提单号或柜号,不创建脱离业务单据的孤立轮询任务。送港、进港、甩柜和客户报关确认在阶段三分别记录,不能用预计 ETD 提前创建“海运中”展示。

标准节点保留国内送港事实,但海运查询的起点是实际开船:

DEPARTED_WAREHOUSE、AT_ORIGIN_PORT 和 LOADED_ON_VESSEL 可以作为送港/装船历史补录;客户的“海运中”节点和定时船节点查询以真实 DEPARTED_ORIGIN_PORT/VESSEL_DEPARTED 为起点。

10 DEPARTED_WAREHOUSE       已离开国内仓
20 AT_ORIGIN_PORT           已到起运港
30 LOADED_ON_VESSEL         已装船
40 DEPARTED_ORIGIN_PORT     已离开起运港
50 IN_TRANSIT               海运途中
60 ARRIVED_DESTINATION_PORT 已到目的港
70 DISCHARGED_FROM_VESSEL   已卸船
80 PICKUP_READY             已清关、可提柜
90 PICKED_UP                已提柜
100 EMPTY_RETURNED          已还空柜

4.2 自动查询操作与频率

入口:Admin → 船期/货柜详情 → 船节点查询。

平台查看:查询任务状态、当前最新实际节点、预计节点、最近成功时间、下次允许时间、供应商、失败原因、异常事实和每次尝试历史。

正常查询槽位按北京时间每天 09:00、12:30、16:00。调度器每分钟只扫描已到期任务,不代表每分钟调用船司。

  • 成功、无变化、需人工或永久失败:进入下一固定槽位;
  • 技术性可重试失败:当前槽内按 15/30 分钟退避,含首次最多三次;
  • 重试不得跨越下一正常槽位;
  • 服务恢复后错过的槽位直接顺延,不集中补打供应商;
  • 实际 EMPTY_RETURNED 后任务停止。

4.3 节点时间和推进规则

时间 含义 推进最新实际节点
estimatedAt 预计发生时间 否
actualAt 已确认实际时间 是
observedAt 本次观测到事实的时间 否
createdAt 平台写入时间 否

只有带 actualAt 的标准节点可以推进。节点按序号单调前进;迟到的较早节点可作为历史保存,但不能回退当前节点。供应商缺少中间节点时保持缺失,不能自动补齐。

同一供应商事件按稳定 providerEventId 幂等;无原生 ID 时用稳定字段组合生成哈希。每条事实保留原始节点编码、来源、地点、观测时间和原始响应哈希,但业务表不保存含密钥的完整网页。

4.4 异常事实

以下异常与正常节点并行保存:

  • CUSTOMS_HOLD:海关扣留;
  • TERMINAL_HOLD:码头/堆场扣留;
  • DOCUMENT_HOLD:单证问题;
  • UNKNOWN_HOLD:其他无法分类扣留。

异常不能覆盖最近正常节点。解除时新增解除事实,不删除原异常。

4.5 人工补录

供应商缺节点、网页需要人工验证或业务已有可信凭证时,有权限人员可在查询详情补录:

  1. 选择标准节点;
  2. 填写实际时间,预计事实不能冒充实际时间;
  3. 填写地点、来源说明和必要凭证;
  4. 核对节点不会回退当前实际进度;
  5. 携带版本和幂等键提交;
  6. 查看历史中来源标识为人工。

人工补录 PICKUP_READY 会通过跨区事实开放海外 PDA 柜号候选;人工补录 EMPTY_RETURNED 会停止任务,因此必须使用真实还柜事实。

5. F25 目的港清关、车队、到仓和还空

5.1 清关和文件

入口:Admin → 清关提柜。

  1. 按柜号、提单号、目的港和节点筛选;
  2. 核对目的港清关资料、DO 和 PU 当前版本;
  3. 上传或替换合法文件引用;
  4. 将线下清关结果反映为可信业务事实;
  5. 清关完成、码头明确可提后,确保实际 PICKUP_READY 已进入标准节点链。

清关资料状态和标准船节点有关联但不互相覆盖。只有明确可提事实才能推进 PICKUP_READY。

5.2 选择海外码头车队

  1. 选择 Warehouse 中 ACTIVE/TRUCKING/OVERSEAS 供应商;
  2. 服务端读取供应商名称和邮箱快照,不能用自由文本绕过主档;
  3. 首次选择车队只保存选择,不自动发信;
  4. 操作员确认后发送提柜请求邮件;
  5. 邮件进入顺序发送队列,SENT 只表示 SMTP 接受,不代表车队已读或已执行;
  6. 失败邮件保留原因,人工确认后重试。

更换车队时,事务内同时冻结旧车队取消邮件和新车队提柜邮件,并按顺序投递。同一车队重复选择不重复发信。

5.3 实际提柜

车队从码头取得重箱后,目的港操作员确认实际提柜时间。服务端推进实际 PICKED_UP,但不创建海外库存、不替代 PDA 到仓收货。

5.4 预计到仓

清关提柜列表中的“预计到仓”由平台维护:

  1. 输入整柜预计抵达接柜仓的日期/时间;
  2. 按 sourceContainerBookingId 锁定整柜;
  3. 原子同步柜内全部尾程订单的 estimated_warehouse_at;
  4. 记录版本、操作人和幂等历史;
  5. 任一入仓计划已生成后锁定,不再允许修改。

预计到仓不能使用订单创建时间、预计到港时间或当前时间替代。同柜订单缺失或日期不一致时,阶段四的计划转换必须阻断。

5.5 实际到仓与还空

实际到仓不由 Admin 手填,也不取预约提柜时间;只取海外 PDA 首次开始收货会话的 receiving_at。因此本阶段只能展示“待实际到仓”,真实时间在阶段五产生。

海外 PDA 完成卸柜后,跨区 OVERSEAS_CONTAINER_UNLOADED 事件回到 Firstleg。预计报空/还空截止按卸柜完成时间加 72 小时计算并产生预警。

真实还柜可由供应商节点或有权限人员确认:

  • 时间不得早于卸柜完成时间;
  • 若已有实际提柜时间,也不得早于提柜;
  • 无需为了还柜补造车队、预约或提柜事实;
  • 首次命令可以版本 0 创建记录,车队字段允许为空;
  • 成功后推进实际 EMPTY_RETURNED、解除预警并停止查询任务。

目的港码头拖车、国内订舱级拖车和海外配送排车是三张不同业务单,不得复用状态或费用。

6. F26 跨区尾程建单

6.1 国内生产事件

Firstleg 在装柜完成后按最终实装生成 FIRST_LEG_LOADING_PLAN_COMPLETED V3:

  • 信封包含事件 ID、版本、来源区域、聚合版本和 Payload 哈希;
  • Payload 包含来源柜次/计划/真实柜号和每票最终实装;
  • FBA 可以按实装箱数冻结,不伪造逐箱作业账;
  • OVERSEAS 必须逐箱冻结箱码事实;
  • 一件代发必须携带一个或多个不可变来源托盘,以及每托 SKU、箱数、数量和箱唛;
  • 物理柜五类国内装柜照片引用一并冻结。

Outbox 可重复投递,不能因网络失败直接丢事件或在事务外临时拼装 Payload。

6.2 Event Bridge 投递

Event Bridge 校验允许的事件类型、版本、来源/目标区域和内部服务身份后投递 Lastleg。IAM 安全事件使用独立入口,不能交给装柜完成消费者。

6.3 Lastleg Inbox 消费

Lastleg 消费步骤:

  1. 常量时间校验内部令牌;
  2. 校验事件 ID、版本、来源区域、客户和必要字段;
  3. 校验 Payload 哈希;
  4. 以事件 ID、哈希和来源入仓单唯一约束防重;
  5. 在一个事务内处理整柜全部订单;
  6. 任一票失败时整柜回滚,不留下半套订单;
  7. 重放相同事件返回既有结果。

6.4 尾程订单和在途库存

成功消费后:

  • 同一实际集装箱共享业务尾程单号;
  • 每个 sourceInboundId 独立生成一条 ll_order;
  • 保存来源订单、入仓码、客户、接柜仓、目的仓和货物冻结快照;
  • 主状态为 PENDING_ASSIGNMENT;
  • 生成 FIRST_LEG 在途库存;
  • 计划生成前以真实来源入仓码作为库存展示快照;
  • 事件只建订单,不自动生成入仓计划。

一件代发额外生成来源托盘、SKU、箱唛档案和在途库存事实;海外实物托盘资源仍由 Warehouse Overseas 分配,不覆盖国内来源托盘快照。

7. F27 尾程计划维护和整柜转换

7.1 柜级工作台

入口:Admin → 海外仓 → 尾程订单 → 柜级工作台。

列表使用 /container-summaries 按稳定 sourceContainerBookingId 服务端聚合,不允许用当前订单分页在浏览器拼柜。列表至少展示:

  • 柜号、来源柜次和预计到仓;
  • 订单数、已建计划数、待建计划数;
  • allPlansReady;
  • resourcePendingPlanCount;
  • 接柜仓、目的仓分组和异常摘要。

已完成转换的柜仍保留供查询和允许范围内维护。详情接口返回柜内全部订单和计划,不受列表分页截断。

7.2 单票计划维护

对柜内每票填写:

  • 计划托数;
  • 托盘类型;
  • 是否已分配;
  • 是否允许合托;
  • 是否加急;
  • 现场备注。

入仓码、实际接柜仓和预计到仓只读。保存时校验订单版本、客户范围、Warehouse 当前仓库主档和幂等键。

“可合托”只给阶段五现场提供选择,不是实收或完成门禁:合托时扫描同目的仓已使用托盘,独立收货扫描新托盘。

7.3 普通货与一件代发托盘规则

普通散货:

  • 保留头程已经冻结并跨区传入的托盘码;
  • 海外计划托数不得少于已有托盘码数量;
  • 海外装托密度不同导致托数增加时,在同柜、同 FBA 仓连续补码;
  • 预览分别展示头程已有数、海外补充数和最终托数。

一件代发:

  • 必须逐托沿用国内封托的 DP 托盘码和每托箱数;
  • 不允许重算托数、重分配箱子或改写 SKU/箱唛;
  • 无法绑定真实资源时禁止保存半成品计划。

7.4 自动触发与柜级预览

单票柜保存完整计划后立即尝试生成资源;多票柜在最后一票计划齐全时自动触发整柜资源生成。

转换前读取服务端预览,核对:

  • FBA、一件代发、私人地址等分组;
  • 每票来源托数、补充托数和最终托数;
  • 柜内计划是否全部就绪;
  • 接柜仓、预计到仓是否一致;
  • 阻断项;
  • snapshotVersion 和 snapshotHash。

pendingPlanCount 表示尚未建立完整计划;resourcePendingPlanCount 只表示自动物化资源失败,需要按原柜级入口重试,不能把它当作正常人工步骤。

7.5 确认转换

系统执行柜级 Saga:

  1. 以 sourceContainerBookingId 锁柜;
  2. 用版本/哈希重新计算预览;
  3. 向 Warehouse Overseas 批量预留真实托盘、库位和资源锁;
  4. 为柜内每票独立生成入仓计划;
  5. 本地事务确认计划并绑定资源;
  6. 尾程订单进入 INBOUND_PLANNED;
  7. FIRST_LEG 在途库存展示编号从来源入仓码收口为各自 planNo。

整批转换原子且幂等:相同命令重放不生成第二批计划或资源;本地失败只补偿尚未确认的远端资源;远端确认失败的重放只重试确认。

8. 状态、编号与数据归属

维度 关键状态/编号 权威系统
船节点任务 ACTIVE/人工/失败/STOPPED Firstleg
最新实际节点 十节点之一 Firstleg
目的港码头拖车 车队、提柜、卸柜、还柜 Firstleg
尾程主单 PENDING_ASSIGNMENT → INBOUND_PLANNED Lastleg
入仓计划 planNo、计划属性、资源绑定 Lastleg
在途库存 FIRST_LEG Lastleg
海外实物资源 托盘、库位、锁 Warehouse Overseas
仓库/目的仓/供应商 业务主档 Warehouse

containerNo 是真实集装箱号;sourceContainerBookingId 是跨区稳定柜聚合键;inboundCode 永远保存真实来源入仓码;planNo 只在尾程入仓计划生成后产生。任何页面不得以内建数据库 ID 回退展示业务编号。

9. 异常与恢复

场景 系统行为 操作处理
船司无变化 保存查询尝试,进入下一槽位 无需伪造节点
船司技术失败 15/30 分钟受控重试 查看失败原因,必要时人工
只有预计到港 保存预计事实,不推进实际节点 等待真实节点
较早节点迟到 保存历史,不回退当前节点 无需修改最新进度
清关/单证扣留 单独保存异常 处理后新增解除事实
车队邮箱无效 阻断发信/换队 修正 Warehouse 供应商资料
事件重复投递 返回既有消费结果 不人工删 Inbox
事件哈希不同 冲突失败 核对生产端版本和 Payload
柜内任一票事件失败 整柜消费回滚 修复数据后重放原事件
预计到仓缺失/不一致 阻断计划生成 在计划前按柜统一维护
计划版本过期 转换冲突 刷新预览,重新确认
资源预留失败 resourcePendingPlanCount 暴露 用原柜级入口定向重试
重试结果不确定 查询计划和资源事实 复用原幂等键,不另建资源

10. 阶段完成判定

现有测试环境综合证据 baiyue-firstleg/reports/admin-full-postdeploy-66c2651b.json 中,phase4-carrier-nodes、phase4-overseas-pda、phase4-overseas-pda-operations、phase4-overseas-inbound-operations、phase4-overseas-dispatch、phase4-tail-order-controls 和 phase5-overseas-fulfillment 均为通过;每个模块的失败数为 0。F23.3 的最新船期客户端投影另见 baiyue-firstleg/reports/transport-projection-after-schedule-update-20260927.json。

  • 国内离仓产生的船节点任务绑定真实订舱和柜次
  • 节点预计/实际/观测时间没有混用
  • 异常事实与正常节点分开保存
  • 实际 PICKUP_READY 已到达或已有明确待处理状态
  • 装柜完成 V3 事件已被 Lastleg 幂等消费
  • 柜内每个来源入仓单只生成一张尾程订单
  • 尾程订单冻结客户、入仓码、接柜仓、目的仓和最终实装事实
  • FIRST_LEG 在途库存存在且归属正确
  • 整柜预计到仓完整且一致
  • 每票入仓计划属性完整
  • 柜级转换后每票独立 planNo 存在
  • 托盘、库位和资源锁已绑定,或存在可定位的资源失败待办
  • 尾程订单状态为 INBOUND_PLANNED
  • 重放事件/转换不会重复建单、建计划或占资源

11. 易用性与数据流评审问题

  1. 船节点、目的港清关和尾程计划是否需要整合为一条柜级时间线,同时保留三个权威状态?
  2. 预计节点与实际节点的视觉差异是否足够明显?
  3. 船司失败、需人工、扣留异常分别由谁负责,是否需要责任人和 SLA?
  4. 发车队邮件后,页面是否明确区分“已入队、SMTP 已接受、车队已执行”?
  5. 预计到仓锁定前是否应显示会影响哪些订单和计划?
  6. 跨区事件失败是否需要业务友好的“缺哪一票/哪一字段”诊断,而不是只显示事件错误?
  7. 柜级工作台的 pendingPlanCount 与 resourcePendingPlanCount 是否容易混淆?
  8. 普通散货的“头程已有/海外补充/最终托数”是否需要图形化对比?
  9. 一件代发不可重排托盘的约束是否在编辑前就锁定控件?
  10. 转换前预览是否需要展示资源占用和预计库位,减少确认后人工调整?
  11. PICKUP_READY 开放 PDA 候选后,若预计到仓和资源计划尚未完成,现场应看到什么阻断提示?
  12. 还柜预警当前同时存在“两天展示”和“72 小时业务规则”的历史描述,正式页面应统一采用服务端 72 小时口径。

12. 阶段五交接包

交给阶段五“海外接柜、实收、库存和库内服务”的输入包括:

  • 来源柜次、真实柜号、订舱和最新实际船节点;
  • PICKUP_READY 及以后产生的 PDA 候选门禁;
  • 实际接柜海外仓和柜级预计到仓;
  • 柜内全部尾程订单、来源入仓码、目的类型和冻结货物;
  • 每票独立入仓计划及 assigned/mergeAllowed/urgent/mergeHint;
  • 已预留并确认的托盘、库位和资源锁;
  • 普通货头程托盘码与海外补码;
  • 一件代发不可变 DP 托盘、箱唛和 SKU;
  • 国内装柜五类照片引用及跨区事件审计历史。

13. 事实来源

  • docs/海外仓业务/README.md
  • docs/海外仓业务/船节点标准化契约.md
  • docs/海外仓业务/虫虫出海全流程人工验收手册.md
  • docs/跨区域认证与服务通信契约.md
  • baiyue-firstleg/firstleg/AGENTS.md
  • baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/portschedule/
  • baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/terminaldrayage/
  • baiyue-firstleg/common-event-contract/AGENTS.md
  • baiyue-firstleg/lastleg-service/AGENTS.md
  • baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/service/LoadingCompletedConsumer.java
  • baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/
  • apps/admin-web/src/modules/port-schedules/
  • apps/admin-web/src/modules/overseas-warehouse/