docs: organize contracts by business domain
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
# 货柜管理全链验收矩阵
|
||||
|
||||
> 更新时间:2026-08-17
|
||||
> 当前任务:`019ff90b-a72d-7000-abdf-e5363357a564`
|
||||
> 父任务:`019ff600-f9f1-78f1-a357-7c80c13e574e`
|
||||
> 依赖任务:后端主链 `019ff90b-9b45-7191-b68f-c3b52567e3e4`、动态增量后端 `01a00e91-2124-7960-95d6-e0d0f81959f9`、Admin `019ff90b-a037-79b0-b945-8f88bdbde9c5`
|
||||
> 边界:只维护根目录脚本、验收文档和测试矩阵;不修改 Admin 或 Java 业务源码,不部署、不触发 Jenkins、不写测试环境数据库。
|
||||
|
||||
## 验收口径
|
||||
|
||||
- 本矩阵以当前对话、国内货柜履约产品确认版开发规划和实际冻结契约为准。旧确认单中的待确认项不覆盖后续已冻结结论。
|
||||
- 已冻结能力按事实来源落具体路径和断言;尚未冻结能力继续只保留能力级占位,不预设 HTTP 方法、路径、DTO 字段或业务错误码。
|
||||
- 自动化必须通过业务 API 生成数据;人工验收必须能从 Admin/PDA 可见入口点击到对应状态。不得以数据库直写、mock、原型或前端本地假状态代替。
|
||||
- 每次真实 HTTP 验收记录请求用途、响应状态、业务码、`requestId`、`traceId`、关键资源 ID 和清理/保留策略;敏感凭据不得写入报告。
|
||||
- 柜态看板不纳入本轮。
|
||||
- 列表逐字段来源、格式门禁与 `UNKNOWN` 登记见《货柜履约原型字段验收矩阵-2026-08-17》;任何未冻结字段不得由 fixture 伪造或用其他字段代填。
|
||||
|
||||
## 状态数据目录
|
||||
|
||||
| 数据代号 | 必备状态/形态 | 生成前置 | 自动化断言 | 人工可点击入口 | 当前状态 |
|
||||
|---|---|---|---|---|---|
|
||||
| CT-D01 | 订舱 DRAFT 登记柜型需求并最终放舱 | DRAFT 可部分保存/编辑/删除;完整资料含五项运输事实及 `containerRequirements(type/kind/quantity/spec)` | release 完整性校验后进入 `RELEASED` 并冻结;订舱不含 `containerNo`,不生成货柜或 allocation | 订舱列表/详情仅显示 DRAFT、RELEASED | `LANDED_STATIC`,待环境验收 |
|
||||
| CT-D02 | 不同渠道各一单 | 渠道主数据可用 | 柜次/清单/任务不得跨渠道混装或串查 | 排柜候选可按渠道辨识 | 待契约 |
|
||||
| CT-D03 | 内部模拟柜已排货、已 push,但无真实柜号/订舱 | 正式装柜仓库、ACTIVE 物流渠道、箱型和容量可用 | 服务端生成稳定 `containerBookingId/cabinetNo`;同仓同渠道 WAIT_SPLIT 可排;无号 `push-preload` 成功并冻结明细、建立唯一 bridge、使预装 `EDITING` 可见,但 PDA 查询必须为 `A0404` | 货柜列表可新增模拟柜,预装清单显示待关联/待补号 | 新时序已冻结,待环境验收 |
|
||||
| CT-D04 | 港口真实柜号关联、订舱放舱且预装已确认,PDA 可领取 | CT-D03;订舱 `RELEASED`;港口取得唯一 `containerNo`;选择未满配 `requirementId`;预装进入 `CONFIRMED` | link 四字段在原模拟柜上补齐订舱、真实柜号和运输快照并创建 allocation;四元身份稳定,三项前置任缺一项都无 PDA,claim 后才进入 `LOADING` | PDA 任务列表可进入 | `LANDED_STATIC`,待环境验收 |
|
||||
| CT-D05 | 作业中更换真实柜号 | CT-D04,PDA 已开始 | 柜号变化但柜次 ID、任务、清单、证据归属不漂移 | 详情与 PDA 同步显示新柜号 | 待契约 |
|
||||
| CT-D06 | 预装清单已生成/确认 | CT-D03 | push 后 `EDITING` 清单可补真实柜号;订舱 `RELEASED` 后通过计划级 `/loading-plans/{loadingPlanId}/confirm` 原子确认全部关联预装票据,返回 `confirmationStatus=CONFIRMED`、`readyForPda=true` 和唯一 `pdaTaskId`;版本、明细、数量及确认历史可追溯 | 预装清单列表/详情可点击 | 计划级确认已冻结,待环境验收 |
|
||||
| CT-D07 | 装柜清单进行中/已完成 | CT-D04 | 装载明细、数量、状态与预装来源一致 | 装柜清单列表/详情可点击 | 待契约 |
|
||||
| CT-D08 | PDA 领取、拣货、复核、异常摘要 | CT-D04 | overview 分别返回 `taskStatus`、`workflowStatus`、任务 ID、版本、计数、`photoCounts`、`photos`、`downloadPath` 和异常原因;逐照片代理下载成功 | PDA 可完成主流程;Admin 入口待回传 | 服务端已冻结;人工入口待定 |
|
||||
| CT-D09 | 报关/清关资料及有效回执 | CT-D06 | 目的港清关走货柜 `/clearance`;出口报关走 loading-list `/customs`;分别验证上传、完成和完成后替换锁定 | 报关协同入口待回传 | 服务端已冻结;人工入口待定 |
|
||||
| CT-D10 | DO/PU 未齐、部分完成、全部完成 | 柜次与运输协同已建立 | `DELIVERY_ORDER`、`PICKUP_ORDER` 可独立查询、上传和鉴权下载,版本与幂等有效 | 柜次详情入口待回传 | 服务端已冻结;人工入口待定 |
|
||||
| CT-D11 | 正常、异常、取消异常 | 任意有效柜次及显式货柜版本 | 标记/取消使用版本和必填原因;overview 保留 `MARK`/`CANCEL` 全部历史 | 货柜详情入口待回传 | 服务端已冻结;人工入口待定 |
|
||||
| CT-D12 | 多节点运输轨迹与操作日志 | CT-D10 | overview 时间线含运输更新、异常和 PDA 事件,按发生时间升序 | 详情时间线入口待回传 | 服务端聚合已冻结;人工入口待定 |
|
||||
| CT-D13 | PDA 确认装柜并推进 `LOADED` | inbound `LOADING`、bridge、订舱 `RELEASED`、PDA 全拣和五类 ACTIVE 证据齐备;拖车允许缺失、未完成或存在多条 | PDA `complete` 的主事务不以拖车数量/状态为阻断;提交后才在独立事务 best-effort 同步唯一同柜有效拖车。零条直接跳过,一条可推进 `COMPLETED`,多条或拖车并发只隔离记录同步失败,task/plan/inbound 仍保持 `LOADED` | 订单/柜次详情显示完成且编辑锁定;拖车同步失败单独呈现 | `LANDED_STATIC`:OpenAPI、Service、提交后同步隔离与结算版本回归已冻结;待部署后 HTTP 复核 |
|
||||
| CT-D14 | PDA 未最终完成前向同一预装计划增加入库单 | 已有稳定 `loadingPlanId/taskId/containerBookingId`,任务尚未最终完成;新增票满足同客户、仓库、渠道、容量与柜型约束 | `EDITING/LOADING` 可增量;`LOADING` 不回退且复用同一 task;plan/task/item 版本递增,旧 inventory token A0409 后必须刷新;全拣后增项将 `AWAITING_REVIEW` 撤回 `IN_PROGRESS`,证据保留;未拣项可删,已拣数量形成 `minPackageCount` | Admin 预装增量入口与 PDA 同步显示新增项 | `LANDED_STATIC`:assign/adjust/delete 与 capability DTO 已冻结并接入脚本;待部署后真实 HTTP 复核 |
|
||||
|
||||
## 全链验收用例
|
||||
|
||||
| 用例 | 场景 | 服务端/契约断言 | UI/设备断言 | 证据要求 | 状态 |
|
||||
|---|---|---|---|---|---|
|
||||
| CT-E01 | 模拟柜原地关联 RELEASED 订舱需求 | link 请求为 `oceanBookingId+requirementId+containerNo+expectedVersion`;成功后模拟柜 ID/cabinetNo/计划/明细稳定并新建 allocation,不存在中间真实柜 | 货柜详情只显示关联后的一个可操作身份 | link 前后柜次、计划、明细、allocation 及 ACTIVE 列表唯一性快照 | `LANDED_STATIC`,待环境验收 |
|
||||
| CT-E02 | 渠道隔离 | 不同渠道不能进入同一排柜结果;交叉 ID 请求失败 | 候选、清单和详情不串渠道 | 双渠道正向及交叉负向响应 | 待契约 |
|
||||
| CT-E03 | 无真实柜号排柜与 push | 临时身份可完成排柜;`push-preload` 在无 `containerNo` 时成功,只冻结计划、建立 bridge、开放 `EDITING` 预装,不创建 PDA;exact replay 原样返回且计划/版本/历史/link/task 零漂移 | 页面明确展示待补号,不伪造柜号 | push 原始 path/body/key、重放前后全快照、PDA `A0404` | 新时序已冻结,待环境验收 |
|
||||
| CT-E04 | 四字段关联及三项前置开放 PDA | 无号 push 后仍无 PDA;未关联、订舱未 `RELEASED`、预装未 `CONFIRMED` 分别查询 PDA 均为 `A0404`;关联时录入唯一真实柜号,最后一个前置完成后仅生成一个 task,claim 才推进 `LOADING` | 关联、放舱、确认前后 PDA 入口状态同步 | 三个逐项负向、唯一 task 四元身份、claim 前后状态 | `LANDED_STATIC`,待环境验收 |
|
||||
| CT-E05 | 作业中换号身份不漂移 | 只变更展示柜号;柜次 ID、任务 ID、清单、证据关联不变 | Admin/PDA 刷新后显示新号且进度不丢 | 换号前后关联快照 | 待契约 |
|
||||
| CT-E06 | 预装/装柜清单 | push 自动生成/关联预装聚合;仅允许按 `loadingPlanId` 原子确认整份计划,禁止旧单票 `/preload/confirming`、`/preload/confirm`;返回唯一 task 后 claim 才进入 `LOADING` | 两类列表和详情均可人工点击 | `PENDING -> EDITING -> CONFIRMED`、计划版本、readiness、taskId、幂等重放与历史 | 计划级确认已冻结,待环境验收 |
|
||||
| CT-E07 | PDA 主链 | 领取、扫码、批量提交、复核、完成;幂等与版本冲突有效 | 真机/目标设备可完成,失败不假成功 | 请求链、设备记录 | 待契约 |
|
||||
| CT-E08 | PDA 进度异常摘要 | `GET /api/platform/v1/containers/{id}/overview` 返回 PDA `taskStatus/workflowStatus`、任务身份、版本、计数、照片摘要、文件 ID 与鉴权下载路径;每个路径真实 GET 200 | Admin 入口待回传 | overview 响应、字段完整性及二进制下载证据 | 服务端契约已冻结 |
|
||||
| CT-E09 | 清关/报关资料闭环 | 目的港清关:货柜 `/clearance` 查询/上传/完成;出口报关:loading-list `/customs` 查询/上传/完成;两者完成后均禁止替换 | Admin 入口待回传 | 两条专用链路的版本、幂等、完成和锁定负向响应 | 服务端契约已冻结 |
|
||||
| CT-E10 | DO/PU | 通用查询、multipart 上传、鉴权下载;上传要求 `Idempotency-Key`、真实文件、`expectedVersion`,重放不得重复上传 | Admin 入口待回传 | 两类型响应、文件哈希/ID、二进制下载、幂等重放 | 服务端契约已冻结 |
|
||||
| CT-E11 | 货柜异常及取消历史 | `POST/DELETE /api/platform/v1/containers/{id}/exception` 要求 `expectedVersion` 和必填原因;冲突失败;overview 历史只追加不覆盖 | Admin 入口待回传 | 标记/取消响应、版本冲突、overview 历史 | 服务端契约已冻结;版本来源阻断 |
|
||||
| CT-E12 | 运输轨迹/日志 | overview `timeline` 聚合 `TRANSPORT_UPDATE`、`MARK/CANCEL`、`PDA_*`,时间升序且含详情、操作者和发生时间 | Admin 入口待回传 | overview 时间线响应 | 服务端契约已冻结 |
|
||||
| CT-E13 | PDA complete 与可选拖车隔离 | 同柜零/一/多条拖车均不阻断 complete:零条直接 `LOADED`;唯一有效拖车可在主事务提交后独立推进 `COMPLETED`;多条、错柜或拖车并发失败不得回滚 task/plan/inbound,且不得误改其他拖车;同键重放不新增历史 | PDA 完成页、入库单和订单详情先显示 `LOADED`;拖车详情显示独立同步结果 | 零/一/多条三条链 + 幂等重放;记录 task/plan/inbound/truck 前后版本、历史数量、业务码和 `requestId/traceId` | `LANDED_STATIC`:提交后独立同步、异常隔离及一对多保护已冻结;多 fixture HTTP 待跑 |
|
||||
| CT-E19 | PDA 结算导致版本递增后的最终完成 | final complete 前来源 inbound 为 `LOADING`;settle 可能将来源 version 递增并生成全量或部分实装分片 | complete 必须在 settle 后重新锁定实际完成行并使用当前 version,不得复用结算前快照;full/partial 均成功,真实并发仍 A0409,失败 task/plan/inbound/operation/history 零写入 | PDA、计划、入库单和统一订单显示唯一 `LOADED` 事实 | `LANDED_STATIC`:真实缺陷样本 task `2089254643058184193` 已转为 Node/Java 回归;待修复版本部署后 HTTP 复核 |
|
||||
| CT-E20 | PDA pending/detail 工作流一致性 | 同一 task 已有唯一 BATCH、明细全为 PICKED、`pendingItemCount=0` | pending 与 detail 均返回 `AWAITING_REVIEW`;允许证据 GET;派生 actions 为空且不再 POST batch | PDA 待办卡片与详情均显示“待人工复核”,进入取证而非重复拣货 | `LANDED_STATIC`:pending SQL 按明细未完成数投影,OpenAPI 已冻结;待部署后新 marker HTTP 复核 |
|
||||
| CT-E14 | 跨客户与跨仓库隔离 | 交叉资源 ID 不可读写下载,不泄露资源存在性 | 页面无越权入口 | 双身份交叉请求证据 | 待契约 |
|
||||
| CT-E15 | push 幂等、冲突与事务回滚 | 首次成功请求冻结 path/body/expectedVersion/key;同 key 原样重放只读且返回首次结果;同 key 异参、新 key 重复均冲突;各负向后计划、版本、历史、bridge、PDA 全快照零漂移;首次 push 在 bridge 中途失败时整事务零残留且不得触发 PDA | 冲突或失败后页面刷新仍只显示首次成功事实 | 原始请求、三次回查全快照、失败 `requestId/traceId`;中途失败由后端事务合同覆盖 | 新时序合同已冻结,待环境验收 |
|
||||
| CT-E16 | 默认 Admin HTTP 同 marker 完整链 | 默认入口按 `phase3-container-loading -> phase3-loading -> overview/PDA/evidence -> customs -> loading-finalize` 串行;下游只消费 `phase3Loading` 发布的 `taskId/inboundId/loadingPlanId/containerBookingId`,最终同一订单详情和列表均为 `LOADED` | 同一批次可从订单、柜次、预装、PDA、报关入口逐级回查 | 全新 marker、关键资源 ID、五类二进制证据、各请求 `requestId/traceId`、最终统一订单状态 | 静态合同已接入默认入口,待环境 HTTP |
|
||||
| CT-E17 | 订舱代理不区分国内/国外 | 供应商必须为正式 `supplierId` 对应的 `ACTIVE + BOOKING` 记录,名称使用服务端快照;查询、创建和内部快照校验不得携带或要求 `DOMESTIC/INTERNATIONAL scope`,但类别或启用状态不符仍 fail-closed | 订舱代理候选不显示国内/国外范围门禁 | fixture 请求、Warehouse 内部快照、Firstleg 类别/启用校验及 Admin 候选静态合同;部署后补真实 HTTP | Warehouse/Firstleg 共享改动已可见;Admin 与环境 HTTP 待收口 |
|
||||
| CT-E18 | PDA 进行中增量预装与最终完成竞态 | 领取后、最终完成前新增入库单必须复用同一 task;新项出现后撤回最终完成门禁,旧 token 返回 A0409“库存已变化,请刷新后重试”且零写入;未拣项可删除,已拣项删除或减量拒绝;Admin 增量与 PDA final complete 同锁 task 行,只允许一个事务成功;`COMPLETED` 后全部变更拒绝 | Admin 增量结果与 PDA 队列实时一致,失败提示不伪造完成 | 增删前后计划/task/items/evidence 投影、版本和操作历史;并发双方响应及最终唯一事实 | `LANDED_STATIC`:OpenAPI、HTTP 双请求 winner/loser 脚本及离线合同已接线;待部署后定向复核 |
|
||||
|
||||
## PDA 完成后未进入 LOADED 的已登记回归
|
||||
|
||||
- 真实测试样本:订单 `NYEXX2608170001`;PDA task、review、装柜计划与五类证据均已完成,但 inbound 仍为 `LOADING`。
|
||||
- 历史只读证据:旧柜次曾因拖车 `loading_plan_id=NULL` 被误判 `truck_ready=0`;该门禁已被最新产品结论覆盖,不再作为 PDA 完成前置。
|
||||
- 最新冻结:最终入口仍为 `POST /pda-loading/tasks/{taskId}/complete`,保留订舱 `RELEASED`、bridge 和五类 ACTIVE 证据门禁;拖车缺失、未完成或多条均不得阻断。
|
||||
- 同步边界:task/plan/inbound 主事务先提交为 `LOADED`;若同稳定 `containerBookingId` 恰有一条有效拖车,再以独立新事务尝试推进 `COMPLETED`。零条直接跳过;多条、错柜或并发冲突不得回滚主事实。
|
||||
- 已冻结回归包:① 唯一 `LOADING` 拖车 → PDA complete → inbound `LOADED`,拖车独立同步 `COMPLETED`;② 无拖车仍成功;③ 多拖车仍成功且各拖车零误改;④ 错柜拖车零修改;⑤ 同键重放不新增历史;⑥ 拖车同步异常只保留独立失败证据。
|
||||
|
||||
## 拖车独立开立契约
|
||||
|
||||
| 验收项 | 正式断言 | 当前结论 |
|
||||
|---|---|---|
|
||||
| 无履约关联创建 | `oceanBookingId/containerBookingId/loadingPlanId` 可同时为空;本轮客户、正式 ACTIVE `TRUCKING` 承运商、`plannedLoadingAt` 必填;创建后可查询、编辑并独立完成 `DRAFT -> ... -> COMPLETED` | `LANDED_STATIC`:DTO/OpenAPI/Admin 与 HTTP fixture 已接线 |
|
||||
| 客户和供应商事实 | `customerId` 必须指向 ACTIVE IAM 客户,名称由 IAM 冻结;`carrierId` 必须指向 ACTIVE TRUCKING 供应商,名称由 Warehouse 冻结;名称仅为一致性提示 | 静态及 HTTP 必填负向已接线 |
|
||||
| 可选订舱/柜次 | 任一关联存在时校验客户及仓库;订舱和柜次同时存在时必须有 allocation 关系 | Service/OpenAPI 静态合同已锁定;部署后补不同客户/仓库及 allocation HTTP 负向 |
|
||||
| 可选计划 | `loadingPlanId` 仅能与 `containerBookingId` 同时提供,且必须是该柜次当前计划 | 同 marker 柜次派生错误计划 ID 的 HTTP 负向已接线 |
|
||||
| PDA 隔离 | 未关联拖车不受 PDA 影响;同柜零/一/多条均不阻断 PDA 主事务;唯一拖车同步失败也只影响拖车自身 | 静态合同已锁定提交后同步与独立事务;部署后按零/一/多 fixture 验证 |
|
||||
| Admin 表单 | 客户、承运商、预计装箱时间必填;订舱和柜次明确标注可选,清空后不得残留派生计划/仓库/客户 | Admin 静态合同已接线 |
|
||||
| 派车提单门禁 | DRAFT 可先独立开立;DISPATCH 前必须有 `billOfLadingNo` 和有效 `BILL_OF_LADING` 文件,缺任一项明确拒绝 | `truck-appointments` 已覆盖缺失拒绝、正式上传/回查与完整自身状态机;待部署后 HTTP |
|
||||
|
||||
## 装柜清单三备注
|
||||
|
||||
| 验收点 | 冻结契约 | 自动化证据 |
|
||||
|---|---|---|
|
||||
| 来源隔离 | `customerRemark` 来自订单客户备注;`internalRemark` 来自最新内部备注,禁止冒用 `cargoRemark` | `orders` 写入三条互异 marker;`phase3-loading` 精确比较来源与非串值 |
|
||||
| 仓库备注 | `warehouseRemark` 仅在 EDITING/LOADING 通过正式 item PATCH 维护;空白归一化为 null | 覆盖保存、空白清空、版本递增、旧版本 A0409 后回查零漂移 |
|
||||
| 幂等与终态 | 同 operationId 同参数精确重放不重复递增;异参冲突;COMPLETED 后 A0409 且零写 | OpenAPI/Service 静态合同已锁定;COMPLETED HTTP 负向待部署后与 finalize 串联 |
|
||||
| 动态增量 | assignment/数量调整/删除不得覆盖已有仓库备注 | `phase3-loading` 在 LOADING 增量前后断言原明细仓库备注保持,调整明细备注保持 |
|
||||
| 海外事件 | `FirstLegLoadingPlanCompletedV2` 每个 item 含 customer/internal/warehouse 三备注,事件哈希与幂等基于同一稳定 payload | `loading-list-remarks-contract.test.mjs` 锁定 V2 类型与三字段映射;海外消费者仓库不在本仓,列为跨仓部署依赖 |
|
||||
| Admin | 客户/内部备注只读,仅仓库备注显示编辑入口;COMPLETED 隐藏编辑 | Admin 静态合同已锁定 |
|
||||
- 结算版本缺陷证据:task `2089254643058184193`、inbound `2089181999189299202` 在 taskVersion=1/inboundVersion=6、PICKED 2/2 与五证据齐备时返回 A0409;requestId=`12a913ba-9845-45f6-91ec-bdba28e3eb9d`、traceId=`395d11b5c0da45eca948a39a08e29d3d`。回归锁定 settle 后重新读取 full/partial 实际完成分片版本;真实并发仍冲突,失败必须零写入。
|
||||
|
||||
## PDA 进行中增量预装冻结回归
|
||||
|
||||
- 冻结来源仅跟踪动态增量后端任务 `01a00e91-2124-7960-95d6-e0d0f81959f9` 落盘的 SmartLoading assign/adjust/remove、capability DTO/OpenAPI 和版本并发契约;不再向后端主链任务重复询问动态字段。
|
||||
- 用户确认:预装清单在 PDA 尚未最终确认装柜完成前允许继续添加入库单,并由原有同一 PDA task 继续拣货;不得通过新建第二个 task 或替换稳定四元身份实现。
|
||||
- 必测时序:`EDITING` 添加;task 已领取且仍未完成时添加;新增项进入同一 `taskId + inboundId + loadingPlanId + containerBookingId` 工作集;计划/task/item 版本单调递增;旧 inventory token 返回正式版本冲突并零写入;刷新后可拣新增项并再次满足完成条件。
|
||||
- 门禁撤回:新增未拣项后,原先的 ready、完成度及五类证据完成投影不得继续允许 final complete;新增项全部拣完并重新满足正式证据/下游条件后才恢复。
|
||||
- 删除与减量:已拣项删除或减量必须拒绝且全链零漂移;未拣项删除成功后同步 task、计划、库存快照与 readiness。正式写端点为 plan assignments、item PATCH、item DELETE,分别使用 planVersion/itemVersion 与 operationId。
|
||||
- 并发与终态:Admin 增量与 PDA final complete 并发只允许一个事务成功,失败方必须取得明确业务冲突证据;task/计划进入 `COMPLETED` 后,添加、删除、减量全部拒绝。
|
||||
- 隔离基线不变:容量/限重、客户、仓库、物流渠道、柜型/规格和 ACTIVE 柜次归属继续 fail-closed;任何增量都不得借历史入库单、跨 marker 或创建第二个任务绕过。
|
||||
- 默认全量接入:`phase3-loading` 已在首次 batch 与 final complete 之间接入本轮 marker 的独立入库单、旧 token 负向、未拣删除、重新加入、调整、刷新补拣和已拣删除/减量零写入;`phase3-pda-convergence` 回查稳定四元和唯一任务,最后由 `phase3-loading-finalize` 串行执行正式 complete,确保结算自身的版本变化不被人为并发遮蔽,成功后回查实际 full/partial 履约分片及唯一 `LOADED` 事实;失败则保存业务码、`requestId/traceId` 并回查 task/plan/inbound/operation 零漂移。真实增量/final 并发使用独立 fixture,不复用主正向链。
|
||||
|
||||
## P3-Q14 文档同步待总控统一
|
||||
|
||||
- 当前冻结验收时序:订舱只登记 `containerRequirements` 并在完整 release 后进入 `RELEASED`;不会生成真实货柜。未订舱时先建 `SIMULATION/ACTIVE` 模拟柜并排货、无号 push,港口取得真实 `containerNo` 后用四字段 link 原地补全模拟柜并创建 allocation。
|
||||
- `docs/国内货柜履约/国内货柜履约需求确认表.md` 的 P3-Q14 尚未完整描述新的 DRAFT/RELEASED 与港口四字段关联模型。本任务不擅改需求确认表,标记为 `WAIT_CONTROLLER_DOC_SYNC`,由总控统一文档;本矩阵及自动化以当前冻结 DTO/OpenAPI 为准。
|
||||
- 五项运输事实保存在 DRAFT 聚合,release 只校验完整性并冻结持久化快照;RELEASED 不接受编辑或删除。
|
||||
|
||||
## 契约冻结清单
|
||||
|
||||
### 既有冻结基线
|
||||
|
||||
以下能力在本轮新增 overview 契约之前已经由国内货柜履约产品确认版、既有 OpenAPI/Controller 和专项测试冻结。本轮不重定义其路径或状态机。
|
||||
|
||||
| 能力标识 | 冻结边界 | 事实来源 | 状态 |
|
||||
|---|---|---|---|
|
||||
| `booking-requirements-and-port-link` | 订舱按 `containerRequirements[]` 保存箱型数量,不生成真实柜;link 在港口取得真实柜号后补全模拟柜并创建 allocation | `PlatformContainerController`、`ContainerService`、`OceanBookingService`、`firstleg-v1.yaml`、`ocean-bookings-v1.yaml` | 本轮目标冻结,待环境验收 |
|
||||
| `channel-isolation` | 渠道隔离与禁止跨渠道混装 | 国内货柜履约产品确认版及既有排柜契约 | 既有冻结,待环境验收 |
|
||||
| `container-number-lifecycle` | 模拟柜无真实柜号允许排柜及 push;push 本身不开放 PDA;link 从未消费真实柜带入唯一 `containerNo`,内部柜、计划、bridge 身份稳定;作业中换号身份稳定 | `ContainerService`、`SmartLoadingService`、`SplitPreloadService`、`LoadingListService`、相关 OpenAPI 与合同测试 | 新时序已冻结,待环境验收 |
|
||||
| `preload-and-loading-list` | `PENDING -> EDITING -> CONFIRMED`;计划级确认原子确认全部关联票据并唯一建 task;ACTIVE 模拟柜已关联 `RELEASED` 订舱需求、真实柜号和 readiness 全部满足后 `readyForPda=true`,claim 才推进 `LOADING` | `LoadingListService.confirmPreload`、`LoadingPickService`、`POST /loading-plans/{planId}/confirm` 及 Loading List OpenAPI/DTO | 计划级确认已冻结,待环境验收 |
|
||||
| `customs-documents-lock` | 清关/报关专用流程、完成态禁止替换 | 既有 `LoadingListService`、专用 Controller 与专项测试 | 既有冻结,待环境验收 |
|
||||
|
||||
### 本轮新增冻结契约
|
||||
|
||||
事实来源:`baiyue-firstleg/firstleg/src/main/resources/openapi/phase3-container-overview-v1.yaml`、`PlatformContainerController`、`ContainerOverviewDtos`、`ContainerOverviewService`、`LoadingListService`。
|
||||
|
||||
| 能力标识 | 冻结路径与字段 | 权限/并发 | 状态 |
|
||||
|---|---|---|---|
|
||||
| `container-overview` | `GET /api/platform/v1/containers/{id}/overview`;聚合 container、loadingPlanId、PDA 摘要、documents、exception/history、timeline | `platform:firstleg:container:list`;旧 `container:view` 已移除 | 已冻结 |
|
||||
| `pda-progress-exception-summary` | PDA `taskStatus/workflowStatus`、任务 ID/版本、明细计数、`photoCounts`、`photos`(含 fileId/status/downloadPath)及异常原因;照片下载为 `GET /api/platform/v1/containers/{id}/pda/photos/{fileId}/download` | 随 overview 查看权限;下载复核柜次、计划、入库单与文件归属 | 已冻结 |
|
||||
| `container-abnormal-history` | `POST/DELETE /api/platform/v1/containers/{id}/exception`;请求使用 overview 返回的 container.version、必填原因和幂等键 | `platform:firstleg:container:edit`;版本冲突 fail-closed | 已冻结 |
|
||||
| `container-documents` | 通用查询、multipart 上传和受控文件下载仅支持 DO/PU;下载透传已校验 Content-Type,非法类型回退 `application/octet-stream`,并返回 UTF-8 文件名、`no-store` 和内容长度 | 查询/下载用 `platform:firstleg:container:list`,上传用 `platform:firstleg:container:edit`;旧 `container:view` 已移除;下载校验柜次、类型、文件 ID 及文件服务 tenant/business 归属 | 已冻结 |
|
||||
| `do-pu` | `DELIVERY_ORDER`、`PICKUP_ORDER` 通用查询/上传/下载 | 同 `container-documents` | 已冻结 |
|
||||
| `transport-trajectory-log` | overview timeline 的事件类型、详情、操作者、发生时间;服务端升序 | 随 overview 查看权限 | 已冻结 |
|
||||
|
||||
### 最终安全分流
|
||||
|
||||
1. overview 与通用 documents 只覆盖 `DELIVERY_ORDER`、`PICKUP_ORDER`,不得向通用路径传清关或报关类型。
|
||||
2. 目的港清关使用 `/api/platform/v1/containers/{id}/clearance` 及其专用上传、完成动作,权限为 `platform:firstleg:customs:manage`。
|
||||
3. 出口报关使用 `/api/platform/v1/first-leg/loading-lists/{planId}/customs` 及其专用上传、完成动作;查询使用 `platform:firstleg:loading-list:list`,旧 `loading-list:view` 已移除,写入使用 `platform:firstleg:customs:manage`。
|
||||
4. 清关和出口报关分别验证完成态禁止替换,不能用 DO/PU 通用上传替代。
|
||||
5. 下载允许透传经校验的 Content-Type,非法值回退二进制类型;同时必须保留 UTF-8 文件名、`no-store`、内容长度及资源归属复核。
|
||||
|
||||
## 自动化落地门禁
|
||||
|
||||
真实环境脚本只有在对应能力“已冻结=是”后才能加入请求步骤,并必须满足:
|
||||
|
||||
1. 环境地址、账号和令牌只从环境变量读取。
|
||||
2. 默认不执行;必须通过显式运行参数开启真实 HTTP。
|
||||
3. 只通过业务 API 造数,不连接数据库,不调用 Jenkins。
|
||||
4. 支持按本次运行标识检索资源,避免误用历史数据;清理动作仅在契约明确且安全时启用。
|
||||
5. 输出脱敏 JSON 报告,逐请求记录 HTTP 状态、业务码、`requestId`、`traceId` 和资源 ID。
|
||||
6. 对未冻结能力或冻结来源不一致输出 `BLOCKED_CONTRACT`,不得以跳过后仍报告全链通过。
|
||||
|
||||
## 当前阻断
|
||||
|
||||
| 阻断 | 影响 | 解除条件 |
|
||||
|---|---|---|
|
||||
| 测试环境未获得部署授权且本任务禁止部署 | 无法验证环境是否已包含依赖实现 | 人工部署明确提交后,再执行获授权的验收轮次 |
|
||||
| 未提供测试环境凭据和两组隔离身份 | 无法执行跨客户/跨仓库/下载鉴权负向用例 | 由总控提供临时验收身份或既有安全注入方式 |
|
||||
|
||||
## Marker 回归增量(ADMIN-API-20260814032734876)
|
||||
|
||||
| 回归项 | 当前冻结事实与自动化断言 | 当前结论 |
|
||||
|---|---|---|
|
||||
| Release 正式 DTO | `POST /api/platform/v1/ocean-bookings/{id}/release` 已冻结;`ReleaseRequest` 必填提单号、船名、航次、ETD、ETA,并保留 `expectedVersion`。HTTP fixture 必须携带五字段;Admin 未填齐不得调用 release | `LANDED`,不是路径阻断 |
|
||||
| PDA overview 状态语义 | PDA 任务的 `taskStatus=LOADING` 与业务流转 `workflowStatus=AWAITING_REVIEW` 必须分字段返回;进度 100%、未解决数为 0 且任务仍为 `LOADING` 时必须明确为 `AWAITING_REVIEW` | 后端 DTO/OpenAPI/聚合已回传;`LANDED`,待环境 HTTP 验收 |
|
||||
| PDA overview 照片下载 | 对 `photos[]` 每个服务端 `downloadPath` 执行真实鉴权 GET;仅接受站内 `/api/` 路径、HTTP 200、非空二进制和非 JSON/HTML Content-Type | HTTP 回归已准备;待获授权环境验收 |
|
||||
| 客户公开名称一致性 | `customerId` 筛选后的订舱、拖车和预装列表/详情必须显示 IAM `tenantName`,不得优先 `legalName`;列表、详情及关联名称一致 | 列表筛选与拖车预约新增表单已统一 `tenantName`;`LANDED`,待人工筛选回归 |
|
||||
| 已有 `containerNo` 动作语义 | 已有真实柜号时补号动作不可伪装成首次补号;换号前后柜次 ID、PDA taskId、loadingPlanId 和证据归属必须稳定 | Admin 已按柜号是否存在显示“录入集装箱号/修改集装箱号”,后端 HTTP fixture 已锁定身份稳定;`LANDED` |
|
||||
| 订舱/拖车详情关联名称 | 详情中的客户、柜次、订舱及关联资源名称必须来自正式详情响应,并与同 ID 列表显示一致 | 后端详情已返回稳定名称字段,Admin 使用详情快照与受控候选回显;`LANDED` |
|
||||
| 拖车附件闭环 | `POST /truck-appointments/{id}/attachments` 引用、`POST /truck-appointments/{id}/attachments/upload` 上传关联与 `DELETE /truck-appointments/{id}/attachments/{attachmentId}` 已冻结 | Admin 已提供选择文件、上传并关联、列表及删除入口,HTTP 删除后回查已覆盖;`LANDED` |
|
||||
| 中文状态、弹框与 390px 布局 | 列表/详情状态必须中文;release、附件、柜号动作使用正式弹框;390px 下字段、按钮、弹框不横向溢出或遮挡 | `AWAITING_REVIEW`、照片类型、确认按钮已中文化,放舱/改船/附件弹框已落地;桌面与 390px 浏览器无横向溢出;`LANDED` |
|
||||
|
||||
说明:`BLOCKED_CONTRACT` 仅标记明确缺失的 DTO 字段或 Admin 承载,不把已存在的 release、拖车附件 API 路径降级为未冻结能力。
|
||||
|
||||
## 订舱物流渠道与柜次隔离增量
|
||||
|
||||
| 验收项 | 自动化断言 | 当前结论 |
|
||||
|---|---|---|
|
||||
| Admin 渠道选择 | 订舱新增/编辑不允许自由输入 `channelCode/channelName`;选择起运仓后使用渠道下拉,查询必须携带 `originWarehouseId` | `LANDED`:Admin 使用受控渠道下拉并调用正式平台渠道接口;Admin 与根静态合同均锁定渠道选择正向及自由输入负向 |
|
||||
| 平台渠道目录 | `GET /api/platform/v1/ocean-bookings/channels?originWarehouseId=...` 只返回当前 ACTIVE 价格簿渠道;HTTP fixture 记录本轮 marker、`originWarehouseId` 与服务端路径,不借 Merchant 身份或历史资源 | OpenAPI 已冻结;真实查询生产者已发布 `createdResources.platformLogisticsChannels` |
|
||||
| 双有效渠道 fixture | 跨渠道负向必须使用同一起运仓下两个真实有效渠道;只有一个有效渠道时输出 `BLOCKED_FIXTURE`,禁止派生 `-OTHER` 伪渠道 | 脚本门禁与正式渠道生产者已落地;待环境数据验证是否存在双渠道 |
|
||||
| 船公司与物流渠道独立 | `shippingCompanyId/shippingCompanyName` 与渠道选择分别建模,不用船公司字段代替渠道字段 | `LANDED`:Admin 与写请求模型分别承载船公司和物流渠道,静态合同已转绿 |
|
||||
| 关联柜继承渠道 | 港口 link 后货柜详情 `channelCode` 必须等于 RELEASED 订舱的有效渠道;异渠道入库单不能分配到该柜次 | HTTP 断言已准备;异渠道负向只使用真实 ACTIVE 渠道;写 DTO 不发送服务端拥有的 `channelName` |
|
||||
|
||||
## 订舱资料字段与可选客户增量
|
||||
|
||||
事实来源:原型 `prototype-src/modules/06-containers.html`、P3-Q14、`OceanBookingDtos.DraftData`、`ocean-bookings-v1.yaml`、Admin `OceanBookingDetailView.vue` 与 `OceanBookingDraftData`。
|
||||
|
||||
| 字段/链路 | 原型与阶段时序 | 自动化断言 | 当前结论 |
|
||||
|---|---|---|---|
|
||||
| `serviceTerm` | 原型第 516 行以 `*` 标记主要运输条款必填;P3-Q14 未删除该业务快照 | Admin 必填自由文本;Java `@NotBlank`;OpenAPI `required` 且非 nullable;模块基线和统一 SQL 均为 `NOT NULL`;不保留无来源的 `CY-DOOR/DOOR-CY/DOOR-DOOR` 自造字典;验收 fixture 使用原型展示值 `CY-CY` | `LANDED` |
|
||||
| `freightTerm` | 原型第 518 行以 `*` 标记运费条款必填;示例值为 `NINGBO`,不构成枚举事实来源 | Admin 必填自由文本;Java `@NotBlank`;OpenAPI `required` 且非 nullable;模块基线和统一 SQL 均为 `NOT NULL`;不保留无来源的 `PREPAID/COLLECT` 自造字典;验收 fixture 使用原型展示值 `NINGBO` | `LANDED` |
|
||||
| 可选客户 | 原型第 527 行“客户/公司名称”无必填标记;当前产品确认允许平台先建订舱后关联客户 | Admin 可清空选择;前端类型、Java DTO 与 OpenAPI 均允许 `customerId/customerName` 同时为空,单边填写必须拒绝 | `LANDED` |
|
||||
| 可选客户合同 | 不以历史客户或占位 ID/名称替代可空契约 | 共享 builder 保留无客户能力;当前默认 `ocean-bookings` 主链使用正式可选客户字段并验证 DRAFT/RELEASED,不生成柜次 | 离线合同已覆盖;独立无客户 HTTP 链待总控决定 |
|
||||
| 指定客户隔离链 | 保留来自本轮入库单的正式客户范围 | `phase3-container-loading` 与既有订舱主链继续断言客户、仓库、渠道一致和跨渠道拒绝,不借历史资源 | 已准备,待部署后 HTTP 验收 |
|
||||
| 提单号、船名、航次、ETD、ETA | 原型存在相关展示/录入字段;DRAFT 可部分保存,release 前必须补齐 | 五字段属于持久化 DRAFT;`ReleaseRequest` 只传 `expectedVersion`,服务端校验并冻结已存快照;RELEASED 不可修改 | `LANDED_STATIC` |
|
||||
| 单证号 | 原型第 529 行存在“单证号”,但当前阶段 DTO/OpenAPI 未冻结对应写字段 | 不猜字段名或复用提单号;本轮不扩展写契约 | 非本轮能力,不标记接口阻断 |
|
||||
|
||||
离线合同:`ocean-booking-prototype-contract.test.mjs` 锁定原型证据、跨端可选客户、DRAFT 编辑与 release 完整性门禁;`ocean-booking-fixture-contract.test.mjs` 与 `full-regression-entry-contract.test.mjs` 锁定 `containerRequirements` 和默认编排。订舱正式状态仅为 DRAFT/RELEASED。
|
||||
|
||||
## 内部模拟柜关联真实订舱增量
|
||||
|
||||
事实来源:`PlatformContainerController`、`ContainerDtos`、`ContainerService`、`OceanBookingService`、`OceanBookingMapper`、`firstleg-v1.yaml`、`ocean-bookings-v1.yaml`。
|
||||
|
||||
| 验收项 | 自动化断言 | 当前结论 |
|
||||
|---|---|---|
|
||||
| 正式订舱列表 | 仅允许 `DRAFT/RELEASED`;DRAFT 可编辑删除,RELEASED 不可编辑删除;内部模拟柜不进入订舱列表 | 契约与 HTTP fixture 已落地,待部署后验证 |
|
||||
| 新增内部模拟柜 | `POST /api/platform/v1/containers` 只接收正式装柜仓库、当前 ACTIVE 物流渠道、箱型、容量和限重;不接收真实柜号或订舱;服务端生成稳定 `containerBookingId/cabinetNo` | 契约与 HTTP fixture 已落地,待部署后验证 |
|
||||
| 订舱柜型需求 | `POST /ocean-bookings` 保存 `containerRequirements(type/kind/quantity/capacityCbm/maxWeightKg)`;不接收真实柜号,不创建货柜/allocation | DTO/OpenAPI/静态合同及 HTTP fixture 已落地,待部署后验证 |
|
||||
| 港口逐柜关联 | 真实柜号取得后,对已有 `SIMULATION/ACTIVE` 柜调用 `{oceanBookingId,requirementId,containerNo,expectedVersion}`;模拟柜 `containerBookingId/cabinetNo/loadingPlan/items` 不变 | 契约与 HTTP fixture 已落地,待部署后验证 |
|
||||
| ACTIVE 唯一操作身份 | link 直接补全原模拟柜并创建 allocation;不存在另一条真实柜或 MERGED 中间记录 | 静态合同与 HTTP 列表/详情断言已落地,待部署后验证 |
|
||||
| 隔离与唯一占用 | 跨仓、跨渠道、箱型/容量/限重/客户范围不匹配、需求超量或重复柜号拒绝;所有失败保持柜、计划、明细、allocation 和列表零漂移 | 静态合同已锁定;双渠道和主要 HTTP 负向待部署后验证 |
|
||||
| 首次关联不可逆门禁 | 存在 PDA、有效装柜证据、业务单证或已进入 `LOADING/COMPLETED` 时首次 link 拒绝 | 服务端静态门禁已锁定;需部署后以独立 marker fixture 验证 |
|
||||
| 解绑与换绑 | 服务端仍仅允许完全空的 `WAIT_LOADING` 合并柜执行原子 unlink,并恢复来源为 ACTIVE;一旦已有排货、PDA、证据或单证事实,unlink/rebind 均拒绝 | 静态门禁已锁定;排货后负向 HTTP fixture 已落地,待部署后验证 |
|
||||
| 全量编排 | 默认入口先运行 `phase3-container-loading` 完成“模拟柜新增 -> 同仓同渠道排货 -> 首次 link -> PDA”,再由证据、finalize、出仓模块沿本轮 marker 的稳定 ID 继续;禁止历史数据和 mock 回退 | Node 入口合同已锁定,待默认全量 HTTP 验证 |
|
||||
|
||||
离线合同:`container-simulation-association-contract.test.mjs` 锁定跨层契约及全量顺序;`phase3-producer-chain-contract.test.mjs`、`phase3-order-splitting-contract.test.mjs`、`ocean-booking-channel-contract.test.mjs` 锁定生产者只使用 DRAFT/RELEASED、需求关联且不在订舱阶段自动建柜。
|
||||
Reference in New Issue
Block a user