From df6f434550527d2b813a1316cbea295478b0f33f Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 28 Sep 2026 15:04:36 +0800 Subject: [PATCH] docs: align firstleg release contracts and add sailing plans --- README.md | 1 + 国内货柜履约/README.md | 8 +- 国内货柜履约/国内货柜履约需求确认表.md | 10 +- 国内货柜履约/报关资料与船期价格接入梳理.md | 44 +- 国内货柜履约/船期日历功能规划.md | 671 ++++++++++++++++++ 头程到尾程/README.md | 7 +- .../头程至实际开船节点冻结矩阵与缺口清单.md | 95 +-- 头程到尾程/头程节点与报关清关交互矩阵.md | 78 ++ 头程到尾程/报关代码开发交接清单.md | 82 ++- 头程到尾程/正式申报与海关结果接入设计.md | 128 ++++ 头程到尾程/测试环境真实联调记录-20260925.md | 109 +++ 头程到尾程/甩柜改配接入设计.md | 35 + 头程到尾程分阶段流程/README.md | 2 +- .../阶段三-国内货柜履约与出仓.md | 18 +- .../阶段五-海外接柜库存与库内服务.md | 2 + .../阶段六-海外排车出库派送与回写.md | 2 + .../阶段四-海运目的港与尾程计划.md | 2 + 头程到尾程流程节点梳理.md | 22 +- 18 files changed, 1199 insertions(+), 117 deletions(-) create mode 100644 国内货柜履约/船期日历功能规划.md create mode 100644 头程到尾程/头程节点与报关清关交互矩阵.md create mode 100644 头程到尾程/正式申报与海关结果接入设计.md create mode 100644 头程到尾程/测试环境真实联调记录-20260925.md create mode 100644 头程到尾程/甩柜改配接入设计.md diff --git a/README.md b/README.md index 50eacd7..e10d8a7 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ - [订单与客户](订单与客户/README.md):登录认证、客户与企业、权限、头程订单和客户工作台。 - [入库测量与计费](入库测量与计费/README.md):预约取货、到仓收货、箱码与箱唛、测量、尺寸策略、计价和入库费用。 - [国内货柜履约](国内货柜履约/README.md):分柜与同柜、智能排柜、订舱、拖车、PDA 拣货、装柜、报关和国内出仓。 + - [船期日历功能规划](国内货柜履约/船期日历功能规划.md):渠道、周模板、单次船期、收货截止时间和按渠道货量统计的独立日历规划。 - [海外仓业务](海外仓业务/README.md):船节点、海外接柜、入仓、库存、托盘、换标、转运、废弃、退货、排车、PDA 出库、派送、异常退回、客户回访、一件代发及海外本土业务。 - [船节点标准化契约](海外仓业务/船节点标准化契约.md):统一船司原始状态、标准节点、预计/实际时间、异常事实、还柜停止规则和新增船司接入门禁。 - [财务管理](财务管理/README.md):应收、应付、费用池、账单、收款、成本、核销、凭证以及国内外业务费用来源。 diff --git a/国内货柜履约/README.md b/国内货柜履约/README.md index 5a5b6bc..86dfe3f 100644 --- a/国内货柜履约/README.md +++ b/国内货柜履约/README.md @@ -8,6 +8,7 @@ - [阶段三:国内货柜履约与出仓](../头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md):分柜、订舱、拖车、拣货、装柜、报关和国内出仓的详细操作。 - [阶段四:海运、目的港与尾程计划](../头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md):实际开船后的海运、目的港和尾程计划衔接。 - [报关资料与船期价格接入梳理](报关资料与船期价格接入梳理.md):报关资料、报关行回执、客户确认/打回、正式申报、海关结果和船期价格专题。 +- [船期日历功能规划](船期日历功能规划.md):渠道、周模板、单次船期、收货截止时间和按渠道货量统计的独立日历规划。 - [报关代码开发交接清单](../头程到尾程/报关代码开发交接清单.md):报关代码当前未完成时,下一开发对话使用的范围和验收条件。 ## 货柜关键节点 @@ -16,12 +17,15 @@ 分柜/订舱/拖车 → 拣货 → 装柜完成(LOADED) ├─ 报关协同:资料 → 报关行回执 → 客户确认/打回重做 │ → 全部客户确认 → 整柜提交 → 正式申报 → 海关结果 - └─ 送港运输:离仓 → 送港 → 进港 → 甩柜/改配(如发生) + ↓ 报关完成 + 进入待发区 + ↓ + 送港运输:离仓 → 送港 → 进港 → 甩柜/改配(如发生) ↓ 船舶实际开航后进入海运节点 ``` -报关协同和送港运输在装柜完成后分别启动,谁先完成都保留真实事实。报关行回执、客户确认、正式申报、海关放行、进港、甩柜和实际开船分别记录,不能用其中一个节点代替另一个节点。 +报关完成是进入待发区的门槛。进入待发区后再推进离仓、送港、进港和船期;甩柜/改配只改变运输船次,不影响已完成的报关资料、回执和客户确认。报关行回执、客户确认、正式申报、海关放行、进港、甩柜和实际开船分别记录,不能用其中一个节点代替另一个节点。 费用确认属于头程下单块的并行事项,不阻断排柜、拣货或装柜;装柜完成时仍未确认的当前有效费用按系统默认确认并保留来源。这个默认确认只适用于费用,不适用于报关资料的客户确认。 diff --git a/国内货柜履约/国内货柜履约需求确认表.md b/国内货柜履约/国内货柜履约需求确认表.md index 262775b..a25aade 100644 --- a/国内货柜履约/国内货柜履约需求确认表.md +++ b/国内货柜履约/国内货柜履约需求确认表.md @@ -25,13 +25,13 @@ | P3-Q8 | 报关代理如何接收资料并返回回执? | 首版系统内整理、线下提交,正式接口后续评估 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10;2026-09-24 更正 | `LOADED` 后平台按客户/入仓码收集资料并线下发给报关行;授权人员上传每轮报关行回执,发给对应客户确认。客户打回后重新上传、重新发报关行并生成新回执,直到该客户确认;记录资料版本、回执版本、roundNo、发送时间和确认/打回审计 | 报关协同、客户确认、回执上传 | | P3-Q9 | “港务信息”指船期、港口作业状态还是两者,包含哪些字段,由谁维护? | 国内货柜履约只维护订舱与出仓前船期资料 | 已重新归期 | 已确认 | 产品/业务 | 2026-08-19 | 柜子确认离开国内仓库后的船公司/货物跟踪查询、每 3 天最多 3 次、来源、更新时间和过期标识整体归海外仓业务;国内货柜履约不建设或验收该查询 | 国内货柜履约订舱资料、海外仓业务船节点查询 | | P3-Q10 | 订单进入“装柜完成”后发现错误如何处理? | 仅保留线下人工处理和审计,不建设在线冲正 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | `LOADED` 后不提供在线冲正/回退入口,统一线下人工处理;系统保留原状态和审计记录,不由国内 Admin/PDA 推进 `DELIVERED` | 装柜完成门禁、权限、审计 | -| P3-Q11 | 九个动作中哪些是强制前置,哪些允许并行? | 统一门禁按已确认前置执行;PDA 单柜次单人作业 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10;2026-09-24 更正 | 费用确认不阻断排柜、预装、PDA 或装柜。进入 `LOADED` 只校验物理装柜、PDA、数量、真实柜号和五类证据;`LOADED` 后报关线和送港线同时启动,客户报关确认不阻断送港,送港/进港也不替代客户确认;只有实际开船前才汇合检查报关结果、港口和船次条件;PDA 单柜次单人作业 | 全流程、状态机、PDA、报关、送港、页面进度 | +| P3-Q11 | 九个动作中哪些是强制前置,哪些允许并行? | 统一门禁按已确认前置执行;PDA 单柜次单人作业 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10;2026-09-24 更正 | 费用确认不阻断排柜、预装、PDA 或装柜。进入 `LOADED` 只校验物理装柜、PDA、数量、真实柜号和五类证据;`LOADED` 后先完成退税报关,报关完成后进入待发区,再推进送港和船期;甩柜/改配只改变船次,不重做已完成报关;PDA 单柜次单人作业 | 全流程、状态机、PDA、报关、送港、页面进度 | | P3-Q12 | 报关回执包含哪些类型,客户确认和海关放行如何衔接? | 首版人工上传回执并保留版本 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10;2026-09-24 更正 | `LOADED` 后按客户/入仓码收集资料并发送报关行;报关行回执发对应客户确认,客户打回则重新上传、重新发送并生成新回执;所有客户确认后才向报关行提交整柜资料并正式申报;之后分别记录查验、不查验放行、补件/退回等海关结果。回执上传不等于客户确认,客户确认也不等于海关放行 | 报关状态、客户回执、整柜申报、海关结果 | | P3-Q13 | 国内货柜履约终点以什么状态为准? | 国内系统以能掌控的最后环节为终点 | 开工阻断 | 已确认 | 用户当前对话确认 | 2026-08-08 | 国内货柜履约终点为 `LOADED`/装柜完成;`DELIVERED`/派送完成只能在到达海外仓后由海外仓可信回传推进,不属于国内国内货柜履约操作和验收范围 | 阶段边界、状态、里程碑、验收、海外仓回传 | | P3-Q14 | 订舱、渠道柜次、放舱与智能排柜的先后关系是什么? | 线下已订妥的订舱在创建时完整登记五项真实运输快照并直接确认;放舱不覆盖首次快照 | 开工阻断 | 已确认 | 用户当前对话确认 | 2026-08-12 | 订舱创建请求必须携带提单号、船名、航次、预计开船时间、预计到港时间五项真实运输数据,并直接进入 `CONFIRMED`;渠道、箱型和数量同时确定,系统按箱型需求数量生成绑定渠道的稳定内部柜次。未放舱不影响候选查询、智能推荐、人工调整和保存装柜计划;同一柜次只能装同渠道入库单,服务端禁止跨渠道混装。`RELEASED` 仅作为后续放舱/PDA 门禁,不补录、不覆盖首次五项运输快照;真实集装箱号可在放舱时或之后录入 | 订舱、柜次、智能排柜、预装、PDA、运输信息 | | P3-Q15 | 客户未确认费用是否阻断排柜、装柜?装柜完成后如何处理? | 费用作为并行事实,装柜完成时对当前有效版本做系统默认确认 | 模块阻断 | 已确认 | 用户当前对话确认 | 2026-09-24 | 客户费用确认不阻断排柜、预装、PDA 或装柜。装柜完成后,针对本次已装范围的当前有效且已发布费用版本,若客户未确认则记录“系统默认确认(装柜完成)”;保留客户确认与 `SYSTEM_AUTO_AT_LOADED` 来源、版本、柜次/入仓码、时间和幂等标识。没有有效费用版本不得伪造确认;部分装载不确认余量或整张未完成订单 | 费用版本、装柜完成、客户进度、审计、部分装载 | -| P3-Q16 | 报关资料何时收集、何时正式报送? | 装柜后通知报关,按客户确认轮次完成后正式提交 | 模块阻断 | 已确认 | 用户当前对话确认 | 2026-09-24 | `LOADED` 后以最终实装清单通知报关行,按客户/入仓码收集资料并发送报关行;回执发客户确认,打回则重新上传、重新发送并产生新回执,循环至所有客户通过;全部客户确认后再提交整柜资料给报关行确认,由报关行正式申报;海关查验/不查验放行等结果单独记录。送港线与报关线并行,谁先到都保留事实 | 客户资料、回执轮次、客户确认、整柜申报、送港/海运 | -| P3-Q17 | 送港和报关是否互相等待?甩柜何时发生? | 两条线并行,实际开船才进入海运 | 开工阻断 | 已确认 | 用户当前对话确认 | 2026-09-24 | `LOADED` 后可同时安排拖车、送港和报关;送港可先到港,报关也可先完成客户确认/正式申报。船舱不足记录 `ROLLED_OVER`,保存原船次、改配船次、滚动次数和通知;只有承运船舶真实开航才写 `VESSEL_DEPARTED`/海运节点 | 送港、船次、甩柜、海运节点 | +| P3-Q16 | 报关资料何时收集、何时正式报送? | 装柜后通知报关,按客户确认轮次完成后正式提交 | 模块阻断 | 已确认 | 用户当前对话确认 | 2026-09-24 | `LOADED` 后以最终实装清单通知报关行,按客户/入仓码收集资料并发送报关行;回执发客户确认,打回则重新上传、重新发送并产生新回执,循环至所有客户通过;全部客户确认后再提交整柜资料给报关行确认,由报关行正式申报;海关查验/不查验放行等结果单独记录;报关完成后进入待发区 | 客户资料、回执轮次、客户确认、整柜申报、待发区 | +| P3-Q17 | 送港和报关是否互相等待?甩柜何时发生? | 报关完成后进入待发区,实际开船才进入海运 | 开工阻断 | 已确认 | 用户当前对话确认 | 2026-09-24 | `LOADED` 后先完成报关;报关完成后进入待发区,再安排拖车、送港和进港。船舱不足记录 `ROLLED_OVER`,保存原船次、改配船次、滚动次数和通知;甩柜/改配不影响已完成报关资料、回执和客户确认;只有承运船舶真实开航才写 `VESSEL_DEPARTED`/海运节点 | 送港、船次、甩柜、海运节点 | ### 2.1 PDA 已确认子决策 @@ -55,10 +55,10 @@ |---|---|---|---| | P3-D1 | 2026-08-08 | 国内货柜履约不新建独立出仓单,现有订单列表承载全部主状态;柜次、订舱、拖车、拣货、证据和报关作为订单关联子对象 | 取消出仓单页面和数据模型规划,改为增强现有订单列表/详情及服务端统一编排 | | P3-D2 | 2026-08-10 | 订单拆分采用“父订单→子订单→柜次”;已装载数量形成子订单,未装载数量自动生成后续子订单;支持一单多柜和多订单拼柜 | 后端必须保留父子订单、柜次、数量分摊和整体时间线;不得把未装载部分静默丢弃 | -| P3-D3 | 2026-08-10;2026-09-24 更正 | `LOADED` 只表示物理装柜完成,门禁包含真实柜号、PDA 拣货、数量守恒和五类证据;装柜后报关线、送港线独立推进,报关客户确认不阻断送港,进港不代表报关完成;实际开船前再校验报关结果、港口和船次条件;`LOADED` 后错误线下人工处理 | 统一门禁服务分别维护物理装柜、报关案例、送港/进港、甩柜和实际开船事实;国内页面不提供在线冲正或 `DELIVERED` 操作 | +| P3-D3 | 2026-08-10;2026-09-24 更正 | `LOADED` 只表示物理装柜完成,门禁包含真实柜号、PDA 拣货、数量守恒和五类证据;报关完成后进入待发区,再推进送港/进港;甩柜只影响船期,不影响已完成报关;`LOADED` 后错误线下人工处理 | 统一门禁服务分别维护物理装柜、报关案例、待发区、送港/进港、甩柜和实际开船事实;国内页面不提供在线冲正或 `DELIVERED` 操作 | | P3-D4 | 2026-08-10;2026-08-19 更正归期 | 船公司官网查询:每 3 天一次、最多 3 次,保存来源、更新时间和过期标识 | 该能力及首批六家来源整体归海外仓业务,国内货柜履约只保留订舱与出仓前船期资料 | | P3-D5 | 2026-08-10 | 初始化仓库常用角色:操作员、拣货员、理货员;按最小权限授予拣货、证据上传和查看能力 | 角色初始化由 IAM/统一 SQL 任务实现,具体权限矩阵在技术契约评审中落表 | -| P3-D6 | 2026-09-24 | 费用确认不阻断排柜和装柜;装柜完成后对已装范围的当前有效已发布版本执行系统默认确认,来源与客户主动确认分开审计;`LOADED` 后报关采用“报关行回执→客户确认/打回重做→所有客户通过→整柜正式申报→查验/放行”,送港线并行并单独记录甩柜和实际开船 | 同步费用版本、部分装载、客户报关案例、回执轮次、整柜申报、送港/船次和客户/后台节点;该规则覆盖旧的“装柜完成不得代替客户自动确认”和“报关/送港单线串行”口径 | +| P3-D6 | 2026-09-24 | 费用确认不阻断排柜和装柜;装柜完成后对已装范围的当前有效已发布版本执行系统默认确认,来源与客户主动确认分开审计;`LOADED` 后报关采用“报关行回执→客户确认/打回重做→所有客户通过→整柜正式申报→查验/放行”,报关完成后进入待发区,送港/船次单独记录甩柜和实际开船 | 同步费用版本、部分装载、客户报关案例、回执轮次、整柜申报、待发区、送港/船次和客户/后台节点 | ## 四、建议确认顺序 diff --git a/国内货柜履约/报关资料与船期价格接入梳理.md b/国内货柜履约/报关资料与船期价格接入梳理.md index 2859e1a..f662bd5 100644 --- a/国内货柜履约/报关资料与船期价格接入梳理.md +++ b/国内货柜履约/报关资料与船期价格接入梳理.md @@ -8,14 +8,16 @@ **当前基线**:以最新用户确认和[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准。旧版需求表、README、开发规划和本文件中的历史建议若发生冲突,先在当前入口记录收尾变更,再决定是否需要修改专题细节。 +**当前实现快照(2026-09-26)**:两份文件链路已经落到平台、客户和 Firstleg 报关接口:客户资料、报关行回执、客户整份回执确认/打回、平台发送报关行执行、真实报关完税文件分别保存并受版本门禁控制。回执发送给报关行后不可再替换;只有包含退税货物的柜才允许走发送执行接口;全买单柜仍走平台直接完成。`brokerSubmittedAt` 只表示发送执行时间,不表示报关完成。PDA 只负责产生 `LOADED` 前置事实,报关验收不创建或操作 PDA 任务;船期、甩柜和改配只修改原柜运输信息,不重置报关资料和确认结果。 + ## 先锁定的范围 -国内货柜履约的物理装柜节点为 `LOADED`。`LOADED` 后同时启动两条独立流程: +国内货柜履约的物理装柜节点为 `LOADED`。`LOADED` 后先完成退税客户的报关协同,报关完成后进入待发区,再推进船期运输: 1. **报关线**:仅对退税客户通知报关行,收集退税客户资料,发送报关行,接收报关行回执并发客户确认;客户认为不正确时打回、重新上传、重新发送并生成新回执,循环至柜内退税客户均确认;全部确认后,再将退税申报资料提交报关行确认,由报关行正式申报,记录查验、不查验放行或其他海关结果。买单货物不进入这条资料和回执流程。 -2. **送港线**:安排拖车、从仓库发运、送港、进港;港口容量不足时记录甩柜和改配船次。送港线可以早于或晚于报关线完成,`PORT_RECEIVED` 不等于海运中,只有船舶真实开航后才进入海运节点。 +2. **船期线**:报关完成并进入待发区后,安排拖车、从仓库发运、送港、进港;港口容量不足时记录甩柜和改配船次。甩柜/改配只改变运输船次,不重新处理已完成的报关资料、回执和客户确认;`PORT_RECEIVED` 不等于海运中,只有船舶真实开航后才进入海运节点。 -两条线互不作为 `LOADED` 的前置,也不要求一条线完成后才能启动另一条线。首期不对接海关单一窗口或报关代理系统:报关行回执以文件上传为主,正式申报由授权人员人工提交,客户确认和海关结果由平台人工记录。 +报关完成是进入待发区的前置;进入待发区后才推进船期运输。首期不对接海关单一窗口或报关代理系统:报关行回执以文件上传为主,正式申报由授权人员人工提交,客户确认和海关结果由平台人工记录。 费用确认是并行事实,不阻断排柜、预装、PDA 或装柜。装柜完成后,对应已实装范围若客户仍未确认当前有效且已发布费用版本,系统记录“系统默认确认(装柜完成)”;不伪造客户点击,保留 `SYSTEM_AUTO_AT_LOADED` 来源、费用版本、柜次/入仓码、时间和幂等标识。没有有效费用版本时不得生成零额或伪造确认,须保留费用异常待办。 @@ -35,27 +37,27 @@ ## 当前实现事实 -1. 客户端当前通过订单接口查询报关资料,现状主要只对服务端确认已完成装柜的退税订单开放;本目标稿调整为 `LOADED` 后启动本柜报关批次,按客户/入仓码收集资料、接收报关行回执、提交客户确认并支持打回重做。资料可上传、替换、改关联、删除并保留版本;每轮发送和回执都要留痕,客户确认后才进入该客户的 `CUSTOMER_CONFIRMED`。对应接口和权限见 [customs-v1.yaml](C:/Users/BY-OY/Desktop/code/chongchong-global/baiyue-firstleg/src/main/resources/openapi/customs-v1.yaml:48)。 +1. 客户端当前通过订单接口查询报关资料,现状主要只对服务端确认已完成装柜的退税订单开放;本目标稿调整为 `LOADED` 后启动本柜报关批次,按客户/入仓码收集资料、接收报关行回执、提交客户确认并支持打回重做。资料可上传、替换、改关联、删除并保留版本;每轮发送和回执都要留痕,客户确认后才进入该客户的 `CUSTOMER_CONFIRMED`。对应接口和权限见 [customs-v1.yaml](../../baiyue-firstleg/firstleg/src/main/resources/openapi/customs-v1.yaml#L48)。 2. 当前柜级状态为 WAITING_CUSTOMER_DOCUMENTS → READY_TO_START → DECLARING → COMPLETED;目标需要增加客户确认轮次、整柜正式提交、查验/放行和送港子状态。资料关联以 loadingPlanId、柜级聚合、客户报关案例和整票入仓码为根。 -3. 当前 COMPLETED 会发布报关完成事件并参与离仓门禁。目标契约改为“客户资料确认轮次”“整柜正式提交”“海关查验/放行”分开;报关线和送港线独立维护,不能让某一条线的完成事件直接代替另一条线。 +3. 当前 COMPLETED 会发布报关完成事件并参与待发区门禁。契约将“客户资料确认轮次”“整柜正式提交”“海关查验/放行”分开;报关完成后才允许进入待发区,船期事实独立维护。 4. 全买单柜已有独立的二次确认接口和导出契约,本期继续保留;需要补齐其在客户确认轮次、整柜正式申报、海关结果和送港/开船状态中的位置。 -5. 客户端现有价格接口为按起运仓查询渠道,以及按指定渠道估算参考费用。/estimate 只返回基础参考费用,不含复杂附加费和最终结算调整;pricingTaxMode 不等同于订单 taxMode。见 [fba-pricing-v1.yaml](C:/Users/BY-OY/Desktop/code/chongchong-global/baiyue-firstleg/firstleg/src/main/resources/openapi/fba-pricing-v1.yaml:130)。 -6. 仓库内原型与页面索引仍将报关上传、回执下载和出仓前船期资料列为待原型或部分参考;外部个人电脑路径不能作为唯一事实来源。页面范围需同步 [国内货柜履约页面与原型清单.md](C:/Users/BY-OY/Desktop/code/chongchong-global/docs/国内货柜履约/国内货柜履约页面与原型清单.md:30)。 +5. 客户端现有价格接口为按起运仓查询渠道,以及按指定渠道估算参考费用。/estimate 只返回基础参考费用,不含复杂附加费和最终结算调整;pricingTaxMode 不等同于订单 taxMode。见 [fba-pricing-v1.yaml](../../baiyue-firstleg/firstleg/src/main/resources/openapi/fba-pricing-v1.yaml#L130)。 +6. 仓库内原型与页面索引仍将报关上传、回执下载和出仓前船期资料列为待原型或部分参考;页面范围需同步 [国内货柜履约页面与原型清单.md](国内货柜履约页面与原型清单.md#L30)。 7. **费用默认确认目前是目标变更,不是现有实现。** 当前装柜完成逻辑只会自动发送/发布费用,不能把 `SENT` 直接当成客户确认;现有费用锁定也主要依赖客户确认时间。实现本轮目标时必须增加确认来源和幂等审计,并改为“客户确认或装柜默认确认 + 已装柜完成后才最终锁定”。部分装载只能确认本次已装范围,余量不能被顺手确认。 -8. **本轮报关/送港并行模型目前也是目标变更。** 当前代码的四态报关和离仓门禁不能直接证明已具备 `customerCustomsCase`、`roundNo`、报关行回执确认、客户打回重做、所有客户汇总、`ROLLED_OVER` 和 `VESSEL_DEPARTED` 事实;开发必须把这些作为新契约实现,不能只在现有页面上增加状态文案。 +8. **本轮报关完成→待发区门禁和船期例外需要保持独立。** 报关完成后才允许进入待发区;`ROLLED_OVER` 只记录新旧船次和运输变更,不回退或重新评估已完成的报关资料、回执和客户确认。 ## 报关资料模型 -### 0. `LOADED` 后报关线与送港线 +### 0. `LOADED` 后报关完成与待发区 | 线路 | 触发时点 | 顺序 | 结果 | |---|---|---|---| | 报关线 | `LOADED` 事件产生后 | 通知报关行 → 收集每个客户资料 → 发报关行 → 接收回执 → 发客户确认 → 打回则重传重发并生成新回执 → 所有客户确认 → 整柜资料交报关行确认 → 正式申报 → 查验/放行 | 客户确认轮次、整柜正式申报、海关结果 | -| 送港线 | `LOADED` 事件产生后 | 安排拖车 → 仓库离开 → 送港 → 进港 → 等待船次;装不下时甩柜/改配 | `DEPARTED_WAREHOUSE`、`PORT_RECEIVED`、`ROLLED_OVER`、实际开船 | +| 送港线 | 报关完成并进入待发区后 | 安排拖车 → 仓库离开 → 送港 → 进港 → 等待船次;装不下时在原柜船期上人工修改船信息并留痕 | `DEPARTED_WAREHOUSE`、`PORT_RECEIVED`、`ROLLED_OVER`、实际开船 | -两条线路可以先后不同。客户资料未确认只阻断报关线的整柜正式提交,不阻断送港;已进港也不代表报关完成或已经进入海运。只有船舶真实开航后,才写入海运起点。 +报关资料未完成时不得进入待发区;完成报关并进入待发区后才推进送港。已进港也不代表已经进入海运;只有船舶真实开航后,才写入海运起点。 客户确认是每个客户报关案例的完成条件;海关放行是整柜正式申报后的外部结果,不能用上传回执或任意“完成文件”代替。 @@ -63,11 +65,11 @@ 报关资料主流程在 `LOADED` 后启动。每个客户/入仓码在本柜建立一个 `customerCustomsCase`,再挂载稳定的 `packageId` 和文件版本。案例至少记录:订单/子订单、入仓码或入仓明细、实际装箱数展示、资料清单版本、每个清单项的文件版本、报关行发送时间、回执文件版本、客户确认/打回人和时间、打回原因、当前 `roundNo`、客户可见范围和审计记录。 -资料包不能只关联整票入仓码。已确认支持一单多柜、拆批和父订单—子订单关系,因此每个关联项保存客户、订单、入仓码和装柜明细引用;部分装柜只展示本柜实际箱数并标记线下处理,不在系统内自动做数量分摊。换柜时保留新旧柜关联,受影响案例不能静默沿用旧回执轮次。 +资料包不能只关联整票入仓码。已确认支持一单多柜、拆批和父订单—子订单关系,因此每个关联项保存客户、订单、入仓码和装柜明细引用;部分装柜只展示本柜实际箱数并标记线下处理,不在系统内自动做数量分摊。柜次一旦装柜完成不因甩柜改船而变化,受影响案例不能静默重置回执轮次。 ### 2. 实际装柜绑定快照 -资料包与 loadingPlanId、containerBookingId 的关系应通过绑定记录表达,而不是覆盖原资料包。绑定记录至少保存实际装柜明细引用、实装箱数、客户、订单、入仓码、柜次和绑定版本。`LOADED` 后开始本轮报关时冻结该范围;部分装柜只生成箱数展示和线下处理标记,换柜才需要使受影响案例的资料绑定和回执轮次失效并生成新版本。 +资料包与 loadingPlanId、containerBookingId 的关系应通过绑定记录表达,而不是覆盖原资料包。绑定记录至少保存实际装柜明细引用、实装箱数、客户、订单、入仓码、柜次和绑定版本。`LOADED` 后开始本轮报关时冻结该范围;部分装柜只生成箱数展示和线下处理标记,甩柜改船不使资料绑定和回执轮次失效。 ### 3. 申报组与柜级总览 @@ -98,7 +100,7 @@ | 送港/船期事实 | PORT_DELIVERY_PENDING、DEPARTED_WAREHOUSE、IN_TRANSIT_TO_PORT、PORT_RECEIVED、ROLLED_OVER、VESSEL_DEPARTED | 与报关案例独立;进港和甩柜不等于海运中,只有真实开船才进入海运节点 | | 装柜门禁 | PASS/BLOCKED | 只判断是否满足 LOADED 的已确认前置 | -上述是首期状态投影。回执首期以文件为主、客户确认整份回执;正式申报由平台授权人员人工提交并回填结果;实际开航首期人工录入,甩柜/改配生成新航次并重新评估申报批次。其余稳定编码、退回/重开规则和责任人仍需在开发前确认。当前四态不能直接承担新流程;收敛时应明确旧状态的映射和删除时点,不保留双协议。 +上述是首期状态投影。回执首期以文件为主、客户确认整份回执;正式申报由平台授权人员人工提交并回填结果;实际开航首期人工录入,甩柜/改配人工修改原柜船信息并保留原报关事实,不重新评估申报批次。其余稳定编码、退回/重开规则和责任人仍需在开发前确认。当前四态不能直接承担新流程;收敛时应明确旧状态的映射和删除时点,不保留双协议。 物理 `LOADED` 门禁必须明确校验以下事实: @@ -107,7 +109,7 @@ 3. 空仓、半仓、满仓、锁仓、带锁码照五类证据各有至少一张有效照片,锁码文本已保存; 4. 数量守恒、无未解决 PDA 异常。 -`LOADED` 后分别创建报关案例和送港任务。报关案例的整柜正式提交只校验所有客户 `CUSTOMER_CONFIRMED`;送港只校验装柜完成、真实柜号、订舱/拖车等运输条件。两条线可以先后不同。到港后如船舱不足记录 `ROLLED_OVER`;只有实际 `VESSEL_DEPARTED` 才进入海运节点。报关放行、送港和甩柜不能反向作为 `LOADED` 的前置。 +`LOADED` 后创建报关案例;报关案例完成整柜正式申报并达到报关完成条件后,才允许进入待发区并创建/推进送港任务。送港任务继续校验装柜完成、真实柜号、订舱/拖车等运输条件。到港后如船舱不足记录 `ROLLED_OVER`;只有实际 `VESSEL_DEPARTED` 才进入海运节点。报关放行、送港和甩柜不能反向作为 `LOADED` 的前置,甩柜也不改变已完成的报关事实。 每个写动作都需要 Idempotency-Key、expectedVersion、规范化请求哈希、乐观锁冲突码、审计事件和结果回放。上传、替换、改关联、补件、审核、提交批次、回执上传和门禁确认不得仅靠前端推进。 @@ -117,7 +119,7 @@ - 客户查看、上传/替换、补件确认和下载分别校验当前企业、订单/子订单、入仓明细和客户可见标记;不能信任请求中的 tenantId、订单 ID 或入仓码。 - 平台查看、审核/退回、生成提交批次、上传回执和发布结果分别授权;列表权限只包含详情只读,写权限独立。 -- File 文件类型、业务 ID、客户归属、版本、冻结和下载审计必须定义。现有 LOADING_LIST_CUSTOMS_SOURCE/RESULT 不能直接覆盖资料包、提交批次和回执的新类别。 +- File 文件类型、业务 ID、客户归属、版本、冻结和下载审计必须定义。现有 `LOADING_LIST_CUSTOMS_SOURCE`、`LOADING_LIST_CUSTOMS_RECEIPT`、`LOADING_LIST_CUSTOMS_RESULT` 只负责不可变文件对象,不能替代客户案例、提交批次和海关结果对象;正式申报与海关结果的独立接入见[专题设计](../头程到尾程/正式申报与海关结果接入设计.md)。 - File 上传成功但业务写入失败、业务写入成功但 File 失败、替换/作废和重试都要有补偿或可重放规则;不能产生越权文件或孤儿记录。 独立客户列表、详情、待办计数和平台筛选必须补充明确的路径、分页、稳定排序、筛选参数、空态/无权限响应和错误码。不能只写“新增列表”或继续复用单订单查询接口。 @@ -140,7 +142,7 @@ ## 实施顺序与进入条件 -1. **冻结业务规则**:确认客户资料清单、回执轮次、打回重做、所有客户确认、整柜正式申报、查验/放行、甩柜/改配和跨客户合并;已确认规则以[需求确认表](C:/Users/BY-OY/Desktop/code/chongchong-global/docs/国内货柜履约/国内货柜履约需求确认表.md:24)为准。 +1. **冻结业务规则**:确认客户资料清单、回执轮次、打回重做、所有客户确认、整柜正式申报、查验/放行、甩柜/改配和跨客户合并;已确认规则以[需求确认表](国内货柜履约需求确认表.md#L24)为准。 2. **先做服务端契约**:完成 customerCustomsCase、资料版本、报关行回执轮次、客户确认、整柜申报批次、送港/进港/甩柜/开船事实、状态投影、权限、幂等、审计、File 类别和初始化 SQL;同步更新 OpenAPI、Gateway、IAM 和相关消费者。 3. **接入客户入口**:独立列表/详情与订单快捷入口共用 packageId;仅在 `LOADED` 后进入本柜报关案例,覆盖资料上传、报关行回执查看、确认、打回、重新上传和新回执版本。 4. **接入平台协同**:`LOADED` 后按最终实装快照通知报关行,逐客户处理资料和回执,全部客户确认后提交整柜资料;人工记录正式申报、查验、不查验放行和其他结果。送港线独立接入拖车、进港、甩柜和实际开船。 @@ -153,7 +155,7 @@ | 资料清单具体项目、条件规则和版本生效方式 | 清单、审核、补件 | 首版人工维护清单及版本负责人 | | 客户确认/打回原因和回执轮次 | 客户案例、整柜提交 | 回执版本、roundNo、确认人、打回重做规则 | | 海关查验、不查验放行、扣货/补件等正式结果 | 整柜申报批次、客户展示 | 结果类型、凭证、来源、客户可见范围和责任人 | -| 送港、进港、甩柜、改配船次和实际开船事件 | 送港线、海运节点 | 事实字段、重试规则、客户通知和船次历史;首期人工录入实际开航,改配生成新航次并重新评估申报批次 | +| 送港、进港、甩柜、改配船次和实际开船事件 | 待发区、送港线、海运节点 | 事实字段、重试规则、客户通知和船次历史;首期人工录入实际开航,改配人工修改原柜船信息但不改变已完成报关事实 | | 价格比较、导出、报价有效期和金额变化提示 | 客户报价页、下单 | 统一币种/税模式/附加费和失效处理 | ## 最低验收矩阵 @@ -163,7 +165,7 @@ - 同一幂等键同请求只产生一次记录;同键不同请求、版本冲突、并发换柜和重复回执均返回明确业务错误。 - `LOADED` 后每个客户案例都能经历“资料上传→报关行回执→客户确认”;打回后只重开对应案例,重新上传、重新发送并产生新回执轮次,其他客户历史不被覆盖。 - 所有客户案例均 `CUSTOMER_CONFIRMED` 后,平台才允许生成整柜正式提交;正式提交后分别验收查验、不查验放行和其他海关结果。 -- 缺 PDA 结果、缺五类证据、真实柜号或数量不守恒时,`LOADED` 门禁失败;送港线单独验收离仓、进港和甩柜;只有真实开船才进入海运节点,报关线不作为送港启动前置。 +- 缺 PDA 结果、缺五类证据、真实柜号或数量不守恒时,`LOADED` 门禁失败;报关完成后才进入待发区,再验收离仓、进港和甩柜;只有真实开船才进入海运节点,甩柜不重做已完成报关。 - 全买单柜、退税柜和混合柜分别验证状态、权限、导出、回执和门禁结果。 - 价格无命中、失效版本、跨渠道批量估价、不同币种/税模式、附加费说明和订单创建重验均有可验证结果。 - 页面覆盖加载、空态、失败、无权限、过期和数据冲突;客户端按 1920×1080、100% 缩放人工验收。 @@ -173,6 +175,6 @@ - 客户端订单与现有报关:apps/client-web/src/modules/first-leg/routes.ts、views/FirstLegOrdersView.vue、components/CustomsDocumentsDialog.vue、api/customs.ts。 - 客户端导航和新页面:apps/client-web/src/navigation/clientNavigation.ts 及对应页面注册、权限和 release 配置。 - 平台整柜报关:apps/admin-web/src/modules/container-loading/components/ContainerCustomsPanel.vue、api/platformContainerCustoms.ts。 -- 后端报关:baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/customs/container/、[customs-v1.yaml](C:/Users/BY-OY/Desktop/code/chongchong-global/baiyue-firstleg/firstleg/src/main/resources/openapi/customs-v1.yaml:1)、phase3-container-customs-schema.sql。 -- 报价:apps/client-web/src/modules/first-leg/api/firstLeg.ts、apps/admin-web/src/modules/fba-pricing/carrier-rates/、[fba-pricing-v1.yaml](C:/Users/BY-OY/Desktop/code/chongchong-global/baiyue-firstleg/firstleg/src/main/resources/openapi/fba-pricing-v1.yaml:130)。 +- 后端报关:`../baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/customs/container/`、[customs-v1.yaml](../../baiyue-firstleg/firstleg/src/main/resources/openapi/customs-v1.yaml#L1)、`phase3-container-customs-schema.sql`。 +- 报价:`../apps/client-web/src/modules/first-leg/api/firstLeg.ts`、`../apps/admin-web/src/modules/fba-pricing/carrier-rates/`、[fba-pricing-v1.yaml](../../baiyue-firstleg/firstleg/src/main/resources/openapi/fba-pricing-v1.yaml#L130)。 - 国内边界、状态和门禁:[国内货柜履约 README](README.md:3)、[国内货柜履约开发规划(归档)](归档/国内货柜履约开发规划.md:166)、[国内货柜履约需求确认表](国内货柜履约需求确认表.md:24)。 diff --git a/国内货柜履约/船期日历功能规划.md b/国内货柜履约/船期日历功能规划.md new file mode 100644 index 0000000..75afc61 --- /dev/null +++ b/国内货柜履约/船期日历功能规划.md @@ -0,0 +1,671 @@ +# 船期日历功能规划 + +> 文档状态:首版开发规划;2026-09-27 复核补充了数据闭环规则。本文是开发依据,不是代码完成或上线验收证明。 +> 规划对象:Admin「国内头程 → 船期管理」独立船期日历。 +> 目标:支持人工维护渠道和船期规律,按周或单次生成具体船期,并按渠道/船期查看收货体积。 + +> **当前展示版范围已重新冻结:只做船期维护和只读展示,不做自动归班、不消费预报、不改写收货审核、不自动改绑,也不改变现有智能排柜流程。** 首版只需要让管理人员看到每个航次的已收/预计货量、可用容量、按柜型初算的建议柜数、已订柜和待补柜,并据此人工判断是否合并到其他船。后续若要增加货物归班,再单独立项评审。第 15.8 节覆盖本文此前关于自动归班和异常改配的旧口径。 + +> **展示版统计口径**:每个船期按“收货仓 + 渠道 + 起运港 + 目的港”展示;已收使用现有收货/测量结果,预计量使用现有入仓和智能排柜可读数据;不创建或变更船期归班事实。收货截止时间只用于标记“截止前参考量/截止后风险”,不触发自动分配。订柜数只做只读初算,最终以现有智能排柜和人工确认结果为准。 + +## 1. 输入来源与现状边界 + +本规划以当前需求描述为业务输入,以用户提供的截图作为页面布局参考。截图中的红框、日期、船名、航次、数量和示例数据均不构成额外指令,也不代表需要沿用的真实业务数据。 + +仓库当前已有 `apps/admin-web/src/modules/port-schedules/` 和 Firstleg 的 `portschedule` 服务。现有“港务船期”记录绑定客户、订舱或柜次,主要保存船公司/码头/API 的船期观测、过期时间和海运节点查询结果;对应表为 `fl_port_schedule`。它服务于已存在的订舱和货柜履约链路,不直接承载本规划的排班模板、周循环生成或收货量统计。现有 `port-schedules/routes.ts` 也不是本规划新页面的正式入口;新日历应作为独立 Admin 页面、路由和权限接入,不能把现有隐藏/嵌入式船期组件直接改成排班管理页。 + +本功能建议新增“船期计划”域,与现有港务船期并列: + +- 船期计划是运营人员提前安排“哪个渠道哪天开哪班船”,可以没有订舱和真实柜次;价格簿中的参考船期、最晚进仓和参考时效也不能直接当作该计划的实际开船事实。 +- 港务船期是某个订舱/柜次的外部船期事实或人工观测,继续按现有接口和状态机运行。 +- V1 先建立“计划实例 ↔ RELEASED 订舱”的最小关联用于订柜统计;真实柜次、港务船期和海运节点的完整关联后置,不能用计划数据覆盖已产生的运输事实。 + +本规划默认这是平台内部运营日历:渠道主数据平台级维护,模板和实例至少按收货仓隔离,实收汇总按“收货仓 + 渠道 + 收货日期”聚合并对平台运营人员可见。V1 不按客户拆分船期计划;如果实际业务存在客户专属船期或价格承诺,必须在开发前把客户作为模板、实例、查询和权限的正式维度,不能在上线后再用名称筛选补救。 + +## 2. 要解决的问题 + +运营人员需要在一个页面完成以下工作: + +1. 维护当前可售或可安排的运输渠道,例如“MATSON / 美森”。 +2. 配置固定每周哪几天有船,也可以只添加一班临时船期。 +3. 根据开船时间和渠道的提前收货天数,自动算出收货截止时间。 +4. 在月历上看到每天有几班船,以及每个渠道已收多少立方米、预计有多少货、容量还剩多少和建议订几个柜。 +5. 对已生成的具体船期进行编辑、取消、复制和查看关联货量,并保留变更历史。 + +## 3. 建议的 V1 范围 + +### 3.1 本轮纳入 + +- 船期渠道的新增、编辑、启用/停用。 +- 一次性船期的手工添加。 +- 每周模板的配置,按指定周几生成未来具体船期。 +- 每条模板/实例必填收货仓;首版不使用“全部仓”这种模糊范围。 +- 开船时间、预计到港时间、收货截止时间和容量的维护与计算。 +- 月历视图、月份切换、按收货仓/起运港/渠道/船名航次筛选。 +- 选中日期的船期详情和渠道体积汇总。 +- 船期实例的人工编辑、取消、复制下一班和变更历史。 +- 货量按收货仓与渠道只读展示已收实测体积、预计体积、截止前参考量、截止后风险量、已订柜和待补柜;不产生归班事实、不提供货量改绑。 +- 按现有柜型目录计算只读的“建议订柜数”,不直接创建正式订舱或货柜。 + +### 3.2 暂不纳入 + +- 船公司官网或第三方 API 自动抓取船期。 +- 自动订舱、舱位分配、放舱、拖车、报关和实际出仓状态推进。 +- 自动归班、预报消费、实收批次绑定、取消后自动改配和异常重新安排。 +- 在收货审核、测量审核或智能排柜流程中增加回调、写入或阻断。 +- 复杂的价格计算、客户报价和财务结算。 +- 以计划日历替代现有订舱/柜次船期事实。 +- 在没有业务确认前自动修改历史入仓数据或批量回溯全部历史货量。 +- 复杂节假日规则、跨时区排班和通知中心;这些作为后续扩展点保留。 +- 容量预占、超容强制处理、正常货量的批量改绑和跨客户拆分;异常货的最小重新安排按第 6.10 节纳入 V1。 + +## 4. 核心概念与生命周期 + +| 对象 | 作用 | 关键生命周期 | +| --- | --- | --- | +| 渠道 Channel | 表示一类运输服务,如 MATSON / 美森 | `ACTIVE`、`INACTIVE` | +| 船期模板 Schedule Template | 描述每周固定规律;固定添加一班直接创建实例,不再套一层单次模板 | `DRAFT`、`ACTIVE`、`INACTIVE` | +| 船期实例 Sailing | 某一具体日期的某一班船,是日历和货量统计的主体 | `DRAFT`、`OPEN`、`CLOSED`、`DEPARTED`、`CANCELLED`、`COMPLETED` | +| 归班事实 Sailing Assignment | 保存预计量/收货批次与船期的自动归班结果及历史 | `FORECAST_MATCHED`、`RECEIVED`、`LATE`、`UNMATCHED`、`SUPERSEDED` | +| 订舱关联 Sailing Booking Link | 将已放舱订舱的柜型需求关联到计划船期,用于订柜建议 | `ACTIVE`、`REVOKED` | + +模板生成实例后,实例保存自己的船名、航次、港口、截仓时间和容量快照。以后修改模板不回写已经生成、已编辑或已关联货量的实例;需要调整时由运营人员编辑实例或重新生成未落地的未来实例。 + +## 5. 页面信息架构 + +### 5.1 顶部筛选和操作区 + +- 月份:默认当前月,提供上月、下月和“今天”。 +- 收货仓:按仓库筛选;船期计划至少要绑定一个收货仓,不能只靠渠道和起运港推断。 +- 出发港:按港口代码和名称筛选。 +- 船期渠道:按启用渠道筛选,停用渠道仍可用于查询历史。 +- 船名/航次:模糊搜索。 +- 状态:全部、可收货、已截止、已取消、已开船、已完成。 +- 归班状态:全部、预计可赶船、已收、晚到、未安排;用于把“漏排或赶不上”的货量变成运营待办。 +- 操作:`新增船期`、`渠道与模板管理`。 + +另设“待安排/异常货量”入口,集中展示当前权限和仓库/渠道范围内仍待处理的货物,显示实际收货日或预计到仓日、等待天数及异常原因。未安排记录没有开船日期,不强行放进某个开船月,也不混入月历主合计;切换月份不使这些待办消失。 + +筛选条件应由服务端参与查询,不能先拉取整月全部记录后在浏览器本地拼装统计。 + +### 5.2 月历区 + +- 周一至周日为列,显示跨月日期但以浅色区分。 +- 每个日期格显示当天船期数量和航线摘要。 +- 摘要优先显示渠道名和收货体积,例如“美森 120 m³ / 200 m³”;渠道较多时显示前几项并提供“更多”。 +- 当前日期、选中日期、已截止日期、容量超限日期分别使用清晰但不依赖颜色的标签/图标表达。 +- 点击日期后,右侧详情区同步刷新;点击船期卡片可直接进入实例详情。 + +### 5.3 选中日期详情区 + +每个船期卡片至少展示: + +- 渠道、船名、航次和船期业务编号。 +- 起运港 → 目的港。 +- 预计开船、预计到港、最终收货截止时间。 +- 已收总量、本船可赶实收、预计可赶、晚到量、已订柜数、建议订柜数和待补柜数;各指标按第 6.6 节计算,已收总量不能直接当作可赶量。班次容量上限和剩余体积仅在已配置班次容量时展示,V1 不因容量不足自动改绑或强制拦截。 +- 当前状态和风险提示:已过截止、接近满舱、超过容量、已取消。 +- `编辑`、`复制为下一班`、`取消船期`、`查看货量明细`。 + +删除仅适用于未开船、未关联任何货量的草稿/实例;有货量或已产生履约事实的实例只能取消,不能物理删除。 + +### 5.4 新增/编辑弹窗 + +弹窗提供两个明确入口: + +**按周添加** + +- 选择渠道、起运港、目的港。 +- 选择收货仓;同一渠道可按不同收货仓配置不同截止规则。 +- 选择一个或多个周几。 +- 选择开船时间、航程天数或预计到港时间。 +- 设置提前收货天数、有效起止日期和默认容量。 +- 设置船名固定值或船名规则;设置航次生成规则。 +- 选择未来生成范围(建议 4 / 8 / 12 周)。 +- 先预览将生成的实例,再确认批量生成。 + +**固定添加一个** + +- 直接填写开船日期时间、船名、航次、起运港、目的港。 +- 填写或确认收货截止时间、预计到港时间、容量。 +- 保存为一条独立实例,可选关联一个模板作为来源。 + +周模板中的船名是生成实例的默认值;船司确认后可逐班编辑船名、航次和截止时间。当前展示版编辑实例时保留已保存的绝对截止时间,切换到“按开船前 N 天”后才重新计算;规则快照和覆盖原因待后端契约补齐后再做完整留痕。 + +### 5.5 区间汇总 + +月历上方建议提供当前筛选范围的渠道汇总卡:已收实测 CBM、预计可赶 CBM、风险/未安排 CBM、已订柜数、建议订柜数、待补柜数、晚到批次数和船期数量。V1 卡片固定标明“按开船月”,收货月仅在详情和后续报表中使用;多班同渠道同日时仍按船期实例分开,不能只显示一个渠道总数。 + +## 6. 业务规则 + +### 6.1 收货截止时间 + +首版把“收货截止时间”正式命名为**最晚到仓时间 `warehouseCutoffAt`**,表示货物最晚什么时候到达我司收货仓,和船公司的截单、截关、截港时间分开保存。默认公式: + +```text +最晚到仓日期 = 预计开船本地日期 - 提前收货天数 +最晚到仓时间 = 收货仓截收时刻 +``` + +- 计算使用仓库业务时区,V1 默认 `Asia/Shanghai`;接口统一传 ISO 8601 时间。 +- 计划截止计算只基于实例保存的计划 `etdAt`;后续实际开船时间属于订舱/船节点事实,不反向改写已经产生的收货归班。 +- “提前 N 天”首版固定按自然日计算;工作日和节假日规则放到后续工作日历阶段。 +- 若收货仓暂未配置截收时刻,首版按 18:00 默认并记录规则来源,不能由前端使用浏览器本地时刻隐式补齐。 +- 首版默认使用 `3` 个自然日和 `18:00`;这个默认值不是从截图推断的,而是初始运营参数,后续按试运行数据校准。 +- 单班页面允许选择提前 2/3/4 个自然日或自定义本班截止时间;当前展示版保存计算后的最终 `warehouseCutoffAt`,规则快照与覆盖原因审计字段待后端契约补齐后再启用,页面不宣称已完成服务端留痕。 +- 最终截止时间必须严格早于开船时间;开船时间、截止时间和容量的校验由服务端最终执行。 +- 时间边界统一到毫秒:实际/预计到仓时间等于截止时间视为准时;当前时间大于截止时间才停止新归班,不能由不同页面采用不同的 `<`、`<=` 判断。建议值由服务端计算并返回,前端只展示。 +- 是否跳过周末/节假日、节假日向前顺延几天,需要在产品确认后接入工作日历,不能由前端自行猜测。 + +### 6.2 每周模板生成 + +- 按模板有效期和周几生成具体日期,跨月日期仍属于实例,查询某月时按开船时间落入月份返回。 +- V1 采用“预览后手工确认生成”,不做后台滚动生成;页面默认未来 8 周,并提供未来 4/8/12 周快捷范围,生成范围由操作人确认后提交。 +- 生成请求必须幂等;同一模板、日期、航次规则只能生成一条有效实例。 +- 已编辑、已关联货量、已关闭、已开船或已完成的实例不被重新生成覆盖。 +- 发现相同日期/航次冲突时返回冲突清单,让用户选择跳过或进入实例处理,不能静默覆盖。 +- 模板停用只阻止未来生成,不删除历史实例。 +- V1 如遇某周停航或临时改船,允许在生成预览中跳过日期或生成后取消实例;节假日批量例外规则放到后续阶段。 +- 去重和冲突检查必须跨模板执行,至少按“收货仓 + 渠道代码 + ETD 本地日期时间 + 航次”判断,不能只用 `template_id + date` 作为唯一键。 +- 同一收货仓、渠道、起运港和目的港下,若多班船的 ETD 相同,V1 按不可变的 `sailing_no` 升序确定唯一归班;复杂的运营优先级后置。 + +### 6.3 航次号和船名 + +V1 支持固定值和“前缀 + ETD 本地日期”两种航次生成规则;每个生成实例允许人工覆盖航次。顺序号和按船名递增规则后置,避免首版因船公司编号规则不同而误生成正式航次。 + +业务唯一性首版约束“收货仓 + 渠道代码 + 起运港 + 目的港 + ETD 本地日期时间 + 航次”;同一航次跨不同起运港可以存在,但不能在同一组合内重复。`sailing_no` 在实例创建时生成后保持不变,用于同一 ETD 的确定性排序;展示给用户的业务编号应为船期编号、船名和航次,不能回退显示数据库 ID。 + +### 6.4 可赶船判断和人工改绑 + +默认推荐某一入仓记录时,只允许候选实例同时满足: + +- 渠道、起运港和目的港匹配。 +- 状态为 `OPEN`,且当前时间未超过最终收货截止时间。 +- 后续启用容量控制时再校验未超过容量;V1 只展示已配置容量和超量提示,不因容量字段缺失阻断归班。无上限实例可明确标记为“不限舱位”。 +- 按“最早可开船”或产品确认的优先规则排序。 + +超过截止时间时不能自动分配到该船期;容量不足在 V1 只显示明确预警,不阻断自动归班,也不能把预警状态伪装成已锁定舱位。任何已关闭、已取消或已开船的船期都不能作为新的自动归班候选。人工改绑必须记录操作者、原船期、新船期、时间和原因。 + +建议把“预计归班”和“实际收货统计”分成两条事实: + +- 预计归班可使用入仓单的 `expectedArrivalAt`,只有预计到仓时间早于或等于最终截止时间,才标记为“预计可赶船”。没有预计到仓时间的记录进入“待确认”,不能凭渠道名称或创建时间猜测。 +- 实际统计使用已确认的实际收货时间和审核后的实测体积。已有计划归班的货实际到仓晚于截止时,保留原计划并标记“晚到风险”,不能自动塞到下一班。首次形成实收事实且从未归班的货,若仓库、正式渠道和航线明确,可首次自动选择仍开放且未过截止的最早匹配船期,同时校验实际到仓时间不晚于该船截止;无候选或资料不全则写入“未安排”。因取消、晚到而进入未安排的货不属于“从未归班”,须走第 6.10 节。 +- 同一收货批次只能有一个有效计划归班。自动匹配以收货仓、渠道、港口和最早可赶上的有效实例为条件;同一时间存在多班时,必须有固定排序规则。 +- 归班在入仓计划审核、预计到仓时间/渠道/仓库变化或实际收货确认时重新计算;船期取消时只新增一条 `UNMATCHED` 变更记录并标记待人工处理,不自动塞入下一班。船期仍为 `OPEN` 且尚未达到最终收货截止时间、没有锁班/订舱事实时允许动态重算。船期达到截止时间后冻结当前归班,即使实例仍显示为 `OPEN` 也不再自动换到下一班;截止前尚未匹配的对象才继续寻找后续可赶船。运营确认订舱、船期进入 `CLOSED` 或船期取消后的改配必须产生新的人工或明确改配记录。 + +建议的状态落库规则是:预计匹配但尚未收货为 `FORECAST_MATCHED`;实际收货时间不晚于截止且有审核实测体积为 `RECEIVED`;实际收货晚于截止仍沿用原计划为 `LATE`;没有可解释的计划归班为 `UNMATCHED`;重新计算后被新结果替代的旧记录为 `SUPERSEDED`。这些状态首版必须持久化,详情中追溯匹配规则、时间、来源和被替代关系。 + +首版自动归班采用“写入事实 + 版本化重算”: + +- 预计匹配、实际收货、晚到和未安排都写入归班事实,不能只在查询时临时计算。 +- 船期仍为 `OPEN` 且未锁班时,重新计算不覆盖旧记录,而是将旧记录标记 `SUPERSEDED` 并写入新版本。 +- 船期进入 `CLOSED` 或已确认订舱后,原归班结果保留;取消、甩柜或改配只新增变更记录,不静默改写历史。 +- V1 仅开放第 6.10 节的异常重新安排,来源记录为 `MANUAL`;正常货量的批量改绑、拆分分配和强制赶船后置。 +- 冻结的是船期归属,不是收货事实的数值。冻结后最终审核、复测、冲正仍更新事实版本及其统计值;原归属保留,不因数值变化自动换船。 + +### 6.5 货量统计 + +V1 建议至少将“已收体积”和“预计体积”分开;“预占体积”只有在确认需要锁定容量后再启用: + +- **已收体积**:入仓事实已达到产品确认的可计入状态,并有有效体积。 +- **预计体积**:按预计归班的未收货量单独展示,不直接计入“已收体积”,也不自动扣减容量,除非产品确认要按预计量锁舱。 +- **预占体积**:已明确锁定该船期但尚未形成收货事实的货量;V1 若不做预占则固定为 0。 +- **剩余体积**:配置容量上限时按 `容量上限 - 已收体积 - 预占体积` 计算;V1 未启用预占时预占值为 0,预计体积不扣减剩余容量;结果不得小于 0,无上限显示“—”。 + +体积字段必须统一单位为 m³,并保存统计快照时间。V1 只统计明确达到“已收货”状态、且有正数 `actualVolumeCbm` 的收货批次;实测体积是后续作业的权威输入,申报体积仅作对比,计费体积不能冒充“已收体积”。当前 `inboundedAt` 会在多个入库流程节点写入,不能单独视为最终收货事实;V1 必须新增或正式暴露稳定的收货批次事实,不能把 `inboundedAt` 作为替代。取消、草稿、作废或不符合统计口径的记录不计入已收体积。拆批、复测和冲正均按收货批次版本守恒。 + +### 6.5.1 V1 数据来源契约(必须一并实现) + +当前入仓模型已经有 `warehouseId`、`channelCode`、`expectedArrivalAt`、`actualVolumeCbm` 和测量审核状态,但没有稳定的收货批次 ID、实际收货时间和可靠的未收预计 CBM;现有 `originalVolumeCbm` 是客户申报值,不能作为预计可赶体积。首版必须补齐下面两类事实,不能在页面层临时拼接: + +| 事实 | V1 必须提供的字段 | 统计和归班规则 | +| --- | --- | --- | +| 收货批次事实 `ReceiptBatchFact` | `receiptBatchId`、`inboundId`、`receivingWarehouseId`、`channelCode`、起运港/目的港快照、`receivedAt`、`actualVolumeCbm`、最终测量批次 ID、审核状态、冲正/作废状态 | 仅 `RECEIVED/APPROVED` 且实测 CBM 大于 0 的批次计入已收;复测替换同一批次最新有效值,冲正/作废不重复计入 | +| 未收货量预报 `InboundVolumeForecast` | `forecastId`、`inboundId` 或可收货批次键、收货仓/渠道/起运港/目的港、`expectedArrivalAt`、`forecastVolumeCbm`、来源、有效状态、版本和更新时间 | 只有有效状态、预计体积大于 0 且有 ETA 的预报可计入预计可赶量;不得使用 `originalVolumeCbm`、申报箱数或计费体积代替 | + +补充规则: + +- 当前系统没有上述稳定事实的部分,V1 必须由 Firstleg 提供正式的收货批次和货量预报服务事实;页面不直接读取入仓单分页拼装。没有可靠预报时允许只显示已收和风险,但应显示“未提供有效预报”及缺资料票数,不能把未知量写成“预计无货”。数据生产入口按第 6.5.2 节落地。 +- 预报和实收按明确的预报批次关联,不以同一 `inboundId` 就认定整票预报已收完。实收只替换其明确对应的预计批次;未到货部分保留独立有效预报,禁止用实测 CBM 直接减整票预计 CBM。具体拆批与复测规则见第 6.5.2 节。 +- 航线匹配优先使用入仓/预报事实中的起运港和目的港;事实缺失时,仅当启用渠道存在唯一的默认起运港/目的港映射,才使用该映射并保存 `route_source=CHANNEL_DEFAULT`。渠道没有唯一默认航线时进入 `UNMATCHED`/风险,不按目的仓名称或自由文本猜测。 +- 一票分批到仓时按批次统计;复测、冲正和作废必须以版本或状态替换旧值,并保留审计历史。 +- 收货仓、渠道或航线缺失时,批次/预报进入 `UNMATCHED` 或风险清单,不得按渠道名称、订单创建时间或目的地名称猜测。 + +日历汇总应与右侧详情使用同一服务端统计口径,避免页面格子和详情卡片出现不同数字。建议由服务端按收货仓、渠道、船期、收货日聚合后一次返回;前端不得跨分页拉取入仓单再自行求和。超过容量时返回明确的 `overCapacity=true`,前端只负责展示。月历按开船日期展示班次,详情中应能展开实际收货日期和未安排/晚到记录,避免把“收货发生日”和“船期开船日”混为一个日期。 + +日期维度固定为两种:月历落格使用 `etdAt` 的本地日期;已收体积明细保留收货批次的 `receivedAt` 日期。V1 月历默认按“开船月”汇总,并将归属该船期的已收实测体积展示在对应开船日;收货月只用于详情展开和后续报表,不参与首版月历主合计。没有稳定 `receivedAt` 的批次只能进入风险/未安排,不能回退使用 `inboundedAt`。月历主合计排除已取消实例;取消实例仍可查历史快照,当前货量进入独立异常待办,重新安排后只计入目标实例,不能在两班重复相加。 + +### 6.5.2 事实产生、分批收货与预报替换 + +- **实际收货来源**:仓库完成一批到货确认时生成稳定收货批次业务键,记录真实 `receivedAt`、仓库和对应箱/件范围;最终测量审核通过后,该批次的实测体积才能计入已收。到货确认和最终审核是两个独立条件,审核操作时间不能冒充实际到仓时间。到货待审核单列票数;体积未知显示“待测量”,不补成 0 m³。 +- **未收预报来源**:V1 推荐由运营在入仓详情的“货量预报”区域维护预计批次、预计到仓时间、预计 CBM 和航线,Firstleg 保存来源、录入人及版本;更新/作废预报沿用入仓写权限,服务端核验仓库范围。日历消费这些正式事实。客户申报值可作录入参考,但不得未经运营确认直接成为有效预报。 +- **分批规则**:一条有效预报表示一批可对应收货的货物;部分到仓前或确认到仓时,将其拆成“本次到货预报部分”和“剩余未到货部分”,子批次保留父预报键、各自预计 CBM 和预计到仓时间。拆分必须显式确认且预计量合计等于拆分前预计量;修订预计总量则另存一个有原因的新版本。 +- **替换规则**:本次到货批次一经确认,就停止把该部分计为未收预报;尚未测量审核时归入“已到待审核”,审核通过后用该批的实际体积替换。剩余批次继续按自己的预计体积统计。复测只更新对应实收批次,不能改变其他未到货批次的预计量。 +- **无法对应**:实收与预报无法确认对应关系时,相关预计量暂列“待核对”,不与可能重复的实收量一起计入可赶总量;展示缺口原因,运营补齐关系后再恢复。不得凭实测体积相近自动抵消。 +- **首版批次关联入口**:审核事件若能携带 `SAILING_FORECAST:`,服务端只消费该预报批次;多条有效预报且事件没有明确批次键时,实收保持 `UNMATCHED`/待核对,不自动按相近体积抵销。运营可通过预报维护接口显式绑定实收批次、修订预报或作废预报,所有动作均追加版本并保留原记录。 +- **事件与版本**:到货、审核、预报修订/拆分、冲正和作废均带稳定业务键及版本;同一事件重复到达不重复记量。来源版本更新与归班更新必须具备重试及对账机制,返回事实版本、归班版本和计算时间,不能只声明建了四张表就认为数据链路完成。 + +示例:整票预计 100 m³,先拆成本批预计 40、后批预计 60。本批实际到货审核后为 45,则“已收 45 + 未收预计 60 = 可赶 105”;复测为 43 后变成 103。不能用 `100 - 45` 把后批预计改成 55。 + +### 6.6 订柜数量建议 + +订柜数量是只读的运营建议,不是正式订舱或货柜创建。首版按以下口径展示: + +```text +本船可赶实收 CBM = 当前有效归班为 RECEIVED 的审核实测 CBM +可赶总 CBM = 本船可赶实收 CBM + 有效未收预计可赶 CBM +已收口径建议柜数 = 向上取整(本船可赶实收 CBM / 规划装载容量) +建议订柜数 = 向上取整(可赶总 CBM / 规划装载容量) +已订规划容量 = 求和(每个有效订舱需求的柜数 × 该柜型规划装载容量) +待补 CBM = max(0, 可赶总 CBM - 已订规划容量) +待补柜数(某柜型方案) = 向上取整(待补 CBM / 该方案柜型规划装载容量) +``` + +- “有效预计 CBM”只取有明确预计到仓时间、渠道/仓库/航线匹配且不晚于最晚到仓时间的有效入仓计划;没有 ETA 的货列为风险,不直接导致多订柜。 +- `LATE` 仍保留在该船历史和已收总量中,但不计入本船可赶实收或订柜建议。已收总量与可赶量是不同指标,不要求相等。 +- 超过截止但尚无到货确认的原预报,保留原归属并标为“到仓待核实”,退出有效预计可赶量;实际到货事实到达后依据真实到仓时间判为准时或晚到。不得仅凭“当前时间已过截止”把所有未审核批次判成晚到。 +- `规划装载容量`、柜型、重量和装载约束复用现有统一柜型目录和智能排柜规则,不在船期日历中另写一套容量或利用率。未选择柜型时,按 40GP/40HQ/45HQ 分别展示方案,不能给出无条件的单一柜数。 +- 已订柜型混合时,展示各柜型数量及合计柜数,先按各自规划容量折算已订容量再计算待补量;不能拿“已订 1 个小柜”直接抵掉“建议 1 个大柜”。柜型容量缺失时待补数显示“待核实”,不默认为 0。 +- 班次容量上限只触发超量预警,不用它截断可赶总量。例如可赶 150 m³、班次上限 100 m³,建议仍按 150 m³ 计算,并标明超出 50 m³;不能少显示所需柜数。 +- 各柜型方案表示“如果待补量全部采用该柜型”的体积初算,未执行重量、混装及实际摆放优化;页面不用“必须订柜数”表示已经确认的订舱指令。 +- 页面必须标注“按体积初算,最终以智能排柜/人工确认结果为准”;重量、箱数、货物混装限制或数据缺失会使结果进入风险提示。 +- 已订柜数只读取 V1 计划船期-订舱关联下的有效 `RELEASED` 订舱需求;日历只保存建议计算的输入、规则版本、计算时间和结果快照,不直接生成正式柜次。 + +### 6.7 容量提示 + +- 0%~80%:正常。 +- 80%~100%:接近满舱提示。 +- 大于 100%:超容量提示;V1 不自动阻断只读汇总,也不提供绕过容量的强制关联。异常重新安排仍须满足目标船期状态、截止时间和履约锁定校验。 +- 无容量上限:展示“—”或“不限”,不参与百分比计算。 + +### 6.8 船期实例状态转换 + +建议只允许以下状态转换: + +```text +DRAFT → OPEN → CLOSED → DEPARTED → COMPLETED + └──────────────→ CANCELLED +OPEN → CANCELLED +CLOSED → CANCELLED(尚未开船;必须确认影响) +``` + +`CLOSED` 表示停止收货,`DEPARTED`/`COMPLETED` 表示计划记录的运营状态,不得代替现有订舱、装柜或实际船节点事实。实例一旦有有效收货或预占记录,不能回到 `DRAFT`,取消后仍保留货量关联和审计历史。 + +建议 `OPEN → CLOSED` 由服务端根据最终截止时间自动生效,页面只展示结果;`CLOSED` 不因刷新或修改筛选重新打开。`DEPARTED`、`COMPLETED` 在 V1 仅允许明确的运营动作或后续已确认事实推进,不能由“预计开船时间已到”直接推断。 + +### 6.9 停用、取消和甩柜 + +- 渠道停用只阻止新模板和新实例生成;已经生成且仍为 `OPEN` 的实例默认继续有效,是否批量关闭必须由运营人员明确操作。 +- 取消实例前必须展示影响范围:预计归班量、已收量、预占量和已关联订舱/柜次。已有已收量的实例只能取消或进入改配流程,不能删除。 +- 取消后,将原有效归班标记 `SUPERSEDED`,新增 `UNMATCHED` 版本并保存原船期及 `reason=CANCELLED`,展示为“未安排/待人工处理”;不自动把货量塞进下一班。新版本保留事实引用,原版本可追溯,不原地覆盖历史。 +- 同一取消操作将有效订舱关联改为 `REVOKED`,保留历史快照;不自动作废、重开或修改正式订舱。关联解除后当前订柜统计重新计算,正式订舱是否改船由已有订舱流程处理。 +- 甩柜/改配时保留原实例、原归班和实际收货事实,新增目标实例关联;不能回写或覆盖现有港务船期、订舱资料或报关事实。 + +### 6.10 V1 受限的异常重新安排 + +这是本轮推荐的范围补充,解决“异常已展示,但首版没有办法处理”的缺口。只允许处理未安排、晚到或因船期取消而待处理的货,正常批次批量改绑仍后置。 + +1. 运营在异常待办选择货物,查看原船期、当前事实版本、原因及匹配候选;选择目标并填写原因后确认,保存前先显示两班的货量变化。 +2. 目标须仓库、正式渠道、港口相符,状态 `OPEN` 且当前未过截止;预报另核验预计到仓时间,实收另核验真实到仓时间。V1 不提供绕过截止、强行修改实收时间或跨仓挪量的入口。 +3. 服务端核验独立异常安排权限、当前归班版本及目标船期版本;原有效版本转 `SUPERSEDED`,新版本写 `MANUAL`,保留原/新船期、操作者、时间和原因。并发重复确认只能成功一次。 +4. 货物如已绑定真实柜次、预装或装柜履约,先阻止在日历直接改配,并指向既有履约流程;不得通过改日历归班绕过实物锁定。无符合条件的目标时继续待安排,可先新增临时船期。 +5. 归班重新安排不自动转移订舱关联;目标班的已订柜仍只来自重新校验后建立的有效订舱关联。 + +## 7. 建议数据模型 + +以下为规划字段,具体命名应在接口和 SQL 评审时统一。 + +### 7.1 `fl_sailing_channel` + +| 字段 | 说明 | +| --- | --- | +| `id` | 渠道业务主键 | +| `channel_code` | 稳定渠道代码;固定渠道可映射现有渠道目录,自定义渠道也必须先建立稳定代码。现有装柜的九类渠道分组只作为兼容映射,不能把枚举写死为日历渠道全集 | +| `channel_name` | 渠道名称,如 MATSON / 美森 | +| `source_type` | `CATALOG`(复用现有物流渠道)或 `SCHEDULE_ONLY`(仅用于排班,尚未映射为可订舱渠道) | +| `mapped_channel_code` | 自定义排班渠道对应的正式物流渠道代码,可为空;为空时不能被订舱/价格接口当作正式渠道 | +| `default_departure_port_code` | 默认起运港,可被模板覆盖 | +| `default_destination_port_code` | 默认目的港,可被模板覆盖 | +| `default_cutoff_days` | 默认提前收货天数 | +| `status` | `ACTIVE` / `INACTIVE` | +| `remark` | 备注 | +| `created_at` / `updated_at` | 审计时间 | + +标准渠道优先复用现有仓库范围内的 ACTIVE 物流渠道和稳定 `channelCode`,不能只保存一个自由文本名称。自定义排班渠道必须通过 `SCHEDULE_ONLY` 明确标记,后续若要用于订舱或报价,先完成正式渠道映射。渠道停用不影响历史实例和历史统计;停用后不能新建模板或自动生成未来实例。 + +### 7.2 `fl_sailing_template` + +| 字段 | 说明 | +| --- | --- | +| `template_no` | 模板业务编号 | +| `channel_id` | 所属渠道 | +| `receiving_warehouse_id` | 收货仓;截止规则和可赶船判断的范围键 | +| `template_type` | V1 固定为 `WEEKLY` | +| `weekdays` | 周一至周日的选中集合 | +| `effective_from` / `effective_to` | 规则有效期 | +| `departure_time` | 开船本地时间 | +| `voyage_rule` | 船名/航次生成规则快照 | +| `transit_days` 或 `eta_time` | 预计到港计算依据 | +| `cutoff_days` | 模板级提前收货天数 | +| `cutoff_local_time` | 收货仓默认截收时刻,可被实例覆盖 | +| `default_capacity_cbm` | 可选的班次计划容量;不替代统一柜型目录的柜容 | +| `status` | `DRAFT` / `ACTIVE` / `INACTIVE` | + +### 7.3 `fl_sailing` + +| 字段 | 说明 | +| --- | --- | +| `sailing_no` | 船期实例业务编号 | +| `template_id` | 来源模板,可为空(独立单次船期) | +| `channel_id` | 渠道快照引用 | +| `channel_code_snapshot` / `channel_name_snapshot` | 生成时的渠道编码和名称快照 | +| `receiving_warehouse_id` | 收货仓 | +| `departure_port_code` / `destination_port_code` | 港口快照 | +| `vessel_name` / `voyage_no` | 船名和航次 | +| `etd_at` / `eta_at` | 预计开船、预计到港 | +| `suggested_cutoff_at` | 计算出的建议截止时间 | +| `cutoff_at` | 最终收货截止时间 | +| `cutoff_override` / `cutoff_override_reason` | 是否人工覆盖及原因 | +| `cutoff_rule_version` | 计算时使用的时区、自然日/工作日和截收时刻规则版本 | +| `capacity_cbm` | 可选的班次计划容量上限;空值表示不做班次容量提示,不替代统一柜型目录的柜容 | +| `container_type_code` | 默认柜型;为空时按可用柜型分别给出建议 | +| `status` | 实例生命周期状态 | +| `generated_key` | 模板生成幂等键 | +| `version` | 乐观锁版本 | +| `created_at` / `updated_at` | 审计时间 | + +不建议把已收体积、剩余体积作为可直接修改的主表字段;它们应由关联事实聚合,必要时做带统计时间的服务端快照。 + +### 7.4 `fl_sailing_assignment`(V1 自动归班;V1 受限异常重新安排) + +V1 必须由服务端持久化自动归班结果;常规人工改绑、拆分分配和预占仍放到 Phase 2,第 6.10 节的异常重新安排除外。归班对象以收货批次或货量预报为最小粒度,不以整张订单或整张入仓单代替。`sailing_id` 可以为空,表示已记录但尚未找到可解释班次的 `UNMATCHED` 结果。 + +| 字段 | 说明 | +| --- | --- | +| `id` | 归班事实 ID | +| `sailing_id` | 船期实例;`UNMATCHED` 时为空 | +| `inbound_id` / `receipt_batch_id` / `forecast_id` | 归班对象;至少有一个稳定业务键 | +| `assignment_source` | V1 为 `AUTO`;预留 `MANUAL`、`ROLLOVER` | +| `assignment_version` | 同一归班对象的版本号,重算递增 | +| `match_status` | `FORECAST_MATCHED` / `RECEIVED` / `LATE` / `UNMATCHED` / `SUPERSEDED` | +| `volume_cbm` | 本次归属的已收实测体积;V1 固定来自审核后的 `actualVolumeCbm` | +| `forecast_volume_cbm` | 本次归属的未收有效预计体积,与已收体积分开 | +| `forecast_source` | 预计体积来源;没有可靠预计体积时为空,不得用申报值冒充已收体积 | +| `route_source` | 航线来自入仓/预报事实或 `CHANNEL_DEFAULT`,用于追溯匹配依据 | +| `volume_source` | 已收状态固定为 `MEASURED_ACTUAL`;仅预计状态为空,计费/申报仅作对比或后续扩展 | +| `rule_version` | 自动归班规则版本 | +| `matched_at` / `superseded_at` | 归班和被替代时间 | +| `locked_at` / `lock_reason` | 达到船期截止、确认订舱或船期关闭后冻结归班的时间和原因 | +| `operator_id` / `reason` | 自动任务/后续人工操作审计 | + +同一批次或预报在同一时刻只能有一个 `AUTO` 有效归班版本;重新计算采用旧版本 `SUPERSEDED` + 新建版本,不能静默覆盖旧历史。 + +“同一业务对象”在这里指收货批次,不是整票订单或整张入仓单;一票分批到仓、复测或冲正时,必须按批次守恒,不能用单据级唯一键把后续批次锁死。 + +### 7.5 `fl_sailing_booking_advice_snapshot` + +这是订柜建议的可追溯快照,不是正式订舱记录。每次刷新或人工确认建议时保存: + +| 字段 | 说明 | +| --- | --- | +| `sailing_id` / `container_type_code` | 船期和柜型 | +| `received_cbm` / `forecast_catchable_cbm` / `risk_cbm` | 已收、可赶预计和风险体积 | +| `planning_capacity_cbm` | 从统一柜型目录读取的规划容量快照 | +| `recommended_container_count` | 按体积初算的建议柜数 | +| `booked_container_count` / `shortage_count` | 已订柜数和待补柜数 | +| `rule_version` / `calculated_at` | 计算规则版本和计算时间 | +| `risk_codes` | ETA 缺失、重量缺失、箱数缺失、混装限制等风险 | + +### 7.6 `fl_sailing_booking_link`(V1 最小订舱关联) + +首版要显示“已订柜数”和“待补柜数”,因此必须在 V1 建立计划船期与订舱的最小关系;复杂的实际柜次、甩柜和海运节点关联仍放到后续阶段。 + +| 字段 | 说明 | +| --- | --- | +| `sailing_id` | 计划船期实例 | +| `ocean_booking_id` | 海运订舱 | +| `link_status` | `ACTIVE` / `REVOKED`;解除关系保留历史 | +| `booking_status_snapshot` | 关联时的订舱状态快照;当前只有订舱状态为 `RELEASED` 才允许计数 | +| `warehouse_id` / `channel_code` / 起运港 / 目的港 | 关联时的业务匹配快照 | +| `linked_at` / `operator_id` / `reason` | 关联审计 | + +V1 采用以下计数契约: + +- 只有当前订舱状态为 `RELEASED` 且关联记录为 `ACTIVE` 的订舱才计入已订柜;`DRAFT`、已作废或已解除关联的不计入。`RELEASED` 是订舱状态,不是关联记录状态。 +- 已订柜数按该订舱的柜型需求 `quantity` 汇总,不按已生成真实柜次数量、不按装柜完成数量替代。 +- 一个 `RELEASED` 订舱首版只能关联一个计划船期;如果未来需要一个订舱拆到多班,再升级到按柜型需求行分摊的关系。 +- 关联时必须校验收货仓、渠道代码、起运港、目的港和计划船期一致;不一致进入冲突,不允许仅凭船名/航次文字关联。 +- 订舱解除、作废或计划取消后,已订柜数应在服务端重新计算,并保留原关联历史;不得把已订柜数当作人工可编辑字段。 + +## 8. 接口草案 + +接口路径和 DTO 以最终服务端归属为准,以下只作为拆分和评审入口: + +| 能力 | 建议接口 | 说明 | +| --- | --- | --- | +| 月历查询 | `GET /platform/v1/sailings/calendar` | 按月份、收货仓、港口、渠道、关键词、状态返回实例和服务端汇总;同时返回未安排/晚到摘要 | +| 实例详情 | `GET /platform/v1/sailings/{sailingId}` | 返回实例、统计、关联货量和操作权限 | +| 新增单次实例 | `POST /platform/v1/sailings` | 幂等创建,支持无模板来源 | +| 编辑/取消实例 | `PUT/PATCH /platform/v1/sailings/{sailingId}` | 乐观锁;取消保留历史 | +| 渠道管理 | `GET/POST/PUT /platform/v1/sailing-channels` | 启用、停用和主数据维护 | +| 模板管理 | `GET/POST/PUT /platform/v1/sailing-templates` | 周模板和启停;固定单次船期直接走实例接口 | +| 生成预览 | `POST /platform/v1/sailing-templates/{id}/generation-preview` | Phase 1 必须支持;返回日期、航次、冲突和截止时间预览 | +| 批量生成 | `POST /platform/v1/sailing-templates/{id}/generate` | 使用幂等键,返回成功、跳过和冲突清单 | +| 货量明细 | `GET /platform/v1/sailings/{id}/volume-summary` | V1 返回自动归班结果、服务端汇总和收货批次明细,不要求已经存在人工改绑 | +| 收货批次事实 | Firstleg 服务正式事实查询(路径以 Controller 归属评审为准) | 提供 `receiptBatchId`、`receivedAt`、最终实测 CBM、审核/冲正状态及仓库/渠道/航线快照;船期页面不得从入仓单分页自行拼装 | +| 货量预报事实 | Firstleg 服务正式事实查询(路径以 Controller 归属评审为准) | 提供 `forecastId`、`expectedArrivalAt`、`forecastVolumeCbm`、有效状态、版本和来源;没有可靠预报时只返回风险/未安排 | +| 订柜建议 | `GET /platform/v1/sailings/{id}/booking-advice` | 按柜型返回已收、可赶预计、风险、已订柜、建议柜数和待补柜数;只读 | +| 订舱关联 | `POST /platform/v1/sailings/{id}/booking-links` | V1 关联一个 `RELEASED` 订舱并校验仓库、渠道、港口和船期;只建立最小关系,不创建柜次 | +| 手工关联/改绑 | `POST /platform/v1/sailings/{id}/volume-allocations` | Phase 2+;校验截止、容量、收货仓归属和幂等键 | +| 变更历史 | `GET /platform/v1/sailings/{id}/history` | 实例、模板和手工改绑审计 | + +所有写接口建议使用 `Idempotency-Key`、`expectedVersion` 和服务端权限校验;错误响应应能区分重复生成、容量不足、已截止、状态冲突和归属不一致。 + +## 9. 权限建议 + +权限按“看”和“改”拆分,至少包括: + +- `platform:firstleg:sailing-calendar:list`:查看月历、详情、货量汇总和只读历史。 +- `platform:firstleg:sailing-calendar:create`:新增单次船期。 +- `platform:firstleg:sailing-calendar:edit`:编辑、复制和取消。 +- `platform:firstleg:sailing-volume:exception-reassign`:V1 受限异常重新安排;只能处理取消、晚到和未安排货量,不能绕过截止、容量或真实履约锁定。 +- `platform:firstleg:sailing-volume:bind`:常规人工改绑、拆分和预占,Phase 2+ 才启用。 +- `platform:firstleg:sailing-booking:link`:建立或解除计划船期与订舱的最小关联。 +- `platform:firstleg:sailing-template:manage`:渠道、模板、批量生成和停用。 +- `platform:firstleg:sailing-volume:bind`(Phase 2+):关联/改绑货量。 +- 审计导出或跨业务检索如确有需要,再单独增加权限;普通详情历史不另造重复的只读权限。 + +权限只由服务端决定,前端按钮隐藏不能替代后端校验。 + +## 10. 分期建议 + +### Phase 1:可用的日历排班 + +- 渠道主数据、单次船期、周模板。 +- 截止时间计算和实例生成。 +- 生成预览、冲突清单和确认后批量生成。 +- 月历、日期详情、渠道维度的预计/已收体积汇总。 +- 服务端自动归班的只读结果:预计可赶船、已收、晚到风险、未安排。 +- 按现有柜型目录计算只读订柜建议:可赶总 CBM、建议柜数、已订柜数、待补柜数和风险提示。 +- 保存自动归班事实和版本历史;建立计划船期与 `RELEASED` 订舱的最小关联,用于计算已订柜数;为取消、晚到和未安排货提供受限异常重新安排。 +- 实例编辑、取消和基础历史。 + +Phase 1 不提供正常货量的批量改绑、强制赶截止和容量预占;只提供第 6.10 节的受限异常重新安排。若没有明确归班事实,只展示“未安排”,不能把按渠道汇总的体积伪装成某一班船已收。 + +### Phase 2:排班辅助和容量控制 + +- 模板复制和批量调整。 +- 在 V1 已实现的收货仓、渠道、港口、截止时间和确定性排序基础上,Phase 2 再增加复杂优先级、容量约束和多班冲突处理。 +- 容量阈值、超容拦截和有权限的强制处理。 +- 手工关联、改绑、预占和货量明细。 + +### Phase 3:运营增强 + +- 工作日/节假日日历。 +- 月度/渠道汇总导出和报表。 +- 截止提醒、异常通知和更完整的审计检索。 +- 与真实柜次、港务船期、甩柜/改配和实际海运节点的完整可追溯关联,但不覆盖已有运输事实;V1 的最小订舱关联已经前置。 + +## 11. 验收标准 + +1. 新建“美森每周周四”模板,预览并生成指定月份的所有周四实例;再次生成不产生重复实例。 +2. 新增一条固定船期,能够编辑开船时间、船名、航次、截止时间和容量;已有归班或已收货事实后只能取消,不能物理删除。 +3. 日历格和日期详情显示同一套渠道统计口径;至少能区分预计体积、已收体积、未安排/晚到和剩余容量。 +4. 根据收货仓、起运港、渠道、船名/航次和月份筛选后,月历数量、日期详情和统计合计一致;跨月日期不会重复或漏显示。 +5. 截止时间按服务端规则计算,人工覆盖有明确标识;超过截止或已取消的船期不能被自动推荐。 +6. 接近容量上限和超容量有明确状态;V1 只读提示,不能因为体积初算直接生成正式柜次。 +7. 停用渠道的历史实例可查询,停用后不能创建新的模板实例;渠道改名不改变历史实例的名称快照。 +8. 写接口具备幂等和乐观锁;重复提交、并发编辑、重复生成均返回可理解的冲突信息。 +9. 列表/详情只读、实例编辑/取消、模板管理、货量改绑分别受权限控制;操作历史可追溯到操作者和原因。 +10. 页面展示业务编号、船名、航次、港口和渠道,不以内部数据库 ID 作为用户可见回退。 +11. 对一班固定船和一班临时船,系统能分别展示已收 CBM、截止前预计 CBM、风险 CBM、已订柜数、建议订柜数和待补柜数;建议结果标注计算时间、柜型和规则版本,并明确最终以智能排柜/人工确认结果为准。 +12. 同一收货批次先产生预计归班,之后实际收货并复测;系统保留旧归班版本、只计最新有效实测体积,且不把预计体积与实测体积重复相加。 +13. 同一时刻建立两班船,自动归班结果稳定选择 `sailing_no` 较小者;船期截止后刷新页面,原归班仍显示为 `LATE` 或 `RECEIVED`,不会变成无历史的未安排。 +14. 一个 `RELEASED` 订舱关联一条计划船期,柜型需求数量计入已订柜;`DRAFT` 订舱、未关联订舱和真实柜次数量不会被错误计入。 +15. 自动归班在截止前可以重算;达到截止后原归班被冻结,后续实际收货标记为 `LATE` 时仍保留原船期。没有稳定收货批次或预报事实时只显示风险/未安排,不得用 `inboundedAt`、`originalVolumeCbm` 或入仓单分页合计补出数字。 + +## 12. 首版已冻结与后续校准 + +本轮已先采用以下口径,开发按此实现: + +1. 船期模板/实例必须绑定收货仓、渠道、起运港和目的港;不使用“全部仓”作为模糊范围。 +2. 已收只统计 V1 收货批次事实中明确完成收货、最终测量审核通过且 `actualVolumeCbm > 0` 的批次;申报体积和计费体积不计入已收。 +3. V1 新增或正式暴露稳定的 `receiptBatchId + receivedAt` 收货批次事实;不能用现有会被多个流程节点更新的 `inboundedAt` 单独代替。 +4. V1 新增或正式暴露 `forecastVolumeCbm + expectedArrivalAt` 货量预报事实;`originalVolumeCbm`、申报箱数和计费体积不得作为预计可赶量。 +5. 预计可赶量只纳入有明确 ETA、预计体积、渠道/仓库/航线匹配且不晚于 `warehouseCutoffAt` 的有效预报;没有 ETA 或航线的货列为风险/未安排。 +6. 自动归班选择最早可赶的 `OPEN` 船期,并在 V1 持久化 `FORECAST_MATCHED`、`RECEIVED`、`LATE`、`UNMATCHED` 和 `SUPERSEDED` 历史;截止前且未锁班时可以版本化重算,达到截止、`CLOSED` 或已确认订舱后冻结当前归班;船期取消只转为风险/待人工处理,不自动换班;晚到不自动改班。 +7. 同一收货仓、渠道、起运港和目的港下,ETD 相同的多班船按 `sailing_no` 升序确定唯一归班;同一归班对象同一时刻只能有一个有效版本。 +8. `warehouseCutoffAt` 暂定为开船本地日期前 3 个自然日、收货仓 18:00,时区为 `Asia/Shanghai`;它与官方截单/截关/截港分开。 +9. V1 建立计划船期与 `RELEASED` 订舱的最小关联;已订柜数按关联订舱的柜型需求 `quantity` 统计,`DRAFT` 不计入,不按真实柜次数量替代。 +10. 订柜建议复用现有柜型目录、容量和已订柜事实,只读展示建议柜数和待补柜数,不直接创建正式柜次;结果标注“按体积初算,最终以智能排柜/人工确认结果为准”。 +11. V1 航次规则只支持固定值或“前缀 + ETD 本地日期”,生成实例允许人工覆盖;不做顺序号自动递增。 +12. V1 采用人工预览后生成固定周模板实例;停航或临时变更先手工跳过/取消,暂不做节假日自动日历。 + +以下事项不阻断首版,但需要在试运行或进入后续阶段前校准: + +1. 多个收货仓是否能共同供货给同一班船;如果可以,建立明确的收货仓组,再做线路级合计,不能直接跨仓混算。 +2. 提前天数是否从自然日升级为工作日,周末/节假日是否接入工作日历。 +3. 渠道是否需要客户专属范围;若需要,客户必须进入模板、实例、查询和权限维度。 +4. 同一渠道同一天多班船的复杂运营优先级、航次生成规则和模板覆盖策略。 +5. 订柜建议是否支持多柜型混合、重量约束和装载率优化;首版按体积初算,最终以智能排柜/人工确认结果为准。 +6. 计划实例与真实柜次、港务船期的完整关联时机,以及甩柜、改配后的运输事实展示。 + +## 13. 工程接入门禁 + +进入实现阶段后,页面与接口需要同步维护以下入口: + +- Admin 页面放在 `apps/admin-web/src/modules/` 的独立业务模块内,包含 `pages/`、`routes.ts`、`api/` 和 `types.ts`;不能把模板和实例逻辑塞入现有 `CarrierScheduleQueryPanel.vue`。 +- 正式接入时同步 `src/app/router/index.ts`、`src/core/navigation/adminNavigation.ts` 和平台 IAM 权限初始化;菜单归属应在“国内仓”与“货柜管理”中选定后固定。 +- Firstleg 若承载服务端能力,需同步 Controller、OpenAPI、数据库基线、Gateway 路由和权限契约;月历统计由服务端返回,前端不以 `InboundOrderSummary` 分页结果自行拼装。 +- 需要优先复用现有仓库范围内的正式 `channelCode`/渠道目录,再为确有需要的排班专用渠道建立明确映射;同时校验入库实测字段、订舱/货柜船期和价格簿的引用边界。新计划不能回写港务船期观测或订舱快照。 +- V1 开发前必须先落地 `ReceiptBatchFact`、`InboundVolumeForecast`、`fl_sailing_assignment` 和 `fl_sailing_booking_link` 的服务端事实与索引;Firstleg 的当前基线对应 `phase4-sailing-facts-schema.sql`、`sailingcalendar/fact/entity` 和 `SailingFactsRepository`,部署统一增量也必须包含这四张表。如果这些事实没有来源,接口只能返回风险/未安排,不能伪造已收或已订柜数字。 +- 订柜建议必须读取统一柜型目录和 `RELEASED` 订舱需求;不得另建 40GP/40HQ/45HQ 容量常量,也不得用真实柜次数量替代订舱需求数量。 +- 页面验收覆盖正常、空数据、加载、失败、无权限、并发冲突、已截止、超容量和已取消状态,并按 Admin 当前 1920×1080、100% 缩放基线执行。 + +## 14. 建议实施顺序 + +1. 按第 12 节首版冻结口径建立统一的术语、体积、归班、截止时间和订柜建议规则。 +2. 画出模板、实例、货量关联和现有港务船期之间的关系,并评审权限与审计边界。 +3. 先落地服务端查询模型和月历返回结构,再实现 Admin 月历页面,避免前端自行拼装统计。 +4. 用“美森每周周四 + 一条临时船期 + 一批预计到仓数据 + 一批已收实测数据 + 一批晚到数据”做端到端造数和验收。 +5. 完成 Phase 1 后再决定手工改绑、容量预占、工作日历、导出和外部船期接入,避免首期把订舱和船公司接口一起带入。 + +## 15. 本轮复核结论与验收算例 + +本轮复核后的结论是:**基础排班可以进入开发;完整的收货统计、订柜建议和异常处理必须按本节算例验收后,才能认为首版可用。** 下面的数字是验收用例,不是初始化数据,也不是对截图示例的默认值。 + +### 15.1 分批收货不能用整票相减 + +- 一票有效预报拆为 A 批 40 m³、B 批 60 m³。 +- A 批实际到货并审核为 45 m³时,结果为“已收 45 m³ + 未收预计 60 m³”;不能把整票 100 m³ 直接减去 45 m³后把 B 批改成 55 m³。 +- A 批复测为 43 m³时,只更新 A 批实收版本;B 批仍为 60 m³。任一版本重复消费都不得重复计量。 +- 如果实收不能明确对应 A 或 B,相关预报暂列“待核对”,不把实收和预报同时计入可赶总量。 + +### 15.2 无预报直接收货与晚到的区别 + +- 没有预报但首次形成 20 m³审核实收,且仓库、渠道、航线明确、实际到仓时间不晚于某个 `OPEN` 船期截止:自动归入该船,状态为 `RECEIVED`。 +- 已经归属于周四船的批次,实际到仓晚于周四截止:保留周四历史,状态为 `LATE`;已收总量增加,但周四的“本船可赶实收”和订柜建议不增加。 +- 没有归班、资料缺失或已过截止才首次到仓的批次进入异常待办,不能仅因体积或渠道相似自动塞进下一班。 + +### 15.3 订柜建议要排除晚到并抵扣真实柜型容量 + +- 40HQ 规划容量按统一柜型目录读取,不能在日历模块复制常量。 +- 一班船有本船可赶实收 40 m³、有效未收预报 28 m³、晚到 35 m³;建议计算量为 68 m³,晚到 35 m³只在已收总量/风险中展示。 +- 若已有一个 40GP 和一个 40HQ 的 `RELEASED` 订舱关联,已订规划容量按两个柜型各自容量折算;不能只按“已订 2 柜”抵扣,也不能把 `DRAFT` 订舱计入。 +- 班次规划容量小于可赶总量时只显示超容量和超出体积,不能静默截断可赶量或降低建议柜数。 + +### 15.4 取消后的异常重新安排 + +- `CLOSED` 且尚未开船的船期可以取消;取消会保留原归班和订舱关联历史,将当前货量转为异常待办,不自动改到下一班。 +- 运营有异常重新安排权限时,选择目标 `OPEN` 船期、填写原因,系统同时校验仓库、渠道、港口、截止时间、目标版本和履约锁定状态。 +- 成功后旧归班为 `SUPERSEDED`,新归班为 `MANUAL`,目标班只计一次;目标班订柜关联必须另行建立或确认,不随货量改配自动转移。 +- 已有真实柜次、预装或装柜履约锁定的货不能从日历直接改配,必须回到对应履约流程处理。 + +### 15.5 开发完成判定 + +满足以下条件才通过首版业务验收:事实来源可追溯、预报和实收不重复、晚到不增加原班可赶量、取消后有异常处理入口、订柜按柜型需求折算且仅统计有效 `RELEASED` 关联、月历与详情使用同一服务端快照。仅完成页面、接口返回空数组或通过类型/编译检查,均不能作为通过依据。 + +### 15.6 成熟货代系统的排船期做法 + +成熟系统把“排船期”视为一条可执行的运输计划,而不是日历上的一个标记,通常分为四层: + +1. **服务/周班模板**:维护渠道、收货仓、起运港、目的港、固定星期、开船时间、时区、默认航程和默认截止规则。固定周班按滚动窗口生成未来 8~12 周的具体航次;模板停用只影响未来生成,不回写历史实例。Oracle OTM 也支持按固定星期时间或相对开船时间的偏移配置航次截点:[Oracle Cutoff Recovery Time](https://docs.oracle.com/en/cloud/saas/transportation/26c/otmol/planning/power_data/rates_and_codes/cutoff_recovery_time_details.htm)。 +2. **具体航次实例**:每班保存自己的船名、航次、计划 ETD/ETA、内部收货截止、船司确认的各类截止、状态和容量。模板只提供默认值;船司确认或运营人工覆盖后,只更新实例并保留变更历史。 +3. **货物归班事实**:预计到仓、审核后的实收批次、体积版本和当前归属独立保存,能追溯自动归班、晚到、取消和人工改配的前后航次。 +4. **订舱执行**:预报量、已收量、已订柜量、待补柜量分开统计。只有已确认/已放舱的订舱关联计入已订柜,草稿和取消订舱不计入。 + +一个航次不应只有一个“截止时间”。至少区分:我司仓库最晚收货时间、订舱接受截止、截单/SI、截关/CY、VGM,以及危险品/冷柜等特殊货类截止。DCSA 将这些作为不同的业务节点,并指出其会随船期、码头和货类变化:[DCSA Cut-off Times](https://dcsa.org/newsroom/cut-off-times-in-shipping)。VGM 还必须在装船前提前提交,才能满足装载条件:[IMO VGM](https://www.imo.org/en/ourwork/safety/pages/verification-of-the-gross-mass.aspx)。因此,本系统的“开船前 3 个自然日、收货仓 18:00”只能作为我司内部 `warehouseCutoffAt` 默认值,不能当作船司截关时间。 + +自动归班采用以下顺序:先按收货仓、渠道、起运港、目的港筛选 `OPEN` 且尚未超过 `warehouseCutoffAt` 的候选,再按 ETD 最早排序。实际到仓时间等于截止时间仍算准时;超过截止时间后,未锁班、未订舱的货物自动寻找下一班,下一班不存在时进入 `UNMATCHED/待人工`。已经锁班或已确认订舱的货物即使晚到,也保留原 `sailingId`,标记 `LATE/MISSED_CUTOFF`,由运营确认是否转下一班,不能静默改写原归属。 + +例如美森固定周四 10:00 开船,义乌仓内部收货截止为周二 18:00:周二 17:59 和 18:00 到仓的货物可赶本周四;周二 18:01 首次到仓的货物只能进入下一周四;已经确认归属本周四的晚到货物则保留本周四并进入晚到异常。 + +建议状态补充 `NEAR_CUTOFF` 和 `BOOKING_CONFIRMED/LOCKED`。`NEAR_CUTOFF` 只用于预警,仍允许收货;超过内部截止后由服务端禁止新的自动归班。船司延误、甩柜或取消时,保留原实例和归班历史,生成异常待办并要求明确改配,不直接把货物静默塞入下一班。 + +### 15.7 从当前版本到可运营版本的改造顺序 + +结论是保留现有“模板 → 航次实例 → 收货归班 → 货量汇总 → 订柜建议”主模型,不重做日历页面,先补齐以下规则和闭环。 + +**P0:上线前必须完成** + +1. 服务端统一执行收货截止门禁。候选航次必须同时满足 `status=OPEN` 和 `arrivalAt <= warehouseCutoffAt`;首次晚到不能继续挂当前航次,已存在归班的晚到只能保留原航次并标记 `LATE`。 +2. 建立锁班和字段冻结。已有确认订舱、人工锁班或履约事实后,禁止直接修改收货仓、渠道、港口、ETD、截止时间等关键字段;需要调整时走复制、取消或异常改配。 +3. 完善预报与实收的批次关联。同一收货批次只能消费一个有效预报;多个预报、错误的预报键、预报作废和拆分必须进入待核对,不能同时计入预报量和实收量。 +4. 取消/甩柜只产生异常待办,不自动把货物静默塞进下一班;人工改配必须记录原航次、目标航次、操作者、时间、原因和目标版本。 +5. 收货仓、渠道、起运港和目的港使用主数据选择并由服务端校验,不能长期依赖前端自由填写名称或 ID。 +6. 月历和详情只统计同一服务端口径:已收使用审核实测 CBM,晚到不计入原班可赶量,取消航次不计入主汇总,已订柜只统计有效的 `RELEASED/CONFIRMED` 关联。 + +**P1:首版稳定运行后完成** + +1. 增加预报维护、异常待办、人工改配、订舱关联/撤销等 Admin 操作入口。 +2. 模板支持完整有效期、停班例外、跨月生成和生成前冲突预览;默认滚动生成未来 8~12 周。 +3. 增加 `NEAR_CUTOFF`、待补柜、超容量、未安排等风险提示,并提供按渠道的 CBM 和柜量分组汇总。 +4. 所有写操作接入统一幂等和版本校验,避免重复点击、重复生成和并发覆盖。 + +**P2:运营增强** + +再接入船司/码头实际截点、节假日工作日历、容量预占、自动提醒、外部船期同步和更复杂的混合柜型优化。它们不应阻塞首版排船和收货统计上线。 + +### 15.8 当前展示版范围修正(以本节覆盖前文自动归班口径) + +本轮需求已明确:船期日历先作为**展示和决策辅助页面**,不接管现有收货、预报、智能排柜或订舱流程。前文关于 `Sailing Assignment` 自动写入、自动下一班、晚到改配、取消后异常重排和收货审核回调的内容,全部降为后续规划,不纳入当前开发验收。 + +当前版本允许运营人员维护渠道、周模板和具体船期;货量相关能力全部只读: + +- **已收 CBM**:读取现有收货/测量流程已经产生的有效实测结果,不在船期页面重新生成收货事实。 +- **预计 CBM**:读取现有入仓预报或智能排柜可读数据;没有可靠来源时显示“暂无数据”,不凭渠道名称或订单分页猜测。 +- **截止前参考量**:按船期的收货仓、渠道、起运港、目的港和 `warehouseCutoffAt` 做查询口径,只用于显示“理论上可供管理人员参考的货量池”,不表示货物已经归入该船。 +- **已明确本船量**:只读取现有系统已经明确关联到该船名/航次或现有订舱/柜次事实的数据;日历不新增关联。 +- **建议订柜数**:按可展示货量和统一柜型容量做初算,显示计算时间、柜型和“最终以智能排柜/人工确认结果为准”;不创建订舱、不锁舱位、不改柜次。 +- **合船判断**:页面只提供“本船未满、建议关注相邻船期”的提示,并展示相邻船的可用容量和货量对比;不自动合并、不自动改绑。 + +展示版的数据实现口径再明确一层:已收实测只统计测量审核为 `APPROVED` 且有 `actual_volume_cbm` 的有效入库单,按上一班截止时间到当前班截止时间的窗口汇总;主单只在未拆分时统计,拆分后的有效余量子单单独统计,避免父子单重复。当前没有可核验的预计体积来源时,预计量按 0 展示并在页面提示“暂无可核验数据”,不得把申报体积、原始体积或分页列表合计冒充预计量。已订柜读取已放舱订舱的柜型需求,优先识别已有船期关联,同时允许用仓库、渠道、港口、船名、航次和开船日期做确定性只读匹配;日历页面不创建关联。建议柜数只按统一柜型容量计算,待补柜只做提示。 + +当前版本明确不做以下写操作: + +1. 收货审核通过时,不调用船期日历服务,不写入 `fl_sailing_assignment`、预报消费或船期实收事实。 +2. 创建或修订预报不自动生成船期归班;预报维护接口不作为本轮页面入口。 +3. 取消船期不自动把任何货物转到下一班;货物归属仍由原智能排柜和订舱流程维护。 +4. 页面不提供货量异常改配、手工绑定实收、订舱关联/解除等操作;这些操作留在现有业务流程。 + +因此,本轮验收重点从“自动归班正确”改为:船期维护正确、展示口径透明、已收/预计/已订柜/建议柜数不重复、取消或截止只影响展示标签、不会改变原收货和智能排柜数据。后续如果需要让管理人员在页面上确认“合并到哪一班”,再单独增加人工确认动作和正式归属模型。 diff --git a/头程到尾程/README.md b/头程到尾程/README.md index 74d32b4..514137c 100644 --- a/头程到尾程/README.md +++ b/头程到尾程/README.md @@ -11,13 +11,16 @@ | 货柜入口 | [国内货柜履约 README](../国内货柜履约/README.md) | 分柜、装柜、报关协同、送港和进港的货柜范围 | | 报关与船期专题 | [报关资料与船期价格接入梳理](../国内货柜履约/报关资料与船期价格接入梳理.md) | 客户资料、报关行回执、客户确认/打回、正式申报、海关结果和船期价格 | | 报关开发交接 | [报关代码开发交接清单](报关代码开发交接清单.md) | 当前未完成的报关代码范围、完成条件和开发入口 | -| 第一阶段冻结矩阵 | [头程至实际开船节点冻结矩阵与缺口清单](头程至实际开船节点冻结矩阵与缺口清单.md) | F01-F24 节点、报关与送港并行关系、当前实现缺口和开发前确认项 | +| 头程与报关交互矩阵 | [头程节点与报关清关交互矩阵](头程节点与报关清关交互矩阵.md) | F01-F24 各节点的客户、平台、PDA、报关行和船期交互 | +| 第一阶段冻结矩阵 | [头程至实际开船节点冻结矩阵与缺口清单](头程至实际开船节点冻结矩阵与缺口清单.md) | F01-F24 节点、报关完成进入待发区、当前实现缺口和开发前确认项 | +| 正式申报与海关结果 | [正式申报与海关结果接入设计](正式申报与海关结果接入设计.md) | F22.7 正式申报批次、报关单号、F22.8 查验/补资料/放行/扣货/其他结果及三端边界 | +| 甩柜改配接入设计 | [甩柜改配接入设计](甩柜改配接入设计.md) | F23.3 原柜人工修改船信息并保留修改历史 | ## 变更查找 - **改客户看到的主节点或三大块关系**:先改总览,再检查对应阶段文档。 - **改头程下单**:查阶段一、阶段二;费用确认仍是并行事项,不阻断排柜和装柜。 -- **改海运(货柜)**:查阶段三、阶段四和报关专题;`LOADED` 后报关协同、送港运输两条线并行,实际开船后才进入海运节点。 +- **改海运(货柜)**:查阶段三、阶段四和报关专题;报关完成后进入待发区,甩柜只影响船期,实际开船后才进入海运节点。 - **安排报关开发**:只看[报关代码开发交接清单](报关代码开发交接清单.md),流程规则回看报关专题,不再从归档的开发规划开始。 - **改尾程入库和派送**:查阶段五、阶段六。 - **改页面范围或已确认需求**:查[页面与原型清单](../国内货柜履约/国内货柜履约页面与原型清单.md)和[需求确认表](../国内货柜履约/国内货柜履约需求确认表.md)。 diff --git a/头程到尾程/头程至实际开船节点冻结矩阵与缺口清单.md b/头程到尾程/头程至实际开船节点冻结矩阵与缺口清单.md index 94eb769..c31bcdb 100644 --- a/头程到尾程/头程至实际开船节点冻结矩阵与缺口清单.md +++ b/头程到尾程/头程至实际开船节点冻结矩阵与缺口清单.md @@ -9,14 +9,14 @@ F01-F13:下单、审核、到仓、测量、计费、费用确认、组托、待分柜 国内货柜履约 F14-F21:分柜、订舱、拖车、拣货、装柜、LOADED -LOADED 后并行 +报关完成后进入待发区 F22:报关协同 - F23:送港、进港、甩柜、改配 + F23:待发区、送港、进港、甩柜、改配 海运起点 F24:承运船舶实际开航 ``` -本阶段的终点是实际开航事实,不是“报关完成”、国内离仓、目的港清关或海外入仓。`LOADED` 只表示物理装柜完成;报关协同线和送港运输线从 `LOADED` 后同时启动,不能把其中一条线的结果写成另一条线的结果。 +本阶段的终点是实际开航事实,不是“报关完成”、国内离仓、目的港清关或海外入仓。`LOADED` 只表示物理装柜完成;报关完成是进入待发区的前置条件,待发区和船期节点分别保存,不能把其中一条线的结果写成另一条线的结果。 ## 二、F01-F24 节点冻结矩阵 @@ -27,24 +27,24 @@ LOADED 后并行 | F11-F13 | 费用待确认、待组托、待分柜 | 费用版本、确认记录、托盘 | 计费推送、客户确认、组托/封托 | 已确认并行规则 | 保证费用默认确认不能冒充报关确认 | | F14-F20 | 待分柜、订舱中、装柜中 | 柜次、装柜计划、拖车、PDA 任务 | 分柜、订舱、排车、拣货、照片、铅封、数量核对 | 主链已有 | 核对真实柜号、订舱和装柜快照能否冻结 | | F21 | 国内已装柜 | 装柜计划、物理货柜、装柜证据 | 实际柜号、实装箱数、装柜证据、`LOADED` | 已有 | 报关案例按最终实装范围建立;部分装柜只显示已装箱数并标记线下处理,不在系统内自动分摊 | -| F22.1 | 报关确认中 | 客户报关案例 | 每客户案例、客户范围、入仓码范围、实装箱数显示 | 缺失 | 新增客户级案例和柜内覆盖信息;部分装柜显示箱数并交线下处理 | -| F22.2 | 待提交资料、待补资料 | 客户资料包 | 上传、替换、补充、资料类型、版本、提交时间 | 部分已有 | 当前任意文件模型需补类型化清单和补件原因 | -| F22.3 | 已发送报关行 | 报关行发送批次 | 发送范围、文件快照、发送人、发送时间、报关行 | 缺失 | 新增发送批次及幂等历史 | -| F22.4 | 待客户确认 | 回执轮次 | 报关行回执、回执版本、返回时间、关联客户案例 | 缺失 | 新增每客户/每轮回执对象 | -| F22.5 | 客户确认中、已打回 | 客户确认记录 | 确认/打回、成员、时间、原因、当前轮次 | 缺失 | 客户端新增确认与打回,打回只重开当前客户 | -| F22.6 | 等待整柜确认 | 柜级申报批次 | 所有客户案例确认完成的门禁快照 | 缺失 | 未全部确认不得进入整柜正式提交 | -| F22.7 | 已提交正式申报 | 整柜正式申报 | 提交报关行确认、正式申报时间、操作人、批次 | 缺失 | 不能用旧 `start` 直接代替正式申报 | -| F22.8 | 查验中、待补资料、已放行、扣货/其他 | 海关结果事实 | 报关单号、结果类型、时间、凭证、处理结果 | 缺失 | 查验、不查验放行、扣货和其他结果分开记录 | -| F23.1 | 送港中、已离仓 | 送港/出仓任务 | 离仓时间、车辆/任务、操作人、证据 | 已有对象 | 报关确认不能成为送港前置 | +| F22.1 | 报关确认中 | 柜级报关聚合内的客户资料范围 | 每客户范围、入仓码范围、混合柜隔离、实装范围回显 | 已实现并通过真实 HTTP 验收 | 独立“案例”对象仍可在正式批次设计时补充;部分装柜仍线下处理 | +| F22.2 | 待提交资料、待补资料 | 客户资料包 | 上传、替换、关联范围、版本、冻结 | 已实现并通过真实 HTTP 验收 | 资料类型化清单和补件原因待补 | +| F22.3 | 已发送报关行 | 独立首次发送批次 `brokerSubmission` | 业务批次号、发送人、发送时间、冻结版本、资料快照、幂等历史 | 已实现并通过定向测试与测试环境部署 | 报关行接收确认和回执轮次对象待补 | +| F22.4 | 待客户确认 | 回执/完成文件版本 | 文件版本、关联客户范围、客户可下载 | 已实现;回执历史和确认动作历史均只读投影 | 独立回执返回时间/下载凭证仍待补 | +| F22.5 | 客户确认中、已打回 | 客户确认记录与动作历史 | 确认/打回、回执版本、操作人、时间、原因 | 已实现并通过定向测试与测试环境部署 | 通知聚合和报关行回执轮次待补 | +| F22.6 | 等待整柜确认 | 完税文件齐全门禁 | 所有退税客户确认、发送执行、真实完税文件齐全 | 已实现并通过专项真实 HTTP 验收 | 复杂结果凭证和补资料专项门禁待补 | +| F22.7 | 已提交正式申报 | 正式申报批次 | 报关行确认、正式申报时间、操作人、批次、报关单号 | 已实现并通过真实 HTTP 7 步联调 | 后续补更复杂的结果凭证类型 | +| F22.8 | 查验中、待补资料、已放行、扣货/其他 | 海关结果事实 | 报关单号、结果类型、时间、凭证、处理结果 | 已实现并通过真实 HTTP 7 步联调 | 后续补查验/扣货/补资料专项场景的更细验收 | +| F23.1 | 待发区、送港中、已离仓 | 待发区与送港/出仓任务 | 报关完成时间、待发区门禁、离仓时间、车辆/任务、操作人、证据 | 已实现并通过真实 HTTP 验收 | 继续补待发区客户/平台投影展示 | | F23.2 | 已送港、已进港 | 运输和港口事实 | 送港时间、进港时间、来源和凭证 | 部分已有 | 与订舱、拖车和船次事实统一读写 | -| F23.3 | 已甩柜、改配中、待下一航次 | 异常/改配记录 | 甩柜原因、发生时间、原航次、新航次、处理人 | 部分已有 | 需要独立历史,不能覆盖原进港事实 | +| F23.3 | 已甩柜、等待改船后承运 | 船期记录修改历史 | 甩柜原因、发生时间、修改前后船名/航次/船期、处理人 | 已实现并通过测试环境真实 HTTP;平台与客户端最新船期投影一致 | 继续补页面截图和更复杂异常分支;柜次、订舱关联和报关事实不变 | | F24 | 海运中 | 船次实际节点 | 承运船舶、航次、实际开航时间、来源/凭证 | 基础已有 | 只允许实际开航事实推进海运节点 | ## 三、当前实现与目标的主要断点 -### 1. 报关数据模型仍是旧柜级模型 +### 1. 报关数据模型已支持客户范围,发送批次仍需独立建模 -当前 `fl_customs_container` 只有 `WAITING_CUSTOMER_DOCUMENTS`、`READY_TO_START`、`DECLARING`、`COMPLETED` 四个状态;客户资料根记录挂在柜级报关聚合下,不能表达“同柜多个客户各自有独立案例和轮次”。 +当前 `fl_customs_container` 仍是柜级状态聚合,但客户资料通过客户和入仓码范围隔离,真实验收已覆盖同柜多客户和混合柜。正式申报批次、海关结果事实、首次发送报关行批次和客户确认动作历史已经独立落地;尚未独立建模的是报关行接收回执、回执轮次和更细的客户案例聚合。 目标至少需要以下关系: @@ -54,54 +54,46 @@ LOADED 后并行 ├─ 客户报关案例 × N │ ├─ 客户资料包与版本 │ ├─ 报关行回执轮次 × N - │ └─ 客户确认/打回记录 × N + │ └─ 客户确认/打回记录与动作历史 × N ├─ 整柜正式申报批次 └─ 海关结果事实 × N ``` -### 2. 当前“报关完成”含义过宽 +### 2. 当前“报关完成”仍需与正式申报、海关结果区分 -现有完成动作是平台上传每份完成文件,或对全买单柜直接确认;这不能继续作为客户确认、正式申报、海关放行和可离仓的统一含义。状态需要按客户案例、整柜申报和海关结果分别投影。 +现有完成动作是平台上传每份完成文件,或对全买单柜直接确认;客户确认和完成文件链路已有真实验收。正式申报批次、报关单号和海关结果已经分别记录,仍不能把其中任何一个状态直接当成海关放行或所有运输事实。 -### 3. 报关线与送港线的门禁关系需要调整 +### 3. 报关完成与待发区的门禁关系 -当前 `CustomsDispatchGateContributor` 要求 `fl_customs_container.status=COMPLETED` 才通过国内出仓门禁,`CustomsAutoDispatchCoordinator` 也在报关完成后自动尝试离仓。这与冻结口径冲突:报关资料未确认只能阻断报关线正式提交,不能阻断送港线。 +当前 `CustomsDispatchGateContributor` 要求 `fl_customs_container.status=COMPLETED` 才通过国内出仓门禁,`CustomsAutoDispatchCoordinator` 也在报关完成后自动尝试确认出仓。按最新口径,这不是冲突:报关完成后货柜进入待发区,待发区是送港运输真正开始前的状态门槛;甩柜只在船期运输层处理,不触碰报关事实。 需要重新定义: -- 送港/离仓门禁只检查装柜、PDA、订舱、证据和其他已确认的运输条件。 -- 报关线单独检查客户案例确认、整柜申报和海关结果。 -- 报关完成事件不能自动伪造送港或开船事实。 +- 待发区门禁先检查报关 `COMPLETED`,再叠加装柜、PDA、订舱、证据等运输条件;通过后只推进到 `WAITING_FOR_LOADING`。 +- 报关线单独保存客户确认、整柜申报和海关结果;这些事实不会被船期修改覆盖。 +- 报关完成事件只能推进待发区,不得自动伪造送港、进港或开船事实。 - 实际开航只能由船次实际节点推进。 -### 4. 客户端缺少报关协同闭环 +### 4. 客户端基础报关协同闭环已完成 -当前客户端 `CustomsDocumentsDialog.vue` 只能上传、替换、调整关联入仓码和下载完成文件,缺少: +当前客户端 `CustomsDocumentsView.vue` 提供独立报关资料列表和待办入口,`CustomsDocumentsDialog.vue` 已支持上传、替换、调整关联入仓码、查看和下载报关行回执/真实报关完税文件、确认整份回执和填写原因打回,并展示回执历次上传版本及确认/打回动作历史;仍缺少: -- 独立报关资料列表和待办数; -- 报关行回执查看; -- 当前轮次确认; -- 打回原因和重新提交; - 客户案例的进度和通知。 -### 5. 平台端缺少整柜协同闭环 +### 5. 平台端基础整柜协同闭环已完成 -当前 `ContainerCustomsPanel.vue` 主要展示缺资料清单、冻结资料和完成文件,缺少: +当前 `ContainerCustomsPanel.vue` 已展示退税资料、首次发送报关行批次、回执/完成文件、客户范围、确认状态、回执历次上传版本和确认/打回动作历史,并支持正式申报批次和海关结果基础操作;仍缺少: - 按客户查看案例和实际装柜覆盖; -- 发送报关行批次; -- 回执轮次管理; -- 客户确认汇总; -- 全部客户确认后的整柜正式提交; -- 报关单号和海关结果录入; -- 查验、扣货、补资料和其他结果的历史。 +- 报关行接收回执和回执轮次管理; +- 更细的查验、扣货、补资料和其他结果凭证历史。 ## 四、接口、权限、审计和测试缺口 ### 接口与数据库 - OpenAPI 不能继续只暴露旧的四态 `ContainerView`。 -- 需要新增客户案例、资料包、发送批次、回执轮次、确认记录、整柜申报和海关结果的查询/命令契约。 +- 需要继续补充报关行接收回执、回执轮次、下载凭证及更复杂结果凭证的查询/命令契约;资料包、首次发送批次、回执版本和确认动作只读历史、整柜申报和海关结果基础契约已落地。 - 文件仍由 File 服务保存,但每个文件必须绑定业务类型、客户案例/申报批次、版本和覆盖范围。 - 每个写命令都要带版本和幂等键;重放同参数返回原结果,不同参数返回冲突。 - 换柜时需要保留新旧柜关联;部分装柜只记录已装箱数和线下处理标记,不在系统内自动做数量分摊或覆盖旧资料。 @@ -129,8 +121,8 @@ LOADED 后并行 3. 同一请求重放、同幂等键换参数、版本冲突。 4. 未全部客户确认时正式提交被拒绝。 5. 正式申报、查验、不查验放行、扣货和其他结果分别显示。 -6. 报关线未完成时送港仍可按运输门禁继续。 -7. 甩柜改配保留原航次事实并生成新航次关联。 +6. 报关完成后货柜进入待发区,等待船舶承运。 +7. 甩柜改配在原柜上人工修改船信息并留痕,柜子和报关事实不变。 8. 只有实际开航事实推进 F24。 9. 客户越权读取同柜其他客户资料被拒绝。 10. 部分装柜能显示实际箱数并留下线下处理标记;换柜不能直接覆盖原案例和历史回执。 @@ -148,17 +140,34 @@ LOADED 后并行 | 回执与客户确认 | 首期以报关行回执文件为主,客户对整份回执确认;回执上传不等于客户确认 | 本轮业务确认 | | 资料与部分装柜 | 报关资料、报关行回执都按文件保存;部分装柜只展示箱数,线下人员处理后续,不做系统内数量分摊 | 本轮业务确认 | | 首期正式申报 | 由平台授权人员人工提交并回填报关行确认和海关结果 | 本轮业务确认;报关专题状态约定 | -| 报关与送港关系 | `LOADED` 后两条线并行,报关确认、正式申报和海关结果不作为送港前置 | 交接清单“二、必须保持的并行关系”;总流程“四、关键节点” | -| 海运起点与改配 | 首期人工录入实际开航;甩柜/改配生成新航次,并重新评估关联申报批次;只有实际开航事实推进 F24 | 本轮业务确认;交接清单第二条;总流程 F23/F24 | +| 报关与待发区关系 | 报关完成后货柜才能进入待发区;待发区是等待船舶承运的运输状态,报关和船期事实分开保存 | 本轮业务确认 | +| 海运起点与改配 | 首期人工录入实际开航;甩柜/改配只变更船期/航次,不重新处理已完成报关资料;只有实际开航事实推进 F24 | 本轮业务确认;交接清单第二条;总流程 F23/F24 | + +### 本轮补充确认的甩柜/改配口径 + +| 项目 | 已确认口径 | +|---|---| +| 发起与确认 | 平台人员直接编辑原柜船期,记录操作人、时间、原因和修改前后船信息。 | +| 资料继承 | 报关完成后资料、平台回执和客户确认与船期独立;甩柜/改配不触发重新上传或重新确认。 | +| 航次任务 | 平台人工修改原柜船信息,继续使用原任务;保留修改历史和已有节点。 | ### 仍需补充的字段和操作规则 1. 首版资料清单具体项目、条件规则、版本生效方式和责任人是什么? +2. (已确认)第一版由平台人员直接修改原柜船名、航次和船期,填写原因并保留修改历史。 +3. (已确认)平台人工修改原柜船名、航次和船期;柜子与原任务不变。 +4. (已确认)原航次退税资料、回执和客户确认与船期独立,甩柜/改配不触发重新确认。 +5. (已确认)甩柜/改配与报关资料无关,不重新生成报关批次,不要求客户重新确认。 +6. 修改船信息不生成实际开航事实;只有本柜实际随船开航后才记录 `DEPARTED_ORIGIN_PORT`。 + +### 代码接入前置缺口 + +最新确认取消新增航次对象和重建任务的方案。复用现有船期编辑及修改历史,柜次、订舱关联和查询任务保持不变。测试环境已核验平台与客户端都会投影修改后的最新船期,报关资料、回执、完成文件和客户确认保持不变;证据见 `baiyue-firstleg/reports/platform-and-client-transport-projection-20260927.json`。 ## 六、冻结结论 - 第一阶段覆盖 F01-F24,终点为实际开航。 -- F22 报关协同和 F23 送港运输从 `LOADED` 后并行启动。 +- F22 报关完成后货柜进入 F23 待发区;甩柜/改配只改变运输航次,不改变报关事实。 - 客户确认、报关行回执、整柜正式申报、海关放行、离仓、进港、甩柜和实际开航都是独立事实。 - 先完成节点矩阵、对象关系、状态投影、门禁和验收缺口确认,再进入代码设计。 - 尾程 F25-F40 暂不纳入本阶段实现,但必须保留 F24 到目的港清关的接口衔接点。 diff --git a/头程到尾程/头程节点与报关清关交互矩阵.md b/头程到尾程/头程节点与报关清关交互矩阵.md new file mode 100644 index 0000000..e4946b1 --- /dev/null +++ b/头程到尾程/头程节点与报关清关交互矩阵.md @@ -0,0 +1,78 @@ +# 头程节点与报关清关交互矩阵 + +> 本文把头程下单 F01-F24 与报关清关的客户、平台、报关行交互放在同一张图里。当前产品先覆盖国内头程到实际开航;尾程不在本轮。报关资料只适用于包含退税货物的柜,买单货物不创建客户资料协同。 + +## 一、总链路 + +```text +客户下单/入仓 + → 收货、测量、计费、费用确认 + → 分柜、订舱、拖车、PDA 装柜 + → LOADED(物理事实) + → 客户上传报关资料 + → 平台冻结资料并首次发送报关行(生成独立批次) + → 报关行回执 + → 客户确认整份回执/打回 + → 平台把客户确认后的回执发送报关行执行 + → 报关行完成 + → 平台上传真实报关完税文件 + → 报关完成 + → 待发区、送港、进港 + → 甩柜/改配只修改原柜船期 + → 实际开航 +``` + +`LOADED` 是 PDA 产生的装柜事实,也是当前客户报关详情的准入条件;PDA 不参与资料、回执、确认或完税文件接口。报关完成是待发区的门禁,实际开航只由船次实际事实推进。 + +## 二、F01-F21:报关前的头程节点 + +| 节点 | 客户动作 | 平台动作 | PDA/运输动作 | 报关影响 | +|---|---|---|---|---| +| F01-F07 下单、审核、补件 | 提交订单、补充订单信息 | 审核订单、生成入仓单 | 无 | 仅确定客户、订单和退税/买单属性;不创建报关资料 | +| F08-F10 到仓、收货、测量 | 查看入仓进度 | 收货、扫码、称重、测量并审核 | 仓内作业 | 形成后续实装范围的来源数据 | +| F11-F13 计费、费用确认、组托、待分柜 | 查看/确认费用 | 发布费用版本、记录确认、组托封托 | 无 | 费用确认不能代替报关资料确认 | +| F14-F20 分柜、订舱、拖车、拣货、装柜中 | 查看柜次和船期 | 建立柜次、订舱、拖车和装柜计划 | PDA 领取、拣货、复核、装柜 | 仍不能启动客户报关资料入口 | +| F21 `LOADED` | 查看实际装箱数 | 固化实际柜号、实装箱数和装柜证据 | PDA 提交并产生 `LOADED` | 按最终实装范围建立退税客户报关资料范围 | + +部分装柜只回显实际箱数并留下线下处理标记,系统不自动分摊数量,也不覆盖原始资料范围。 + +## 三、F22:报关平台与客户交互 + +| 子节点 | 平台页面/接口 | 客户页面/接口 | 关键状态与门禁 | +|---|---|---|---| +| F22.1 建立资料范围 | Admin 查看柜级退税客户、入仓码和实装范围 | Client 只能看到自身订单范围 | 退税客户按租户和入仓码隔离;买单客户不建资料 | +| F22.2 客户上传资料 | `GET /api/platform/v1/customs/loading-plans/{planId}` 查看汇总 | `GET /api/merchant/v1/customs/orders/{orderId}`;`POST .../documents/upload`;可替换、调整入仓码范围 | 当前要求 `LOADED`;资料版本和幂等键受门禁控制 | +| F22.3 首次发送报关行 | Admin `POST .../{planId}/send-to-broker` | 只读看到批次和发送时间 | 资料全部冻结后生成独立 `brokerSubmission` 批次;未首次发送不能上传回执;只适用于含退税货物的柜 | +| F22.4 上传回执 | Admin `POST .../documents/{documentId}/receipt/upload` | `GET .../receipt/download` | 回执进入 `PENDING`;回执不是报关完成文件 | +| F22.5 客户确认/打回 | Admin 查看每客户回执状态 | `POST .../receipt/confirm` 或 `.../receipt/reject` | 确认整份回执;打回必须填写原因;版本冲突拒绝 | +| F22.6 回执冻结与执行 | Admin `POST .../{planId}/submit-to-broker` 再次发送客户确认后的回执 | Client 只能查看确认结果和动作历史 | 发送执行后回执不能替换;`brokerSubmittedAt` 仅表示发送执行时间 | +| F22.7 正式申报与报关行完成 | Admin 创建/提交正式申报批次、回填报关单号,并上传真实报关完税文件:`POST .../final/upload` | `GET .../final/download`;只读批次投影 | 完税文件齐全后整柜状态才可 `COMPLETED`;正式申报批次和完税文件是两件事,不能把回执或客户确认当成正式申报 | +| F22.8 清关结果 | 平台人工补录查验、补资料、放行、扣货等独立事实;可处理未决结果 | 客户只读查看自身可见结果和凭证 | 已落地 `customs_declaration_batch`、`customs_clearance_result`;结果不推进待发区、船期或 PDA | + +当前客户端状态映射:`WAITING_UPLOAD` → `DOCUMENT_UPLOADED` → `DECLARING` → `CUSTOMS_COMPLETED`。平台柜级状态映射:`WAITING_CUSTOMER_DOCUMENTS` → `READY_TO_START` → `DECLARING` → `COMPLETED`。`COMPLETED` 仍需继续与正式申报、海关放行和运输节点拆开。 + +## 四、F23-F24:报关完成后的运输交互 + +| 节点 | 平台动作 | 客户可见内容 | 报关资料处理 | +|---|---|---|---| +| F23.1 待发区、送港、离仓 | 报关完成后通过待发区门禁,记录送港/离仓事实 | 查看待发、送港状态和当前船期 | 资料、回执、完税文件只读保留 | +| F23.2 进港 | 记录进港时间、来源和凭证 | 查看进港节点 | 不改变报关状态 | +| F23.3 甩柜/改配 | 平台人员编辑原柜船名、航次、预计时间并记录前后值、原因、操作人 | 查看修改后的当前船期和历史 | 柜号、订舱关联、资料、回执、客户确认和完税文件不变,不重新确认 | +| F24 实际开航 | 人工录入承运船舶实际开航事实 | 查看海运已开航 | 只记录关联关系,不重做报关 | + +甩柜只改变运输信息,不生成新柜、不重建报关任务、不把预计船期修改误写成实际开航。 + +## 五、当前接口覆盖与待补项 + +已落地并部署的基础闭环:客户资料上传/替换/范围调整、平台查看、冻结资料首次发送报关行并生成独立批次、回执上传及历次版本只读投影、客户整份回执确认/打回及动作历史、平台发送报关行执行、真实完税文件上传/下载、退税与买单分流、版本和幂等门禁;当前平台与客户页面均读取最新预计船期字段,实际开航字段单独保留。 + +仍需补齐: + +1. 报关行接收确认、回执轮次和回执下载凭证的独立对象及更细历史投影。 +2. 待发区客户/平台投影的更细页面展示和截图证据;`LOADED → 报关 → 待发区` 已在既有混合柜报告中通过,平台与客户改船后的当前船期双端回读已验收。 + +正式申报批次和海关结果已在本轮实现并通过真实 HTTP:平台创建/提交批次、录入查验、查询并处理结果,客户按自身订单查询结果;证据见 `baiyue-firstleg/reports/formal-customs-declaration-and-clearance-result-20260927.json`。 + +报关专项真实 HTTP 证据、构建号和当前 PDA 边界见[报关代码开发交接清单](报关代码开发交接清单.md)、`baiyue-firstleg/reports/focused-customs-flow-without-pda-20260927.json`、`baiyue-firstleg/reports/customs-mixed-20260927i.json` 及 `baiyue-firstleg/reports/customs-prep-container-20260926.json`。专项证据验证客户确认回执、发送报关行、上传完税文件和客户回读 `COMPLETED`,没有调用 PDA;新建混合柜全链路报告已通过 532/532。 + +F22.7/F22.8 的独立批次、报关单号和海关结果设计见[正式申报与海关结果接入设计](正式申报与海关结果接入设计.md);该设计不改变现有两份文件闭环,也不把结果事实写入船期或 PDA 状态。 diff --git a/头程到尾程/报关代码开发交接清单.md b/头程到尾程/报关代码开发交接清单.md index 062e2ad..22c68a5 100644 --- a/头程到尾程/报关代码开发交接清单.md +++ b/头程到尾程/报关代码开发交接清单.md @@ -1,28 +1,31 @@ # 报关代码开发交接清单 -> **当前状态:流程已确认,报关协同代码进入第一批开发。** 本文是开发交接入口,已落地内容不代表完整报关协同或真实验收通过。第一阶段冻结范围和缺口以[头程至实际开船节点冻结矩阵与缺口清单](头程至实际开船节点冻结矩阵与缺口清单.md)为准;流程规则以[报关资料与船期价格接入梳理](../国内货柜履约/报关资料与船期价格接入梳理.md)为准,节点关系以[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准。 +> **当前状态:第一阶段报关协同已接入测试环境。** 客户资料、首次发送报关行批次、回执、客户确认历史和真实完税文件已形成独立链路;报关行确认回执和更复杂结果凭证仍是后续补充项。第一阶段冻结范围和缺口以[头程至实际开船节点冻结矩阵与缺口清单](头程至实际开船节点冻结矩阵与缺口清单.md)为准;流程规则以[报关资料与船期价格接入梳理](../国内货柜履约/报关资料与船期价格接入梳理.md)为准,节点关系以[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准。 -> **本轮补充确认:** 首期报关行回执以文件为主,客户确认整份回执;正式申报由平台授权人员人工提交并回填结果;实际开航首期人工录入,甩柜/改配生成新航次并重新评估关联申报批次。 +> **本轮补充确认:** 首期报关行回执以文件为主,客户确认整份回执;正式申报由平台授权人员人工提交并回填结果;报关完成后货柜进入待发区;实际开航首期人工录入,甩柜/改配只变更船期,不重新处理已完成报关资料。 + +> **验收证据:** 既有全链路报告保留旧版 526/526、混合柜 532/532 记录;本轮新增代码、数据库和三端已部署,已用现有完成柜做接口烟测并核对首次发送门禁。完整造数到报关回归仍需要测试环境提供 PDA 作业员账号,当前 `test-acceptance.env` 缺少该变量,脚本按契约在装柜前置处停止。 ## 一、必须实现的报关流程 从装柜完成(`LOADED`)开始,按柜内客户分别处理: 1. 按最终实装清单建立客户报关案例和资料包。 -2. 收集客户上传、替换或补充的资料,发送给报关行。 +2. 收集客户上传、替换或补充的资料,冻结后由平台生成独立批次首次发送给报关行。 3. 接收报关行回执并发给对应客户确认。 -4. 客户打回时,只重开对应客户当前轮次,重新上传、重新发送并生成新回执;保留每轮资料、回执、确认人、时间和打回原因。 -5. 柜内所有客户确认后,提交整柜资料给报关行确认,由报关行正式申报。 -6. 分别记录海关查验、不查验放行、扣货或其他正式结果。 +4. 客户打回时,只重开对应客户当前轮次,重新上传、重新发送并生成新回执;保留每轮资料、回执、确认人、时间、动作历史和打回原因。 +5. 柜内所有客户确认后,平台发送客户确认后的回执给报关行执行。 +6. 报关行执行完成后,平台上传真实报关完税文件;全部退税资料对应的完税文件齐全后,整柜报关完成。 +7. 分别记录海关查验、不查验放行、扣货或其他正式结果。 报关行回执、客户确认、整柜正式申报和海关放行是不同节点。客户确认不能自动完成,费用的系统默认确认也不能代替报关资料确认。 -## 二、必须保持的并行关系 +## 二、报关完成与待发区关系 -- `LOADED` 之后,报关协同线和送港运输线分别启动,互不作为对方的前置。 -- 报关资料未确认只阻断报关线的整柜正式提交,不阻断送港。 -- 送港、进港、甩柜和改配独立留痕;只有承运船舶实际开航后才进入海运节点。 -- `LOADED` 只表示物理装柜完成,不表示报关完成、已放行或已开船。 +- `LOADED` 只表示物理装柜完成;报关资料、回执、客户确认和正式申报仍需独立完成。 +- 报关完成后,货柜才能进入待发区;待发区表示等待船舶承运,不表示已经开船。 +- 送港、进港、甩柜和改配是运输事实;甩柜只在原柜船期记录上人工修改船信息,不回退或重新处理已完成报关资料。 +- 只有承运船舶实际开航后,才推进 `DEPARTED_ORIGIN_PORT` 海运节点。 ## 三、当前代码交接重点 @@ -30,19 +33,49 @@ - 平台端和客户端都能展示当前视角的实际装箱数;部分装柜只展示箱数,后续由线下人员处理,系统不做数量分摊。 - 报关资料和报关行回执继续按文件上传、覆盖、版本和下载处理;页面文案已区分“回执”和“完成”,避免把上传回执误认为客户确认或正式申报。 +- 首次发送报关行单独记录 `brokerSubmission`(业务批次号、冻结资料版本、快照、操作人和时间);未完成首次发送时不能上传回执,也不能发送客户确认结果给报关行执行。 - 报关资料链路仅适用于退税货物;买单货物不创建客户报关资料、回执和客户确认流程。 -- 回执上传后进入待确认状态;客户端已提供整份回执确认和打回入口,打回原因回传后再由平台重新上传回执。 +- 回执上传后进入待确认状态;客户端已提供整份回执确认和打回入口,平台与客户端都展示每个回执版本的确认/打回历史,打回原因回传后再由平台重新上传回执。 - 后端 OpenAPI、平台/客户端模型和基础测试已同步实际箱数字段;管理员端、客户端类型检查及相关组件测试已通过。 -这批能力支撑 F21 的实装范围展示和退税客户 F22 的文件承载、回执确认入口;客户案例、回执轮次、整柜正式申报和海关结果仍未完成。 +旧版资料与回执基础链路已通过测试环境真实 HTTP 验收;两份文件新流程已通过本地单测、契约测试和测试环境部署。报关闭环不依赖 PDA;真实 HTTP 验收应使用已经处于待发区的柜作为前置,不能因为装柜/PDA 前置失败而把报关结论判为失败。 -当前实现仍是旧的柜级报关状态和离仓门禁,不能直接证明已经具备以下能力: +### 报关与 PDA、船期的边界 -- 每客户报关案例和实际装柜快照; -- 报关行回执轮次和客户确认/打回重做; -- 柜内所有客户确认后的整柜正式提交; -- 查验、不查验放行和其他海关结果的独立记录; -- 报关线与送港线的独立状态、幂等、权限和审计。 +- PDA 只负责装柜现场作业,产出 `LOADED` 事实;本报关模块不创建、领取、认领或提交 PDA 任务。 +- 报关模块只消费已完成装柜且可进入待发区的柜。装柜链路可以作为系统级前置验收,但不属于报关两份文件闭环的验收内容。 +- 船期、价格、甩柜和改配属于运输模块。甩柜时只人工修改原柜的船名、航次和时间,柜号、报关资料、回执、客户确认和完税文件不变,也不重新创建报关任务。 + +### 本轮对 PDA 关系的落地说明(2026-09-26) + +- PDA 没有参与本轮代码修改,也没有被报关接口调用;客户资料、报关行回执、客户确认和真实报关完税文件仍由平台与客户/报关行接口独立处理。 +- 当前客户报关详情接口只对已完成装柜的订单开放,未达到 `LOADED` 时返回“订单尚未完成装柜”。因此 PDA 只是报关入口的上游准入事实,不是报关协同动作的一部分。 +- 若后续业务确认“装柜前就允许客户上传报关资料”,应单独调整 `LOADED` 准入门禁;不能通过在报关模块里偷偷创建或操作 PDA 任务解决。 +- 本轮测试已用真实 HTTP 建立退税柜、订舱和船期关联,并确认装柜计划仍为 `EDITING`、`readyForPda=false` 时不启动报关;证据见 `baiyue-firstleg/reports/customs-prep-container-20260926.json`。 + +### 本轮报关专项真实 HTTP 证据(2026-09-27) + +- 使用测试库中已完成装柜的退税计划 `loadingPlanId=2103494180160507905`,没有调用任何 PDA 接口。 +- 客户确认回执:HTTP 200、业务码 `200`,报关状态仍为 `DECLARING`。 +- 平台发送客户确认结果给报关行:HTTP 200、业务码 `200`,产生 `brokerSubmittedAt`,状态仍为 `DECLARING`。 +- 平台上传真实报关完税文件:HTTP 200、业务码 `200`;随后平台和客户查询均返回 `COMPLETED`,并可见完成文件。 +- 完整证据:`baiyue-firstleg/reports/focused-customs-flow-without-pda-20260927.json`。该证据证明两份文件报关协同闭环本身不依赖 PDA。 +- 早期全量验收报告 `customs-full-20260926h.json` 的失败项集中在 PDA 任务被分配给其他作业员,导致装柜链未进入 `LOADED`;修正验收作业员绑定并补齐 File 服务回执类型后,新的全链路报告 `customs-mixed-20260927i.json` 已通过 532/532,报关模块 223+47+23 项全部通过。 + +### 本轮部署证据 + +- 本轮 Firstleg 后端 `backend-java #652`、下游 `baiyue-firstleg-firstleg #455`、平台管理端 `admin-web-test #473`、客户端 `client-web-test #355` 均已成功部署到测试环境,健康检查为 `UP`。 +- 客户端报关资料定向测试 61/61 通过;报关服务单测、OpenAPI 契约测试和平台报关组件测试结果记录在本轮交接记录及对应构建产物中。 +- 正式申报/海关结果接入提交:Firstleg `ed692ee3`、路由合同修正 `95da66c7`、执行顺序修正 `4bec639a`,`backend-java #639/#640/#641` 成功;Admin `29cb0bd`、顺序修正 `855d8c0`,`admin-web-test #461/#462` 成功;Client `8c8fdbc`、`client-web-test #350` 成功。正式申报和结果真实 HTTP 7 步全部通过,证据见 `baiyue-firstleg/reports/formal-customs-declaration-and-clearance-result-20260927.json`。 +- 甩柜改配投影提交 `ac3acfce`、`f1218cef`,平台容器读模型修复提交 `2c4f1ea3`;当前分支的船期展示修复已由 `backend-java #649`、`baiyue-firstleg-firstleg #452` 和 `client-web-test #351` 成功部署。真实验证确认改船只更新原柜船期,平台与客户端同步最新船期,柜号和报关资料/回执/完成文件保持不变,证据见 `baiyue-firstleg/reports/platform-and-client-transport-projection-20260927.json`。 +- 回执历史投影提交 Firstleg `f6e70ea5`、Admin `ffe91a1`、Client `3e28478` 已成功部署:`backend-java #650`、`baiyue-firstleg-firstleg #453`、`admin-web-test #471`、`client-web-test #353`。健康检查为 `UP`,平台和客户真实接口均返回 `receiptHistory`;证据见 `baiyue-firstleg/reports/customs-receipt-history-20260928.json`。 +- 本轮首次发送批次与确认动作历史提交为 Firstleg `e63cb2b2`、Admin `730defa`、Client `8fd4063`;数据库已核对 `fl_customs_broker_submission` 与 `fl_customs_completion_action_history`。现有完成柜烟测返回 `A0409 当前柜不在报关中`,确认新首次发送接口的状态门禁;证据见 `baiyue-firstleg/reports/customs-send-batch-confirmation-history-20260928.json`。 + +当前仍需继续补齐的不是客户资料协同、正式申报和海关结果基础链路,而是: + +- 报关行回执的外部确认/接收回执、下载凭证和回执轮次的更细对象;首次发送批次与客户确认动作历史已经落地; +- 更复杂的结果凭证上传和补资料专项门禁; +- 将正式申报/海关结果继续扩展到待发区、送港、进港和实际开航的只读投影,保持运输线独立;F23.3 的船期投影已完成真实 HTTP 核验。 开发时不要只增加页面节点文案,也不要把旧的 `COMPLETED` 直接当成客户确认、正式申报或海关放行。 @@ -60,9 +93,10 @@ ## 五、完成条件 - 客户 A 与客户 B 的资料、回执和确认严格隔离。 -- 每个客户都能完成“资料上传 → 报关行回执 → 客户确认”,打回后产生新轮次且不覆盖历史。 -- 未全部确认时不能提交整柜正式报关;全部确认后才能进入报关行正式申报。 -- 海关查验、不查验放行、扣货和其他结果可分别记录并回显。 -- 报关线和送港线可以先后完成,任一线的完成事件不能伪造另一条线的节点。 +- 每个客户都能完成“资料上传 → 报关行回执 → 客户确认/打回”,资料和完成文件保留版本,客户范围严格隔离。 +- 首次发送报关行必须生成独立业务批次;客户每次确认或打回都保留对应回执版本、操作人、时间和原因。 +- 未全部客户确认时不能完成整柜报关;正式申报批次、海关回填结果和报关单号已独立建模,不能把客户确认或完税文件上传直接当作海关放行事实。 +- 海关查验、不查验放行、扣货和其他结果已落地为批次下独立事实;后续只需补更复杂的凭证上传和补资料专项验收。 +- 报关完成后才能进入待发区;进入待发区后才推进送港/进港。甩柜/改配只修改原柜船名、航次和船期并保留历史,不能伪造或覆盖报关资料、回执和客户确认。 - 重复请求、版本冲突、换柜、部分装柜箱数展示和权限越界都有明确结果和审计记录;部分装柜的后续处理在线下完成。 -- 完成代码联调后,再回写 F22 和阶段三的实现状态;真实验收通过前不要标记“报关完成”。 +- 完成代码联调后,再回写 F22 和阶段三的实现状态;当前真实 HTTP 已通过,后续仍按 `COMPLETED`、海关放行和运输节点分别验收。 diff --git a/头程到尾程/正式申报与海关结果接入设计.md b/头程到尾程/正式申报与海关结果接入设计.md new file mode 100644 index 0000000..2679177 --- /dev/null +++ b/头程到尾程/正式申报与海关结果接入设计.md @@ -0,0 +1,128 @@ +# 正式申报与海关结果接入设计 + +本文只补 F22.7、F22.8 的业务对象和交互边界,不改变已经验收的退税报关基础闭环:客户上传退税资料 → 平台发送报关行 → 报关行回执 → 客户确认或打回 → 平台发送确认结果给报关行 → 平台上传真实报关完税文件。 + +## 一、先冻结现有边界 + +```text +LOADED + ↓ +客户退税资料齐全 + ↓ 平台开始报关,冻结资料范围和版本 +DECLARING + ↓ 报关行回执 +客户确认整份回执 / 打回 + ↓ 平台发送客户确认结果给报关行 +等待真实报关完税文件 + ↓ 每个退税客户均有完成文件 +COMPLETED(平台已收到本轮完税文件) + ↓ +WAITING_FOR_LOADING(进入待发区) +``` + +`COMPLETED` 只表示平台收到本轮真实完税文件,不能解释为海关放行、正式申报成功或船舶已开航。正式申报批次可以在报关行执行后、完税文件回传前建立;PDA 只在上游产出 `LOADED`;待发区、送港、甩柜、改配和船舶实际开航属于运输线,不能由正式申报对象反向改写。 + +## 二、F22.7 正式申报批次 + +正式申报批次是平台授权人员人工提交后形成的独立事实,粒度为整柜一次申报批次。它引用当前柜级报关聚合和已冻结的客户资料/回执快照,不复制文件内容。 + +建议对象:`customs_declaration_batch` + +| 字段 | 说明 | +|---|---| +| `id` | 平台长 ID,前端按字符串传输 | +| `customsContainerId` / `loadingPlanId` | 绑定整柜报关聚合和装柜计划,创建后不可换柜 | +| `batchNo` | 平台生成的批次号,人工提交前为空或草稿号 | +| `status` | `READY`、`SUBMITTED`、`ACKNOWLEDGED`、`RESULT_PENDING`、`CLOSED`、`CANCELLED` | +| `sourceVersion` | 提交时整柜报关聚合版本,防止提交后资料范围漂移 | +| `receiptSnapshot` | 提交时客户资料、回执、确认结果的客户范围和文件版本快照 | +| `customsEntryNo` | 报关单号,平台人工回填;同一有效批次唯一 | +| `submittedBy/submittedAt` | 平台提交人和时间 | +| `acknowledgedBy/acknowledgedAt` | 报关行或平台确认受理人和时间 | +| `remark` | 提交说明,长度受服务端限制 | + +创建或提交门禁: + +1. 柜级报关已进入 `DECLARING`,且整柜退税资料已覆盖实际装柜退税票;批次也允许在完税文件上传后的 `COMPLETED` 阶段补建。 +2. 所有退税客户的当前回执均为 `CONFIRMED`。 +3. 已执行发送动作,`brokerSubmittedAt` 已存在。 +4. 提交使用版本号和幂等键;相同请求重放返回同一批次,不同载荷返回冲突。 +5. 提交后禁止修改客户资料范围、回执和确认结果;补资料必须通过新批次或明确的退回重提动作产生新版本,不能覆盖历史批次。 + +建议平台接口: + +- `GET /api/platform/v1/customs/loading-plans/{planId}/declaration-batches` +- `POST /api/platform/v1/customs/loading-plans/{planId}/declaration-batches` +- `POST /api/platform/v1/customs/loading-plans/declaration-batches/{batchId}/submit` +- 提交时在请求体回填 `customsEntryNo`,不另设独立改单接口。 + +客户端只读当前批次的可见投影,不提供提交和修改入口;客户只能看到自己资料覆盖的结果。 + +## 三、F22.8 海关结果事实 + +海关结果不是柜级状态字段,而是批次下的不可变事实记录。一次正式申报可以先产生“待结果”,之后根据实际回执追加查验、补资料、放行、扣货或其他结果;修正不能覆盖历史记录。 + +建议对象:`customs_clearance_result` + +| 字段 | 说明 | +|---|---| +| `id` | 结果事实长 ID | +| `declarationBatchId` | 所属正式申报批次 | +| `resultType` | `INSPECTION`、`SUPPLEMENT_REQUIRED`、`RELEASED`、`DETAINED`、`OTHER` | +| `resultStatus` | `OPEN`、`RESOLVED`、`CANCELLED` | +| `customsEntryNo` | 报关单号快照,必须与批次一致 | +| `occurredAt` | 海关事实发生时间 | +| `recordedAt/recordedBy` | 平台录入时间和操作人 | +| `resolution` | 处理结果、补资料说明或扣货原因 | +| `evidenceFileId` | 可选结果凭证,文件由 File 保存,归属由 Firstleg 校验 | +| `previousResultId` | 更正或追加结果的前序事实,不能原地覆盖 | + +结果门禁: + +- `INSPECTION` 和 `SUPPLEMENT_REQUIRED` 未解决时,客户看到处理中/待补资料,平台不能显示放行。 +- `RELEASED` 只表示海关放行事实,不自动写入送港、进港或实际开航。 +- `DETAINED` 进入扣货/异常处理,保留原因和凭证,不自动删除报关文件。 +- `OTHER` 必须有说明,不能用空状态吞掉未知海关结果。 +- 只有平台授权人员可以新增或更正结果;客户只能读取自身可见的结果和凭证。 + +建议平台接口: + +- `GET /api/platform/v1/customs/loading-plans/declaration-batches/{batchId}/results` +- `POST /api/platform/v1/customs/loading-plans/declaration-batches/{batchId}/results` +- `POST /api/platform/v1/customs/loading-plans/clearance-results/{resultId}/resolve` +- `GET /api/merchant/v1/customs/orders/{orderId}/clearance-results` + +## 四、三端交互 + +| 参与方 | 可以做什么 | 不可以做什么 | +|---|---|---| +| 客户 | 上传/替换自身退税资料;查看并确认或打回整份回执;查看自身批次、报关单号、海关结果和凭证 | 不能查看同柜其他客户;不能提交正式申报;不能录入放行/扣货 | +| 平台报关人员 | 核对资料和回执;发送报关行;创建/提交正式申报批次;回填报关单号;录入和解决海关结果 | 不能用客户确认代替正式申报;不能用完税文件代替放行结果 | +| 报关行 | 线下处理申报并返回回执、报关单号和海关结果文件 | 不直接调用客户接口;所有回执和结果由平台留痕上传 | +| PDA/运输 | PDA 产出 `LOADED`;运输处理待发区、送港、进港、甩柜、改配和实际开航 | 不创建报关批次,不修改报关结果,不因甩柜重置资料或确认 | + +## 五、状态投影 + +平台柜级状态继续保留当前四态,用新增投影补充信息: + +| 现有状态 | 新增投影 | 客户文案 | +|---|---|---| +| `WAITING_CUSTOMER_DOCUMENTS` | 无有效批次 | 待上传退税报关资料 | +| `READY_TO_START` | 可开始报关 | 资料已齐,等待平台发送报关行 | +| `DECLARING` | 回执确认中/已发送报关行/正式申报中 | 报关处理中 | +| `COMPLETED` | 完税文件齐全,正式申报或结果可能仍未关闭 | 报关文件已完成,等待海关结果(如有) | + +运输投影单独读取待发区和船期对象;甩柜只更新原柜船名、航次和时间历史,不变更批次、资料、回执、结果或客户确认。 + +## 六、最小验收矩阵 + +1. 未全部客户确认时创建/提交正式批次返回业务冲突,数据零漂移。 +2. 同一幂等键重放返回同一批次;换参数返回冲突。 +3. 提交后资料范围、回执和客户确认不可修改。 +4. 同一批次可追加查验、补资料、放行、扣货和其他结果,历史顺序稳定。 +5. 查验/补资料未解决时不显示放行;扣货保留原因和凭证。 +6. 客户 A 不能读取客户 B 的批次、结果和文件。 +7. 报关结果不推进送港、进港或实际开航;甩柜只改变原柜船期。 +8. 正式申报和结果事实可以在报关 `COMPLETED` 后继续存在,不能把 `COMPLETED` 直接当成 `RELEASED`。 + +本设计已完成代码接入:Firstleg 建立正式申报批次和海关结果表、版本/幂等/审计门禁及平台/客户接口;Admin 页面提供创建、提交、录入和处理入口,Client 页面展示本订单可见结果。真实 HTTP 证据见 `baiyue-firstleg/reports/formal-customs-declaration-and-clearance-result-20260927.json`。当前仍保持 `COMPLETED`、海关放行、待发区和实际开航的状态边界,PDA 与船期不参与结果对象。 diff --git a/头程到尾程/测试环境真实联调记录-20260925.md b/头程到尾程/测试环境真实联调记录-20260925.md new file mode 100644 index 0000000..1081dfa --- /dev/null +++ b/头程到尾程/测试环境真实联调记录-20260925.md @@ -0,0 +1,109 @@ +# 测试环境真实联调记录(2026-09-25) + +本记录只登记已经在测试环境真实调用得到的结果,不把本地单测或设计文档当作真实验收证据。环境配置来自本机受控配置目录,不在文档中记录密码、Token 或 Jenkins 凭据。 + +## 一、本批部署 + +| 部署单元 | 测试构建 | 结果 | 说明 | +|---|---:|---|---| +| `backend-java` | 618 | 成功 | `firstleg` 选择构建;第 617 次因测试仍引用已删除旧方法失败,修正后第 618 次成功 | +| `admin-web-test` | 454 | 成功 | 平台回执上传不再携带 `finalConfirmation`,上传后等待客户确认 | +| `client-web-test` | 331 | 成功 | 客户端新增整份回执确认、打回和原因展示 | + +路由合同检查通过;后端报关服务定向测试和 Controller 合同测试通过,Admin 类型检查及报关组件测试通过,Client 类型检查通过。 + +## 二、真实接口证据 + +测试客户属于退税客户,使用已完成装柜的测试订单和柜次进行验证。测试库已补齐 `fl_customs_completion_document` 的客户确认字段,现有记录仅用于本次测试。 + +### 1. 客户查看退税报关资料 + +调用: + +```text +GET /api/merchant/v1/customs/orders/{orderId} +``` + +结果:`200`。客户只能看到自身资料,返回实际箱数 `40`、退税资料 `1` 份;部分装柜的系统展示只读箱数,不做数量拆分。 + +### 2. 平台查看柜级报关状态 + +调用: + +```text +GET /api/platform/v1/customs/loading-plans/{loadingPlanId} +``` + +结果:`200`。平台视角返回同一柜次实际箱数 `40`、退税资料覆盖数和回执状态;客户视角没有返回同柜其他客户资料。 + +### 3. 平台上传报关行回执 + +调用: + +```text +POST /api/platform/v1/customs/loading-plans/documents/{documentId}/completion/upload?expectedVersion=1 +``` + +结果:`200`,回执状态为 `PENDING`,文件版本变为 `2`。上传回执没有自动把柜次标记为报关完成。 + +### 4. 客户打回整份回执 + +调用: + +```text +POST /api/merchant/v1/customs/documents/{documentId}/receipt/reject +``` + +结果:`200`,回执状态为 `REJECTED`,打回原因被保存,柜次仍为 `DECLARING`。 + +### 5. 客户确认整份回执 + +调用: + +```text +POST /api/merchant/v1/customs/documents/{documentId}/receipt/confirm +``` + +结果:`200`,回执状态为 `CONFIRMED`;该柜唯一退税客户确认后,柜次变为 `COMPLETED`。相同幂等键重放仍返回同一完成结果。 + +### 6. 头程到报关真实 HTTP 回归 + +在补齐国内 PDA 测试作业员凭据后,使用 `scripts/admin-test-env-acceptance.mjs --modules phase3-container-customs` 重新执行依赖闭环,覆盖客户下单、审核、入库测量、分柜/订舱、预装、PDA 装柜、`LOADED`、退税资料上传、平台回执上传、客户回执确认、自动离仓及船期查询任务。 + +结果:报告 `baiyue-firstleg/reports/e2e-phase3-container-customs-20260925d.json`,`526/526` 断言通过,`0` 失败;其中混合柜验证确认回执后才进入 `COMPLETED`,自动离仓 `SYSTEM` 历史为 `1` 条,`OUTBOUND_CONFIRM` 船期查询任务为 `1` 条。验收脚本同步提交为 `8940c4bc`。 + +### 7. 送港、船期与实际开航真实 HTTP 回归 + +使用 `phase3-port-schedules,phase3-carrier-schedule-queries,phase3-outbound-dispatch` 执行送港和出仓链路,报告 `baiyue-firstleg/reports/e2e-phase3-transport-20260925.json`,`1024/1024` 通过;验证报关完成后国内离仓门禁、拖车自动完成、`OUTBOUND_CONFIRM` 任务唯一性及 `DEPARTED_WAREHOUSE` 事实。 + +随后使用 `phase4-carrier-pickup-ready` 执行船节点人工回填,报告 `baiyue-firstleg/reports/e2e-phase4-carrier-pickup-ready-20260925.json`,`1093/1093` 通过;节点按顺序推进到 `AT_ORIGIN_PORT`、`LOADED_ON_VESSEL`、`DEPARTED_ORIGIN_PORT`,并覆盖幂等重放、旧版本冲突、旧节点回写禁止和至 `PICKUP_READY` 的连续事实。 + +## 三、当前已确认的业务边界 + +- 报关资料、报关行回执和客户确认流程只适用于退税货物。 +- 买单货物不创建客户报关资料、回执和客户确认流程;买单装柜、导出和运输节点独立处理。 +- 报关资料和回执均为文件;回执状态单独保存,文件版本覆盖会重新进入待确认。 +- 部分装柜只展示实际箱数,后续由线下人员处理,系统不自动分摊数量。 +- `LOADED` 后先完成报关协同;报关完成后货柜进入待发区,等待船期承运。甩柜/改配只影响运输航次,不回退或重做报关资料、回执和客户确认。 + +## 四、F01-F24 验证状态 + +| 范围 | 当前证据 | 状态 | +|---|---|---| +| F01-F13 下单、审核、到仓、测量、计费、费用确认、组托 | 本批依赖闭环已通过真实 HTTP;仍需拆分逐节点证据和异常分支 | 主链路已验收 | +| F14-F21 分柜、订舱、拖车、拣货、装柜、`LOADED` | 本批依赖闭环已通过真实 HTTP,包含 PDA 领取、提交、审核和 `LOADED` 冻结 | 主链路已验收 | +| F22 退税报关资料、回执、客户确认 | 已完成真实平台/客户端闭环 | 本批已验收 | +| F23 送港、进港、甩柜、改配 | 送港/进港/出仓和船期查询主链路已通过真实 HTTP;已用测试环境真实柜次验证平台人工修改原柜船名/航次/预计时间,柜次、订舱关联和船期记录 ID 不变,修改历史新增 `UPDATE`;报关事实保持不变 | 主链路和原柜人工改船已验收;完整装柜依赖链仍需补 PDA 凭据后复跑 | +| F24 实际开航 | 已通过人工船节点回填验证 `DEPARTED_ORIGIN_PORT`,顺序、版本和旧节点冲突均通过 | 本批已验收 | +| F25 以后目的港清关、海外入仓、尾程 | 已有综合真实 HTTP 证据覆盖目的港节点、海外 PDA 收货、库存、排车、出库、派送和跨区回写;`admin-full-postdeploy-66c2651b.json` 相关模块失败数为 0 | 已有主链证据;仍需按具体柜次补最终业务签字和页面截图 | + +## 五、下一批开发入口 + +下一批聚焦 F23 的人工改船页面回读、客户侧船期投影和异常分支;当前已确认只变更原柜船期,柜次、订舱关联和报关事实均不被覆盖。尾程节点再按 F25 以后阶段推进。每批完成后继续追加真实 HTTP 证据。 + +## 六、2026-09-27 追加验证:F23.3 客户船期投影 + +- 后端提交 `f1218cef` 已由 `backend-java #643` 完整测试并部署,Firstleg 独立任务 `baiyue-firstleg-firstleg #446` 成功;随后提交 `2c4f1ea3` 由 `backend-java #645` 完整测试并部署,Firstleg 独立任务 `baiyue-firstleg-firstleg #448` 成功;当前分支追加船期展示修复后,`backend-java #647` 与 `baiyue-firstleg-firstleg #450` 也已成功。 +- 修复统一订单运输摘要仍读取订舱初始船名/航次的问题:现在按客户、订舱和柜次读取最新 `fl_port_schedule` 记录,采用窗口函数选取最新观测,保留柜次与报关对象独立性。 +- 对退税柜 `TSTU0152125` 实际执行“创建原柜改配船期 → 平台容器详情与客户订单同时查询 → 版本更新恢复原船信息”。平台和客户端均读到新船名、航次及预计时间;柜号不变,恢复后两端再次一致。本轮不涉及 PDA,PDA 仍只作为 `LOADED` 上游事实。 +- 详细请求结果和断言见 `baiyue-firstleg/reports/platform-and-client-transport-projection-20260927.json`;此前客户侧单独投影证据仍保留在 `transport-projection-after-schedule-update-20260927.json`。 diff --git a/头程到尾程/甩柜改配接入设计.md b/头程到尾程/甩柜改配接入设计.md new file mode 100644 index 0000000..7b74386 --- /dev/null +++ b/头程到尾程/甩柜改配接入设计.md @@ -0,0 +1,35 @@ +# 甩柜与改配接入设计(F23.3) + +## 最新确认 + +柜子不会变。平台人员在原柜子的船期信息上人工修改船名、航次和预计时间即可;保留修改前后内容、修改人和时间。报关资料、回执、完成文件和客户确认保持不变。 + +## 操作流程 + +1. 退税报关完成后进入待发区,等待船舶承运。 +2. 原船装满导致甩柜时,平台编辑该柜当前船期,填写实际安排的船名、航次和预计开船/到港时间。 +3. 保存后继续使用原柜次和原船期查询任务;保留已经发生的离仓、进港事实。 +4. 货柜实际随船开航后,再记录实际开航节点。修改预计船期本身不表示已经开船。 + +不新建柜子、订舱关联或航次变更审批对象,不重建船期任务,也不重新上传或确认报关资料。此前建议的 voyage-changes 接口和批次评估状态已取消。 + +## 现有接入入口与待验收项 + +现有平台船期页面 `PortSchedulesView.vue` 提供编辑船名、航次、预计开船和到港时间的入口;后端 `PortScheduleService.update` 保持客户、订舱和柜次归属不变,并保存版本和修改前后历史。优先复用该能力。 + +当前船期展示已改为读取同一客户、订舱和柜次下最新船期记录,不再固定读取订舱初始快照。平台人工改船后,客户端会同步显示最新船名、航次和预计时间。 + +## 验收要求 + +- 修改后柜次、柜号、装柜清单、订舱关联和船期查询任务不变。 +- 船名、航次和预计时间正确更新,平台与客户可见的当前船期一致。 +- 修改前后历史、操作人和时间可追溯,重复请求和版本冲突有明确结果。 +- 报关状态、资料、回执、完成文件、客户确认与修改前一致。 +- 已发生的物理节点不重置,预计时间调整不推进实际开航。 + +## 真实联调证据(2026-09-27) + +测试柜 `TSTU0152125`(`containerBookingId=2104006600809353218`)的退税报关计划 +`2104006600830324737` 已完成资料、回执确认和完税文件闭环。平台创建一次原柜船期改配记录后,客户端同一订单立即读到新船名、航次和预计时间;柜号、柜次不变,报关状态、退税客户数量、资料/回执/完成文件 ID 与版本均未变化。随后已用版本更新恢复原船信息,恢复后的客户端投影再次一致。完整证据见 +`baiyue-firstleg/reports/platform-and-client-transport-projection-20260927.json`(平台与客户端同时回读)以及 +`baiyue-firstleg/reports/transport-projection-after-schedule-update-20260927.json`。 diff --git a/头程到尾程分阶段流程/README.md b/头程到尾程分阶段流程/README.md index bda24f4..2bf4ac4 100644 --- a/头程到尾程分阶段流程/README.md +++ b/头程到尾程分阶段流程/README.md @@ -22,7 +22,7 @@ ## 跨段交接 - 阶段二完成后进入阶段三的分柜;费用确认是并行事项,不阻断排柜、拣货和装柜。 -- 阶段三的装柜完成(`LOADED`)后,报关协同和送港运输同时启动,谁先完成都保留真实事实。 +- 阶段三的装柜完成(`LOADED`)后先完成退税报关;报关完成后货柜进入待发区,再推进送港运输。甩柜/改配只影响船期,不改变已完成报关事实。 - 报关协同必须经过“客户资料 → 报关行回执 → 客户确认/打回重做”,柜内所有客户确认后才提交整柜资料并正式申报。 - 送港完成、进港或甩柜都不等于海运中;承运船舶实际开航后才进入阶段四的海运节点。 - 阶段四形成海外接柜输入后,阶段五负责实收、入库和库存,阶段六负责出库、派送、签收和异常回写。 diff --git a/头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md b/头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md index 04914c8..6a95534 100644 --- a/头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md +++ b/头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md @@ -2,8 +2,8 @@ > 对应全景流程:F14~F23。 > 阶段起点:入库单主状态为 `WAIT_SPLIT`,不存在有效 HOLD。 -> 阶段终点:装柜后完成送港线的仓库离开/进港事实,报关线保留客户确认、正式申报和海关结果;实际开船 `VESSEL_DEPARTED` 由阶段四承接。 -> 本阶段复用订单、入库单、柜次和装柜计划,不新建独立“出仓单”。`LOADED` 后报关线和送港线并行;费用确认是并行事实,装柜完成后对已装范围的当前有效费用版本执行系统默认确认。 +> 阶段终点:装柜后完成退税报关并进入待发区,再完成送港线的仓库离开/进港事实;实际开船 `VESSEL_DEPARTED` 由阶段四承接。 +> 本阶段复用订单、入库单、柜次和装柜计划,不新建独立“出仓单”。`LOADED` 后先推进报关协同,报关完成后进入待发区,再推进送港;费用确认是并行事实,装柜完成后对已装范围的当前有效费用版本执行系统默认确认。 ## 1. 阶段目标和边界 @@ -20,7 +20,7 @@ 9. `LOADED` 后通知报关行、客户资料收集、回执确认、整柜正式申报和海关结果; 10. 送港、进港、甩柜/改配、实际离仓和拖车费用归集。 -`LOADED` 表示货物已经完成实际装柜。此时同时触发报关线和送港线:报关线收集客户资料、发送报关行、处理回执和客户确认;送港线安排拖车、离仓和进港。两条线谁先到都保留各自事实,客户未确认不阻断送港,已进港不代表报关完成。容量不足时记录甩柜和改配船次;只有实际开船后才进入海运节点。国内 Admin/PDA 不得把订单推进到海外派送完成 `DELIVERED`。 +`LOADED` 表示货物已经完成实际装柜。此时先触发报关线:收集退税客户资料、发送报关行、处理回执和客户确认;报关完成后进入待发区,才允许推进拖车、离仓和进港。已进港不代表报关完成,容量不足时记录甩柜和改配船次;甩柜不影响已完成报关资料、回执和客户确认。只有实际开船后才进入海运节点。国内 Admin/PDA 不得把订单推进到海外派送完成 `DELIVERED`。 ## 2. 角色、终端和对象 @@ -269,7 +269,7 @@ PDA 点击“完成装柜”时,服务端重新校验: 3. 平台将资料发送给报关行,记录发送时间、资料版本和 `roundNo`; 4. 报关行返回本轮回执,平台保存文件和回执字段,并向对应客户展示确认任务。 -柜前可以存在资料准备或历史附件,但不创建本柜正式客户确认轮次,也不能显示“已通知报关”。客户资料缺失只形成报关线补件待办,不阻断送港线。 +柜前可以存在资料准备或历史附件,但不创建本柜正式客户确认轮次,也不能显示“已通知报关”。客户资料缺失形成报关补件待办,未完成报关不得进入待发区或推进送港。 ### 12.2 F22-B 报关行回执与客户确认循环 @@ -285,7 +285,7 @@ PDA 点击“完成装柜”时,服务端重新校验: 1. 平台检查所有客户案例均已确认,冻结本柜最终实装和资料版本,生成整柜正式申报批次; 2. 将整柜资料提交报关行确认,报关行完成正式申报;首版不做外部系统直连,保留人工提交和审计记录; 3. 海关结果独立记录为查验、免查验放行、补件/退回、扣货等,不把客户确认回执直接当成海关放行; -4. 报关线的任一结果都不覆盖送港线的离仓、进港、甩柜事实。送港线可以先到港,报关线也可以先完成客户确认或正式申报。 +4. 报关完成后进入待发区;报关事实不覆盖送港线的离仓、进港、甩柜事实。甩柜只改变运输船期,不回退报关资料、回执或客户确认。 ## 13. F23 送港、进港与甩柜 @@ -300,9 +300,9 @@ PDA 点击“完成装柜”时,服务端重新校验: - 订舱已 `RELEASED` 且分配当前柜次; - 五类证据与有效锁码文本完整; - 送港任务和当前船次分配完整; -- 报关客户确认或海关结果不作为仓库离开、送港和进港的前置。 +- 报关完成是进入待发区以及后续仓库离开、送港和进港的前置。 -订舱、拖车、仓库离开和港口进场属于送港线事实。报关线可以先完成客户确认或正式申报,也可以晚于进港;两条线各自展示阻断项。容量不足时记录 `ROLLED_OVER`,保存原船次、滚动次数、新船次、预计开船时间和客户通知。 +订舱、拖车、仓库离开和港口进场属于待发区之后的送港线事实。容量不足时记录 `ROLLED_OVER`,保存原船次、滚动次数、新船次、预计开船时间和客户通知;不重新生成报关批次或客户确认任务。 ### 13.2 自动与人工确认离仓 @@ -334,7 +334,7 @@ PDA 点击“完成装柜”时,服务端重新校验: | 订舱 | `DRAFT → RELEASED` | 补齐资料并放舱 | | 拖车 | 非终态 → `COMPLETED` | 所有要求柜次实际离仓后自动完成 | | 报关 | `WAITING_DOCUMENTS → SENT_TO_BROKER → RECEIPT_PENDING_CUSTOMER_CONFIRM → CUSTOMER_CONFIRMED / NEEDS_RESUBMIT → ALL_CUSTOMERS_CONFIRMED → FORMAL_SUBMITTED → INSPECTION/RELEASED` | 装柜后通知报关行;回执必须经对应客户确认,打回则新资料/新回执轮次 | -| 送港 | `PORT_DELIVERY_PENDING → DEPARTED_WAREHOUSE → IN_TRANSIT_TO_PORT → PORT_RECEIVED / ROLLED_OVER` | 独立安排拖车和进港;容量不足记录甩柜和改配,不等待报关客户确认 | +| 送港 | `WAITING_FOR_LOADING → PORT_DELIVERY_PENDING → DEPARTED_WAREHOUSE → IN_TRANSIT_TO_PORT → PORT_RECEIVED / ROLLED_OVER` | 报关完成后进入待发区,再安排拖车和进港;容量不足时在原柜船期上人工修改船信息并留痕 | | 海运 | `WAITING_SAILING → VESSEL_DEPARTED → IN_TRANSIT` | 只有承运船舶真实开航才进入海运节点 | 主状态只表达阶段结果。订舱、拖车、PDA、证据和报关保持关联子状态,页面应汇聚展示,但不能互相覆盖。 @@ -386,7 +386,7 @@ WAIT_SPLIT 入库单/已封托托盘 - [ ] 送港线已记录唯一国内离仓历史;如已进港,存在 `PORT_RECEIVED`,如甩柜,存在原船次/改配船次历史 - [ ] 客户全部确认后才允许整柜正式提交;正式申报后的查验/放行结果单独记录 - [ ] 船舶实际开航后才写入 `VESSEL_DEPARTED` 并启动海运节点查询 -- [ ] 跨区事件可幂等重试;送港线和报关线任一先完成都不覆盖另一条线 +- [ ] 跨区事件可幂等重试;甩柜/改配只新增船期事实,不覆盖报关资料、回执和客户确认 ## 17. 易用性与数据流评审问题 diff --git a/头程到尾程分阶段流程/阶段五-海外接柜库存与库内服务.md b/头程到尾程分阶段流程/阶段五-海外接柜库存与库内服务.md index 86e3bd6..a672950 100644 --- a/头程到尾程分阶段流程/阶段五-海外接柜库存与库内服务.md +++ b/头程到尾程分阶段流程/阶段五-海外接柜库存与库内服务.md @@ -345,6 +345,8 @@ PDA 扫描托盘后按服务端返回的 `palletVersion`、`positionVersion` 执 ## 12. 阶段完成判定 +测试环境综合证据 `baiyue-firstleg/reports/admin-full-postdeploy-66c2651b.json` 已覆盖海外 PDA、收货、库存、库内服务和 `phase5-overseas-fulfillment`;上述模块失败数均为 0。这里的清单继续保留为逐票验收条件,不能用综合报告替代具体柜次的业务核对。 + 主链完成必须满足: - [ ] 柜号由正确仓库操作员认领 diff --git a/头程到尾程分阶段流程/阶段六-海外排车出库派送与回写.md b/头程到尾程分阶段流程/阶段六-海外排车出库派送与回写.md index ae8ae78..d446d53 100644 --- a/头程到尾程分阶段流程/阶段六-海外排车出库派送与回写.md +++ b/头程到尾程分阶段流程/阶段六-海外排车出库派送与回写.md @@ -264,6 +264,8 @@ INBOUND_COMPLETED + 可用库存 ## 13. 全流程最终完成判定 +测试环境综合证据 `baiyue-firstleg/reports/admin-full-postdeploy-66c2651b.json` 已覆盖 `phase4-overseas-dispatch`、`phase5-terminal-drayage`、`phase5-overseas-fulfillment`、客户服务和跨区回写模块,相关模块失败数均为 0。清单仍按具体派送单保留,最终上线前需要用业务柜次逐项复核。 + - [ ] 排车候选来自真实、可用且未被其他业务占用的库存 - [ ] 草稿锁、正式锁和取消/完成释放均可追溯 - [ ] 排车路线由实际目的地生成 diff --git a/头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md b/头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md index da6d66a..58e40fd 100644 --- a/头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md +++ b/头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md @@ -329,6 +329,8 @@ Lastleg 消费步骤: ## 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`。 + - [ ] 国内离仓产生的船节点任务绑定真实订舱和柜次 - [ ] 节点预计/实际/观测时间没有混用 - [ ] 异常事实与正常节点分开保存 diff --git a/头程到尾程流程节点梳理.md b/头程到尾程流程节点梳理.md index 901b850..4a930eb 100644 --- a/头程到尾程流程节点梳理.md +++ b/头程到尾程流程节点梳理.md @@ -9,7 +9,7 @@ | 业务块 | 覆盖范围 | 对外主要进度 | 后台主要对象 | 分段详情 | |---|---|---|---|---| | **头程下单** | 客户下单、审核、国内到仓、测量、计费、确认、组托 | 待下单 → 审核中 → 待到仓/测量 → 待分柜 | 订单、入仓单、测量记录、费用记录、托盘 | [阶段一](头程到尾程分阶段流程/阶段一-客户准入与头程下单.md)、[阶段二](头程到尾程分阶段流程/阶段二-国内到仓测量计费与组托.md) | -| **海运(货柜)** | 分柜、订舱、拖车、拣货、装柜、报关协同、送港、进港、甩柜、实际开船、目的港和尾程计划 | 待分柜 → 装柜中 → 报关确认中/送港中 → 待开船 → 海运中 → 待入仓 | 柜次、装柜任务、报关批次、送港任务、船次、尾程入仓计划 | [阶段三](头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md)、[阶段四](头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md)、[报关专题](国内货柜履约/报关资料与船期价格接入梳理.md) | +| **海运(货柜)** | 分柜、订舱、拖车、拣货、装柜、报关协同、待发区、送港、进港、甩柜、实际开船、目的港和尾程计划 | 待分柜 → 装柜中 → 报关中 → 待发区 → 送港/待开船 → 海运中 → 待入仓 | 柜次、装柜任务、报关批次、待发区、送港任务、船次、尾程入仓计划 | [阶段三](头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md)、[阶段四](头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md)、[报关专题](国内货柜履约/报关资料与船期价格接入梳理.md) | | **尾程入库和派送** | 海外接柜、拆柜实收、入库、库存服务、排车、出库、派送、签收、异常回写 | 待接柜 → 入库中 → 待派送 → 出库/派送中 → 已签收/异常 | 接柜任务、入库单、库存、出库单、派送单、异常单 | [阶段五](头程到尾程分阶段流程/阶段五-海外接柜库存与库内服务.md)、[阶段六](头程到尾程分阶段流程/阶段六-海外排车出库派送与回写.md) | 三大块是客户和产品的展示分组;F01~F40 是后台查找和验收用的内部编号,不代表客户必须看到 40 个节点,也不代表所有动作严格串行。 @@ -22,9 +22,11 @@ ↓ 海运(货柜) 分柜/订舱/拖车 → 拣货 → 装柜完成(LOADED) - ├─ 报关协同:客户资料 → 报关行回执 → 客户确认/打回重做 → 全部客户通过 - │ → 整柜资料交报关行 → 正式申报 → 查验或不查验放行 - └─ 送港运输:离仓 → 送港 → 进港 → (容量不足时)甩柜/改配 + └─ 报关协同:客户资料 → 报关行回执 → 客户确认/打回重做 → 全部客户通过 + → 整柜资料交报关行 → 正式申报 → 查验或不查验放行 + ↓ 报关完成 + 进入待发区 + 送港运输:待发区 → 离仓 → 送港 → 进港 → (容量不足时)甩柜/改配 ↓ 船舶实际开航后进入海运节点 ↓ @@ -42,9 +44,9 @@ | F08-F10 | 头程下单 | 待到仓、测量中、待确认 | 入仓单、测量记录 | 到仓收货、扫码、称重、测量、审核 | 形成可排柜的实测数据 | | F11-F13 | 头程下单 | 费用待确认、待组托、待分柜 | 费用版本、确认记录、托盘 | 计费、推送、客户确认、组托/封托 | 费用不阻断主链;装柜完成时未确认的当前有效费用按系统默认确认留痕 | | F14-F20 | 海运(货柜) | 待分柜、订舱中、装柜准备/进行中 | 柜次、装柜计划、拖车任务、拣货任务 | 分柜、订舱、排车、拣货、拍照、铅封、数量核对 | 通过装柜门禁后才能完成装柜 | -| F21 | 海运(货柜) | 国内已装柜 | 装柜任务已完成 | 实际柜号、实装数量、装柜证据确认 | 产生 `LOADED`;同时启动报关协同和送港运输两条线 | +| F21 | 海运(货柜) | 国内已装柜 | 装柜任务已完成 | 实际柜号、实装数量、装柜证据确认 | 产生 `LOADED`;完成报关后才进入待发区 | | F22 | 海运(货柜) | 报关确认中、待补资料、已提交报关 | 客户报关案例、报关批次 | 收集资料、发报关行、接收回执、客户确认或打回、重新上传和重发 | **流程已确认、代码未完成**;柜内所有客户确认后,才能提交整柜资料并正式申报;客户确认不等于海关放行 | -| F23 | 海运(货柜) | 送港中、已进港、待开船、已甩柜 | 送港/拖车任务、港口和船次事实 | 离仓、送港、进港、甩柜、改配 | 与报关线独立,先后顺序不固定;进港不等于开船 | +| F23 | 海运(货柜) | 待发区、送港中、已进港、待开船、已甩柜 | 待发区、送港/拖车任务、港口和船次事实 | 报关完成后入待发区、离仓、送港、进港、甩柜、改配 | 报关完成是进入待发区的门槛;甩柜/改配只改变运输船期,不重做已完成报关 | | F24 | 海运(货柜) | 海运中 | 船次实际状态 | 承运船舶实际开航、船期回写 | 只有实际开航后进入海运节点 | | F25-F27 | 海运(货柜) | 目的港处理中、待海外接柜 | 目的港清关/提柜、尾程订单、入仓计划 | 清关、提柜、创建尾程计划 | 形成海外接柜输入,不等于已经入库 | | F28-F33 | 尾程入库和派送 | 待接柜、入库中、库存可用 | 接柜任务、入库单、库存 | 接柜、拆柜、收货核对、上架、盘点及库内服务 | 实收核平并入账后形成可用库存 | @@ -53,14 +55,14 @@ ## 四、必须保持的流程关系 -### 1. 装柜完成后是两条并行线 +### 1. 报关完成后进入待发区,船期单独推进 -`LOADED` 只表示货物已经实际装入集装箱并完成装柜记录。之后同时产生: +`LOADED` 只表示货物已经实际装入集装箱并完成装柜记录。之后先完成报关协同,报关完成后货物进入待发区: - **报关协同线**:通知报关行,按客户/入仓码收集资料;报关行生成回执后发客户确认。客户打回时,只重做对应客户的资料、发送和回执,直到柜内所有客户都确认。全部确认后,将整柜资料交报关行确认,再记录正式申报和海关结果。 -- **送港运输线**:安排拖车、离仓、送港和进港;船舱不足时记录甩柜和改配。送港可以早于或晚于报关协同完成。 +- **待发区与船期线**:报关完成后进入待发区,再安排离仓、送港和进港;船舱不足时记录甩柜和改配。甩柜/改配只人工修改原柜的船名、航次和船期,不影响已完成的报关资料、回执和客户确认。 -两条线互不作为对方的完成前置。报关行回执、客户确认、正式申报、海关放行、进港、甩柜和实际开船是不同事实,不能合并成一个“报关完成”或“海运中”。 +报关行回执、客户确认、正式申报、海关放行、进入待发区、进港、甩柜和实际开船是不同事实,不能合并成一个“报关完成”或“海运中”。 ### 2. 费用确认不阻断装柜主链