Files
docs/国内货柜履约/报关资料与船期价格接入梳理.md

181 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 报关资料与船期价格接入梳理
> **当前用途:报关与船期价格专题参考。** 报关流程已经确认,代码已进入第一批开发;开发交接看[报关代码开发交接清单](../头程到尾程/报关代码开发交接清单.md)。主流程和节点关系以[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准;本文保留资料字段、回执轮次、价格口径和接口查找信息。
>
> 文中“目标、实施顺序、进入条件、待确认事项”等段落属于原评审记录。开发已经完成后,不再据此重新拆开发任务;若与当前确认不一致,以总览和最新业务确认修正对应专题段落。
本文是企业客户端“报关资料”“船期价格”入口的专题评审记录。当前使用时只取已确认的流程、资料和价格口径;“建议”和“待确认”保留为历史评审痕迹,不再自动生成开发任务或验收门禁。
**当前基线**:以最新用户确认和[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准。旧版需求表、README、开发规划和本文件中的历史建议若发生冲突,先在当前入口记录收尾变更,再决定是否需要修改专题细节。
**当前实现快照(2026-09-26)**:两份文件链路已经落到平台、客户和 Firstleg 报关接口:客户资料、报关行回执、客户整份回执确认/打回、平台发送报关行执行、真实报关完税文件分别保存并受版本门禁控制。回执发送给报关行后不可再替换;只有包含退税货物的柜才允许走发送执行接口;全买单柜仍走平台直接完成。`brokerSubmittedAt` 只表示发送执行时间,不表示报关完成。PDA 只负责产生 `LOADED` 前置事实,报关验收不创建或操作 PDA 任务;船期、甩柜和改配只修改原柜运输信息,不重置报关资料和确认结果。
## 先锁定的范围
国内货柜履约的物理装柜节点为 `LOADED`。`LOADED` 后先完成退税客户的报关协同,报关完成后进入待发区,再推进船期运输:
1. **报关线**:仅对退税客户通知报关行,收集退税客户资料,发送报关行,接收报关行回执并发客户确认;客户认为不正确时打回、重新上传、重新发送并生成新回执,循环至柜内退税客户均确认;全部确认后,再将退税申报资料提交报关行确认,由报关行正式申报,记录查验、不查验放行或其他海关结果。买单货物不进入这条资料和回执流程。
2. **船期线**:报关完成并进入待发区后,安排拖车、从仓库发运、送港、进港;港口容量不足时记录甩柜和改配船次。甩柜/改配只改变运输船次,不重新处理已完成的报关资料、回执和客户确认;`PORT_RECEIVED` 不等于海运中,只有船舶真实开航后才进入海运节点。
报关完成是进入待发区的前置;进入待发区后才推进船期运输。首期不对接海关单一窗口或报关代理系统:报关行回执以文件上传为主,正式申报由授权人员人工提交,客户确认和海关结果由平台人工记录。
费用确认是并行事实,不阻断排柜、预装、PDA 或装柜。装柜完成后,对应已实装范围若客户仍未确认当前有效且已发布费用版本,系统记录“系统默认确认(装柜完成)”;不伪造客户点击,保留 `SYSTEM_AUTO_AT_LOADED` 来源、费用版本、柜次/入仓码、时间和幂等标识。没有有效费用版本时不得生成零额或伪造确认,须保留费用异常待办。
出仓后的实际装船、提单、舱单、结关、退税正式资料和船公司节点查询属于后续或海外仓业务事实,不作为本期国内货柜履约页面、接口和验收范围。若国内页面需要展示,只能消费已确认的跨服务只读快照,并单独定义事件、来源、更新时间和责任边界。
## 入口与权威数据
| 入口 | 本期职责 | 权威数据 | 当前状态 |
|---|---|---|---|
| 客户端“报关资料” | `LOADED` 后查看本企业资料包,上传/替换/补件,查看报关行回执并确认或打回 | Firstleg 报关协同;文件由 File 服务保存 | **目标新增独立入口** |
| 订单中的“上传资料” | 带订单和入仓码上下文进入同一资料包 | 与独立入口共用 packageId 和接口 | **现有快捷入口** |
| 平台整柜报关工作台 | 按实际装柜清单通知报关行,管理客户资料、回执轮次、全部确认、整柜正式提交和海关结果 | Firstleg 柜级报关与提交批次 | **已有四态,需收敛新投影** |
| 客户端“船期价格” | 查询当前企业可见的有效渠道、参考船期、最晚进仓、参考时效和估价 | 生效价格簿及服务端估价 | **建议新增独立入口** |
| 平台“船期价格表” | 上传、解析、核对、发布公共或客户专属价格簿 | Firstleg 价格簿版本 | **已有平台能力** |
平台端应写“按申报组整理并线下提交”。在跨客户合并规则确认前,默认禁止把不同客户放入同一正式报关单;不得在结论表中把待决规则写成既定能力。
## 当前实现事实
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 会发布报关完成事件并参与待发区门禁。契约将“客户资料确认轮次”“整柜正式提交”“海关查验/放行”分开;报关完成后才允许进入待发区,船期事实独立维护。
4. 全买单柜已有独立的二次确认接口和导出契约,本期继续保留;需要补齐其在客户确认轮次、整柜正式申报、海关结果和送港/开船状态中的位置。
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. **本轮报关完成→待发区门禁和船期例外需要保持独立。** 报关完成后才允许进入待发区;`ROLLED_OVER` 只记录新旧船次和运输变更,不回退或重新评估已完成的报关资料、回执和客户确认。
## 报关资料模型
### 0. `LOADED` 后报关完成与待发区
| 线路 | 触发时点 | 顺序 | 结果 |
|---|---|---|---|
| 报关线 | `LOADED` 事件产生后 | 通知报关行 → 收集每个客户资料 → 发报关行 → 接收回执 → 发客户确认 → 打回则重传重发并生成新回执 → 所有客户确认 → 整柜资料交报关行确认 → 正式申报 → 查验/放行 | 客户确认轮次、整柜正式申报、海关结果 |
| 送港线 | 报关完成并进入待发区后 | 安排拖车 → 仓库离开 → 送港 → 进港 → 等待船次;装不下时在原柜船期上人工修改船信息并留痕 | `DEPARTED_WAREHOUSE`、`PORT_RECEIVED`、`ROLLED_OVER`、实际开船 |
报关资料未完成时不得进入待发区;完成报关并进入待发区后才推进送港。已进港也不代表已经进入海运;只有船舶真实开航后,才写入海运起点。
客户确认是每个客户报关案例的完成条件;海关放行是整柜正式申报后的外部结果,不能用上传回执或任意“完成文件”代替。
### 1. 客户报关案例与资料包
报关资料主流程在 `LOADED` 后启动。每个客户/入仓码在本柜建立一个 `customerCustomsCase`,再挂载稳定的 `packageId` 和文件版本。案例至少记录:订单/子订单、入仓码或入仓明细、实际装箱数展示、资料清单版本、每个清单项的文件版本、报关行发送时间、回执文件版本、客户确认/打回人和时间、打回原因、当前 `roundNo`、客户可见范围和审计记录。
资料包不能只关联整票入仓码。已确认支持一单多柜、拆批和父订单—子订单关系,因此每个关联项保存客户、订单、入仓码和装柜明细引用;部分装柜只展示本柜实际箱数并标记线下处理,不在系统内自动做数量分摊。柜次一旦装柜完成不因甩柜改船而变化,受影响案例不能静默重置回执轮次。
### 2. 实际装柜绑定快照
资料包与 loadingPlanId、containerBookingId 的关系应通过绑定记录表达,而不是覆盖原资料包。绑定记录至少保存实际装柜明细引用、实装箱数、客户、订单、入仓码、柜次和绑定版本。`LOADED` 后开始本轮报关时冻结该范围;部分装柜只生成箱数展示和线下处理标记,甩柜改船不使资料绑定和回执轮次失效。
### 3. 申报组与柜级总览
申报组归属一次实际装柜和一次整柜正式提交,记录成员客户案例、合并关系、报关代理、每轮回执、客户确认结果、正式提交时间、正式业务编号、查验/放行结果和异常历史。跨客户合并在业务确认前默认拒绝;若未来开放,必须增加授权、客户可见投影、组成员冻结快照和取消/重组规则。
柜级总览仅供平台使用,汇总实际装柜行、退税/买单行、缺件、提交批次和门禁结果。客户端接口必须按当前企业裁剪返回,不返回同柜其他客户的名称、数量、资料包 ID、申报组 ID 或异常细节。
### 4. 买单、退税和混合柜完成条件
三类柜不能用一条“缺回执即阻断”的规则代替:
| 柜型 | `LOADED` 前 | `LOADED` 后报关线 | 完成条件与开船影响 |
|---|---|---|---|
| 全买单 | 装柜物理门禁独立判断 | 不进入本报关资料、报关行回执和客户确认流程;继续按买单装柜、导出和运输节点处理 | 不创建退税报关案例,不以报关资料或回执作为门禁 |
| 退税柜 | 装柜物理门禁独立判断 | 对每个参与入仓码收集/补件,发送报关行,逐份接收回执并让对应客户确认;打回则重做当前案例 | 所有退税客户案例确认后才允许整柜正式提交;正式申报后的查验/放行单独记录 |
| 混合柜 | 装柜物理门禁独立判断 | 仅退税行建立报关资料和回执确认案例;买单行不进入该流程,仍保留买单装柜和导出事实 | 仅退税客户案例全部确认后才允许提交退税申报批次;不得把买单明细冒充报关确认 |
同一客户多个入仓码可以共享其授权资料;跨客户物理拼柜不等于允许跨客户正式合报。跨客户合并仍默认禁止,必须有独立授权和客户可见隔离契约。
## 状态、事实与门禁
建议把状态拆成独立事实面,页面总状态只做投影:
| 事实面 | 建议状态 | 说明 |
|---|---|---|
| 客户报关案例 | WAITING_DOCUMENTS、SENT_TO_BROKER、RECEIPT_PENDING_CUSTOMER_CONFIRM、CUSTOMER_CONFIRMED、NEEDS_RESUBMIT、INVALIDATED | 每轮 `roundNo` 保存资料版本、发送时间、报关行回执、客户确认/打回原因;回执上传不等于客户确认 |
| 整柜申报批次 | WAITING_ALL_CUSTOMER_CONFIRM、ALL_CUSTOMERS_CONFIRMED、FORMAL_SUBMITTED_TO_BROKER、DECLARED、INSPECTION、NO_INSPECTION、RELEASED、REJECTED | 所有客户案例确认后才允许整柜正式提交;首期由授权人员人工记录报关行确认和海关结果 |
| 送港/船期事实 | PORT_DELIVERY_PENDING、DEPARTED_WAREHOUSE、IN_TRANSIT_TO_PORT、PORT_RECEIVED、ROLLED_OVER、VESSEL_DEPARTED | 与报关案例独立;进港和甩柜不等于海运中,只有真实开船才进入海运节点 |
| 装柜门禁 | PASS/BLOCKED | 只判断是否满足 LOADED 的已确认前置 |
上述是首期状态投影。回执首期以文件为主、客户确认整份回执;正式申报由平台授权人员人工提交并回填结果;实际开航首期人工录入,甩柜/改配人工修改原柜船信息并保留原报关事实,不重新评估申报批次。其余稳定编码、退回/重开规则和责任人仍需在开发前确认。当前四态不能直接承担新流程;收敛时应明确旧状态的映射和删除时点,不保留双协议。
物理 `LOADED` 门禁必须明确校验以下事实:
1. 真实柜号、预装计划和数量版本完整;
2. PDA 拣货和复核完成,整批提交成功;
3. 空仓、半仓、满仓、锁仓、带锁码照五类证据各有至少一张有效照片,锁码文本已保存;
4. 数量守恒、无未解决 PDA 异常。
`LOADED` 后创建报关案例;报关案例完成整柜正式申报并达到报关完成条件后,才允许进入待发区并创建/推进送港任务。送港任务继续校验装柜完成、真实柜号、订舱/拖车等运输条件。到港后如船舱不足记录 `ROLLED_OVER`;只有实际 `VESSEL_DEPARTED` 才进入海运节点。报关放行、送港和甩柜不能反向作为 `LOADED` 的前置,甩柜也不改变已完成的报关事实。
每个写动作都需要 Idempotency-Key、expectedVersion、规范化请求哈希、乐观锁冲突码、审计事件和结果回放。上传、替换、改关联、补件、审核、提交批次、回执上传和门禁确认不得仅靠前端推进。
## 权限、文件与接口边界
现有报关接口使用 merchant:order:view/edit 和 platform:firstleg:customs:list/manage。新增独立入口前必须确认是复用还是拆分为报关专用权限,并落到客户端路由、导航、Controller、OpenAPI x-permission、IAM 初始化 SQL 和服务端对象级校验:
- 客户查看、上传/替换、补件确认和下载分别校验当前企业、订单/子订单、入仓明细和客户可见标记;不能信任请求中的 tenantId、订单 ID 或入仓码。
- 平台查看、审核/退回、生成提交批次、上传回执和发布结果分别授权;列表权限只包含详情只读,写权限独立。
- File 文件类型、业务 ID、客户归属、版本、冻结和下载审计必须定义。现有 `LOADING_LIST_CUSTOMS_SOURCE`、`LOADING_LIST_CUSTOMS_RECEIPT`、`LOADING_LIST_CUSTOMS_RESULT` 只负责不可变文件对象,不能替代客户案例、提交批次和海关结果对象;正式申报与海关结果的独立接入见[专题设计](../头程到尾程/正式申报与海关结果接入设计.md)。
- File 上传成功但业务写入失败、业务写入成功但 File 失败、替换/作废和重试都要有补偿或可重放规则;不能产生越权文件或孤儿记录。
独立客户列表、详情、待办计数和平台筛选必须补充明确的路径、分页、稳定排序、筛选参数、空态/无权限响应和错误码。不能只写“新增列表”或继续复用单订单查询接口。
## 船期价格接入
### 展示边界
客户页只展示当前企业可见的有效价格簿快照:渠道、起运仓、目的地、pricingTaxMode、计费单位、单价、币种、参考船期、最晚进仓、参考时效、附加费说明、价格簿版本和更新时间。价格簿中的预计船期是参考文本,不是已订舱 ETD、实际开船或到港节点;时区、有效期、来源和过期展示必须明确。
客户专属与公共价格按版本作用域选择:先选择当前企业专属 ACTIVE 版本;只有不存在专属 ACTIVE 版本时才选择公共 ACTIVE 版本,不能按单条费率缺行再逐行回退。页面展示业务版本号或生效时间,不直接把内部 priceBookVersionId 当作用户可见编号。
### 批量估价契约
若要跨渠道列表展示,服务端新增批量估价契约,至少定义:起运仓、目的类型/目的地、渠道候选、重量、体积、pricingTaxMode、版本快照、批量上限、超时、无命中错误、计费量、单位、币种、基础金额、未包含附加费、舍入规则和排序规则。不得由浏览器自行计算或逐渠道扇出。
“价格优选”只有在币种、目的地、税模式、计费口径和附加费范围可比时才允许启用;否则只展示参考结果。订单创建时必须重新校验渠道资格和生效版本,明确旧报价失效、金额变化和重新报价的用户提示,不把客户端显示金额当成最终结算金额。
价格导出如需上线,应另定义客户可见字段、公共/专属价格隔离、导出审计、快照版本、文件保留期限和下载权限;在这些规则确认前不纳入本期上线。
## 实施顺序与进入条件
1. **冻结业务规则**:确认客户资料清单、回执轮次、打回重做、所有客户确认、整柜正式申报、查验/放行、甩柜/改配和跨客户合并;已确认规则以[需求确认表](国内货柜履约需求确认表.md#L24)为准。
2. **先做服务端契约**:完成 customerCustomsCase、资料版本、报关行回执轮次、客户确认、整柜申报批次、送港/进港/甩柜/开船事实、状态投影、权限、幂等、审计、File 类别和初始化 SQL;同步更新 OpenAPI、Gateway、IAM 和相关消费者。
3. **接入客户入口**:独立列表/详情与订单快捷入口共用 packageId;仅在 `LOADED` 后进入本柜报关案例,覆盖资料上传、报关行回执查看、确认、打回、重新上传和新回执版本。
4. **接入平台协同**:`LOADED` 后按最终实装快照通知报关行,逐客户处理资料和回执,全部客户确认后提交整柜资料;人工记录正式申报、查验、不查验放行和其他结果。送港线独立接入拖车、进港、甩柜和实际开船。
5. **接入船期价格**:先复用有效价格簿和单渠道参考估价,再实现批量估价;批量列表、排序和导出必须先通过接口和价格可比性评审。
## 待确认事项
| 问题 | 阻断范围 | 需要形成的结论 |
|---|---|---|
| 资料清单具体项目、条件规则和版本生效方式 | 清单、审核、补件 | 首版人工维护清单及版本负责人 |
| 客户确认/打回原因和回执轮次 | 客户案例、整柜提交 | 回执版本、roundNo、确认人、打回重做规则 |
| 海关查验、不查验放行、扣货/补件等正式结果 | 整柜申报批次、客户展示 | 结果类型、凭证、来源、客户可见范围和责任人 |
| 送港、进港、甩柜、改配船次和实际开船事件 | 待发区、送港线、海运节点 | 事实字段、重试规则、客户通知和船次历史;首期人工录入实际开航,改配人工修改原柜船信息但不改变已完成报关事实 |
| 价格比较、导出、报价有效期和金额变化提示 | 客户报价页、下单 | 统一币种/税模式/附加费和失效处理 |
## 最低验收矩阵
- 客户 A 无法查询、上传、替换或下载客户 B 的资料、回执、价格和导出文件。
- 独立入口与订单快捷入口返回同一 packageId、版本历史和待办结果,不产生双历史。
- 同一幂等键同请求只产生一次记录;同键不同请求、版本冲突、并发换柜和重复回执均返回明确业务错误。
- `LOADED` 后每个客户案例都能经历“资料上传→报关行回执→客户确认”;打回后只重开对应案例,重新上传、重新发送并产生新回执轮次,其他客户历史不被覆盖。
- 所有客户案例均 `CUSTOMER_CONFIRMED` 后,平台才允许生成整柜正式提交;正式提交后分别验收查验、不查验放行和其他海关结果。
- 缺 PDA 结果、缺五类证据、真实柜号或数量不守恒时,`LOADED` 门禁失败;报关完成后才进入待发区,再验收离仓、进港和甩柜;只有真实开船才进入海运节点,甩柜不重做已完成报关。
- 全买单柜、退税柜和混合柜分别验证状态、权限、导出、回执和门禁结果。
- 价格无命中、失效版本、跨渠道批量估价、不同币种/税模式、附加费说明和订单创建重验均有可验证结果。
- 页面覆盖加载、空态、失败、无权限、过期和数据冲突;客户端按 1920×1080、100% 缩放人工验收。
## 接入核对入口
- 客户端订单与现有报关: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](../../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)。