20 KiB
阶段四:海运、目的港与尾程入仓计划
对应全景流程:F24~F27。
阶段起点:柜次已完成送港/进港或甩柜处理,并产生承运船舶实际VESSEL_DEPARTED/DEPARTED_ORIGIN_PORT节点;真实DEPARTED_WAREHOUSE和PORT_RECEIVED属于阶段三送港线事实。
阶段终点:跨区尾程订单完整生成,整柜每票入仓计划及托盘/库位资源已生成或有明确资源失败待办,订单进入INBOUND_PLANNED。
本阶段同时维护船舶/货柜轨迹和尾程业务准备,但两类状态不得互相冒充。
1. 阶段目标和边界
本阶段完成四条相互关联但独立的链路:
- 从承运船舶实际开航开始查询并保存十个标准船节点;
- 管理目的港清关、海外码头车队、提柜、预计到仓和还空;
- 将国内最终实装快照可靠投递到海外区域并创建尾程订单;
- 按整柜维护每票计划并转换为可执行的海外入仓计划和资源。
阶段四不执行海外仓实收、库存入账、库内服务、排车或出库。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 人工补录
供应商缺节点、网页需要人工验证或业务已有可信凭证时,有权限人员可在查询详情补录:
- 选择标准节点;
- 填写实际时间,预计事实不能冒充实际时间;
- 填写地点、来源说明和必要凭证;
- 核对节点不会回退当前实际进度;
- 携带版本和幂等键提交;
- 查看历史中来源标识为人工。
人工补录 PICKUP_READY 会通过跨区事实开放海外 PDA 柜号候选;人工补录 EMPTY_RETURNED 会停止任务,因此必须使用真实还柜事实。
5. F25 目的港清关、车队、到仓和还空
5.1 清关和文件
入口:Admin → 清关提柜。
- 按柜号、提单号、目的港和节点筛选;
- 核对目的港清关资料、DO 和 PU 当前版本;
- 上传或替换合法文件引用;
- 将线下清关结果反映为可信业务事实;
- 清关完成、码头明确可提后,确保实际
PICKUP_READY已进入标准节点链。
清关资料状态和标准船节点有关联但不互相覆盖。只有明确可提事实才能推进 PICKUP_READY。
5.2 选择海外码头车队
- 选择 Warehouse 中
ACTIVE/TRUCKING/OVERSEAS供应商; - 服务端读取供应商名称和邮箱快照,不能用自由文本绕过主档;
- 首次选择车队只保存选择,不自动发信;
- 操作员确认后发送提柜请求邮件;
- 邮件进入顺序发送队列,
SENT只表示 SMTP 接受,不代表车队已读或已执行; - 失败邮件保留原因,人工确认后重试。
更换车队时,事务内同时冻结旧车队取消邮件和新车队提柜邮件,并按顺序投递。同一车队重复选择不重复发信。
5.3 实际提柜
车队从码头取得重箱后,目的港操作员确认实际提柜时间。服务端推进实际 PICKED_UP,但不创建海外库存、不替代 PDA 到仓收货。
5.4 预计到仓
清关提柜列表中的“预计到仓”由平台维护:
- 输入整柜预计抵达接柜仓的日期/时间;
- 按
sourceContainerBookingId锁定整柜; - 原子同步柜内全部尾程订单的
estimated_warehouse_at; - 记录版本、操作人和幂等历史;
- 任一入仓计划已生成后锁定,不再允许修改。
预计到仓不能使用订单创建时间、预计到港时间或当前时间替代。同柜订单缺失或日期不一致时,阶段四的计划转换必须阻断。
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 消费步骤:
- 常量时间校验内部令牌;
- 校验事件 ID、版本、来源区域、客户和必要字段;
- 校验 Payload 哈希;
- 以事件 ID、哈希和来源入仓单唯一约束防重;
- 在一个事务内处理整柜全部订单;
- 任一票失败时整柜回滚,不留下半套订单;
- 重放相同事件返回既有结果。
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:
- 以
sourceContainerBookingId锁柜; - 用版本/哈希重新计算预览;
- 向 Warehouse Overseas 批量预留真实托盘、库位和资源锁;
- 为柜内每票独立生成入仓计划;
- 本地事务确认计划并绑定资源;
- 尾程订单进入
INBOUND_PLANNED; 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. 易用性与数据流评审问题
- 船节点、目的港清关和尾程计划是否需要整合为一条柜级时间线,同时保留三个权威状态?
- 预计节点与实际节点的视觉差异是否足够明显?
- 船司失败、需人工、扣留异常分别由谁负责,是否需要责任人和 SLA?
- 发车队邮件后,页面是否明确区分“已入队、SMTP 已接受、车队已执行”?
- 预计到仓锁定前是否应显示会影响哪些订单和计划?
- 跨区事件失败是否需要业务友好的“缺哪一票/哪一字段”诊断,而不是只显示事件错误?
- 柜级工作台的
pendingPlanCount与resourcePendingPlanCount是否容易混淆? - 普通散货的“头程已有/海外补充/最终托数”是否需要图形化对比?
- 一件代发不可重排托盘的约束是否在编辑前就锁定控件?
- 转换前预览是否需要展示资源占用和预计库位,减少确认后人工调整?
PICKUP_READY开放 PDA 候选后,若预计到仓和资源计划尚未完成,现场应看到什么阻断提示?- 还柜预警当前同时存在“两天展示”和“72 小时业务规则”的历史描述,正式页面应统一采用服务端 72 小时口径。
12. 阶段五交接包
交给阶段五“海外接柜、实收、库存和库内服务”的输入包括:
- 来源柜次、真实柜号、订舱和最新实际船节点;
PICKUP_READY及以后产生的 PDA 候选门禁;- 实际接柜海外仓和柜级预计到仓;
- 柜内全部尾程订单、来源入仓码、目的类型和冻结货物;
- 每票独立入仓计划及
assigned/mergeAllowed/urgent/mergeHint; - 已预留并确认的托盘、库位和资源锁;
- 普通货头程托盘码与海外补码;
- 一件代发不可变
DP托盘、箱唛和 SKU; - 国内装柜五类照片引用及跨区事件审计历史。
13. 事实来源
docs/海外仓业务/README.mddocs/海外仓业务/船节点标准化契约.mddocs/海外仓业务/虫虫出海全流程人工验收手册.mddocs/跨区域认证与服务通信契约.mdbaiyue-firstleg/firstleg/AGENTS.mdbaiyue-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.mdbaiyue-firstleg/lastleg-service/AGENTS.mdbaiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/service/LoadingCompletedConsumer.javabaiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/apps/admin-web/src/modules/port-schedules/apps/admin-web/src/modules/overseas-warehouse/