Compare commits

59 Commits
Author SHA1 Message Date
ouyangxq 2f8d59c871 docs(admin): include referenced measurement dialog sample 2026-10-20 10:34:00 +08:00
ouyangxq 298b6b5ac4 docs(admin): record dialog rollout and first twenty screenshot paths 2026-10-20 10:32:47 +08:00
ouyangxq ca3f0c01ef docs(fees): record default price release and expanded verification 2026-10-19 21:24:43 +08:00
ouyangxq 94bbdea386 优化 2026-10-19 17:56:33 +08:00
ouyangxq c116bcfe8a docs(release): verify first-leg optional courier tracking over HTTP 2026-10-19 17:54:12 +08:00
ouyangxq 6426c020a1 docs(first-leg): allow optional courier tracking on express drafts 2026-10-19 17:46:01 +08:00
ouyangxq 7ec2f45a10 docs(release): verify unified Admin and Client transport forms 2026-10-19 15:53:52 +08:00
ouyangxq c6a3b9ee0e docs(transport): define identical Admin and Client demand form contract 2026-10-19 15:51:05 +08:00
ouyangxq 78b20e53a5 docs(release): record TEST truck and looseboard verification 2026-10-19 15:29:59 +08:00
ouyangxq afd42e4e6d docs(looseboard): define split route contacts and required local times 2026-10-19 15:11:48 +08:00
ouyangxq cf8cb6dc48 docs(trucking): define standalone truck demand contract 2026-10-19 14:38:48 +08:00
ouyangxq d0fac0118f 优化 2026-10-19 10:40:53 +08:00
ouyangxq aa904e4a2d docs(selfop): define bounded outbound recovery and failure diagnostics 2026-10-16 11:05:59 +08:00
ouyangxq c446410cb2 docs(selfop): record backend Excel export deployment and verification 2026-10-15 15:17:05 +08:00
ouyangxq b778b52166 docs(selfop): record turnover rate header sorting and test release 2026-10-15 14:33:32 +08:00
ouyangxq 54d33faaa4 docs: record TEST inventory history rollout and verified turnover 2026-10-15 14:20:01 +08:00
ouyangxq 265e270e72 docs(selfop): freeze historical reconstruction contract and local verification 2026-10-15 13:31:19 +08:00
ouyangxq 29d8997680 docs: record turnover multi-owner export TEST release 2026-10-15 11:20:57 +08:00
ouyangxq fe23b1d7a8 docs(selfop): record zero stock filter release and verification 2026-10-15 10:34:50 +08:00
ouyangxq d5c0a1e1d6 docs(selfop): record volume sorting and ranking release verification 2026-10-14 18:25:30 +08:00
ouyangxq 6f2577c372 优化 2026-10-14 18:13:16 +08:00
ouyangxq 74abdb8b10 docs(selfop): record volume release and verified customer totals 2026-10-14 18:02:29 +08:00
ouyangxq e81f07053a docs(selfop): define volume metrics and record idle planner release 2026-10-14 17:48:54 +08:00
ouyangxq 51ac4756b6 docs(selfop): record master data release and verified synchronization 2026-10-14 17:13:42 +08:00
ouyangxq 6d557e36c6 docs(selfop): define customer and product directory integration 2026-10-14 16:15:41 +08:00
ouyangxq a4199bdc28 docs: record final turnover and transit TEST release 2026-10-14 14:16:18 +08:00
ouyangxq 7164105623 docs(self-operated): include transit stock and simplify ranking explanations 2026-10-14 14:08:54 +08:00
ouyangxq 34c65c8c7c docs(self-operated): align turnover eligibility and explicit zero stock 2026-10-14 14:00:38 +08:00
ouyangxq 62de8d1407 docs(test): record matched analytics and warehouse release verification 2026-10-14 12:54:09 +08:00
ouyangxq 5510638b4d docs(self-operated): align selected ranges and inventory assessment contracts 2026-10-14 12:39:38 +08:00
ouyangxq f6d329cdb0 docs: verify final Admin batch deployment and collection continuity 2026-10-14 11:27:32 +08:00
ouyangxq 52c2c0b54a docs: record October 14 batch deployment and final frontend gate 2026-10-14 11:24:54 +08:00
ouyangxq 8d6db2787b 优化 2026-10-14 11:02:49 +08:00
ouyangxq b768145b22 优化 2026-10-14 00:06:59 +08:00
ouyangxq b472dadd61 优化 2026-10-09 17:36:27 +08:00
ouyangxq d89e8ec16c 优化 2026-10-09 12:40:00 +08:00
ouyangxq 0a4dd606f8 优化 2026-10-09 11:47:22 +08:00
ouyangxq acafab11d6 优化 2026-10-09 11:43:36 +08:00
ouyangxq d91a28e7ee 优化 2026-10-09 11:10:40 +08:00
ouyangxq c521f50a81 docs: record verified TEST recovery and gray release completion 2026-10-09 10:38:30 +08:00
ouyangxq 1ceaf67718 docs: record current TEST releases and export permission smoke 2026-10-08 20:52:52 +08:00
ouyangxq 8832e9d4ed 优化 2026-10-08 19:09:34 +08:00
ouyangxq c0d1e1a0ba 优化 2026-10-08 18:20:03 +08:00
ouyangxq c825c14ac7 优化 2026-10-08 17:08:00 +08:00
ouyangxq 40224c34a1 优化 2026-09-30 17:13:15 +08:00
ouyangxq f9ba0e17c6 优化 2026-09-30 15:16:42 +08:00
ouyangxq 32677551a7 优化 2026-09-30 14:01:55 +08:00
ouyangxq 407abd634c 优化 2026-09-29 19:55:27 +08:00
ouyangxq 606abeb2c6 优化 2026-09-29 18:47:39 +08:00
ouyangxq 16ecfae84d 优化 2026-09-29 18:06:20 +08:00
ouyangxq 19943112c0 优化 2026-09-29 17:55:58 +08:00
admin e579ca2d3a Merge pull request 'Test' (#1) from test into main
Reviewed-on: #1
2026-09-28 16:01:15 +08:00
ouyangxq df6f434550 docs: align firstleg release contracts and add sailing plans 2026-09-28 15:04:36 +08:00
ouyangxq a4c9ca162a 优化 2026-09-24 17:02:32 +08:00
ouyangxq 5b9f6dc3c1 优化 2026-09-24 14:09:45 +08:00
ouyangxq d8be2ccdef 优化 2026-09-24 13:43:53 +08:00
ouyangxq 6116ad61e1 优化 2026-09-24 09:39:55 +08:00
ouyangxq 005c14a960 优化 2026-09-23 18:26:07 +08:00
ouyangxq 37b143cc2e 优化 2026-09-23 17:47:52 +08:00
92 changed files with 14328 additions and 3883 deletions
+12 -1
View File
@@ -17,6 +17,17 @@
- 禁止在 `apps/*/`、`baiyue-firstleg/` 及业务模块内部新增 `.codex-temp/`、`.codex-tmp/`、`worktree/` 或类似项目副本。遗留目录须先确认没有运行进程和唯一证据,再按精确路径清理。 - 禁止在 `apps/*/`、`baiyue-firstleg/` 及业务模块内部新增 `.codex-temp/`、`.codex-tmp/`、`worktree/` 或类似项目副本。遗留目录须先确认没有运行进程和唯一证据,再按精确路径清理。
- 端口冲突通过停止已知旧进程或指定其他端口解决,不得复制项目。普通验证应直接覆盖当前未提交修改,不为获得“干净目录”绕开真实变更。 - 端口冲突通过停止已知旧进程或指定其他端口解决,不得复制项目。普通验证应直接覆盖当前未提交修改,不为获得“干净目录”绕开真实变更。
## 本机重型检查与多对话限流
- Windows 本机的测试、类型检查、构建、依赖安装和 Maven 命令统一经 `baiyue-firstleg/scripts/local-check.ps1`(PowerShell 7)执行。锁位于当前用户 `%LOCALAPPDATA%/Chongchong/LocalChecks/`,与工作目录和对话无关;同一用户下使用该入口的任务同时只有一个执行,等待者每 15 秒提示占用。它是入口级互斥,不拦截绕过入口的命令,也不会接管已经运行的任务。
- 在工作区根使用:`& ./baiyue-firstleg/scripts/local-check.ps1 -WorkingDirectory ./apps/admin-web -Label 'Admin typecheck' -Command @('pnpm', 'typecheck')`。定向 Vitest 示例:`-Command @('pnpm', 'exec', 'vitest', 'run', 'src/目标.test.ts')`;后端示例:`-WorkingDirectory ./baiyue-firstleg -Command @('mvn', '-pl', '目标模块', '-am', 'test-compile')`。参数使用数组,不拼接命令字符串。
- 查看占用:`& ./baiyue-firstleg/scripts/local-check.ps1 -Status`。默认最多排队 900 秒(`-WaitSeconds`),执行最多 1200 秒(`-TimeoutSeconds`)。排队超时退出 75 且不启动检查;执行超时退出 124 并回收本次进程树;其他情况透传命令退出码。锁由操作系统文件句柄维护,不删除锁文件抢占。正常结束、超时和包装器强制退出均由 Windows Job Object 回收本次后代;不按 Node/Java 进程名清理其他任务。
- 子进程默认设置 Vitest 最多 2 个 worker;Node 单进程堆上限 2048MB;Java 单进程堆上限 1536MB、可见处理器 2 个。直接运行 `node --test` 时自动补 `--test-concurrency=2`;直接运行 Maven 时补 `-T 1 -DforkCount=1 -DreuseForks=true`,拒绝重复指定这些并发参数。嵌套 shell/自定义脚本不得另行提高并发、覆盖限制或并发启动重型任务;经包管理器间接调用 Node 内置测试时,在该测试命令中显式保留 `--test-concurrency=2`。这些是每进程限制,并非整个进程树的总内存限额。
- 前后端全量入口 `backend-full-regression.ps1`、`frontend-full-regression.ps1` 执行时整批占一个名额,DryRun 不占用。已在入口保护下的批次执行原始命令,不重复申请锁;入口会拒绝嵌套调用,避免互相等待。
- 每个任务先完成必要的定向检查;批次收尾再统一执行应用要求的全量门禁,不因排队取消必要验证。复用结果前核对命令、目录、相关源码/依赖/配置均相同;验证期间相关输入变化则作废重跑。入口仅保存最近一次执行摘要,不自动计算代码快照、不自动跳过测试,也不保证先来先执行。
- 本机 `owner.json`、`last-result.json` 仅保存检查名称、目录、工具、PID、时间和退出码,不保存命令参数、凭据或测试输出;名称不得包含秘密。摘要不是业务/部署事实来源。无需凭据,不访问网络、数据库或部署环境;被包装命令原有的网络/写入能力及授权要求不变。
- 只读检索和互不冲突的编辑可并行;开发服务按应用复用已有实例,不纳入短任务队列,也不通过本入口启动常驻服务。已有运行任务由所属对话收尾;本入口不自动终止它们。
## 当前开发阶段 ## 当前开发阶段
- 项目尚未上线,没有需要兼容的生产存量数据、线上客户端或已发布接口版本;所有代码与契约直接收敛到当前确认目标,用户确认上线或存在不可变外部契约后才重新建立版本兼容和升级规则。 - 项目尚未上线,没有需要兼容的生产存量数据、线上客户端或已发布接口版本;所有代码与契约直接收敛到当前确认目标,用户确认上线或存在不可变外部契约后才重新建立版本兼容和升级规则。
@@ -28,7 +39,7 @@
## 联调、部署与数据库 ## 联调、部署与数据库
- 默认只准备代码、验证结果和人工部署步骤,不触发 Jenkins、不启动本地 Java/Nacos/数据库。开发全流程总控可按 `开发环境独立任务协作登记.md` 的授权操作开发数据库、部署开发环境并执行开发环境真实 HTTP;登记专项可按 `独立任务协作登记.md` 的持续授权查询和修改用户指定的测试数据库。两类授权不得跨环境复用,也不得自动扩大到 Jenkins 或生产环境。 - 默认只准备代码、验证结果和人工部署步骤,不触发 Jenkins、不启动本地 Java/Nacos/数据库。开发全流程总控可按 `开发环境独立任务协作登记.md` 的授权操作开发数据库、部署开发环境并执行开发环境真实 HTTP;登记专项可按 `独立任务协作登记.md` 的持续授权查询和修改用户指定的测试数据库。两类授权不得跨环境复用,也不得自动扩大到 Jenkins 或生产环境。
- 只有用户在当前轮明确授权指定环境、服务和提交时,才可部署或执行 HTTP 验收;测试数据库的读写例外仅适用于登记表中已持续授权的总控与专项,并遵守其中的职责和破坏性操作门禁。 - 只有用户在当前轮明确授权指定环境、服务和提交时,才可部署或执行 HTTP 验收;同一环境和服务的非破坏性写入可复用本轮授权,删除、重置、执行 SQL、部署或发布仍逐项授权。测试数据库的读写例外仅适用于登记表中已持续授权的总控与专项,并遵守其中的职责和破坏性操作门禁。
- 环境地址、凭据和 Token 不写入源码或 `AGENTS.md`。接口不可用或契约不一致时记录路径、状态、错误码、`requestId`/`traceId` 和阻断原因,不回退到模拟成功。 - 环境地址、凭据和 Token 不写入源码或 `AGENTS.md`。接口不可用或契约不一致时记录路径、状态、错误码、`requestId`/`traceId` 和阻断原因,不回退到模拟成功。
- 测试环境联调、部署和验收命令读取 `测试环境Jenkins部署指南.md`;开发全流程只按 `开发环境独立任务协作登记.md` 的授权与目标项目指引执行,不把测试 Jenkins 流程当作开发部署入口。 - 测试环境联调、部署和验收命令读取 `测试环境Jenkins部署指南.md`;开发全流程只按 `开发环境独立任务协作登记.md` 的授权与目标项目指引执行,不把测试 Jenkins 流程当作开发部署入口。
@@ -33,6 +33,7 @@ Admin 与 Client 已向客户讲解或确认过的页面,必须以对应原型
### Admin 已确认布局基线 ### Admin 已确认布局基线
- Admin 所有弹窗的统一目标风格见 [Admin 统一弹窗规范](Admin高密度界面规范.md#弹框与表单)(2026-10-19 测量弹窗样板)。按大模块逐组盘点、实现和截图确认;在已确认范围内优先采用该规范的外观与密度,原业务字段、权限、提交逻辑以及独立页面/弹框/抽屉承载方式继续逐操作核对。
- 订单样板及国内仓样式统一采用 [Admin 高密度界面规范](Admin高密度界面规范.md)。其已确认的密度、容器和页签图标规则优先于历史原型中的对应视觉;字段、业务分组、权限、操作语义与页面/弹框/抽屉承载方式继续逐操作核对。该规范不表示其他页面已完成验收。 - 订单样板及国内仓样式统一采用 [Admin 高密度界面规范](Admin高密度界面规范.md)。其已确认的密度、容器和页签图标规则优先于历史原型中的对应视觉;字段、业务分组、权限、操作语义与页面/弹框/抽屉承载方式继续逐操作核对。该规范不表示其他页面已完成验收。
- Admin 是高信息密度业务系统。保留原型字段、顺序、业务分组和交互语义,但普通短字段优先使用连续白底、多列键值网格、描述表或紧凑列表,不把“一个标签 + 一个值”做成独立卡片。 - Admin 是高信息密度业务系统。保留原型字段、顺序、业务分组和交互语义,但普通短字段优先使用连续白底、多列键值网格、描述表或紧凑列表,不把“一个标签 + 一个值”做成独立卡片。
- 详情页顶部尽量合并返回、标题、核心状态和主要操作;路由壳层已显示标题时正文不重复。状态或流程结论只保留一个主要视觉落点,除真实错误、阻断或危险外不叠加大面积彩色横幅。 - 详情页顶部尽量合并返回、标题、核心状态和主要操作;路由壳层已显示标题时正文不重复。状态或流程结论只保留一个主要视觉落点,除真实错误、阻断或危险外不叠加大面积彩色横幅。
+132
View File
@@ -0,0 +1,132 @@
# Admin 列表样式推广核对记录
## 本轮依据与边界
2026-09-30,用户确认排车列表样式后授权按客户管理、国内仓、货柜管理、海外仓顺序推广;特殊页面保留待人工确认。直接视觉依据为本轮截图 `41fea1ee-f30a-46db-97b0-82ec96846ec7/image-1.png` 与 [排车样板](Admin排车列表样式试点.md)。仅修改测试环境工作区 `apps/admin-web`,不部署或发布。
统一布局:左侧列表名称、右侧原业务按钮与字段设置,搜索和表格位于同一连续卡片。仅列表操作列采用蓝色普通文字、红色危险文字、悬停无下划线;查询、顶部、弹框按钮不变。列显隐、排序和拖动宽度使用公共浏览器偏好存储。保持所有业务字段、状态、权限和事件,不改变详情、新增、编辑、审核、文件预览与删除确认的承载方式。
## 修改前页面与操作矩阵
以下实现路径均相对 `apps/admin-web/src/modules/`。列表变化依据上述截图;其它操作以现有组件和事件为核对入口,保持原样,未定义的新承载方式不在本轮引入。
| 模块 | 页面 / 入口 | 当前实现与操作证据 | 本轮结论 |
|---|---|---|---|
| 客户管理 | 客户列表 `/customers` | `customers/pages/CustomersView.vue`:`customerRowActions`、`handleCustomerRowAction`、`openCreate`,客户详情路由及编辑/审核/重置密码弹框 | 接入连续列表;详情、新增、编辑、审核、资质与确认操作保持 |
| 客户管理 | 海外仓阶梯费用 | `customers/pages/OverseasStorageFeesView.vue`:`openEdit`、`save`,费用编辑 AppDialog | 接入连续列表;费用编辑弹框保持 |
| 国内仓 | 订单列表 | `unified-orders/pages/UnifiedOrdersView.vue`:状态页签、`unifiedOrderRowActions`、详情分支及批量审核、导入、扣货与文件入口 | 仅列表分支接入;详情和各弹框保持 |
| 国内仓 | 订单测量 / 测量数据审核 | `inbounds/components/InboundTaskList.vue`:`taskLabel`、客户查询警告、测量和审核选择事件 | 两个路由共用列表接入;作业弹框和确认保持 |
| 国内仓 | 预装清单 | `loading-lists/components/LoadingListsView.vue`:`mode`、列表权限判断、清单行操作、详情导航 | 接入连续列表;权限错误态和详情保持 |
| 国内仓 | 库位管理 | `warehouse-resources/locations/pages/LocationsView.vue`:仓库加载与列表分别失败、编辑与删除确认 | 接入连续列表;独立错误提示、维护弹框和确认保持 |
| 国内仓 | 托盘管理 | `warehouse-resources/pallets/pages/PalletsView.vue`:仓库加载、新增/编辑/停用/删除行操作 | 接入连续列表;维护弹框和确认保持 |
| 国内仓 | 整柜业务 | `domestic-containers/pages/DomesticContainersView.vue`:入库/出库/库存页签、库存汇总及维护入口 | 三个视图共用连续列表,页签、汇总和原操作保持 |
| 国内仓 | 船期日历 | `sailing-calendar/pages/SailingCalendarView.vue`:日历和渠道/模板/船期管理工作区 | 保留现状;日历布局待人工确认 |
| 货柜管理 | 订舱列表 | `ocean-bookings/pages/OceanBookingsView.vue`:列表查询、行操作和订舱资料入口 | 接入连续列表;新建、编辑、详情、放舱及文件保持 |
| 货柜管理 | 拖车列表 | `trucking/pages/TruckAppointmentsView.vue`:拖车查询和行操作 | 接入连续列表;创建、编辑、详情和确认保持 |
| 货柜管理 | 送柜报关 / 清关提柜 | `container-loading/pages/ContainersView.vue`:`workbench` 双模式、在途/历史页签、行操作、预计到仓维护 | 两个工作台共用列表接入;所有详情、节点、订舱、资料、邮件和确认保持 |
| 海外仓 | 尾程订单 | `overseas-warehouse/pages/LastMileOrdersView.vue`:普通列表与柜子工作台分支、行操作和柜级计划弹框 | 普通列表可接入;柜子工作台保留业务结构并单独核对 |
| 海外仓 | 入库单 | `overseas-warehouse/pages/InboundOrdersView.vue`:预约、行操作及详情 | 接入连续列表;预约和详情保持 |
| 海外仓 | 海外库位 | `overseas-warehouse/pages/LocationsView.vue`:普通/A0/虚拟库位资格和维护操作 | 接入连续列表;受保护资格和确认保持 |
| 海外仓 | 排车列表 | `overseas-warehouse/pages/DispatchesView.vue` 已确认样板 | 保留样板;字段设置和列宽偏好保持 |
| 海外仓 | 出库单 | `overseas-warehouse/pages/OutboundsView.vue`:按类型新建、取消、出库详情和选择作业弹框 | 仅主列表接入;新建候选及各弹框保持 |
| 海外仓 | 派送单 | `overseas-warehouse/pages/DeliveryOrdersView.vue`:行操作、资料汇总和签收入口 | 接入连续列表;签收、详情和资料保持 |
| 海外仓 | 换标单 | `overseas-warehouse/pages/RelabelOrdersView.vue`:新增、详情与编辑入口 | 接入连续列表;表单与详情保持 |
| 海外仓 | 托盘管理 | `overseas-warehouse/pages/PalletsView.vue`:详情、单张打印及原维护入口 | 接入连续列表;打印尺寸和其它操作保持 |
| 海外仓 | 库存管理 | `overseas-warehouse/pages/InventoryView.vue`:库存汇总、导出、详情和行操作 | 接入连续列表;汇总数据、导出及详情保持 |
| 海外仓 | 退货库存 / 退货箱号 | `overseas-warehouse/pages/ReturnInventoryManagementView.vue` 两种 `mode` | 沿实际公共列表组件接入;明细和作业保持 |
| 海外仓 | 进销存记录(关联入口) | `overseas-warehouse/pages/InventoryTransactionsView.vue`:只读边界提示、关系查询、导出 | 接入连续列表;只读边界与关系查询保持 |
## 本轮实现与待确认项
客户管理 2 个、国内仓 7 个、货柜管理 4 个、海外仓 11 个菜单列表已接入;另外接入海外库存关联的进销存记录,共 25 个列表入口(含原排车样板)。包装页面继续复用实际公共列表组件;整柜的三种业务页签、测量与审核双模式、货柜国内/海外双工作台、尾程订单隐藏柜子工作台和退货库存/流水/箱号分支均保留。
船期日历 `/sailing-calendar` 保留原样。日历与渠道/模板/船期管理工作区不等同于标准业务列表;需要人工确认顶部按钮、查询及日历的排列,再决定如何接入。本轮没有隐藏或移除该入口。
尾程订单隐藏柜子工作台仍保留自身卡片与分页,通过公共 `results` 插槽承载。修正了共享表格在自定义工作台或列表加载失败时重置页码的问题;普通列表继续使用原服务端分页。
新增页面的视觉均待人工在 1920×1080、100% 缩放下截图确认;样板截图不代表其余页面视觉已验收。重点核对页签、多字段查询、长编号横向滚动、汇总、危险文字、每页数量、字段显隐及拖动后刷新列宽。
## 验证记录
客户管理相关回归 9 个文件、120 项通过;特殊工作台、公共表格和其它受影响回归 7 个文件、180 项通过。源码审计确认已接入页面的原业务点击事件全部保留;除退货列表增加列配置与公共表格导入外,业务脚本保持不变,API 和权限没有修改。退货库存/流水/箱号增加行为回归,覆盖搜索分页、偏好隔离与详情入口。
2026-09-30 最终完整 `pnpm test`:263 个文件、2131 项全部通过。`pnpm build`(包含 `vue-tsc --noEmit`)通过。仅修改本地测试环境代码;未提交、未部署或发布。
## 第二批修改前页面与操作矩阵(2026-09-30)
用户授权继续客户服务、海外仓、财务管理、通用、系统管理等剩余页面;沿当前菜单扩展海外业务和消息入口。上一批海外仓标准列表复核并保持。隐藏原型菜单不启用,首页数据看板不是列表,保留并记录待人工确认。
本批仍只改变主列表布局和操作列外观。下列实现路径相对 `apps/admin-web/src/modules/`;详情、新建、编辑、审核、文件预览、打印及删除/停用确认仍沿原组件、路由和事件,不引入新承载方式。视觉依据与第一批相同。
| 模块 | 页面 / 路由 | 当前列表实现及操作核对入口 | 结论 |
|---|---|---|---|
| 客户服务 / 通用 | 异常订单 `/overseas-warehouse/exception-orders` | `overseas-warehouse/pages/ExceptionOrdersView.vue`:toolbar-actions、actions、related、handlerName、status、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 客户服务 / 通用 | 客户回访 `/overseas-warehouse/customer-visits` | `overseas-warehouse/pages/CustomerVisitsView.vue`:actions、status、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 客户服务 / 通用 | 称重机器 `/general/mojia-sku-sync` | `overseas-warehouse/pages/MojiaSkuSyncView.vue`:toolbar-start、toolbar-actions、actions、sourceCode、kind、image、dimensions、syncStatus、match、measuredAt、failure;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 海外业务 | 海外采购订单 `/overseas-business/purchases` | `overseas-business/pages/PurchaseOrdersView.vue`:actions、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 海外业务 | 本土卡车 `/overseas-business/trucks` | `overseas-business/pages/TransportOrdersView.vue`:toolbar-actions、actions、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 海外业务 | 本土散板 `/overseas-business/looseboards` | `overseas-business/pages/TransportOrdersView.vue`:toolbar-actions、actions、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 财务管理 | 客户账户 `/finance/customer-accounts` | `finance/pages/FinanceCustomerAccountsView.vue`:toolbar-actions、actions、customerName、customerCode、contactName、contactPhone、lastChangedAt、actualBalance、frozenBalance、availableBalance、creditLimit、creditExpiresOn、creditUsed、pendingRechargeCount、status、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 财务管理 | 客户应收应付 `/finance/customer-arap` | `finance/pages/FinanceCustomerArapView.vue`:toolbar-actions、actions、customerName、direction、businessReference、sourceType、supplierName、sourceStatus、status、generated、businessDate、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 财务管理 | 应收款统计表 `/finance/receivable-statistics` | `finance/pages/FinanceReceivableStatisticsView.vue`:toolbar-actions、customerName、totalReceivable、totalReceived、totalOutstanding、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 财务管理 | 客户对账单 `/finance/customer-statements` | `finance/pages/FinanceCustomerStatementsView.vue`:toolbar-actions、actions、status、customerConfirmationStatus、customerName、lastPaymentAt、settled、createdByName、createdAt、submittedAt、reviewedAt、issuedAt、customerConfirmedByName、customerConfirmedAt、updatedByName、updatedAt、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 财务管理 | 结算单应收 `/finance/settlement-receivables` | `finance/pages/FinanceSettlementReceivablesView.vue`:包装页,实际列表为 FinanceFormalSettlementPage 的 kind 双模式;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 财务管理 | 结算单应付 `/finance/settlement-payables` | `finance/pages/FinanceSettlementPayablesView.vue`:包装页,实际列表为 FinanceFormalSettlementPage 的 kind 双模式;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 供应商列表 `/suppliers` | `suppliers/pages/SuppliersView.vue`:toolbar-actions、actions、name、category、truckingScope、carrierCodes、license、status、settlement;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 快递公司 `/master-data/express-companies` | `master-data/express-companies/pages/ExpressCompaniesView.vue`:toolbar-actions、actions、company、website、status、empty、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 往来单位 `/master-data/counterparties` | `master-data/counterparties/pages/PartnersView.vue`:toolbar-actions、actions、partner、type、address、status、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 费用项目 `/master-data/fee-items` | `fee-items/pages/FeeItemsView.vue`:toolbar-actions、actions、feeItem、tradeScope、pickup、warehouse、supplierCategory、allocationFee、description、status、empty、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 海外仓报价 `/overseas-master-data/quotes` | `overseas-master-data/pages/OverseasQuotesView.vue`:toolbar-actions、actions、status;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 汇率管理 `/overseas-master-data/exchange-rates` | `overseas-master-data/pages/ExchangeRatesView.vue`:toolbar-actions、actions、conversion、status;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 车辆列表 `/overseas-master-data/vehicles` | `overseas-master-data/pages/VehiclesView.vue`:toolbar-actions、actions、status、region;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 仓库管理 `/warehouses` | `warehouses/pages/WarehousesView.vue`:toolbar-actions、actions、warehouse、warehouseType、countryCode、address、contact、status、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 船期价格表 `/first-leg-pricing/carrier-rates` | `fba-pricing/carrier-rates/pages/CarrierRatesView.vue`:toolbar-actions、actions、version、scope、status、contents、issues、empty、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 通用 | 下载中心 `/downloads` | `downloads/pages/DownloadCenterView.vue`:pagination-left、actions、type、status、progress、requester、requestedAt、completedAt、expiresAt;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 系统管理 | 用户管理 `/system/users` | `iam/pages/InternalUsersView.vue`:toolbar-actions、actions、roles、status、lastLoginAt、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 系统管理 | 角色权限 `/system/roles` | `iam/pages/RolesView.vue`:toolbar-actions、actions、role、permissionSummary、roleType、status、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 系统管理 | 菜单权限 `/system/permissions` | `iam/pages/PermissionsView.vue`:toolbar-start、toolbar-actions、actions、name、code、endpoint、status、pagination-left;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 系统管理 | PDA版本 `/system/pda-releases` | `pda-releases/pages/PdaReleasesView.vue`:toolbar-start、toolbar-actions、actions、app、packageType、status、mandatory、sizeBytes、createdAt、publishedAt;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 消息入口 | 我的消息 `/notifications` | `notifications/pages/PlatformNotificationsView.vue`:toolbar-actions、pagination-left、actions、category、sentAt、status;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 消息入口 | 消息管理 `/notifications/messages` | `notifications/pages/MessageManagementView.vue`:toolbar-actions、pagination-left、actions、category、scheduledAt、sentAt、status;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
| 消息入口 | 模板管理 `/notifications/templates` | `notifications/pages/MessageTemplatesView.vue`:toolbar-actions、pagination-left、actions、status;原详情/表单/确认保持 | 接入公共连续列表;业务展示与操作保持 |
应收款统计保留月份、客户筛选、汇总、CNY 边界、打印/导出及原打印媒体规则;权限树保留展开、收起、保护提示和树形参数;PDA 版本保留国内/海外应用切换、当前版本事实和发布/停发确认;称重机器保留现有筛选、连接测试、人工推送和分页。这些页面沿实际结构单独处理,不删功能套标准模板。
第二批新增 29 个列表路由,复用 27 个实际列表组件;两个结算单包装路由继续复用 `FinanceFormalSettlementPage`,应收/应付各自保存字段和列宽偏好,本土卡车/散板继续共用原运输订单列表。菜单核对覆盖当前全部正式可见业务列表,加上三个消息入口与库存流水关联入口,共 54 个接入入口;未发现遗漏。隐藏原型菜单保持隐藏。
称重机器从独立 Element 分页改为公共表格分页,保留原 10/20/30/40/50/100 选项、服务端分页和查询条件。新增行为回归验证查询及每页数量变化回到第一页、每页数量变化仅发送一次查询、字段设置可用、列宽重新挂载恢复和原操作入口。PDA 与称重机器原加载中的 `aria-busy` 状态随列表保留。
源码核对确认第二批全部原点击表达式和业务脚本保留,仅清理已移除的装饰图标导入;未修改 API、权限、计算规则、状态或详情/表单承载方式。旧样式断言同步到连续卡片、通知区、纯文字“更多”和无斑马纹;原业务断言继续保留。
## 第二批异常及待确认清单
| 项目 | 当前处理 | 后续确认 |
|---|---|---|
| 首页数据看板 `/dashboard` | 保留原工作区,未套列表布局 | 人工确认是否需要独立调整看板顶部 |
| 船期日历 `/sailing-calendar` | 已按用户截图制作连续工作台版本,保留日历及渠道/模板/船期工作区 | 待人工确认新版按钮、查询与日历排列;见单页收尾记录 |
| 财务统计/打印、结算汇总、权限树、PDA应用切换、供应商分类及尾程柜子工作台 | 沿原结构接入,保留全部业务控件;自动检查通过 | 人工重点核对汇总、页签、树展开、打印和条件切换 |
| 所有新增页面真实视觉 | 未使用 AI 操作页面或截图替代验收 | 待人工 1920×1080、100% 缩放截图确认 |
| 完整测试中的 Vue 编译提示 | 出现 `v-model` 对 `const reactive query` 的非阻断提示;完整测试及构建通过,本轮未扩展修改 | 后续专项核查对应绑定 |
## 第二批验证结果
2026-09-30 完整 `pnpm test`:264 个文件、2133 项全部通过。`pnpm build`(包含 `vue-tsc --noEmit`)通过,`git diff --check` 通过。菜单/包装组件核对和原操作事件审计通过。所有修改均在本地测试环境工作区;未提交、未部署或发布。视觉验收仍待人工截图确认。
## 船期日历单页收尾(2026-09-30)
用户提供当前页面截图 `codex-clipboard-e64ee273-3108-4711-be25-f63785611e59.png`,授权按上述建议制作一版。仅处理测试环境的船期日历;首页数据看板和其它待确认页面留到后续逐页处理。
| 操作 | 截图/当前代码依据 | 本版结论 |
|---|---|---|
| 页头、筛选、日历与当日船次 | 截图显示独立筛选、日历、当日详情卡片;`SailingCalendarView.vue` 的 `calendar-toolbar`、`calendar-layout` | 共用连续容器;左标题/右业务按钮,下面筛选与日历/当日详情;保留月切换、今天、时区和船期数量 |
| 查询与重置 | 原筛选字段绑定、下拉自动查询、关键字回车及 `resetFilters` | 全部保留,重置仍在筛选区 |
| 单次新增/编辑 | 原 `dialogOpen` 居中 760px 表单及 `openCreate`/`openEdit` | 保留原表单与承载方式;页头保留新增单个船次,当日详情新增仍保留 |
| 渠道与周模板/批量生成 | 原 `openManagement` 居中管理工作区 | 按钮移到页头右侧;内部管理表格、生成步骤及权限保留 |
| 船次详情、货量明细、历史、订柜建议 | 原右侧详情、`openVolumeDetail`/`openHistory`/`openBookingAdvice` | 保留原交互和浮层,只合并外层卡片 |
| 复制、取消及批量生成确认 | 原 `copySelected`、`cancelSelected`、`confirmTemplateGeneration` | 原权限、确认、处理中和提示保留;不改业务状态 |
| 文件预览/审核 | 本页面无此类独立入口 | 不新增 |
公共页头及筛选沿 `DataTable appearance="integrated"` 的 `results` 插槽接入日历工作台;无列表列配置,不展示字段设置或虚构分页。日期格紧凑排列,保留日期、数量、航线和容量提示。修改后的视觉待人工在 1920×1080、100% 缩放下截图确认。
本版验证:公共表格与密度合同 51 项通过;新增船期日历行为回归 2 项通过,覆盖月切换、日期/船次选择、关键字查询、重置、失败重试及只读权限。源码审计确认除公共组件导入外业务脚本未变,全部事件和查询绑定保留。完整测试 265 个文件、2135 项通过,构建(含类型检查)及 `git diff --check` 通过。代码版本已完成,未提交、未部署;新版视觉待用户截图确认。
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
# Admin 排车列表一体式布局试点
初次试点仅接入测试环境代码的 `/overseas-warehouse/dispatches`。依据为用户提供截图及 `新版.html` 的 `page-outbound-vehicle`(4472–4484 行);用户明确保留字段设置、搜索与表格不分离。2026-09-30 用户确认样板后授权推广至客户管理、国内仓、货柜管理和海外仓,并继续客户服务、海外业务、财务管理、通用、系统管理及消息列表。范围及例外见 [推广核对记录](Admin列表样式推广核对记录.md)。
船期日历单页收尾按用户当前截图接入相同的页头、筛选和连续容器,通过 `results` 插槽保留日历与当日船次详情。日历不具备表格列配置,明确关闭字段设置且不添加分页;日历日期格和右侧详情布局由业务页维护。
## 修改前核对
| 页面/操作 | 参考布局或承载方式 | 当前实现 | 本轮结论 |
|---|---|---|---|
| 排车列表 | 同一容器内:左标题/右按钮、搜索、表格、分页 | 路由标题、独立搜索面板、表格面板及列设置工具栏 | 改为一体式容器,标题只出现一次,字段设置放右上角 |
| 查询/重置 | `search-row` 紧接表格 | QueryToolbar,含 FBA 预约号及筛选布局偏好 | 保留全部筛选与偏好,只调整容器外观 |
| 表格字段设置 | 用户明确要求保留 | DataTable 列显隐/排序及持久化 | 继续使用原组件、原 preference-key |
| 新建/导出 | 参考页顶部有示例按钮 | 正式排车列表无这两项操作 | 仅参考排列,不新增业务功能;公共组件保留 toolbar-actions 插槽 |
| 查看 | 当前正式路由详情页 | DispatchDetailView | 不变 |
| 编辑/转派送 | 当前居中表单弹框 | AppDialog | 不变 |
| 打印 BOL/取消 | 当前 PDF 窗口/二次确认 | 服务端 PDF、ElMessageBox | 不变 |
| 审核/停用/文件上传 | 本列表无相应入口 | 无 | 不新增 |
## 公共接入
`DataTable` 使用 `appearance="integrated"` 启用公共样式,`toolbar-start` 放页面标题,`toolbar-actions` 放已有业务按钮,`filters` 放 QueryToolbar,条件 `state` 插槽放加载错误与重试。表格字段偏好、行操作和分页继续由 DataTable 管理。该模式下标题、搜索、表格共用边框与圆角,搜索和表格间没有卡片外间距。
页面自行关闭列表路由 `showPageHeading`,避免重复标题;详情路由保留原配置。样式唯一维护位置为 `src/shared/components/DataTable.vue`,业务页不复制样式。未在本轮范围内的页面继续保持默认外观。
一体式列表的搜索区默认输入框、选择框、日期框和按钮共用 `--el-component-size: 36px`。选择框默认外框的最小高度由公共 DataTable 同步,避免 Element Plus 固定的 `32px` 与输入框产生高度差;显式 small/large 尺寸及多选换行继续按组件自身规则处理。该规则同时覆盖 QueryToolbar 和搜索插槽内直接使用的选择框。
Admin 仍使用 Element Plus。普通 `el-select` 由构建组件解析器统一接入 `src/shared/components/AdminSelect.ts`,仅将 `filterable` 默认值设为 `true`,使用 Element Plus 原有渲染、插槽、事件和公开方法;列表、表单、弹框及分页选择框均可输入关键词筛选当前选项。已有 `remote-method`、`filter-method`、多选、禁用和清空行为保持原有配置;搜索不改变候选业务范围,也不会自动新增远程接口调用。虚拟托盘选择框 `el-select-v2` 已显式启用远程搜索。
已接入列表的表格“操作”列使用纯文字按钮:无描边、填充或装饰图标,字重为普通正文的 `400`,普通操作蓝色,取消等危险操作红色,悬停无下划线;禁用为灰色,保留加载反馈、键盘焦点和危险确认。通过 `RowActions` 的 `text-actions` 接入,更多菜单使用相同配色与普通字重;已有手写按钮组使用 `row-actions density-actions admin-text-actions`,危险语义仍由原来的 `data-tone="danger"` 或 `type="danger"` 显式提供。搜索区、顶部字段设置、分页、列设置面板及弹框按钮保持原样。公共行操作外观维护在 `src/styles/adminTextActions.css`,随 `adminDensity.css` 加载;未接入页面默认不启用。
推广时列设置显式使用 `column-settings-mode="show"`。已有 `preference-key` 保持,新接入的退货库存、流水和箱号各使用独立偏好键。存在非阻断警告时使用 `notices` 插槽,列表失败时通过 `results-visible` 隐藏结果和分页,标题、查询与重试保持可用;`before-results` 保留原统计与汇总。特殊工作台可使用 `results` 插槽承载原内容和自身分页,公共表格不重置它的页码与每页数量。
列宽保存为公共 DataTable 能力,与已有列设置一同启用(提供 `preference-key` 且列设置可用),不依赖试点样式。拖动表头边界松开时,将宽度按稳定列键写入同一份本地偏好;重排、隐藏再显示不会丢失,刷新/重新进入时恢复。账号与表格分别隔离,仅保存到当前浏览器,不跨设备同步。“恢复默认”同时重置列顺序、显隐和宽度,重新采用页面声明的 width/minWidth。未启用列设置的表格不写入列宽偏好。
## 验收
代码检查与真实页面视觉验收分别记录。视觉待人工在 1920×1080、100% 缩放下截图确认,重点核对顶部字段设置、搜索连表格、长编号、横向滚动、分页、加载/空态/失败重试,以及原有操作权限。
2026-09-29 代码验证:定向 78 项通过;完整 `pnpm test` 的 262 个测试文件、2118 项测试通过;`pnpm build`(含 `vue-tsc --noEmit`)通过。未提交、未部署,当前修改不涉及 API、权限或业务状态。
纯文字按钮追加验证:相关 6 个文件、81 项检查通过,类型检查与构建通过。完整测试运行 2118 项通过、1 项失败,失败为原型合同硬编码了 RowActions 属性顺序;改为检查真实动作绑定后,该文件 21 项定向复测通过。视觉仍待人工确认。
列宽保存追加验证:完整 262 个文件、2125 项测试通过;列属性类型调整后公共表格与偏好存储 33 项再次通过;类型检查与构建通过。覆盖拖动保存、重新挂载、排序与显隐保留、恢复默认、独立表格/账号范围、异常宽度与关闭偏好场景。尚未部署,真实表头拖动效果待人工确认。
+280 -1
View File
@@ -2,7 +2,7 @@
## 范围与依据 ## 范围与依据
本轮用户确认继续“海外仓”模块。范围以 `adminNavigation.ts` 的 `overseas-inventory` 分组为准,包含 10 个菜单、对应独立详情和实际调用的作业弹框。客户服务、海外业务、隐藏产品库和旧箱号页面不在范围内。 本轮用户确认继续“海外仓”模块。范围以 `adminNavigation.ts` 的 `overseas-inventory` 分组为准,按当前公开菜单、对应独立详情和实际调用的作业弹框逐项核对;当前分组包含11个菜单,废弃单和海外库位管理均单独登记。客户服务、海外业务、隐藏产品库和旧箱号页面不在范围内。
视觉采用 [Admin 高密度界面规范](Admin高密度界面规范.md),保留当前路由、字段、权限、服务端状态资格及操作承载方式。原型入口为 `悦/货代SAAS平台后台/prototype-src/modules/03-overseas-warehouse.html`;入库、出库、换标、托盘详情分别见 706、714、720、726 行,尾程列表/详情见 894/927 行,库存详情/流水见 974/1022 行。当前真实业务契约优先于历史原型占位。 视觉采用 [Admin 高密度界面规范](Admin高密度界面规范.md),保留当前路由、字段、权限、服务端状态资格及操作承载方式。原型入口为 `悦/货代SAAS平台后台/prototype-src/modules/03-overseas-warehouse.html`;入库、出库、换标、托盘详情分别见 706、714、720、726 行,尾程列表/详情见 894/927 行,库存详情/流水见 974/1022 行。当前真实业务契约优先于历史原型占位。
@@ -90,3 +90,282 @@
后续截图 `codex-clipboard-1adadeb3-9d55-4c41-81c1-d6dafba87293.png` 确认搜索与批量按钮占行过多:海外仓搜索(280px)和一件代发订单搜索及查询/重置(640px)同排,移除独立批量按钮行,已选数并入分页左侧。普通说明收为单行文字,跨客户警告仍保留,备注默认一行并按输入自动增高至三行。 后续截图 `codex-clipboard-1adadeb3-9d55-4c41-81c1-d6dafba87293.png` 确认搜索与批量按钮占行过多:海外仓搜索(280px)和一件代发订单搜索及查询/重置(640px)同排,移除独立批量按钮行,已选数并入分页左侧。普通说明收为单行文字,跨客户警告仍保留,备注默认一行并按输入自动增高至三行。
已增加真实组件回归覆盖分页选择、筛选后跨页勾选、半选状态、每页条数切换、仓库变更清空选择、提交明细数量以及多客户提交门禁。仅使用测试 Mock 验证提交,无真实出库单创建或 PDA 推送。修正后视觉仍待 1920×1080、100% 截图确认。 已增加真实组件回归覆盖分页选择、筛选后跨页勾选、半选状态、每页条数切换、仓库变更清空选择、提交明细数量以及多客户提交门禁。仅使用测试 Mock 验证提交,无真实出库单创建或 PDA 推送。修正后视觉仍待 1920×1080、100% 截图确认。
## 统一弹窗整理:尾程订单主窗口(2026-10-20)
依据当前统一弹窗样板、浅色背景、无左侧色条和连续编辑表;当前入口为尾程订单列表、独立详情及列表调用的WarehouseTransferReviewDialog。截图编号唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),本组为279—309。最近指引与旧样式矩阵中的转运审核尺寸不一致时,按当前实际420px简短确认保留,只提交APPROVE,不恢复旧详细审核或新增驳回功能。
| 操作 / 状态 | 当前承载与尺寸 | 本组处理 | 保留边界 |
|---|---|---|---|
| 转仓 | AppDialog,默认560px | 票数标题、连续FBA/备注、全屏 | 公共ACTIVE FBA仓、空态/错误、原选择与转仓请求 |
| 按柜生成与恢复资源 | AppDialog,1240px | 连续选择、浅绿服务端汇总、浅蓝分组、结果表、全屏 | 托数/阻断/快照及原请求重试、完整结果和原确认门禁 |
| 单票入库计划 | AppDialog,720px | 冻结资料文字、浅黄连续登记、全屏 | 原托数约束、一件代发固定托数、开关/备注、版本与幂等键 |
| 暂扣 / 解除 | AppDialog,620px | 单号标题、连续状态/计费/原因、全屏 | 原开放状态、原因、0版本和原请求 |
| 人工节点 | AppDialog,700px | 单号标题、八行连续时间表、全屏 | 全部8项、0版本、原警告及完整提交 |
| 换标退回重做 | AppDialog,620px | 换标号标题、连续单号/原因、全屏 | 原应用候选、复核任务版本、原因及幂等键 |
| 仓储转运审核 | AppDialog,420px,align-center | 单号标题、浅蓝客户和确认后果 | 原返回/通过、无详情请求、原客户范围及提交锁定 |
| 详情新增费用 | AppDialog,720px | 单号标题、连续费用登记、全屏 | 原应收/应付、USD/CNY、供应商、期间、数量与完整载荷 |
| 合托、废弃/退货/贴标审核及换标确认 | 原ElMessageBox | 业务单号/勾选票数标题 | 原通过/驳回/取消/关闭分支、原因校验、权限与请求 |
原隐藏柜子详情及接柜仓修改窗口保留,不恢复隐藏页签;旧隐藏工作台样式未借本轮扩大处理。原单票/按柜命令与服务端事实、版本、幂等、未知结果及资源恢复逻辑不变。普通来源说明改为InlineHelp;清关后不可更改、固定托数、人工节点覆盖、阻断与资源未确认等提示保留可见。节点表和按柜分组取消内部纵向限高,正文承担主要滚动;横向业务列宽保留。全部写入只以本地Mock验证,不执行真实计划、库存、节点、审核或费用写入。
详情内WarehouseTransferFulfillmentPanel库存分配、WarehouseTransferReceiptPanel签收箱号/增加预报/箱内清点三个子窗口在下节接续;其余海外仓正式菜单尚待整理,本组不视为整个海外仓完成。
自动检查:12个文件、211项定向检查通过;类型检查与构建通过;全量432个文件、3796项测试通过。均通过统一local-check入口串行执行,沿用用户本轮授权的Node 6GB堆上限。冻结的30项源码、测试、共享组件、声明和构建输入前后哈希一致;生成声明与依赖/构建配置未改变,git diff --check通过。主清单1—309号连续且无重复。回归修正了费用标题误传订单对象和计费单位显式disabled覆盖表单保存锁定的问题;原费用载荷不变。
仅完成本地实现与自动检查,未提交、推送、部署或写入测试业务数据;279—309号视觉待人工1920×1080、100%缩放截图确认。
## 统一弹窗整理:转运分配与签收子窗口(2026-10-20)
沿尾程独立详情的实际import进入WarehouseTransferFulfillmentPanel和WarehouseTransferReceiptPanel;同票出库/目标仓实收仍由WarehouseTransferMovementPanel原页面内操作承担,本批不改变承载方式。截图编号310—321唯一维护在[跨模块清单](Admin国内仓样式核对记录.md)。
| 操作 / 状态 | 当前承载与尺寸 | 本组处理 | 保留边界 |
|---|---|---|---|
| 库存来源分配 | AppDialog,1320px | 转运号标题、浅绿数量核对、浅蓝完整候选表、全屏 | 原客户/库存权限、可分配箱数、选择总量、来源阻断、冻结原请求与明确拒绝后重新选择 |
| 签收箱号明细 | AppDialog,1120px | 转运号标题、已清点箱汇总、连续箱号表、全屏 | 只统计COUNTED箱,原托盘/箱唛/SKU/尺寸/重量/体积和箱内入口 |
| 增加预报箱数 | AppDialog,520px | 原箱数与增加后核对、浅黄连续表单、固定底栏、全屏、失败诊断与输入保留 | 原客户/单号、开窗箱数快照、expectedPackageCount及最终packageCount;正整数与既有5000箱上限同时约束按钮和提交入口 |
| 箱内清点明细 | AppDialog,820px | 箱唛标题、只读箱唛/清点时间、浅蓝多SKU实收、直接展示差异原因、全屏 | 原混箱SKU、件数与品名;子窗口关闭后保留箱号父窗口和其全屏状态 |
三个弹窗内DataTable显式以空max-height取消其默认纵向限高,由弹窗正文承担主滚动;长字段仍复用DataTable的默认单行省略与悬停完整文本,横向列宽不变。未将预报箱视为实收,也未改动SKU件数、测量汇总、打印入口或后台请求格式。增加预报的普通说明收进InlineHelp,失败原因及requestId等诊断保留可见。保存时锁定表单、底栏和关闭;切换客户或来源单号时关闭旧窗口,迟到响应不更新新票或展示旧错误;取消后重开恢复新增1箱。
自动检查:12个文件、204项定向检查、类型检查与构建均通过;全量432个文件、3808项测试通过。均经统一local-check入口串行执行,沿用用户本轮授权的Node 6GB堆上限。31项冻结源码、测试、共享组件、声明与构建输入前后哈希一致;业务API文件、生成声明、依赖和构建配置未改变;git diff --check通过。主截图清单1—321号连续且无重复。原库存分配脚本仅增加公共样式导入,分配、原请求重试和明确拒绝后的重新选择逻辑保持原样。
本批只以本地Mock验证分配、重试和增加预报,未执行真实库存/箱唛/预报写入,也未生成真实打印资料;未提交、推送或部署。310—321号视觉待人工1920×1080、100%缩放截图确认。海外入库单的预约、计划编辑和托盘移库弹窗在下节接续,其余海外仓正式菜单仍待整理。
## 统一弹窗整理:海外入库单预约计划编辑与托盘移库(2026-10-20)
实际入口为InboundOrdersView两个AppDialog、显式continuous的FbaAppointmentFields,以及InboundOrderDetailView的移库AppDialog。编号322—336唯一维护在[跨模块截图清单](Admin国内仓样式核对记录.md)。列表及独立详情、智能排车入口、同接仓点/同FBA选择与多批预约跳转保持原样;本批不代表智能排车及其子窗口已整理完成。
| 操作 / 状态 | 原承载与尺寸 | 本组处理 | 保留边界 |
|---|---|---|---|
| 预约 / 编辑 / 只读预约 | AppDialog,1080px | 数量/FBA浅绿核对、系统约号/时区文字、浅黄连续登记、业务号标题和全屏 | 原PENDING/SUCCESS/FAILED/CANCELLED、外部约号、计划与确认起止时间、补充时段、重叠时差清空、必填原因和原完整请求 |
| 原批次已替代或只读权限 | 同预约窗口 | 原替代预约号直接警示、真实表单禁用 | 原列表只读、取消/替代批次不可写;原预约状态和替代关系不变 |
| 预约结果未确认 | 同预约窗口 | 弹窗内诊断、原请求重试和字段冻结 | 原pendingAppointment载荷、版本、幂等键与关闭/路由守卫;明确拒绝后可重新填写的原分支不变 |
| 编辑入库单 | 默认560px AppDialog | 单号/版本文字、连续目的仓选择、全屏、读取/保存锁定和错误诊断 | 原平台候选、客户范围、目的仓ID/编码/名称与版本0完整提交;候选失败仍关闭窗口并保留列表错误 |
| 托盘移库 | AppDialog,560px | 来源单/托盘文字、浅黄连续目标/原因、全屏、候选空态/错误/重试、保存锁定与诊断 | 原仓库范围、普通/A0过滤、当前托盘版本、业务码及移库载荷;原服务端canMove阻断仍留窗,不作为成功刷新 |
共享FbaAppointmentFields只为本列表的continuous调用新增布局,预约工作台等已有消费者保留默认结构;全部原模型字段均保留。本地调整不改变预约确认口径、时区/DST解析、API路径或服务端载荷。移库原先用真假值禁用了合法版本0,现区分版本0和未返回版本;缺失版本或托盘号不可操作。移库保存增加重复提交门禁并锁定原输入,候选读取失败与服务端错误在窗口内保留诊断;每次移库调用原有幂等键生成方式保持不变,本批不另行设计移库命令恢复协议。
自动检查:16个文件、181项定向检查、类型检查与构建通过;全量433个文件、3825项测试通过。均经统一local-check入口串行执行,沿用本轮授权的Node 6GB堆上限。38项冻结源码、共享字段直接消费者、测试、声明与构建输入前后哈希一致;预约/计划/库位API、appointmentForm载荷转换、生成声明、依赖及构建配置未改变;git diff --check通过。连续分支与原字段集合对比为10项且无差异;实际5个预约工作台消费者均保留默认布局并完成定向回归。主截图清单1—336号连续、无重复。
仅进行本地Mock验证,未创建真实预约、修改计划、移动库存、提交、推送或部署。322—336号视觉待人工1920×1080、100%缩放截图确认。入库单实际引用的SmartDispatchDialog新建排车作业窗口及资源字段在下节接续;其余海外仓和Admin模块仍待整理。
## 统一弹窗整理:新建排车与资源登记(2026-10-20)
从入库单及排车列表实际引用的SmartDispatchDialog进入,直接复用的DispatchResourceFields另有DispatchWorkflowDialog消费者;本批仅对新建排车显式启用连续资源登记,不改变后者默认布局。当前1800px AppDialog、先选货/先建空单、候选与装车组双栏、原版本化草稿命令及真实排车核对均保留。
| 当前操作 / 承载 | 本批整理目标 | 保留边界 |
|---|---|---|
| 建单方式、起运仓、分组时间与备注 | 浅黄连续表单、原生标题与全屏、装车组上下文 | 原同仓、按组独立settings、空单与整车分支 |
| 车辆/司机档案及本趟临时资源 | 显式连续资源表、完整字段与禁用反馈 | 档案权限/搜索、实际容量、证照/任务结束、本趟资料不建档案 |
| 草稿恢复、新建/释放、装车组增删 | 浅绿草稿汇总与连续分组 | 原token、版本、容量15/30、来源锁定及未知结果恢复 |
| 货物查询、仓库分类和来源明细 | 浅蓝候选、长文本省略、完整来源组展开、正文主滚动 | 原查询条件、完整候选、整组资格、全部真实来源与加入/移除 |
| 提交/未知结果/明确拒绝/读取失败 | 原固定底栏、可见阻断与诊断、原请求重试 | 原会话内请求、幂等键、响应身份/版本和整车核对,不重造协议 |
实施结果:新建排车启用原生全屏,设置与车辆司机分成浅黄连续表,草稿管理和装车组采用浅绿分区,候选采用浅蓝分区。保留1800px和候选/分组双栏;移除候选表420px纵向限高,由弹窗正文承担主要滚动,明细列宽及横向滚动保留。普通长列使用原生溢出提示,业务引用和托盘号使用LineClampText;完整来源组可展开查看全部来源,选取资格和整组请求不变。外配仅本趟、空单不可核平/装车/发车、未知结果冻结和明确拒绝后的重新核对仍直接显示。
共享DispatchResourceFields新增显式continuous分支,默认消费者DispatchWorkflowDialog布局保持不变;档案和外配的全部原绑定、档案权限、实际容量、任务结束与证照字段保留,未生成假档案或按计划托位推算车辆容量。初次生成组配置时,原逻辑直接返回赋值表达式的原始对象,资源切换后可能出现界面仍有车牌、实际配置已为空的情况。现先存入响应式settings再返回其代理对象;真实组件回归验证车牌、容量、司机及分组切换后的完整载荷,保留原版本、幂等、转换和恢复协议。未选择装车组时,先选货模式的车辆/司机/时间/备注保持禁用,建单方式及起运仓仍可设置;空单模式不受装车组前置限制,避免资料落入未提交的占位组配置。
自动检查:16个文件、242项定向检查、类型检查与构建通过;全量434个文件、3839项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。42项冻结源码、直接消费者、测试、共享组件、API/模型/恢复输入、声明与构建输入前后哈希一致。除已说明的组配置初始化修复及样式导入/显式属性外,两组件脚本与本批修改前一致;资源连续分支包含全部14项原绑定。原有API、模型和恢复协议的工作区修改均保留,本批未改动;生成声明、依赖及构建配置未产生改动。git diff --check通过,主截图清单1—351号连续且无重复。
截图337—351唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本地Mock覆盖先建空单、档案/临时资源、组配置保留、整组来源展开、未知结果原请求、明确拒绝重选及已证明转换后的详情重读;未真实创建或转换草稿、排车、档案及业务数据,未提交、推送或部署。下一批接续排车详情的维护/审核/移货/卸货顺序等动作窗口及附件预览,其余Admin模块仍待整理。
## 统一弹窗整理:排车详情操作与取证附件(2026-10-20)
实际操作承载为DispatchWorkflowDialog,直接引用DispatchResourceFields、DispatchArrangeFields和DispatchEvidenceFiles;后者也供DispatchDetailView只读取证使用。保留560/760/1120px动作尺寸及900px图片预览,不改变详情路由、服务器Gate、版本化命令、费用覆盖、文件鉴权或恢复协议。
| 操作 / 原承载 | 本组整理目标 | 保留边界 |
|---|---|---|
| 维护车辆、司机、时间及备注 | 业务号标题、浅黄连续登记、共享资源显式接入、全屏 | 原资源档案/外配、证据引用、完整EDIT载荷 |
| 调度/理货审核及简单确认 | 浅蓝事实、浅黄结果/原因或备注、可见业务警示 | 原两级审核、驳回必填、取消/回退/发车及服务端资格 |
| 添加/移除货物、卸货顺序 | 浅蓝完整明细、来源展开、原生长文本提示、正文主滚动 | 真实来源组、逐项移货Gate、已扫码限制、既有全部站点及调整原因 |
| 装车完成与依据 | 实测连续表、逐托证据表、全屏 | PDA核平、真实实测与参考区分、manifest及卸货顺序 |
| 整车分组派送 | 各组连续安排、完整货物/外接报价/原费覆盖及新增费用 | 原客户/目的地归属、覆盖哈希、未覆盖正数费用及买约卖家必填 |
| 本趟附件与图片预览 | 操作在前的紧凑附件表、只读/上传资格、全屏图片框 | 原字符串文件ID、上传/替换/移除引用、鉴权Blob/PDF、迟到响应及URL释放 |
| 上传、未确认结果与错误 | 固定底栏与关闭锁定、原错误和原请求重试 | 原证据busy、未知结果冻结、明确拒绝后重新核对 |
实施结果:动作窗口标题携带原排车业务号,车辆/司机与计划时间、操作原因、分组派送均采用浅黄连续表;原审核资料、完整货物来源、逐托测量依据及附件采用浅蓝分区,无左色条。1120/760px窗口开放原生全屏,560px简单确认保留紧凑尺寸,底栏与关闭在提交和上传期间锁定。移除货物420px、添加候选380px、派送分组货物240px的表内纵向限高取消,由弹窗正文承担主滚动;列宽与横向滚动保留。原生长列溢出提示和LineClampText承载完整文本;完整来源组可展开全部来源,实测与参考依据直接区分。
DispatchArrangeFields脚本及费用覆盖算法保持原样,派送、原费用、外接报价与新增费用的全部原绑定和业务字段保留;两级审核、真实dispatchItemId、全部既有卸货点、合法版本0及长版本、manifest、费用哈希和原命令恢复协议不变。原服务器资格与前端权限同时决定表单禁用,提交校验继续保留。本地回归发现失败操作关闭重开后,重新读取会用服务端旧资料覆盖当前实例已提交的输入,而重试仍使用原请求;现仅按当前实例记录的幂等键和原业务号保留该请求对应的表单与诊断。新实例恢复仍读取当前事实,明确拒绝后重新核对仍先清除被拒请求再读取,不新增存储或恢复协议。
DispatchEvidenceFiles保留原本车/附件类型鉴权、字符串引用、上传校验、Blob/PDF读取、迟到响应隔离及URL释放;附件表将操作放前,失败诊断可重新读取,原上传与主单引用保存提示直接显示。图片预览保留900px与图片72vh适配上限并增加全屏;此上限只控制图片适配,不建立嵌套滚动。DispatchDetailView只读取证直接消费者一并回归,未添加上传资格。
自动检查:17个文件、251项定向检查、类型检查与构建通过;全量435个文件、3855项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。52项冻结源码、直接消费者、API/模型/恢复输入、测试、共享组件、生成声明与构建输入前后哈希一致;生成声明、依赖与构建配置未改变,git diff --check通过。三个组件脚本扣除已列明的样式/显示组件导入和当前实例请求标记后,与本批修改前哈希一致;派送组件13项原模型绑定无缺失。原有选货分组/API/模型工作区修改保持原样,本批未改动。主截图清单1—375号连续且无重复。
截图352—375唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本批仅使用本地Mock,未真实审核、移货、发车、创建派送/费用、上传业务附件或写入测试数据;未提交、推送或部署。其他海外仓及Admin模块仍待继续整理。
## 统一弹窗整理:新建出库三种模式(2026-10-20)
当前实际入口为OutboundsView的1760px上限AppDialog,保留独立出库详情及列表/详情原取消原因提示框;本批不改动派送列表、资料窗口和详情路由。
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 一件代发出库 | 浅黄连续类型/仓库/查询、浅蓝完整候选、正文主滚动、原全屏 | inventoryPositionId+SKU跨页选择、本页全选、同客户同仓、实际可出箱数和三项测量 |
| 退货出库 | 浅黄连续客户/收件/仓库/退货单、浅蓝SKU与实物箱双栏、原分页 | 原整包裹/整箱/整托、原箱内SKU与数量、原退货来源,不引入部分SKU直接出库 |
| 仓储转运目的地绑定 | 浅蓝真实转运单、浅黄FBA/私人仓连续信息 | 按客户+转运单合并托盘、无目的地资格、全部真实绑定对象及原目的地载荷 |
| 候选/资源读取、保存、失败与重开 | 锁定读取/提交期间的编辑和关闭、错误诊断与重读、保留失败输入 | 原读取接口、客户范围、原写请求与幂等键生成方式;新会话重新初始化 |
| 取消出库关联核对 | 保留原ElMessageBox承载与admin-density-confirm | 原取消原因、费用处理警示、关联排车释放及权限,不将取消视为库存自动回滚 |
实施结果:保留当前1760px上限、原生全屏、固定底栏及三种真实模式;类型、仓库与订单查询、收件/退货来源、FBA/私人仓目的地、备注采用浅黄连续表。原一件代发候选及转运单采用浅蓝分区,退货SKU与实物箱保留双栏和各自分页,全部原候选列及18项模型绑定保留。取消360/380/400px表内纵向限高和旧候选列表300px限高,由弹窗正文承担主滚动;保留横向滚动、每页条数128px及原窄屏规则。长客户/品名、业务号、箱内SKU和托盘继续使用原生溢出提示;无客户名称的转运单显示“客户名称待补充”,不回退内部ID。
读取/保存期间,表单、选择框、分页、提交和关闭均锁定;提交方法独立检查当前开窗、权限、读取/保存状态及候选失败,防止重复调用或在来源读取失败时继续提交。基础资料及候选读取失败在弹窗内保留ApiErrorMeta诊断,可按原范围重读;创建失败保留当前输入与选择,由原提交入口重试。重新新建清空上一单备注、收件信息、退货来源和箱托方式,默认一件代发;失败留窗、切换全屏不清空当前输入。一件代发候选重读保留仍有对应键的选择;退货候选重读仍沿用原加载逻辑重新核对整箱选择。
原创建校验与请求正文逐字核对保持一致:按库存位置+SKU出全部可用箱数,同客户同海外仓;退货仍按原物理包裹/箱号或托盘,不引入部分SKU载荷;转运仍按客户+转运单聚合并绑定目的地,不直接创建出库。原接口路径、客户作用域、幂等键生成方式与取消处理协议未改变,本批不新增未知结果恢复协议。列表及详情取消确认仅关联核对,保留原承载、费用警示、原排车释放和权限逻辑。
自动检查:10个文件、135项定向检查、类型检查与最终构建通过;全量436个文件、3865项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。32项冻结源码、测试、共享组件、原API与模型、生成声明及构建输入前后哈希一致;原出库/退货API、独立出库详情、取消确认、依赖与生成声明未改变,git diff --check通过。布局合同改为核对实际消费的公共全宽控件规则,原取消、权限、数量、跨页选择与实际请求断言均保留。主截图清单1—391号连续且无重复。
截图376—391唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认;本批仅本地Mock验证,未创建真实出库/退货、绑定目的地、推送PDA、取消业务单据或部署。下一组接续派送状态、标记退货和资料管理,其他Admin模块仍待整理。
## 统一弹窗整理:派送状态退货与资料(2026-10-20)
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 编辑派送状态,520px AppDialog | 业务号标题、浅蓝只读事实、浅黄连续状态/备注、读取/保存锁定 | 最新版本0、服务端allowedActions、冲突重读、原取消须经出库提示 |
| 标记退货,720px AppDialog | 业务号标题、连续原因/去向/物流、来源表操作在前、全屏 | 原尾程主单、原出库明细与可退上限、原退货箱整箱、真实来源标识与原幂等请求 |
| 派送资料,1040px AppDialog | 业务号标题、浅绿摘要、连续BOL、三类浅蓝附件表、全屏 | 原只读/管理资格、每类20份/50MiB、上传/替换/删除草稿、保存版本/幂等、签收文件完成派送 |
| 资料重新加载确认 | 保留ElMessageBox与admin-density-confirm | 原未保存资料放弃确认、关闭丢弃草稿、重开读取真实快照 |
实施结果:520px状态窗口保留紧凑承载,标题携带派送业务号,当前状态/关联出库采用浅蓝普通文字,允许状态及备注采用浅黄连续表。读取/保存时锁定表单及关闭;版本冲突保留备注、禁用提交,原重读只保留最新仍允许的状态;最新已无可选状态时直接提示。720px退货窗口增加原生全屏,主单、原因、去向、物流采用连续表;原出库明细改为操作在前的来源/上限/箱数表,LineClampText承载完整业务来源,原箱固定1箱与整箱警示保留。读取失败可在原派送号/客户范围重新读取;提交失败仍由原入口重试同一载荷和幂等键。
1040px资料窗口增加原生全屏、浅绿资料摘要、连续BOL登记与三类浅蓝附件表;文件动作放前,长文件名使用LineClampText,上传时间、已保存/待保存状态仍完整显示。未保存文件继续不可下载,上传/替换/删除仍只改草稿,完整保存后生效;只读BOL采用普通文字,保留已保存文件下载。读取和上传/保存锁定关闭,读取失败摘要显示“资料未返回”,避免误示仍在读取。版本冲突保留草稿,重新加载继续使用原放弃未保存资料确认;关闭/重开继续读取服务端原三类快照。
两个组件的业务脚本扣除长文本显示组件导入后均与修改前逐字一致,原14项和2项模型绑定无缺失;状态版本0、allowedActions、尾程/来源归属、整数可退上限、原箱来源、每类20份/50MiB、文件上传/下载作用域、版本及幂等协议保持原样。原权限/数量/错误/请求断言保留,既有测试仅将弹窗选择器改为匹配携带业务号的标题前缀;未修改服务端契约、API路径或写入载荷。列表及独立详情承载保持原样。
自动检查:12个文件、160项定向检查、类型检查与最终构建通过;全量437个文件、3876项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。37项冻结源码、直接消费者、原API/来源模型、测试、共享组件、生成声明及构建输入前后哈希一致;原API、独立派送详情、依赖与生成声明未改变,git diff --check通过。主截图清单1—409号连续且无重复。
截图392—409唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认;本批仅本地Mock验证,未真实修改状态、生成异常退货、上传业务文件、保存资料、提交、推送或部署。下一组接续换标单及实际引用的作业窗口,其他Admin模块仍待整理。
## 统一弹窗整理:换标新增审核与PDF(2026-10-20)
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 新增换标单,760px AppDialog | 连续基础/作业表、公共候选、全屏、处理中与失败反馈 | 客户及公共收货仓独立读取、必填、箱数/金额、原幂等键及创建载荷 |
| 审核换标单,同一760px窗口 | 原完整多SKU/数量普通文字、连续动作与备注、业务号标题 | 原审核资格、尾程审核分流、驳回原因及状态请求 |
| 作废、完工确认、退回重新贴标 | 保留ElMessageBox密度确认 | 原权限、状态、复核版本与PDA退回原因 |
| 总/明细PDF预览,900px AppDialog | 业务号、全屏、加载/错误重试、关闭释放URL | 原TOTAL/ITEM及明细标识、鉴权下载、原iframe72vh/760px适配 |
| PDF上传与箱唛映射 | 原PDF入口、权限禁用、操作在前、缺失仓码不显示内部ID | Controller上传使用relabel-order:create,下载使用list;原类型/50MB及请求保持 |
| 贴标文件共享下载表 | 仅将原下载操作列放前 | RelabelOrderDetailView与LastMileOrderDetailView两个直接消费者,原两列及文件分类/归属/下载不变 |
实施结果:新增/审核保留760px并增加原生全屏,新增采用自动编号文字、浅黄连续基础/作业/备注表;审核将原多SKU、新SKU逐项数量、箱数、关联订单、品名、货件号、要求及费用完整显示为浅蓝普通文字,只保留原动作和备注可编辑。19项原模型绑定无缺失,创建与审核的原验证/请求正文逐字一致。客户与公共收货仓继续独立读取,候选失败各自显示诊断与重读;新建/审核在读取或保存期间锁定编辑和关闭,失败留窗保留原字段与原创建幂等键。审核详情读取失败仍按原规则关闭并提示;合箱入口仍跳转原库存来源选择,不恢复旧本地合箱表单或把箱数当SKU数量。
原作废、完工确认和退回重新贴标继续使用密度ElMessageBox,提示携带业务号,真实确认/原因输入仍触发原业务请求;完工确认和退回动作增加互相禁用与处理门禁,避免等待结果时并发发起另一动作,原退回复核版本0及原因保留。详情PDF预览增加原生全屏、业务号/文件名标题、读取中与错误重读;保留900px、iframe的72vh/760px尺寸和PDF内部查看方式。关闭/切换业务号/卸载释放URL并忽略迟到预览响应;TOTAL/ITEM和明细标识保持原样。PDA完工照片仍沿原鉴权读取、浏览器页签及60秒URL释放流程,不改变承载。
上传入口和提交方法按现行Controller的relabel-order:create权限约束,预览下载保留list只读访问;原PDF校验、50MiB及上传接口保持不变,上传处理中防重复,失败在详情保留诊断,旧请求结果不覆盖另一业务号。箱唛映射表将原明细PDF动作放前,长文件名使用LineClampText;缺失FBA仓码显示“—”,不再回退内部仓ID。共享RelabelDocumentsPanel只重排原两列,脚本逐字未变;换标详情及尾程详情两个直接消费者均纳入回归,不增加原来省略的文件名字段或修改分类/下载规则。
自动检查:14个文件、147项定向检查、类型检查、最终构建通过;全量438个文件、3889项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。39项冻结源码、直接消费者、API、权限依据、测试、共享组件、生成声明及构建输入前后哈希一致;服务端Controller、API、依赖与生成声明未修改,git diff --check通过。
截图410—430唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本批仅本地Mock验证,未创建/审核/作废真实换标、推进完工、退回PDA、上传业务文件、写入测试数据、提交、推送或部署。下一组接续海外仓托盘管理,其他Admin模块仍待整理。
## 统一弹窗整理:海外仓托盘新增与编辑(2026-10-20)
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 新增托盘,760px AppDialog | 一张浅黄连续资料表、横排标签、原生全屏 | 原8项字段、默认值、五种类型、三种状态、容积/价格精度、必填校验及创建载荷 |
| 编辑托盘,同一760px窗口 | 托盘编码标题、仓库普通文字、读取/保存锁定 | 原固定仓库、当前服务端版本含0、更新载荷及权限 |
| 编辑详情读取 / 失败 | 留在业务号窗口、诊断与同范围重读 | 原仓库与托盘字符串标识,失败不显示上次编辑资料、不允许提交 |
| 候选读取 / 失败 | 原候选来源、弹窗内错误与重读期间门禁 | 原公共收货仓和ACTIVE FBA仓;不按客户缩小候选、不新增候选协议 |
| 保存 / 失败 / 取消 | 防重复、失败保留、关闭重开默认值 | 原验证、完整请求、更新版本及关闭丢弃规则 |
| 单张打印与独立详情 | 沿用现有PDF下载和只读路由 | 不创建打印预览弹窗、不改模板、原仓库/托盘标识及下载URL释放 |
实施结果:760px弹窗增加原生全屏,原顶部标签/双列栅格改为横排120px标签与连续资料表;只使用共享浅黄录入背景,不增加左侧强调线和嵌套汇总。编码、类型、容积、采购价格、海外仓、FBA仓、状态、备注共8项模型绑定保留;编辑仓库直接展示名称和仓码,其余资料继续可编辑。原容积四位/价格两位、必填规则、备注500字上限保持;备注使用两行并显示字数。
编辑窗口先显示托盘业务号与读取状态,读取成功后才显示表单;失败保留本次对象并提供诊断和原仓库/托盘范围重读。候选来源与读取逻辑保持原样,原上下文失败同时出现在弹窗并阻止保存,重新读取时锁定关闭。读取、保存和候选重读过程中锁定编辑、关闭及再次打开;创建/编辑入口和保存方法核对原独立权限。保存失败留窗保留原输入,版本冲突不静默覆盖或改写旧请求版本。
原8项绑定、必填验证、payload构造与创建/更新请求、候选/列表读取、标签打印函数经修改前后逐字比对均保持;不修改API、权限码、模型、独立只读详情或服务端模板。单张打印继续使用现有鉴权PDF下载,不新增预览承载。
自动检查:8个文件、109项定向检查、类型检查、最终构建通过;全量439个文件、3898项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限;29项冻结源码、直接依赖、原API/模型/权限、测试、生成声明及构建输入前后哈希一致,git diff --check通过。主截图清单1—440号连续、无重复。
截图431—440唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本批只使用本地Mock,未创建或修改真实托盘、下载业务标签、写入测试数据、提交、推送或部署。下一组接续海外库位管理,其他Admin模块仍待整理。
## 统一弹窗整理:海外库位维护(2026-10-20)
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 新增 / 编辑,560px AppDialog | 连续录入、横排标签、原生全屏、固定仓库普通文字 | 公共收货仓、普通库位、原仓库及库位标识、原创建/更新接口 |
| 候选加载 / 保存 / 失败 | 明确加载和诊断、防重复、失败保留原输入 | 原候选与查询、关闭规则、原权限;不新增服务端接口 |
| 启用 / 停用,ElMessageBox | 原业务编码确认、统一密度与操作锁定 | 原NORMAL资格、A0/共享溢出与虚拟库位保护、原状态请求 |
| 删除,ElMessageBox | 停用且无托盘的普通库位确认、处理中和失败反馈 | 服务端禁止A0/虚拟库位和绑定托盘删除,前端不扩大为其他类型 |
实现前契约核对:现行LocationRequests.SaveRequest只接收locationCode、locationType、maxLoadKg、status、remark,没有库位名称;最大承重必须大于0。WarehouseResourceService的状态包含INACTIVE,不包含DISABLED,且禁止删除虚拟库位。原页面存在无保存字段的名称输入、INACTIVE编辑默认成ACTIVE及删除入口只判断DISABLED的问题;本组在弹窗收敛时按现行契约修正,不增加名称接口或修改服务端。托盘全量检查通过并核对冻结输入后才写入库位改动。
实施结果:560px新增/编辑增加原生全屏,统一浅黄连续单列表与110px横排标签,不再使用顶部标签及本地editor-grid外观。海外仓、库位编码、承重及备注4项实际可保存资料保留;移除没有保存接口的库位名称输入。编辑固定海外仓采用名称和仓码普通文字;标题携带原库位编码。取消后新建恢复原默认仓库、空编码/承重与备注,全屏不清空输入。
编辑INACTIVE库位保留停用状态,已停用筛选直接提交INACTIVE;最大承重增加有限正数校验、最小0.001,保留三位精度及kg单位。删除资格收敛为NORMAL、INACTIVE且无托盘,保留A0编码、共享溢出类型/标记和虚拟库位保护。启用/停用与删除仍采用原ElMessageBox,统一密度、业务编码及危险语义,原创建/更新/状态/删除API、完整业务载荷与原版本参数保持;不宣称服务端额外校验未实现的版本参数。
候选和列表错误采用原读取范围重试并显示诊断;候选失败在弹窗同时明确阻断保存。读取/保存锁定编辑及关闭,操作确认与命令执行期间锁定其他维护动作;失败保留表单或列表上下文、显示诊断,取消不发写请求。保存方法再次核对独立权限。页面不复制公共外观、无新增本地CSS,不改API、DTO、权限码、数据库或服务端。
自动检查:7个文件、113项定向检查、类型检查、最终构建通过;全量440个文件、3911项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。36项冻结源码、直接依赖、原API/模型/权限、测试、生成声明、构建输入及只读服务端契约依据前后哈希一致,git diff --check通过。主截图清单1—453号连续、无重复。
截图441—453唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本批只使用本地Mock,未新增/编辑/启停/删除真实库位、写入测试数据、提交、推送或部署。下一组接续已注册的废弃单详情与审核窗口,其他Admin模块仍待整理。
## 统一弹窗整理:废弃单详情与审核(2026-10-20)
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 废弃单详情,920px AppDialog | 业务号标题、普通文字摘要、完整明细、原生全屏 | 原6项详情摘要、5列废弃明细及实际箱唛、只读资格 |
| 审核并推送PDA,ElMessageBox | 业务编码、统一密度、危险提示与处理中锁定 | 原PENDING_REVIEW与discardApprove权限、APPROVE请求及客户范围,不增加驳回/取消入口 |
| 现场照片缩略图 / 大图 | 原150px图片与原生大图查看、逐图加载/失败重试 | 原鉴权文件与客户范围、关闭/切换/卸载释放URL、迟到响应隔离 |
| 详情读取 / 失败 | 先显示本次业务号、明确加载和原范围重读 | 原详情接口及客户参数,失败不显示上次单据资料 |
| 客户候选 / 列表读取 | 候选及列表独立错误、原范围重读 | 原ACTIVE客户第1页200条与原筛选/分页请求,不新增候选协议 |
实现前已核对CargoDiscardController:照片下载要求discard:list及显式customerId,审核由服务端核对审批权限。详情cartonMarks来自各来源的真实所选箱唛;缺失时不得据此推断“全部库存”。本组保留原审核及PDA流程、API和原生图片查看,不新增业务动作或改库存扣减。
实施结果:原920px只读详情增加原生全屏与废弃单号标题,6项原摘要采用浅绿普通文字表,原5列废弃明细采用浅蓝分区;入仓码、SKU、品名和箱唛通过LineClampText单行省略并保留完整悬停及键盘内容。缺失箱唛显示“—”,不再推断全部库存;原状态流转记录以时间、状态、备注连续表承载,顺序及原展示内容保留,空照片和空流转分别明确提示。页面只维护摘要列宽、照片排列与150px业务图片面积,不复制公共外观或添加左侧强调条。
详情先显示本次业务号与读取状态,失败保留本次单据及客户范围重试,不复用上次资料。图片仍经原鉴权接口读取Blob、原生ElImage大图查看,保留源照片顺序、当前索引及150px缩略图;逐图失败显示诊断和同文件重试,缺少客户范围直接阻断,不向接口传undefined字符串。关闭/切换/卸载释放URL、清除状态并隔离迟到详情及照片响应;图片读取期间仍允许正常关闭,不新增独立图片弹窗。
审核仍使用原ElMessageBox和原APPROVE请求,原权限及PENDING_REVIEW双重资格在入口及确认后核对,确认正文包含废弃单号与推送PDA后果。确认和请求期间锁定其他操作及重复提交;失败保留列表并显示诊断,取消/关闭不发写请求。原6项摘要、列表请求构造和审批调用逐字核对保持;不增加驳回/取消业务动作、审批载荷、API、权限码或服务端变更。
客户候选和列表各自加载、错误诊断及原范围重读,客户读取失败不阻断其他列表条件;候选仍为原ACTIVE第1页200条。查询采用原字段/分页参数,旧查询响应不会覆盖新结果。列表操作显式采用公共文字操作样式,操作列保留首列固定并扩为180px容纳原两项动作;状态缺失显示“—”。
自动检查:8个文件、121项定向检查、类型检查、最终构建通过;全量441个文件、3925项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。45项冻结源码、直接依赖、原API/模型/权限、测试、生成声明、构建输入及只读服务端契约依据前后哈希一致,git diff --check通过。主截图清单1—469号连续、无重复。
截图454—469唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本批只使用本地Mock,未审核真实废弃申请、推送PDA作业、下载真实业务照片、扣减库存、写入测试数据、提交、推送或部署。下一组接续退货库存/箱号及原合箱作业窗口,其他Admin模块仍待整理。
## 统一弹窗整理:退货库存合箱与箱号(2026-10-20)
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 创建合箱计划,1380px AppDialog | 连续基础/来源/备注表、原生全屏、正文单一滚动 | BOX整箱和SKU部分两模式、原物理箱唛+SKU数量绑定、原来源分页/过滤/上限与创建请求 |
| 合箱计划详情,1400px AppDialog | 普通文字摘要、来源/流向/完成时快照、原生全屏 | 仍读取原本页计划快照,不新增详情接口;原预计取出/剩余和实际完成数量、当前箱唛打印资格 |
| 退货箱号详情,1080px AppDialog | 业务箱唛标题、只读资料与合箱流水、全屏及读取失败重试 | 原11项箱号资料、换标实际/占用数量、箱内SKU、来源/目标和流向 |
| 计划审核 / 取消 | 原直接审核与ElMessageBox取消确认、处理中互锁 | 原状态资格、原请求与释放库存语义;不新增业务确认步骤 |
| 箱唛打印 | 保留现有浏览器HTML打印入口 | 原鉴权标签、opener隔离、服务端printableHtml及打印内容/尺寸,不生成第二套模板 |
实现前已核对PlatformReturnPackingPlanController和PlatformReturnInventoryController:创建/审核/取消要求退货库存列表权限和lastleg:inventory:manage;来源选择另要求退货箱号列表权限;箱号详情/标签要求退货箱号列表权限。本组补齐对应前端资格与只读状态,不改变服务端权限或库存流程。退货客户候选原有全分页、公共收货仓、来源分页与旧查询隔离继续保留。
实施结果:原1380px创建、1400px计划详情、1080px箱号详情均增加原生全屏,保留两个详情原无底栏承载。创建采用110px横排标签、浅黄基础/备注和浅蓝来源连续表,8项原模型绑定集合无缺失;BOX与SKU来源分别采用原选择方式,保留箱唛、来源退货单、载体、完整混箱SKU和逐物理箱+SKU数量。移除原260px内部纵向滚动与窗口resize覆盖,来源表头继续粘性定位,正文使用AppDialog单一滚动。两行备注保留1000字上限及原锁源/新箱/PDA箱规说明。
原来源分页、去重筛选、BOX包含任一SKU、SKU精确匹配、模式切换清空及数量归集函数逐字保持;增加正整数/可用上限校验和整数控件,不改原提交计算及API。原幂等键生成从每次提交移至本次打开或深链打开,失败重试保留原键和输入,关闭/成功后结束本次键;不新增HTTP协议或恢复流程。读取失败显示同范围诊断/重读,候选失败不误示空库存;客户与仓库仍由原allSettled入口加载,客户全分页和公共仓来源保留。来源关闭/切换/卸载隔离迟到结果并停止继续分页;提交期间锁定编辑与关闭,阻止重复提交。
计划详情保留原本页快照,不新增服务端详情接口。6项摘要改为浅绿普通文字,来源、流向和完成/计划明细采用同级连续分区;原计划来源/取出/剩余与完成箱计算函数逐字保持,完成时快照和当前可打印箱资格分开显示,原说明及箱规/重量/时间/操作员保留。打印当前箱唛操作列前置,已MERGED或清空的当前箱仍不可打印;无箱号列表权限时隐藏打印操作列。
箱号详情保留11项原资料、换标实际完成/占用数量、箱内SKU和合箱流水;摘要改为普通文字,业务号/中文品名使用LineClampText保留完整悬停与键盘内容,缺失合箱计划号显示“—”,不推断现场或历史流程。读取先显示本次箱唛,失败在原范围重试,不显示上次资料;关闭/卸载隔离迟到响应。原标签读取及popup.opener=null、原服务端HTML写入、focus/print正文逐字保持,不改变打印尺寸或模板;增加重复打印门禁和失败诊断。
原直接审核不增加确认步骤;取消仍使用原密度ElMessageBox,确认中携带计划号与释放来源库存后果。创建/审核/取消/来源/箱号及标签分别按当前Controller权限核对,管理动作互锁,失败保留表单或列表,取消不发写请求。四种主列表仍采用原查询/分页和独立偏好键,补充错误诊断及原范围重读,旧查询响应不覆盖新结果。原14项列表/业务测试全部保留,只为明确授权场景补入权限Mock,并将一处点到表格隐藏测量行的详情选择器改为真实箱唛行,增加业务箱唛请求断言。
自动检查:8个文件、127项最终定向检查、类型检查、最终构建通过;全量442个文件、3939项测试通过。均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。56项冻结源码、直接依赖、原API/模型/权限、测试、生成声明、构建输入及只读服务端契约依据前后哈希一致,git diff --check通过。主截图清单1—496号连续、无重复;另已只读核对ReturnInventoryService对同幂等键请求内容的hash校验,本组不改服务端协议。
截图470—496唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本批只使用本地Mock,未创建/审核/取消真实合箱计划、打印真实箱唛、占用/释放库存、写入测试数据、提交、推送或部署。下一组补齐库存流水与国内入库共用的入仓码关联数据窗口,其他Admin模块仍待整理。
## 统一弹窗整理:库存与入库关联数据(2026-10-20)
| 操作 / 当前承载 | 本组目标 | 保留边界 |
|---|---|---|
| 国内入库单 / 海外库存流水 → 入仓码关联数据,1060px AppDialog | 两个实际入口显式dense、原生全屏、只读分区与长文本 | 原三个独立权限、原三个读取API与业务号,默认非dense样式保持 |
| 订单基础 / 装柜PDA / 海外库存 | 公共背景、连续普通文字、完整业务标识及库存数 | 原6项基础、6项装柜、客户/仓库、尾程单/计划/托盘和SKU库存,不显示内部ID |
| 空码 / 无权限 / 未找到 / 局部失败 | 原警示、局部空态与各分区诊断/重读 | 仍只查当前允许的读模型,原重试重读全部允许分区,不新增接口或权限 |
| 关闭 / 切换 / 卸载 | 原可在读取中关闭、迟到响应隔离、清理读取状态 | 不改readonly承载及请求作用域,修正空码/无权限提前返回时旧loading未清理的问题 |
实际直接调用方仅InboundOrdersView与InventoryTransactionsView,另有共享组件合同测试;不会把原关联框重新引入统一订单或InboundTaskList。dense外观通过现有显式参数启用,默认模式不启用新背景或全屏;原API、显示字段、合法业务编号回退和权限过滤保持。
实施结果:原1060px框架通过现有dense参数增加原生全屏,国内入库单实际入口同步显式启用dense,海外库存流水入口继续保持显式启用。基础/装柜采用公共只读来源背景,海外入仓与库存采用汇总背景;标题与状态仍同行,保留无底栏、destroy-on-close和读取中可关闭的原承载。旧边框、背景、15px标题、正文高度/内边距仅限制在默认非dense模式,删除原dense零边框/零内边距及通用字体覆盖,避免抵消公共背景;新模式只配置两列、宽行、表头及内容约束。
原6项基础、6项装柜、海外客户与仓库、完整尾程单/入库计划/托盘、SKU/产品和库存箱数全部保留。dense长值使用LineClampText,尾程单/计划/托盘采用同一连续资料表的宽行及两行省略;原状态组合文本、顺序及柜号/柜次业务号回退保持,数量0仍显示。非dense保留原标题属性、旧列表和布局,不启用新背景/全屏/长文本组件。真实未找到与已找到但无SKU库存分别提示;原仓库未分配和名称未返回语义不变。
三个权限过滤和API任务段经前后逐字对比未改,继续只读当前允许的服务端读模型,各分区错误保留诊断及原重试读取全部允许分区规则。修正空码/无权限提前返回及关闭时旧loading未复位;卸载增加serial失效,切码/关闭/权限变化后的迟到结果不覆盖当前数据。不改请求路径/参数/访问域或后端契约,不新增业务动作。
自动检查:10个文件、139项最终定向检查、类型检查、最终构建通过;全量443个文件、3951项测试通过。包含共享默认/密度两模式、真实Element过渡关闭、国内直接页面及海外真实API Mock挂载,均经统一local-check入口串行执行,沿用用户授权的Node 6GB堆上限。66项冻结源码、直接调用方及其测试、原API/模型/权限、共享组件、生成声明与构建输入前后哈希一致,git diff --check通过。主截图清单1—510号连续、无重复。
截图497—510唯一维护在[跨模块清单](Admin国内仓样式核对记录.md),视觉待人工1920×1080、100%缩放截图确认。本批仅本地Mock,未读取真实关联数据、写入测试环境、提交、推送或部署。下一组接续预约管理当前日历入口的新增FBA与计划到仓窗口,其余原业务办理分支继续逐操作整理。
+209 -1
View File
@@ -1,5 +1,198 @@
# Admin 货柜管理样式核对记录 # Admin 货柜管理样式核对记录
## 统一弹窗整理:预装清单与全局智能装柜(2026-10-20)
本批沿预装清单的正式详情路由,以及订单列表实际调用的`SmartLoadingDialog → GlobalSmartLoadingView`进入,依据已确认的[测量样板](界面参考/Admin弹窗样板-测量.png)和[高密度规范](Admin高密度界面规范.md)。全局智能装柜实际为候选、柜次、方案三栏数据工作台,本批保留三栏尺寸、筛选、独立滚动及默认全屏。截图编号从91接续。
| 操作 | 当前承载 | 本批实施结论 |
|---|---|---|
| 补录/纠正集装箱号及航次 | `PreloadPlanDetailView`,620px AppDialog | 原3项字段改浅黄连续表,标题带预装单号;保留大写规范化、纠错原因、PDA状态门禁和版本 |
| 编辑预装明细备注 | 680px AppDialog,客户备注为禁用输入 | 800px连续表,客户备注显示只读文字、原3项备注可编辑,支持全屏;保留两层版本、操作号及冲突后保留输入 |
| 确认预装并推送PDA | 520px AppDialog,分散描述块 | 浅绿连续资料表、业务编号标题及原警告,保留外部作业员选择、可确认条件与原请求 |
| 全局智能装柜工作台 | 默认全屏AppDialog,普通模式1600px/94vh | 接入统一标题/底栏和显式密度根,保留三栏几何、各自滚动和返回普通尺寸;行内操作接入现有公共样式 |
| 普通/待审核候选加入 | 全局工作台`assignOpen` | 920px来源浅蓝、填写浅黄连续表、业务编号标题及全屏;保留普通与待审核各自API、平均毛重/体积、数量上下限及跨渠道警告 |
| 同柜组/封托整托加入 | 同一窗口的两种分支 | 保留完整组成及不可拆提示,无部分箱数控件,继续走原子分配接口 |
| 普通/同柜组/整托移除、移除全部未拣 | 现有ElMessageBox | 接入公共确认样式及柜次标题;原拣货保护、联动范围、数量、版本和请求顺序不变 |
本批不新增PDA分配入口、装柜方式或权限,不修改三栏工作台的业务筛选和容量统计。
代码已落实为91—103号,唯一截图入口继续维护在[固定编号清单](Admin国内仓样式核对记录.md#当前修改的截图核对清单)。客户备注保留换行并显示为只读文字;运输、其余备注、预装确认的原字段、权限、规范化、版本和操作号均保留。全局工作台新增显式密度根及公共行操作样式,原固定字号改为公共变量;选中柜次使用背景、边框和`aria-pressed`,去掉左侧色条。
外层工作台保留默认全屏、普通模式1600px/94vh及各栏独立滚动。业务专属零内边距和隐藏外层滚动使用更明确的几何选择器,避免公共弹窗样式覆盖后引入第二层滚动。分配窗口保留目标、集装箱号、发货仓、双方渠道、未知测量值及跨渠道警告;同柜组和整托保持完整组成,无部分分配控件。移除确认只补业务标题和公共样式,原请求顺序、范围、拣货保护和版本不变。
三个组件的脚本在排除标题格式化、确认框样式及密度导入后与本批起点一致。初次定向检查识别出旧固定字号和描述块标签断言;已按公共变量及同一确认表格的资料项收敛,未放宽样式所有权检查。新增真实表单验证沿用仓库现有CJS入口,避免测试导入方式影响校验器;覆盖补录/纠错、客户备注只读、全屏保留输入、双版本冲突后重试及PDA作业员必选。全局补查普通与整托精确载荷、待审核未知测量/跨渠道提示、整组和整托原子接口及批量移除。
本批最终验证(2026-10-20):
- 定向8文件151项通过;类型检查、构建及Admin完整419文件3551项测试全部通过,最终四项退出码均为0。
- 重型检查经统一入口串行执行,临时沿用用户已授权的6GB Node堆上限;项目配置、统一入口和worker并发保持原值。
- 本批25个直接源码、测试、API、类型、公共框架、样式和依赖输入在最终完整检查前后散列一致;差异空白检查通过,生成声明、依赖清单和锁文件没有改动。
- 当前仍在`release/test`;本批未提交或部署,91—103号继续等待人工1920×1080、100%缩放截图确认。
- 持续目标未完成。下一组从104号整理客户管理的新增/编辑/查看、资质预览、入驻审核、账号结果及受限操作窗口;已从`CustomersView`的实际调用定位,尚未改写其原权限、资质、账号或凭据流程。当前货柜和预装清单通过不能替代客户管理及其余Admin模块验收。
## 统一弹窗整理:原柜船期与智能装柜(2026-10-19)
本批依据用户确认的[测量样板](界面参考/Admin弹窗样板-测量.png)及[统一高密度规范](Admin高密度界面规范.md),沿`container-loading/routes.ts`的实际货柜列表、详情和智能装柜子路由核对。截图从83号接续;以下为修改前实施矩阵。
| 操作 | 当前承载 | 实施结论 |
|---|---|---|
| 登记原柜船期 | `ContainerPortSchedulePanel`,1120px AppDialog,12项字段 | 原归属资料浅蓝只读表、填写区浅黄连续表、历史浅蓝,标题带柜次,支持全屏;来源、有效期与截止校验保留 |
| 原柜船期维护及历史 | 同一窗口,1000px;4项船运资料及修改原因 | 连续表与原历史记录,去掉内部65vh二次滚动;保留原客户/订舱/货柜归属、版本、冻结请求与关闭后忽略迟到响应 |
| 仅列表权限查看 | 同一窗口,禁用输入框 | 当前四项船运事实直接显示文字,历史保持可见;不新增写权限,不将修改原因输入当作当前事实 |
| 普通入仓码分配箱数 | 智能装柜工作台`assignOpen`,默认AppDialog | 780px浅黄连续表,原货物、可用箱数与本次箱数紧凑横排;保留整数、上下限及原接口 |
| 同柜组/封托托盘加入 | 同一窗口两种分支 | 原来源组成浅蓝、整组/整托事实及不可拆提示保留,无部分箱数输入;支持全屏、原子分配接口不变 |
| 移除普通明细/同柜整组 | 两种原ElMessageBox确认 | 仅标题补柜次业务编号,保留风险提示、联动移除及原版本链 |
实际列表路由经过`ContainerWorkbenchView`复用此前已整理的`ContainersView`;详情的其余直接子面板及打印/费用窗口见前批固定编号。`ContainerOverviewPanel`无额外业务弹框,智能装柜本页只发现上述分配窗口与两种移除确认;不以这一条路由审计推定所有Admin模块已完成。
代码已落实为83—90号,唯一截图入口见[跨模块固定编号](Admin国内仓样式核对记录.md#当前修改的截图核对清单)。原柜归属、当前四项船运事实及历史快照均保留;只读账号不再显示不可编辑的灰色表单,也不将本次修改原因输入当作当前事实。写入账号保留12项首次登记、5项维护字段,以及处理中/待重试时的冻结控件和原请求。
智能装柜仍为独立页面。仅重排居中分配窗口:普通入仓码保留可用箱数、本次数量、摘要及核验说明;同柜组保留全部订单和入仓片段;封托托盘继续使用原入仓组成展开组件。窗口标题显示入仓码、同柜组号或托盘号,移除确认显示柜次。未重写已存在的页头帮助改动、表内箱数编辑或原分配/移除接口。
两份业务脚本在排除本批标题/样式导入,并保留本批之前已存在的`InlineHelp`导入后,与本批起点一致。初次定向6文件102项通过,覆盖原归属校验、首次来源必填、无变化不保存、冲突/失败重试、迟到响应、只读历史、全屏保留值,以及三种分配的精确请求;已将新接入的原柜船期组件纳入公共样式所有权清单。
本组最终验证:
- 补查托盘组成组件后,定向7文件104项通过;类型检查、构建和Admin完整418文件3545项测试全部通过,最终四项退出码均为0。
- 检查经统一入口串行执行,临时沿用用户已授权的6GB Node堆上限;没有修改入口、项目配置或worker并发。
- 本组22个源码、测试、类型、公共框架、样式和依赖输入在最终完整检查前后散列一致;差异空白检查通过,生成声明、依赖清单和锁文件无改动。
- 当前仍在`release/test`,本组未提交或部署;83—90号等待人工1920×1080、100%缩放截图确认。
- 持续目标未全部完成。下一组从91号整理预装清单详情的运输信息、备注、确认推送,以及订单列表实际调用的`SmartLoadingDialog → GlobalSmartLoadingView`及其子窗口。全局工作台通过弹窗嵌入,并非本次已处理的货柜智能装柜子路由;不以同名业务或当前路由通过推定其完成。
## 统一弹窗整理:柜次费用、托盘打印与船节点(2026-10-19)
本组沿货柜详情的实际调用继续,依据用户确认的[测量样板](界面参考/Admin弹窗样板-测量.png)和[高密度规范](Admin高密度界面规范.md)。修改前实施矩阵如下,截图编号从77接续。
| 操作 | 当前承载与直接消费者 | 本组实施结论 |
|---|---|---|
| 新增/调整柜次费用 | `ContainerFeesPanel`的AppDialog,货柜详情唯一调用 | 1080px浅黄连续表,调整资料只读文字与日期/金额同表,支持全屏;保留付款校验、单票和分摊组请求及版本 |
| 多票费用分摊 | 同一费用窗口的逐条卡片 | 同一表单内连续明细表,客户/订单/入仓码只读,金额编辑及合计末行;原分摊限制不变 |
| 驳回/作废柜次费用 | 原AppDialog/ElMessageBox | 原白底原因/确认框,标题带业务编号;保留整组审核、原因必填和版本 |
| 散货托盘码打印选择 | `PalletLabelPrintDialog`的760px AppDialog,货柜详情及清单详情调用 | 仅dense模式改920px,接入浅黄打印选择、浅蓝服务器清单和全屏,标题使用服务端柜号;默认模式和PDF标签格式保留 |
| 人工补录船节点 | `CarrierScheduleQueryPanel`的620px AppDialog | dense模式改780px浅黄连续填写表和全屏,父货柜传业务编号供标题展示;默认消费者保留原排列,窗口观测时间、幂等键及原失败重试不变 |
| 清单详情/清单打印 | 现有页内详情和`window.print()` | 保留既有承载与纸张样式;详情组件本身无额外业务弹框,不因名称含Drawer改造承载 |
本组不会改写其他任务已移除的页面说明,也不将业务编号展示属性写入费用或船节点请求。
代码已落实为77—82号,完整截图入口维护在[固定编号清单](Admin国内仓样式核对记录.md#当前修改的截图核对清单)。新增费用的条件付款字段及备注保留;调整资料不再使用另一套描述组件,方向、项目、供应商、结算和既有备注为只读文字,日期与金额使用原控件。多客户分摊使用同一表单内的连续明细表及合计末行,原分摊范围、正数/合计限制、整组审核和版本不变。
凭证选择提示改为文件格式及最多20个,不展示内部用途枚举。托盘码仅改变选择窗口,不改服务端编号、PDF格式、按仓张数或下载文件名;未开启dense模式的消费者保留原尺寸和排列。船节点同样仅在dense模式接入新布局,默认消费者保留旧排列,业务编号只作标题展示。
三个组件的业务脚本在排除展示标题及柜次上下文后与本组修改前相同。定向覆盖费用权限、候选异步过期、单票及跨客户分摊、调整载荷、已付凭证、托盘码两种密度模式的按仓打印、船节点两种布局下的冲突重试、关闭/全屏和直接货柜详情消费者。后续原柜船期窗口仍待整理,本组不代表全部货柜入口已完成。
首轮定向7文件123项、类型和构建通过;完整检查发现货柜详情的一条旧源码断言将标题、计划及货柜属性拼接为固定相邻顺序,新增展示属性后失败,其余417文件3544项通过。已将该断言改为在同一个`ContainerFeesPanel`标签内逐项核对原标题、计划、真实货柜、客户及业务归属,并核对新增展示属性;没有降低原关联要求或改动运行代码。最终门禁按修正后的测试输入重新执行。
本组最终验证:
- 补齐直接消费者后的定向8文件134项通过;类型检查、构建及完整418文件3545项测试全部通过,最终四项退出码均为0。
- 检查统一经`local-check.ps1`串行执行,沿用本轮已授权的6GB临时Node堆上限,未修改配置或worker并发。
- 本组22个源码、测试、公共框架、样式及依赖输入在最终完整检查前后散列一致;差异空白检查通过,生成声明、依赖清单及锁文件无改动。
- 当前仍在`release/test`;本组未提交或部署,77—82号等待人工1920×1080、100%缩放截图确认。
- 持续目标仍未完成。下一组从83号进入`ContainerPortSchedulePanel`的登记原柜船期、维护/只读及修改历史,随后继续核对货柜剩余入口;不能以本组通过推定所有Admin弹窗已完成。
## 统一弹窗整理:报关与尾程费用(2026-10-19)
本批沿货柜详情的实际共享组件进入,不改变报关与财务流程。视觉依据为本轮用户确认的[测量弹窗样板](界面参考/Admin弹窗样板-测量.png)及[高密度界面规范](Admin高密度界面规范.md),沿用无左色条、浅色背景和紧凑连续表。修改前实施矩阵如下;固定截图编号从62接续,人工视觉结果与自动检查分别记录。
| 操作 | 当前承载 | 本批实施结论 |
|---|---|---|
| 标记海关异常/结果 | 460px原生弹框 | 同尺寸AppDialog、白底短表单、固定底栏;标题带申报批次,保留其他原因必填和原关闭规则 |
| 七种报关确认/说明 | ElMessageBox | 仅补柜次号或申报批次标题,保留确认文本、原因校验、版本和资格 |
| 新增/调整尾程费用 | 620px AppDialog | 920px浅黄连续编辑表、原条件字段与固定底栏、支持全屏;调整时所属客户显示只读文字 |
| 付款凭证预览 | 900px AppDialog | 浅蓝预览区、业务编号标题、完整文件名;图片支持全屏,保留下载、错误和Blob释放 |
| 四种费用确认/原因 | ElMessageBox | 标题带柜次或真实柜号,保留审核、驳回、作废及版本/幂等语义 |
柜次号仅用于窗口标识,真实集装箱号仍独立作为费用写入门禁和请求字段。没有新增权限、状态、业务字段或接口。
本组代码已落实为62—76号,唯一截图入口维护于[跨模块固定编号清单](Admin国内仓样式核对记录.md#当前修改的截图核对清单)。两个共享组件的脚本在排除标题格式化及新增柜次上下文后,与本组修改前完全相同;保存请求、版本、原因校验、上传异步隔离和资源释放没有变化。货柜详情只新增柜次号展示属性,费用业务编号与真实柜号请求仍使用原字段。
新增交互覆盖其他原因必填及原批次版本、取消开始报关、条件付款字段、全屏保留输入、实际费用载荷、调整客户只读和真实柜号缺失门禁。已有凭证替换/移除、客户切换忽略旧上传、只读预览释放资源和报关只读/下载测试保留。样式所有权检查仅将显式`density-table--editable`内的表单按钮与列表行操作区分,普通数据表的行操作检查继续生效。
本组最终验证:
- 定向4文件86项通过;`pnpm typecheck`、`pnpm build`及Admin完整418文件3541项测试全部通过,最终三项退出码均为0。
- 所有重型检查经统一入口串行执行,临时沿用用户已授权的6GB Node堆上限;没有修改项目配置、统一入口或worker并发。
- 本组15个直接源码、测试、样式、框架及依赖输入在最终检查前后散列一致,差异空白检查通过;生成声明、依赖清单和锁文件没有改动。
- 当前仍在`release/test`分支,本组未提交或部署。62—76号等待人工1920×1080、100%缩放截图确认,不以自动检查替代视觉验收。
- 持续目标仍未全部完成。下一组从77号接续共享柜次费用、清单/打印及船节点窗口;本组没有将这些未整理入口计为完成。
## 统一弹窗整理:货柜列表与详情(2026-10-19)
本批从当前`ContainersView`、`ContainerDetailView`的12个实际居中窗口及5个ElMessageBox确认进入,沿用用户已确认的紧凑信息表、浅色背景、无左色条和固定底栏。以下为修改前实施矩阵,正式详情路由保留;不以旧版密度验收或单个消费者推定整组完成。
| 操作 | 当前承载/尺寸 | 本批实施结论 |
|---|---|---|
| 列表 → 编辑基础资料 | `editorOpen`,820px | 17项字段改为1080px三组横排的连续编辑表;只读柜号、柜次、容量、限重直接显示文字;保持仓库/柜型等校验和原保存载荷 |
| 列表 → 新增模拟柜 | `ContainerSimulationCreate`,560px,另由预装入口消费 | 仅dense模式接入紧凑连续表与浅黄填写区;默认消费者保留原样,仓库渠道联动和固定规格不变 |
| 列表/详情 → 关联订舱 | `OceanBookingLinkDialog`,680px | 同一连续表展示柜次号、候选与可选真实柜号;柜次只读,业务编号标题、支持全屏;原筛选/版本/规范化不变 |
| 列表 → 还柜登记 | `drayageActionOpen`,520px | 原短白底时间/备注表单,标题带柜次或集装箱号,原资格与版本保留 |
| 列表 → 邮件记录/重试确认 | `emailHistoryOpen`,1100px;ElMessageBox | 只读浅蓝表格、全屏、业务编号标题;保留最近100封、正文展开、发送风险说明和重试门禁 |
| 列表 → 码头拖车记录 | `drayageHistoryOpen`,980px | 浅绿状态汇总、浅蓝历史表格,编号标题和全屏;错误重试、列与排序保留 |
| 详情 → 确认还柜 | `emptyReturnOpen`,520px | 原白底时间/备注表单及警告、业务编号标题;保留冻结载荷、幂等键重试与关闭保护 |
| 详情 → DO资料 | `documentOpen`,520px | 浅黄上传区和编号标题;当前上传控件重置、替换历史及错误反馈保留 |
| 详情 → 标记/取消异常 | `exceptionOpen`,520px | 白底原因表单及原危险/警告语义,标题带业务编号,必填原因与历史保留 |
| 详情 → 目的港清关资料 | `clearanceOpen`,520px | 浅黄上传区、完成状态沿用原提示;上传与完成动作放入固定底栏,保留加载/提交锁定及原资格 |
| 详情 → 直送卸货登记 | `directOpen`,1080px | 来源浅蓝表格、当前票浅黄连续表;只读票/无写权限显示文本,编辑使用原字段;支持全屏,保持冻结重试和退出保护 |
| 详情 → 提柜安排与执行 | `terminalOpen`,780px | 当前事实与填写内容在同一连续表中;三项原业务动作移到固定底栏,支持全屏,保持权限/待重试载荷/未保存保护 |
| 详情 → 国内出仓/三种未保存确认 | 现有ElMessageBox | 仅补业务编号标题,保留确认文本、动作、阻断和路由保护 |
标题统一使用本模块的柜次号优先、真实集装箱号其次;两个业务标识均缺失时只显示操作名,不使用内部ID补位。本批未新增业务操作或字段,后续固定截图编号从45接续。
本组代码已落实,固定截图编号为45—61,入口唯一清单见[跨模块截图编号](Admin国内仓样式核对记录.md#当前修改的截图核对清单)。四个业务组件的script在排除标题导入/格式化调整后与基线一致,未改动请求、校验、权限、版本、幂等键或关闭保护。直送只读内容显示实际来源记录,不把填写区的默认时间当作已签收事实。
模拟柜仅在显式dense模式使用连续表;默认模式保留原表单。两个模式均通过真实表单必填校验和相同固定规格载荷检查,预装入口的创建消费者同步回归。简短说明、定制固定底栏分别使用公共`density-dialog-note`和`density-actions--footer`;页面只维护字段排列、尺寸与表格列数,不复制公共配色/字号。
本组定向8文件137项通过,类型检查通过。覆盖列表与详情、国内/海外资格、版本0、还柜/提柜/签收冻结重试、关闭保护、全屏保留输入、只读签收凭据、关联订舱规范化与模拟柜两种密度模式。旧的820px双列和无业务编号标题断言已按本次矩阵更新,原业务请求与阻断断言保留。视觉仍待人工1920×1080、100%截图确认,未提交或部署。
初次完整检查418文件3535项及类型/构建通过后,代码复核发现提柜事实表的空值展示还需收敛:真实柜号不能回退为柜次号或窗口标题;已绑定车队但名称缺失时显示“—”,不误称尚未安排。已修正并新增来源响应空值用例,详情交互单文件35项通过,最终完整门禁按修正后的输入重新执行。
本组最终验证:
- `pnpm typecheck`、`pnpm build`均通过;Admin全量418个测试文件、3536项全部通过,三项退出码均为0。
- 所有检查经统一入口串行执行,临时沿用已授权的6GB Node堆上限;统一入口、并发限制与项目配置未修改。
- 本组18个相关源码、测试及共享框架/样式输入在最终完整检查前后散列一致,差异空白检查通过;生成声明、依赖清单和锁文件无本组改动。
- 本组未提交或部署。45—61号继续等待人工1920×1080、100%缩放截图确认,不以自动检查替代视觉验收。
- 持续目标尚未完成。下一组沿实际调用处理`ContainerCustomsPanel`的海关结果与报关确认、`ContainerLastLegFeesPanel`的费用编辑/凭证预览及确认,再接续共享头程费用、清单/打印和船节点窗口;新增截图编号从62开始。没有把这些尚未整理的子窗口记为本组完成。
## 统一弹窗整理:订舱与拖车(2026-10-19)
本批依据《Admin高密度界面规范》的统一弹窗目标和本轮用户对紧凑布局、无左色条的确认,沿实际组件实施以下矩阵。固定截图编号接续《Admin国内仓样式核对记录》的1—35,不另行重排;代码检查与人工截图分别记录,不以旧版密度检查推定新版已通过。
| 页面 → 操作 | 当前承载/直接消费者 | 本批结论 |
|---|---|---|
| 订舱列表/订舱详情 → 选择打印类型 | `OceanBookingPrintDialog`,1120px AppDialog;列表、详情两处调用 | 原两种PDF保留,选择区浅蓝,单选与说明紧凑排列;标题和当前订舱仅用订舱号,缺失不展示内部ID |
| 上一窗口 → PDF预览、返回选择、下载 | 同一1120px窗口和iframe | 保留PDF载体与正常预览高度,PDF阶段增加全屏,固定原底栏;核对返回、关闭、重新选择时的选择值和Blob释放;文件名不以内部ID回退 |
| 订舱详情 → 确认放舱 | `OceanBookingDetailView.releaseDialogOpen`,560px AppDialog | 标题带订舱号,浅绿只读资料表和原警告;去掉面向用户的数据库处理说明,保留不可修改/删除语义及原保存后放舱版本链 |
| 订舱资料 → 替换文件/作废文件 | `OceanBookingDocumentsPanel`,现有ElMessageBox | 沿用已接入的公共确认框样式,标题带订舱号;保留文件名、二次确认、上传限制、作废历史和版本链,操作人缺失不展示数据库ID |
| 订舱详情 → 删除草稿确认 | `OceanBookingDetailView.removeDraft`,现有ElMessageBox | 标题带订舱号,保留原不可恢复说明、删除权限、版本和成功后的列表跳转 |
| 订舱新建/详情、资料主面板 | 正式路由与详情页内组件 | 保留现有承载;不将新建或资料面板改为弹窗 |
订舱详情向共享船期组件仅传`oceanBookingId`,本页不能打开其要求`containerBookingId`的人工补录窗口;该窗口归后续货柜实际消费者整理,不将其列为订舱弹窗完成项。
同批接续下一个实际菜单“拖车列表”,新增与编辑仍沿独立页面执行,仅整理以下浮层:
| 页面 → 操作 | 当前承载/直接消费者 | 本批结论 |
|---|---|---|
| 拖车详情 → 预约附件 | `TruckAttachmentDialog`,640px原生居中弹框;详情唯一直接调用 | 收敛为同尺寸AppDialog,保留原关闭/遮罩规则和固定关闭底栏;预约号标题,上传区浅黄、现有附件浅蓝,长文件名完整换行,支持全屏 |
| 预约附件 → 删除附件 | 原ElMessageBox确认 | 保留删除权限与忙碌门禁,标题带预约号,确认中明确文件名,不展示内部ID |
| 拖车详情 → 状态变更确认 | `TruckAppointmentDetailView.changeStatus`的现有ElMessageBox | 原目标状态、权限及接口保留,仅标题补充预约号;改期沿用页面已有装货时间来源,未新增状态表单 |
固定截图编号为36—44,完整入口继续维护于[截图核对清单](Admin国内仓样式核对记录.md#当前修改的截图核对清单)。打印选择与资料确认属于订舱列表/详情直接消费者;附件窗口由拖车详情唯一调用,正式新增、编辑和详情路由未改动。
按两模块当前Vue文件中的AppDialog/原生弹框和ElMessageBox调用复核,本批覆盖3个居中窗口和5个确认框;打印窗口的选择/预览两种状态分开编号,共9个截图入口。订舱引用的共享船期人工补录窗口不在本页开放,未据此声称共享货柜窗口已完成。
除业务编号标题、缺失值文案及打印资源生命周期外,订舱资料、放舱、拖车附件和状态变更的业务script经差异还原核对与基线一致;保持全部请求字段、权限、版本及文件限制。打印窗口关闭/重开后,迟到的旧请求不会创建或覆盖新的Blob预览;返回选择、退出全屏及下载仍使用当前单据与原打印类型。预览只增加本组件显式全屏布局,不修改AppDialog、公共颜色/字号默认值或PDF输出内容。
本组关键交互与公共密度定向5文件63项通过,覆盖打印类型/全屏/返回/缺失编号/旧请求隔离、资料替换与作废版本链、放舱当前编辑值及附件只读/上传/删除。扩大到订舱、拖车及密度的首次定向检查发现两处新用例的挂载与Blob断言问题,已修正后复验;最终回归还覆盖全屏后保留已选附件和类型。
本组最终验证:
- `pnpm typecheck`、`pnpm build`均通过;Admin全量416个测试文件、3530项全部通过,三项退出码均为0。
- 检查均经统一入口串行执行,临时沿用已授权的6GB Node堆上限;未修改统一入口、并发限制或项目配置。
- 本组14个相关源码、测试及共享样式/框架输入在完整检查前后散列一致,差异空白检查通过;生成声明、依赖清单和锁文件无本组改动。
- 人工视觉仍待1920×1080、100%缩放下按36—44号截图确认,本轮未提交或部署。
- 持续目标尚未完成。下一组从货柜列表的`container-loading/pages/ContainersView.vue`开始,核对当前4个列表窗口及模拟柜、关联订舱直接消费者,再接续`ContainerDetailView.vue`当前6个窗口和其共享子窗口;国内/海外实际消费者分别核对,正式详情路由继续保留。新增截图编号从45开始,不以本组通过推定整个Admin弹窗完成。
## 本次范围与状态 ## 本次范围与状态
用户确认继续优化货柜管理的 4 个菜单。本轮按下表实现列表、独立新建/详情页、智能装柜工作台及关联弹框的密度统一。代码检查结果在文末记录;未进行本轮浏览器视觉验收,所有修改后效果均待人工截图确认。 用户确认继续优化货柜管理的 4 个菜单。本轮按下表实现列表、独立新建/详情页、智能装柜工作台及关联弹框的密度统一。代码检查结果在文末记录;未进行本轮浏览器视觉验收,所有修改后效果均待人工截图确认。
@@ -31,7 +224,7 @@
原型先读 [局部指引](悦/货代SAAS平台后台/AGENTS.md),目标模块为 `prototype-src/modules/06-containers.html`:订舱 `page-booking-list` / `page-booking-detail`,拖车 `page-truck-list` / `page-truck-add` / `page-truck-edit`,历史货柜与装柜入口 `page-ct-list` / `page-ct-manifest` / `page-ct-board`。 原型先读 [局部指引](悦/货代SAAS平台后台/AGENTS.md),目标模块为 `prototype-src/modules/06-containers.html`:订舱 `page-booking-list` / `page-booking-detail`,拖车 `page-truck-list` / `page-truck-add` / `page-truck-edit`,历史货柜与装柜入口 `page-ct-list` / `page-ct-manifest` / `page-ct-board`。
历史原型没有完整表达当前国内/海外双工作台,不能照其页面数量恢复旧菜单。本轮以用户确认的密度规则和当前实际组件、事件为依据,保留如下承载方式: 当前菜单以用户提供的新版.html为准,恢复订舱、拖车、货柜、装柜清单、预装清单五个入口;货柜入口提供国内/海外阶段切换,沿用各自服务端权限与动作。本轮以用户确认的密度规则和当前实际组件、事件为依据,保留如下承载方式:
| 页面/模式 | 操作与承载方式 | 当前组件与依据 | 采用公共规则/业务例外 | 验证与截图 | | 页面/模式 | 操作与承载方式 | 当前组件与依据 | 采用公共规则/业务例外 | 验证与截图 |
|---|---|---|---|---| |---|---|---|---|---|
@@ -77,3 +270,18 @@
- `pnpm typecheck`、`pnpm build` 与 `git diff --check` 通过;AGENTS 索引合同 1050 项通过。 - `pnpm typecheck`、`pnpm build` 与 `git diff --check` 通过;AGENTS 索引合同 1050 项通过。
- 本轮业务脚本与修改前版本对比,仅增加样式导入、确认浮层类和可选密度参数,没有修改业务处理逻辑。实际浏览器加载、长数据布局、浮层普通/全屏/重开及各权限状态仍待 1920×1080、100% 缩放人工截图确认。 - 本轮业务脚本与修改前版本对比,仅增加样式导入、确认浮层类和可选密度参数,没有修改业务处理逻辑。实际浏览器加载、长数据布局、浮层普通/全屏/重开及各权限状态仍待 1920×1080、100% 缩放人工截图确认。
- 本轮未部署、未启动后端或修改业务数据。代码验证不替代实际业务写入及视觉验收。 - 本轮未部署、未启动后端或修改业务数据。代码验证不替代实际业务写入及视觉验收。
## 新版菜单回归矩阵(2026-10-08)
依据:用户提供 `新版.html`,货柜菜单 1480–1487 行、货柜列表 `page-ct-list`(8133、8162 行)、装柜清单 `page-ct-manifest`(8202 行)、尾程计划 `modal-lmo-inbound-plan`(9647 行)。本轮用户确认恢复五菜单并承接海外操作,不回退现行整柜预计到仓规则。
| 页面 | 操作 | 原型承载与布局 | 本轮处理 |
|---|---|---|---|
| 货柜列表 | 国内、海外操作 | 同一货柜入口,宽表含清关/DO/PU/车队/到港/还柜 | 同一菜单内阶段切换,保留现有独立详情与原操作弹框;两阶段分别鉴权 |
| 装柜清单 | 查询、查看 | 独立列表,明细在列表下方展开;宽表水平滚动 | 恢复正式列表路由,复用真实清单查询与嵌入明细 |
| 装柜清单 | 打印 | 行内打印动作 | 读取所选清单成功后打印明细,不打印失败或过期响应 |
| 装柜清单 | 备注、删除 | 原型备注弹框,删除为提示占位 | 当前正式已确认清单只读,不增加未经服务端支持的修改/删除 |
| 尾程计划 | 到仓日期 | 居中计划弹框中日期输入 | 服从现行整柜统一规则,保留只读并补充带柜号跳转维护、计划生成后锁定说明 |
| 其他既有操作 | 新增、编辑、确认、文件 | 见上方逐操作矩阵 | 保留原组件、业务权限与状态门禁,不改变提交契约 |
人工视觉:待用户在1920×1080、100%缩放下截图确认。自动测试与部署结果分别记入主契约,不以源码核对代替真实页面验收。
+73 -7
View File
@@ -25,6 +25,8 @@
本规范与 [Admin/Client 前端原型还原验收规则](Admin-Client前端原型还原验收规则.md) 配合使用。在本规范适用范围内,已确认的密度、容器和页签图标规则优先于历史原型中的大卡片、大留白和单色页签图标;字段、业务分组、权限、操作语义及页面/弹框/抽屉承载方式仍按当前业务契约和逐操作矩阵核对。样板中某个字段的专属宽度不能直接当作其他页面的固定宽度。 本规范与 [Admin/Client 前端原型还原验收规则](Admin-Client前端原型还原验收规则.md) 配合使用。在本规范适用范围内,已确认的密度、容器和页签图标规则优先于历史原型中的大卡片、大留白和单色页签图标;字段、业务分组、权限、操作语义及页面/弹框/抽屉承载方式仍按当前业务契约和逐操作矩阵核对。样板中某个字段的专属宽度不能直接当作其他页面的固定宽度。
2026-10-19,用户确认以下“[弹框与表单](#弹框与表单)”作为所有 Admin 弹窗的统一目标规范,按大模块逐组落实,首组为导航“国内头程”。该弹窗目标范围补充上文早期推广范围;页面、列表、详情页签及 Client/PDA 仍按各自已确认范围执行。规范固定不表示全部弹窗已改造或验收。
## 基本原则 ## 基本原则
表格顶部操作栏的桌面尺寸统一由 `DataTable.vue` 维护:`padding: 6px 12px`、`min-height: 44px`。普通栏与 `.is-compact` 共用尺寸,后者只改变对齐;不再按 1920px 断点切换尺寸。公共密度样式和业务页面不得重复声明这部分 padding / height;组件现有移动端排列规则保留。 表格顶部操作栏的桌面尺寸统一由 `DataTable.vue` 维护:`padding: 6px 12px`、`min-height: 44px`。普通栏与 `.is-compact` 共用尺寸,后者只改变对齐;不再按 1920px 断点切换尺寸。公共密度样式和业务页面不得重复声明这部分 padding / height;组件现有移动端排列规则保留。
@@ -103,6 +105,7 @@
- 汇总使用单行摘要或紧凑描述表。自动费用与其他费用保持各自业务口径,金额、单价、计费量、附加费和版本完整展示。 - 汇总使用单行摘要或紧凑描述表。自动费用与其他费用保持各自业务口径,金额、单价、计费量、附加费和版本完整展示。
- 保留公式、计费依据和价格来源入口,不能为了减少行数合并不同口径的金额或重量。 - 保留公式、计费依据和价格来源入口,不能为了减少行数合并不同口径的金额或重量。
- 测量各来源保留独立分组;展开时在表尾显示合计,折叠时在标题显示摘要,同一口径不在上下重复占位。 - 测量各来源保留独立分组;展开时在表尾显示合计,折叠时在标题显示摘要,同一口径不在上下重复占位。
- 测量作业弹框采用用户确认的彩色分区:申报与实测对比浅绿(`#f4fbf8`)、客户申报明细浅蓝(`#f7f9ff`)、箱规明细浅黄(`#fffbf4`),保留浅色背景、细边框和 8px 圆角,不使用左侧强调色条,作为连续白底规则的局部例外。区块不得使用负外边距伸出正文;左右内边距由 `measurementDensity.css` 统一维护,通用密度规则不得将其清零。保持 1560px、92vh 居中作业弹框及原有业务分组,不因修复裁切而移除彩色分区。 三个分区同级排列,客户申报不得嵌套在实测大框内。箱数、毛重、体积集中在“指标/客户申报/平台实测/差异(实测 − 申报)”表中,不在下方重复总数;未采集显示“未测量/待测量”,申报缺失显示“—”,相等显示“一致”。净重、材积重单独显示平台事实,不与申报毛重混比。 客户申报区保持只读;实际品名和预计托数放在“平台实测箱规”区,沿用原保存与权限规则。未采集时只保留主状态,有箱规和来源后显示采集来源;平台补充数据的口径说明通过提示展示。提交按钮旁显示当前订单状态、缺少测量或称重等实际阻断原因。 桌面布局中,对比区标题与客户、渠道、状态同排;申报区标题与原单据号码同排,标签和值横向排列;实测箱规标题、实际品名、预计托数及录入操作共享一行。长内容自然换行,不截断编号或缩小字号。提交阻断原因集中在固定底栏,正文不重复显示同一提示,业务状态、偏差和冲突提醒保留。
- 同一计算策略只保留一个明确操作入口,保存中、无权限、冻结与失败信息照常显示。 - 同一计算策略只保留一个明确操作入口,保存中、无权限、冻结与失败信息照常显示。
- 称重图片可用缩略图加紧凑事实行;保留查看原图、托盘/库位信息和人工修正入口。可视化、图纸、标签预览、库位示意等按业务用途保留合适尺寸。 - 称重图片可用缩略图加紧凑事实行;保留查看原图、托盘/库位信息和人工修正入口。可视化、图纸、标签预览、库位示意等按业务用途保留合适尺寸。
@@ -114,12 +117,68 @@
### 弹框与表单 ### 弹框与表单
- 保留各操作已确认的独立页面、居中弹框或抽屉承载方式。审核确认不自动变为完整详情;简单备注不套用大型作业弹框。 本节是 **Admin 统一弹窗规范** 的唯一维护入口。2026-10-19 用户确认以测量作业弹窗为视觉样板,统一白底框架、紧凑标题栏、正文分区和固定底部操作。适用于 Admin 各大模块的新增、编辑、审核、只读查看、上传、预览及确认弹窗;按实际用途选择尺寸和内容结构。
- 标题和底部操作保持可见,长内容只滚动正文。优先使用 `AppDialog` 的原生标题栏和已有全屏能力。
- 宽度按内容选择:简单确认/备注参考 560–600px,普通双列表单参考 680–920px,批量预览参考 1100px;订单测量作业样板为 1560px、92vh。以上是类型参考,不是所有弹框的统一固定尺寸。 参考图:[测量弹窗原始截图](界面参考/Admin弹窗样板-测量.png)(原附件 `codex-clipboard-3eeb665f-6eee-437e-886b-75d3cc0dc78e.png`)。截图只用于风格依据,尺寸沿用已确认规范;验收仍为 1920×1080、浏览器 100%,不按图片像素反推控件尺寸。
- 普通弹框参考上边距 6vh、最大高度 88vh;大型测量作业参考上边距 4vh、最大高度 92vh。全屏时使用组件的完整视口规则。
- 表单控件、单位、必填标识、校验错误和原因说明完整保留。长表单按业务分组排两至四列,文本域按需跨列。 ![Admin 弹窗样板:测量作业](界面参考/Admin弹窗样板-测量.png)
- 审核确认清楚展示业务对象;批量审核保留逐票预览、选中数量和不可操作原因。保留处理中锁定、关闭未保存确认与失败上下文。
#### 外框、标题与滚动
- 使用白色外框、细边线和紧凑标题栏;标题为“操作名称 · 业务编号”,没有业务编号时仅显示操作名称,缺失值不以数据库 ID 补位。复用现有标题字号、字重和分隔线。
- 标题栏与底部操作区固定可见,长内容只滚动正文;同一内容区保持一个主要纵向滚动容器。明细表保留业务所需的横向滚动。
- 优先使用 `AppDialog` 的原生标题栏和已有全屏能力;关闭、全屏/退出全屏位于右上角,保留可访问名称。大型表格和作业弹窗按需启用全屏,小型确认弹窗无需强行加入全屏。
- 普通弹窗按内容自然增高,上边距参考 6vh、最大高度 88vh;测量等大型作业弹窗按已确认作业高度使用上边距 4vh、最大高度 92vh。全屏采用组件的完整视口规则。小表单不设置无业务依据的固定大高度或大块空白。
- 各操作已确认的独立页面、居中弹框或抽屉承载方式继续保留。此次统一弹窗外观不改变正式详情路由,也不将抽屉自动改成弹框。
#### 按内容选择尺寸
| 用途 | 桌面宽度参考 | 内容排列 |
|---|---|---|
| 简单确认、备注、原因填写 | 560–600px | 紧凑单列,按内容增高 |
| 普通新增、编辑 | 680–920px | 通常双列;长地址、备注、附件跨列 |
| 多字段表单、资料审核 | 1040–1200px | 短字段通常三列,按业务分组,长内容整行 |
| 批量预览、对照与选择 | 约 1100px,随实际列宽调整 | 表格为主,保留数量、逐条明细和不可操作原因 |
| 测量等大型作业 | 样板 1560px、92vh | 业务分区、作业表格和固定操作底栏 |
以上为类型参考,不覆盖已有逐操作确认的业务尺寸,例如客户重置密码 520px、客户新增/编辑 1120px。宽度同时受视口边距约束;不得靠缩小字号、隐藏字段或截断关键编号来容纳内容。
#### 正文分区、配色与密度
- 短字段使用紧凑表单或连续键值表,明细使用表格;按业务分组保持阅读顺序。分区标题可与客户、渠道、来源单号、状态或当前操作同行,长内容自然换行。
- 同一组含只读与可编辑数据时,优先放在一张连续信息表中:只读值直接展示,可编辑值在对应单元格中录入,保留标签、单位和焦点反馈。标签和值横排,不把只读字段做成禁用输入框;少量预估值并入同组末行,不为套用配色额外拆出大汇总卡片。配色统一不能增加层级、重复标题或挤压业务明细。
- 多分区作业采用浅色背景和细边框,取消左侧强调色条;分区圆角 8px,作为普通容器圆角规则的明确例外。分区同级排列,不层层套卡片。简单确认、短表单及普通说明保持连续白底,按需采用彩色分区。
- 同类信息复用同一配色,保留文字标题;颜色不代替业务状态或校验提示。
| 信息用途 | 样板对应分区 | 浅底色 |
|---|---|---|
| 汇总、实测对比与结论 | 申报与实测对比 | `#f4fbf8` |
| 来源资料、只读申报与明细 | 客户申报明细 | `#f7f9ff` |
| 当前录入、编辑与作业明细 | 平台实测箱规 | `#fffbf4` |
- 表格单元格以白底为主,表头浅灰;普通字号、控件高度、行高、间距沿用本规范公共令牌。单位、必填标识、校验错误、表单标签及原因说明完整保留。
- 汇总尽量只出现一次;表格已完整表达的字段不再另做统计卡片。错误、警告、成功及禁用状态继续使用现有语义,彩色分区不掩盖真实风险。
#### 底部操作与交互
- 底部以细分隔线与正文区分,右侧排列原有取消、保存、提交等操作;一个阶段突出一个主操作,其他操作保持次级样式。按钮职责、顺序和保存触发方式按当前业务确认保留,不新增原本没有的“暂存”或“保存并提交”。
- 自定义底栏可显式使用`density-actions density-actions--footer`,由公共样式维护右对齐、换行和按钮间距,不在业务页复制底栏通用布局。
- 左侧可显示当前状态、选中数量或实际提交阻断原因,同一阻断说明集中显示;只读、预览和小型确认弹窗按其实际动作提供关闭/取消/确认。
- 审核、确认清楚展示业务对象;批量操作保留逐票预览、选中数量和不可操作原因。加载中、无数据、接口失败、无权限、禁用与处理中均应有明确反馈。
- 保留提交锁定、原有遮罩/Esc/关闭规则、未保存保护及失败上下文;全屏切换、关闭和重开不丢失应保留的输入,不允许重复提交。关闭、全屏等功能图标保留,不为统一风格给标题、字段或按钮添加装饰 Emoji。
#### 公共维护与分模块落地
- 框架能力维护在 `AppDialog.vue`,默认尺寸、字号和间距维护在 `adminDensityTokens.css`,通用外观维护在 `adminDensity.css`。彩色分区推广时提取到公共令牌与显式接入的样式原语;模块只维护字段顺序、列数、业务分组和已确认的尺寸例外,不复制通用 CSS。
- 已提供的分区原语为 `density-dialog-section`,通过 `data-tone="summary/source/work"` 分别选择汇总绿、来源蓝、录入黄;分区标题使用 `density-dialog-section__title`,连续分区容器使用 `density-dialog-sections`。弹窗通过 `admin-density-dialog` 接入;保留抽屉并显式采用相同详情密度时使用 `admin-density-drawer admin-density-drawer--detail`;实际侧滑编辑使用 `admin-density admin-density-drawer admin-density-drawer--editor`,复用相同分区、连续编辑表和底栏,不改变其他抽屉。公共选择器保持原弹窗的优先级。测量样板与订单弹窗共同消费 `--admin-dialog-*` 令牌,后续模块沿用同一入口。
- 弹窗内简短说明显式使用 `density-dialog-note`,由公共样式维护辅助字号、颜色和尾距;业务页面不重复这些普通说明外观。
- JSON及原文快照显式使用 `density-code-block`,由公共样式维护代码字号、底色和边框;长内容完整换行,沿用外框正文滚动,不另设固定高度、内容截断或纵向滚动。快照属于诊断证据,不据此将数据库ID展示为业务编号。
- 连续信息表需要单元格编辑时,在 `density-table` 上显式添加 `density-table--editable`;数值与单位使用 `density-table-editor` 横排。输入的普通边框融入表格,保留悬停、键盘焦点及禁用反馈;页面只配置标签列宽和字段排列,不复制输入框外观。
- 小表单继续使用 `density-form`;末项已有明确紧凑尾距约定时显式添加 `density-form--flush-end`,不改变其他表单末项为校验错误保留的空间。
- Teleport 弹框自身显式使用 `admin-density-dialog`,原有 `ElMessageBox` 使用 `admin-density-confirm`;原生 `el-dialog` 的外观按同一规范接入,是否收敛到 `AppDialog` 按实际能力和消费者核对,避免一次替换全部弹窗。抽屉继续使用既有 `admin-density-drawer` 边界。
- 按“盘点当前大模块 → 填写逐操作矩阵 → 完成样板组 → 人工截图确认 → 推广本模块其余弹窗 → 模块整体核对”的流程推进。先从“国内头程”的订单列表相关弹窗开始,以测量弹窗为样板,再依次整理订单测量、测量数据审核、库位管理、托盘管理、整柜业务、船期管理。实际入口以 `adminNavigation.ts` 和模块路由为准,共享弹窗记录全部直接调用方。
- 后续每个大模块按同一流程开展,进度和截图结论写入对应模块核对记录;本规范只维护稳定规则。页面字段、状态、权限、接口、计算口径、校验和提交逻辑继续按当前业务契约执行。
- 代码检查与人工视觉结论分别报告,逐项核对普通/全屏/关闭重开、长内容、空态、错误和权限状态;缺少截图时标记“待人工截图确认”。按模块汇总发布范围,部署继续沿用对应环境授权规则。
## 彩色图标 ## 彩色图标
@@ -176,7 +235,11 @@
## 国内仓、客户管理的样式维护边界 ## 国内仓、客户管理的样式维护边界
本节适用于已接入的两个菜单及其实际子组件,不改变其他菜单默认样式。此次收敛以保留业务字段、权限、计算与承载方式为前提。 2026-09-30 确认的连续列表模式见 [排车列表公共接入规范](Admin排车列表样式试点.md):通过 `DataTable appearance="integrated"` 显式接入标题、业务按钮、查询、结果和分页共用卡片;仅操作列使用蓝色普通文字、红色危险文字并禁止悬停下划线。该模式的行高、卡片、搜索与页头样式由 DataTable 统一维护,行操作外观由 `adminTextActions.css` 维护;查询、顶部和弹框按钮保持原样。此约定优先于本节历史的行内描边、图标和独立路由标题规则;未接入页面保持默认。当前接入范围与特殊页面见 [推广核对记录](Admin列表样式推广核对记录.md)。
本节维护表适用于已接入页面及其实际子组件,当前范围以推广核对记录为准。此次收敛以保留业务字段、权限、计算与承载方式为前提。
页面和区块不再常驻重复的功能介绍。一般流程、计费规则和图表图例复用 `InlineHelp.vue`,在标题或对应操作旁显示信息图标,鼠标移入或键盘聚焦时浮层展示说明,不展开正文或增加独立说明行。已有包含交互操作的统计说明弹层保留其原交互。错误、权限、过期状态、操作阻断和危险后果仍直接展示,不通过全局隐藏段落或说明组件来精简页面。
| 要修改什么 | 唯一维护位置 | 页面需要做什么 | | 要修改什么 | 唯一维护位置 | 页面需要做什么 |
|---|---|---| |---|---|---|
@@ -184,6 +247,7 @@
| 表格行高、输入高度、操作按钮高度、页签高度 | `--admin-row-height`、`--admin-control-height`、`--admin-action-height`、`--admin-tab-height` | 使用已有公共组件和公共类 | | 表格行高、输入高度、操作按钮高度、页签高度 | `--admin-row-height`、`--admin-control-height`、`--admin-action-height`、`--admin-tab-height` | 使用已有公共组件和公共类 |
| 常用间距、圆角、普通数据区底色 | `--admin-space-*`、`--admin-radius`、`--admin-surface` 等 | 业务布局引用变量;不可在页面重定义变量默认值 | | 常用间距、圆角、普通数据区底色 | `--admin-space-*`、`--admin-radius`、`--admin-surface` 等 | 业务布局引用变量;不可在页面重定义变量默认值 |
| 描边按钮外观、悬停/禁用/焦点状态 | `adminDensity.css` 的 `.density-action` | 只选择 `data-tone` 与业务事件 | | 描边按钮外观、悬停/禁用/焦点状态 | `adminDensity.css` 的 `.density-action` | 只选择 `data-tone` 与业务事件 |
| 列表状态/分类页签(国内订单、尾程订单、车辆、供应商、整柜业务、国内/海外货柜工作台、退货库存) | `adminDensity.css` 的 `.density-status-tabs` | 原生按钮使用 `is-active`,Element 页签同时保留 `density-element-tabs`;保留业务分类、图标、数量、查询与切换,不在页面复制页签样式;详情页签继续使用原有详情规则 |
| 详情返回导航 | `.density-back` | 使用 `link`,保留返回事件和可访问名称;客户管理按纯文字约定保留返回文字 | | 详情返回导航 | `.density-back` | 使用 `link`,保留返回事件和可访问名称;客户管理按纯文字约定保留返回文字 |
| 详情页头与业务摘要 | `.density-detail-header` / `.density-detail-heading` / `.density-detail-title` / `.density-detail-overview` | 与国内订单样板共用排版;页面提供实际业务编号、状态及摘要,不复制标题字号和摘要间距 | | 详情页头与业务摘要 | `.density-detail-header` / `.density-detail-heading` / `.density-detail-title` / `.density-detail-overview` | 与国内订单样板共用排版;页面提供实际业务编号、状态及摘要,不复制标题字号和摘要间距 |
| 连续白底独立详情容器 | `DetailPageLayout` 上的 `.density-detail-layout` | 显式接入统一页头分隔线、正文间距与零区块间隙;正文去掉重复面板,业务仅保留列数和长字段跨列 | | 连续白底独立详情容器 | `DetailPageLayout` 上的 `.density-detail-layout` | 显式接入统一页头分隔线、正文间距与零区块间隙;正文去掉重复面板,业务仅保留列数和长字段跨列 |
@@ -215,6 +279,8 @@
`density-actions` 使用 `gap` 管理间距,并将 `--cc-list-action-sibling-margin` 设为 0;`DataTable` 通过该变量保留未接入按钮的默认 8px 左边距。不得将两份间距叠加,也不以更强选择器在页面逐个覆盖。 `density-actions` 使用 `gap` 管理间距,并将 `--cc-list-action-sibling-margin` 设为 0;`DataTable` 通过该变量保留未接入按钮的默认 8px 左边距。不得将两份间距叠加,也不以更强选择器在页面逐个覆盖。
纯文字行操作由 `adminTextActions.css` 统一将按钮横向内边距和组间距减半:每侧 5px、组间距 3px(随公共间距变量缩放),相邻文字间留白由 26px 收紧为 13px。描边操作继续使用原间距;页面不单独覆盖文字操作间距。
### 防止维护退化 ### 防止维护退化
1. **同一通用外观只有一个实现。** 已由公共类接管的按钮配色、页签高度、信息表边框或弹框内边距,删除原页面声明,不能保留两套后再增加优先级或 `!important`。 1. **同一通用外观只有一个实现。** 已由公共类接管的按钮配色、页签高度、信息表边框或弹框内边距,删除原页面声明,不能保留两套后再增加优先级或 `!important`。
+37 -15
View File
@@ -1,41 +1,62 @@
# 虫虫出海文档索引 # 虫虫出海文档索引
项目交付文档按业务域组织。当前开发环境以端到端全流程为统一范围;历史规划、确认和验收记录保留在对应业务域目录,仅用于追溯决策,不构成功能边界。 项目交付文档按业务域组织。当前只有测试环境,以端到端全流程为统一范围;历史规划、确认和验收记录保留在对应业务域目录,仅用于追溯决策,不构成功能边界。
- [测试环境单机部署与配置契约](测试环境单机部署与配置契约.md):唯一环境、部署配置、整体切换与验收。
- [统一认证与服务通信契约](统一认证与服务通信契约.md):统一入口、权限撤销、逐事件投递与幂等。
## 业务域文档 ## 业务域文档
- [业务快速索引](业务快速索引.md):按关键词检索跨端代码入口与业务边界;先查根 AGENTS.md 短路由,按需读取命中行。 - [业务快速索引](业务快速索引.md):按关键词检索跨端代码入口与业务边界;先查根 AGENTS.md 短路由,按需读取命中行。
- 终端业务细则:[Admin](../apps/admin-web/docs/business-index.md)、[Client](../apps/client-web/docs/business-index.md)、[海外 PDA](../apps/pda-overseas-uniapp/docs/business-index.md);先从各应用 AGENTS.md 短表定位,行为变更再核对受影响条款。
- [订单与客户](订单与客户/README.md):登录认证、客户与企业、权限、头程订单和客户工作台。 - [订单与客户](订单与客户/README.md):登录认证、客户与企业、权限、头程订单和客户工作台。
- [入库测量与计费](入库测量与计费/README.md):预约取货、到仓收货、箱码与箱唛、测量、尺寸策略、计价和入库费用。 - [入库测量与计费](入库测量与计费/README.md):预约取货、到仓收货、箱码与箱唛、测量、尺寸策略、计价和入库费用。
- [Firstleg 按需业务索引](../baiyue-firstleg/firstleg/docs/business-index.md):服务代码入口及测量、计价、装柜、PDA 资源结算细则;先读服务 AGENTS,再查受影响条款。
- [国内货柜履约](国内货柜履约/README.md):分柜与同柜、智能排柜、订舱、拖车、PDA 拣货、装柜、报关和国内出仓。 - [国内货柜履约](国内货柜履约/README.md):分柜与同柜、智能排柜、订舱、拖车、PDA 拣货、装柜、报关和国内出仓。
- [船期日历功能规划](国内货柜履约/船期日历功能规划.md):渠道、周模板、单次船期、收货截止时间和按渠道货量统计的独立日历规划。
- [海外仓业务](海外仓业务/README.md):船节点、海外接柜、入仓、库存、托盘、换标、转运、废弃、退货、排车、PDA 出库、派送、异常退回、客户回访、一件代发及海外本土业务。 - [海外仓业务](海外仓业务/README.md):船节点、海外接柜、入仓、库存、托盘、换标、转运、废弃、退货、排车、PDA 出库、派送、异常退回、客户回访、一件代发及海外本土业务。
- [Lastleg 按需业务索引](../baiyue-firstleg/lastleg-service/docs/business-index.md):服务代码入口及事件、查询、履约约束;先读服务 AGENTS,再查受影响条款。
- [排车列表统一作业改造契约](海外仓业务/排车列表统一作业改造契约.md):五阶段排车、一单一趟、跨客户同车、派送安排及四块排车详情的当前改造入口。
- [排车流程修复规划](海外仓业务/排车流程修复规划.md):取消释放、派送状态、换标全托、合托来源和前端草稿的修复边界、分工及回归要求。
- [采购订单样品履约流程变更需求](海外仓业务/采购订单样品履约流程变更需求.md):采购样品购买、装箱、面单、交寄、国内核费与寄客户的变更入口。
- [船节点标准化契约](海外仓业务/船节点标准化契约.md):统一船司原始状态、标准节点、预计/实际时间、异常事实、还柜停止规则和新增船司接入门禁。 - [船节点标准化契约](海外仓业务/船节点标准化契约.md):统一船司原始状态、标准节点、预计/实际时间、异常事实、还柜停止规则和新增船司接入门禁。
- [美国预约管理统一总览与优化方案](海外仓业务/美国预约管理统一总览与优化方案.md):美国段各类预约的范围、关联关系、表单精简及分步实施建议。
- [预约工作日历 V13 变更说明](海外仓业务/预约工作日历V13变更说明.md):多客户共车、分批后送、改期取消、重新预约和未定日期跟进的正式业务规则与验收场景。
- [预约工作日历开发协作契约](海外仓业务/预约工作日历开发协作契约.md):工作日历与完整待办的接口、数据归属和开发文件边界。
- [预约送仓](海外仓业务/README.md#预约送仓):预约日历与跨客户同仓预约入口。
- [车辆管理原型梳理与任务规划](海外仓业务/车辆管理原型梳理与任务规划.md):司机资质、车次、自有/外接承运、运维与报价的范围及契约入口。
- [内部拼车需求池首版开发契约](海外仓业务/内部拼车需求池首版开发契约.md):车次余位发布、销售意向、承运占位、本土订单关联及我仓上车流程。
- [财务管理](财务管理/README.md):应收、应付、费用池、账单、收款、成本、核销、凭证以及国内外业务费用来源。 - [财务管理](财务管理/README.md):应收、应付、费用池、账单、收款、成本、核销、凭证以及国内外业务费用来源。
- [自营业务](自营业务/README.md):平台自营经营总览图表、SKU 销量、分仓产品库存、库存周转视图与数据采集;Admin 入口 `apps/admin-web/src/modules/self-operated/AGENTS.md`,业务设计、采集页面与进度图、查询性能优化及领星 API 联调依据见该业务域入口。
- [打印标签维护](打印标签维护/README.md):箱唛、各类托盘标、HOLD、BOL 与其他单据的现状盘点、参考样张和逐项改版记录。 - [打印标签维护](打印标签维护/README.md):箱唛、各类托盘标、HOLD、BOL 与其他单据的现状盘点、参考样张和逐项改版记录。
## 全流程公共契约 ## 全流程公共契约
- [头程到尾程顺序回路流程图](头程到尾程流程/头程到尾程顺序回路流程图.md):按“主线节点→完成判定→下一节点;异常→处理→回到原节点复核”建模,提供节点卡模板,适合继续画泳道流程图;附[可编辑示例](头程到尾程流程/头程到尾程顺序回路流程图.drawio)。 ### 当前流程入口(收尾变更只看这里)
- [头程到尾程流程节点梳理](头程到尾程流程/头程到尾程流程节点梳理.docx):可直接分发和打印的 Word 文档,按四段流程整理 27 个节点、负责人、正常下一步、异常处理和回流节点。
- [头程到尾程逐节点思维导图](头程到尾程流程/头程到尾程逐节点思维导图.md):按实际节点编号,保留建议负责人、正常去向及异常分支,供人工填写和增删;附[可编辑思维导图源文件](头程到尾程流程/头程到尾程逐节点思维导图.mm)。 - [头程到尾程当前维护入口](头程到尾程/README.md):集中进入总览、六个阶段、货柜入口、报关专题,以及页面和需求参考。
- [头程柜级履约尾程流程节点责任与异常梳理](头程到尾程流程/头程柜级履约尾程流程节点责任与异常梳理.md):按 H/G/W/Z 分解现有流程节点,列出执行岗位、前置、交接、异常和负责人填写栏,附人工待确认问题及[可编辑浏览打印版](头程到尾程流程/头程柜级履约尾程流程节点责任与异常梳理.html)。
- [头程下单到尾程出库全流程操作手册](头程下单到尾程出库全流程操作手册.md):从客户头程下单、国内收货测量、分柜装柜和国内出仓,贯通跨区尾程建单、海外接柜入仓、排车、PDA 拣货与尾程出库的角色、操作、状态、编号、门禁和异常处理。 ### 历史与参考(保留,不作为日常流程入口)
- [头程下单到尾程出库现状流程全景清单](头程下单到尾程出库现状流程全景清单.md):以 F01~F40 盘点现有主链、并行流程、条件分支和异常流,明确操作人、入口/出口状态、单据、编号、数据交接和评审项;应先评审本清单,再进入优化。
- [头程到尾程分阶段流程](头程到尾程分阶段流程/README.md):F01~F40 六个阶段现状文档已全部完成,逐阶段记录操作、字段、状态、数据流、异常、完成判定和上下游交接条件,可按阶段评审并进入优化。 - [头程到尾程历史文档](归档/头程到尾程/README.md):全流程操作手册、旧现状全景、AI 上下文和易用性方案。
- [头程到尾程 AI 流程优化上下文包](头程到尾程AI流程优化上下文包.md):统一 AI 分析所需的术语、流程变体、RACI、阶段合同、阻断分类、问题证据、指标口径、优化卡模板和完成定义。 - [国内货柜履约历史记录](国内货柜履约/归档/README.md):开发规划、进度、门禁、验收矩阵、审计和旧确认材料。
- [头程下单到尾程出库流程易用性与数据流转优化方案](头程下单到尾程出库流程易用性与数据流转优化方案.md):基于已走通主链梳理现状操作问题,提出统一进度、下一动作、操作回执、数据归属、跨区可观测、PDA 易用性、P0-P2 优先级和验收指标。
以上文件继续保留,分别用于历史现状、操作说明和方案追溯;开发规划、进度、门禁和验收记录也按业务域保留,不再与当前节点总表同步改写。
- [跨区域认证与服务通信契约](跨区域认证与服务通信契约.md):统一账号、国内/海外 Token、双区域 API、JWKS、Outbox/Inbox 与服务身份边界。 - [跨区域认证与服务通信契约](跨区域认证与服务通信契约.md):统一账号、国内/海外 Token、双区域 API、JWKS、Outbox/Inbox 与服务身份边界。
- [双区域部署与 Nacos 规划](双区域部署与Nacos规划.md):开发/测试同机共置、生产国内/海外独立控制面、Nacos、数据库及 Event Bridge 部署边界。 - [双区域部署与 Nacos 规划](双区域部署与Nacos规划.md):开发/测试同机共置、生产国内/海外独立控制面、Nacos、数据库及 Event Bridge 部署边界。
### 通用规则与专项入口
- [平台、客户层级与权限契约](平台客户层级与权限契约.md):平台/客户两级产品语义、列表包含详情的只读权限和跨层同步要求。 - [平台、客户层级与权限契约](平台客户层级与权限契约.md):平台/客户两级产品语义、列表包含详情的只读权限和跨层同步要求。
- [统一订单主状态与操作契约](统一订单主状态与操作契约.md):统一订单状态、操作编码、内部状态映射和可信履约回传边界。 - [统一订单主状态与操作契约](统一订单主状态与操作契约.md):统一订单状态、操作编码、内部状态映射和可信履约回传边界。
- [Admin/Client 前端原型还原验收规则](Admin-Client前端原型还原验收规则.md):页面操作承载方式、视觉还原、响应式检查和验收证据要求。 - [Admin/Client 前端原型还原验收规则](Admin-Client前端原型还原验收规则.md):页面操作承载方式、视觉还原、响应式检查和验收证据要求。
- [Admin 高密度界面规范](Admin高密度界面规范.md):已确认订单样板的字号、间距、表格、描述表、弹框和彩色页签规则,以及国内仓、客户管理推广入口。 - [Admin 高密度界面规范](Admin高密度界面规范.md):已确认订单样板的字号、间距、表格、描述表和彩色页签规则;[统一弹窗规范](Admin高密度界面规范.md#弹框与表单)维护所有 Admin 弹窗的目标风格、尺寸分类和分模块实施入口。
- [Admin 客户管理样式核对记录](Admin客户管理样式核对记录.md):客户列表、海外仓阶梯费用及关联详情和弹框的样式与人工验收项。 - [Admin 客户管理样式核对记录](Admin客户管理样式核对记录.md):客户列表、海外仓阶梯费用及关联详情和弹框的样式与人工验收项。
- [Admin 国内仓样式核对记录](Admin国内仓样式核对记录.md):7 个菜单、关联详情与浮层的范围、样式复核和验收证据。 - [Admin 国内仓样式核对记录](Admin国内仓样式核对记录.md):7 个菜单、关联详情与浮层的范围、样式复核和验收证据。
- [Admin 货柜管理样式核对记录](Admin货柜管理样式核对记录.md):订舱、拖车、送柜报关、清关提柜入口及共享组件边界。 - [Admin 货柜管理样式核对记录](Admin货柜管理样式核对记录.md):订舱、拖车、送柜报关、清关提柜入口及共享组件边界。
- [Admin 海外仓样式核对记录](Admin海外仓样式核对记录.md):海外仓 10 个菜单、独立详情、作业弹框和共享组件显式接入边界。 - [Admin 海外仓样式核对记录](Admin海外仓样式核对记录.md):海外仓 10 个菜单、独立详情、作业弹框和共享组件显式接入边界。
- [AI 工程执行与协作约束](AI工程执行与协作约束.md):工作区、依赖、Git、部署、数据库、质量门禁和独立任务协作规则。 - [AI 工程执行与协作约束](AI工程执行与协作约束.md):工作区、依赖、Git、部署、数据库、质量门禁、本机多对话重型检查限流和独立任务协作规则。
- [数据库中文注释维护规范](数据库注释维护规范.md):数据库注释口径、职责、迁移流程、自动门禁与实值验收要求。 - [数据库中文注释维护规范](数据库注释维护规范.md):数据库注释口径、职责、迁移流程、自动门禁与实值验收要求。
- [数据库版本迁移与 Jenkins 自动发布方案](数据库版本迁移与Jenkins自动发布方案.md):两人团队自动迁移规划;统一工具入口、自动编号、开发/测试/生产执行分工、单服务迁移范围、漏写迁移检查、Flyway 校验、失败候选修订、发布证据保留、带数据升级演练及实施顺序。 - [数据库版本迁移与 Jenkins 自动发布方案](数据库版本迁移与Jenkins自动发布方案.md):两人团队自动迁移规划;统一工具入口、自动编号、开发/测试/生产执行分工、单服务迁移范围、漏写迁移检查、Flyway 校验、失败候选修订、发布证据保留、带数据升级演练及实施顺序。
- [数据库迁移操作手册](../baiyue-firstleg/deploy/sql/数据库迁移操作手册.md):开发者和发布执行人日常使用说明;包含新建、检查、生成清单、测试执行、生产晋级、失败处理和维护规则。 - [数据库迁移操作手册](../baiyue-firstleg/deploy/sql/数据库迁移操作手册.md):开发者和发布执行人日常使用说明;包含新建、检查、生成清单、测试执行、生产晋级、失败处理和维护规则。
@@ -49,7 +70,7 @@
## 环境协作 ## 环境协作
- [开发环境独立任务协作登记](开发环境独立任务协作登记.md):开发环境全流程总控与长期专项的稳定任务、职责及开发数据库/部署/HTTP 授权。 - [开发环境独立任务协作登记](开发环境独立任务协作登记.md):开发环境全流程总控与长期专项的稳定任务、职责及开发数据库/部署/HTTP 授权。
- [测试环境独立任务协作登记](独立任务协作登记.md):登记已清空,任务由用户手动管理。 - [测试环境独立任务协作登记](独立任务协作登记.md):测试环境独立任务的稳定身份、职责和协作边界。
- [测试任务盘点与需求台账](测试任务盘点与需求台账.md):历史任务快照、未闭环需求、提交线索和待核实证据,不作为当前调度依据。 - [测试任务盘点与需求台账](测试任务盘点与需求台账.md):历史任务快照、未闭环需求、提交线索和待核实证据,不作为当前调度依据。
## 参考资料 ## 参考资料
@@ -60,7 +81,8 @@
## 维护规则 ## 维护规则
- 新文档按业务域归档,不新增以开发批次编号命名的目录、文件、标题、任务或范围标签。 - 新文档按业务域归档,不新增以开发批次编号命名的目录、文件、标题、任务或范围标签。
- 已完成开发阶段的流程手册、规划、进度和验收资料统一放入 `归档/`;后续流程变更只从[头程到尾程当前维护入口](头程到尾程/README.md)进入。
- 当前交付范围始终按端到端全流程理解;业务域目录只用于检索和职责归属,不用于排除上下游流程。 - 当前交付范围始终按端到端全流程理解;业务域目录只用于检索和职责归属,不用于排除上下游流程。
- 范围、字段或流程冲突时,按“当前对话确认 > 正式契约与确认记录 > 项目指引与代码 > 原型 > 历史记录”判断。 - 范围、字段或流程冲突时遵循根 AGENTS.md 的事实优先级;归档确认记录不覆盖当前正式契约。文档角色按当前入口和明确标记判断,不只按文件名判断。
- 新增或修改业务能力时,同步更新业务域 README、跨端契约、接口、权限、SQL、测试和验收入口。 - 业务事实变化只修改其当前主文档及实际受影响的接口、权限、SQL、代码和测试;业务域 README 与索引仅在入口或职责变化时更新。历史规划、确认和验收记录冻结,不为追随当前规则批量改写。
- 原型中出现的功能不自动成为有效实现;必须由正式契约、代码和验收证据共同确认。 - 原型中出现的功能不自动成为有效实现;必须由正式契约、代码和验收证据共同确认。
+51 -13
View File
@@ -2,11 +2,35 @@
本文件按需检索,不作为启动必读文档。以下路径均按工作区根目录或表内注明的应用源码根目录起算,不相对于 docs/。 本文件按需检索,不作为启动必读文档。以下路径均按工作区根目录或表内注明的应用源码根目录起算,不相对于 docs/。
Firstleg 代码从 `baiyue-firstleg/firstleg/AGENTS.md` 的短表定位;状态、计价、装柜和 PDA 资源规则按需查 `baiyue-firstleg/firstleg/docs/business-index.md` 对应条款,不全文加载其他业务。
Admin、Client、海外 PDA 从各应用 AGENTS.md 短表定位,行为变更按需查 [Admin 细则](../apps/admin-web/docs/business-index.md)、[Client 细则](../apps/client-web/docs/business-index.md)、[海外 PDA 细则](../apps/pda-overseas-uniapp/docs/business-index.md);Lastleg 的事件、查询与履约细则见[服务业务索引](../baiyue-firstleg/lastleg-service/docs/business-index.md),只读取受影响条款。
架构/环境/部署查[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md);网关/Token/会话撤销/事件通信查[统一认证与服务通信契约](统一认证与服务通信契约.md)。下文旧区域服务路径用于定位现有实现,目标规则以这两份主契约为准。
## 常用说法与歧义分流 ## 常用说法与歧义分流
仓储转运审核、转运驳回:Admin 尾程订单 `apps/admin-web/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue` → `apps/admin-web/src/modules/overseas-warehouse/components/WarehouseTransferReviewDialog.vue`;权限、状态及 API 见该模块 `AGENTS.md` 的“仓储转运审核、通过与驳回”。不要按“审核”误入头程订单审核,也不要按“转运”误入排车转派送。 仓储转运审核、转运驳回:Admin 尾程订单 `apps/admin-web/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue` → `apps/admin-web/src/modules/overseas-warehouse/components/WarehouseTransferReviewDialog.vue`;权限、状态及 API 见该模块 `AGENTS.md` 的“仓储转运审核、通过与驳回”。不要把该入口当作头程订单审单,也不要按“转运”误入排车转派送。
先从任务中取“终端 + 业务对象 + 动作”,如“海外 PDA + 柜号 + 收货”。下面是检索提示,不替代业务契约;代码路径均从工作区根起算。用短词检索,不拿整句自然语言做精确匹配。 先从任务中取“终端 + 业务对象 + 动作”,如“海外 PDA + 柜号 + 收货”。优先检索下面列出的组合词,不拿整句自然语言做精确匹配;命中后沿指定模块继续,不把所有含同一宽词的行全部读入。代码路径从工作区根起算,检索提示不替代业务契约。
- 审核:订单审核 / 测量审核 / 仓储转运审核,分别进入 Order / Firstleg / Admin 海外仓模块。
- 库位:海外库位 / 整票库位块,分别进入 Warehouse Overseas / 国内 Warehouse,按任务只选其一。
- 收货:柜号签收 / 到仓测量,分别进入 Lastleg `ReceivingContainerService` / Firstleg 测量入口。
- 拖车:订舱级拖车 / 目的港码头拖车,分别进入 Firstleg `TruckAppointmentService` / `TerminalDrayageService`。
- 托盘:自动生成托盘 / 托盘标签,前者进入 Lastleg `ContainerInboundPlanConversionCoordinator`;后者先区分国内散货、一件代发与海外资源。
先在本节定位组合词,再只查命中的一行或模块。仍无法区分且会改变修改范围时,补问终端、对象或操作阶段。
### 高频任务最小读取集
- 订单审核:根 `AGENTS.md` → `docs/业务快速索引.md` 本节 → `apps/admin-web/src/modules/unified-orders/` → `baiyue-firstleg/order/AGENTS.md`;只有审核门禁跨到履约时才增加 `firstleg/AGENTS.md`。不读海外仓审核或全量权限 SQL。
- PDA 出库:根 `AGENTS.md` → `apps/pda-overseas-uniapp/AGENTS.md` → `src/pages/dispatch/` 和 `src/api/fulfillment.js` → `lastleg-service/AGENTS.md`;只有网关路径或 Token 失败才增加 `gateway/AGENTS.md`。不读 Admin 排车配置,除非问题涉及平台转派送资格。
- 客户账单:根 `AGENTS.md` → Client `apps/client-web/AGENTS.md` → `src/modules/finance/` → `baiyue-firstleg/finance/AGENTS.md`;平台账单才切换 Admin Finance。不要因“账单”自动加载柜费分摊或海外费用契约。
- 退货、异常、拖车:先用终端、阶段和动作分流;无法确定时只读取本节对应行,不全文加载海外仓 README 或 Lastleg 全部业务索引。
- Admin 弹窗样式、统一弹窗:先读 [Admin 统一弹窗规范](Admin高密度界面规范.md#弹框与表单),再进入当前大模块最近指引和实际弹窗组件;逐操作核对记录按 [Admin/Client 验收规则](Admin-Client前端原型还原验收规则.md) 维护。
每个入口标出业务边界,避免把相邻生命周期当作同一业务。读取量与适用指引层级统一遵循根 AGENTS.md;已提供的根规则不重复全文加载,跨服务只增加实际涉及的直接消费者或提供者。
| 常用说法 | 区分依据 | 首个定位范围 | | 常用说法 | 区分依据 | 首个定位范围 |
|---|---|---| |---|---|---|
@@ -19,18 +43,20 @@
| 接柜、卸柜、收货、签收 | 海外 PDA 柜号认领、照片、实收 | `apps/pda-overseas-uniapp/src/pages/operation/operation.vue`;后端查 `ReceivingContainerService` | | 接柜、卸柜、收货、签收 | 海外 PDA 柜号认领、照片、实收 | `apps/pda-overseas-uniapp/src/pages/operation/operation.vue`;后端查 `ReceivingContainerService` |
| 入仓计划、生成计划、按柜生成 | 平台尾程订单预览与确认,不是现场实收 | `apps/admin-web/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue`;后端查 `ContainerInboundPlanConversionCoordinator` | | 入仓计划、生成计划、按柜生成 | 平台尾程订单预览与确认,不是现场实收 | `apps/admin-web/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue`;后端查 `ContainerInboundPlanConversionCoordinator` |
| 审核、审单、批量审核 | 客户头程订单待审核 | `apps/admin-web/src/modules/unified-orders/`;后端查 `BatchOrderReviewPreviewService` | | 审核、审单、批量审核 | 客户头程订单待审核 | `apps/admin-web/src/modules/unified-orders/`;后端查 `BatchOrderReviewPreviewService` |
| 订单审核、头程订单审核、批量审单 | 平台审核客户头程订单,状态以 Order `SUBMITTED` 和服务端 `canApprove/blockReason` 为准;不要按仓储转运审核定位 | Admin `apps/admin-web/src/modules/unified-orders/`;Client 只读订单状态查 `apps/client-web/src/modules/first-leg/`;Backend `baiyue-firstleg/order/` 的 `BatchOrderReviewPreviewService`、`PlatformFirstLegOrderController` |
| 审核、测量审核、实测审核 | 仓库测量结果审核 | `baiyue-firstleg/firstleg/AGENTS.md` 中“审核与初始计价”;页面先查 Admin 入库模块 | | 审核、测量审核、实测审核 | 仓库测量结果审核 | `baiyue-firstleg/firstleg/AGENTS.md` 中“审核与初始计价”;页面先查 Admin 入库模块 |
| 费用、运费、报价、计费、船期价格表、价格簿 | 单票入仓计价、客户专属报价或调价 | `apps/admin-web/src/modules/inbounds/fee/`、`apps/admin-web/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue`(列表/上传)、`apps/admin-web/src/modules/fba-pricing/carrier-rates/pages/CarrierRateDetailView.vue`(版本详情/映射确认);后端查 `FbaPricingService` | | 费用、运费、报价、计费、船期价格表、价格簿 | 单票入仓计价、客户专属报价或调价 | `apps/admin-web/src/modules/inbounds/fee/`、`apps/admin-web/src/modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue`(列表/上传)、`apps/admin-web/src/modules/fba-pricing/carrier-rates/pages/CarrierRateDetailView.vue`(版本详情/映射确认);后端查 `FbaPricingService` |
| 柜费、公共费用、分摊 | 国内柜费来源归 Firstleg;海外柜费来源归 Lastleg;账单与结算结果归 Finance | 业务路由查“财务管理与柜级公共费用分摊”或“海外业务费用来源与客户财务”,按实际请求区分 | | 柜费、公共费用、分摊 | 国内柜费来源归 Firstleg;海外柜费来源归 Lastleg;账单与结算结果归 Finance | 业务路由查“财务管理与柜级公共费用分摊”或“海外业务费用来源与客户财务”,按实际请求区分 |
| 充值、余额、授信、账单、核销 | 客户自助与平台管理先按终端区分 | Client `apps/client-web/src/modules/finance/`;Admin `apps/admin-web/src/modules/finance/` | | 充值、余额、授信、账单、核销 | 客户自助与平台管理先按终端区分 | Client `apps/client-web/src/modules/finance/`;Admin `apps/admin-web/src/modules/finance/` |
| 客户账单、客户对账单、账单确认 | 客户查看和确认本企业账单,不是平台柜费分摊或充值审核 | Client `apps/client-web/src/modules/finance/views/FinanceBillsView.vue`;Admin 平台账单查 `apps/admin-web/src/modules/finance/`;Backend `baiyue-firstleg/finance/` 的 Client Finance Controller |
| 自动生成托盘、托盘码没生成、计划齐全、重试生成托盘码 | 海外入库计划保存后资源生成,不是国内托盘标签打印 | Admin `apps/admin-web/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue`;Backend `baiyue-firstleg/lastleg-service/docs/business-index.md` 的“人工计划自动生成托盘与资源重试”,执行规则先读该服务 `AGENTS.md` | | 自动生成托盘、托盘码没生成、计划齐全、重试生成托盘码 | 海外入库计划保存后资源生成,不是国内托盘标签打印 | Admin `apps/admin-web/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue`;Backend `baiyue-firstleg/lastleg-service/docs/business-index.md` 的“人工计划自动生成托盘与资源重试”,执行规则先读该服务 `AGENTS.md` |
| 托盘码、托盘标签、补打 | 先区分散货装柜、一件代发和海外实体托盘 | 散货 `apps/admin-web/src/modules/loading-lists/components/PalletLabelPrintDialog.vue`;一件代发 `apps/admin-web/src/modules/inbounds/core/DropshipPalletPrintPanel.vue`,从订单“托盘打印”页签进入;海外单张打印 `apps/admin-web/src/modules/overseas-warehouse/pages/PalletsView.vue`,详见各应用/模块指引 | | 托盘码、托盘标签、补打 | 先区分散货装柜、一件代发和海外实体托盘 | 散货 `apps/admin-web/src/modules/loading-lists/components/PalletLabelPrintDialog.vue`;一件代发 `apps/admin-web/src/modules/inbounds/core/DropshipPalletPrintPanel.vue`,从订单“托盘打印”页签进入;海外单张打印 `apps/admin-web/src/modules/overseas-warehouse/pages/PalletsView.vue`,详见各应用/模块指引 |
| 箱码、箱唛、箱标、单箱扫码 | 单箱身份与测量,不是托盘或库位 | 业务路由查“箱唛、箱码与单箱测量”;后端查 `InboundCartonLabelService` | | 箱码、箱唛、箱标、单箱扫码 | 单箱身份与测量,不是托盘或库位 | 业务路由查“箱唛、箱码与单箱测量”;后端查 `InboundCartonLabelService` |
| 库位、托盘、占位、释放 | 国内称重整票块归 Warehouse;海外实物托盘资源归 Warehouse Overseas;业务任务归 Lastleg | 业务路由查“称重确认”或“海外仓库与通用资料”;用国内/海外和业务阶段继续限定 | | 库位、托盘、占位、释放 | 国内称重整票块归 Warehouse;海外实物托盘资源归 Warehouse Overseas;业务任务归 Lastleg | 业务路由查“称重确认”或“海外仓库与通用资料”;用国内/海外和业务阶段继续限定 |
| 海外库位维护、库区、A0溢出位、虚拟收货位 | Admin 海外仓资源维护,区别于 PDA 收货时展示的服务端预留库位 | Admin `apps/admin-web/src/modules/overseas-warehouse/pages/LocationsView.vue` → `api/locations.ts`;海外资源归 `warehouse-overseas-service/`,PDA 收货展示入口见 `apps/pda-overseas-uniapp/src/pages/operation/operation.vue` |
| 拖车、派车、提柜、还柜 | 国内订舱拖车与目的港码头车队是不同业务;海外配送排车另属 Lastleg | 国内 `apps/admin-web/src/modules/trucking/`;目的港 `apps/admin-web/src/modules/container-loading/api/terminalDrayages.ts`;配送查“海外出库、排车” | | 拖车、派车、提柜、还柜 | 国内订舱拖车与目的港码头车队是不同业务;海外配送排车另属 Lastleg | 国内 `apps/admin-web/src/modules/trucking/`;目的港 `apps/admin-web/src/modules/container-loading/api/terminalDrayages.ts`;配送查“海外出库、排车” |
| 报关资料、退税资料、完成文件 | 平台整柜操作与客户订单上传先按终端区分 | Admin `apps/admin-web/src/modules/container-loading/components/ContainerCustomsPanel.vue`;Client `apps/client-web/src/modules/first-leg/components/CustomsDocumentsDialog.vue` | | 报关资料、退税资料、完成文件 | 平台整柜操作与客户订单上传先按终端区分 | Admin `apps/admin-web/src/modules/container-loading/components/ContainerCustomsPanel.vue`;Client `apps/client-web/src/modules/first-leg/components/CustomsDocumentsDialog.vue` |
| 退货、退货预报、退货换标、退货签收、退货合箱 | 客户退货预报及签收库存,区别于派送异常退回 | Client `apps/client-web/src/modules/overseas-warehouse/views/ReturnOrdersView.vue`;Admin `apps/admin-web/src/modules/overseas-warehouse/pages/ReturnInventoryManagementView.vue`;PDA `apps/pda-overseas-uniapp/AGENTS.md`;Lastleg `returnreceipt/`,见下文“退货预报、签收、库存与合箱” | | 退货、退货预报、退货换标、退货签收、退货合箱 | 客户退货预报及签收库存,区别于派送异常退回 | Client `apps/client-web/src/modules/overseas-warehouse/views/ReturnOrdersView.vue`;Admin `apps/admin-web/src/modules/overseas-warehouse/pages/ReturnInventoryManagementView.vue`;PDA `apps/pda-overseas-uniapp/AGENTS.md`;Lastleg `returnreceipt/`,见下文“退货预报、签收、库存与合箱” |
| PDA 出库、PDA 发车、扫码出库、整托出库 | 海外 PDA 执行排车和出库,不是平台排车配置或客户派送查询 | 海外 PDA `apps/pda-overseas-uniapp/src/pages/dispatch/dispatch.vue`、`src/api/fulfillment.js`;Backend `baiyue-firstleg/lastleg-service/dispatch/pda/`;统一经 `gateway/` |
| 异常、退回、退仓、回访 | 派送异常退回与库存退货业务不可混用 | 派送查 `apps/admin-web/src/modules/overseas-warehouse/pages/ExceptionOrdersView.vue`;退货预报/库存查 Lastleg `returnreceipt/` | | 异常、退回、退仓、回访 | 派送异常退回与库存退货业务不可混用 | 派送查 `apps/admin-web/src/modules/overseas-warehouse/pages/ExceptionOrdersView.vue`;退货预报/库存查 Lastleg `returnreceipt/` |
## 定位步骤与反馈 ## 定位步骤与反馈
@@ -44,13 +70,22 @@
## 业务快速路由表 ## 业务快速路由表
领星 WMS 自研系统(OMP)、经营总览图表、自营 SKU 日销量、热销与滞销排行、分仓产品库存与可售天数、库存周转、数据采集:先读 `apps/admin-web/src/modules/self-operated/AGENTS.md`;查询与采集编排查 `baiyue-firstleg/lastleg-service/AGENTS.md` 的自营入口,签名/限流/供应商分页问题才读 `baiyue-firstleg/integration-service/AGENTS.md`。区别于整箱库存和客户 WMS 作业库存。
自营专题按任务选择:总览图形/下钻查 `docs/自营业务/经营总览图表设计.md`,库存周转查 `docs/自营业务/库存周转视图设计.md`,采集交互查 `docs/自营业务/数据采集页面设计.md`,查询性能查 `docs/自营业务/领星统计查询性能优化方案.md`,外部接口联调查 `docs/自营业务/领星WMS接口联调手册.md`。架构/表结构不明时从 `docs/自营业务/README.md` 定位一期方案,不默认同时读取所有专题。
美国各类预约统一总览、提柜/用车/送仓预约梳理:`docs/海外仓业务/美国预约管理统一总览与优化方案.md`(设计建议);实际维护仍按下述来源模块进入。
预约工作日历、多客户共车、中转分批后送、改期取消、重新预约和未定日期事项:先读 `docs/海外仓业务/预约工作日历V13变更说明.md`(正式业务规则与验收),再读 `docs/海外仓业务/预约工作日历开发协作契约.md`(接口与文件边界);权威业务事实仍由下述来源模块维护。
预约管理、预约列表、到港/排车/还柜/计划到仓四类日历:Admin `apps/admin-web/src/modules/appointment-calendar/`,当前入口与日期规则见 `docs/海外仓业务/预约工作日历V13变更说明.md` 的“2026-10-19 当前预约列表收敛规则”;原送仓业务仍从 `docs/海外仓业务/README.md` 的“预约送仓”进入。排车只取海外仓送往 FBA/客户仓的真实车次,区别于订舱级拖车和港口提柜。
退货预报、签收、库存与合箱:Client `modules/overseas-warehouse/views/ReturnOrdersView.vue`、`ReturnInventoryView.vue`;Admin `modules/overseas-warehouse/pages/ReturnInventoryManagementView.vue`;海外 PDA `src/pages/return-receipt/return-receipt.vue`、`src/pages/return-packing/return-packing.vue`,API 与检查入口见 `apps/pda-overseas-uniapp/AGENTS.md`;Backend `lastleg-service/returnreceipt/`,执行规则先读 `baiyue-firstleg/lastleg-service/AGENTS.md`,详细接口与状态按需查 `baiyue-firstleg/lastleg-service/docs/business-index.md` 的退货入口,OpenAPI 为 `overseas-business-v1.yaml`。客户预报 → 平台审核 → PDA 签收 → 退货箱/SKU 库存 → 同客户合箱 → `delivery/` 退货出库;两个 PDA 页面均在 `src/pages.json` 注册,由 `src/data/overseas-workbench.js` 提供入口,真机验收另取证。派送异常退回仍归 `exceptionorder/`。 退货预报、签收、库存与合箱:Client `modules/overseas-warehouse/views/ReturnOrdersView.vue`、`ReturnInventoryView.vue`;Admin `modules/overseas-warehouse/pages/ReturnInventoryManagementView.vue`;海外 PDA `src/pages/return-receipt/return-receipt.vue`、`src/pages/return-packing/return-packing.vue`,API 与检查入口见 `apps/pda-overseas-uniapp/AGENTS.md`;Backend `lastleg-service/returnreceipt/`,执行规则先读 `baiyue-firstleg/lastleg-service/AGENTS.md`,详细接口与状态按需查 `baiyue-firstleg/lastleg-service/docs/business-index.md` 的退货入口,OpenAPI 为 `overseas-business-v1.yaml`。客户预报 → 平台审核 → PDA 签收 → 退货箱/SKU 库存 → 同客户合箱 → `delivery/` 退货出库;两个 PDA 页面均在 `src/pages.json` 注册,由 `src/data/overseas-workbench.js` 提供入口,真机验收另取证。派送异常退回仍归 `exceptionorder/`。
本表只路由到范围依据和首个代码入口;Admin/Client 路径从对应应用的 `src/` 起算,国内 PDA 路径从 `apps/pda-uniapp/` 起算,海外 PDA 路径从 `apps/pda-overseas-uniapp/src/` 起算,Backend 路径从 `baiyue-firstleg/` 起算。进入目标后继续读最近的 `AGENTS.md`,不要把根表当作模块细节清单。 本表只路由到范围依据和首个代码入口;Admin/Client 路径从对应应用的 `src/` 起算,国内 PDA 路径从 `apps/pda-uniapp/` 起算,海外 PDA 路径从 `apps/pda-overseas-uniapp/src/` 起算,Backend 路径从 `baiyue-firstleg/` 起算。进入目标后继续读最近的 `AGENTS.md`,不要把根表当作模块细节清单。
| 业务 | 范围依据 | 首个代码入口 | | 业务 | 范围依据 | 首个代码入口 |
|---|---|---| |---|---|---|
| 登录认证 | `docs/订单与客户/README.md` | Admin `modules/auth/`、`core/auth/`;Client `modules/auth/`;Backend `auth/`、`iam/`。海外 Token 不携带角色或权限集,Admin/Client/海外 PDA 从 Auth 登录与刷新响应的顶层授权快照读取,海外 Gateway 再按 IAM 安全投影校验 | | 登录认证 | `docs/订单与客户/README.md` | Admin `modules/auth/`、`core/auth/`;Client `modules/auth/`;Backend `auth/`、`iam/`。统一 Token 不携带角色或权限集;各端读取 Auth 登录/刷新响应的顶层授权快照用于展示,Gateway 与业务服务通过统一会话及 Auth 权威校验执行授权,不再依赖 Lastleg 安全投影 |
| 客户与企业 | `docs/订单与客户/README.md`、`docs/订单与客户/订单与客户头程订单闭环设计.md` | Admin `modules/customers/`;Client `modules/tenant-management/`、`modules/account/`;Backend `iam/`、`auth/`、`file/`。公司联系电话/邮箱是企业资料,不作为成员登录标识且不要求跨企业唯一;成员登录手机号归账号链路,修改时同步 Auth 并撤销该账号会话。审核必填资质仅营业执照与统一社会信用代码;法人身份证选填,可在已有营业执照后单独补传或替换,营业执照仍须与统一社会信用代码整包提交;默认尺寸配置由 IAM 持久任务异步调用 `firstleg/`,未就绪不得审核通过 | | 客户与企业 | `docs/订单与客户/README.md`、`docs/订单与客户/订单与客户头程订单闭环设计.md` | Admin `modules/customers/`;Client `modules/tenant-management/`、`modules/account/`;Backend `iam/`、`auth/`、`file/`。公司联系电话/邮箱是企业资料,不作为成员登录标识且不要求跨企业唯一;成员登录手机号归账号链路,修改时同步 Auth 并撤销该账号会话。审核必填资质仅营业执照与统一社会信用代码;法人身份证选填,可在已有营业执照后单独补传或替换,营业执照仍须与统一社会信用代码整包提交;默认尺寸配置由 IAM 持久任务异步调用 `firstleg/`,未就绪不得审核通过 |
| 供应商与国内整柜 | `docs/国内货柜履约/国内货柜履约需求确认表.md` | Admin `modules/suppliers/`、`modules/domestic-containers/`;Backend `warehouse/`;OpenAPI `supplier-v1.yaml`、`domestic-container-v1.yaml` | | 供应商与国内整柜 | `docs/国内货柜履约/国内货柜履约需求确认表.md` | Admin `modules/suppliers/`、`modules/domestic-containers/`;Backend `warehouse/`;OpenAPI `supplier-v1.yaml`、`domestic-container-v1.yaml` |
| 平台收货仓 | `docs/订单与客户/订单与客户头程订单闭环设计.md` | Admin `modules/warehouses/`;Client `modules/first-leg/`;Backend `warehouse/` | | 平台收货仓 | `docs/订单与客户/订单与客户头程订单闭环设计.md` | Admin `modules/warehouses/`;Client `modules/first-leg/`;Backend `warehouse/` |
@@ -58,17 +93,17 @@
| 客户头程订单批量导入 | 当前 Order 契约 | Client `modules/first-leg/views/FirstLegOrdersView.vue`、`api/firstLeg.ts`;Backend `order/` 的 `MerchantBatchImportService`、`MerchantWarehouseCatalogClient`、`MerchantPricingCatalogClient` 与 `order-v1.yaml`。中文 XLSX 模板按当前客户动态生成地址、全部有效仓库和渠道下拉;导入时重新校验动态选项与客户归属,最多 50 行,只创建草稿,支持部分成功或整批原子模式 | | 客户头程订单批量导入 | 当前 Order 契约 | Client `modules/first-leg/views/FirstLegOrdersView.vue`、`api/firstLeg.ts`;Backend `order/` 的 `MerchantBatchImportService`、`MerchantWarehouseCatalogClient`、`MerchantPricingCatalogClient` 与 `order-v1.yaml`。中文 XLSX 模板按当前客户动态生成地址、全部有效仓库和渠道下拉;导入时重新校验动态选项与客户归属,最多 50 行,只创建草稿,支持部分成功或整批原子模式 |
| 平台旧系统订单导入 | 当前 Order 契约 | Admin `modules/unified-orders/pages/UnifiedOrdersView.vue`、`api/unifiedOrders.ts`;Backend `order/` 的 `PlatformLegacyOrderImportService` 与 `/api/platform/v1/orders/first-leg/legacy-import`。固定归属启用客户“IT测试公司”,保留旧入仓码,按当前公共仓库和客户价格簿逐行校验,成功行进入待审核 | | 平台旧系统订单导入 | 当前 Order 契约 | Admin `modules/unified-orders/pages/UnifiedOrdersView.vue`、`api/unifiedOrders.ts`;Backend `order/` 的 `PlatformLegacyOrderImportService` 与 `/api/platform/v1/orders/first-leg/legacy-import`。固定归属启用客户“IT测试公司”,保留旧入仓码,按当前公共仓库和客户价格簿逐行校验,成功行进入待审核 |
| 平台修改客户原始申报与履约渠道 | 当前 Order/Firstleg 契约 | Admin `modules/unified-orders/components/OrderDeclarationEditorDialog.vue`、`api/unifiedOrders.ts`;Backend `order/` 的 `OrderDeclarationUpdateService` 与 `order-v1.yaml`,通过 `ORDER_DECLARATION_UPDATED_V1` 同步 `firstleg/` 的 `OrderDeclarationSyncService`。只修改申报快照,不覆盖仓库/PDA 实测、测量审核、箱码或已确认费用;渠道变化额外校验分柜、同柜、装柜可逆性与重新计价,国内收货仓或中转仓变化必须重新下单 | | 平台修改客户原始申报与履约渠道 | 当前 Order/Firstleg 契约 | Admin `modules/unified-orders/components/OrderDeclarationEditorDialog.vue`、`api/unifiedOrders.ts`;Backend `order/` 的 `OrderDeclarationUpdateService` 与 `order-v1.yaml`,通过 `ORDER_DECLARATION_UPDATED_V1` 同步 `firstleg/` 的 `OrderDeclarationSyncService`。只修改申报快照,不覆盖仓库/PDA 实测、测量审核、箱码或已确认费用;渠道变化额外校验分柜、同柜、装柜可逆性与重新计价,国内收货仓或中转仓变化必须重新下单 |
| 脚本管理、全量验证与测试造数 | `baiyue-firstleg/scripts/AGENTS.md`、`baiyue-firstleg/scripts/README.md` | Backend `scripts/` 为仓库级入口,`scripts/admin-test-env-modules/` 为 Admin HTTP 内部模块;服务局部脚本留在 `<service>/scripts/`,不得散落到 `src/test/scripts/`;真实 HTTP、部署或环境写入仍须当前轮明确授权 | | 脚本管理、全量验证与测试造数 | `baiyue-firstleg/scripts/AGENTS.md`、`baiyue-firstleg/scripts/README.md` | 本机重型检查经 `scripts/local-check.ps1` 统一限流,规则见 `docs/AI工程执行与协作约束.md`;Backend `scripts/` 为仓库级入口,`scripts/admin-test-env-modules/` 为 Admin HTTP 内部模块;服务局部脚本留在 `<service>/scripts/`,不得散落到 `src/test/scripts/`;真实 HTTP、部署或环境写入仍须当前轮明确授权 |
| 平台/企业 RBAC | 订单与客户契约;公共语义见 `docs/平台客户层级与权限契约.md` | Admin `modules/iam/`、`core/access/`;Client `modules/tenant-management/`;Backend `iam/`、`auth/` | | 平台/企业 RBAC | 订单与客户契约;公共语义见 `docs/平台客户层级与权限契约.md` | Admin `modules/iam/`、`core/access/`;Client `modules/tenant-management/`;Backend `iam/`、`auth/` |
| 消息中心与站内通知 | 触发业务的阶段/专题契约,收件箱以 IAM OpenAPI 为准 | Admin/Client `modules/notifications/`;Backend `iam/.../notification/`;生产者留在所属服务 | | 消息中心与站内通知 | 触发业务的阶段/专题契约,收件箱以 IAM OpenAPI 为准 | Admin/Client `modules/notifications/`;Backend `iam/.../notification/`;生产者留在所属服务 |
| PDA 拣货与柜级装柜证据 | 国内 PDA README、拣货原型、国内货柜履约需求确认 | PDA `pages/picking/`、`stores/picking.js`、`api/pda-loading.js`;证据以 `taskId + warehouseId` 进入任务专用 API,业务所有权固定真实 `containerBookingId`,不得按入仓单或客户拆分;上传以幂等键绑定包含文件内容的请求哈希,完全重放直接返回已有结果且不得重复上传 File;Backend `firstleg/`、`warehouse/`、`file/` | | PDA 拣货与柜级装柜证据 | 国内 PDA README、拣货原型、国内货柜履约需求确认 | PDA `pages/picking/`、`stores/picking.js`、`api/pda-loading.js`;证据以 `taskId + warehouseId` 进入任务专用 API,业务所有权固定真实 `containerBookingId`,不得按入仓单或客户拆分;上传以幂等键绑定包含文件内容的请求哈希,完全重放直接返回已有结果且不得重复上传 File;Backend `firstleg/`、`warehouse/`、`file/` |
| 到仓测量、测量库位、箱规策略与头程计费 | `docs/入库测量与计费/README.md`、测量计费入库主流程 | Admin 测量 `modules/inbounds/measurement/InboundMeasurementDialog.vue`、`InboundMeasurementPanel.vue`,称重 `modules/inbounds/weight/components/WeightOcrPanel.vue`,以及 `warehouse-resources/`、`fba-pricing/`、`dimension-config/`、`fee-items/`;Backend `firstleg/` 的 `InboundMeasurementService`、`MeasurementLocationOccupationService`、`MeasurementSubmissionService`、`CustomerDimensionConfigService`、`CustomerDimensionWeightingService`、`FbaPricingService`,并联查 `warehouse/`、`file/`、`integration-service/`。整票库位按确认图片数与有效体积容量需求的较大值尽力预留,扩容只追加且删除图片保留空槽;库位指引失败不阻断称重确认或测量提交。客户固定四档箱规可选择 `ADD/MULTIPLY`,计价和费用确认以服务端及当前实际测量明细为准 | | 到仓测量、测量库位、箱规策略与头程计费 | `docs/入库测量与计费/README.md`;规则查 `baiyue-firstleg/firstleg/AGENTS.md` 对应入口 | Admin `modules/inbounds/measurement/InboundMeasurementDialog.vue`、`InboundMeasurementPanel.vue`,称重 `modules/inbounds/weight/components/WeightOcrPanel.vue`;Backend `firstleg/` 的 `InboundMeasurementService`、`MeasurementLocationOccupationService`、`FbaPricingService`。库位归 `warehouse/`,图片归 `file/`,OCR 归 `integration-service/`;只按实际调用增加服务指引 |
| 客户专属报价、柜级阶梯运费与费用调整 | 当前 Firstleg 计价契约、`docs/入库测量与计费/README.md` | Admin `modules/fba-pricing/carrier-rates/`、`modules/inbounds/fee/`、`modules/unified-orders/components/InboundFeeDetailManager.vue`;Backend `firstleg/` 的 `PlatformPriceBookService`、`ActivePriceBookEstimator`、`FbaPricingService`、`ContainerTierAmountAllocator`、`InboundFeeDetailService` 与 `fba-pricing-v1.yaml`。公共报价使用 `customerId=0`,客户专属报价按客户独立版本化并优先于公共 ACTIVE 版本;柜级区域重量阶梯只聚合同柜同客户中费用快照同为 `REGION_WEIGHT_TIER` 的成员并守恒分摊,混柜的固定仓价等其他模型不参与阶梯且保持原费用,装柜成员变化只重算未锁定的区域阶梯费用。人工调整计费量限系统基准上下 10% 且必须带版本、原因和二次确认;`PRIVATE_LAST_MILE_DELIVERY` 只允许私人目的仓;一件代发在预装确认前完成计价,`WAIT_PALLETIZE` 试算不得回退托盘化状态 | | 客户专属报价、柜级阶梯运费与费用调整 | 当前 Firstleg 计价契约、`docs/入库测量与计费/README.md` | Admin `modules/fba-pricing/carrier-rates/`、`modules/inbounds/fee/`、`modules/unified-orders/components/InboundFeeDetailManager.vue`;Backend `firstleg/` 的 `PlatformPriceBookService`、`ActivePriceBookEstimator`、`FbaPricingService`、`ContainerTierAmountAllocator`、`InboundFeeDetailService` 与 `fba-pricing-v1.yaml`。公共报价使用 `customerId=0`,客户专属报价按客户独立版本化并优先于公共 ACTIVE 版本;柜级区域重量阶梯只聚合同柜同客户中费用快照同为 `REGION_WEIGHT_TIER` 的成员并守恒分摊,混柜的固定仓价等其他模型不参与阶梯且保持原费用,装柜成员变化只重算未锁定的区域阶梯费用。人工调整计费量限系统基准上下 10% 且必须带版本、原因和二次确认;`PRIVATE_LAST_MILE_DELIVERY` 只允许私人目的仓;一件代发在预装确认前完成计价,`WAIT_PALLETIZE` 试算不得回退托盘化状态 |
| 箱唛、箱码与单箱测量 | `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md`、`docs/墨家设备测量上传接口说明-V3.md` | Admin `modules/inbounds/measurement/`;Client `modules/first-leg/`;Backend 按 `firstleg/AGENTS.md` 的箱唛与测量入口 | | 箱唛、箱码与单箱测量 | `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md`、`docs/墨家设备测量上传接口说明-V3.md` | Admin `modules/inbounds/measurement/`;Client `modules/first-leg/`;Backend 按 `firstleg/AGENTS.md` 的箱唛与测量入口 |
| 称重确认、整票库位块与部分拣货资源结算 | 入库测量与计费主流程、国内货柜履约 PDA 契约 | Admin `modules/inbounds/weight/components/WeightOcrPanel.vue`;Backend `firstleg/` 的 `MeasurementLocationOccupationService`、`InboundMeasurementService`、`MeasurementSubmissionService` 与 `warehouse/` 的 `LocationBlockService`。测量提交审核前至少上传并确认一张称重图片,单箱也不得免称重;称重确认尽力建立整票块,提交时再次补齐,库位指引失败不阻断称重确认或测量提交。容量按确认图片数与有效体积折算的较大值,最新测量批次内实测/冻结申报体积取有效较大值;删除图片只清空绑定不释放槽位。部分拣货有余量时整段转移给子单,整票拣完才一次性释放全部普通位与共享 A0,资源身份以 `reservationId` 为准 | | 称重确认、整票库位块与部分拣货资源结算 | `baiyue-firstleg/firstleg/AGENTS.md` 的称重入口、`baiyue-firstleg/warehouse/AGENTS.md` 的 A0/资源结算规则 | Admin `modules/inbounds/weight/components/WeightOcrPanel.vue`;Backend Firstleg `MeasurementLocationOccupationService`、`InboundMeasurementService`、`MeasurementSubmissionService` → Warehouse `LocationBlockService`。国内整票资源结算按 `reservationId` 定位;称重、槽位容量和部分拣货的详细门禁留在所属服务指引 |
| 入库扣货、解除与凭证 | 入库测量与计费、国内货柜履约契约 | Admin `modules/unified-orders/pages/UnifiedOrdersView.vue`、`modules/inbounds/core/api.ts`;Backend `firstleg/` 的 `InboundHoldService`、`InboundHoldGuard`、`InboundHoldEvidenceService`,文件归 `file/` 的 `INBOUND_HOLD_EVIDENCE`。扣货状态必须阻断后续物理履约写入;已发生拣货、装柜或出仓时禁止手工扣货/解除,命令携带版本与幂等键,只有进入不可变历史的凭证可下载 | | 入库扣货、解除与凭证 | 入库测量与计费、国内货柜履约契约 | Admin `modules/unified-orders/pages/UnifiedOrdersView.vue`、`modules/inbounds/core/api.ts`;Backend `firstleg/` 的 `InboundHoldService`、`InboundHoldGuard`、`InboundHoldEvidenceService`,文件归 `file/` 的 `INBOUND_HOLD_EVIDENCE`。扣货状态必须阻断后续物理履约写入;已发生拣货、装柜或出仓时禁止手工扣货/解除,命令携带版本与幂等键,只有进入不可变历史的凭证可下载 |
| 财务管理与柜级公共费用分摊 | `docs/财务管理/` 产品确认、五页验收契约、Firstleg-Finance 跨服务契约 | Admin `modules/finance/`、`modules/loading-lists/components/ContainerFeesPanel.vue`;Client `modules/finance/views/FinanceBillsView.vue`,账单行按 `inboundCode` 复用头程入仓关系详情;Backend `finance/`、`firstleg/`,契约 `container-fees-v1.yaml`;导出与凭证归 `file/`。跨客户公共柜费按柜内真实客户与订单归属原子建组,金额合计等于柜费总额,审核、驳回、调整和作废整组处理,单行入口不得破坏组一致性 | | 财务管理与柜级公共费用分摊 | `docs/财务管理/` 产品确认、五页验收契约、Firstleg-Finance 跨服务契约 | Admin `modules/finance/`、`modules/loading-lists/components/ContainerFeesPanel.vue`;Client `modules/finance/views/FinanceBillsView.vue`,账单行按 `inboundCode` 复用头程入仓关系详情;Backend `finance/`、`firstleg/`,契约 `container-fees-v1.yaml`;导出与凭证归 `file/`。跨客户公共柜费按柜内真实客户与订单归属原子建组,金额合计等于柜费总额,审核、驳回、调整和作废整组处理,单行入口不得破坏组一致性 |
| 客户资金账户、充值、授信与业务扣费 | `docs/财务管理/README.md`、跨区域认证与服务通信契约 | Admin `modules/finance/pages/FinanceCustomerAccountsView.vue`;Client `modules/finance/views/FinanceAccountView.vue`;Backend `finance/` 的 `FinanceWalletService` 与三类 Wallet Controller。充值申请经 File 保存凭证,平台审核或手工充扣;余额、授信、冻结、结算和释放以 Finance 主账为准。海外业务经 `WALLET_COMMAND_REQUESTED/COMPLETED` Outbox/Event Bridge 往返,不跨区同步调用钱包 | | 客户资金账户、充值、授信与业务扣费 | `docs/财务管理/README.md`、统一认证与服务通信契约 | Admin `modules/finance/pages/FinanceCustomerAccountsView.vue`;Client `modules/finance/views/FinanceAccountView.vue`;Backend `finance/` 的 `FinanceWalletService` 与三类 Wallet Controller。充值申请经 File 保存凭证,平台审核或手工充扣;余额、授信、冻结、结算和释放以 Finance 主账为准。海外业务经 `WALLET_COMMAND_REQUESTED/COMPLETED` Outbox 直接投递往返,不跨区同步调用钱包 |
| 订单编排、分柜、同柜不可拆组与柜次 | `docs/国内货柜履约/README.md`、`docs/国内货柜履约/国内货柜履约需求确认表.md`、`docs/统一订单主状态与操作契约.md` | Admin `modules/unified-orders/api/coLoadGroups.ts`、`modules/unified-orders/`、`container-loading/`;Client `modules/first-leg/`;Backend `firstleg/loading/coload/`、`firstleg/split/`、`firstleg/loading/`、`order/`;同柜组按订单创建,由服务端冻结每票全部可用入仓片段,仅要求同国内仓、同渠道,允许跨客户及不同目的仓港 | | 订单编排、分柜、同柜不可拆组与柜次 | `docs/国内货柜履约/README.md`、`docs/国内货柜履约/国内货柜履约需求确认表.md`、`docs/统一订单主状态与操作契约.md` | Admin `modules/unified-orders/api/coLoadGroups.ts`、`modules/unified-orders/`、`container-loading/`;Client `modules/first-leg/`;Backend `firstleg/loading/coload/`、`firstleg/split/`、`firstleg/loading/`、`order/`;同柜组按订单创建,由服务端冻结每票全部可用入仓片段,仅要求同国内仓、同渠道,允许跨客户及不同目的仓港 |
| 全局智能排柜、预装与真实集装箱号后补 | 同上 | Admin `modules/container-loading/components/SmartLoadingDialog.vue` 内嵌 `pages/GlobalSmartLoadingView.vue`,柜次页 `SmartLoadingWorkbenchView.vue`,预装详情 `loading-lists/pages/PreloadPlanDetailView.vue`;PDA `pages/picking/`;Backend `firstleg/` 的 `PlatformSmartLoadingController`、`SmartLoadingService`、`PendingReviewOrderClient`、`loading/`,待审核事实来自 Order `PendingReviewOrderQueryService`。全局候选覆盖 `PENDING_REVIEW/WAIT_MEASURE/WAIT_SPLIT/LOADING`,状态只用于筛选展示,能否加入以服务端 `canAssign` 为准;待审核/待测量可提前占位,但确认预装或启动 PDA 前必须进入 `WAIT_SPLIT`。暂估明细的 `totalPackageCount/remainingPackageCount` 在测量前取 Order 原始申报箱数,测量完成后取最新已审核测量箱数,读取补充失败只回退当前已分配数,写入调整仍重新校验权威数量。同柜不可拆组仅在全员命中状态集合时作为一个分页与分配单元;人工加入允许跨渠道,智能推荐仍按柜次渠道。计划可一次性移除全部未拣明细,但任一成员已拣的同柜组必须整组保留。创建柜次时原子生成唯一预装计划,加入入仓码即建立关联;真实集装箱号不阻塞订舱关联,但确认预装和创建 PDA 任务前必须补齐。历史缺号任务允许在预装详情首次补录,保存后恢复 PDA 可进入状态 | | 全局智能排柜、预装与真实集装箱号后补 | 同上 | Admin `modules/container-loading/components/SmartLoadingDialog.vue` 内嵌 `pages/GlobalSmartLoadingView.vue`,柜次页 `SmartLoadingWorkbenchView.vue`,预装详情 `loading-lists/pages/PreloadPlanDetailView.vue`;PDA `pages/picking/`;Backend `firstleg/` 的 `PlatformSmartLoadingController`、`SmartLoadingService`、`PendingReviewOrderClient`、`loading/`,待审核事实来自 Order `PendingReviewOrderQueryService`。全局候选覆盖 `PENDING_REVIEW/WAIT_MEASURE/WAIT_SPLIT/LOADING`,状态只用于筛选展示,能否加入以服务端 `canAssign` 为准;待审核/待测量可提前占位,但确认预装或启动 PDA 前必须进入 `WAIT_SPLIT`。暂估明细的 `totalPackageCount/remainingPackageCount` 在测量前取 Order 原始申报箱数,测量完成后取最新已审核测量箱数,读取补充失败只回退当前已分配数,写入调整仍重新校验权威数量。同柜不可拆组仅在全员命中状态集合时作为一个分页与分配单元;人工加入允许跨渠道,智能推荐仍按柜次渠道。计划可一次性移除全部未拣明细,但任一成员已拣的同柜组必须整组保留。创建柜次时原子生成唯一预装计划,加入入仓码即建立关联;真实集装箱号不阻塞订舱关联,但确认预装和创建 PDA 任务前必须补齐。历史缺号任务允许在预装详情首次补录,保存后恢复 PDA 可进入状态 |
| 客户入库结果与头程费用确认 | 入库测量与计费主流程、当前 Firstleg 契约 | Client `modules/first-leg/components/InboundBillingPanel.vue`、`api/inboundBilling.ts`;Backend `firstleg/` 的 `MerchantInboundBillingController`、`MerchantInboundBillingService`、`FbaPricingService` 与 `firstleg-v1.yaml`。客户仅能确认本客户 `SENT` 的最新费用版本,提交 `expectedFeeVersion` 与幂等键;确认记录当前成员和时间并永久锁定该版本,平台不得再修改 | | 客户入库结果与头程费用确认 | 入库测量与计费主流程、当前 Firstleg 契约 | Client `modules/first-leg/components/InboundBillingPanel.vue`、`api/inboundBilling.ts`;Backend `firstleg/` 的 `MerchantInboundBillingController`、`MerchantInboundBillingService`、`FbaPricingService` 与 `firstleg-v1.yaml`。客户仅能确认本客户 `SENT` 的最新费用版本,提交 `expectedFeeVersion` 与幂等键;确认记录当前成员和时间并永久锁定该版本,平台不得再修改 |
@@ -79,13 +114,16 @@
| 客户统计与平台日志 | 当前统计/审计契约 | Admin `modules/customers/`、`modules/audit/`;Backend `firstleg/customerstatistics/`、`audit-service/` | | 客户统计与平台日志 | 当前统计/审计契约 | Admin `modules/customers/`、`modules/audit/`;Backend `firstleg/customerstatistics/`、`audit-service/` |
| 客户工作台账户与设置 | 订单与客户契约 | Client `modules/account/`、`system/`、`tenant-management/`;Backend `iam/`、`auth/` | | 客户工作台账户与设置 | 订单与客户契约 | Client `modules/account/`、`system/`、`tenant-management/`;Backend `iam/`、`auth/` |
| 企业订单与跨境业务 | 订单与客户、国内货柜履约契约 | Client `modules/order-management/`、`cross-border/`;Backend `order/`、`firstleg/`、`integration-service/` | | 企业订单与跨境业务 | 订单与客户、国内货柜履约契约 | Client `modules/order-management/`、`cross-border/`;Backend `order/`、`firstleg/`、`integration-service/` |
| 海外接柜、入库与库内库存 | `docs/海外仓业务/README.md` | Admin 按 `apps/admin-web/AGENTS.md` 海外模块入口;海外入口 `gateway-overseas/`;尾程/入仓/换标/库存 `lastleg-service/`;仓库主档归国内 `warehouse/`,库位/托盘/锁归 `warehouse-overseas-service/` 并只引用国内 warehouseId;与排车、出库、派送共同组成海外仓全流程 | | 海外接柜、入库与库内库存 | `docs/海外仓业务/README.md` | Admin 按 `apps/admin-web/AGENTS.md` 海外模块入口;海外入口 `gateway/`;尾程/入仓/换标/库存 `lastleg-service/`;仓库主档归国内 `warehouse/`,库位/托盘/锁归 `warehouse-overseas-service/` 并只引用国内 warehouseId;与排车、出库、派送共同组成海外仓全流程 |
| 尾程订单控制与柜级入仓计划转换 | `docs/海外仓业务/README.md` | Admin `modules/overseas-warehouse/pages/LastMileOrdersView.vue`、`LastMileOrderDetailView.vue`、`api/lastMileOrders.ts`;Backend `lastleg-service/` 的 `LastlegOrderController`、`LastlegOrderCommandService`、`InboundPlanService`、`ContainerInboundPlanConversionCoordinator`,资源归 `warehouse-overseas-service/` 的 `WarehousePalletBatchService`。`orders/container-summaries` 按 `sourceContainerBookingId` 跨客户聚合并分页返回全部稳定来源柜,已完成计划转换的柜仍保留用于接柜仓查询与修改;生成动作只消费 `allPlansReady/pendingPlanCount/resourcePendingPlanCount`,详情不受列表分页截断。确认前从 `/inbound-plans/container-preview` 读取服务端分组、托数、阻断项与 `snapshotVersion/snapshotHash`;`convert-container` 锁柜重算后先批量预留真实托盘,再本地原子生成剩余独立计划并确认资源,失败仅补偿未确认资源,同柜重放不得产生第二批资源。单票手工计划保存后,全柜计划齐全且预览就绪时自动生成并绑定托盘资源,一票柜立即触发;`resourcePendingPlanCount` 表示自动生成异常后的重试入口,资源未齐不得进入 PDA 接柜。自动入口见 Lastleg `ContainerInboundPlanConversionCoordinator.convertManualAndAutoMaterialize`。单票可维护完整入库计划、暂扣/解除及八行人工节点快照;命令提交订单版本与幂等键,新增暂扣只允许完成入库后执行并仅阻断该票后续排车/出库,不阻断入库计划或入库作业;人工节点首次保存后固定 `MANUAL` 来源且不得回退柜级节点 | | 尾程订单控制与柜级入仓计划转换 | `docs/海外仓业务/README.md` | Admin `modules/overseas-warehouse/pages/LastMileOrdersView.vue`、`LastMileOrderDetailView.vue`、`api/lastMileOrders.ts`;Backend `lastleg-service/` 的 `LastlegOrderController`、`LastlegOrderCommandService`、`InboundPlanService`、`ContainerInboundPlanConversionCoordinator`,资源归 `warehouse-overseas-service/` 的 `WarehousePalletBatchService`。`orders/container-summaries` 按 `sourceContainerBookingId` 跨客户聚合并分页返回全部稳定来源柜,已完成计划转换的柜仍保留用于接柜仓查询与修改;生成动作只消费 `allPlansReady/pendingPlanCount/resourcePendingPlanCount`,详情不受列表分页截断。确认前从 `/inbound-plans/container-preview` 读取服务端分组、托数、阻断项与 `snapshotVersion/snapshotHash`;`convert-container` 锁柜重算后先批量预留真实托盘,再本地原子生成剩余独立计划并确认资源,失败仅补偿未确认资源,同柜重放不得产生第二批资源。单票手工计划保存后,全柜计划齐全且预览就绪时自动生成并绑定托盘资源,一票柜立即触发;`resourcePendingPlanCount` 表示自动生成异常后的重试入口,资源未齐不得进入 PDA 接柜。自动入口见 Lastleg `ContainerInboundPlanConversionCoordinator.convertManualAndAutoMaterialize`。单票可维护完整入库计划、暂扣/解除及八行人工节点快照;命令提交订单版本与幂等键,新增暂扣只允许完成入库后执行并仅阻断该票后续排车/出库,不阻断入库计划或入库作业;人工节点首次保存后固定 `MANUAL` 来源且不得回退柜级节点 |
| 海外仓 PDA | `docs/海外仓业务/README.md` | Overseas PDA 入仓 `api/inbound.js`、`api/receiving-adapter.js`、`pages/operation/`,库内/换标按工作台入口,排车与出库 `pages/dispatch/`、`pages/outbound/`;Backend `lastleg-service/inboundplan/pda/`、`pda/`、`dispatch/pda/`、`delivery/`;统一经 `gateway-overseas/`。接柜候选、会话、照片和整柜完成按 `sourceContainerBookingId + containerNo` 聚合且不绑定客户,允许同柜多客户;各入仓码的计划、任务、SKU、托盘与库存仍按自身客户隔离。多计划同柜按服务端返回的 `assigned/mergeAllowed/urgent` 展示,合托只是现场可选提示;扫码实收确认计划生成时预留的真实托盘与库位,不重新分配资源;派送与回访由 Admin/Client 承载 | | 海外仓 PDA | `apps/pda-overseas-uniapp/AGENTS.md`;执行规则查 `baiyue-firstleg/lastleg-service/AGENTS.md`,跨模块流程才查海外仓 README | 入仓 `src/pages/operation/`、`src/api/inbound.js`;排车与出库 `src/pages/dispatch/`、`src/pages/outbound/`、`src/api/fulfillment.js`。Backend `lastleg-service/inboundplan/pda/`、`dispatch/pda/`、`delivery/`;统一经 `gateway/`。柜级收货与单票客户隔离按 Lastleg“PDA 入仓”规则核对 |
| 海外采购、本土卡车与散板 | `docs/海外仓业务/README.md` | Admin `modules/overseas-business/`;Client `modules/cross-border/`;Backend `lastleg-service/` 的 `procurement/`、`trucking/`、`looseboard/`;统一经 `gateway-overseas/` | | 海外采购、本土卡车与散板 | `docs/海外仓业务/README.md` | Admin `modules/overseas-business/`;Client `modules/cross-border/`;Backend `lastleg-service/` 的 `procurement/`、`trucking/`、`looseboard/`;统一经 `gateway/` |
| 采购样品、货款、装箱清单、面单、预估快递费、国内收货寄客户 | `docs/海外仓业务/采购订单样品履约流程变更需求.md` | 采购流程变更入口;代码从上述采购模块进入 |
| 海外仓库与通用资料 | `docs/海外仓业务/README.md` | 全部仓库主档进入 Admin `modules/warehouses/` 与国内 `warehouse/`;海外库位/托盘/锁进入 `warehouse-overseas-service/` 并引用国内 warehouseId;报价、汇率、车辆按海外服务实际契约 | | 海外仓库与通用资料 | `docs/海外仓业务/README.md` | 全部仓库主档进入 Admin `modules/warehouses/` 与国内 `warehouse/`;海外库位/托盘/锁进入 `warehouse-overseas-service/` 并引用国内 warehouseId;报价、汇率、车辆按海外服务实际契约 |
| 车辆管理、司机证照、保养加油、车辆维修/故障/救援/异常、外接货与车次 | `apps/admin-web/src/modules/overseas-master-data/AGENTS.md`、`baiyue-firstleg/lastleg-service/AGENTS.md`;原型范围有疑问时查 `docs/海外仓业务/车辆管理原型梳理与任务规划.md` | Admin `modules/overseas-master-data/`;Backend `lastleg-service/fleet/`,接口 `lastleg-service/src/main/resources/openapi/fleet-drivers-v1.yaml`、`fleet-trips-v1.yaml`、`fleet-vehicle-records-v1.yaml`;证照与运维照片存储查 `file/AGENTS.md` |
| 拼车需求池、车次余位、销售拼车意向 | `docs/海外仓业务/内部拼车需求池首版开发契约.md`、`apps/admin-web/src/modules/overseas-master-data/AGENTS.md` | 复用 Lastleg Fleet 与本土业务;区分车次余位发布和客户订单,不从需求池生成第二套库存或费用 |
| 国内出仓后船节点 | `docs/海外仓业务/README.md` | Admin `modules/port-schedules/`、`ocean-bookings/`、货柜详情;Backend `firstleg/portschedule/`、`integration-service/`;从确认国内出仓查询至目的港到达、提柜和还柜。节点按 `containerBookingId` 柜级聚合,跨区事件使用 `tenantId=0` 平台技术范围,不携带或校验客户 | | 国内出仓后船节点 | `docs/海外仓业务/README.md` | Admin `modules/port-schedules/`、`ocean-bookings/`、货柜详情;Backend `firstleg/portschedule/`、`integration-service/`;从确认国内出仓查询至目的港到达、提柜和还柜。节点按 `containerBookingId` 柜级聚合,跨区事件使用 `tenantId=0` 平台技术范围,不携带或校验客户 |
| 海外出库、排车、派送、异常与回访 | 当前海外履约契约 | Admin `modules/overseas-warehouse/pages/OutboundsView.vue`、`DeliveryOrdersView.vue`、`ExceptionOrdersView.vue`、`CustomerVisitsView.vue`;Backend `lastleg-service/dispatch/`、`delivery/`、`dropship/`、`exceptionorder/`、`customervisit/`;统一经 `gateway-overseas/`。异常单按 `PENDING → PROCESSING → COMPLETED` 流转,处理完成必须引用归属为 `OVERSEAS_EXCEPTION_EVIDENCE` 的证据;派送退回只从原出库拣货事实选择可退明细,退回海外仓时先把实收恢复到指定真实托盘/库位,再原子完成异常单并将派送置为 `RETURNED` | | 海外出库、排车、派送、异常与回访 | 排车改造查[排车列表统一作业改造契约](海外仓业务/排车列表统一作业改造契约.md);既有缺陷修复查[排车流程修复规划](海外仓业务/排车流程修复规划.md) | Admin `modules/overseas-warehouse/pages/DispatchesView.vue`、`DispatchDetailView.vue`、`OutboundsView.vue`、`DeliveryOrdersView.vue`、`ExceptionOrdersView.vue`、`CustomerVisitsView.vue`;Backend `lastleg-service/dispatch/`、`delivery/`、`dropship/`、`exceptionorder/`、`customervisit/`;统一经 `gateway/` |
| 海外业务费用来源与客户财务 | 财务契约、`docs/跨区域认证与服务通信契约.md` | 海外入仓、采购、美国卡车、本土散板和海外仓服务费由 `lastleg-service/financefee/` 校验真实业务归属并版本化审核;通过 `BUSINESS_FEE_SOURCE_CHANGED` 完整快照、`event-bridge-service/` 和国内 Finance `/internal/finance/v1/business-fee-source-events` 可靠入池。`PAYABLE + DIRECT_PAID` 进入已确认成本且不得再次进入 AP 待结算;Client 仍从 `modules/finance/` 读取获准客户财务,不自动开放平台费用来源维护页 | | 海外业务费用来源与客户财务 | 当前实现查财务契约与统一认证与服务通信契约;阶段 0A—0E 开发再读 `docs/财务管理/海外仓费用统一接入阶段0技术契约.md` | 当前 V1 由 `lastleg-service/financefee/` 校验海外入仓、采购、美国卡车、本土散板和海外仓服务费,通过完整快照和 Outbox 直接投递 Finance 内部入口入池;阶段 0 目标改为收费身份/候选版本、Finance 接受或拒绝结果事件及版本化资金计划。必须沿代码确认落地范围,不把技术契约当成已实现状态;Client 仍只读取获准客户财务 |
散货托盘码生成、打印与跨区传递:Admin `modules/loading-lists/components/PalletLabelPrintDialog.vue`;Firstleg `LoadingPalletLabelService`、`LoadingCompletedOutboxService`;Lastleg `LastlegSourcePalletMapper`、`InboundPlanService`。从各项目最近指引继续定位;散货 FBA 标签与一件代发实装托盘分别取各自冻结事实。 散货托盘码生成、打印与跨区传递:Admin `modules/loading-lists/components/PalletLabelPrintDialog.vue`;Firstleg `LoadingPalletLabelService`、`LoadingCompletedOutboxService`;Lastleg `LastlegSourcePalletMapper`、`InboundPlanService`。从各项目最近指引继续定位;散货 FBA 标签与一件代发实装托盘分别取各自冻结事实。
+2
View File
@@ -10,6 +10,8 @@
## 文档 ## 文档
费用项目默认价格规则(2026-10-19):平台公共项目可配置可空的 `defaultPrice`(CNY、非负、两位小数),不填表示人工录入,`0` 表示明确的零元默认价。入库与柜次费用仅在用户主动选择项目时带入;入库同时带入单价与金额,柜次带入金额,均允许人工修改。切换到无默认价格的项目时清除前项带价并回到零值待填;打开已有费用、切换供应商或保存业务费用不重新套用默认价。修改或清空项目默认价不追改已有费用,也不改变审核、发布与结算流程;本次不增加计费数量或条件报价。
- [入库测量与计费 V2 需求确认清单(当前会议填写)](入库测量与计费V2需求确认清单.md) - [入库测量与计费 V2 需求确认清单(当前会议填写)](入库测量与计费V2需求确认清单.md)
- [入库测量与计费需求优化版 V2:测量、计费、托盘入库主流程](入库测量与计费需求优化版-v2-测量计费入库主流程.md) - [入库测量与计费需求优化版 V2:测量、计费、托盘入库主流程](入库测量与计费需求优化版-v2-测量计费入库主流程.md)
- [入库测量与计费需求优化版:原型对照(上一版优化稿)](入库测量与计费需求优化版-原型对照.md) - [入库测量与计费需求优化版:原型对照(上一版优化稿)](入库测量与计费需求优化版-原型对照.md)
+3 -164
View File
@@ -1,166 +1,5 @@
# 双区域部署与 Nacos 规划 # 双区域部署与 Nacos 规划(已替代)
## 1. 适用范围与结论 自 2026-09-29 起,不再规划开发/测试/生产与 CN/OVERSEAS 双区域。当前唯一目标为单一测试环境、所有服务同机部署。唯一部署主契约见[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md),认证通信见[统一认证与服务通信契约](统一认证与服务通信契约.md)。
本文冻结国内头程与海外仓服务在开发、测试和生产环境中的部署拓扑、Nacos、数据库及 Event Bridge 边界。账号、Token、API 路由和事件语义继续以《跨区域认证与服务通信契约》为准。 此文件仅保留旧链接入口,不再定义有效规则。运行配置切换仍待实施与验证。
当前结论:
- 开发、测试采用单宿主机共置:同一环境内同时部署国内 Compose 与海外 Compose,通过独立容器、网络、端口、Nacos Namespace 和数据库 Schema 隔离。
- 生产采用国内、海外两套独立区域控制面:各自使用本区域 Nacos 集群、数据库和 Redis,不允许海外服务跨境依赖国内 Nacos、MySQL 或 Redis。
- 跨区域只开放双区域 API、JWKS 公钥和 Event Bridge 接收入口,不使用跨区域服务发现。
## 2. 环境拓扑
| 环境 | 宿主与网络 | Nacos | 数据库 | 适用目的 |
|---|---|---|---|---|
| development | 单宿主机共置国内/海外 Compose | 一套开发 Nacos,国内/海外独立 Namespace | 可共用一个开发 MySQL 实例,但必须使用独立 Schema | 日常开发联调 |
| test | 单宿主机共置国内/海外 Compose | 一套测试 Nacos,国内/海外独立 Namespace | 可共用一个测试 MySQL 实例,但必须使用独立 Schema | 集成测试和验收 |
| production-cn | 国内独立部署单元 | 国内高可用 Nacos 集群 | 国内独立 MySQL/Redis | Auth、IAM、头程、国内仓和 Finance |
| production-overseas | 海外独立部署单元 | 海外高可用 Nacos 集群 | 海外独立 MySQL/Redis | 海外 Gateway、Lastleg 和海外 Warehouse |
如果开发与测试实际共用同一套 Nacos 实例,必须创建四个 Namespace,不得复用:
```text
development-cn
development-overseas
test-cn
test-overseas
```
Namespace 名称不是服务名。环境变量必须填写 Nacos 实际 Namespace ID;控制台自动生成 UUID 时使用 UUID,不使用展示名称代替。
## 3. 服务归属
### 3.1 国内区域
- `gateway`、`auth-service`、`iam-service`
- `firstleg-service`、`order-service`、`finance-service`
- 国内 `warehouse-service`、`file-service`、`audit-service` 等公共服务
- 国内 Event Bridge,用于接收目标区域为 `CN` 的事件并投递本地 Firstleg
### 3.2 海外区域
- `gateway-overseas`
- `lastleg-service`,同时持有 `baiyue_lastleg` 内的 IAM 安全事件 Inbox/投影,并开放内部事件接收和实时校验端点
- `warehouse-overseas-service`
- 海外 `file-service`,独占海外 RDS 中的 `baiyue_file`,只访问海外本区域私有 OSS Bucket;详细边界见《[阿里云 OSS 文件中心接入设计与评审](阿里云OSS文件中心接入设计与评审.md)》
- 海外 Event Bridge,用于接收目标区域为 `OVERSEAS` 的事件;业务事件和三类 IAM 安全事件按事件类型投递 Lastleg 的不同内部入口
海外浏览器请求直接进入海外 Gateway,不经过国内 Gateway。Auth 仍只部署在国内;海外服务通过受控 JWKS 地址验证 Auth 签发的短时海外 Token,不访问国内 Redis。
## 4. Nacos 规划
### 4.1 开发与测试
非生产环境允许一套 Nacos 实例承载多个 Namespace。国内配置发布自 `baiyue-firstleg/config/nacos/cn/`,海外配置发布自 `baiyue-firstleg/config/nacos/overseas/`,相同 Data ID 依靠 Namespace 隔离。
国内环境变量:
```dotenv
NACOS_SERVER_ADDR=<当前环境Nacos地址>
NACOS_NAMESPACE=<当前环境国内Namespace ID>
REGION_CODE=CN
DEPLOYMENT_CELL=<environment>-cn
DATA_RESIDENCY=CN
```
海外环境变量:
```dotenv
OVERSEAS_NACOS_SERVER_ADDR=<当前环境Nacos地址>
OVERSEAS_NACOS_NAMESPACE=<当前环境海外Namespace ID>
OVERSEAS_DEPLOYMENT_CELL=<environment>-overseas
```
海外 Compose 必须强制传入 `REGION_CODE=OVERSEAS` 和 `DATA_RESIDENCY=OVERSEAS`,不得继承共享文件中的国内默认值。
### 4.2 生产
生产国内、海外分别部署本区域 Nacos 集群。服务只注册到本区域,不同步或复制临时服务注册表,也不通过公网访问另一地区 Nacos。
```dotenv
# 国内生产凭据
NACOS_SERVER_ADDR=<国内Nacos内网地址>
NACOS_NAMESPACE=<production-cn Namespace ID>
# 海外生产凭据
OVERSEAS_NACOS_SERVER_ADDR=<海外Nacos内网地址>
OVERSEAS_NACOS_NAMESPACE=<production-overseas Namespace ID>
```
生产 Nacos 必须启用认证、网络 ACL 和持久化;不暴露公网管理端口。数据库密码、JWT 私钥、内部服务 Token 和第三方密钥不得写入 Nacos 明文,继续由 Jenkins Credentials 或生产密钥管理系统注入。
## 5. 数据库隔离
开发、测试即使共用一个 MySQL 实例,也必须保持以下 Schema 独立:
| 区域 | 服务 | Schema |
|---|---|---|
| 国内 | Event Bridge | `baiyue_event_bridge` |
| 海外 | Event Bridge | `baiyue_event_bridge_overseas` |
| 海外 | Lastleg | `baiyue_lastleg` |
| 海外 | Warehouse | `baiyue_lastlag_warehouse` |
生产必须进一步使用区域内独立数据库实例或集群。国内服务不得查询海外 Schema,海外服务不得查询国内 Schema;跨区域事实只通过版本化事件或已确认的受保护内部接口传递。
## 6. Event Bridge 双实例
每个区域部署一个相同制品、独立数据库的 Event Bridge:
```text
Firstleg Outbox
-> 海外 Event Bridge Inbox
-> Lastleg 本地消费者
Lastleg Outbox
-> 国内 Event Bridge Inbox
-> Firstleg 本地消费者
```
国内 Firstleg 配置海外 Bridge 基础地址,Feign 自动追加接收路径:
```dotenv
LASTLEG_EVENT_BRIDGE_URL=<海外Event Bridge基础地址>
```
海外 Lastleg 配置国内 Bridge 基础地址:
```dotenv
FIRSTLEG_EVENT_BRIDGE_URL=<国内Event Bridge基础地址>
```
区域内消费者使用本地服务地址:
```dotenv
# 海外 Bridge
EVENT_CONSUMER_URL=http://lastleg-service:9303/internal/lastleg/events
# 国内 Bridge
FIRSTLEG_CONTAINER_EVENT_CONSUMER_URL=http://firstleg:9202/internal/firstleg/v1/container-events
```
跨区域 Bridge 接收入口使用 TLS、内部服务身份、网络白名单和幂等校验;不得暴露数据库或消费者内部接口。
## 7. Jenkins 与环境文件
开发、测试可以各用一份 Secret File,同时包含国内和海外非敏感路由变量;Compose 负责选择本区域变量。生产必须拆分凭据:
```text
firstleg-production-cn-env
firstleg-production-overseas-env
```
生产海外部署不得读取国内数据库、Redis 或 Nacos 地址。Event Bridge 同一制品需要按 `CN`、`OVERSEAS` 两个部署单元分别发布,使用不同 Compose Project、容器名、端口和数据库。
## 8. 当前仓库实施差距
目标架构已冻结,但当前部署代码仍需完成以下收敛:
1. `docker-compose.overseas.yml` 当前仍从 `NACOS_SERVER_ADDR` 取值,应改为显式使用 `OVERSEAS_NACOS_SERVER_ADDR`。
2. `deploy/scripts/deploy-built-service.sh` 与 `deploy-services.sh` 的海外服务门禁应校验 `OVERSEAS_NACOS_SERVER_ADDR`。
3. Jenkins 生产配置需要拆分国内/海外 Secret File,并为 Event Bridge 提供明确区域部署参数或独立 Job。
4. 海外 Nacos Namespace 创建、配置发布、JWKS 可达性和双向 Event Bridge 真实投递必须分别验收,不能以容器健康检查代替。
5. 海外 Gateway 和 Nacos 已存在 File Service 入口,但海外统一 SQL 与部署清单尚未包含海外 `file-service`、`baiyue_file`;OSS 接入实施前必须补齐并完成区域内真实上传、下载和双实例读取验收。
这些差距未完成前,不得声称生产双区域部署已就绪。
+29 -39
View File
@@ -1,51 +1,41 @@
# 国内货柜履约文档 # 国内货柜履约
国内货柜履约以国内头程后程作业为范围,完成从排柜、订舱、拖车和仓内拣货,到装柜证据齐全并进入 `LOADED`/装柜完成的业务闭环。`DELIVERED`/派送完成由到达海外仓后的可信回传推进,不属于国内国内货柜履约操作范围。 本目录负责国内分柜、订舱、拖车、拣货、装柜、装柜后的报关协同、送港、进港和甩柜事实。整体货柜流程进入收尾,**报关协同代码尚未完成**;当前只在这里查找流程节点,报关开发请转到交接清单。
> 范围更正:国内货柜履约只维护订舱和出仓前所需的船名航次、港口、ETD/ETA 等资料。柜子确认离开国内仓库后的 `CarrierScheduleQuery`、六家船公司查询、每 3 天/最多 3 次、来源/过期标识和后续定时船节点查询整体归海外仓业务,见 `../海外仓业务/README.md`。国内货柜履约不再建设或验收这套查询。 ## 当前流程入口
## 当前主体模型与开工禁令 - [头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md):三大业务块总览和 F01-F40 节点总表。
- [阶段三:国内货柜履约与出仓](../头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md):分柜、订舱、拖车、拣货、装柜、报关和国内出仓的详细操作。
- [阶段四:海运、目的港与尾程计划](../头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md):实际开船后的海运、目的港和尾程计划衔接。
- [报关资料与船期价格接入梳理](报关资料与船期价格接入梳理.md):报关资料、报关行回执、客户确认/打回、正式申报、海关结果和船期价格专题。
- [船期日历功能规划](船期日历功能规划.md):渠道、周模板、单次船期、收货截止时间和按渠道货量统计的独立日历规划。
- [报关代码开发交接清单](../头程到尾程/报关代码开发交接清单.md):报关代码当前未完成时,下一开发对话使用的范围和验收条件。
- 国内货柜履约继续按业务单租户、“平台—客户”两级开发,客户之间严格隔离。Java 与接口中的业务 `tenant_id > 0` / `tenantId` 当前表示客户 ID;`tenant_id=0` 是平台身份、平台 RBAC 和平台公共仓库、快递公司、托盘、库位等公共资源技术作用域。客户往来单位、订单、文件和费用仍归属客户 `tenant_id>0`。 ## 货柜关键节点
- 国内货柜履约不得新增租户主表、租户选择器、客户所属租户配置、租户切换、租户级 RBAC 或租户级配置,也不得把当前 `tenant_id` 从客户 ID 改义为上级租户 ID。
- `tenant`、`Tenant*`、`merchant`、接口路径和字段属于历史兼容命名,继续保留;真实租户能力必须等未来独立需求、数据迁移和跨服务契约方案确认后再实施。
## 文档 货柜对外统一使用 `cabinetNo` 柜次号(`D0001` 起,全局连续、不按日期重置),创建时只生成一次;日历、提柜、智能装柜、货柜详情及出仓均读取该值。`containerBookingId` 仅用于技术关联,`containerNo` 为真实集装箱号。货柜不再维护独立的 CB 格式 `bookingNo`;海运订舱和外接货登记各自的 `bookingNo` 不属于货柜编号,保留各自业务语义。
- [国内货柜履约闭环审计报告(2026-08-08)](国内货柜履约闭环审计报告-2026-08-08.md):基于当前代码、接口、自动化和测试环境证据的闭环审计,列出阻断项、优先级和 GO 准入标准。 ```text
- [国内货柜履约装柜闭环产品确认表(2026-08-08)](国内货柜履约装柜闭环产品确认表-2026-08-08.md):提供给产品直接填写的纯业务确认表,不包含技术实现细节。 分柜/订舱/拖车 → 拣货 → 装柜完成(LOADED)
- [国内货柜履约装柜闭环开发前确认单(2026-08-08)](国内货柜履约装柜闭环开发前确认单-2026-08-08.md):用于产品确认直接开发前的状态、门禁、PDA 取证、冲正和验收细节。 ├─ 报关协同:资料 → 报关行回执 → 客户确认/打回重做
- [国内货柜履约开发规划:国内出仓](国内货柜履约开发规划.md) │ → 全部客户确认 → 整柜提交 → 正式申报 → 海关结果
- [国内货柜履约开发进度表](国内货柜履约开发进度表.md):参考订单与客户采用“大任务 → 详细任务 → 里程碑 → 未确认事项 → 开工准入 → 验收”结构维护。 ↓ 报关完成
- [虫虫出海国内货柜履约开发进度表(Excel)](虫虫出海国内货柜履约开发进度表.xlsx):可筛选、可下拉维护并使用公式汇总的项目进度工作簿。 进入待发区
- [国内货柜履约需求确认表](国内货柜履约需求确认表.md):集中跟踪 P3-Q1~P3-Q13、负责人和最终结论。 ↓
- [国内货柜履约开工门禁](国内货柜履约开工门禁.md):维护已确认范围、跨端硬边界和局部阻断项;模块指引引用本文件,不重复维护阶段状态。 送港运输:离仓 → 送港 → 进港 → 甩柜/改配(如发生)
- [国内货柜履约页面与原型清单](国内货柜履约页面与原型清单.md):按管理后台、企业客户端和 PDA 维护页面范围及原型状态。 ↓
- [国内货柜履约验收任务拆分与待确认清单](国内货柜履约验收任务拆分与待确认清单.md):真实 HTTP/真机验收覆盖、coverageGap 解除条件和并行任务入口。 船舶实际开航后进入海运节点
- `参考资料/出仓流程.png`:本期 9 个核心动作及业务终点的原始参考图。 ```
## 当前状态 报关完成是进入待发区的门槛。进入待发区后再推进离仓、送港、进港和船期;甩柜/改配只改变运输船次,不影响已完成的报关资料、回执和客户确认。报关行回执、客户确认、正式申报、海关放行、进港、甩柜和实际开船分别记录,不能用其中一个节点代替另一个节点。
国内货柜履约已进入分模块部署联调。已确认不新建独立出仓单,现有订单列表/详情承载主状态;支持一单多柜、一个柜拼多个订单,并采用“父订单→子订单→柜次”关系,已装载数量形成子订单,未装载数量自动生成后续子订单。进入 `LOADED`/装柜完成前,订舱完成、拖车完成、报关放行回执、PDA 拣货完成及五类证据完整均为服务端硬门禁;`LOADED` 后错误统一线下人工处理,国内 Admin/PDA 不提供在线冲正或手工推进 `DELIVERED`。当前不能因子链路已通过而宣告整期完成,最终结论以真实 HTTP 全链路验收为准。 费用确认属于头程下单块的并行事项,不阻断排柜、拣货或装柜;装柜完成时仍未确认的当前有效费用按系统默认确认并保留来源。这个默认确认只适用于费用,不适用于报关资料的客户确认。
柜子出仓后的船公司/船节点查询已重新归入海外仓业务。国内货柜履约报关首版不做系统对接,全部由人工整理、线下提交和人工上传回执。仓库初始化角色包括操作员、拣货员、理货员,具体权限矩阵由 IAM 契约任务落表。 ## 当前变更相关文档
P3-Q1~P3-Q13 均已确认;P3-Q4 采用 uni-app 开发并支持在线更新,Android 广播扫描已接入。P3-Q5 复用入库测量与计费实时库存、当前位置和可用量接口,不扩展完整 WMS。 - [国内货柜履约需求确认表](国内货柜履约需求确认表.md):需要核对已确认的业务口径时使用。
- [国内货柜履约页面与原型清单](国内货柜履约页面与原型清单.md):需要核对页面范围或原型入口时使用。
### PDA 当前确认口径(2026-08-10) ## 冻结记录(只用于追溯)
- Android 扫描广播方式已接入;PDA 采用 uni-app 开发并支持在线更新,按既定发布安排完成真机验收。 开发规划、进度、门禁、验收矩阵、审计、产品确认和旧任务卡已移入[国内货柜履约历史记录](归档/README.md)。这些文件不删除、不回写;若要调整当前流程,修改总览、对应阶段或报关专题,并同步实际接口/权限契约。
- 正式作业仅支持在线:进入任务即标记“拣货中”,扫描保存在绑定作业员+任务+柜次的设备持久化草稿,点击提交时批量写后端。
- 允许部分拣货或跳拣,但每个未完成项必须填写异常原因;存在未解决异常时不能完成或进入 `LOADED`。
- 重复提交返回原结果,版本冲突提示员工刷新重试。
- PDA 只能现场拍照,Admin 可人工上传;五类证据各至少 1 张有效照片,可同类型多张追加,错图只作废不硬删除。
- 单柜次只允许一名作业员作业,不做多人并行和任务接管;进入任务即标记“拣货中”,扫描草稿按作业员+任务+柜次隔离,点击提交时批量写入后端。
- 后台操作员、理货员可按权限人工上传证据;拣货员只负责 PDA 现场拍照,不开放后台人工上传。照片无限期保留,客户不可见照片和锁码。
### 发布与真实验收状态(2026-08-10)
- Admin 已部署 `b593d72`:智能装柜、预装清单、装柜清单均可访问真实接口;预装/装柜清单不再要求选择仓库,详情仍使用列表行返回的真实仓库归属。
- Firstleg 已部署 `3bfc11a`:修复 PDA 拣货时库位分配状态提前变更的问题;真实复跑仍发现 PDA `pick` 第二处 `S0500`,当前仍阻断 PDA 复核、装柜完成、报关 LOADED 关联和最终门禁,不能标记国内货柜履约闭环完成。
- 验收 fixture 顺序已核实为 `orders → inbound-measurement → phase3-container-loading → phase3-loading → phase3-customs → phase3-port-schedules → phase3-loading-finalize`;脚本保留真实失败,不以 mock、历史资源或 coverage gap 伪装通过。
- PDA“点击提交时批量写入后端”的原子 batch 契约尚未实现;当前页面仍不能证明整批事务、批次幂等、服务端库存快照和失败整批回滚已具备。
- ZIM hCaptcha、COSCO 动态页继续按产品确认的人工兜底保留为 `MANUAL_REQUIRED`,不作为自动查询 PASS。
@@ -8,7 +8,7 @@
- 状态统一使用:待确认、确认中、已确认、已取消。 - 状态统一使用:待确认、确认中、已确认、已取消。
- 阻断级别统一使用:开工阻断、模块阻断、非阻断。 - 阻断级别统一使用:开工阻断、模块阻断、非阻断。
- 结论确认后同步更新 `国内货柜履约开发规划.md`、`国内货柜履约开发进度表.md` 和受影响的页面原型。 - 结论确认后同步更新 `归档/国内货柜履约开发规划.md`、`归档/国内货柜履约开发进度表.md` 和受影响的页面原型。
- 未确认事项只能作为候选方案,不能直接写成固定开发或验收承诺。 - 未确认事项只能作为候选方案,不能直接写成固定开发或验收承诺。
## 二、确认事项 ## 二、确认事项
@@ -22,13 +22,16 @@
| P3-Q5 | 拣货是否依赖实时库存和库位可用量? | 默认使用入库测量与计费处理单元和当前位置;如需完整库存,单独评估 WMS 范围 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10 | PDA 拣货必须依赖实时库存和库位可用量;首版复用入库测量与计费处理单元、当前位置和可用量接口,超量、库存不足和库位不可用由服务端拒绝;不扩展完整 WMS | 入库测量与计费及国内货柜履约契约、拣货、库存边界 | | P3-Q5 | 拣货是否依赖实时库存和库位可用量? | 默认使用入库测量与计费处理单元和当前位置;如需完整库存,单独评估 WMS 范围 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10 | PDA 拣货必须依赖实时库存和库位可用量;首版复用入库测量与计费处理单元、当前位置和可用量接口,超量、库存不足和库位不可用由服务端拒绝;不扩展完整 WMS | 入库测量与计费及国内货柜履约契约、拣货、库存边界 |
| P3-Q6 | 柜封照片有哪些必传类型、数量、采集方式、处理规则和留存期限? | 五类证据、角色和留存按确认版直接进入契约 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | 空仓、半仓、满仓、锁仓、带锁码照五类各至少 1 张有效照片,同类型可无限追加;PDA 只能现场拍照;后台操作员和理货员可人工上传;拣货员只负责 PDA 现场采集,不开放后台人工上传;错图不硬删除,按原因、操作人、时间作废;带锁码照必须填写锁码文本;照片无限期保留,客户不可见照片和锁码 | 装柜、PDA 拍照、Admin 上传、文件存储、订单后程门禁 | | P3-Q6 | 柜封照片有哪些必传类型、数量、采集方式、处理规则和留存期限? | 五类证据、角色和留存按确认版直接进入契约 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | 空仓、半仓、满仓、锁仓、带锁码照五类各至少 1 张有效照片,同类型可无限追加;PDA 只能现场拍照;后台操作员和理货员可人工上传;拣货员只负责 PDA 现场采集,不开放后台人工上传;错图不硬删除,按原因、操作人、时间作废;带锁码照必须填写锁码文本;照片无限期保留,客户不可见照片和锁码 | 装柜、PDA 拍照、Admin 上传、文件存储、订单后程门禁 |
| P3-Q7 | 报关资料清单是否按国家、渠道和货物类型变化? | 清单配置化,并保存业务使用的清单版本 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | 首版不对接海关或代理系统;按人工维护资料清单、收集/补件并保存版本,具体清单可配置 | 客户资料、报关审核、文件版本 | | P3-Q7 | 报关资料清单是否按国家、渠道和货物类型变化? | 清单配置化,并保存业务使用的清单版本 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | 首版不对接海关或代理系统;按人工维护资料清单、收集/补件并保存版本,具体清单可配置 | 客户资料、报关审核、文件版本 |
| P3-Q8 | 报关代理如何接收资料并返回回执? | 首版系统内整理、线下提交,正式接口后续评估 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | 全部人工处理:平台整理资料后线下交代理,授权人员人工上传代理回执;系统记录提交批次、回执版本和时间,不建设自动对接 | 报关协同、回执上传 | | P3-Q8 | 报关代理如何接收资料并返回回执? | 首版系统内整理、线下提交,正式接口后续评估 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10;2026-09-24 更正 | `LOADED` 后平台按客户/入仓码收集资料并线下发给报关行;授权人员上传每轮报关行回执,发给对应客户确认。客户打回后重新上传、重新发报关行并生成新回执,直到该客户确认;记录资料版本、回执版本、roundNo、发送时间和确认/打回审计 | 报关协同、客户确认、回执上传 |
| P3-Q9 | “港务信息”指船期、港口作业状态还是两者,包含哪些字段,由谁维护? | 国内货柜履约只维护订舱与出仓前船期资料 | 已重新归期 | 已确认 | 产品/业务 | 2026-08-19 | 柜子确认离开国内仓库后的船公司/货物跟踪查询、每 3 天最多 3 次、来源、更新时间和过期标识整体归海外仓业务;国内货柜履约不建设或验收该查询 | 国内货柜履约订舱资料、海外仓业务船节点查询 | | P3-Q9 | “港务信息”指船期、港口作业状态还是两者,包含哪些字段,由谁维护? | 国内货柜履约只维护订舱与出仓前船期资料 | 已重新归期 | 已确认 | 产品/业务 | 2026-08-19 | 柜子确认离开国内仓库后的船公司/货物跟踪查询、每 3 天最多 3 次、来源、更新时间和过期标识整体归海外仓业务;国内货柜履约不建设或验收该查询 | 国内货柜履约订舱资料、海外仓业务船节点查询 |
| P3-Q10 | 订单进入“装柜完成”后发现错误如何处理? | 仅保留线下人工处理和审计,不建设在线冲正 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | `LOADED` 后不提供在线冲正/回退入口,统一线下人工处理;系统保留原状态和审计记录,不由国内 Admin/PDA 推进 `DELIVERED` | 装柜完成门禁、权限、审计 | | P3-Q10 | 订单进入“装柜完成”后发现错误如何处理? | 仅保留线下人工处理和审计,不建设在线冲正 | 模块阻断 | 已确认 | 产品/业务 | 2026-08-10 | `LOADED` 后不提供在线冲正/回退入口,统一线下人工处理;系统保留原状态和审计记录,不由国内 Admin/PDA 推进 `DELIVERED` | 装柜完成门禁、权限、审计 |
| P3-Q11 | 九个动作中哪些是强制前置,哪些允许并行? | 统一门禁按已确认前置执行;PDA 单柜次单人作业 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10 | 订舱完成、拖车完成、报关资料完成且有放行回执、PDA 拣货完成及五类证据完整均为进入 `LOADED` 的强制门禁;PDA 单柜次单人作业,不做多人并行;进入任务即拣货中,提交时批量写入 | 全流程、状态机、PDA、页面进度 | | P3-Q11 | 九个动作中哪些是强制前置,哪些允许并行? | 统一门禁按已确认前置执行;PDA 单柜次单人作业 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10;2026-09-24 更正 | 费用确认不阻断排柜、预装、PDA 或装柜。进入 `LOADED` 只校验物理装柜、PDA、数量、真实柜号和五类证据;`LOADED` 后先完成退税报关,报关完成后进入待发区,再推进送港和船期;甩柜/改配只改变船次,不重做已完成报关;PDA 单柜次单人作业 | 全流程、状态机、PDA、报关、送港、页面进度 |
| P3-Q12 | 报关回执包含哪些类型,海关放行是否为装柜完成硬门禁? | 有效放行回执作为硬门禁,首版人工上传 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10 | 首版回执由人工上传;必须存在有效放行回执才能通过 `LOADED` 门禁。回执类型和版本可追溯,具体字段按人工业务单据映射 | 报关状态、装柜完成门禁、客户回执 | | P3-Q12 | 报关回执包含哪些类型,客户确认和海关放行如何衔接? | 首版人工上传回执并保留版本 | 开工阻断 | 已确认 | 产品/业务 | 2026-08-10;2026-09-24 更正 | `LOADED` 后按客户/入仓码收集资料并发送报关行;报关行回执发对应客户确认,客户打回则重新上传、重新发送并生成新回执;所有客户确认后才向报关行提交整柜资料并正式申报;之后分别记录查验、不查验放行、补件/退回等海关结果。回执上传不等于客户确认,客户确认也不等于海关放行 | 报关状态、客户回执、整柜申报、海关结果 |
| P3-Q13 | 国内货柜履约终点以什么状态为准? | 国内系统以能掌控的最后环节为终点 | 开工阻断 | 已确认 | 用户当前对话确认 | 2026-08-08 | 国内货柜履约终点为 `LOADED`/装柜完成;`DELIVERED`/派送完成只能在到达海外仓后由海外仓可信回传推进,不属于国内国内货柜履约操作和验收范围 | 阶段边界、状态、里程碑、验收、海外仓回传 | | P3-Q13 | 国内货柜履约终点以什么状态为准? | 国内系统以能掌控的最后环节为终点 | 开工阻断 | 已确认 | 用户当前对话确认 | 2026-08-08 | 国内货柜履约终点为 `LOADED`/装柜完成;`DELIVERED`/派送完成只能在到达海外仓后由海外仓可信回传推进,不属于国内国内货柜履约操作和验收范围 | 阶段边界、状态、里程碑、验收、海外仓回传 |
| P3-Q14 | 订舱、渠道柜次、放舱与智能排柜的先后关系是什么? | 线下已订妥的订舱在创建时完整登记五项真实运输快照并直接确认;放舱不覆盖首次快照 | 开工阻断 | 已确认 | 用户当前对话确认 | 2026-08-12 | 订舱创建请求必须携带提单号、船名、航次、预计开船时间、预计到港时间五项真实运输数据,并直接进入 `CONFIRMED`;渠道、箱型和数量同时确定,系统按箱型需求数量生成绑定渠道的稳定内部柜次。未放舱不影响候选查询、智能推荐、人工调整和保存装柜计划;同一柜次只能装同渠道入库单,服务端禁止跨渠道混装。`RELEASED` 仅作为后续放舱/PDA 门禁,不补录、不覆盖首次五项运输快照;真实集装箱号可在放舱时或之后录入 | 订舱、柜次、智能排柜、预装、PDA、运输信息 | | 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`/海运节点 | 送港、船次、甩柜、海运节点 |
### 2.1 PDA 已确认子决策 ### 2.1 PDA 已确认子决策
@@ -44,7 +47,7 @@
| P3-PDA-D08 | 2026-08-09 | 同类型证据允许多张并采用追加记录;错误/重复照片不硬删除,只作废 | 每条照片独立保存;作废记录原因、操作人和时间,历史可追溯 | | P3-PDA-D08 | 2026-08-09 | 同类型证据允许多张并采用追加记录;错误/重复照片不硬删除,只作废 | 每条照片独立保存;作废记录原因、操作人和时间,历史可追溯 |
| P3-PDA-D09 | 2026-08-09 | 空仓、半仓、满仓、锁仓、带锁码照五类证据各至少 1 张有效且未作废的照片,可多张;带锁码照同时要求锁码文本 | 服务端完整性门禁按“每类至少一张有效记录”校验,不能按单槽位替换模型实现 | | P3-PDA-D09 | 2026-08-09 | 空仓、半仓、满仓、锁仓、带锁码照五类证据各至少 1 张有效且未作废的照片,可多张;带锁码照同时要求锁码文本 | 服务端完整性门禁按“每类至少一张有效记录”校验,不能按单槽位替换模型实现 |
> 验收映射:当前自动化已真实覆盖五类证据上传、同类型多图追加、跨类型/伪造 `fileId` 拒绝、锁码文本门禁和错图作废审计;设备在线、持久化草稿批量提交仍按[验收任务拆分与待确认清单](国内货柜履约验收任务拆分与待确认清单.md)保留 coverageGap。 > 验收映射:当前自动化已真实覆盖五类证据上传、同类型多图追加、跨类型/伪造 `fileId` 拒绝、锁码文本门禁和错图作废审计;设备在线、持久化草稿批量提交仍按[验收任务拆分与待确认清单](归档/国内货柜履约验收任务拆分与待确认清单.md)保留 coverageGap。
## 三、已确认架构决策 ## 三、已确认架构决策
@@ -52,9 +55,10 @@
|---|---|---|---| |---|---|---|---|
| P3-D1 | 2026-08-08 | 国内货柜履约不新建独立出仓单,现有订单列表承载全部主状态;柜次、订舱、拖车、拣货、证据和报关作为订单关联子对象 | 取消出仓单页面和数据模型规划,改为增强现有订单列表/详情及服务端统一编排 | | P3-D1 | 2026-08-08 | 国内货柜履约不新建独立出仓单,现有订单列表承载全部主状态;柜次、订舱、拖车、拣货、证据和报关作为订单关联子对象 | 取消出仓单页面和数据模型规划,改为增强现有订单列表/详情及服务端统一编排 |
| P3-D2 | 2026-08-10 | 订单拆分采用“父订单→子订单→柜次”;已装载数量形成子订单,未装载数量自动生成后续子订单;支持一单多柜和多订单拼柜 | 后端必须保留父子订单、柜次、数量分摊和整体时间线;不得把未装载部分静默丢弃 | | P3-D2 | 2026-08-10 | 订单拆分采用“父订单→子订单→柜次”;已装载数量形成子订单,未装载数量自动生成后续子订单;支持一单多柜和多订单拼柜 | 后端必须保留父子订单、柜次、数量分摊和整体时间线;不得把未装载部分静默丢弃 |
| P3-D3 | 2026-08-10 | `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-D4 | 2026-08-10;2026-08-19 更正归期 | 船公司官网查询:每 3 天一次、最多 3 次,保存来源、更新时间和过期标识 | 该能力及首批六家来源整体归海外仓业务,国内货柜履约只保留订舱与出仓前船期资料 |
| P3-D5 | 2026-08-10 | 初始化仓库常用角色:操作员、拣货员、理货员;按最小权限授予拣货、证据上传和查看能力 | 角色初始化由 IAM/统一 SQL 任务实现,具体权限矩阵在技术契约评审中落表 | | P3-D5 | 2026-08-10 | 初始化仓库常用角色:操作员、拣货员、理货员;按最小权限授予拣货、证据上传和查看能力 | 角色初始化由 IAM/统一 SQL 任务实现,具体权限矩阵在技术契约评审中落表 |
| P3-D6 | 2026-09-24 | 费用确认不阻断排柜和装柜;装柜完成后对已装范围的当前有效已发布版本执行系统默认确认,来源与客户主动确认分开审计;`LOADED` 后报关采用“报关行回执→客户确认/打回重做→所有客户通过→整柜正式申报→查验/放行”,报关完成后进入待发区,送港/船次单独记录甩柜和实际开船 | 同步费用版本、部分装载、客户报关案例、回执轮次、整柜申报、待发区、送港/船次和客户/后台节点 |
## 四、建议确认顺序 ## 四、建议确认顺序
@@ -73,8 +77,8 @@
### 5.2 会议输入 ### 5.2 会议输入
- 本确认表中的 P3-Q1~P3-Q13。 - 本确认表中的 P3-Q1~P3-Q17。
- `国内货柜履约开发规划.md` 的流程、状态、里程碑和任务骨架。 - `归档/国内货柜履约开发规划.md` 的流程、状态、里程碑和任务骨架。
- `国内货柜履约页面与原型清单.md` 中已有参考原型和待补页面。 - `国内货柜履约页面与原型清单.md` 中已有参考原型和待补页面。
- 入库测量与计费输出契约、目标 PDA 信息、文件存储能力及报关/港务协作现状。 - 入库测量与计费输出契约、目标 PDA 信息、文件存储能力及报关/港务协作现状。
@@ -93,3 +97,4 @@
- 国内货柜履约范围内/范围外清单及跨期依赖。 - 国内货柜履约范围内/范围外清单及跨期依赖。
- 仍有风险的事项、责任人和完成日期。 - 仍有风险的事项、责任人和完成日期。
- 已允许进入 T02 契约设计与任务拆分;未决技术项只阻断其对应实现,不反向阻断整期已确认范围。 - 已允许进入 T02 契约设计与任务拆分;未决技术项只阻断其对应实现,不反向阻断整期已确认范围。
+18
View File
@@ -0,0 +1,18 @@
# 国内货柜履约历史记录
本目录保存国内货柜履约的开发规划、进度、开工门禁、验收、审计和旧确认材料。内容不删除,也不作为当前流程入口;当前规则以[国内货柜履约 README](../README.md)、[头程到尾程流程节点梳理](../../头程到尾程流程节点梳理.md)和[报关资料与船期价格接入梳理](../报关资料与船期价格接入梳理.md)为准。
## 文件
- [开发规划](国内货柜履约开发规划.md)
- [开发进度表](国内货柜履约开发进度表.md)
- [开发进度表(Excel)](虫虫出海国内货柜履约开发进度表.xlsx)
- [需求确认表之外的开工门禁与验收记录](国内货柜履约开工门禁.md)
- [验收任务拆分与待确认清单](国内货柜履约验收任务拆分与待确认清单.md)
- [货柜管理全链验收矩阵](货柜管理全链验收矩阵-2026-08-13.md)
- [货柜履约原型字段验收矩阵](货柜履约原型字段验收矩阵-2026-08-17.md)
- [闭环审计报告](国内货柜履约闭环审计报告-2026-08-08.md)
- [装柜闭环产品确认表](国内货柜履约装柜闭环产品确认表-2026-08-08.md)
- [装柜闭环开发前确认单](国内货柜履约装柜闭环开发前确认单-2026-08-08.md)
- [Wave1 开发任务卡](国内货柜履约Wave1开发任务卡-2026-08-09.md)
@@ -1,5 +1,7 @@
# 国内货柜履约 Wave 1 开发任务卡 # 国内货柜履约 Wave 1 开发任务卡
> **历史版本声明(2026-09-24)**:本文是旧版低风险任务拆分,不能直接作为当前开发排期或门禁依据。当前流程改为“柜前资料预收集 → 物理装柜 `LOADED` → 按最终实装清单正式报关 → 有效放行回执后 `DEPARTED_WAREHOUSE`”,费用确认不阻断装柜,装柜完成时按已装范围对当前有效已发布费用版本执行系统默认确认。当前开发范围以 [头程到尾程流程节点梳理(重构版)](../../头程到尾程流程节点梳理.md)、[报关资料与船期价格接入梳理](../报关资料与船期价格接入梳理.md) 和最新需求确认表为准。
整理日期:2026-08-09 整理日期:2026-08-09
用途:产品确认后用于研发排期和任务分派。 用途:产品确认后用于研发排期和任务分派。
当前范围:只做低风险基础能力;不提前实现未确认的主状态机规则。 当前范围:只做低风险基础能力;不提前实现未确认的主状态机规则。
@@ -53,3 +55,4 @@
- 允许无拣货、缺照片或缺锁码进入 `LOADED`。 - 允许无拣货、缺照片或缺锁码进入 `LOADED`。
- 国内 Admin/PDA 手工推进 `DELIVERED`。 - 国内 Admin/PDA 手工推进 `DELIVERED`。
- 在产品未确认前固化部分拣货拆单和一单多柜聚合规则。 - 在产品未确认前固化部分拣货拆单和一单多柜聚合规则。
@@ -2,12 +2,12 @@
> 创建日期:2026-07-28 > 创建日期:2026-07-28
> 状态:已进入分模块开发规划 > 状态:已进入分模块开发规划
> 流程依据:[出仓流程](参考资料/出仓流程.png)中的头程物流“03 出仓”;用户已于 2026-08-08 确认国内国内货柜履约以 `LOADED`/装柜完成为阶段终点 > 流程依据:[出仓流程](../参考资料/出仓流程.png)中的头程物流“03 出仓”;当前以 `LOADED` 作为物理装柜节点,报关线和送港线在装柜后并行,实际开船后进入海运节点。
> 前置阶段:[订单与客户文档](../订单与客户/README.md) · [入库测量与计费文档](../入库测量与计费/README.md) > 前置阶段:[订单与客户文档](../../订单与客户/README.md) · [入库测量与计费文档](../../入库测量与计费/README.md)
> 2026-08-10 产品确认版:国内货柜履约不新建独立出仓单;支持一单多柜、一个柜拼多个订单,采用“父订单→子订单→柜次”关系,已装载数量形成子订单,未装载数量自动生成后续子订单。`LOADED` 硬门禁为订舱完成、拖车完成、报关放行回执、PDA 拣货完成和五类证据完整;`LOADED` 后错误线下人工处理。五类证据各至少 1 张有效照片,同类型多张追加,PDA 仅现场拍照,后台操作员和理货员可人工上传,照片无限期保留且客户不可见。 > 2026-08-10 产品确认版;2026-09-24 按最新流程更正:国内货柜履约不新建独立出仓单;支持一单多柜、一个柜拼多个订单,采用“父订单→子订单→柜次”关系,已装载数量形成子订单,未装载数量自动生成后续子订单。`LOADED` 仅校验真实柜号、PDA 拣货、数量守恒和五类证据;装柜后报关线按“客户资料→报关行回执→客户确认/打回重做→所有客户通过→整柜正式申报→查验/放行”推进,送港线独立记录离仓、进港、甩柜和改配,实际开船才进入海运。费用确认不阻断排柜和装柜;装柜完成后对已装范围的当前有效已发布费用版本执行系统默认确认,保留客户/系统来源。`LOADED` 后错误线下人工处理。五类证据各至少 1 张有效照片,同类型多张追加,PDA 仅现场拍照,后台操作员和理货员可人工上传,照片无限期保留且客户不可见。
> 当前范围更正:原 `P3-PORT-01`、六家船公司官网查询及 `CarrierScheduleQuery` 是柜子确认离开国内仓库后的业务,整体重新归入海外仓业务。国内货柜履约仅保存订舱与出仓前所需的船名航次、港口和 ETD/ETA 等资料,不建设或验收出仓后的定时节点查询。 > 当前范围更正:国内货柜履约保留 `DEPARTED_WAREHOUSE`、`PORT_RECEIVED`、`ROLLED_OVER` 和实际开船前的船次/港口事实;承运船舶真实 `VESSEL_DEPARTED` 后的六家船公司官网查询、`CarrierScheduleQuery` 和定时节点查询归入海外仓业务。国内侧不以预计 ETD 提前展示海运中。
> 主体模型与硬约束:国内货柜履约只实现“平台—客户”两级,业务 `tenant_id > 0` / `tenantId` 当前表示客户 ID;`tenant_id=0` 是平台身份、平台 RBAC 和平台公共仓储资源技术作用域,客户往来单位、订单、文件和费用归属客户 `tenant_id>0`。禁止新增租户主表、租户选择器、客户所属租户配置、租户切换、租户级 RBAC 或租户级配置,禁止把现有 `tenant_id` 改义为上级租户 ID;历史类名、路径和字段继续兼容。 > 主体模型与硬约束:国内货柜履约只实现“平台—客户”两级,业务 `tenant_id > 0` / `tenantId` 当前表示客户 ID;`tenant_id=0` 是平台身份、平台 RBAC 和平台公共仓储资源技术作用域,客户往来单位、订单、文件和费用归属客户 `tenant_id>0`。禁止新增租户主表、租户选择器、客户所属租户配置、租户切换、租户级 RBAC 或租户级配置,禁止把现有 `tenant_id` 改义为上级租户 ID;历史类名、路径和字段继续兼容。
@@ -20,16 +20,15 @@
```text ```text
智能排柜 → 订舱 → 预约拖车 智能排柜 → 订舱 → 预约拖车
↓ ↓
PDA 拣货 → 装柜并上传货柜/铅封照片 PDA 拣货 → 装柜并上传五类证据
↓ ↓
客户上传报关资料 → 平台整理提交报关代理 → 上传回执供客户下载 `LOADED`/装柜完成
↓ ├─ 报关:通知报关行 → 客户资料 → 报关行回执 → 客户确认/打回重做
维护订舱与出仓前所需的船名航次、港口和预计时间 │ → 所有客户通过 → 整柜正式申报 → 查验/放行
↓ └─ 送港:拖车 → 离仓 → 送港/进港 → 甩柜/改配(如发生)→ 实际开船
国内国内货柜履约完成:`LOADED`/装柜完成
``` ```
国内货柜履约完成标准是同一订单/柜次已完成排柜和 PDA 拣货,空仓、半仓、满仓、锁仓、带锁码照五类证据各至少 1 张有效照片已真实上传,锁码文本已保存,服务端门禁通过并将订单推进为 `LOADED`/装柜完成。`DELIVERED`/派送完成必须等货物到达海外仓后由海外仓可信回传推进,不是国内国内货柜履约人工操作。 国内货柜履约的装柜完成标准是同一订单/柜次已完成排柜和 PDA 拣货,空仓、半仓、满仓、锁仓、带锁码照五类证据各至少 1 张有效照片已真实上传,锁码文本已保存,数量守恒且服务端门禁通过后推进为 `LOADED`/装柜完成。`LOADED` 后报关线和送港线同时启动;客户确认不阻断送港,进港不代表报关完成,容量不足记录甩柜;只有承运船舶实际开航后才进入海运节点。`DELIVERED`/派送完成必须等货物到达海外仓后由海外仓可信回传推进,不是国内国内货柜履约人工操作。
### 原型动作覆盖 ### 原型动作覆盖
@@ -42,8 +41,8 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
| 5. 拍货柜及铅封照上传 | 装柜及柜封证据 | P3-LOAD-01、P3-LOAD-02 | 已确认五类证据各至少 1 张有效照片、同类型可多张,锁码文本必填 | | 5. 拍货柜及铅封照上传 | 装柜及柜封证据 | P3-LOAD-01、P3-LOAD-02 | 已确认五类证据各至少 1 张有效照片、同类型可多张,锁码文本必填 |
| 6. 客户上传报关资料 | 报关资料协同 | P3-CUS-01 | 已覆盖 | | 6. 客户上传报关资料 | 报关资料协同 | P3-CUS-01 | 已覆盖 |
| 7. 整理给到报关代理报关 | 报关资料协同 | P3-CLEAR-01 | 已覆盖 | | 7. 整理给到报关代理报关 | 报关资料协同 | P3-CLEAR-01 | 已覆盖 |
| 8. 回执上传到系统供客户下载 | 报关回执与客户下载 | P3-CLEAR-01、P3-CUS-02 | 已覆盖,首版由授权人员人工上传放行回执 | | 8. 回执上传并由客户确认 | 报关行回执与客户确认 | P3-CLEAR-01、P3-CUS-02 | 待补齐多轮回执、客户确认/打回和整柜正式提交 |
| 9. 出仓后查询港务/船节点 | 海外仓业务船节点定时查询 | 原 P3-PORT-01、P3-CUS-02 对应查询部分 | 已重新归入海外仓业务,不是国内货柜履约动作或验收项 | | 9. 送港、甩柜与实际开船 | 送港/船次事实 | P3-TRUCK-01、P3-CUS-02 | 装柜后与报关线并行;实际开船后进入海运节点 |
## 二、阶段边界 ## 二、阶段边界
@@ -54,8 +53,9 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
- 预约拖车、车辆司机、到仓装柜和离仓记录。 - 预约拖车、车辆司机、到仓装柜和离仓记录。
- PDA 任务领取、扫码拣货、部分拣货、异常、复核和幂等提交。 - PDA 任务领取、扫码拣货、部分拣货、异常、复核和幂等提交。
- 装柜、柜号、铅封号及货柜/铅封照片证据。 - 装柜、柜号、铅封号及货柜/铅封照片证据。
- 客户上传报关资料、平台审核补件、整理并提交报关代理。 - `LOADED` 后通知报关行,客户上传报关资料、平台审核补件、线下发送报关行。
- 报关回执上传、版本、客户可见范围和授权下载。 - 报关行回执上传、版本、客户确认/打回重做、客户可见范围和授权下载;所有客户确认后才提交整柜资料正式申报。
- 装柜后送港、进港、甩柜/改配和实际开船事实。
- 装柜完成门禁、确认、时间线和站内通知;`LOADED` 后纠错走线下人工流程。 - 装柜完成门禁、确认、时间线和站内通知;`LOADED` 后纠错走线下人工流程。
### 明确不纳入国内货柜履约 ### 明确不纳入国内货柜履约
@@ -65,7 +65,7 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
- GPS 实时跟车、电子铅封、称重设备、摄像头 OCR 和 IoT 自动采集。 - GPS 实时跟车、电子铅封、称重设备、摄像头 OCR 和 IoT 自动采集。
- 自动报关、关税计算、退税、完整清关业务和自动单证识别。 - 自动报关、关税计算、退税、完整清关业务和自动单证识别。
- 海上运输、海外清关、目的港提柜、海外仓入库和末端派送。 - 海上运输、海外清关、目的港提柜、海外仓入库和末端派送。
- 柜子确认离开国内仓库后的 `CarrierScheduleQuery`、船公司查询、定时船节点和到港跟踪;整体归海外仓业务。 - 承运船舶真实 `VESSEL_DEPARTED` 后的 `CarrierScheduleQuery`、船公司查询、定时船节点和海上到港跟踪;整体归海外仓业务。国内侧保留送港、进港和甩柜事实。
- 无人工确认的全自动排柜、自动订舱和不可逆业务操作。 - 无人工确认的全自动排柜、自动订舱和不可逆业务操作。
## 三、参与角色与数据边界 ## 三、参与角色与数据边界
@@ -87,7 +87,7 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
## 四、流程与状态设计 ## 四、流程与状态设计
原型以 1 至 9 编号表达动作顺序。产品确认后,订舱、拖车、报关放行、PDA 拣货和证据完整是进入 `LOADED` 的强制前置;智能排柜、订舱、拖车和资料整理可按子流程并行,但服务端不得绕过门禁。PDA 单柜次单作业员,不实现多人并行或任务接管。 原图以 1 至 9 编号表达展示动作顺序。按本轮确认,费用确认不阻断排柜或装柜;`LOADED` 只校验物理装柜事实,装柜后报关线和送港线并行,客户确认不阻断送港,进港不代表报关完成,实际开船才进入海运。PDA 单柜次单作业员,不实现多人并行或任务接管。
### 1. 现有订单的国内货柜履约主状态 ### 1. 现有订单的国内货柜履约主状态
@@ -95,7 +95,7 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
|---|---|---| |---|---|---|
| `WAIT_SPLIT` | 待分柜 | 入库测量与计费已完成,等待排柜/预装 | | `WAIT_SPLIT` | 待分柜 | 入库测量与计费已完成,等待排柜/预装 |
| `LOADING` | 装柜中 | 预装已确认,PDA 执行拣货和装柜证据上传 | | `LOADING` | 装柜中 | 预装已确认,PDA 执行拣货和装柜证据上传 |
| `LOADED` | 装柜完成 | 订舱、拖车、报关放行回执、PDA 拣货完成,且五类证据各至少 1 张有效照片和锁码文本已通过服务端门禁 | | `LOADED` | 装柜完成 | 真实柜号、PDA 拣货与数量守恒、五类证据各至少 1 张有效照片和锁码文本已通过服务端门禁;装柜后同时启动报关线和送港线 |
| `DELIVERED` | 派送完成 | 货物到达海外仓后由海外仓可信回传推进;属于国内货柜履约之后的只读状态 | | `DELIVERED` | 派送完成 | 货物到达海外仓后由海外仓可信回传推进;属于国内货柜履约之后的只读状态 |
### 2. 子流程状态 ### 2. 子流程状态
@@ -103,8 +103,8 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
- 订舱:待订舱、订舱中、已订舱、订舱失败、已取消。 - 订舱:待订舱、订舱中、已订舱、订舱失败、已取消。
- 拖车:待预约、已预约、车辆已到仓、装柜中、已离仓、改约、已取消。 - 拖车:待预约、已预约、车辆已到仓、装柜中、已离仓、改约、已取消。
- 拣货:待分配、待拣货、拣货中、待复核、已完成、异常挂起、已取消。 - 拣货:待分配、待拣货、拣货中、待复核、已完成、异常挂起、已取消。
- 报关:资料待上传、资料待审核、待补件、待提交、已提交代理、回执待上传、回执已上传、已退回、已取消;有效放行回执是 `LOADED` 硬门禁,首版由授权人员人工上传。 - 报关:`LOADED` 后待通知报关、客户资料待上传/审核、已发报关行、回执待客户确认、客户已确认、客户打回待重做、所有客户已确认、整柜正式申报、查验、放行/退回;回执上传不等于客户确认,客户确认不等于海关放行。
- 出仓前船期资料:待维护、已确认、信息变更;出仓后节点和“已开船”等运输事实归海外仓业务。 - 送港/船期:待送港、已离仓、送港中、已进港、甩柜/改配、待开船;只有实际 `VESSEL_DEPARTED` 后进入海运节点。
主状态由服务端根据已确认的必要子流程推进。客户端不得通过传任意目标状态跳过拣货复核、装柜证据或已配置的装柜完成门禁。 主状态由服务端根据已确认的必要子流程推进。客户端不得通过传任意目标状态跳过拣货复核、装柜证据或已配置的装柜完成门禁。
@@ -127,10 +127,10 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
### 3. 订舱与出仓前船期资料 ### 3. 订舱与出仓前船期资料
- 国内货柜履约只维护订舱和装柜/出仓交接所需的预计开船、到港等静态资料,不执行出仓后的船公司或船节点查询。 - 国内货柜履约维护订舱、送港、进港、甩柜/改配和实际开船前的状态;承运船舶实际开航后由海外仓业务执行船公司和船节点查询。
- 船公司/订舱代理、航线、订舱号、船名航次、起运港、目的港、截单、截关、截港、ETD 和 ETA 暂列为候选字段。 - 船公司/订舱代理、航线、订舱号、船名航次、起运港、目的港、截单、截关、截港、ETD 和 ETA 暂列为候选字段。
- 订舱失败、改船、甩柜、船期延误和取消暂列为候选异常场景,按业务确认结果实现。 - 订舱失败、改船、甩柜、船期延误和取消暂列为候选异常场景,按业务确认结果实现。
- 六家船公司来源、每 3 天/最多 3 次、最近有效结果和过期标识,以及对应适配层全部移至海外仓业务船节点查询维护。 - 六家船公司来源、每 3 天/最多 3 次、最近有效结果和过期标识,以及对应适配层在 `VESSEL_DEPARTED` 后由海外仓业务船节点查询维护。
- 国内货柜履约页面展示的 ETD/ETA 必须明确为订舱或人工确认快照,不得伪装成出仓后的实时查询结果。 - 国内货柜履约页面展示的 ETD/ETA 必须明确为订舱或人工确认快照,不得伪装成出仓后的实时查询结果。
- 建议关键信息变更保留旧值、新值、原因,并向授权用户发送站内提醒。 - 建议关键信息变更保留旧值、新值、原因,并向授权用户发送站内提醒。
@@ -165,18 +165,20 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
### 7. 报关资料协同 ### 7. 报关资料协同
- 客户按资料清单上传发票、箱单、合同、委托书和申报要素等文件。 - `LOADED` 后按最终实装清单建立每个客户/入仓码的报关案例;客户按资料清单上传发票、箱单、合同、委托书和申报要素等文件。
- 资料清单可按国家/地区、渠道和货物类型配置,并保存订单使用的清单版本。 - 资料清单可按国家/地区、渠道和货物类型配置,并保存订单使用的清单版本。
- 平台报关专员审核完整性,可退回具体文件并记录补件原因和时限。 - 平台报关专员审核完整性,可退回具体文件并记录补件原因和时限。
- 提交报关代理时生成提交批次,冻结该批次关联的文件版本。 - 资料发送报关行时记录 roundNo 和发送时间,报关行回执上传后发对应客户确认;客户打回则重新上传、重新发送并生成新回执版本。
- 柜内所有客户确认后才生成整柜正式提交批次,冻结该批次关联的文件版本并交报关行正式申报。
- 首版采用系统内整理加线下提交,不直接对接海关单一窗口。 - 首版采用系统内整理加线下提交,不直接对接海关单一窗口。
### 8. 报关回执与客户下载 ### 8. 报关回执与客户下载
- 授权人员人工上传代理回传的报关回执并关联提交批次;有效放行回执是装柜完成硬门禁,回执类型、版本和操作者可追溯。 - 授权人员人工上传报关行回传的每轮回执并关联客户报关案例;回执类型、版本、roundNo、操作者和客户确认/打回结果可追溯。
- 替换文件产生新版本,不覆盖原记录;退单或补件形成明确任务。 - 替换文件产生新版本,不覆盖原记录;退单或补件形成明确任务。
- 客户只能下载本企业且标记为客户可见的回执。 - 客户只能下载本企业且标记为客户可见的回执。
- 文件下载使用授权地址并记录审计,不暴露内部存储路径。 - 文件下载使用授权地址并记录审计,不暴露内部存储路径。
- 所有客户确认后,平台向报关行提交整柜资料;报关行正式申报后另行记录查验、不查验放行、补件/退回等海关结果。
### 9. 装柜完成确认与海外回传边界 ### 9. 装柜完成确认与海外回传边界
@@ -246,8 +248,8 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
| P3-M2 订舱与拖车 | 订舱、出仓前船期资料、拖车预约和异常处理可用 | 服务商与权限可用 | | P3-M2 订舱与拖车 | 订舱、出仓前船期资料、拖车预约和异常处理可用 | 服务商与权限可用 |
| P3-M3 PDA 拣货 | 在线任务、持久化草稿、批量提交、差异、复核和幂等可用 | 服务端任务与库存契约可用 | | P3-M3 PDA 拣货 | 在线任务、持久化草稿、批量提交、差异、复核和幂等可用 | 服务端任务与库存契约可用 |
| P3-M4 装柜封柜 | 柜号、铅封和照片证据完整,门禁生效 | 文件能力与必传清单确认 | | P3-M4 装柜封柜 | 柜号、铅封和照片证据完整,门禁生效 | 文件能力与必传清单确认 |
| P3-M5 报关协同 | 客户上传、平台审核、补件、提交和回执下载闭环 | 报关资料清单确认 | | P3-M5 报关协同 | `LOADED` 后客户资料、报关行回执、客户确认/打回重做、所有客户通过、整柜正式申报和查验/放行闭环 | 报关资料清单确认 |
| P3-M6 装柜完成 | 订舱、拖车、放行回执、PDA 拣货、五类证据和锁码文本满足门禁后进入 `LOADED`/装柜完成 | 装柜完成硬门禁已确认 | | P3-M6 装柜完成及并行送港 | 真实柜号、PDA 拣货、数量守恒、五类证据和锁码文本满足门禁后进入 `LOADED`;随后并行推进送港/进港/甩柜和报关线,实际开船才进入海运 | 装柜完成、报关线和送港线分开 |
| P3-M7 联调验收 | 跨端、设备、安全、弱网、性能、迁移和发布完成 | P3-M1 至 P3-M6 验收通过 | | P3-M7 联调验收 | 跨端、设备、安全、弱网、性能、迁移和发布完成 | P3-M1 至 P3-M6 验收通过 |
## 九、建议开发任务 ## 九、建议开发任务
@@ -259,18 +261,18 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
| P3-DSP-01 | 后台 | 订单国内货柜履约编排 | 在现有订单列表/详情中接入柜次、子流程、异常、时间线和门禁操作 | P0 | P3-BASE-02 | | P3-DSP-01 | 后台 | 订单国内货柜履约编排 | 在现有订单列表/详情中接入柜次、子流程、异常、时间线和门禁操作 | P0 | P3-BASE-02 |
| P3-PLAN-01 | 公共 | 排柜规则 | 按已确认规则实现输入、约束、偏好和冲突判断 | P0 | P3-BASE-02、P3-Q1 | | P3-PLAN-01 | 公共 | 排柜规则 | 按已确认规则实现输入、约束、偏好和冲突判断 | P0 | P3-BASE-02、P3-Q1 |
| P3-PLAN-02 | 后台 | 智能排柜 | 按已确认范围实现建议、人工确认和追溯 | P0 | P3-PLAN-01 | | P3-PLAN-02 | 后台 | 智能排柜 | 按已确认范围实现建议、人工确认和追溯 | P0 | P3-PLAN-01 |
| P3-BOOK-01 | 后台 | 订舱 | 订舱和经确认的船名航次、港口、变更及异常;订舱完成是 `LOADED` 门禁 | P0 | P3-DSP-01 | | P3-BOOK-01 | 后台 | 订舱 | 订舱和经确认的船名航次、港口、变更及异常;订舱/拖车服务送港线,不作为 `LOADED` 的报关前置 | P0 | P3-DSP-01 |
| 原 P3-PORT-01 | 后台/服务端 | 出仓后船节点查询 | 已重新归入海外仓业务,不作为国内货柜履约交付或验收项;沿用现有 `CarrierScheduleQuery`,不得重复实现 | 海外仓业务 | P3-BOOK-01、确认国内出仓 | | P3-PORT-01 | 后台/服务端 | 送港、进港与甩柜 | 记录 `DEPARTED_WAREHOUSE`、`PORT_RECEIVED`、`ROLLED_OVER`、改配船次和客户通知;不以预计 ETD 推进海运 | P0 | P3-BOOK-01、P3-TRUCK-01 |
| P3-TRUCK-01 | 后台 | 拖车预约 | 服务商、车辆司机、时间窗、到离仓和异常 | P0 | P3-DSP-01 | | P3-TRUCK-01 | 后台 | 拖车预约 | 服务商、车辆司机、时间窗、到离仓、进港和异常 | P0 | P3-DSP-01 |
| P3-PICK-01 | 公共 | 拣货任务 | 按排柜方案生成任务、明细、差异和复核规则 | P0 | P3-PLAN-02 | | P3-PICK-01 | 公共 | 拣货任务 | 按排柜方案生成任务、明细、差异和复核规则 | P0 | P3-PLAN-02 |
| P3-PDA-01 | PDA | 在线扫码拣货 | 进入任务标记拣货中、扫描草稿、部分/跳拣异常原因和批量提交 | P0 | P3-PICK-01 | | P3-PDA-01 | PDA | 在线扫码拣货 | 进入任务标记拣货中、扫描草稿、部分/跳拣异常原因和批量提交 | P0 | P3-PICK-01 |
| P3-PDA-02 | PDA/服务端 | 草稿与提交安全 | 作业员+任务+柜次持久化草稿、幂等重试、版本冲突、成功/放弃清理 | P0 | P3-PDA-01 | | P3-PDA-02 | PDA/服务端 | 草稿与提交安全 | 作业员+任务+柜次持久化草稿、幂等重试、版本冲突、成功/放弃清理 | P0 | P3-PDA-01 |
| P3-LOAD-01 | 后台 | 装柜封柜 | 柜号、锁码文本、装柜节点、五类多图证据和门禁复核 | P0 | P3-PICK-01 | | P3-LOAD-01 | 后台 | 装柜封柜 | 柜号、锁码文本、装柜节点、五类多图证据和门禁复核 | P0 | P3-PICK-01 |
| P3-LOAD-02 | PDA/Admin/服务端 | 柜封拍照上传 | PDA 现场拍摄、Admin 人工上传、五类证据多图追加、真实文件上传、预览、失败重试、作废和提交 | P0 | P3-LOAD-01、文件能力可用 | | P3-LOAD-02 | PDA/Admin/服务端 | 柜封拍照上传 | PDA 现场拍摄、Admin 人工上传、五类证据多图追加、真实文件上传、预览、失败重试、作废和提交 | P0 | P3-LOAD-01、文件能力可用 |
| P3-CUS-01 | 客户端 | 报关资料 | 清单、上传、补件、版本和进度查看 | P0 | 文件能力可用 | | P3-CUS-01 | 客户端 | 报关资料与客户确认 | `LOADED` 后清单、上传、补件、回执查看、确认/打回和轮次进度 | P0 | 文件能力可用 |
| P3-CLEAR-01 | 后台 | 报关协同 | 人工审核、补件、线下提交代理、人工上传放行回执和版本审计 | P0 | P3-CUS-01 | | P3-CLEAR-01 | 后台 | 报关协同 | 通知报关行、人工审核、回执轮次、客户确认汇总、所有客户通过后整柜正式提交、查验/放行记录 | P0 | P3-CUS-01 |
| P3-CUS-02 | 客户端 | 回执及出仓前船期资料 | 回执下载、订舱预计开船/到港快照和变更时间线;出仓后查询展示归海外仓业务 | P0 | P3-BOOK-01、P3-CLEAR-01 | | P3-CUS-02 | 客户端 | 回执及送港/船期资料 | 回执确认、打回重做、送港/进港/甩柜和实际开船前状态展示 | P0 | P3-BOOK-01、P3-CLEAR-01 |
| P3-GATE-01 | 服务端 | 装柜完成门禁 | 校验订舱、拖车、报关放行回执、PDA 拣货、五类证据和锁码文本,幂等推进 `LOADED`;`LOADED` 后仅线下人工处理 | P0 | P3-PICK-01、P3-LOAD-01、P3-LOAD-02 | | P3-GATE-01 | 服务端 | 装柜完成与并行分支门禁 | 校验真实柜号、PDA 拣货、数量守恒、五类证据和锁码文本,幂等推进 `LOADED`;随后分别创建报关案例和送港任务,实际开船才推进海运 | P0 | P3-PICK-01、P3-LOAD-01、P3-LOAD-02 |
| P3-OVERSEAS-01 | 服务端 | 海外仓派送完成回传 | 只接受海外仓可信回传,校验身份、签名、时间窗、防重放和幂等,推进 `DELIVERED` | P1/后续阶段 | 海外仓契约 | | P3-OVERSEAS-01 | 服务端 | 海外仓派送完成回传 | 只接受海外仓可信回传,校验身份、签名、时间窗、防重放和幂等,推进 `DELIVERED` | P1/后续阶段 | 海外仓契约 |
| P3-NOTIFY-01 | 公共 | 通知异常 | 站内通知、阻塞、责任人、时限和失败补偿 | P1 | 核心流程完成 | | P3-NOTIFY-01 | 公共 | 通知异常 | 站内通知、阻塞、责任人、时限和失败补偿 | P1 | 核心流程完成 |
| P3-TEST-01 | 公共 | 自动化测试 | 权限、排柜、幂等、并发、文件、门禁和状态测试 | P0 | 所有 P0 模块 | | P3-TEST-01 | 公共 | 自动化测试 | 权限、排柜、幂等、并发、文件、门禁和状态测试 | P0 | 所有 P0 模块 |
@@ -305,11 +307,12 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
| P3-Q5 | 拣货是否依赖实时库存和库位可用量? | 已确认依赖入库测量与计费实时库存、当前位置和可用量接口;不扩展完整 WMS | | P3-Q5 | 拣货是否依赖实时库存和库位可用量? | 已确认依赖入库测量与计费实时库存、当前位置和可用量接口;不扩展完整 WMS |
| P3-Q6 | 柜封照片有哪些必传角度和留存期限? | 已确认:五类各至少 1 张、同类型可多张追加、后台操作员/理货员可上传、拣货员仅 PDA 现场采集、错图作废、无限期保留、客户不可见 | | P3-Q6 | 柜封照片有哪些必传角度和留存期限? | 已确认:五类各至少 1 张、同类型可多张追加、后台操作员/理货员可上传、拣货员仅 PDA 现场采集、错图作废、无限期保留、客户不可见 |
| P3-Q7 | 报关资料清单是否按国家、渠道和货物类型变化? | 已确认首版人工维护清单和版本,不接自动报关 | | P3-Q7 | 报关资料清单是否按国家、渠道和货物类型变化? | 已确认首版人工维护清单和版本,不接自动报关 |
| P3-Q8 | 报关代理如何接收资料和返回回执? | 已确认线下提交,授权人员人工上传回执 | | P3-Q8 | 报关代理如何接收资料和返回回执? | 已确认 `LOADED` 后线下提交;授权人员人工上传每轮回执,客户确认/打回,所有客户通过后再提交整柜资料 |
| P3-Q9 | 原型中的“港务信息”具体指船期、港口作业状态还是两者,包含哪些字段,由谁维护? | 当前更正:国内货柜履约只维护订舱与出仓前船期资料;六家船公司及出仓后节点查询整体归海外仓业务 | | P3-Q9 | 原型中的“港务信息”具体指船期、港口作业状态还是两者,包含哪些字段,由谁维护? | 当前更正:国内货柜履约维护送港、进港、甩柜/改配和实际开船前状态;只有实际开船后进入海运节点查询 |
| P3-Q10 | 进入装柜完成后发现错误如何处理? | 已确认线下人工处理,当前不提供在线冲正 | | P3-Q10 | 进入装柜完成后发现错误如何处理? | 已确认线下人工处理,当前不提供在线冲正 |
| P3-Q11 | 九个动作中哪些是强制前置,哪些允许并行? | 已确认订舱、拖车、报关放行、PDA 拣货和五类证据为 `LOADED` 硬门禁;单柜次单作业员 | | P3-Q11 | 九个动作中哪些是强制前置,哪些允许并行? | 费用确认不阻断排柜/装柜;`LOADED` 只校验物理装柜、PDA、数量和证据;报关线和送港线并行,客户确认不阻断送港,进港不代表报关完成;单柜次单作业员 |
| P3-Q12 | “报关回执”具体包含哪些类型,海关放行是否为国内出仓硬门禁? | 已确认有效放行回执为 `LOADED` 硬门禁,首版人工上传 | | P3-Q12 | “报关回执”具体包含哪些类型,海关放行如何与客户确认衔接? | 已确认:回执人工上传并发客户确认;客户打回则重做并生成新回执;所有客户通过后才整柜正式申报,查验/放行单独记录 |
| P3-Q17 | 送港和报关是否互相等待?甩柜何时发生? | 已确认:`LOADED` 后两条线同时启动;送港可先到港,报关可先完成客户确认;船舱不足记录甩柜/改配,实际开船才进入海运 |
| P3-Q13 | 国内货柜履约终点以什么状态为准? | 已确认为 `LOADED`/装柜完成;`DELIVERED`/派送完成由海外仓回传,不属于国内国内货柜履约 | | P3-Q13 | 国内货柜履约终点以什么状态为准? | 已确认为 `LOADED`/装柜完成;`DELIVERED`/派送完成由海外仓回传,不属于国内国内货柜履约 |
## 十二、建议实施顺序 ## 十二、建议实施顺序
@@ -320,3 +323,5 @@ PDA 拣货 → 装柜并上传货柜/铅封照片
4. 完成管理后台的出仓编排,再接 PDA 现场执行和客户资料协同。 4. 完成管理后台的出仓编排,再接 PDA 现场执行和客户资料协同。
5. 使用脱敏数据演练拼柜、一单多柜、未装数量生成子订单、错拣、补件和改船;`LOADED` 后不演练在线冲正。 5. 使用脱敏数据演练拼柜、一单多柜、未装数量生成子订单、错拣、补件和改船;`LOADED` 后不演练在线冲正。
6. 在真实 PDA 和代表性仓库网络环境中完成联调、验收和灰度发布。 6. 在真实 PDA 和代表性仓库网络环境中完成联调、验收和灰度发布。
@@ -8,7 +8,7 @@
## 一、国内货柜履约目标 ## 一、国内货柜履约目标
国内货柜履约承接入库测量与计费到仓、实测、差异处理、处理单元编码和当前位置记录,完成智能排柜、订舱、拖车预约、PDA 拣货、装柜拍照、报关协同、港务信息查询,并将现有订单推进到 `LOADED`/装柜完成。 国内货柜履约承接入库测量与计费到仓、实测、差异处理、处理单元编码和当前位置记录,完成智能排柜、订舱、拖车预约、PDA 拣货、装柜拍照,并在 `LOADED` 后分别推进报关客户确认闭环和送港/进港/甩柜;只有承运船舶实际开航才进入海运节点。
当前验收基线已确认为 `LOADED`/装柜完成。`DELIVERED`/派送完成只能在货物到达海外仓后由海外仓可信回传推进,不属于国内国内货柜履约操作和验收范围。 当前验收基线已确认为 `LOADED`/装柜完成。`DELIVERED`/派送完成只能在货物到达海外仓后由海外仓可信回传推进,不属于国内国内货柜履约操作和验收范围。
@@ -24,8 +24,8 @@
| T06 | 拖车预约 | 服务商、车辆司机、预约时间窗、到离仓节点和异常 | 联调中 | 80% | 2026-08-10 | 待排期 | Firstleg/Admin | 预约生命周期和服务中心串联已通过,最终 LOADED 门禁待 PDA | | T06 | 拖车预约 | 服务商、车辆司机、预约时间窗、到离仓节点和异常 | 联调中 | 80% | 2026-08-10 | 待排期 | Firstleg/Admin | 预约生命周期和服务中心串联已通过,最终 LOADED 门禁待 PDA |
| T07 | PDA 拣货与复核 | 在线进入任务、持久化扫描草稿、批量提交、部分拣货、异常、幂等和单人作业 | 已阻塞 | 45% | 2026-08-10 | 待排期 | Firstleg/PDA | `pick` 第二处真实 S0500 未收口;原子 batch、库存快照、失败整批回滚未实现 | | T07 | PDA 拣货与复核 | 在线进入任务、持久化扫描草稿、批量提交、部分拣货、异常、幂等和单人作业 | 已阻塞 | 45% | 2026-08-10 | 待排期 | Firstleg/PDA | `pick` 第二处真实 S0500 未收口;原子 batch、库存快照、失败整批回滚未实现 |
| T08 | 装柜及柜封证据 | 装柜节点、柜号、铅封号、PDA 现场拍照、后台角色上传、多图追加、作废和复核 | 联调中 | 80% | 2026-08-10 | 待排期 | Firstleg/Admin/PDA | 五类证据、多图追加、作废和硬门禁已通过;终态仍依赖 PDA | | T08 | 装柜及柜封证据 | 装柜节点、柜号、铅封号、PDA 现场拍照、后台角色上传、多图追加、作废和复核 | 联调中 | 80% | 2026-08-10 | 待排期 | Firstleg/Admin/PDA | 五类证据、多图追加、作废和硬门禁已通过;终态仍依赖 PDA |
| T09 | 报关资料与回执 | 人工资料清单、后台审核补件、线下提交代理、人工上传放行回执 | 联调中 | 70% | 2026-08-10 | 待排期 | Firstleg/Admin | 人工清单和资料版本已通过;LOADED 子订单关联受 PDA 失败级联阻断 | | T09 | 装柜后报关资料与客户确认 | `LOADED` 后通知报关行;客户资料→报关行回执→客户确认/打回重做→所有客户通过→整柜正式申报→查验/放行 | 联调中 | 70% | 2026-09-24 | 待排期 | Firstleg/Admin | 多轮回执、客户确认和整柜提交仍待实现 |
| T10 | 装柜完成门禁 | 校验订舱、拖车、报关放行、PDA 拣货、五类证据和锁码文本,推进 `LOADED` | 已阻塞 | 70% | 2026-08-10 | 待排期 | Firstleg | 门禁逐项读取和 fail-closed 已通过,真实推进 `LOADED` 等 PDA 修复 | | T10 | 装柜完成与送港/开船门禁 | `LOADED` 校验物理装柜;送港线独立校验订舱/拖车、离仓、进港和甩柜;实际开船才进入海运 | 已阻塞 | 70% | 2026-09-24 | 待排期 | Firstleg | 报关线和送港线并行口径已确认,真实推进与 PDA 修复仍待完成 |
| T11 | 客户端国内货柜履约协同 | 装柜进度、柜次、回执、预计开船/到港和变更时间线 | 待开始 | 0% | 待排期 | 待排期 | 待分配 | 客户不查看装柜照片和锁码;依赖 T05、T09、T10 | | T11 | 客户端国内货柜履约协同 | 装柜进度、柜次、回执、预计开船/到港和变更时间线 | 待开始 | 0% | 待排期 | 待排期 | 待分配 | 客户不查看装柜照片和锁码;依赖 T05、T09、T10 |
| T12 | 联调测试与发布 | 跨端联调、自动化测试、PDA 真机、安全、弱网、迁移、验收和发布 | 联调中 | 70% | 2026-08-10 | 待排期 | 总控/测试 | Admin、Firstleg 已分模块部署并持续真实 HTTP 验收;PDA S0500、batch 契约和真机验收未收口 | | T12 | 联调测试与发布 | 跨端联调、自动化测试、PDA 真机、安全、弱网、迁移、验收和发布 | 联调中 | 70% | 2026-08-10 | 待排期 | 总控/测试 | Admin、Firstleg 已分模块部署并持续真实 HTTP 验收;PDA S0500、batch 契约和真机验收未收口 |
@@ -43,8 +43,8 @@
| P3-T06-00 | T06 | 后台/服务端 | 拖车预约 | 服务商、车辆司机、时间窗、到离仓和异常;完成状态供门禁校验 | P0 | 联调中 | 80% | P3-T03-00 | Firstleg/Admin | 预约、附件、历史及服务中心链路已通过真实接口 | | P3-T06-00 | T06 | 后台/服务端 | 拖车预约 | 服务商、车辆司机、时间窗、到离仓和异常;完成状态供门禁校验 | P0 | 联调中 | 80% | P3-T03-00 | Firstleg/Admin | 预约、附件、历史及服务中心链路已通过真实接口 |
| P3-T07-00 | T07 | PDA/后台/服务端 | PDA 拣货与复核 | 按单柜次单作业员实现在线草稿、批量提交、异常、幂等和实时库存校验 | P0 | 已阻塞 | 45% | P3-T04-00 | Firstleg/PDA | 广播扫描已接入;真实 pick S0500 与原子 batch 契约仍待收口 | | P3-T07-00 | T07 | PDA/后台/服务端 | PDA 拣货与复核 | 按单柜次单作业员实现在线草稿、批量提交、异常、幂等和实时库存校验 | P0 | 已阻塞 | 45% | P3-T04-00 | Firstleg/PDA | 广播扫描已接入;真实 pick S0500 与原子 batch 契约仍待收口 |
| P3-T08-00 | T08 | PDA/后台/服务端 | 装柜及柜封证据 | 实现五类多图追加、角色上传、作废和无限期留存,客户不可见 | P0 | 联调中 | 80% | P3-T07-00 | Firstleg/Admin/PDA | 五类证据与安全边界已通过,真机拍照和终态待验收 | | P3-T08-00 | T08 | PDA/后台/服务端 | 装柜及柜封证据 | 实现五类多图追加、角色上传、作废和无限期留存,客户不可见 | P0 | 联调中 | 80% | P3-T07-00 | Firstleg/Admin/PDA | 五类证据与安全边界已通过,真机拍照和终态待验收 |
| P3-T09-00 | T09 | 客户端/后台/服务端 | 报关资料与回执 | 实现人工清单、补件、线下提交记录、人工放行回执上传 | P0 | 联调中 | 70% | P3-T02-00 | Firstleg/Admin | 人工协同接口已部署,最终子订单关联受 PDA 失败级联阻断 | | P3-T09-00 | T09 | 客户端/后台/服务端 | 报关资料与客户确认闭环 | 实现客户案例、报关行回执轮次、确认/打回重做、所有客户通过后整柜正式提交、查验/放行记录 | P0 | 联调中 | 70% | P3-T02-00 | Firstleg/Admin | 人工协同接口已部署,客户确认闭环仍待实现 |
| P3-T10-00 | T10 | 后台/服务端 | 装柜完成门禁 | 实现订舱/拖车/放行/PDA/证据硬门禁并推进 `LOADED` | P0 | 已阻塞 | 70% | P3-T07-00、P3-T08-00、P3-T09-00 | Firstleg | 门禁读取已通过;推进 LOADED 受 PDA 主链阻断 | | P3-T10-00 | T10 | 后台/服务端 | 装柜完成与送港/开船事实 | 实现物理 `LOADED`、送港/进港、甩柜/改配和实际开船分层事实,不以报关确认阻断送港 | P0 | 已阻塞 | 70% | P3-T07-00、P3-T08-00、P3-T09-00 | Firstleg | 门禁读取已通过;推进 LOADED 受 PDA 主链阻断 |
| P3-T11-00 | T11 | 客户端/服务端 | 客户端国内货柜履约协同 | 展示柜次、装柜进度、客户可见回执和船期;不返回照片与锁码 | P0 | 待开始 | 0% | P3-T05-00、P3-T09-00、P3-T10-00 | 待分配 | - | | P3-T11-00 | T11 | 客户端/服务端 | 客户端国内货柜履约协同 | 展示柜次、装柜进度、客户可见回执和船期;不返回照片与锁码 | P0 | 待开始 | 0% | P3-T05-00、P3-T09-00、P3-T10-00 | 待分配 | - |
| P3-T12-00 | T12 | 公共 | 联调测试与发布 | 维护定向/全量真实 HTTP、PDA 真机、安全和发布回归 | P0 | 联调中 | 70% | P3-T02-00~P3-T11-00 | 总控/测试 | 已进入分模块部署验收;不得用 mock、历史资源或 coverage gap 伪装通过 | | P3-T12-00 | T12 | 公共 | 联调测试与发布 | 维护定向/全量真实 HTTP、PDA 真机、安全和发布回归 | P0 | 联调中 | 70% | P3-T02-00~P3-T11-00 | 总控/测试 | 已进入分模块部署验收;不得用 mock、历史资源或 coverage gap 伪装通过 |
| P3-T01-PROTO-01 | T01 | 公共 | 原型盘点 | 盘点流程图、后台、企业客户端和 PDA 中与国内货柜履约相关的页面及交互 | P0 | 已完成 | 100% | - | 待分配 | 2026-07-28 已完成首次盘点,来源为 `docs/悦` | | P3-T01-PROTO-01 | T01 | 公共 | 原型盘点 | 盘点流程图、后台、企业客户端和 PDA 中与国内货柜履约相关的页面及交互 | P0 | 已完成 | 100% | - | 待分配 | 2026-07-28 已完成首次盘点,来源为 `docs/悦` |
@@ -97,12 +97,12 @@
| P3-M2 订单国内货柜履约编排 | 现有订单、柜次、排柜、订舱、港务和拖车可关联追溯 | 联调中 | 待排期 | | P3-M2 订单国内货柜履约编排 | 现有订单、柜次、排柜、订舱、港务和拖车可关联追溯 | 联调中 | 待排期 |
| P3-M3 仓内出仓 | PDA 拣货、复核、装柜和柜封证据闭环 | 已阻塞 | 待排期 | | P3-M3 仓内出仓 | PDA 拣货、复核、装柜和柜封证据闭环 | 已阻塞 | 待排期 |
| P3-M4 报关协同 | 客户资料、后台审核、提交代理、回执上传下载闭环 | 联调中 | 待排期 | | P3-M4 报关协同 | 客户资料、后台审核、提交代理、回执上传下载闭环 | 联调中 | 待排期 |
| P3-M5 装柜完成 | 订舱、拖车、放行回执、PDA 和证据门禁满足后进入 `LOADED`;后续错误线下处理 | 已阻塞 | 待排期 | | P3-M5 装柜完成及并行分支 | 真实柜号、PDA、数量守恒和五类证据门禁满足后进入 `LOADED`;随后并行推进报关客户确认闭环和送港/进港/甩柜,实际开船才进入海运 | 已阻塞 | 待排期 |
| P3-M6 国内货柜履约上线 | 联调、真机、安全、测试、验收和生产发布完成 | 进行中 | 待排期 | | P3-M6 国内货柜履约上线 | 联调、真机、安全、测试、验收和生产发布完成 | 进行中 | 待排期 |
## 七、未确认事项(需求确认进度) ## 七、未确认事项(需求确认进度)
当前 13 项主确认事项均已有产品最终结论;P3-Q4 已确认采用 uni-app、在线更新与 Android 广播扫描。完整结论统一维护在 [国内货柜履约需求确认表](国内货柜履约需求确认表.md)。 当前 13 项主确认事项均已有产品最终结论;P3-Q4 已确认采用 uni-app、在线更新与 Android 广播扫描。完整结论统一维护在 [国内货柜履约需求确认表](../国内货柜履约需求确认表.md)。
验收拆分已建立:PDA 进入任务、拣货幂等/版本冲突、五类证据真实上传、多图追加和锁码门禁进入自动化;真机在线、设备草稿批量提交、证据作废、设备与权限留存等仍保留 coverageGap,详见[国内货柜履约验收任务拆分与待确认清单](国内货柜履约验收任务拆分与待确认清单.md)。 验收拆分已建立:PDA 进入任务、拣货幂等/版本冲突、五类证据真实上传、多图追加和锁码门禁进入自动化;真机在线、设备草稿批量提交、证据作废、设备与权限留存等仍保留 coverageGap,详见[国内货柜履约验收任务拆分与待确认清单](国内货柜履约验收任务拆分与待确认清单.md)。
@@ -118,8 +118,8 @@
| P3-Q8 | 模块阻断 | 报关代理接收资料和返回回执的方式 | 已确认 | 线下提交、人工上传回执 | | P3-Q8 | 模块阻断 | 报关代理接收资料和返回回执的方式 | 已确认 | 线下提交、人工上传回执 |
| P3-Q9 | 开工阻断 | 港务信息的业务含义、字段和维护方 | 已确认 | 六家船公司查询、三日周期、三次上限、过期标识 | | P3-Q9 | 开工阻断 | 港务信息的业务含义、字段和维护方 | 已确认 | 六家船公司查询、三日周期、三次上限、过期标识 |
| P3-Q10 | 模块阻断 | 装柜完成后的错误处理和冲正方式 | 已确认 | 线下人工处理,不提供在线冲正 | | P3-Q10 | 模块阻断 | 装柜完成后的错误处理和冲正方式 | 已确认 | 线下人工处理,不提供在线冲正 |
| P3-Q11 | 开工阻断 | 九个动作的强制前置和并行关系 | 已确认 | 订舱/拖车/放行/PDA/证据为硬门禁;单柜次单人 | | P3-Q11 | 开工阻断 | 九个动作的强制前置和并行关系 | 已确认 | `LOADED` 后报关线和送港线并行;客户确认不阻断送港,进港不代表报关完成;单柜次单人 |
| P3-Q12 | 开工阻断 | 报关回执类型及海关放行是否为装柜完成硬门禁 | 已确认 | 有效放行回执为硬门禁,人工上传 | | P3-Q12 | 开工阻断 | 报关行回执、客户确认、正式申报和海关结果 | 已确认 | 回执必须发客户确认,打回则重做;所有客户通过后才整柜正式申报,查验/放行单独记录 |
| P3-Q13 | 开工阻断 | 国内货柜履约终点 | 已确认 | `LOADED`/装柜完成;`DELIVERED` 由海外仓回传,移出国内货柜履约验收 | | P3-Q13 | 开工阻断 | 国内货柜履约终点 | 已确认 | `LOADED`/装柜完成;`DELIVERED` 由海外仓回传,移出国内货柜履约验收 |
## 八、开工准入记录 ## 八、开工准入记录
@@ -128,7 +128,7 @@
| 准入编号 | 准入条件 | 当前状态 | 责任方 | 完成证据 | | 准入编号 | 准入条件 | 当前状态 | 责任方 | 完成证据 |
|---|---|---|---|---| |---|---|---|---|---|
| P3-GO-01 | P3-Q1~P3-Q13 均形成产品结论 | 已完成 | 产品、业务 | `国内货柜履约需求确认表.md` 已同步最终结论 | | P3-GO-01 | P3-Q1~P3-Q17 均形成产品结论 | 已完成 | 产品、业务 | `国内货柜履约需求确认表.md` 已同步最终结论 |
| P3-GO-02 | 确认结论已同步开发规划、进度表、页面清单和验收范围 | 已完成 | 产品、项目负责人 | README、进度表、页面清单和验收口径已按确认版同步 | | P3-GO-02 | 确认结论已同步开发规划、进度表、页面清单和验收范围 | 已完成 | 产品、项目负责人 | README、进度表、页面清单和验收口径已按确认版同步 |
| P3-GO-03 | 关键缺失原型已补齐并评审,包括订单装柜完成门禁、客户端国内货柜履约页面和 PDA 五类多图拍照 | 进行中 | 产品、设计、业务 | 页面清单中的关键页面达到已确认状态 | | P3-GO-03 | 关键缺失原型已补齐并评审,包括订单装柜完成门禁、客户端国内货柜履约页面和 PDA 五类多图拍照 | 进行中 | 产品、设计、业务 | 页面清单中的关键页面达到已确认状态 |
| P3-GO-04 | T02 公共契约完成,入库测量与计费输入、状态机、权限、数据模型、接口、错误码和审计口径稳定 | 进行中 | 前后端、架构/技术负责人 | 主体契约已部署;PDA 原子 batch 契约仍缺 | | P3-GO-04 | T02 公共契约完成,入库测量与计费输入、状态机、权限、数据模型、接口、错误码和审计口径稳定 | 进行中 | 前后端、架构/技术负责人 | 主体契约已部署;PDA 原子 batch 契约仍缺 |
@@ -152,3 +152,4 @@
3. 完成 PDA 真机广播扫码、在线草稿、五类证据拍照、多图追加和作废验收。 3. 完成 PDA 真机广播扫码、在线草稿、五类证据拍照、多图追加和作废验收。
4. 收口 T11 客户端国内货柜履约页面及客户可见性、安全边界。 4. 收口 T11 客户端国内货柜履约页面及客户可见性、安全边界。
5. 复跑国内货柜履约定向和默认全量真实 HTTP 验收,完成发布记录后再评估国内货柜履约完成状态。 5. 复跑国内货柜履约定向和默认全量真实 HTTP 验收,完成发布记录后再评估国内货柜履约完成状态。
@@ -6,14 +6,15 @@
- 已确认规则可进入契约、数据、接口、页面和测试拆分,不需要等待整期所有模块完成。 - 已确认规则可进入契约、数据、接口、页面和测试拆分,不需要等待整期所有模块完成。
- 订单继续承载国内货柜履约主状态,不新建独立出仓单;支持父订单、子订单与柜次关系,以及一单多柜和多订单拼柜。 - 订单继续承载国内货柜履约主状态,不新建独立出仓单;支持父订单、子订单与柜次关系,以及一单多柜和多订单拼柜。
- 智能排柜、订舱与船期、拖车预约、PDA 在线拣货、五类装柜证据、人工报关回执和 `LOADED` 服务端门禁按需求确认表执行。 - 智能排柜、订舱与船期、拖车预约、PDA 在线拣货、五类装柜证据、`LOADED` 后客户报关确认闭环、送港/甩柜和实际开船按本轮确认流程执行。
- 国内货柜履约的国内终点为 `LOADED`;`DELIVERED` 只由海外仓可信回传推进。 - 国内货柜履约的国内终点为 `LOADED`;`DELIVERED` 只由海外仓可信回传推进。
## 跨端硬边界 ## 跨端硬边界
- `LOADED` 前必须由服务端校验订舱完成、拖车完成、有效报关放行回执、PDA 拣货完成和五类有效证据完整;国内 Admin/PDA 不提供在线冲正或手工推进 `DELIVERED`。 - `LOADED` 前必须由服务端校验真实柜号、PDA 拣货与数量守恒、五类有效证据和未解决异常。`LOADED` 后报关线和送港线分别校验:报关线按客户资料、报关行回执、客户确认/打回、所有客户通过、整柜正式申报和海关结果推进;送港线按订舱/拖车、离仓、进港、甩柜和实际开船推进。客户确认不阻断送港,进港不代表报关完成。国内 Admin/PDA 不提供在线冲正或手工推进 `DELIVERED`。
- PDA 正式作业仅在线;单柜次只允许一名作业员,不支持多人并行、任务接管或换班释放。进入任务即由服务端标记拣货中,扫描草稿按作业员、任务和柜次隔离,提交时批量写入。 - PDA 正式作业仅在线;单柜次只允许一名作业员,不支持多人并行、任务接管或换班释放。进入任务即由服务端标记拣货中,扫描草稿按作业员、任务和柜次隔离,提交时批量写入。
- 每类证据至少一张有效照片,允许同类型追加;错误照片只能作废并保留审计。客户不可见照片与锁码。 - 每类证据至少一张有效照片,允许同类型追加;错误照片只能作废并保留审计。客户不可见照片与锁码。
- 报关在 `LOADED` 后正式启动:每个客户经历资料上传、报关行回执、客户确认或打回重做,所有客户通过后才提交整柜资料给报关行正式申报;送港线独立记录拖车、进港、甩柜和实际开船。费用确认不阻断排柜/装柜,装柜完成后对已装范围的当前有效已发布费用版本记录系统默认确认,来源和客户主动确认必须分开审计。
- 前端页面、菜单和路由只能在对应服务端契约、权限和数据模型稳定后发布;原型中的完整 WMS、海外仓及未确认能力不属于国内货柜履约默认范围。 - 前端页面、菜单和路由只能在对应服务端契约、权限和数据模型稳定后发布;原型中的完整 WMS、海外仓及未确认能力不属于国内货柜履约默认范围。
## 局部阻断项 ## 局部阻断项
@@ -27,3 +28,4 @@
1. 先读 `README.md`、`国内货柜履约需求确认表.md` 和本文件,确认任务属于已确认范围。 1. 先读 `README.md`、`国内货柜履约需求确认表.md` 和本文件,确认任务属于已确认范围。
2. 再进入目标应用或服务的 `AGENTS.md`,按本地模块入口实现。 2. 再进入目标应用或服务的 `AGENTS.md`,按本地模块入口实现。
3. 发现新的产品决策或门禁变化时,先更新确认表与本文,再更新受影响模块指引;不要将短期进度、联调故障或环境地址写回模块规则。 3. 发现新的产品决策或门禁变化时,先更新确认表与本文,再更新受影响模块指引;不要将短期进度、联调故障或环境地址写回模块规则。
@@ -1,5 +1,7 @@
# 国内货柜履约装柜闭环产品确认表 # 国内货柜履约装柜闭环产品确认表
> **历史版本声明(2026-09-24)**:本文仅保留 2026-08-08 的原始讨论记录,其中“装柜完成即结束”和报关/离仓关系等内容已被当前流程替代。当前规则以 [头程到尾程流程节点梳理(重构版)](../../头程到尾程流程节点梳理.md)、[报关资料与船期价格接入梳理](../报关资料与船期价格接入梳理.md) 和最新需求确认表为准:`LOADED` 只表示物理装柜完成;正式报关在装柜完成后按最终实装清单执行,放行回执参与 `DEPARTED_WAREHOUSE` 离仓门禁。
> 确认方式:产品只需在“产品确认”一列填写“同意”,或写明修改后的规则。 > 确认方式:产品只需在“产品确认”一列填写“同意”,或写明修改后的规则。
> 会议目标:本表确认后直接进入开发,不再补完整高保真原型。 > 会议目标:本表确认后直接进入开发,不再补完整高保真原型。
@@ -64,3 +66,4 @@
| 本次明确不做的内容 | | | 本次明确不做的内容 | |
| 产品确认人 | | | 产品确认人 | |
| 确认日期 | | | 确认日期 | |
@@ -1,5 +1,7 @@
# 国内货柜履约装柜闭环开发前确认单 # 国内货柜履约装柜闭环开发前确认单
> **历史版本声明(2026-09-24)**:本文是旧版“以 `LOADED` 作为国内履约终点”的开发前确认材料,旧规则已被本轮新流程替代。当前按三大业务块梳理;`LOADED` 只表示物理装柜完成,正式报关在装柜完成后按最终实装清单执行,放行回执、订舱、拖车和异常门禁用于推进 `DEPARTED_WAREHOUSE`。费用确认不阻断装柜,当前有效已发布费用版本在 `LOADED` 时按已装载范围默认确认。开发以 [头程到尾程流程节点梳理(重构版)](../../头程到尾程流程节点梳理.md)、[报关资料与船期价格接入梳理](../报关资料与船期价格接入梳理.md) 和当前确认记录为准。
> 整理日期:2026-08-08 > 整理日期:2026-08-08
> 用途:产品、业务、仓库、研发在直接开发前确认最小闭环细节 > 用途:产品、业务、仓库、研发在直接开发前确认最小闭环细节
> 当前建议:不补完整高保真原型,确认本清单后直接开发 > 当前建议:不补完整高保真原型,确认本清单后直接开发
@@ -144,3 +146,4 @@ DELIVERED / 海外仓已收货
2. 更新 `国内货柜履约需求确认表.md` 中对应的 P3-Q2/P3-Q4/P3-Q5/P3-Q6/P3-Q10/P3-Q11/P3-Q12。 2. 更新 `国内货柜履约需求确认表.md` 中对应的 P3-Q2/P3-Q4/P3-Q5/P3-Q6/P3-Q10/P3-Q11/P3-Q12。
3. 明确是否允许按“服务端门禁 -> PDA -> Admin -> 联调验收”的顺序直接开发。 3. 明确是否允许按“服务端门禁 -> PDA -> Admin -> 联调验收”的顺序直接开发。
4. 将本清单作为接口、页面和测试验收的共同依据。 4. 将本清单作为接口、页面和测试验收的共同依据。
@@ -1,5 +1,7 @@
# 虫虫出海国内货柜履约闭环审计报告 # 虫虫出海国内货柜履约闭环审计报告
> **历史记录声明(2026-09-24)**:本文记录的是 2026-08-08 的旧口径和旧审计结论,不再作为当前流程或开发门禁依据。当前统一采用三大业务块和“装柜完成后正式报关”的新流程:`LOADED` 只确认物理装柜完成;装柜完成后按最终实装清单正式报送,取得有效回执/放行结果后,结合订舱、拖车和异常门禁推进 `DEPARTED_WAREHOUSE`。费用确认不阻断装柜,装柜完成时对当前有效已发布版本按已装载范围默认确认。当前规则以 [头程到尾程流程节点梳理(重构版)](../../头程到尾程流程节点梳理.md)、[报关资料与船期价格接入梳理](../报关资料与船期价格接入梳理.md) 和本轮确认记录为准。
> 审计日期:2026-08-08 > 审计日期:2026-08-08
> 审计范围:入库测量与计费终点→智能排柜→订舱→拖车→PDA 拣货→装柜/柜封证据→`LOADED`/装柜完成 > 审计范围:入库测量与计费终点→智能排柜→订舱→拖车→PDA 拣货→装柜/柜封证据→`LOADED`/装柜完成
> 审计对象:Admin、Client、PDA、`baiyue-firstleg` 后端、OpenAPI/SQL、自动化测试与现有测试环境报告 > 审计对象:Admin、Client、PDA、`baiyue-firstleg` 后端、OpenAPI/SQL、自动化测试与现有测试环境报告
@@ -239,3 +241,4 @@ PDA 已有调用拣货/证据/装柜接口的适配代码,但当前仍存在
> **国内货柜履约已确认复用现有订单列表承载全部主状态,不新建出仓单,国内终点为 `LOADED`/装柜完成;已完成排柜/预装/PDA 拣货/装柜清单子链路,订舱和拖车 API 可用。但订单国内货柜履约统一编排、五张装柜照片与锁码文本硬门禁、报关协同、冲正、Client 协同和 PDA 真机仍未闭环,且国内手工推进 `DELIVERED` 的现有能力必须整改,当前不具备整期验收条件。** > **国内货柜履约已确认复用现有订单列表承载全部主状态,不新建出仓单,国内终点为 `LOADED`/装柜完成;已完成排柜/预装/PDA 拣货/装柜清单子链路,订舱和拖车 API 可用。但订单国内货柜履约统一编排、五张装柜照片与锁码文本硬门禁、报关协同、冲正、Client 协同和 PDA 真机仍未闭环,且国内手工推进 `DELIVERED` 的现有能力必须整改,当前不具备整期验收条件。**
因此,现阶段不应标记“国内货柜履约完成”,应标记为“**子能力已实现,闭环整改中**”。 因此,现阶段不应标记“国内货柜履约完成”,应标记为“**子能力已实现,闭环整改中**”。
@@ -12,9 +12,9 @@
| 五类装柜证据 | 空仓、半仓、满仓、锁仓、带锁码照均上传真实文件并按客户/柜次绑定 | `phase3-loading.mjs` | | 五类装柜证据 | 空仓、半仓、满仓、锁仓、带锁码照均上传真实文件并按客户/柜次绑定 | `phase3-loading.mjs` |
| 同类型多图 | 同一证据类型追加第二张真实图片,原记录与新增记录同时保持有效 | `phase3-loading.mjs` | | 同类型多图 | 同一证据类型追加第二张真实图片,原记录与新增记录同时保持有效 | `phase3-loading.mjs` |
| 锁码门禁 | 缺少锁码照片或锁码文本为空时,完成装柜请求被拒绝 | `phase3-loading.mjs` | | 锁码门禁 | 缺少锁码照片或锁码文本为空时,完成装柜请求被拒绝 | `phase3-loading.mjs` |
| 统一装柜门禁 | 订舱未完成、拖车未完成、报关无有效放行回执、PDA 未完成或五类证据不完整时,真实 `LOADED` 请求均被拒绝 | `service-center-flow.mjs` / `phase3-loading.mjs` | | 统一装柜门禁 | 真实柜号缺失、PDA 未完成、数量不守恒或五类证据不完整时,真实 `LOADED` 请求被拒绝;`LOADED` 后分别验收客户报关回执确认闭环和送港/进港/甩柜事实,任何一条线都不反向阻断物理装柜 | `service-center-flow.mjs` / `phase3-loading.mjs` |
| 订单/柜次聚合 | 一单多柜、一个柜多订单、父子订单数量分摊及未装数量自动生成子订单可追溯 | `phase3-order-aggregate.mjs`(待补) | | 订单/柜次聚合 | 一单多柜、一个柜多订单、父子订单数量分摊及未装数量自动生成子订单可追溯 | `phase3-order-aggregate.mjs`(待补) |
| 出仓后船节点查询 | 已重新归入海外仓业务,不属于国内货柜履约验收 | 海外仓业务沿用现有 `CarrierScheduleQuery` 设计验收入口,不再补 `phase3-vessel-tracking.mjs` | | 实际开船后船节点查询 | 只有承运船舶真实开航后才进入海运节点;送港、进港和甩柜属于国内货柜履约并行线 | 海外仓业务沿用现有 `CarrierScheduleQuery` 设计验收入口,不再用预计 ETD 或 `DEPARTED_WAREHOUSE` 提前推进海运 |
| 仓库角色 | 操作员、拣货员、理货员初始化、最小权限和跨客户隔离 | `phase3-role-contract.mjs`(待补) | | 仓库角色 | 操作员、拣货员、理货员初始化、最小权限和跨客户隔离 | `phase3-role-contract.mjs`(待补) |
| 伪造与交叉归属 | 不存在 `fileId`、其他证据类型的 `fileId` 不能绑定 | `phase3-loading.mjs` | | 伪造与交叉归属 | 不存在 `fileId`、其他证据类型的 `fileId` 不能绑定 | `phase3-loading.mjs` |
@@ -33,3 +33,4 @@
4. `P3-ACCEPT-PDA-RELEASE`:按既定 uni-app 在线更新安排完成发布与真机验收。 4. `P3-ACCEPT-PDA-RELEASE`:按既定 uni-app 在线更新安排完成发布与真机验收。
每个任务完成后,必须把真实请求、响应状态、业务码、`requestId/traceId` 写入报告,并删除对应 coverageGap;不得以 mock 或数据库直写替代接口验收。 每个任务完成后,必须把真实请求、响应状态、业务码、`requestId/traceId` 写入报告,并删除对应 coverageGap;不得以 mock 或数据库直写替代接口验收。
@@ -42,3 +42,4 @@
- `phase3-container-loading` 对 ACTIVE 货柜、预装清单和完成装柜清单执行字段断言。 - `phase3-container-loading` 对 ACTIVE 货柜、预装清单和完成装柜清单执行字段断言。
- `ocean-bookings`、`phase3-port-schedules`、`truck-appointments`、`phase3-customs`、`phase3-outbound-dispatch` 在既有本轮资源响应上执行字段断言,不增加历史查询或伪造回退。 - `ocean-bookings`、`phase3-port-schedules`、`truck-appointments`、`phase3-customs`、`phase3-outbound-dispatch` 在既有本轮资源响应上执行字段断言,不增加历史查询或伪造回退。
- 默认 Admin 全量入口已包含上述生产模块;真实 HTTP 仅在测试环境重新部署且当前对话明确授权后执行。 - 默认 Admin 全量入口已包含上述生产模块;真实 HTTP 仅在测试环境重新部署且当前对话明确授权后执行。
@@ -219,3 +219,4 @@
| 全量编排 | 默认入口先运行 `phase3-container-loading` 完成“模拟柜新增 -> 同仓同渠道排货 -> 首次 link -> PDA”,再由证据、finalize、出仓模块沿本轮 marker 的稳定 ID 继续;禁止历史数据和 mock 回退 | Node 入口合同已锁定,待默认全量 HTTP 验证 | | 全量编排 | 默认入口先运行 `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、需求关联且不在订舱阶段自动建柜。 离线合同:`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、需求关联且不在订舱阶段自动建柜。
@@ -0,0 +1,207 @@
# 报关资料与船期价格接入梳理
> **当前用途:报关与船期价格专题参考。** 报关流程已经确认,第一批代码和页面已经接入测试环境;开发交接看[报关代码开发交接清单](../头程到尾程/报关代码开发交接清单.md)。主流程和节点关系以[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准;本文保留资料字段、回执轮次、价格口径和接口查找信息。
>
> 文中“目标、实施顺序、进入条件、待确认事项”等段落属于原评审记录。开发已经完成后,不再据此重新拆开发任务;若与当前确认不一致,以总览和最新业务确认修正对应专题段落。
本文是企业客户端“报关资料”“船期价格”入口的专题评审记录。当前使用时只取已确认的流程、资料和价格口径;“建议”和“待确认”保留为历史评审痕迹,不再自动生成开发任务或验收门禁。
**当前基线**:以最新用户确认和[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准。旧版需求表、README、开发规划和本文件中的历史建议若发生冲突,先在当前入口记录收尾变更,再决定是否需要修改专题细节。
**当前实现快照(2026-09-29)**:两份文件链路已经落到平台、客户和 Firstleg 报关接口,客户端“报关资料”和“船期价格”也已经作为独立模块接入导航和路由。客户资料、报关行回执、客户整份回执确认/打回、平台发送报关行执行、真实报关完税文件分别保存并受版本门禁控制。回执发送给报关行后不可再替换;只有包含退税货物的柜才允许走发送执行接口;全买单柜仍走平台直接完成。`brokerSubmittedAt` 只表示发送执行时间,不表示报关完成。PDA 只负责产生 `LOADED` 前置事实,报关验收不创建或操作 PDA 任务;船期、甩柜和改配只修改原柜运输信息,不重置报关资料和确认结果。
## 客户报关资料菜单待办红标
- 侧栏“报关资料”在文字右侧显示红底白字数量,白色描边;无待办时隐藏,超过99显示“99+”。承载依据为客户提供的菜单截图,菜单入口和资料弹框保持原承载方式。
- 数量按当前客户需要处理的**柜次去重**:最新实际装柜的退税货物尚缺本客户有效资料,或者报关中本客户冻结资料的当前回执待确认(PENDING)。同柜多个入仓码、多份回执合计1个红标待办;已确认、已打回等待平台重做、已完成及同柜其他客户的待办不计入。
- `GET /api/merchant/v1/customs/pending-summary` 由Firstleg只读聚合返回`pendingCount`,客户范围来自认证上下文,读取权限`merchant:order:view`;复用现有网关customs路由,不在侧栏逐票加载报关详情或创建报关记录。计数与订单列表“上传资料”的订单数不是同一单位,不能相互替代。
- 首次进入工作台、页面可见时每60秒、窗口重新获得焦点、报关资料刷新及资料操作后重新查询。刷新期间保留已确认数值;失败显示红色“!”并说明数量加载失败,不把失败显示成零。退出或失去菜单权限立即清空,旧会话响应不能写入新会话。
| 页面/操作 | 原型依据与承载 | 实现 |
|---|---|---|
| 报关资料菜单红标 | 用户提供菜单截图,文字右侧圆形红色数量 | 真实待办数、白描边、同柜去重;不添加新弹框 |
| 资料处理后更新 | 原有上传、覆盖范围、删除及回执确认/打回操作 | 查询最新待办数,不在浏览器自行减1 |
## 当前差异与下一步
当前主流程和代码的关系已经收敛:F01-F24(国内头程、报关、待发区、送港、进港、甩柜和实际开航)有最新真实 HTTP 证据;F25-F40(目的港、海外入库、库存、出库、派送和最终回写)已有综合真实 HTTP 证据和页面实现。客户端两个独立模块、订单快捷入口、平台整柜报关工作台和船期价格查询均已接入,不需要再按“新增页面”拆任务。
2026-09-29 的最新综合 F01-F40 验收报告为 `baiyue-firstleg/reports/fba-full-current-20260929.json`。报告前段业务链大量通过,但尾程和海外 PDA 产生了环境型阻断:`test-api-overseas.buggoglobal.com` 当时 DNS 不可解析,后续请求均为 `fetch failed`,因此这份报告不能作为全流程全绿结论,也不能据此判断报关或船期代码失败。此前报关专项 `customs-current-20260928.json`(543/543)和运输专项 `transport-current-20260929.json`(1036/1036)仍是当前可复用的绿色证据。
当前状态分为三类任务:
1. **规则已简化并确认**:不维护资料类型清单,也不区分逐项责任人;客户或平台只要在资料包上传文件即可。查验、扣货、补资料均由平台人工标记异常,选择预设理由;选择“其他”时填写备注即可,不要求接入短信或自动海关系统。
2. **环境/外部验收**:恢复海外测试域名解析后重新跑 F25-F40;COSCO 官方接口凭据、COSCO 动态页面和 ZIM hCaptcha 仍是外部非阻断项;Android/HBuilderX 真机扫码、弱网和在线草稿仍需现场设备验收。
3. **后续增强**:报关行接收回执/回执轮次和下载凭证仍可增强,但不影响当前两份文件闭环、客户确认、正式申报和报关完成后进入待发区。
4. **费用默认确认**:业务规则已经确认,但代码仍主要完成费用发布/客户确认;`LOADED` 时按已装范围写入 `SYSTEM_AUTO_AT_LOADED`、费用版本、柜次/入仓码和幂等审计的落地实现,仍需单独补齐,不能把 `SENT` 直接当成默认确认。
你当前不需要先操作系统或确认代码。资料上传和异常人工处理规则已经足够继续开发;其余技术修复和重新验收由开发侧继续处理。
## 先锁定的范围
国内货柜履约的物理装柜节点为 `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. 原型文档仍有“待原型/部分参考”的历史表述,但当前页面已按现行契约接入;页面范围以客户端路由、平台报关工作台和当前 OpenAPI 为准,不再把原型中的待建入口当作开发缺口。
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)。
@@ -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:<forecastKey>`,服务端只消费该预报批次;多条有效预报且事件没有明确批次键时,实收保持 `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. 页面不提供货量异常改配、手工绑定实收、订舱关联/解除等操作;这些操作留在现有业务流程。
因此,本轮验收重点从“自动归班正确”改为:船期维护正确、展示口径透明、已收/预计/已订柜/建议柜数不重复、取消或截止只影响展示标签、不会改变原收货和智能排柜数据。后续如果需要让管理人员在页面上确认“合并到哪一班”,再单独增加人工确认动作和正式归属模型。
+32
View File
@@ -0,0 +1,32 @@
# 头程到尾程当前维护入口
这里集中列出 F01-F40 全流程变更需要查找和修改的文档;实现与验收范围以[全流程实现对照](头程至实际开船节点冻结矩阵与缺口清单.md)为准。日常只从本目录进入,历史开发材料统一放在[文档归档](../归档/README.md)。
## 当前流程文档
| 用途 | 文档 | 修改什么 |
|---|---|---|
| 总览与节点 | [头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md) | 三大业务块、客户进度、后台节点、真实明细和 F01-F40 关系 |
| 分段流程 | [头程到尾程分阶段流程](../头程到尾程分阶段流程/README.md) | 六个阶段的字段、页面操作、权限、状态和异常 |
| 货柜入口 | [国内货柜履约 README](../国内货柜履约/README.md) | 分柜、装柜、报关协同、送港和进港的货柜范围 |
| 报关与船期专题 | [报关资料与船期价格接入梳理](../国内货柜履约/报关资料与船期价格接入梳理.md) | 客户资料、报关行回执、客户确认/打回、正式申报、海关结果和船期价格 |
| 报关开发交接 | [报关代码开发交接清单](报关代码开发交接清单.md) | 报关代码完成条件、已验收范围和后续增强项 |
| 头程与报关交互矩阵 | [头程节点与报关清关交互矩阵](头程节点与报关清关交互矩阵.md) | F01-F24 各节点的客户、平台、PDA、报关行和船期交互 |
| 全流程实现对照 | [全流程节点矩阵与缺口清单](头程至实际开船节点冻结矩阵与缺口清单.md) | F01-F40 节点、现行规则、实现差异和验证边界;保留原文件路径 |
| 正式申报与海关结果 | [正式申报与海关结果接入设计](正式申报与海关结果接入设计.md) | F22.7 正式申报批次、报关单号、F22.8 查验/补资料/放行/扣货/其他结果及三端边界 |
| 甩柜改配接入设计 | [甩柜改配接入设计](甩柜改配接入设计.md) | F23.3 原柜人工修改船信息并保留修改历史 |
## 变更查找
- **改客户看到的主节点或三大块关系**:先改总览,再检查对应阶段文档。
- **改头程下单**:查阶段一、阶段二;费用确认仍是并行事项,不阻断排柜和装柜。
- **改海运(货柜)**:查阶段三、阶段四和报关专题;报关完成后进入待发区,甩柜只影响船期,实际开船后才进入海运节点。
- **安排报关开发**:只看[报关代码开发交接清单](报关代码开发交接清单.md),流程规则回看报关专题,不再从归档的开发规划开始。
- **改尾程入库和派送**:查阶段五、阶段六。
- **改页面范围或已确认需求**:查[页面与原型清单](../国内货柜履约/国内货柜履约页面与原型清单.md)和[需求确认表](../国内货柜履约/国内货柜履约需求确认表.md)。
## 归档位置
- [头程到尾程历史文档](../归档/头程到尾程/README.md):全流程手册、旧现状全景、AI 上下文、易用性方案。
- [国内货柜履约历史记录](../国内货柜履约/归档/README.md):开发规划、进度、门禁、验收、审计和旧确认材料。
- 跨区域认证、权限、统一订单状态、船节点、部署和数据库等正式契约继续留在原业务目录,不归入流程历史归档。
@@ -0,0 +1,248 @@
# 全流程节点矩阵与缺口清单
本文按当前确认结果冻结 F01-F40 全流程范围:从头程下单开始,完成国内履约、报关协同、送港运输、实际开航、海外入库、出库和最终回写。F01-F24 是国内头程至实际开航的前段,F25-F40 是海运目的港及尾程履约。流程基线同时采用《报关代码开发交接清单》和《头程到尾程流程节点梳理》;原型只用于页面字段和承载方式参考。
## 一、阶段边界
```text
头程下单
F01-F13:下单、审核、到仓、测量、计费、费用确认、国内扣货/解除、组托、待分柜
国内货柜履约
F14-F21:分柜、订舱、拖车、拣货、装柜、LOADED
报关完成后进入待发区
F22:报关协同
F23:待发区、送港、进港、甩柜、改配
海运起点
F24:承运船舶实际开航
目的港与海外入库
F25-F30:目的港处理、尾程订单、入仓计划、接柜、收货、库存入账
海外库存与出库
F31-F37:库内操作、暂扣、库内服务、排车、生成出库/派送单、拣货发车、出库
派送与完成
F38-F40:签收、异常退回、回访和完成回写
```
国内前段 F01-F24 的终点是实际开航,全流程继续至 F40;其中 F37 为海外出库。`LOADED` 只表示物理装柜完成;报关完成是进入待发区的前置条件,待发区和船期节点分别保存,不能把其中一条线的结果写成另一条线的结果。
### 实现与验证口径
“已有实现”不等于最新版本已完成验收。下表的既有 HTTP 证据只证明对应报告范围与版本;历史通过不能替代当前完整链路、页面或 PDA 现场验证。报关和运输专项的通过也不能外推为 F01-F40 全部通过。后续增强项不作为首期主流程缺失处理。
当前部署版本、已验证场景和未关闭项统一查阅[测试环境单机部署与配置契约](../测试环境单机部署与配置契约.md)文首的最新验收状态。本文以下带日期的复验记录及矩阵内历史状态保留作为当时证据,不替代该主契约的最新结论。
### 2026-09-30 当前复验结论
**F01-F40 尚未完成逐节点全量验收,不能宣布全部完工或出库以后没有问题。** 以下旧报告保留为对应版本证据,不代表本轮完整验收结论。
- 装柜完成后订单拣货汇总仍显示进行中的缺陷已修复。Firstleg 提交 `e5832d5c` 经测试环境 Jenkins #459 部署成功;服务测试 1,477 项,0 失败、0 错误、9 跳过。本轮实际 HTTP 已在 8 组装柜场景核对订单列表和详情的拣货汇总均为 `COMPLETED`。
- 本轮已通过实际页面打开普通 FBA 入仓码 `NYEXX2609290171`,核对列表和详情显示已完成;这是买单样本,不能替代同一票退税报关至签收完成的证据。页面截图为后端仓库 `reports/fba-completed-order-page-20260930.jpg`。
- 当前 Admin 全量 HTTP 复验已于 2026-09-30 11:23(上海时间)结束:11,642 项检查,11,638 通过、4 失败,148 次模块执行、120 个独立模块、7,427 次请求、0 跳过模块,整体未通过。其中 3 条失败来自“真实投递重试与同事件幂等证据”覆盖阻断;重复读取不等于同一事件重复消费,不能据此认定业务重试实现失效。另 1 条为海外托盘汇总接口返回 `A0404`,闲置、占用和报废数量未取得,须定位修复后复验。
- 海外托盘汇总的 `A0404` 已定位为脚本使用旧路径。已改为现行 `/api/platform/v1/overseas-warehouse-resources/pallets/summary`,相关 9 项离线检查通过;11:28 实际 HTTP 返回成功,总数 3,101 = 闲置 1,915 + 占用 1,010 + 报废 176。证据为 `reports/overseas-pallet-summary-current-20260930.json`。这是定向修复复验,不改写上一轮全量失败结果,也不代表剩余覆盖阻断已解除。
- 六阶段 77 项明确完成条件已作静态映射,其中 29 项只有部分或间接断言。另有 6 类待补证据:同柜多退税客户确认隔离;正式申报和各类人工海关异常;事件故障后重试与幂等;同一派送退回异常的收货、处理及库存恢复;出库前后库存和流水只扣一次;有效分片未全部签收不得提前完成及客户最终状态/签收文件访问。这些是当前验收覆盖缺口,不自动等于功能缺失。
- 正式申报批次忽略其他未处理异常而提前关闭的问题已修复,提交 `c7f88030` 经 Firstleg Jenkins #460 部署。之后发现平台公共订舱的船期任务触发器将空客户与平台范围 0 错误比较,以及报关完成后的自动出仓事务不能保证独立提交/回滚;提交 `125ca34b` 已修复,测试环境对应触发器已更新,Firstleg #461 部署成功、容器健康,1,485 项服务测试,0 失败、0 错误、9 跳过。61 项定向测试包含真实事务回滚与重试。
- 报关 r4 于 12:45(上海时间)结束为 702 项检查、701 通过、1 失败;唯一失败是平台范围船期任务详情读取被正客户范围校验错误拦截。该问题已由 `eae630e6` 修复、Firstleg #462 部署,1,493 项服务测试,0 失败、0 错误、9 跳过,容器健康;原任务详情、历史、唯一出仓船节点/系统历史和访问隔离 6 项真实检查通过。新的完整报关 r5 于 13:10 结束,702 项全部通过、9 个模块、452 次请求、0 跳过模块。范围包含同柜两位退税客户和买单客户、资料/确认隔离、打回替换、正式申报、四类人工异常及全部处理门禁、全部完成文件齐全、客户下载隔离、自动出仓及唯一船期任务/节点/历史。保留 r1-r4 的失败报告,不改写为通过。
- 客户签收文件接口和页面已部署:后端 `4a14001a` 经 Lastleg #184,客户端功能 `6abb8b7` 随 `6564d412` 经 Client #361。新增“入库订单、派送订单”菜单 `706e3e87` 经 Client #362 部署成功,34 项定向检查通过,实际页面已核对菜单、详情面包屑、签收文件和下载按钮。新尾程 r1 的客户文件 HTTP 检查通过,包含下载字节一致及其他客户拒绝访问;浏览器实际下载等待仍超时,不能记作页面下载通过,也不能用历史页面样本替代本轮同票全流程。
- 原排车单 `DS-WH-20260930-262785`、原退回异常 `EX-WH-20260930-960514` 的库存来源问题已由 `d320e78b` 修复,经 Lastleg #186 部署且容器健康。原异常使用原托盘、原证据成功完成,恢复 1 箱、只新增 1 条 `RETURN_STOCK_IN`,派送变为 `RETURNED`。首轮续验 r3 为 29 项检查、27 通过、2 失败:实际完成及重放成功,但脚本错误地用余额 DTO 未提供的入仓码字段过滤,漏掉位置。原异常后续对账及原完成请求重放 19 项全部通过,独立核平全部库存桶、目标位置/原票身份及流水,并验证重放零漂移。r2/r3 原失败报告保留。
- 新完整尾程 r1 于 13:21(上海时间)结束:5,714 项检查,5,706 通过、8 失败,99 次模块执行、75 个独立模块、3,484 次请求、0 跳过模块,整体未通过。其中原异常完整退回/库存恢复和客户签收文件 HTTP 场景已通过;6 条失败来自船期脚本把平台客户范围 0 当作非法 ID,已由 `7f3c0690` 修正,13 项本地检查通过。另 2 条分别为按 SKU 汇总余额与单条真实余额混用导致出库库存取证不完整,以及误把 PDA 任务完成状态当作排车待发状态。脚本已改为从正式 PDA 任务冻结真实余额/位置,独立核对位置、真实余额、客户仓汇总及流水,并分别核对任务与排车状态;23 项本地合同通过。
- 新尾程 r2 于 13:51(上海时间)结束:5,822 项检查,5,821 通过、1 失败,99 次模块执行、75 个独立模块、3,538 次请求、0 跳过模块。船期范围与发车门禁已通过;唯一失败仍为“PDA扫码及重放实际库存只扣本出库数量一次”,证据显示取证范围 `before=6, after=3, expected=9, SHIPRows=5`,原因正在核对,不能据此宣布出库数量已核平,也不能直接判定为业务重复扣库。该轮退回恢复、重放、客户文件下载及隔离通过;不改写 r1 失败报告。真机与外部第三方覆盖缺口另列,不能计作已验收。
- 新尾程 r3 于 14:29(上海时间)结束:5,830 项检查,5,828 通过、2 失败,99 次模块执行、75 个独立模块、3,536 次请求、0 跳过模块。正式 PDA 冻结的全部来源位置、原始余额、汇总余额和 SHIP 流水扣减及重放检查通过;r2 的代表入仓码过滤漏取同托其他来源问题已在脚本纠正,保留原失败报告。两项失败均为平台/客户统一订单期望 `COMPLETED`;实际只读诊断确认该根订单原有 4 箱,仅装运签收 1 箱,另有 3 箱真实余量子单未履约。根保持 `PROCESSING`,自身 `OVERSEAS_DELIVERED` 事实只有一次,统一展示 `DELIVERED` 符合未全部完成的门禁;需纠正旧样本预期,并另验两片全部实际签收。证据:`reports/fulfillment-stock-receipt-current-20260930-r3.json`、`reports/root-completion-r3-diagnostic-20260930.json`。
- 真实 Firstleg → Lastleg 装柜完成事件故障演练已通过:同一事件 12 次真实 ACK 丢失进入 DEAD,受保护接口重试原事件后得到 DUPLICATE 并最终 PUBLISHED,42 项检查全部通过,业务单据/消费事实零新增,生产服务原配置和健康状态已恢复、故障代理已停止。证据:`reports/event-ack-fault-current-20260930.json`。这不外推为反向卸柜/签收事件已取得同事件幂等证据。
- F40 修复已实现根自身签收事实与全部有效子单完成门禁、最后余量取消后的聚合、事务内历史/事件及 Firstleg 摘要可靠同步;92 项本地测试全部通过,含真实 SQL、事务回滚和并发,API 路由门禁 5 项通过。`041a27c3` 已经 Order #173、Firstleg #463 部署,容器健康;服务测试分别为 317 项零失败/零跳过和 1,500 项零失败/9 跳过。真实两箱、两柜根/余量子单的根先签和子先签专项已实现、本地合同通过,尚待实际 HTTP 和完成 Outbox 唯一发布验收。六阶段 77 项完成条件复核仍有 19 项证据不足,客户页面实际下载也未通过;这些不能按总断言数量折算完成率。
- 后续补验发现人工完成接口仍能绕过余量完成门禁,以及真实余量子单再次装柜时托盘标签数量为 0。两项已分别由 `71202bce`、`1a7e4800` 修复,统一提交 `1a7e4800` 经 Order #174、Firstleg #464 部署且健康;服务测试分别为 318 项零失败/零跳过、1,517 项零失败/9 跳过。原失败余量子柜重新准备标签及全部/指定仓 PDF 打印均通过;旧人工完成入口返回 `A0404`,原未完成根单的状态、版本、历史及完成事件零变化,8 项真实检查全部通过。证据:`reports/node-closure-original-regression-20260930-r1.json`。两片全部签收和合法取消末票余量仍待实际验收。
- 尾程补充只读取证已核对 123 项事实、11 项负向自检:8 个来源各唯一关联尾程/入仓单;标准 6 票在途共 12 箱,全部 8 票的 13 条入库流水及 13 条收货记录共 20 箱且完整键匹配;每票各有一次 `INBOUND_COMPLETED`;5 柜首次收货时间及完成结果一致,5 组卸柜 Outbox/Inbox 各一次、事件 ID/摘要/负载一致且均已发布/处理,国内还空预估精确为卸柜后 72 小时。原 r1 错误事件字面量的查询不作为事件结论,实际事件证据取修正后的 r2。核验结果为 `reports/tail-node-readonly-evidence-20260930-r1-verified.json`;这是当前/不可变事实,不能替代收货重放前后完整库存零漂移,不能换算为 77 项完成条件全部通过。
- 最新逐条审计 `reports/fba-stage-completion-audit-current-20260930-r2.json` 已按现行六阶段正文重新核对 77 条完成条件,65 条具备本轮限定范围证据,12 条仍待闭环;这不表示 65 条已完成全部产品/页面验收,不换算总体完成率。待补条件为 C05 订单类型/申报组合、C21 同退税柜改船前后报关摘要稳定、C36/C37 共托逐箱权属与冻结快照、C39 不提前创建国内库存、C49 收货重放完整库存前后、C52 排车线路目的地集合、C60 反向完成同事件去重、C62 根/余量全部签收与合法取消完成回写、C63 客户最终状态及页面下载、C66 独立船异常、C77 重试资源锁数量。已由用户确认拆为 4 个独立任务,总控在本对话汇总;稳定职责与任务 ID 见 `docs/独立任务协作登记.md`。
- 阶段三、四、六文档已统一客户文件确认链、原柜人工改船、统一 Gateway 和事件直接投递。船期任务可在出仓确认后创建并查询进港事实,只有实际开航才推进海运节点。全部业务页面仍无逐节点完整操作证据。
本轮证据位于后端仓库:`reports/firstleg-node-convergence-deploy-20260930.json`、`reports/firstleg-node-convergence-local-20260930.log`、`reports/admin-full-current-20260930-r1.json`、`reports/fba-stage-coverage-audit-20260930.json`、`reports/customs-open-exception-deploy-20260930.json`、`reports/customs-auto-dispatch-atomic-deploy-20260930.json`、`reports/customs-multi-customer-current-20260930-r4.json`、`reports/lastleg-return-receipts-deploy-20260930.json`、`reports/lastleg-return-sku-source-deploy-20260930.json`、`reports/dispatch-return-same-exception-current-20260930-r2.json`、`reports/client-receipt-download-deploy-20260930.json`。静态审查、局部修复通过和单票完成均不能替代全流程验收。
最新专项证据:`reports/customs-multi-customer-current-20260930-r5.json`、`reports/carrier-platform-scope-deploy-20260930.json`、`reports/lastleg-canonical-return-deploy-20260930.json`、`reports/dispatch-return-current-reconciliation-20260930-r2.json`、`reports/fulfillment-stock-receipt-current-20260930-r3.json`、`reports/client-order-navigation-deploy-20260930-r2.json`、`reports/root-completion-local-20260930-r2.json`、`reports/node-closure-order-deploy-20260930.json`、`reports/node-closure-firstleg-deploy-20260930.json`、`reports/node-closure-original-regression-20260930-r1.json`、`reports/tail-node-readonly-evidence-20260930-r1-verified.json`。完成门禁和后续修复已部署;剩余实际验收边界见上文。
### 2026-09-29 对应版本历史证据
2026-09-29 修复后的默认全量真实 HTTP 回归已通过:Admin 11,627 项检查、120 个模块、7,429 次请求,0 失败、0 跳过模块;Client 195 项检查全部通过。F31 换托同库位比较、A0 共享溢出位移库、F33 无贴标转仓查询及跨服务错误处理已修复并部署测试环境;验收脚本补齐直接贴标审核、返工重新领取及禁止回移虚拟收货位的边界。离线合同 128 个文件、773 项断言全部通过。
同票普通 FBA 主链证据为入仓码 `NYEXX2609290171`、柜次 `D1063`、柜号 `TSTU3425326`、排车单 `DS-WH-20260929-067073`、出库单 `OB-WH-20260929-158402`;两张目的仓派送单签收后,已核对来源入仓单 `DELIVERED` 和来源订单 `COMPLETED`。随后故意执行的退回异常测试会改变留存单据状态,不能把最终留存状态误读成未曾完成。退税报关分支另由同一全量报告中的混合柜检查覆盖,不冒充同一票退税至签收证据。
对应证据:`baiyue-firstleg/reports/admin-full-current-20260929-r7.json`、`reports/client-full-current-20260929-r3/client-test-env-20260929063613-e54d44dd.json`、`reports/fba-main-chain-evidence-20260929.json`(后两个路径同属后端仓库)。Admin/Client 报关详情已按 1920×1080 页面核对;船期日历网络恢复后重载正常。未离仓测试柜 `TSTU7897110` 已实际验证首次发送、普通文本回执上传、客户确认后的平台执行、正式申报、其他理由必填备注、异常保存与人工处理;客户确认通过该客户自己的 HTTP 接口完成。异常处理后回执确认保留,未上传完税文件仍保持报关中并阻断离仓。
页面复验发现并修复异常发生时间早 8 小时的问题:国内 `LocalDateTime` 接口改为接收上海业务时间。Admin 提交 `4ead51a5feedf65be9443ddfe3dd45da7ca49e64` 已通过测试环境 Jenkins #482 部署;262 个测试文件、2,121 项测试和构建通过。部署后真实页面新增查验记录的发生时间与服务器记录时间相差 0.879 秒。详见后端仓库 `reports/customs-time-postdeploy-20260929.json` 和 `reports/customs-other-resolved-1920-20260929.jpg`。Android 真机、弱网和外部船司正式凭据仍属于单列验证边界,不纳入本次内置浏览器与 HTTP 通过结论。
## 二、F01-F40 节点冻结矩阵
| 节点 | 客户可见进度 | 后台业务对象 | 必须形成的真实事实 | 当前状态 | 本阶段缺口 |
|---|---|---|---|---|---|
| F01-F07 | 待下单、审核中、已审核 | 企业、订单、审核任务 | 提交、补件、审核、入仓单生成 | 已有主链 | 按现有订单契约回归,不在本轮重做 |
| F08-F10 | 待到仓、测量中、待确认 | 入仓单、测量记录 | 收货、扫码、称重、测量、审核 | 已有主链 | 只核对是否能稳定产出排柜事实 |
| F11 | 费用待确认 | 费用版本、客户确认记录 | 计费推送、客户主动确认、版本留痕 | 已有实现;旧总览的默认确认表述与阶段二及服务指引冲突 | 按现行规则,装柜可自动发布费用,但不能代替客户确认;不将缺少 `SYSTEM_AUTO_AT_LOADED` 列为必修代码缺陷 |
| F12 | 国内扣货中、已解除 | 国内入仓单 HOLD 记录 | 扣货、解除、原因和后续作业门禁 | 已实现;最新全量 inbound-hold 模块通过 | 与报关海关异常、海外库存暂扣分别维护,不能混为同一节点 |
| F13 | 待组托、待分柜 | 一件代发清点、托盘和封托记录 | 逐箱清点、归托、封托 | 已有主链 | 结合一件代发路径验证;不要求普通散货重复执行一件代发清点流程 |
| F14-F20 | 待分柜、订舱中、装柜中 | 柜次、装柜计划、拖车、PDA 任务 | 分柜、订舱、排车、拣货、照片、铅封、数量核对 | 主链已有 | 核对真实柜号、订舱和装柜快照能否冻结 |
| F21 | 国内已装柜 | 装柜计划、物理货柜、装柜证据 | 实际柜号、实装箱数、装柜证据、`LOADED` | 已有 | 报关案例按最终实装范围建立;部分装柜只显示已装箱数并标记线下处理,不在系统内自动分摊 |
| F22.1 | 报关确认中 | 柜级报关聚合内的客户资料范围 | 每客户范围、入仓码范围、混合柜隔离、实装范围回显 | 已实现并通过真实 HTTP 验收 | 独立“案例”对象仍可在正式批次设计时补充;部分装柜仍线下处理 |
| F22.2 | 待提交资料、待补资料 | 客户资料包 | 上传、替换、关联范围、版本、冻结 | 已实现并通过真实 HTTP 验收 | 首期不维护资料类型清单;有文件即可上传,补件通过人工异常理由和备注说明 |
| F22.3 | 已发送报关行 | 独立首次发送批次 `brokerSubmission` | 业务批次号、发送人、发送时间、冻结版本、资料快照、幂等历史 | 已实现并通过定向测试与测试环境部署 | 报关行接收确认和回执轮次对象待补 |
| F22.4 | 待客户确认 | 回执/完成文件版本 | 文件版本、关联客户范围、客户可下载 | 已实现;回执历史和确认动作历史均只读投影 | 独立回执返回时间/下载凭证仍待补 |
| F22.5 | 客户确认中、已打回 | 客户确认记录与动作历史 | 确认/打回、回执版本、操作人、时间、原因 | 已实现并通过定向测试与测试环境部署 | 通知聚合和报关行回执轮次待补 |
| F22.6 | 等待整柜确认 | 完税文件齐全门禁 | 所有退税客户确认、发送执行、真实完税文件齐全 | 已实现并通过专项真实 HTTP 验收 | 查验、扣货、补资料作为平台人工异常节点处理,不新增自动凭证门禁 |
| F22.7 | 已提交正式申报 | 正式申报批次 | 报关行确认、正式申报时间、操作人、批次、报关单号 | 已实现并通过真实 HTTP 7 步联调 | 后续可补报关行接收时间和下载凭证 |
| F22.8 | 查验中、待补资料、已放行、扣货/其他 | 海关结果事实 | 报关单号、结果类型、时间、人工理由、备注和处理结果 | 已实现;真实 HTTP 与人工异常页面保存/处理通过,发生时间偏差已修复并部署复验 | 不接短信或自动海关系统;真机及外部系统不在页面验证范围 |
| F23.1 | 待发区、送港中、已离仓 | 待发区与送港/出仓任务 | 报关完成时间、待发区门禁、离仓时间、车辆/任务、操作人、证据 | 已实现并通过真实 HTTP 验收 | 继续补待发区客户/平台投影展示 |
| F23.2 | 已送港、已进港 | 运输和港口事实 | 送港时间、进港时间、来源和凭证 | 已实现;平台范围船期详情错误已部署修复,原任务与新报关 r5 均通过 | 继续补充实际页面操作证据 |
| F23.3 | 已甩柜、等待改船后承运 | 船期记录修改历史 | 甩柜原因、发生时间、修改前后船名/航次/船期、处理人 | 已实现并通过测试环境真实 HTTP;平台与客户端最新船期投影一致 | 继续补页面截图和更复杂异常分支;柜次、订舱关联和报关事实不变 |
| F24 | 海运中 | 船次实际节点 | 承运船舶、航次、实际开航时间、来源/凭证 | 已实现;实际节点与查询任务已有真实 HTTP 证据 | 继续补充最新一轮页面证据;只允许实际开航事实推进海运节点 |
| F25 | 目的港处理中、待海外接柜 | 船节点、目的港清关/提柜、尾程订单 | 到港、卸船、清关、提柜和可接柜事实 | 已实现并有综合真实 HTTP 证据 | 外部码头/车队差异继续按异常分支补充 |
| F26 | 尾程订单待建计划 | 跨区事件、尾程订单 | 装柜完成、船节点和来源入仓单快照可靠投递与消费 | 正常投递及 Firstleg→Lastleg 真实 ACK 丢失、DEAD 原事件重试、零重复 42 项通过 | 继续补逐来源唯一尾程映射和收货前在途库存归属证据 |
| F27 | 待建立海外入仓计划 | 入仓计划、计划托盘和资源锁 | 按柜内每票生成计划、预计到仓和托盘资源冻结 | 已实现并有综合真实 HTTP 证据 | 继续补齐异常重试页面证据 |
| F28 | 待接柜、接柜中 | 海外 PDA 接柜会话 | 柜号认领、三类签收照片和签收确认 | 已实现并有综合真实 HTTP 证据 | Android 真机验收仍是独立非阻塞项 |
| F29 | 入库中 | 海外 PDA 收货任务 | FBA 散货、海外仓逐箱、一件代发整托等实收事实 | 已实现并有综合真实 HTTP 证据 | 继续补充现场设备和弱网证据 |
| F30 | 入库完成 | 入库任务、库存和跨区回写事件 | 全柜核平、库存同事务入账、卸柜完成事件 | 已实现并有综合真实 HTTP 证据 | 保持事件幂等和库存数量守恒 |
| F31 | 库存可用、库内服务中 | 库存、库位、托盘、盘点 | 上架、移库、合托/拆托、盘点和库存流水 | 已实现并有综合真实 HTTP 证据 | 继续补充大批量库存性能验收 |
| F32 | 暂扣中、已解除 | 暂扣记录和库存锁 | 暂扣原因、解除原因、操作人和库存可用性变化 | 已实现并有综合真实 HTTP 证据 | 暂扣与出库并发场景继续补充 |
| F33 | 换标/转运/废弃处理中 | 换标、转运、废弃子单 | 客户确认、箱唛/托盘变更、库存锁和实际扣减事实 | 已实现并有综合真实 HTTP 证据 | 继续补充复杂返工和跨仓异常 |
| F34 | 待派送、排车中 | 智能预排、排车单 | 候选、草稿锁、正式排车和目的仓分配 | 已实现并有综合真实 HTTP 证据 | 继续补充多车多目的仓页面证据 |
| F35 | 待转派送、待出库 | 排车转派送、出库单、派送单 | 出库/派送单生成、目的仓拆分、费用只发布一次 | 已实现并有综合真实 HTTP 证据 | 保持转派送前不可发车 |
| F36 | 拣货中、待发车 | 海外 PDA 排车任务 | 托盘扫描、数量核平、车辆资料和发车门禁 | 已实现并有综合真实 HTTP 证据 | Android 真机和弱网恢复仍需专项验证 |
| F37 | 已出库、派送中 | 出库单、派送单 | 出库完成、库存扣减和派送任务关联 | r3 拣货、发车、重放的来源位置/原始余额/汇总/SHIP 流水数量及零重复通过 | 不将整轮仍有其他失败的报告描述为全流程通过 |
| F38 | 派送中、已签收 | 派送单、签收凭证 | 签收文件、签收时间和每个目的仓派送完成 | 已实现;当前部署、文件操作与隔离验收范围见[测试环境主契约](../测试环境单机部署与配置契约.md)的 C63 记录 | 原样本下载缺口已有通过证据,其他样本/格式及逐节点页面边界以主契约为准,不沿用旧“浏览器下载未通过”结论 |
| F39 | 异常退回处理中 | 异常单、退回入仓和库存恢复 | 拒收/部分拒收、退回、库存恢复和原因历史 | 不可变出库来源解析已部署修复,原异常成功恢复及重放/完整对账通过 | 新完整尾程生命周期及多次退回/部分恢复组合场景待验 |
| F40 | 已完成、待回访 | 客户回访、跨区完成事件、订单回写 | 回访记录、`DELIVERED` 回写及订单 `COMPLETED` 收口 | 已实现根单余量门禁及可靠完成回写;当前版本和各签收次序/恢复场景的验收事实见[测试环境主契约](../测试环境单机部署与配置契约.md) | 两种签收次序、取消、同事件和完成 Outbox 幂等均须分别核对对应证据;新车辆退回重派组合及逐节点页面不得由历史局部通过推定关闭 |
## 三、当前实现与目标的主要断点
### 1. 客户范围和首次发送批次已落地,回执轮次属于后续增强
当前 `fl_customs_container` 仍是柜级状态聚合,但客户资料通过客户和入仓码范围隔离,真实验收已覆盖同柜多客户和混合柜。正式申报批次、海关结果事实、首次发送报关行批次和客户确认动作历史已经独立落地;尚未独立建模的是报关行接收回执、回执轮次和更细的客户案例聚合。
### 1.1 费用自动发布与客户确认必须区分
阶段二“费用计费与确认”和 `baiyue-firstleg/firstleg/AGENTS.md` 明确规定:费用不阻断排柜和装柜,装柜完成不得代替客户自动确认,客户确认与本票装柜完成共同构成最终冻结条件。`FbaPricingService.autoSendAfterLoadingCompleted` 执行平台费用确认与发送,`confirmByCustomer` 才记录客户确认人和时间;`SENT` 不等于客户确认。旧总览要求 `SYSTEM_AUTO_AT_LOADED` 的表述与现行规则冲突,不能据此直接新增自动代客确认。若未来明确改变该规则,再同步费用版本、确认来源和冻结边界。
### 1.2 海关异常按人工节点处理
海关短信由平台人员人工查看和操作,系统不接短信、不自动判断查验或扣货。平台在正式申报批次上人工标记异常,选择“查验”“扣货”“补资料”或“其他”等理由;选择“其他”时填写备注,后续由平台人员人工解除或录入处理结果。异常是申报批次上的附加事实,不改变已上传资料、回执和客户确认历史。
目标至少需要以下关系:
```text
物理货柜
├─ 最终实装快照
├─ 客户报关案例 × N
│ ├─ 客户资料包与版本
│ ├─ 报关行回执轮次 × N
│ └─ 客户确认/打回记录与动作历史 × N
├─ 整柜正式申报批次
└─ 海关结果事实 × N
```
### 2. 当前“报关完成”仍需与正式申报、海关结果区分
现有完成动作是平台上传每份完成文件,或对全买单柜直接确认;客户确认和完成文件链路已有真实验收。正式申报批次、报关单号和海关结果已经分别记录,仍不能把其中任何一个状态直接当成海关放行或所有运输事实。
### 3. 报关完成与待发区的门禁关系
当前 `CustomsDispatchGateContributor` 要求 `fl_customs_container.status=COMPLETED` 才通过国内出仓门禁,`CustomsAutoDispatchCoordinator` 也在报关完成后自动尝试确认出仓。按最新口径,这不是冲突:报关完成后货柜进入待发区,待发区是送港运输真正开始前的状态门槛;甩柜只在船期运输层处理,不触碰报关事实。
需要重新定义:
- 待发区门禁先检查报关 `COMPLETED`,再叠加装柜、PDA、订舱、证据等运输条件;通过后只推进到 `WAITING_FOR_LOADING`。
- 报关线单独保存客户确认、整柜申报和海关结果;这些事实不会被船期修改覆盖。
- 报关完成事件只能推进待发区,不得自动伪造送港、进港或开船事实。
- 实际开航只能由船次实际节点推进。
### 4. 客户端基础报关协同闭环已完成
当前客户端 `CustomsDocumentsView.vue` 提供独立报关资料列表和待办入口,`CustomsDocumentsDialog.vue` 已支持上传、替换、调整关联入仓码、查看和下载报关行回执/真实报关完税文件、确认整份回执和填写原因打回,并展示回执历次上传版本及确认/打回动作历史;仍缺少:
- 客户案例的进度和通知。
### 5. 平台端基础整柜协同闭环已完成
当前 `ContainerCustomsPanel.vue` 已展示退税资料、首次发送报关行批次、回执/完成文件、客户范围、确认状态、回执历次上传版本和确认/打回动作历史,并支持正式申报批次和海关结果基础操作;仍缺少:
- 按客户查看案例和实际装柜覆盖;
- 报关行接收回执和回执轮次管理;
- 报关行接收回执时间和下载凭证等更细历史。
## 四、接口、权限、审计和测试缺口
### 接口与数据库
- OpenAPI 不能继续只暴露旧的四态 `ContainerView`。
- 需要继续补充报关行接收回执、回执轮次和下载凭证的查询/命令契约;资料包、首次发送批次、回执版本和确认动作只读历史、整柜申报和海关结果基础契约已落地。
- 文件仍由 File 服务保存,但每个文件必须绑定业务类型、客户案例/申报批次、版本和覆盖范围。
- 每个写命令都要带版本和幂等键;重放同参数返回原结果,不同参数返回冲突。
- 换柜时需要保留新旧柜关联;部分装柜只记录已装箱数和线下处理标记,不在系统内自动做数量分摊或覆盖旧资料。
### 权限
至少区分:
- 客户上传、替换、补件、确认、打回;
- 平台客服接收、核对、退回补件;
- 平台报关操作员发送报关行、上传回执、提交正式申报;
- 平台人员录入查验、放行、扣货及其他海关结果;
- 客户和平台各自的只读下载权限。
### 审计
需要保留客户范围、资料版本、回执轮次、确认人、打回原因、提交批次、报关单号、异常理由、备注和操作时间。客户 A 的动作不能出现在客户 B 的案例中;柜级汇总可以看到客户名和业务编号,但客户端只能看到自身范围。
### 测试
最小验收矩阵至少覆盖:
1. 单客户和多客户同柜。
2. 一客户打回时其他客户继续保持已确认。
3. 同一请求重放、同幂等键换参数、版本冲突。
4. 未全部客户确认时正式提交被拒绝。
5. 正式申报、查验、不查验放行、扣货和其他结果分别显示。
6. 报关完成后货柜进入待发区,等待船舶承运。
7. 甩柜改配在原柜上人工修改船信息并留痕,柜子和报关事实不变。
8. 只有实际开航事实推进 F24。
9. 客户越权读取同柜其他客户资料被拒绝。
10. 部分装柜能显示实际箱数并留下线下处理标记;换柜不能直接覆盖原案例和历史回执。
## 五、后续增强(无需当前业务确认)
以下内容不阻断当前开发:回执接收时间、回执轮次和下载凭证可以后续增强;海关短信、查验、扣货、补资料和其他异常按平台人工标记、选择理由和填写备注处理。
### 已冻结的业务规则
| 规则 | 冻结口径 | 依据 |
|---|---|---|
| 资料提交时点 | `LOADED` 后按最终实装快照建立客户案例并进入本轮报关 | 交接清单“一、必须实现的报关流程”;总流程 F21/F22 |
| 同柜客户边界 | 一个客户案例只属于一个客户;同一客户多个入仓码可以共享资料,但跨客户正式合报默认禁止 | 报关专题“申报组与柜级总览”“买单、退税和混合柜完成条件” |
| 回执与客户确认 | 首期以报关行回执文件为主,客户对整份回执确认;回执上传不等于客户确认 | 本轮业务确认 |
| 资料与部分装柜 | 报关资料、报关行回执都按文件保存;部分装柜只展示箱数,线下人员处理后续,不做系统内数量分摊 | 本轮业务确认 |
| 首期正式申报 | 由平台授权人员人工提交并回填报关行确认和海关结果 | 本轮业务确认;报关专题状态约定 |
| 报关与待发区关系 | 报关完成后货柜才能进入待发区;待发区是等待船舶承运的运输状态,报关和船期事实分开保存 | 本轮业务确认 |
| 海运起点与改配 | 首期人工录入实际开航;甩柜/改配只变更船期/航次,不重新处理已完成报关资料;只有实际开航事实推进 F24 | 本轮业务确认;交接清单第二条;总流程 F23/F24 |
### 本轮补充确认的甩柜/改配口径
| 项目 | 已确认口径 |
|---|---|
| 发起与确认 | 平台人员直接编辑原柜船期,记录操作人、时间、原因和修改前后船信息。 |
| 资料继承 | 报关完成后资料、平台回执和客户确认与船期独立;甩柜/改配不触发重新上传或重新确认。 |
| 航次任务 | 平台人工修改原柜船信息,继续使用原任务;保留修改历史和已有节点。 |
### 已确认的字段和操作规则
1. (已确认)首期不维护资料类型清单和逐项责任人;资料包只要有文件即可上传、替换和留版本。
2. (已确认)查验、扣货、补资料和其他结果由平台人员人工标记异常、选择理由;选择“其他”时填写备注,异常解除也由平台人工点击。
3. (已确认)第一版由平台人员直接修改原柜船名、航次和船期,填写原因并保留修改历史。
4. (已确认)平台人工修改原柜船名、航次和船期;柜子与原任务不变。
5. (已确认)原航次退税资料、回执和客户确认与船期独立,甩柜/改配不触发重新确认。
6. (已确认)修改船信息不生成实际开航事实;只有本柜实际随船开航后才记录 `DEPARTED_ORIGIN_PORT`。
### 代码接入前置缺口
最新确认取消新增航次对象和重建任务的方案。复用现有船期编辑及修改历史,柜次、订舱关联和查询任务保持不变。测试环境已核验平台与客户端都会投影修改后的最新船期,报关资料、回执、完成文件和客户确认保持不变;证据见 `baiyue-firstleg/reports/platform-and-client-transport-projection-20260927.json`。
## 六、冻结结论
- 全流程基线覆盖 F01-F40;F01-F24 终点为实际开航,F25-F40 继续完成目的港、海外入库、出库、派送和最终回写。
- F22 报关完成后货柜进入 F23 待发区;甩柜/改配只改变运输航次,不改变报关事实。
- 客户确认、报关行回执、整柜正式申报、海关放行、离仓、进港、甩柜和实际开航都是独立事实。
- 节点清单覆盖完整范围;各节点实现与验证程度以表内状态为准,不将整张矩阵标为全部验收完成。
- F25-F40 已有实现,最新默认全量 HTTP 回归已通过,并核对同票签收后的国内完成回写;本轮报关可写异常页面操作已完成,设备和外部船司边界继续单列,不能用 HTTP 全绿替代这些证据。
@@ -0,0 +1,78 @@
# 头程节点与报关清关交互矩阵
> 本文把 F01-F40 全流程中的头程、海运与报关清关交互放在同一张图里;其中 F01-F24 是国内头程到实际开航,F25-F40 由阶段四至阶段六继续承接。报关资料只适用于包含退税货物的柜,买单货物不创建客户资料协同。
## 一、总链路
```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 → 报关 → 待发区` 已在混合柜报告中通过,平台与客户改船后的当前船期双端回读已验收。F25-F40 的海运目的港、海外入库、库存、出库、派送和最终回写由阶段四至阶段六维护,综合证据见 `baiyue-firstleg/reports/admin-overseas-chain-final-fixture-20260924.json`。
正式申报批次和海关结果已在本轮实现并通过真实 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 状态。
@@ -0,0 +1,110 @@
# 报关代码开发交接清单
> **当前状态:报关协同已接入测试环境。** 客户资料、首次发送报关行批次、回执、客户确认历史和真实完税文件已形成独立链路;海关查验、扣货、补资料和其他结果由平台人员人工标记异常、选择理由并填写备注,不接短信或自动海关系统。报关行接收回执和下载凭证仍可后续增强。头程至尾程的全流程范围和缺口以[头程至实际开船节点冻结矩阵与缺口清单](头程至实际开船节点冻结矩阵与缺口清单.md)为准;流程规则以[报关资料与船期价格接入梳理](../国内货柜履约/报关资料与船期价格接入梳理.md)为准,节点关系以[头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md)为准。
> **本轮补充确认:** 首期报关行回执以文件为主,客户确认整份回执;正式申报由平台授权人员人工提交并回填结果;报关完成后货柜进入待发区;实际开航首期人工录入,甩柜/改配只变更船期,不重新处理已完成报关资料。
> **验收证据:** 既有全链路报告保留旧版 526/526、混合柜 532/532 记录;本轮新增代码、数据库和三端已部署,已用现有完成柜做接口烟测并核对首次发送门禁。完整造数到报关回归已补齐测试环境专用国内 PDA 作业员并通过;当前报关主链报告为 543/543,运输节点报告为 1036/1036。
## 一、必须实现的报关流程
从装柜完成(`LOADED`)开始,按柜内客户分别处理:
1. 按最终实装清单建立客户报关案例和资料包。
2. 收集客户上传、替换或补充的资料,冻结后由平台生成独立批次首次发送给报关行。
3. 接收报关行回执并发给对应客户确认。
4. 客户打回时,只重开对应客户当前轮次,重新上传、重新发送并生成新回执;保留每轮资料、回执、确认人、时间、动作历史和打回原因。
5. 柜内所有客户确认后,平台发送客户确认后的回执给报关行执行。
6. 报关行执行完成后,平台上传真实报关完税文件;全部退税资料对应的完税文件齐全后,整柜报关完成。
7. 分别记录海关查验、不查验放行、扣货或其他正式结果。
报关行回执、客户确认、整柜正式申报和海关放行是不同节点。客户确认不能自动完成,平台费用确认与发布也不能代替报关资料确认。
## 二、报关完成与待发区关系
- `LOADED` 只表示物理装柜完成;报关资料、回执、客户确认和正式申报仍需独立完成。
- 报关完成后,货柜才能进入待发区;待发区表示等待船舶承运,不表示已经开船。
- 送港、进港、甩柜和改配是运输事实;甩柜只在原柜船期记录上人工修改船信息,不回退或重新处理已完成报关资料。
- 只有承运船舶实际开航后,才推进 `DEPARTED_ORIGIN_PORT` 海运节点。
## 三、当前代码交接重点
### 已落地的第一批能力
- 平台端和客户端都能展示当前视角的实际装箱数;部分装柜只展示箱数,后续由线下人员处理,系统不做数量分摊。
- 报关资料和报关行回执继续按文件上传、覆盖、版本和下载处理;页面文案已区分“回执”和“完成”,避免把上传回执误认为客户确认或正式申报。
- 首次发送报关行单独记录 `brokerSubmission`(业务批次号、冻结资料版本、快照、操作人和时间);未完成首次发送时不能上传回执,也不能发送客户确认结果给报关行执行。
- 报关资料链路仅适用于退税货物;买单货物不创建客户报关资料、回执和客户确认流程。
- 回执上传后进入待确认状态;客户端已提供整份回执确认和打回入口,平台与客户端都展示每个回执版本的确认/打回历史,打回原因回传后再由平台重新上传回执。
- 后端 OpenAPI、平台/客户端模型和基础测试已同步实际箱数字段;管理员端、客户端类型检查及相关组件测试已通过。
旧版资料与回执基础链路已通过测试环境真实 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`。
- 本轮页面回归又修复了一个实际问题:Client 订单列表契约此前没有保留 `taxMode`,导致真实退税订单在“报关资料”页被过滤为 0 个资料包;Client `214fe4f` 已补齐退税字段映射,测试部署 `client-web-test #357` 成功。随后发现船期价格页首次加载重复请求渠道列表,`32c5241` 已收敛初始化监听,`client-web-test #358` 成功。
- 后续回归又修复两个页面事实问题:未知海外仓不再把内部仓库 ID当作客户可见名称;报关完成详情改为明确提示“真实报关完税文件已齐全”。同时同步了现有实现对应的离线合同断言,客户端全量 `npm test` 已通过 `398/398`,生产构建通过,提交 `ffbe348`,测试部署 `client-web-test #359` 成功。
- 测试环境内置浏览器已按 1920×1080 复验 Admin 与 Client:最新 Admin 柜次详情展示 `LOADED`、8 条仓内节点、PDA 作业摘要 100%、报关“已完成”、国内离仓“已自动离仓”和 7/7 门禁通过;最新 Client 报关资料页展示退税资料包“报关完成”,详情可见回执版本、客户确认状态、真实完税文件和下载入口。Client 船期价格查询以 100 KG/1.2 CBM 真实调用 15 个估价接口并返回 4 个匹配渠道;同一页面初始化只保留 1 次渠道列表请求。
- 页面请求量抽样:Admin 货柜详情 13 个 API 请求且无重复;Client 报关资料列表 10 个不同 API 请求,打开两个资料详情各刷新一次资料接口;Client 船期价格初始化 1 次渠道请求,查询阶段 15 次并行估价请求,符合当前“每渠道估价”契约。完整新造数 HTTP 链已解除 PDA 前置阻塞并通过;报告 `baiyue-firstleg/reports/customs-current-20260928.json` 共 543/543 项通过,包含订单、测量、PDA 装柜、混合柜报关资料、回执、客户确认、报关行执行、完税文件、自动离仓和客户端下载。
- 2026-09-28 再次复核:测试 API 健康检查、Admin 货柜列表/详情和 Client 报关资料页均返回 HTTP 200;Admin 与 Client 均在 1920×1080 下重新打开验证。已完成柜调用首次发送接口并携带确认参数,服务端返回 `A0409 当前柜不在报关中`,证明已完成柜不会重复创建报关批次;当前无新增数据库记录。客户端全量测试保持 `398/398` 通过,`client-web-test #359` 成功。
当前仍需继续补齐的不是客户资料协同、正式申报和海关结果基础链路,而是:
- 报关行回执的外部确认/接收回执、下载凭证和回执轮次的更细对象;首次发送批次与客户确认动作历史已经落地;
- 更细的报关行接收回执和下载凭证;海关异常继续按人工理由和备注处理,不新增自动结果凭证门禁;
- 将正式申报/海关结果继续扩展到待发区、送港、进港和实际开航的只读投影,保持运输线独立;F23.3 的船期投影已完成真实 HTTP 核验。
开发时不要只增加页面节点文案,也不要把旧的 `COMPLETED` 直接当成客户确认、正式申报或海关放行。
## 四、开发入口
先核对当前代码和 OpenAPI,再决定复用或调整现有接口:
- 客户端报关资料:`apps/client-web/src/modules/first-leg/`,重点查看 `routes.ts`、`CustomsDocumentsDialog.vue` 和 `api/customs.ts`。
- 平台整柜报关:`apps/admin-web/src/modules/container-loading/`,重点查看 `ContainerCustomsPanel.vue` 和 `api/platformContainerCustoms.ts`。
- 后端报关:`baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/customs/container/`。
- 接口与数据:`baiyue-firstleg/firstleg/src/main/resources/openapi/customs-v1.yaml`、报关相关数据库脚本和 IAM 权限初始化。
具体类名、接口路径、状态编码和数据库字段以当前代码核对结果为准;本清单只定义业务完成条件,不预先替换技术实现。
## 五、完成条件
- 客户 A 与客户 B 的资料、回执和确认严格隔离。
- 每个客户都能完成“资料上传 → 报关行回执 → 客户确认/打回”,资料和完成文件保留版本,客户范围严格隔离。
- 首次发送报关行必须生成独立业务批次;客户每次确认或打回都保留对应回执版本、操作人、时间和原因。
- 未全部客户确认时不能完成整柜报关;正式申报批次、海关回填结果和报关单号已独立建模,不能把客户确认或完税文件上传直接当作海关放行事实。
- 海关查验、不查验放行、扣货、补资料和其他结果已落地为批次下独立事实;平台人员人工选择理由,选择“其他”时填写备注并人工处理异常。
- 报关完成后才能进入待发区;进入待发区后才推进送港/进港。甩柜/改配只修改原柜船名、航次和船期并保留历史,不能伪造或覆盖报关资料、回执和客户确认。
- 重复请求、版本冲突、换柜、部分装柜箱数展示和权限越界都有明确结果和审计记录;部分装柜的后续处理在线下完成。
- F22 和阶段三的实现状态已按当前代码和真实 HTTP 结果回写;后续继续按 `COMPLETED`、海关放行和运输节点分别验收,不把报关完成合并成海运或尾程完成。
- 2026-09-29:补齐测试环境专用 `CN_FIRSTLEG_PDA_OPERATOR` 账号并验证登录,重新执行 `phase3-container-customs` 正式 HTTP 造数链;订单、测量、PDA 领取/扫码/提交、`LOADED` 硬门禁、混合柜 BUY/TAX 隔离、首次发送批次、回执幂等、客户确认、报关行执行、完税文件、`COMPLETED`、自动离仓和 Client 完税文件下载共 543/543 通过,348 个唯一 HTTP 请求,0 个 coverage gap。报告:`baiyue-firstleg/reports/customs-current-20260928.json`。
- 2026-09-29:继续执行头程运输节点造数链;订舱、港务船期、甩柜改船、拖车预约、报关完成后的待发区、国内离仓门禁和船司查询策略共 1036/1036 通过,641 个唯一 HTTP 请求,0 个阻塞缺口。甩柜只更新原柜船期,柜次及报关事实不变。报告:`baiyue-firstleg/reports/transport-current-20260929.json`;剩余 4 个缺口均为非阻塞的 COSCO/ZIM 外部接入或 Android 真机验收。
@@ -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 与船期不参与结果对象。
@@ -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`。
@@ -0,0 +1,39 @@
# 甩柜与改配接入设计(F23.3)
## 最新确认
柜子不会变。平台人员在原柜子的船期信息上人工修改船名、航次和预计时间即可;保留修改前后内容、修改人和时间。报关资料、回执、完成文件和客户确认保持不变。
## 操作流程
1. 退税报关完成后进入待发区,等待船舶承运。
2. 原船装满导致甩柜时,平台编辑该柜当前船期,填写实际安排的船名、航次和预计开船/到港时间。
3. 保存后继续使用原柜次和原船期查询任务;保留已经发生的离仓、进港事实。
4. 货柜实际随船开航后,再记录实际开航节点。修改预计船期本身不表示已经开船。
不新建柜子、订舱关联或航次变更审批对象,不重建船期任务,也不重新上传或确认报关资料。此前建议的 voyage-changes 接口和批次评估状态已取消。
## 现有接入入口与待验收项
入口放在原柜详情的“船名航次信息”区域,通过“船期维护与历史”打开居中弹框;不依赖已退出路由的独立 `PortSchedulesView.vue`。后端返回与当前运输展示来自同一条记录的只读 `currentPortScheduleId`,前端按此加载详情;不得自行从其他柜或全量船期中选择记录。`PortScheduleService.update` 保持客户、订舱和柜次归属不变,并保存版本和修改前后历史。
已有记录只修改船名、航次、ETD、ETA及本次原因,其余来源与有效期字段保留;提交携带原版本和幂等键,网络结果不明时重试原请求,未改运输值不重复发送。只读权限可查看历史,新增和编辑权限分别校验。无当前记录时,允许在原客户、原订舱和原柜上登记船期信息,来源、确认时间、信息有效至及截港时间须明确填写,不自动编造门禁有效期。
交互依据沿用既有船期维护的居中表单和货柜详情分区;已有记录使用1000px弹框,首次登记使用1120px三列表单,原因跨列,历史展示修改前后四项运输字段、修改人、原因和时间。实际1920×1080页面验收及发布证据仅维护在测试环境主契约,不以此设计说明替代验收结果。
当前船期展示已改为读取同一客户、订舱和柜次下最新船期记录,不再固定读取订舱初始快照。平台人工改船后,客户端会同步显示最新船名、航次和预计时间。
## 验收要求
- 修改后柜次、柜号、装柜清单、订舱关联和船期查询任务不变。
- 船名、航次和预计时间正确更新,平台与客户可见的当前船期一致。
- 修改前后历史、操作人和时间可追溯,重复请求和版本冲突有明确结果。
- 报关状态、资料、回执、完成文件、客户确认与修改前一致。
- 已发生的物理节点不重置,预计时间调整不推进实际开航。
## 真实联调证据(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`。
+24 -28
View File
@@ -1,36 +1,32 @@
# 头程到尾程分阶段流程文档 # 头程到尾程分阶段流程
本目录把“头程下单 → 尾程出库”拆成六个可独立评审、以后也可独立优化的阶段。各阶段统一描述现状操作和数据流,不在流程确认前直接决定改版方案。 本目录是端到端流程的分段查找入口。F01-F40 流程基线已确认,当前用于全流程收尾变更;阶段三报关协同代码已接入并通过真实 HTTP 验收。总览和节点关系看[《头程到尾程流程节点梳理》](../头程到尾程流程节点梳理.md),字段、页面操作、权限和异常细节在对应阶段文件维护。
当前六个阶段的现状基线均已完成。下一步按阶段组织业务、产品、运营、国内仓、海外仓和技术评审;每阶段确认后,再将评审结论转入易用性和数据流转优化方案。 ## 三大业务块与六个分段
## 分阶段计划 | 业务块 | 分段 | 节点范围 | 详细文档 |
| 阶段 | 范围 | 对应全景流程 | 文档 |
|---|---|---|---| |---|---|---|---|
| 阶段一 | 客户准入、基础资料、单票/批量下单、提交、审核、订单交接 | F01~F07 | [阶段一:客户准入与头程下单](阶段一-客户准入与头程下单.md) | | **头程下单** | 阶段一:客户准入与头程下单 | F01-F07 | [打开阶段一](阶段一-客户准入与头程下单.md) |
| 阶段二 | 国内到仓、箱码、测量、称重、费用、扣货、一件代发组托 | F08~F13 | [阶段二:国内到仓、测量计费与组托](阶段二-国内到仓测量计费与组托.md) | | **头程下单** | 阶段二:国内到仓、测量计费与组托 | F08-F13 | [打开阶段二](阶段二-国内到仓测量计费与组托.md) |
| 阶段三 | 模拟柜、排柜、订舱、拖车、预装、国内 PDA、报关、出仓 | F14~F23 | [阶段三:国内货柜履约与出仓](阶段三-国内货柜履约与出仓.md) | | **海运(货柜)** | 阶段三:国内货柜履约与出仓 | F14-F23 | [打开阶段三](阶段三-国内货柜履约与出仓.md) |
| 阶段四 | 海运节点、目的港、跨区尾程建单、尾程入仓计划 | F24~F27 | [阶段四:海运、目的港与尾程入仓计划](阶段四-海运目的港与尾程计划.md) | | **海运(货柜)** | 阶段四:海运、目的港与尾程计划 | F24-F27 | [打开阶段四](阶段四-海运目的港与尾程计划.md) |
| 阶段五 | 海外接柜、实收、库存、暂扣和库内服务 | F28~F33 | [阶段五:海外接柜、库存与库内服务](阶段五-海外接柜库存与库内服务.md) | | **尾程入库和派送** | 阶段五:海外接柜、库存与库内服务 | F28-F33 | [打开阶段五](阶段五-海外接柜库存与库内服务.md) |
| 阶段六 | 海外排车、转派送、PDA 出库、派送、异常和最终回写 | F34~F40 | [阶段六:海外排车、出库、派送与最终回写](阶段六-海外排车出库派送与回写.md) | | **尾程入库和派送** | 阶段六:海外排车、出库、派送与最终回写 | F34-F40 | [打开阶段六](阶段六-海外排车出库派送与回写.md) |
## 每阶段统一模板 ## 修改时只看这三层
1. 阶段目标、起点和终点; 1. **总览层**:三大块、客户进度和节点关系变化,改总览节点梳理。
2. 角色、终端和权限边界; 2. **分段层**:某一段的页面操作、字段、权限、状态或异常,改对应阶段文件。
3. 前置主数据和检查项; 3. **专题层**:报关资料、报关行回执、客户确认、送港/甩柜和船期价格,改[报关资料与船期价格接入梳理](../国内货柜履约/报关资料与船期价格接入梳理.md),并回看总览中的 F22/F23。
4. 页面逐步操作;
5. 字段与条件必填规则;
6. 状态机、可用动作和不可逆节点;
7. 单据、编号、快照和数据归属;
8. 同步/异步调用和上下游交接;
9. 正常流、条件分支和异常恢复;
10. 阶段完成判定与评审清单。
总览入口: ## 跨段交接
- [现状流程全景清单](../头程下单到尾程出库现状流程全景清单.md) - 阶段二完成后进入阶段三的分柜;费用确认是并行事项,不阻断排柜、拣货和装柜。
- [一票主链操作手册](../头程下单到尾程出库全流程操作手册.md) - 阶段三的装柜完成(`LOADED`)后先完成退税报关;报关完成后货柜进入待发区,再推进送港运输。甩柜/改配只影响船期,不改变已完成报关事实。
- [易用性与数据流转优化草案](../头程下单到尾程出库流程易用性与数据流转优化方案.md) - 报关协同必须经过“客户资料 → 报关行回执 → 客户确认/打回重做”,柜内所有客户确认后才提交整柜资料并正式申报。
- [AI 流程优化上下文包](../头程到尾程AI流程优化上下文包.md) - 送港完成、进港或甩柜都不等于海运中;承运船舶实际开航后才进入阶段四的海运节点。
- 阶段四形成海外接柜输入后,阶段五负责实收、入库和库存,阶段六负责出库、派送、签收和异常回写。F01-F37 以海外出库为阶段性业务终点,F38-F40 继续完成派送、签收和国内最终回写。
## 旧文档的使用范围
全流程操作手册、现状全景清单、AI 优化上下文、开发规划、进度表、开工门禁和验收任务继续保留,用于追溯历史决策和实现记录;它们不是当前节点维护入口。新增规则只写入总览、对应阶段或专题文件,避免同一流程在多份历史文档中重复修改。
@@ -2,8 +2,8 @@
> 对应全景流程:F14~F23。 > 对应全景流程:F14~F23。
> 阶段起点:入库单主状态为 `WAIT_SPLIT`,不存在有效 HOLD。 > 阶段起点:入库单主状态为 `WAIT_SPLIT`,不存在有效 HOLD。
> 阶段终点:整柜满足国内出仓门禁,产生唯一实际 `DEPARTED_WAREHOUSE` 节点并开始出仓后的船节点查询。 > 阶段终点:装柜后完成退税报关并进入待发区,再完成送港线的仓库离开/进港事实;实际开船 `VESSEL_DEPARTED` 由阶段四承接。
> 本阶段复用订单、入库单、柜次和装柜计划,不新建独立“出仓单”。 > 本阶段复用订单、入库单、柜次和装柜计划,不新建独立“出仓单”。`LOADED` 后先推进报关协同,报关完成后进入待发区,再推进送港;费用确认是并行事实,装柜完成后对已装范围的当前有效费用版本执行系统默认确认。
## 1. 阶段目标和边界 ## 1. 阶段目标和边界
@@ -15,12 +15,12 @@
4. 模拟柜与订舱柜型需求、真实集装箱号关联; 4. 模拟柜与订舱柜型需求、真实集装箱号关联;
5. 预装确认、动态增减和普通散货托盘标签; 5. 预装确认、动态增减和普通散货托盘标签;
6. 国内 PDA 拣货、整托装柜和异常闭环; 6. 国内 PDA 拣货、整托装柜和异常闭环;
7. 四步装柜照片、铅封照片与铅封号; 7. 空仓、半仓、满仓、锁仓、带锁码照五类装柜证据与锁码文本;
8. 装柜完成、部分装载分片和跨区交接快照; 8. 装柜完成、部分装载分片和跨区交接快照;
9. 客户资料、整柜出口报关与放行; 9. `LOADED` 后通知报关行、客户资料收集、回执确认、整柜正式申报和海关结果;
10. 国内出仓门禁、离仓确认和拖车费用归集。 10. 送港、进港、甩柜/改配、实际离仓和拖车费用归集。
`LOADED` 表示货物已经完成实际装柜,不等于柜子已经离开国内仓。报关放行等条件在国内出仓环节统一校验;国内 Admin/PDA 不得把订单推进到海外派送完成 `DELIVERED`。 `LOADED` 表示货物已经完成实际装柜。此时先触发报关线:收集退税客户资料、发送报关行、处理回执和客户确认;报关完成后进入待发区,才允许推进拖车、离仓和进港。已进港不代表报关完成,容量不足时记录甩柜和改配船次;甩柜不影响已完成报关资料、回执和客户确认。只有实际开船后才进入海运节点。国内 Admin/PDA 不得把订单推进到海外派送完成 `DELIVERED`。
## 2. 角色、终端和对象 ## 2. 角色、终端和对象
@@ -55,7 +55,7 @@
- 柜型规格、国内中转仓、有效渠道和供应商主档可用; - 柜型规格、国内中转仓、有效渠道和供应商主档可用;
- 操作员理解模拟柜、真实柜号、订舱和拖车是不同对象; - 操作员理解模拟柜、真实柜号、订舱和拖车是不同对象;
- 同柜不可拆组、已占用数量和版本冲突均以服务端返回为准; - 同柜不可拆组、已占用数量和版本冲突均以服务端返回为准;
- 费用仍可并行维护,但已经确认/发送或客户已确认版本不得被静默改写。 - 费用仍可并行维护,客户未确认不阻断排柜、预装、PDA 或装柜;装柜完成后对已装范围的当前有效已发布版本记录系统默认确认。客户确认和系统默认确认来源分开审计;缺少有效费用版本不伪造确认,部分装载不得把余量一起确认。
## 4. F14 模拟柜与智能排柜 ## 4. F14 模拟柜与智能排柜
@@ -225,13 +225,13 @@ PDA 装柜完成不推进拖车状态。只有订舱要求的全部柜型数量
## 10. F20 装柜证据与铅封 ## 10. F20 装柜证据与铅封
PDA 按现场顺序拍摄: PDA 按现场要求采集五类证据:
1. `PHOTO_STEP_1`:装柜初始/空柜; 1. `EMPTY`:空仓照片;
2. `PHOTO_STEP_2`:装载过程; 2. `HALF`:半仓照片;
3. `PHOTO_STEP_3`:接近完成; 3. `FULL`:满仓照片;
4. `PHOTO_STEP_4`:满柜/关门前; 4. `LOCKED`:锁仓照片;
5. `SEAL`:带有效铅封号的封柜照片。 5. `SEAL`:带有效铅封号的带锁码照片。
每类至少一张有效照片,同类允许追加。PDA 仅允许现场相机拍摄;有权限的 Admin 操作员/理货员可人工补充,普通拣货员不开放后台上传。 每类至少一张有效照片,同类允许追加。PDA 仅允许现场相机拍摄;有权限的 Admin 操作员/理货员可人工补充,普通拣货员不开放后台上传。
@@ -245,7 +245,7 @@ PDA 点击“完成装柜”时,服务端重新校验:
- 真实集装箱号存在; - 真实集装箱号存在;
- 所有普通箱码或一件代发整托均核平; - 所有普通箱码或一件代发整托均核平;
- 没有未解决异常; - 没有未解决异常;
- 四步照片和带铅封号的 `SEAL` 完整; - 空仓、半仓、满仓、锁仓、带锁码照五类证据和锁码文本完整;
- 计划明细、已拣数量和最终实装数量守恒。 - 计划明细、已拣数量和最终实装数量守恒。
校验通过后: 校验通过后:
@@ -260,45 +260,54 @@ PDA 点击“完成装柜”时,服务端重新校验:
## 12. F22 客户资料与整柜出口报关 ## 12. F22 客户资料与整柜出口报关
### 12.1 客户上传资料 ### 12.1 F22-A `LOADED` 后按退税客户范围收集资料
入口:Client → 头程订单 → 报关资料。 入口:`LOADED` 事件 → Admin/Client → 报关资料。
客户只可对本企业订单上传退税/报关资料,选择资料类型并填写说明。文件归属、订单归属和客户身份由服务端校验,文件名不能代替合法文件 ID。 1. 装柜完成后按最终实装清单确定本柜每个退税客户及其入仓码范围;首期复用柜级报关聚合与客户资料范围,不强制新增独立 `customerCustomsCase` 对象;
2. 退税客户上传本企业资料,平台校验客户、订单、入仓码、实际装载范围和文件归属;有文件即可,不要求资料类型清单。买单订单不走这条客户资料和回执确认链;
3. 平台将资料发送给报关行,记录首次发送批次、发送人、时间、资料版本和范围快照;
4. 报关行返回回执,平台上传文件并向对应退税客户展示整份回执确认任务,保留文件版本和确认动作历史;独立回执轮次对象属于后续增强。
### 12.2 平台整柜报关 柜前可以存在资料准备或历史附件,但不创建本柜正式客户确认轮次,也不能显示“已通知报关”。客户资料缺失形成报关补件待办,未完成报关不得进入待发区或推进送港。
入口:Admin → 柜次详情 → 出口报关。 ### 12.2 F22-B 报关行回执与客户确认循环
1. 查看柜内所有入仓码及其资料覆盖情况; 客户查看报关行回执后有两个结果:
2. 对退税资料逐项核对,缺件时联系对应客户补充;
3. 开始报关时冻结当前参与资料和版本;
4. 线下向报关代理提交;首版不做外部系统直连;
5. 完成后为每份退税资料上传一一对应的完成文件;
6. 全买单柜由平台确认买单,并从导出中心获取最终实装买单明细;
7. 点击完成整柜报关,写入放行结果和历史。
报关完成后系统立即尝试国内出仓;若其他门禁尚未齐全,保留明确阻断项并由受控补偿重试,不能伪装为已离仓。 1. **确认**:该客户当前整份回执确认状态为 `CONFIRMED`,保存确认人、确认时间、回执版本和幂等键;
2. **打回**:保存本客户对当前回执的打回状态和原因;客户重新上传/替换资料,平台与报关行线下处理后上传新的回执版本,再由该客户确认。首期通过资料、回执版本和动作历史追溯,不强制新增 `roundNo` 对象。
## 13. F23 国内出仓 客户打回只改变对应客户资料范围的确认状态,不重置其他客户已确认的回执。只有所有退税客户的当前回执都已确认,平台才可发送客户确认结果给报关行执行,并进入整柜正式申报。首期首发和确认后发送执行是两次独立动作。
### 12.3 F22-C 所有客户通过后的整柜正式申报
1. 平台检查所有退税客户当前回执均已确认,已发送确认结果给报关行执行,冻结本柜最终实装和资料/回执版本,生成整柜正式申报批次;
2. 将整柜资料提交报关行确认,报关行完成正式申报;首版不做外部系统直连,保留人工提交和审计记录;
3. 海关结果独立记录为查验、免查验放行、补件/退回、扣货等,不把客户确认回执直接当成海关放行;
4. 报关行执行后,平台上传对应退税资料范围的真实报关完税文件;每个退税客户的完成文件齐全才完成报关并进入待发区。完税文件、正式申报及海关结果分别留痕,不互相冒充;海关异常由平台人工选择理由、填写说明并处理,“其他”必须填写备注;
5. 报关事实不覆盖送港线的离仓、进港、甩柜事实。甩柜只人工修改原柜船名、航次和船期,保留修改历史;原柜和原任务不变,不回退报关资料、回执或客户确认。
## 13. F23 送港、进港与甩柜
### 13.1 出仓硬门禁 ### 13.1 出仓硬门禁
整柜所有关联入库单逐项检查: 送港线的离仓/进港门禁逐项检查:
- 无有效 HOLD; - 无有效 HOLD;
- 入库单为 `LOADED`; - 入库单为 `LOADED`;
- 装柜计划为 `COMPLETED`; - 装柜计划为 `COMPLETED`;
- PDA 柜次任务为 `COMPLETED`; - PDA 柜次任务为 `COMPLETED`;
- 订舱已 `RELEASED` 且分配当前柜次; - 订舱已 `RELEASED` 且分配当前柜次;
- 四步照片与有效铅封完整; - 五类证据与有效锁码文本完整;
- 整柜报关已完成并放行。 - 送港任务和当前船次分配完整;
- 报关完成是进入待发区以及后续仓库离开、送港和进港的前置。
独立拖车状态和独立船期字段提供调度参考,但不是当前确认离仓的硬门禁。拖车在全部订舱柜次离仓后自动完成。 订舱、拖车、仓库离开和港口进场属于待发区之后的送港线事实。容量不足导致甩柜时,由平台人工编辑原柜船名、航次和预计船期,保存原因、修改前后值、操作人和时间;柜子、订舱关联和原船期任务不变,不新建航次对象,也不重新生成报关批次或客户确认任务。
### 13.2 自动与人工确认离仓 ### 13.2 自动与人工确认离仓
报关完成或其他门禁变化时系统自动尝试收敛。未自动完成时,平台在柜次/国内出仓页面: 送港状态变化或其他送港门禁满足时系统自动尝试收敛。未自动完成时,平台在柜次/送港页面:
1. 打开门禁清单; 1. 打开门禁清单;
2. 逐项处理未通过原因; 2. 逐项处理未通过原因;
@@ -309,13 +318,13 @@ PDA 点击“完成装柜”时,服务端重新校验:
成功后系统: 成功后系统:
- 写入整柜唯一国内离仓事实; - 写入整柜唯一国内离仓事实;
- 创建 `CarrierScheduleQuery`;
- 写入实际 `DEPARTED_WAREHOUSE` 节点; - 写入实际 `DEPARTED_WAREHOUSE` 节点;
- 触发出仓后船节点查询; - 写入 `PORT_RECEIVED` 或 `ROLLED_OVER`;
- 维护船次和开船前等待,不把预计 ETD 记成海运在途;
- 检查并尝试完成订舱级拖车; - 检查并尝试完成订舱级拖车;
- 保持跨区交接事件可重试且不重复建单。 - 保持跨区交接事件可重试且不重复建单。
实际离仓节点产生后禁止撤销。发现错误转入线下和后续阶段异常处理,不提供修改历史伪装未离仓的能力。 实际离仓和进港节点产生后禁止撤销。发现错误转入线下和后续阶段异常处理,不提供修改历史伪装未离仓或未进港的能力。报关线的客户打回、重新发送和海关查验单独记录,不回滚送港事实。
## 14. 状态和动作总表 ## 14. 状态和动作总表
@@ -325,8 +334,11 @@ PDA 点击“完成装柜”时,服务端重新校验:
| 装柜计划 | `EDITING → LOADING → COMPLETED` | 预装调整/PDA 作业/最终完成 | | 装柜计划 | `EDITING → LOADING → COMPLETED` | 预装调整/PDA 作业/最终完成 |
| 订舱 | `DRAFT → RELEASED` | 补齐资料并放舱 | | 订舱 | `DRAFT → RELEASED` | 补齐资料并放舱 |
| 拖车 | 非终态 → `COMPLETED` | 所有要求柜次实际离仓后自动完成 | | 拖车 | 非终态 → `COMPLETED` | 所有要求柜次实际离仓后自动完成 |
| 报关 | 资料收集 → 已冻结办理中 → 已完成/放行 | 客户上传、平台开始、上传回执并完成 | | 柜级报关 | `WAITING_CUSTOMER_DOCUMENTS → READY_TO_START → DECLARING → COMPLETED` | 装柜后收集退税资料并首次发送;回执必须经对应客户确认,平台发送确认结果后等待所有真实完税文件 |
| 国内出仓 | 等待门禁 → 可出仓 → 已离仓 | 自动尝试或平台确认 | | 客户回执确认 | `PENDING → CONFIRMED / REJECTED` | 当前文件版本整份确认或填写原因打回;替换回执只重置对应客户范围,保留历史 |
| 正式申报与海关结果 | 批次、结果分别保存 | 平台人工正式提交、回填报关单号、标记查验/补资料/扣货/其他及人工处理,不改柜级报关四态和运输事实 |
| 送港 | `WAITING_FOR_LOADING → PORT_DELIVERY_PENDING → DEPARTED_WAREHOUSE → IN_TRANSIT_TO_PORT → PORT_RECEIVED / ROLLED_OVER` | 报关完成后进入待发区,再安排拖车和进港;容量不足时在原柜船期上人工修改船信息并留痕 |
| 海运 | `WAITING_SAILING → VESSEL_DEPARTED → IN_TRANSIT` | 只有承运船舶真实开航才进入海运节点 |
主状态只表达阶段结果。订舱、拖车、PDA、证据和报关保持关联子状态,页面应汇聚展示,但不能互相覆盖。 主状态只表达阶段结果。订舱、拖车、PDA、证据和报关保持关联子状态,页面应汇聚展示,但不能互相覆盖。
@@ -358,8 +370,11 @@ WAIT_SPLIT 入库单/已封托托盘
→ 预装确认/动态调整 → 预装确认/动态调整
→ PDA 实装 + 五类证据 → PDA 实装 + 五类证据
→ COMPLETED / LOADED + 数量分片 + 跨区快照 → COMPLETED / LOADED + 数量分片 + 跨区快照
→ 整柜报关放行 ├─ 报关线:通知报关 → 客户资料 → 报关行回执 → 客户确认/打回重做
→ 国内离仓 + DEPARTED_WAREHOUSE + 船节点查询任务 │ → 所有客户通过 → 整柜正式申报 → 查验/放行
└─ 送港线:拖车 → DEPARTED_WAREHOUSE → PORT_RECEIVED
→ 甩柜/改配(如发生)→ 等待实际开船
→ VESSEL_DEPARTED → 海运节点查询
``` ```
阶段完成必须同时满足: 阶段完成必须同时满足:
@@ -367,14 +382,14 @@ WAIT_SPLIT 入库单/已封托托盘
- [ ] 最终柜次、装柜计划、订舱、真实柜号关联可追溯 - [ ] 最终柜次、装柜计划、订舱、真实柜号关联可追溯
- [ ] 全部实装箱/托盘/SKU 与入库单数量守恒 - [ ] 全部实装箱/托盘/SKU 与入库单数量守恒
- [ ] PDA 任务完成且无未解决异常 - [ ] PDA 任务完成且无未解决异常
- [ ] 四步照片、铅封照片和铅封号完整有效 - [ ] 五类证据和锁码文本完整有效
- [ ] 装柜计划 `COMPLETED`,实装入库单 `LOADED` - [ ] 装柜计划 `COMPLETED`,实装入库单 `LOADED`
- [ ] 部分装载时已装子单和余量子单正确 - [ ] 部分装载时已装子单和余量子单正确
- [ ] 整柜报关已完成并放行 - [ ] 报关线按每个退税客户隔离资料和入仓码范围,回执、确认/打回及文件版本可追溯;完成文件覆盖全部退税范围
- [ ] 所有入库单无 HOLD - [ ] 送港线已记录唯一国内离仓历史;如已进港,存在 `PORT_RECEIVED`,如甩柜,存在原船次/改配船次历史
- [ ] 唯一国内离仓历史存在 - [ ] 客户全部确认后才允许整柜正式提交;正式申报后的查验/放行结果单独记录
- [ ] 第一条实际 `DEPARTED_WAREHOUSE` 存在 - [ ] 只有实际 `DEPARTED_ORIGIN_PORT` 才推进 F24海运中;离仓后唯一查询任务可预先建立,甩柜仍使用原任务
- [ ] 船节点查询任务和跨区事件可幂等重试 - [ ] 跨区事件可幂等重试;甩柜/改配只新增船期事实,不覆盖报关资料、回执和客户确认
## 17. 易用性与数据流评审问题 ## 17. 易用性与数据流评审问题
@@ -408,7 +423,7 @@ WAIT_SPLIT 入库单/已封托托盘
- `docs/国内货柜履约/README.md` - `docs/国内货柜履约/README.md`
- `docs/国内货柜履约/国内货柜履约页面与原型清单.md` - `docs/国内货柜履约/国内货柜履约页面与原型清单.md`
- `docs/头程下单到尾程出库现状流程全景清单.md` - `docs/归档/头程到尾程/头程下单到尾程出库现状流程全景清单.md`
- `docs/统一订单主状态与操作契约.md` - `docs/统一订单主状态与操作契约.md`
- `apps/admin-web/src/modules/container-loading/` - `apps/admin-web/src/modules/container-loading/`
- `apps/admin-web/src/modules/loading-lists/` - `apps/admin-web/src/modules/loading-lists/`
@@ -422,3 +437,4 @@ WAIT_SPLIT 入库单/已封托托盘
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/SmartLoadingService.java` - `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/SmartLoadingService.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/LoadingPickService.java` - `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/LoadingPickService.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/outbound/dispatch/service/OutboundDispatchService.java` - `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/outbound/dispatch/service/OutboundDispatchService.java`
@@ -574,7 +574,7 @@ Firstleg 正式入库单 + 稳定箱码
## 16. 事实来源 ## 16. 事实来源
- `docs/头程下单到尾程出库现状流程全景清单.md` - `docs/归档/头程到尾程/头程下单到尾程出库现状流程全景清单.md`
- `docs/入库测量与计费/README.md` - `docs/入库测量与计费/README.md`
- `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md` - `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md`
- `docs/统一订单主状态与操作契约.md` - `docs/统一订单主状态与操作契约.md`
@@ -590,3 +590,4 @@ Firstleg 正式入库单 + 稳定箱码
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/InitialInboundPricingService.java` - `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/InitialInboundPricingService.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/DropshipPalletizationService.java` - `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/DropshipPalletizationService.java`
- `baiyue-firstleg/firstleg/src/main/resources/openapi/dropship-palletization-v1.yaml` - `baiyue-firstleg/firstleg/src/main/resources/openapi/dropship-palletization-v1.yaml`
@@ -28,7 +28,7 @@
| 企业操作员 | Client | 查看本企业库存,发起换标、转运、废弃等自助服务 | 不查看其他客户或直接改实物托盘 | | 企业操作员 | Client | 查看本企业库存,发起换标、转运、废弃等自助服务 | 不查看其他客户或直接改实物托盘 |
| 换标作业员 | 海外 PDA | 认领、扫描旧/新标、拍照、提交复核 | 不自行批准复核或客户确认 | | 换标作业员 | 海外 PDA | 认领、扫描旧/新标、拍照、提交复核 | 不自行批准复核或客户确认 |
| 换标复核员 | Admin | 退回返工、核对作业事实 | 已由客户确认后不能退回 | | 换标复核员 | Admin | 退回返工、核对作业事实 | 已由客户确认后不能退回 |
| 废弃审核员 | Admin/PDA | 审批一件代发废弃并触发实际扣减 | 创建申请时不得直接扣库存 | | 废弃审核员 | Admin | 审批一件代发废弃,授权仓库执行 | 申请与审批均不扣库存;由海外 PDA 实际废弃确认时扣减 |
| Lastleg | 后端 | 入仓作业、库存业务、子单、状态和事件权威 | 不拥有物理仓/托盘主档 | | Lastleg | 后端 | 入仓作业、库存业务、子单、状态和事件权威 | 不拥有物理仓/托盘主档 |
| Warehouse Overseas | 后端 | 海外库位、实物托盘、资源锁和物理状态 | 不拥有库存客户归属和尾程订单 | | Warehouse Overseas | 后端 | 海外库位、实物托盘、资源锁和物理状态 | 不拥有库存客户归属和尾程订单 |
@@ -48,6 +48,8 @@
只要任一计划仍缺真实资源,就不能准备、签收或开始该柜。PDA 首次扫码只确认计划阶段已预留资源,不在现场重新分配托盘或库位。 只要任一计划仍缺真实资源,就不能准备、签收或开始该柜。PDA 首次扫码只确认计划阶段已预留资源,不在现场重新分配托盘或库位。
本地计划和托盘行已保存,不代表远端资源批次已确认。原柜级转换命令处于 `LOCAL_COMMITTED` 时,仅该命令冻结明细中的计划继续显示待资源确认,并计入平台可恢复的柜;同柜此前已确认的计划保持原状态。平台关闭重开后仍使用原幂等键、版本和摘要完成资源确认,不新建计划或预留;远端确认完成后才恢复已计划状态和PDA操作资格。读取预览不自动执行确认。
## 4. F28 海外 PDA 柜号签收 ## 4. F28 海外 PDA 柜号签收
### 4.1 查看待卸货柜 ### 4.1 查看待卸货柜
@@ -297,7 +299,15 @@ PDA 扫描托盘后按服务端返回的 `palletVersion`、`positionVersion` 执
4. 通过后冻结对应库存并进入转运出库; 4. 通过后冻结对应库存并进入转运出库;
5. 实际移出和目标收货按转运单、库存流水和资源操作闭环。 5. 实际移出和目标收货按转运单、库存流水和资源操作闭环。
转运状态保存在子单,不覆盖尾程主状态 `INBOUND_COMPLETED`。 既有库存转运的执行入口承载于 Admin 尾程订单详情中的“转运与换标履约”:来源分配完成且本票必要换标已获客户确认后,按执行权限确认出库;出库后按已发运未实收的来源选择目标海外收货仓、实际托盘及该托盘绑定的库位,逐笔确认目标仓实收。此入口与 PDA 来货转运测量、通用派送出库不同,不能以另一条状态链的按钮替代。
目标实收按本票已发运的来源位置逐笔进行。服务端核对真实海外收货仓、托盘绑定库位和冻结FBA目的仓,先保存原请求及摘要,再取得有效资源占用;同一转运的多个来源收到同一目标托盘时共享一次物理占用。资源服务已成功而本地库存事务失败时,保留原请求供原键原载荷恢复,不盲目释放、换键或更换目标。库存、收货凭据、来源状态及最终关联换标费用/结算命令在本地同一事务完成;原成功请求重放不重复入账、占用或收费,钱包最终结果由既有结算回执确认。
转运详情须提供本客户本票持久化的实收命令状态、原请求和权威目标。关闭重开或换浏览器后,未完成命令仍按原载荷继续;已完成命令的目标可供本票其他来源续收,不能仅因托盘为OCCUPIED而拒绝本票,也不能仅凭浏览器缓存将其他单据占用的托盘放行。出库未知结果先读取正式转运状态核对,不自动新建操作重复出库。
转运目标库存继续归属于该来源余额的真实入仓单ID、入仓单号及入仓码,不能使用转运尾程订单ID冒充入仓单身份。转运号作为本次操作和收货凭据的业务关联保留;目标海外仓、目的仓、托盘与库位取本次确认的权威资源。不同来源入仓单即使落入同一物理托盘,也应分别保留库存归属;后续库存选择与再次转运必须仍能解析合法的入仓来源。
转运状态保存在子单,不覆盖已经成立的尾程主状态 `INBOUND_COMPLETED`。既有库存转运须分别区分原来源尾程订单和本票独立转运尾程订单:原来源不因本次转运修改状态;本票在库存分配后已建立的INBOUND_COMPLETED也不能被换标回调的ALLOCATED、转运出库的IN_TRANSIT或转运实收的COMPLETED覆盖。具体转运进度由转运单及 `sub_order_status` 表达,此规则不替代后续真正的派送出库与签收主链。
### 9.5 一件代发货物废弃 ### 9.5 一件代发货物废弃
@@ -305,12 +315,13 @@ PDA 扫描托盘后按服务端返回的 `palletVersion`、`positionVersion` 执
1. 客户选择箱唛并创建申请; 1. 客户选择箱唛并创建申请;
2. 箱从 `AVAILABLE` 锁定为 `DISCARD_PENDING`,此时不扣 SKU 箱数; 2. 箱从 `AVAILABLE` 锁定为 `DISCARD_PENDING`,此时不扣 SKU 箱数;
3. 有 `lastleg:cargo-discard:approve` 权限的仓库/PDA 人员现场审核; 3. 平台由具有 `lastleg:cargo-discard:approve` 权限的人员审核;审核通过只批准作业,不提前扣库存;
4. 拒绝时只释放锁,不扣库存; 4. 拒绝时只释放锁,不扣库存;
5. 通过时在同一事务调用专用 discard adjustment; 5. 仓库/PDA人员确认实际废弃数量时,在同一事务调用专用 discard adjustment,确认即扣库存(2026-10-05用户确认);
6. 箱进入 `DISCARDED`,写逐箱流水和唯一幂等键; 6. 实际废弃的箱进入 `DISCARDED`,写逐箱流水和幂等事实;
7. 校验扣减前箱数减废弃箱数等于扣减后箱数,且逐箱合计等于申请总数; 7. 校验扣减前箱数减实际废弃箱数等于扣减后箱数,逐箱合计与实际确认总数一致;
8. 任一失败整体回滚。 8. 实际确认失败时扣减、状态及流水整体回滚;同单同托相同完整载荷重放不得重复扣减或追加完成历史,异数量拒绝;
9. 全部PDA作业完成后平台结案;结案及其重放不再次扣库存。审批驳回仍只释放锁。
## 10. 状态与数据归属 ## 10. 状态与数据归属
@@ -341,10 +352,12 @@ PDA 扫描托盘后按服务端返回的 `palletVersion`、`positionVersion` 执
| 暂扣票参与排车 | 服务端拒绝,先按权限解除 | | 暂扣票参与排车 | 服务端拒绝,先按权限解除 |
| 换标一项未完成 | 混合单不计整箱完成 | | 换标一项未完成 | 混合单不计整箱完成 |
| 换标被退回 | 展示备注,清理设备草稿后按新轮返工 | | 换标被退回 | 展示备注,清理设备草稿后按新轮返工 |
| 废弃审批失败 | 锁定和扣减整体回滚,不产生半套流水 | | 废弃实际确认失败 | 本次扣减、确认状态和流水整体回滚,不产生半套流水;审批不提前扣减 |
## 12. 阶段完成判定 ## 12. 阶段完成判定
测试环境综合证据 `baiyue-firstleg/reports/admin-full-postdeploy-66c2651b.json` 已覆盖海外 PDA、收货、库存、库内服务和 `phase5-overseas-fulfillment`;上述模块失败数均为 0。这里的清单继续保留为逐票验收条件,不能用综合报告替代具体柜次的业务核对。
主链完成必须满足: 主链完成必须满足:
- [ ] 柜号由正确仓库操作员认领 - [ ] 柜号由正确仓库操作员认领
@@ -73,6 +73,8 @@ PDA 只调用 `/api/pda/**` 专用接口,客户和仓库由 Token、Gateway
6. 草稿锁原子转换为正式排车锁; 6. 草稿锁原子转换为正式排车锁;
7. 生成排车单,初始为 `PENDING_DEPARTURE`。 7. 生成排车单,初始为 `PENDING_DEPARTURE`。
普通智能预排按界面非空装车容器分组,一次提交整份草稿;服务端核对每组容器归属、当前托盘锁、唯一客户/海外仓及托位容量,逐组生成独立排车单和PDA任务。任一组失败时整批回滚,不能先成功一组再把其余组隐藏。相同分组重新提交返回各自对应原单,不重复创建或将不同容器合并;空容器不产生排车。单张排车接口不得接收多个草稿容器混合的平铺托盘数组。换标仍按其单张申请的完整量排车,多容器选择必须明确拒绝,不能静默合并。
路线由已排托盘目的仓编码去重并稳定排序生成,预排和普通编辑都不接收人工路线文本。 路线由已排托盘目的仓编码去重并稳定排序生成,预排和普通编辑都不接收人工路线文本。
### 4.3 排车编辑和取消 ### 4.3 排车编辑和取消
@@ -81,6 +83,8 @@ PDA 只调用 `/api/pda/**` 专用接口,客户和仓库由 Token、Gateway
未执行、未产生不可逆拣货事实的排车可取消并释放正式锁。开始拣货后不能用取消恢复库存或抹掉作业历史。 未执行、未产生不可逆拣货事实的排车可取消并释放正式锁。开始拣货后不能用取消恢复库存或抹掉作业历史。
取消后保留原排车明细作为历史;入库单的排车状态及“已排车/未排车”筛选只计入同客户、同来源订单的未取消排车。若没有其他有效排车,显示未排车并可重新排车;存在替代排车或已发车、已完成的排车时仍显示已排车。列表与分页总数采用同一判断,不以历史明细存在代替当前排车状态。
## 5. F35 排车转派送 ## 5. F35 排车转派送
允许状态:`PENDING_DEPARTURE`、`PICKING`、`READY_TO_DEPART`,且必须早于发车。 允许状态:`PENDING_DEPARTURE`、`PICKING`、`READY_TO_DEPART`,且必须早于发车。
@@ -213,7 +217,7 @@ Admin/Client 按权限查看拆分后的单仓派送单、目的地、车辆/快
### 10.2 跨区完成事件 ### 10.2 跨区完成事件
每张实际完成的派送单在业务事务内写 Outbox。Event Bridge 跨区投递后,Firstleg: 每张实际完成的派送单在业务事务内写 Outbox。Lastleg Relay 按[统一认证与服务通信契约](../统一认证与服务通信契约.md)直接投递 Firstleg 内部消费者;只有匹配原事件 ID、Payload 哈希和允许结果的持久化消费 ACK 才记为投递成功。Firstleg:
1. 校验内部身份、事件版本、ID 和 Payload 哈希; 1. 校验内部身份、事件版本、ID 和 Payload 哈希;
2. 校验来源订单、来源入仓单、入仓码和 FBA 目的仓; 2. 校验来源订单、来源入仓单、入仓码和 FBA 目的仓;
@@ -223,7 +227,13 @@ Admin/Client 按权限查看拆分后的单仓派送单、目的地、车辆/快
### 10.3 Order 最终完成 ### 10.3 Order 最终完成
Firstleg 检查同一 Order 的全部有效入库单。只有全部都为 `DELIVERED` 时,才调用 Order 推进交易状态为 `COMPLETED`。 Firstleg 检查同一来源 Order 的全部有效入库单。只有全部都为 `DELIVERED` 时,才向 Order 回写该来源单的签收完成事实,并携带真实履约根订单。
余量拆分后,根订单仍承载自身第一批实装货物,子订单分别承载余量。子订单可独立完成;根订单只有自身实装货物已经签收,且全部未删除、未取消的子订单均为 `COMPLETED` 时,才进入 `COMPLETED`。仅明确 `CANCELLED` 的子单排除,草稿、待审核或其他未完成状态均阻断根订单收口。最后余量取消也重新计算根完成条件。来源单签收事实和根最终完成历史分开保存,不能用子单完成代替根自身签收。
Order 在同一事务内写完成状态、历史和完成 Outbox,经内部接口可靠同步 Firstleg 订单状态摘要。来源单与根的状态分别返回,根尚未完成时不得把根摘要提前标成完成。
平台不提供人工完成订单接口。普通订单状态操作不得直接设置 `COMPLETED`,完成状态只能由真实签收回写及符合上述门禁的取消后聚合产生,不能绕过仍有效的余量子单。
部分装载形成的余量子单、另一柜或另一目的仓尚未完成时,Order 不能提前完成。重复事件不得重复推进、重复写历史或重复生成费用。 部分装载形成的余量子单、另一柜或另一目的仓尚未完成时,Order 不能提前完成。重复事件不得重复推进、重复写历史或重复生成费用。
@@ -264,6 +274,8 @@ INBOUND_COMPLETED + 可用库存
## 13. 全流程最终完成判定 ## 13. 全流程最终完成判定
测试环境综合证据 `baiyue-firstleg/reports/admin-full-postdeploy-66c2651b.json` 已覆盖 `phase4-overseas-dispatch`、`phase5-terminal-drayage`、`phase5-overseas-fulfillment`、客户服务和跨区回写模块,相关模块失败数均为 0。清单仍按具体派送单保留,最终上线前需要用业务柜次逐项复核。
- [ ] 排车候选来自真实、可用且未被其他业务占用的库存 - [ ] 排车候选来自真实、可用且未被其他业务占用的库存
- [ ] 草稿锁、正式锁和取消/完成释放均可追溯 - [ ] 草稿锁、正式锁和取消/完成释放均可追溯
- [ ] 排车路线由实际目的地生成 - [ ] 排车路线由实际目的地生成
@@ -1,7 +1,7 @@
# 阶段四:海运、目的港与尾程入仓计划 # 阶段四:海运、目的港与尾程入仓计划
> 对应全景流程:F24~F27。 > 对应全景流程:F24~F27。
> 阶段起点:柜次已确认国内离仓,存在实际 `DEPARTED_WAREHOUSE` 节点和可查询的真实订舱/柜次。 > 阶段起点:柜次已完成送港/进港或甩柜处理,并产生承运船舶实际 `VESSEL_DEPARTED`/`DEPARTED_ORIGIN_PORT` 节点;真实 `DEPARTED_WAREHOUSE` 和 `PORT_RECEIVED` 属于阶段三送港线事实。
> 阶段终点:跨区尾程订单完整生成,整柜每票入仓计划及托盘/库位资源已生成或有明确资源失败待办,订单进入 `INBOUND_PLANNED`。 > 阶段终点:跨区尾程订单完整生成,整柜每票入仓计划及托盘/库位资源已生成或有明确资源失败待办,订单进入 `INBOUND_PLANNED`。
> 本阶段同时维护船舶/货柜轨迹和尾程业务准备,但两类状态不得互相冒充。 > 本阶段同时维护船舶/货柜轨迹和尾程业务准备,但两类状态不得互相冒充。
@@ -9,7 +9,7 @@
本阶段完成四条相互关联但独立的链路: 本阶段完成四条相互关联但独立的链路:
1. 从国内离仓开始查询并保存十个标准船节点; 1. 从承运船舶实际开航开始查询并保存十个标准船节点;
2. 管理目的港清关、海外码头车队、提柜、预计到仓和还空; 2. 管理目的港清关、海外码头车队、提柜、预计到仓和还空;
3. 将国内最终实装快照可靠投递到海外区域并创建尾程订单; 3. 将国内最终实装快照可靠投递到海外区域并创建尾程订单;
4. 按整柜维护每票计划并转换为可执行的海外入仓计划和资源。 4. 按整柜维护每票计划并转换为可执行的海外入仓计划和资源。
@@ -26,18 +26,18 @@
| 企业成员 | Client | 查看本企业尾程订单和允许展示的船期/计划进度 | | 企业成员 | Client | 查看本企业尾程订单和允许展示的船期/计划进度 |
| Firstleg | 后端 | 拥有查询任务、标准节点、目的港码头拖车和装柜完成 Outbox | | Firstleg | 后端 | 拥有查询任务、标准节点、目的港码头拖车和装柜完成 Outbox |
| Integration Service | 后端 | 调用船司/轨迹供应商,解析并返回标准化结果,不保存业务主数据 | | Integration Service | 后端 | 调用船司/轨迹供应商,解析并返回标准化结果,不保存业务主数据 |
| Event Bridge | 跨区通道 | 版本化、认证地投递业务事件 | | 业务服务 Outbox Relay | 内部直接投递 | 按事件类型选择消费者,验证事件身份、摘要和持久化消费 ACK,有限重试与受保护人工恢复 |
| Lastleg | 海外后端 | Inbox 幂等消费、尾程订单、计划、在途库存和海外业务状态 | | Lastleg | 海外后端 | Inbox 幂等消费、尾程订单、计划、在途库存和海外业务状态 |
| Warehouse | 国内主数据 | 海外共享仓、FBA 目的仓和供应商主档权威 | | Warehouse | 国内主数据 | 海外共享仓、FBA 目的仓和供应商主档权威 |
| Warehouse Overseas | 海外资源 | 海外库位、实物托盘和资源锁 | | Warehouse Overseas | 海外资源 | 海外库位、实物托盘和资源锁 |
所有浏览器海外接口经 `gateway-overseas/`。国内 Auth 仍是账号和 Token 签发方;跨区业务写入通过内部身份、Inbox/Outbox 和事件契约完成,不允许浏览器伪造跨区事件。 所有浏览器接口经统一 `gateway/`,Auth 是唯一账号、Token 和会话权威。业务服务保持各自数据归属和客户隔离;服务间写入通过内部身份、Inbox/Outbox 和事件契约直接投递,不允许浏览器伪造服务间事件。现行投递和结果确认规则见[统一认证与服务通信契约](../统一认证与服务通信契约.md)。
## 3. 阶段前置检查 ## 3. 阶段前置检查
- 柜次存在真实集装箱号、订舱、提单号和国内离仓事实; - 柜次存在真实集装箱号、订舱、提单号、送港/进港事实和实际开船节点;
- 装柜完成事件包含最终实装订单、入仓单、目的类型、箱数及必要托盘/SKU/箱唛快照; - 装柜完成事件包含最终实装订单、入仓单、目的类型、箱数及必要托盘/SKU/箱唛快照;
- 国内四步照片和铅封证据已经冻结; - 国内五类装柜证据和锁码文本已经冻结;
- 接柜海外仓是 Warehouse 中 `ACTIVE + OVERSEAS + RECEIVING` 的平台共享物理仓; - 接柜海外仓是 Warehouse 中 `ACTIVE + OVERSEAS + RECEIVING` 的平台共享物理仓;
- FBA 目的仓是 Warehouse 有效公共主档,不能用接柜仓或国内仓代替; - FBA 目的仓是 Warehouse 有效公共主档,不能用接柜仓或国内仓代替;
- 船司/轨迹查询标识足以唯一指向目标订舱和柜次; - 船司/轨迹查询标识足以唯一指向目标订舱和柜次;
@@ -47,9 +47,11 @@
### 4.1 查询任务创建 ### 4.1 查询任务创建
国内出仓确认事务幂等创建 `CarrierScheduleQuery`。任务必须绑定真实订舱、柜次以及可用的船司、船名航次、提单号或柜号,不创建脱离业务单据的孤立轮询任务。 确认国内离仓后,系统按订舱与柜次幂等建立唯一 `CarrierScheduleQuery`,触发来源为 `OUTBOUND_CONFIRM`,用于后续送港和船节点查询。任务必须绑定真实订舱、柜次以及可用的船司、船名航次、提单号或柜号,不创建脱离业务单据的孤立任务。任务已建立不表示船舶已开航;只有实际 `DEPARTED_ORIGIN_PORT` 事实才能推进 F24“海运中”,不能用预计 ETD 或查询任务存在提前推进。
首个实际节点由国内出仓写入: 标准节点保留国内送港事实,但海运查询的起点是实际开船:
`DEPARTED_WAREHOUSE`、`AT_ORIGIN_PORT` 和 `LOADED_ON_VESSEL` 可以作为送港/装船历史记录,查询任务也可收集开航前的实际港口事实。客户的“海运中”节点以真实 `DEPARTED_ORIGIN_PORT` 为起点。甩柜时人工编辑原柜船信息并保留历史,继续使用原任务,不因改船或预计日期生成实际开航事实。
```text ```text
10 DEPARTED_WAREHOUSE 已离开国内仓 10 DEPARTED_WAREHOUSE 已离开国内仓
@@ -187,9 +189,9 @@ Firstleg 在装柜完成后按最终实装生成 `FIRST_LEG_LOADING_PLAN_COMPLET
Outbox 可重复投递,不能因网络失败直接丢事件或在事务外临时拼装 Payload。 Outbox 可重复投递,不能因网络失败直接丢事件或在事务外临时拼装 Payload。
### 6.2 Event Bridge 投递 ### 6.2 Outbox 直接投递
Event Bridge 校验允许的事件类型、版本、来源/目标区域和内部服务身份后投递 Lastleg。IAM 安全事件使用独立入口,不能交给装柜完成消费者。 Firstleg 的 Outbox Relay 将装柜完成和船节点事件直接投递 Lastleg 的内部消费者,保留原事件 ID、版本和 Payload 哈希。只有持久化消费 ACK 的身份、摘要和允许的结果全部匹配才记录投递成功;临时故障按有限退避重试,耗尽后进入 DEAD,由受保护运维入口审计后重试原事件。重复消费不能重复建单;同一事件 ID、不同摘要必须拒绝。IAM 安全事件不能交给装柜完成消费者。
### 6.3 Lastleg Inbox 消费 ### 6.3 Lastleg Inbox 消费
@@ -219,6 +221,13 @@ Lastleg 消费步骤:
## 7. F27 尾程计划维护和整柜转换 ## 7. F27 尾程计划维护和整柜转换
### 7.0 尾程订单列表页签
- 页签固定为“全部、开船前、开船后”。“全部”保留所有订单类型;后两个页签仅包含国内头程订单(`orderType=FIRST_LEG`,不再额外以内部来源字段限制)。一件代发、换标、仓储转运、本土散板、退货及废弃等其他类型只在“全部”展示。
- “开船后”依据实际柜级船节点序号达到 40(实际离开起运港)及后续节点;只有预计开船、装船或尚无实际节点仍归“开船前”。订单启用人工节点覆盖后,仅按该票 `ACTUAL_DEPARTURE` 是否有时间判断,不回退柜级节点。
- 船阶段筛选不改变订单主状态或排车、排约等操作资格;状态筛选继续独立生效。服务端在分页前过滤,列表总数及导出使用相同口径;客户端不按当前页记录二次筛选。
- 按柜批量生成入库计划入口在三个页签保留,仍使用全柜预览和原计划门禁,不将船阶段视为生成计划的资格。
### 7.1 柜级工作台 ### 7.1 柜级工作台
入口:Admin → 海外仓 → 尾程订单 → 柜级工作台。 入口:Admin → 海外仓 → 尾程订单 → 柜级工作台。
@@ -292,6 +301,8 @@ Lastleg 消费步骤:
整批转换原子且幂等:相同命令重放不生成第二批计划或资源;本地失败只补偿尚未确认的远端资源;远端确认失败的重放只重试确认。 整批转换原子且幂等:相同命令重放不生成第二批计划或资源;本地失败只补偿尚未确认的远端资源;远端确认失败的重放只重试确认。
资源确认失败后,即使关闭弹框或刷新页面,也必须恢复原柜级命令。预览在 `LOCAL_COMMITTED` 时额外返回 `resourceRetry`,包含原 `idempotencyKey`、`snapshotVersion` 和 `snapshotHash`;页面用这一整组原值重试。外层快照与分组继续反映当前计划状态,用于展示,不能替换恢复命令的快照。其他命令状态不返回该恢复字段;缺少原重试依据时拒绝操作,不新建命令、计划或第二批资源。此字段不改变服务端“同键不同载荷拒绝”的规则。
## 8. 状态、编号与数据归属 ## 8. 状态、编号与数据归属
| 维度 | 关键状态/编号 | 权威系统 | | 维度 | 关键状态/编号 | 权威系统 |
@@ -327,6 +338,8 @@ Lastleg 消费步骤:
## 10. 阶段完成判定 ## 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`。
- [ ] 国内离仓产生的船节点任务绑定真实订舱和柜次 - [ ] 国内离仓产生的船节点任务绑定真实订舱和柜次
- [ ] 节点预计/实际/观测时间没有混用 - [ ] 节点预计/实际/观测时间没有混用
- [ ] 异常事实与正常节点分开保存 - [ ] 异常事实与正常节点分开保存
@@ -1,172 +0,0 @@
# 头程到尾程逐节点思维导图
2026年9月22日 · 人工梳理与分工版
按实际业务节点编号,不限定阶段或步数。展开每个节点查看负责人、正常去向、异常处理和特殊分支。
岗位为建议分工,姓名留空待填;异常转交路径供人工确认。编号用于讨论定位,可并行或提前的动作以节点说明为准。
标记“待确认”的处理入口或完结规则,需要人工补充,不能当作已具备的系统能力。
思维导图源文件:[头程到尾程逐节点思维导图.mm](头程到尾程逐节点思维导图.mm)。可在支持 FreeMind 格式的软件中导入,填写姓名、增删节点。
新增步骤可沿用相邻编号加字母,例如 04A。详细依据保留在[原梳理文档](头程柜级履约尾程流程节点责任与异常梳理.md)。
- **01 客户下单**
- 负责人:客户下单员 · 姓名____
- 正常:提交订单 → 02 审核;同时安排 03 送仓。
- 异常:资料缺失/下单失败 → 客服协助客户补正 → 重新提交。
- **02 订单审核**
- 负责人:订单审核员 · 姓名____
- 正常:审核通过;与 03—05 可并行,06 测量审核通过前须完成本步。
- 异常:申报/渠道有误 → 审核员联系客户补正 → 重新审核。
- **03 拉货/客户送仓**
- 负责人:国内提货跟单 · 姓名____
- 正常:上门拉货或客户自送 → 04 到仓收货。
- 异常:未备货/迟到/运输破损 → 提货跟单联系客户、司机 → 改约或补交接记录。
- 说明:拉货执行、司机交接的现场规则待补充;当前系统主要记录预约信息。
- **04 国内到仓收货**
- 负责人:国内收货员 · 姓名____
- 正常:核对订单、箱数、外包装 → 05 称重测量。
- 异常:无单/少件/多件/破损 → 收货员留证,仓库主管与客服核对 → 明确收货处理后交测量。
- **05 称重测量**
- 负责人:国内测量员 · 姓名____
- 正常:采集重量、尺寸、箱数和图片 → 06 测量审核;称重确认时开始分配库位。
- 异常:漏测/错码/读数异常 → 测量员复测补证 → 重新提交审核。
- **06 测量审核**
- 负责人:测量审核员 · 姓名____
- 正常:普通货审核通过 → 07 在库交接 → 08 排柜;一件代发另走下方分支。
- 异常:数据/证据存疑 → 审核员联系测量员复核 → 再审;退回修改入口待确认。
- **06A 一件代发拆箱清点**
- 负责人:国内清点员 · 姓名____
- 正常:按箱核对 SKU 与数量 → 06B 归托封托。
- 异常:差异 → 仓库主管、客服核对;接受差异须留原因,接受权限待定。
- **06B 打托/归托/封托**
- 负责人:国内打托员 · 姓名____
- 正常:清点完成、封托完成 → 08 排柜;封托托盘作为不可拆分单元。
- 异常:漏清点/托盘未封 → 国内仓主管安排补作业 → 封托后继续。
- **07 国内入库/库位确认**
- 负责人:国内仓管 · 姓名____
- 正常:确认货物所在库位和交接信息 → 08 排柜;库位安排随 05 开始,本步核对在库结果。
- 异常:库位不足/货位不符 → 国内仓主管落实存放位置并核对记录 → 交接后继续。
- **08 排柜/分柜**
- 负责人:柜务 · 姓名____
- 正常:确定本柜装哪些货 → 11 国内拣货;可与 09 订舱准备并行。
- 异常:超容/扣货/审核未完成 → 柜务协调仓库、审核员 → 调整计划或解除阻断后再拣货。
- 说明:待审核、待测量可先占位;实物作业须满足审核、清点封托等条件。
- **09 订舱/放舱**
- 负责人:船务 · 姓名____
- 正常:确认舱位、船期和放舱资料 → 10 国内拖柜。
- 异常:无舱/甩柜/船期调整 → 船务协调船司、柜务 → 确认新船期及装柜安排。
- **10 国内拖柜:预约、提柜到仓**
- 负责人:国内运输跟单 · 姓名____
- 正常:订舱已放舱、资料齐全后预约;司机提空柜到国内仓 → 12 装柜。
- 异常:车不到/柜不可用/资料缺失 → 运输跟单联络车队、船务 → 补资料或重新安排。
- **11 国内拣货**
- 负责人:国内拣货员 · 姓名____
- 正常:按装柜计划找到货物、扫码核对 → 12 装柜。
- 异常:找不到/错货/少件/扣货 → 国内仓主管与柜务核对 → 补拣、调整计划或解除阻断。
- **12 装柜完成**
- 负责人:国内装柜主管 · 姓名____
- 正常:核对实装、柜号和装柜证据 → 13 出口报关;同时开始海外接柜准备。
- 异常:实装不符/装不下/证据缺失 → 装柜主管与柜务核实 → 调整、补证后确认完成。
- **12A 海外接柜准备**
- 负责人:海外计划员 · 姓名____
- 正常:装柜完成后系统生成尾程订单 → 人工准备入仓计划、托盘与库位 → 18 拆柜收货。
- 异常:订单未同步/计划或资源缺失 → 计划员联系履约运营、仓库主管补齐;系统失败转技术处理。
- **13 出口报关**
- 负责人:出口报关专员 · 姓名____
- 正常:装柜完成后处理整柜报关、收齐完成资料 → 14 国内出仓。
- 异常:资料缺失/退单/查验 → 报关专员联系客户、代理 → 补正或配合查验,完成后继续。
- **14 国内出仓**
- 负责人:国内出仓员 · 姓名____
- 正常:报关完成且出仓条件齐备 → 确认离仓,交 15 海运跟踪。
- 异常:报关未完成/扣货/交接不符 → 出仓员暂停放行,联系对应主责 → 条件满足后出仓。
- **15 海运/到港跟踪**
- 负责人:船务 · 姓名____
- 正常:跟踪开船、到港、卸船 → 与 16 清关、17 提柜衔接。
- 异常:延误/改港/节点未更新 → 船务核实船司消息 → 更新计划并交客服通知客户。
- **16 目的港清关**
- 负责人:海外清关专员 · 姓名____
- 正常:可提前备资料;确认清关放行和提柜条件 → 17 海外提柜。
- 异常:补件/查验/未放行 → 清关专员联系代理、客户 → 处理并确认可提柜后继续。
- **17 海外提柜/送仓**
- 负责人:海外运输跟单 · 姓名____
- 正常:预约港口提柜、协调海外仓接收 → 18 拆柜收货。
- 异常:无车/提柜失败/仓库约不上 → 海外运输跟单协调港口、车队、仓库 → 改约并跟进额外费用。
- **18 海外拆柜收货**
- 负责人:海外收货员 · 姓名____
- 正常:按入仓计划扫描、清点、记录实收 → 无差异时交 19 入库。
- 异常:短收/超收 → 海外仓主管登记差异、留证 → 待核平;可结束卸柜,但不能直接成为可用库存,核平入口待确认。
- **18A 卸柜后还空柜**
- 负责人:海外运输跟单 · 姓名____
- 正常:卸柜结束 → 安排还空并记录凭证;与后续库存、出库流程并行。
- 异常:还空受阻/临近截止 → 海外运输跟单联系车队、堆场 → 调整还空安排并跟进费用。
- **19 海外入库/库位确认**
- 负责人:海外仓管 · 姓名____
- 正常:正常收货形成库存,核对真实托盘、库位和可用数量 → 20 排车。
- 异常:库位不符/暂扣/数量仍有差异 → 海外仓主管核实 → 满足可用条件后再交拣货。
- **19A 一件代发独立出库**
- 负责人:一件代发运营 · 姓名____
- 正常:按独立出库单逐箱或整托拣货,核对 SKU 与数量后出库;签收、回访和整单完结衔接待确认。
- 异常:缺货/错 SKU/数量不符 → 代发运营与海外仓核对 → 补货或调整后再出库。
- **20 海外排车**
- 负责人:海外调度 · 姓名____
- 正常:确定车辆、路线、目的地与货物 → 21 转派送、22 拣货;可提前预排,实际拣货须有可用库存。
- 异常:无车/预约冲突/库存不足 → 海外调度协调仓库、车队 → 调整排车与交付安排。
- **21 转派送/生成待出库单**
- 负责人:海外调度 · 姓名____
- 正常:生成派送关联和待出库单 → 23 发车前核对;可在 22 拣货前或过程中进行,必须早于 24 发车。
- 异常:资料缺失/生成失败 → 海外调度补齐资料、核实关联 → 成功后才能发车。
- **22 按排车拣货**
- 负责人:海外拣货员 · 姓名____
- 正常:按排车任务、托盘与库位扫描拣货 → 23 核平复核。
- 异常:少货/错托/暂扣/货位不符 → 海外仓主管核查 → 补拣或协调调度调整。
- **23 拣货核平/发车前复核**
- 负责人:海外仓主管 · 姓名____
- 正常:核对实拣、出库单、车辆及必需资料 → 条件齐备交 24 发车。
- 异常:数量未核平/单据缺失 → 海外仓主管联系拣货员、调度补齐 → 复核无误后继续。
- 说明:此处是作业检查节点,不表示另设一项系统审批。
- **24 发车/确认出库**
- 负责人:海外出库员 · 姓名____
- 正常:按系统可发车条件确认发车、完成出库 → 25 派送签收;调度负责车辆交接。
- 异常:系统阻断/司机未到/交接不符 → 出库员暂停,海外调度协调处理 → 满足条件后发车。
- **25 派送/签收**
- 负责人:派送运营 · 姓名____
- 正常:送达、保存有效签收资料 → 26 整单完结核对;同时进入 27 客户回访。
- 异常:拒签/送达失败 → 派送运营登记异常 → 退回时按实收恢复到真实托盘、库位 → 另行安排后续;不按正常签收完结。
- **26 整单完结**
- 负责人:履约运营 · 姓名____
- 正常:全部有效履约片段完成后,系统汇总整单完结;履约运营核对结果。
- 异常:还有余货/其他柜未完成/回传失败 → 履约运营追踪对应环节,系统故障转技术 → 齐备后完结。
- 说明:27 回访独立进行;财务结清另行核对。
- **27 客户回访**
- 负责人:客服 · 姓名____
- 正常:普通派送签收后回访,记录反馈、处理结果和附件;与 26 整单完结核对并行。
- 异常:联系不上/投诉/索赔 → 客服持续跟进,交对应业务主管处理 → 反馈客户并补回访记录。
@@ -1,178 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<map version="1.0.1">
<node TEXT="头程 → 柜子 → 尾程|逐节点流程" ID="logistics-process" FOLDED="false">
<richcontent TYPE="NOTE">
<html>
<body>
<p>按实际业务节点编号,不限定阶段或步数。展开每个节点查看负责人、正常去向、异常处理和特殊分支。</p>
<p>岗位为建议分工,姓名留空待填;异常转交路径供人工确认。编号用于讨论定位,可并行或提前的动作以节点说明为准。</p>
<p>标记“待确认”的处理入口或完结规则,需要人工补充,不能当作已具备的系统能力。</p>
</body>
</html>
</richcontent>
<node TEXT="01 客户下单|客户下单员" ID="step-01" FOLDED="true" POSITION="right">
<node TEXT="负责人:客户下单员 · 姓名____" />
<node TEXT="正常:提交订单 → 02 审核;同时安排 03 送仓。" />
<node TEXT="异常:资料缺失/下单失败 → 客服协助客户补正 → 重新提交。" />
</node>
<node TEXT="02 订单审核|订单审核员" ID="step-02" FOLDED="true" POSITION="right">
<node TEXT="负责人:订单审核员 · 姓名____" />
<node TEXT="正常:审核通过;与 03—05 可并行,06 测量审核通过前须完成本步。" />
<node TEXT="异常:申报/渠道有误 → 审核员联系客户补正 → 重新审核。" />
</node>
<node TEXT="03 拉货/客户送仓|国内提货跟单" ID="step-03" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内提货跟单 · 姓名____" />
<node TEXT="正常:上门拉货或客户自送 → 04 到仓收货。" />
<node TEXT="异常:未备货/迟到/运输破损 → 提货跟单联系客户、司机 → 改约或补交接记录。" />
<node TEXT="说明:拉货执行、司机交接的现场规则待补充;当前系统主要记录预约信息。" />
</node>
<node TEXT="04 国内到仓收货|国内收货员" ID="step-04" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内收货员 · 姓名____" />
<node TEXT="正常:核对订单、箱数、外包装 → 05 称重测量。" />
<node TEXT="异常:无单/少件/多件/破损 → 收货员留证,仓库主管与客服核对 → 明确收货处理后交测量。" />
</node>
<node TEXT="05 称重测量|国内测量员" ID="step-05" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内测量员 · 姓名____" />
<node TEXT="正常:采集重量、尺寸、箱数和图片 → 06 测量审核;称重确认时开始分配库位。" />
<node TEXT="异常:漏测/错码/读数异常 → 测量员复测补证 → 重新提交审核。" />
</node>
<node TEXT="06 测量审核|测量审核员" ID="step-06" FOLDED="true" POSITION="right">
<node TEXT="负责人:测量审核员 · 姓名____" />
<node TEXT="正常:普通货审核通过 → 07 在库交接 → 08 排柜;一件代发另走下方分支。" />
<node TEXT="异常:数据/证据存疑 → 审核员联系测量员复核 → 再审;退回修改入口待确认。" />
<node TEXT="06A 一件代发拆箱清点|国内清点员" ID="step-06A" FOLDED="true">
<node TEXT="负责人:国内清点员 · 姓名____" />
<node TEXT="正常:按箱核对 SKU 与数量 → 06B 归托封托。" />
<node TEXT="异常:差异 → 仓库主管、客服核对;接受差异须留原因,接受权限待定。" />
</node>
<node TEXT="06B 打托/归托/封托|国内打托员" ID="step-06B" FOLDED="true">
<node TEXT="负责人:国内打托员 · 姓名____" />
<node TEXT="正常:清点完成、封托完成 → 08 排柜;封托托盘作为不可拆分单元。" />
<node TEXT="异常:漏清点/托盘未封 → 国内仓主管安排补作业 → 封托后继续。" />
</node>
</node>
<node TEXT="07 国内入库/库位确认|国内仓管" ID="step-07" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内仓管 · 姓名____" />
<node TEXT="正常:确认货物所在库位和交接信息 → 08 排柜;库位安排随 05 开始,本步核对在库结果。" />
<node TEXT="异常:库位不足/货位不符 → 国内仓主管落实存放位置并核对记录 → 交接后继续。" />
</node>
<node TEXT="08 排柜/分柜|柜务" ID="step-08" FOLDED="true" POSITION="right">
<node TEXT="负责人:柜务 · 姓名____" />
<node TEXT="正常:确定本柜装哪些货 → 11 国内拣货;可与 09 订舱准备并行。" />
<node TEXT="异常:超容/扣货/审核未完成 → 柜务协调仓库、审核员 → 调整计划或解除阻断后再拣货。" />
<node TEXT="说明:待审核、待测量可先占位;实物作业须满足审核、清点封托等条件。" />
</node>
<node TEXT="09 订舱/放舱|船务" ID="step-09" FOLDED="true" POSITION="right">
<node TEXT="负责人:船务 · 姓名____" />
<node TEXT="正常:确认舱位、船期和放舱资料 → 10 国内拖柜。" />
<node TEXT="异常:无舱/甩柜/船期调整 → 船务协调船司、柜务 → 确认新船期及装柜安排。" />
</node>
<node TEXT="10 国内拖柜:预约、提柜到仓|国内运输跟单" ID="step-10" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内运输跟单 · 姓名____" />
<node TEXT="正常:订舱已放舱、资料齐全后预约;司机提空柜到国内仓 → 12 装柜。" />
<node TEXT="异常:车不到/柜不可用/资料缺失 → 运输跟单联络车队、船务 → 补资料或重新安排。" />
</node>
<node TEXT="11 国内拣货|国内拣货员" ID="step-11" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内拣货员 · 姓名____" />
<node TEXT="正常:按装柜计划找到货物、扫码核对 → 12 装柜。" />
<node TEXT="异常:找不到/错货/少件/扣货 → 国内仓主管与柜务核对 → 补拣、调整计划或解除阻断。" />
</node>
<node TEXT="12 装柜完成|国内装柜主管" ID="step-12" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内装柜主管 · 姓名____" />
<node TEXT="正常:核对实装、柜号和装柜证据 → 13 出口报关;同时开始海外接柜准备。" />
<node TEXT="异常:实装不符/装不下/证据缺失 → 装柜主管与柜务核实 → 调整、补证后确认完成。" />
<node TEXT="12A 海外接柜准备|海外计划员" ID="step-12A" FOLDED="true">
<node TEXT="负责人:海外计划员 · 姓名____" />
<node TEXT="正常:装柜完成后系统生成尾程订单 → 人工准备入仓计划、托盘与库位 → 18 拆柜收货。" />
<node TEXT="异常:订单未同步/计划或资源缺失 → 计划员联系履约运营、仓库主管补齐;系统失败转技术处理。" />
</node>
</node>
<node TEXT="13 出口报关|出口报关专员" ID="step-13" FOLDED="true" POSITION="right">
<node TEXT="负责人:出口报关专员 · 姓名____" />
<node TEXT="正常:装柜完成后处理整柜报关、收齐完成资料 → 14 国内出仓。" />
<node TEXT="异常:资料缺失/退单/查验 → 报关专员联系客户、代理 → 补正或配合查验,完成后继续。" />
</node>
<node TEXT="14 国内出仓|国内出仓员" ID="step-14" FOLDED="true" POSITION="right">
<node TEXT="负责人:国内出仓员 · 姓名____" />
<node TEXT="正常:报关完成且出仓条件齐备 → 确认离仓,交 15 海运跟踪。" />
<node TEXT="异常:报关未完成/扣货/交接不符 → 出仓员暂停放行,联系对应主责 → 条件满足后出仓。" />
</node>
<node TEXT="15 海运/到港跟踪|船务" ID="step-15" FOLDED="true" POSITION="right">
<node TEXT="负责人:船务 · 姓名____" />
<node TEXT="正常:跟踪开船、到港、卸船 → 与 16 清关、17 提柜衔接。" />
<node TEXT="异常:延误/改港/节点未更新 → 船务核实船司消息 → 更新计划并交客服通知客户。" />
</node>
<node TEXT="16 目的港清关|海外清关专员" ID="step-16" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外清关专员 · 姓名____" />
<node TEXT="正常:可提前备资料;确认清关放行和提柜条件 → 17 海外提柜。" />
<node TEXT="异常:补件/查验/未放行 → 清关专员联系代理、客户 → 处理并确认可提柜后继续。" />
</node>
<node TEXT="17 海外提柜/送仓|海外运输跟单" ID="step-17" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外运输跟单 · 姓名____" />
<node TEXT="正常:预约港口提柜、协调海外仓接收 → 18 拆柜收货。" />
<node TEXT="异常:无车/提柜失败/仓库约不上 → 海外运输跟单协调港口、车队、仓库 → 改约并跟进额外费用。" />
</node>
<node TEXT="18 海外拆柜收货|海外收货员" ID="step-18" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外收货员 · 姓名____" />
<node TEXT="正常:按入仓计划扫描、清点、记录实收 → 无差异时交 19 入库。" />
<node TEXT="异常:短收/超收 → 海外仓主管登记差异、留证 → 待核平;可结束卸柜,但不能直接成为可用库存,核平入口待确认。" />
<node TEXT="18A 卸柜后还空柜|海外运输跟单" ID="step-18A" FOLDED="true">
<node TEXT="负责人:海外运输跟单 · 姓名____" />
<node TEXT="正常:卸柜结束 → 安排还空并记录凭证;与后续库存、出库流程并行。" />
<node TEXT="异常:还空受阻/临近截止 → 海外运输跟单联系车队、堆场 → 调整还空安排并跟进费用。" />
</node>
</node>
<node TEXT="19 海外入库/库位确认|海外仓管" ID="step-19" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外仓管 · 姓名____" />
<node TEXT="正常:正常收货形成库存,核对真实托盘、库位和可用数量 → 20 排车。" />
<node TEXT="异常:库位不符/暂扣/数量仍有差异 → 海外仓主管核实 → 满足可用条件后再交拣货。" />
<node TEXT="19A 一件代发独立出库|一件代发运营" ID="step-19A" FOLDED="true">
<node TEXT="负责人:一件代发运营 · 姓名____" />
<node TEXT="正常:按独立出库单逐箱或整托拣货,核对 SKU 与数量后出库;签收、回访和整单完结衔接待确认。" />
<node TEXT="异常:缺货/错 SKU/数量不符 → 代发运营与海外仓核对 → 补货或调整后再出库。" />
</node>
</node>
<node TEXT="20 海外排车|海外调度" ID="step-20" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外调度 · 姓名____" />
<node TEXT="正常:确定车辆、路线、目的地与货物 → 21 转派送、22 拣货;可提前预排,实际拣货须有可用库存。" />
<node TEXT="异常:无车/预约冲突/库存不足 → 海外调度协调仓库、车队 → 调整排车与交付安排。" />
</node>
<node TEXT="21 转派送/生成待出库单|海外调度" ID="step-21" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外调度 · 姓名____" />
<node TEXT="正常:生成派送关联和待出库单 → 23 发车前核对;可在 22 拣货前或过程中进行,必须早于 24 发车。" />
<node TEXT="异常:资料缺失/生成失败 → 海外调度补齐资料、核实关联 → 成功后才能发车。" />
</node>
<node TEXT="22 按排车拣货|海外拣货员" ID="step-22" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外拣货员 · 姓名____" />
<node TEXT="正常:按排车任务、托盘与库位扫描拣货 → 23 核平复核。" />
<node TEXT="异常:少货/错托/暂扣/货位不符 → 海外仓主管核查 → 补拣或协调调度调整。" />
</node>
<node TEXT="23 拣货核平/发车前复核|海外仓主管" ID="step-23" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外仓主管 · 姓名____" />
<node TEXT="正常:核对实拣、出库单、车辆及必需资料 → 条件齐备交 24 发车。" />
<node TEXT="异常:数量未核平/单据缺失 → 海外仓主管联系拣货员、调度补齐 → 复核无误后继续。" />
<node TEXT="说明:此处是作业检查节点,不表示另设一项系统审批。" />
</node>
<node TEXT="24 发车/确认出库|海外出库员" ID="step-24" FOLDED="true" POSITION="right">
<node TEXT="负责人:海外出库员 · 姓名____" />
<node TEXT="正常:按系统可发车条件确认发车、完成出库 → 25 派送签收;调度负责车辆交接。" />
<node TEXT="异常:系统阻断/司机未到/交接不符 → 出库员暂停,海外调度协调处理 → 满足条件后发车。" />
</node>
<node TEXT="25 派送/签收|派送运营" ID="step-25" FOLDED="true" POSITION="right">
<node TEXT="负责人:派送运营 · 姓名____" />
<node TEXT="正常:送达、保存有效签收资料 → 26 整单完结核对;同时进入 27 客户回访。" />
<node TEXT="异常:拒签/送达失败 → 派送运营登记异常 → 退回时按实收恢复到真实托盘、库位 → 另行安排后续;不按正常签收完结。" />
</node>
<node TEXT="26 整单完结|履约运营" ID="step-26" FOLDED="true" POSITION="right">
<node TEXT="负责人:履约运营 · 姓名____" />
<node TEXT="正常:全部有效履约片段完成后,系统汇总整单完结;履约运营核对结果。" />
<node TEXT="异常:还有余货/其他柜未完成/回传失败 → 履约运营追踪对应环节,系统故障转技术 → 齐备后完结。" />
<node TEXT="说明:27 回访独立进行;财务结清另行核对。" />
</node>
<node TEXT="27 客户回访|客服" ID="step-27" FOLDED="true" POSITION="right">
<node TEXT="负责人:客服 · 姓名____" />
<node TEXT="正常:普通派送签收后回访,记录反馈、处理结果和附件;与 26 整单完结核对并行。" />
<node TEXT="异常:联系不上/投诉/索赔 → 客服持续跟进,交对应业务主管处理 → 反馈客户并补回访记录。" />
</node>
</node>
</map>
@@ -1,63 +0,0 @@
<mxfile host="app.diagrams.net" modified="2026-09-22T00:00:00.000Z" agent="Codex" version="24.7.17">
<diagram id="sequential-loop-flow" name="顺序回路示例">
<mxGraphModel dx="1200" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="n01" value="01 客户下单&#10;负责人:客户下单员&#10;通过→下一节点&#10;异常:资料补正" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="60" y="40" width="270" height="90" as="geometry" />
</mxCell>
<mxCell id="e01" value="异常处理&#10;客服协助补正后回 01" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="420" y="45" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="bad-01" value="异常" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="n01" target="e01" />
<mxCell id="back-01" value="处理完成,回本节点复核" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="e01" target="n01" />
<mxCell id="next-01" value="通过" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;strokeColor=#6c8ebf;endArrow=block;html=1;" edge="1" parent="1" source="n01" target="n02" />
<mxCell id="n02" value="02 订单审核&#10;负责人:订单审核员&#10;通过→下一节点&#10;异常:申报/渠道有误" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="60" y="180" width="270" height="90" as="geometry" />
</mxCell>
<mxCell id="e02" value="异常处理&#10;补正后回 02" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="420" y="185" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="bad-02" value="异常" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="n02" target="e02" />
<mxCell id="back-02" value="处理完成,回本节点复核" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="e02" target="n02" />
<mxCell id="next-02" value="通过" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;strokeColor=#6c8ebf;endArrow=block;html=1;" edge="1" parent="1" source="n02" target="n03" />
<mxCell id="n03" value="03 拉货/客户送仓&#10;负责人:国内提货跟单&#10;通过→下一节点&#10;异常:未备货/迟到/破损" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="60" y="320" width="270" height="90" as="geometry" />
</mxCell>
<mxCell id="e03" value="异常处理&#10;改约或补交接后回 03" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="420" y="325" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="bad-03" value="异常" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="n03" target="e03" />
<mxCell id="back-03" value="处理完成,回本节点复核" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="e03" target="n03" />
<mxCell id="next-03" value="通过" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;strokeColor=#6c8ebf;endArrow=block;html=1;" edge="1" parent="1" source="n03" target="n04" />
<mxCell id="n04" value="04 到仓验收与测量&#10;负责人:收货员/测量员&#10;通过→下一节点&#10;异常:差异/漏测/错码" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="60" y="460" width="270" height="90" as="geometry" />
</mxCell>
<mxCell id="e04" value="异常处理&#10;补收或复测后回 04" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="420" y="465" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="bad-04" value="异常" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="n04" target="e04" />
<mxCell id="back-04" value="处理完成,回本节点复核" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="e04" target="n04" />
<mxCell id="next-04" value="通过" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;strokeColor=#6c8ebf;endArrow=block;html=1;" edge="1" parent="1" source="n04" target="n05" />
<mxCell id="n05" value="05 测量审核&#10;负责人:测量审核员&#10;通过→下一节点&#10;异常:数据或证据存疑" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="60" y="600" width="270" height="90" as="geometry" />
</mxCell>
<mxCell id="e05" value="异常处理&#10;复测补证后回 05;订单门禁回 02" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="420" y="605" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="bad-05" value="异常" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="n05" target="e05" />
<mxCell id="back-05" value="处理完成,回本节点复核" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="e05" target="n05" />
<mxCell id="next-05" value="通过" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;strokeColor=#6c8ebf;endArrow=block;html=1;" edge="1" parent="1" source="n05" target="n06" />
<mxCell id="n06" value="06 入库/库位确认&#10;负责人:国内仓管&#10;通过→下一节点&#10;异常:库位不足/货位不符" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="60" y="740" width="270" height="90" as="geometry" />
</mxCell>
<mxCell id="e06" value="异常处理&#10;落实位置并修正后回 06" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="420" y="745" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="bad-06" value="异常" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="n06" target="e06" />
<mxCell id="back-06" value="处理完成,回本节点复核" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;dashed=1;strokeColor=#b85450;endArrow=block;html=1;" edge="1" parent="1" source="e06" target="n06" />
</root>
</mxGraphModel>
</diagram>
</mxfile>
@@ -1,52 +0,0 @@
# 头程到尾程流程节点清单
填写规则:`节点|负责人|完成后进入|异常处理后回到`。姓名、时限和凭证由现场补充。
## 主流程
| 编号 | 节点 | 负责人 | 完成后进入 | 异常处理后回到 |
|---|---|---|---|---|
| 01 | 客户下单 | 客户下单员:____ | 02 订单审核 | 资料补正后回 01 |
| 02 | 订单审核 | 订单审核员:____ | 03 拉货/送仓 | 补正后回 02 |
| 03 | 拉货/客户送仓 | 国内提货跟单:____ | 04 到仓收货 | 改约或补交接后回 03 |
| 04 | 到仓收货 | 国内收货员:____ | 05 称重测量 | 差异确认后回 04 |
| 05 | 称重测量 | 国内测量员:____ | 06 测量审核 | 补测补证后回 05 |
| 06 | 测量审核 | 测量审核员:____ | 07 入库/库位 | 数据问题回 05;订单门禁回 02 后再回 06 |
| 07 | 国内入库/库位 | 国内仓管:____ | 08 排柜 | 修正库位后回 07 |
| 08 | 排柜/分柜 | 柜务:____ | 09 订舱/放舱 | 调整计划后回 08 |
| 09 | 订舱/放舱 | 船务:____ | 10 国内拖柜 | 新船期或资料确认后回 09 |
| 10 | 国内拖柜:预约、提柜到仓 | 国内运输跟单:____ | 11 国内拣货 | 改约或补资料后回 10 |
| 11 | 国内拣货 | 国内拣货员:____ | 12 装柜完成 | 补拣或调整后回 11 |
| 12 | 装柜完成 | 国内装柜主管:____ | 13 出口报关 | 调整或补证后回 12 |
| 13 | 出口报关 | 报关专员:____ | 14 国内出仓 | 补正或查验后回 13 |
| 14 | 国内出仓 | 国内出仓员:____ | 15 海运跟踪 | 解除阻断后回 14 |
| 15 | 海运/到港跟踪 | 船务:____ | 16 目的港清关 | 核实船期后回 15 |
| 16 | 目的港清关 | 海外清关专员:____ | 17 海外提柜 | 补件、查验或放行后回 16 |
| 17 | 海外提柜/送仓 | 海外运输跟单:____ | 18 海外拆柜收货 | 改约后回 17 |
| 18 | 海外拆柜收货 | 海外收货员:____ | 19 海外入库 | 短收/超收先待核平,完成后回 19 |
| 19 | 海外入库/库位 | 海外仓管:____ | 20 海外排车 | 满足可用库存条件后回 19 |
| 20 | 海外排车 | 海外调度:____ | 21 转派送、22 拣货 | 调整车辆或预约后回 20 |
| 21 | 转派送/生成待出库单 | 海外调度:____ | 23 发车前复核 | 补齐资料后回 21 |
| 22 | 按排车拣货 | 海外拣货员:____ | 23 发车前复核 | 补拣或库存调整后回 22 |
| 23 | 拣货核平/发车前复核 | 海外仓主管:____ | 24 发车/出库 | 补齐数量、单据、车辆后回 23 |
| 24 | 发车/确认出库 | 海外出库员:____ | 25 派送签收 | 满足发车条件后回 24 |
| 25 | 派送/签收 | 派送运营:____ | 26 整单完结;27 回访 | 拒签/失败:退回恢复库存,后续重新安排 |
| 26 | 整单完结 | 履约运营:____ | 流程结束 | 还有未完成片段时回对应节点 |
| 27 | 客户回访 | 客服:____ | 流程结束 | 投诉或联系不上时由客服继续跟进 |
## 特殊分支
| 分支 | 负责人 | 流程 | 异常回流 |
|---|---|---|---|
| 一件代发国内处理 | 国内清点员/打托员:____ | 06 测量审核 → 拆箱清点 → 归托封托 → 07 入库/库位 → 08 排柜 | 差异回清点;漏清点或未封托回打托 |
| 海外接柜准备 | 海外计划员:____ | 12 装柜完成后提前准备入仓计划、托盘、库位 | 资料或资源缺失回计划准备 |
| 卸柜后还空 | 海外运输跟单:____ | 18 拆柜完成 → 安排还空 | 还空受阻回运输跟单处理 |
| 一件代发海外独立出库 | 一件代发运营:____ | 按独立出库单逐箱或整托拣货 → 复核 → 出库 | 缺货或错 SKU 回海外仓核对;签收和完结规则待确认 |
## 并行关系
- 02 审核与 03 拉货、04 收货、05 测量可以并行;06 测量审核前必须完成 02。
- 08 排柜、09 订舱准备可以并行;10 拖柜预约须等订舱放舱和资料齐备。
- 12 装柜完成后即可准备海外入仓计划,不必等待海运到港。
- 21 转派送可以早于或晚于 22 拣货,但必须早于 24 发车。
- 26 整单完结与 27 客户回访并行,回访不阻断整单完结。
File diff suppressed because one or more lines are too long
+91
View File
@@ -0,0 +1,91 @@
# 头程到尾程流程节点梳理
> **当前用途:全流程收尾变更的流程入口。** F01-F40 的业务基线已经确认,报关协同代码已接入并通过测试环境验收;本文件只保留三大业务块、关键节点和节点之间的关系,便于查找和修改。报关实现细节请看[报关代码开发交接清单](头程到尾程/报关代码开发交接清单.md),历史开发规划、进度、门禁和评审不在这里继续维护。
>
> **维护原则:** 客户看到的是进度投影,后台看到的是业务对象节点,明细节点记录真实操作和结果。三者使用同一组业务事实,不另建一套客户状态。
## 一、三大业务块
| 业务块 | 覆盖范围 | 对外主要进度 | 后台主要对象 | 分段详情 |
|---|---|---|---|---|
| **头程下单** | 客户下单、审核、国内到仓、测量、计费、确认、组托 | 待下单 → 审核中 → 待到仓/测量 → 待分柜 | 订单、入仓单、测量记录、费用记录、托盘 | [阶段一](头程到尾程分阶段流程/阶段一-客户准入与头程下单.md)、[阶段二](头程到尾程分阶段流程/阶段二-国内到仓测量计费与组托.md) |
| **海运(货柜)** | 分柜、订舱、拖车、拣货、装柜、报关协同、待发区、送港、进港、甩柜、实际开船、目的港和尾程计划 | 待分柜 → 装柜中 → 报关中 → 待发区 → 送港/待开船 → 海运中 → 待入仓 | 柜次、装柜任务、报关批次、待发区、送港任务、船次、尾程入仓计划 | [阶段三](头程到尾程分阶段流程/阶段三-国内货柜履约与出仓.md)、[阶段四](头程到尾程分阶段流程/阶段四-海运目的港与尾程计划.md)、[报关专题](国内货柜履约/报关资料与船期价格接入梳理.md) |
| **尾程入库和派送** | 海外接柜、拆柜实收、入库、库存服务、排车、出库、派送、签收、异常回写 | 待接柜 → 入库中 → 待派送 → 出库/派送中 → 已签收/异常 | 接柜任务、入库单、库存、出库单、派送单、异常单 | [阶段五](头程到尾程分阶段流程/阶段五-海外接柜库存与库内服务.md)、[阶段六](头程到尾程分阶段流程/阶段六-海外排车出库派送与回写.md) |
三大块是客户和产品的展示分组;F01~F40 是后台查找和验收用的内部编号,不代表客户必须看到 40 个节点,也不代表所有动作严格串行。
## 二、主流程
```text
头程下单
客户下单 → 订单审核 → 国内到仓 → 测量/计费 → 费用确认(不阻断)→ 组托/待分柜
↓
海运(货柜)
分柜/订舱/拖车 → 拣货 → 装柜完成(LOADED)
└─ 报关协同:客户资料 → 报关行回执 → 客户确认/打回重做 → 全部客户通过
→ 整柜资料交报关行 → 正式申报 → 查验或不查验放行
↓ 报关完成
进入待发区
送港运输:待发区 → 离仓 → 送港 → 进港 → (容量不足时)甩柜/改配
↓
船舶实际开航后进入海运节点
↓
目的港清关/提柜 → 尾程入仓计划
↓
尾程入库和派送
海外接柜 → 拆柜实收 → 入库/库存 → 排车 → 出库 → 派送 → 签收/异常回写
```
## 三、关键节点总表
| 编号 | 业务块 | 客户进度节点 | 后台管理节点 | 真实明细节点 | 完成结果或分支 |
|---|---|---|---|---|---|
| F01-F07 | 头程下单 | 待下单、审核中、已审核 | 企业、订单、审核任务 | 填写、提交、补件、审核、生成入仓单 | 审核通过后进入国内履约 |
| F08-F10 | 头程下单 | 待到仓、测量中、待确认 | 入仓单、测量记录 | 到仓收货、扫码、称重、测量、审核 | 形成可排柜的实测数据 |
| F11-F13 | 头程下单 | 费用待确认、国内扣货/解除、待组托、待分柜 | 费用版本、确认记录、HOLD 记录、托盘 | 计费、推送、客户确认、国内扣货/解除、组托/封托 | 费用确认不阻断主链;国内扣货单独控制作业门禁;装柜不能代替客户确认费用 |
| F14-F20 | 海运(货柜) | 待分柜、订舱中、装柜准备/进行中 | 柜次、装柜计划、拖车任务、拣货任务 | 分柜、订舱、排车、拣货、拍照、铅封、数量核对 | 通过装柜门禁后才能完成装柜 |
| F21 | 海运(货柜) | 国内已装柜 | 装柜任务已完成 | 实际柜号、实装数量、装柜证据确认 | 产生 `LOADED`;完成报关后才进入待发区 |
| F22 | 海运(货柜) | 报关确认中、待补资料、已提交报关 | 客户报关案例、报关批次 | 收集资料、发报关行、接收回执、客户确认或打回、重新上传和重发 | **已实现并通过真实 HTTP 验收**;柜内所有客户确认后,才能提交整柜资料并正式申报;客户确认不等于海关放行 |
| F23 | 海运(货柜) | 待发区、送港中、已进港、待开船、已甩柜 | 待发区、送港/拖车任务、港口和船次事实 | 报关完成后入待发区、离仓、送港、进港、甩柜、改配 | 报关完成是进入待发区的门槛;甩柜/改配只改变运输船期,不重做已完成报关 |
| F24 | 海运(货柜) | 海运中 | 船次实际状态 | 承运船舶实际开航、船期回写 | 只有实际开航后进入海运节点 |
| F25-F27 | 海运(货柜) | 目的港处理中、待海外接柜 | 目的港清关/提柜、尾程订单、入仓计划 | 清关、提柜、创建尾程计划 | 形成海外接柜输入,不等于已经入库 |
| F28-F33 | 尾程入库和派送 | 待接柜、入库中、库存可用 | 接柜任务、入库单、库存 | 接柜、拆柜、收货核对、上架、盘点及库内服务 | 实收核平并入账后形成可用库存 |
| F34-F37 | 尾程入库和派送 | 待派送、出库处理中、已出库 | 排车、出库单、派送单 | 生成出库/派送单、拣货、复核、发车 | 出库和签收分开记录 |
| F38-F40 | 尾程入库和派送 | 派送中、已签收、异常 | 派送单、签收和异常单 | 送达、签收、拒收/部分拒收、退回、最终回写 | 异常保留原事实和恢复结果;全部有效分片完成后订单收口 |
## 四、必须保持的流程关系
### 1. 报关完成后进入待发区,船期单独推进
`LOADED` 只表示货物已经实际装入集装箱并完成装柜记录。之后先完成报关协同,报关完成后货物进入待发区:
- **报关协同线**:通知报关行,按客户/入仓码收集资料;报关行生成回执后发客户确认。客户打回时,只重做对应客户的资料、发送和回执,直到柜内所有客户都确认。全部确认后,将整柜资料交报关行确认,再记录正式申报和海关结果。
- **待发区与船期线**:报关完成后进入待发区,再安排离仓、送港和进港;船舱不足时记录甩柜和改配。甩柜/改配只人工修改原柜的船名、航次和船期,不影响已完成的报关资料、回执和客户确认。
报关行回执、客户确认、正式申报、海关放行、进入待发区、进港、甩柜和实际开船是不同事实,不能合并成一个“报关完成”或“海运中”。
### 2. 费用确认不阻断装柜主链
费用确认是头程下单块中的并行事项。客户未确认时可以继续排柜、拣货和装柜。按阶段二及 Firstleg 当前服务指引,装柜完成可以触发平台费用确认与发布,但不能代替客户主动确认;客户已确认且本票装柜完成时才最终冻结。费用确认与报关资料的客户确认分别记录。
### 3. 异常附着在主节点上
查验、扣货、资料打回、甩柜、拒收和跨区回写失败都应保留发生在哪个主节点、责任人、处理结果和恢复时间。异常可以阻断对应分支,但不要用“异常”覆盖主流程已经发生的事实。
## 五、三层节点的使用口径
| 层级 | 解决的问题 | 示例 |
|---|---|---|
| 客户进度节点 | 客户现在处于哪一段、下一步做什么 | 报关确认中、送港中、海运中、入库中 |
| 后台管理节点 | 哪个业务对象正在处理、由谁处理 | 报关批次待客户确认、送港任务已进港、派送单已出库 |
| 真实明细节点 | 事实何时发生、凭什么证明 | 上传资料、回执版本、客户确认、离仓时间、进港记录、签收凭证 |
客户页面只展示与自身相关的进度和资料;后台详情保留完整明细;异常作为附加状态展示,不另建一条互相矛盾的主流程。
## 六、查找和修改规则
1. **改流程关系或客户节点**:先改本文件,再检查对应阶段文档的名称和链接。
2. **改单个阶段的字段、页面操作或权限**:只改对应的六份阶段文档和实际契约,不回写历史开发规划。
3. **改报关资料、回执确认或船期价格**:以[报关资料与船期价格接入梳理](国内货柜履约/报关资料与船期价格接入梳理.md)为专题入口,同时核对本文件中的 F22/F23 关系。
4. **开发规划、进度、开工门禁、验收任务、旧审计和优化方案**:保留原文作为追溯资料,标记为冻结,不作为当前流程入口。
5. **新增或调整节点时**:先判断它属于客户进度、后台对象还是明细事实;只有确实改变三大块关系时才改总表,避免在多份文档复制同一段流程。
+8
View File
@@ -14,6 +14,14 @@
- 当前尚未上线;同一资源已有 `*:list` 时,不保留或新增独立 `*:view` 兼容分支。前端不得使用 `permissionAnyOf` 接受旧 `view`,后端不得使用 `hasAnyAuthority(list, view)`,初始化 SQL 应停用或删除旧 `view` 资源及其角色关联。 - 当前尚未上线;同一资源已有 `*:list` 时,不保留或新增独立 `*:view` 兼容分支。前端不得使用 `permissionAnyOf` 接受旧 `view`,后端不得使用 `hasAnyAuthority(list, view)`,初始化 SQL 应停用或删除旧 `view` 资源及其角色关联。
- 供应商固定使用 `platform:supplier:list` 作为菜单、列表和详情唯一只读权限;`platform:supplier:view` 必须停用或移除,不得在导航、路由、页面、Controller、OpenAPI 或 SQL 中恢复兼容。 - 供应商固定使用 `platform:supplier:list` 作为菜单、列表和详情唯一只读权限;`platform:supplier:view` 必须停用或移除,不得在导航、路由、页面、Controller、OpenAPI 或 SQL 中恢复兼容。
### Admin 菜单结构与显示
- 一级、二级菜单的名称、分组和顺序以当前确认原型及当前对话确认为准,唯一代码入口为 `apps/admin-web/src/core/navigation/adminNavigation.ts`。一级结构为首页数据看板、客户管理、国内头程、货柜管理、海外尾程、预约管理、车辆管理、海外业务、客户服务、财务管理、自营业务、通用、系统管理;二级菜单统一在该入口维护,实际显示继续由权限过滤。
- 自营业务的经营总览、销量分析、库存分析、数据采集四个页面统一使用 `platform:self-operated-analytics:list`,包括任务详情只读和运行辅助查询;重试独立使用 `platform:self-operated-analytics:sync`,库存周转后台导出使用独立 `platform:self-operated-analytics:export`,下载中心创建、下载及重试均校验该导出权限和非代登录平台身份。IAM 菜单管理资源不替代上述实际读写授权,不能仅凭采集写权限打开只读页面。
- 已实现菜单继续使用正式路由及服务端权限,不因改名、移动或仅调整菜单结构改变接口、状态和操作资格。当前原型未展示的既有入口通过 `hidden` 退出侧栏,正式路由和权限仍按现行合同管理;角色权限设置仍保留这些正式页面及操作的可分配权限。
- 供应商列表按当前确认保留在“通用”分组,使用正式路由 `/suppliers` 与 `platform:supplier:list`,不因原型未展示而隐藏;新增、编辑及其他写操作继续使用各自独立权限。
- 尚无正式页面的菜单不显示,不保留禁用占位或空分组,不接入原型假数据、虚构权限码或新增业务接口。后续功能实现时再核对正式页面、权限与服务端合同。
## 跨层同步 ## 跨层同步
- 菜单结构、路由权限、页面按钮、Controller `@PreAuthorize`、OpenAPI 权限说明及 IAM 初始化/统一增量 SQL 必须同步核对,不能以局部测试通过替代跨层一致性。 - 菜单结构、路由权限、页面按钮、Controller `@PreAuthorize`、OpenAPI 权限说明及 IAM 初始化/统一增量 SQL 必须同步核对,不能以局部测试通过替代跨层一致性。
+20 -46
View File
@@ -31,20 +31,13 @@
| task_id | parent_task_id | project_id | 展示名称 | 唯一长期职责 | | task_id | parent_task_id | project_id | 展示名称 | 唯一长期职责 |
|---|---|---|---|---| |---|---|---|---|---|
| `01a05b23-bfc6-7121-a6f2-7fc14ee456a3` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【前端1】admin | `apps/admin-web/` 全部平台管理页面、路由、API、权限消费、测试与构建;不修改 Client、PDA、后端或 SQL。 | | `01a05b23-bfc6-7121-a6f2-7fc14ee456a3` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【开发全流程前端】Admin | `apps/admin-web/` 全部平台管理页面、路由、API、权限消费、测试与构建;不修改 Client、PDA、后端或 SQL。 |
| `01a05b23-c20f-7f52-8a26-543f1563f0f8` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【前端2】client | `apps/client-web/` 全部客户工作台页面、路由、API、权限消费、测试与构建;不修改 Admin、PDA、后端或 SQL。 | | `01a05b23-c20f-7f52-8a26-543f1563f0f8` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【开发全流程前端】Client | `apps/client-web/` 全部客户工作台页面、路由、API、权限消费、测试与构建;不修改 Admin、PDA、后端或 SQL。 |
| `01a07fce-5b47-7063-ba0f-52fca32b835c` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【前端3】国内PDA | `apps/pda-uniapp/` 全部国内仓现场作业、真实 API、扫码顺序、草稿恢复、幂等、断网阻断、测试与发布准备;不修改 Admin、Client、海外 PDA、后端或 SQL。 | | `01a05b78-6e28-7460-babf-3a87331f6dd4` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【开发全流程前端】海外PDA | `apps/pda-overseas-uniapp/` 全部海外仓现场作业、真实 API、恢复、扫码、幂等、测试与构建;派送仍由 Admin/Client 承载。 |
| `01a05b78-6e28-7460-babf-3a87331f6dd4` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【前端4】海外PDA | `apps/pda-overseas-uniapp/` 全部海外仓现场作业、真实 API、恢复、扫码、幂等、测试与构建;派送仍由 Admin/Client 承载。 | | `01a05b23-c5ff-77c3-8f77-ceb4f4c40de2` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【开发全流程后端】Lastleg | `baiyue-firstleg/lastleg-service/` 海外尾程、入仓、库存、换标、转运、废弃、排车、出库、派送、一件代发、异常、回访及海外业务的接口、OpenAPI、SQL、权限强制和测试。 |
| `01a07fde-a67c-71c3-add5-968c47b2fe91` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端1】国内仓储 | `baiyue-firstleg/warehouse/` 的仓库主档、供应商、国内整柜、库位、托盘、资源预占、OpenAPI、模块 SQL 与测试;不修改其他服务、前端或统一增量 SQL。 | | `01a05b23-c7f8-72e0-bb3c-afbbf1c7f9e7` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【开发全流程后端】IAM权限 | `baiyue-firstleg/iam/` 及必要 common-security 的平台/客户全流程权限资源、角色初始化、授权快照、OpenAPI、SQL 和测试;不修改 Lastleg 业务或前端。 |
| `01a079b6-b5fa-7fe3-82b5-59c4712a6d4c` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端2】Order订单域 | `baiyue-firstleg/order/` 头程订单主数据、统一订单查询聚合、订单状态与动作、内部 Firstleg 客户端 DTO、Order OpenAPI、模块 SQL 与测试;不修改 Firstleg、身份权限、前端或统一增量 SQL。 | | `01a079b6-b279-7aa3-ba2f-6556dbb44790` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【开发全流程后端】Firstleg头程履约 | `baiyue-firstleg/firstleg/` 国内头程入库、测量、计费、分柜、装柜、PDA 服务端门禁、出仓等 Firstleg 履约接口、DTO、Service、Mapper、模块 OpenAPI、模块 SQL 与测试;不修改 Order、IAM、前端或统一增量 SQL。 |
| `01a079b6-b279-7aa3-ba2f-6556dbb44790` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端3】Firstleg头程履约 | `baiyue-firstleg/firstleg/` 国内头程入库、测量、计费、分柜、装柜、PDA 服务端门禁、出仓等 Firstleg 履约接口、DTO、Service、Mapper、模块 OpenAPI、模块 SQL 与测试;不修改 Order、身份权限、前端或统一增量 SQL。 | | `01a079b6-b5fa-7fe3-82b5-59c4712a6d4c` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【开发全流程后端】Order订单域 | `baiyue-firstleg/order/` 头程订单主数据、统一订单查询聚合、订单状态与动作、内部 Firstleg 客户端 DTO、Order OpenAPI、模块 SQL 与测试;不修改 Firstleg、IAM、前端或统一增量 SQL。 |
| `01a05b23-c7f8-72e0-bb3c-afbbf1c7f9e7` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端4】身份权限 | `baiyue-firstleg/auth/`、`iam/` 及必要 `common-security/` 的账号、Token、客户与成员、RBAC、授权快照、OpenAPI、模块 SQL 和测试;不修改业务服务、前端或统一增量 SQL。 |
| `01a07fde-aa31-7443-b15b-461096aa1edd` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端5】Finance财务 | `baiyue-firstleg/finance/` 的客户资金账户、授信、冻结结算、费用池、应收应付、账单、收付款、核销、OpenAPI、模块 SQL 与测试;不修改业务来源服务、前端或统一增量 SQL。 |
| `01a07fde-ad86-7253-8172-91a5686be994` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端6】File打印审计 | `baiyue-firstleg/file/`、`print/`、`audit-service/` 及必要 `common-audit/` 的文件对象、上传下载、导出、打印、审计、OpenAPI、模块 SQL 与测试;不修改业务服务、前端或统一增量 SQL。 |
| `01a05b23-c5ff-77c3-8f77-ceb4f4c40de2` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端7】Lastleg海外业务 | `baiyue-firstleg/lastleg-service/` 海外尾程、入仓、库存、换标、转运、废弃、排车、出库、派送、一件代发、异常、回访及海外业务的接口、OpenAPI、SQL、权限强制和测试。 |
| `01a07fde-b02c-7d92-b83c-668aa7b37bba` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端8】海外仓储资源 | `baiyue-firstleg/warehouse-overseas-service/` 的海外库位、托盘、资源锁、PDA 物理资源流转、OpenAPI、模块 SQL 与测试;国内仓库主档仍归国内仓储专项。 |
| `01a07fde-b307-7091-be2a-c462ef466182` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端9】国内外网关 | `baiyue-firstleg/gateway/`、`gateway-overseas/`、`overseas-security-service/` 的路由、CORS、JWT/JWKS、可信身份头、失败关闭和测试;账号与权限业务仍归身份权限专项。 |
| `01a07fde-b697-7930-b70e-1ee7887be732` | `01a06c0b-0515-7c60-b329-77342b54e666` | `6f874ec3-d3b2-49bd-8625-327f4d685f98` | 【后端10】集成与跨区事件 | `baiyue-firstleg/integration-service/`、`event-bridge-service/`、`common-event-contract/` 的第三方适配、事件信封、跨区路由、Outbox/Inbox 投递合同与测试;业务服务内生产和消费代码仍归对应业务专项。 |
验收与部署任务不常驻登记。只有用户明确要求开始验收、准备部署或执行验收时,才另行决定是否创建;开发任务不得代行。 验收与部署任务不常驻登记。只有用户明确要求开始验收、准备部署或执行验收时,才另行决定是否创建;开发任务不得代行。
@@ -56,10 +49,10 @@
| 工作包 | 执行任务 | 写入范围 | 交付目标 | 依赖与集成边界 | | 工作包 | 执行任务 | 写入范围 | 交付目标 | 依赖与集成边界 |
|---|---|---|---|---| |---|---|---|---|---|
| `WALLET-BE-FINANCE` | 【后端5】Finance财务 | `baiyue-firstleg/finance/`、Finance OpenAPI、模块 SQL 与必要 Finance/File 内部客户端 | 新增客户资金账户、充值申请、授信额度、资金冻结和流水主账;提供客户账户/流水/充值申请接口及平台账户列表/详情、待审充值、审核、手工充值/扣款/授信接口,并提供业务模块使用的冻结、结算和释放内部接口;实现客户隔离、金额校验、权限、服务令牌、幂等、乐观并发与测试 | Finance 拥有余额、授信、冻结和流水;扣款先使用实际资金再使用授信,充值先归还已用授信;付款截图经 Finance 调用 File 内部 `FINANCE_VOUCHER` 保存;不接第三方支付回调,统一增量 SQL 仍由总控集成 | | `WALLET-BE-FINANCE` | 【开发总控】全流程开发 | `baiyue-firstleg/finance/`、Finance OpenAPI、模块 SQL 与统一增量 SQL、必要 Finance/File 内部客户端 | 新增客户资金账户、充值申请、授信额度、资金冻结和流水主账;提供客户账户/流水/充值申请接口及平台账户列表/详情、待审充值、审核、手工充值/扣款/授信接口,并提供业务模块使用的冻结、结算和释放内部接口;实现客户隔离、金额校验、权限、服务令牌、幂等、乐观并发与测试 | Finance 拥有余额、授信、冻结和流水;扣款先使用实际资金再使用授信,充值先归还已用授信;付款截图经 Finance 调用 File 内部 `FINANCE_VOUCHER` 保存;不接第三方支付回调,具体一件代发业务调用后续接线 |
| `WALLET-FE-CLIENT` | 【前端2】client | `apps/client-web/src/modules/finance/` 及该模块路由、导航和测试 | 新增客户资金账户页,显示实际/冻结/可用余额和流水;按原型完成金额选择、微信/支付宝静态二维码、付款截图上传、提交待审核及状态反馈 | 客户范围只取登录态;只调用 `/api/client/finance/v1/**`,无二维码配置时明确不可提交,不模拟支付成功 | | `WALLET-FE-CLIENT` | 【开发全流程前端】Client | `apps/client-web/src/modules/finance/` 及该模块路由、导航和测试 | 新增客户资金账户页,显示实际/冻结/可用余额和流水;按原型完成金额选择、微信/支付宝静态二维码、付款截图上传、提交待审核及状态反馈 | 客户范围只取登录态;只调用 `/api/client/finance/v1/**`,无二维码配置时明确不可提交,不模拟支付成功 |
| `WALLET-FE-ADMIN` | 【前端1】admin | `apps/admin-web/src/modules/finance/` 及对应测试 | 将客户账户页收敛为三余额账户;详情中待审核客户充值置顶并提供审核,保留流水;列表/详情提供手工充值和手工扣款,操作列固定首列 | 只消费 Finance 正式 API;审核、充值、扣款分别受写权限控制;不在前端计算或兜底余额 | | `WALLET-FE-ADMIN` | 【开发全流程前端】Admin | `apps/admin-web/src/modules/finance/` 及对应测试 | 将客户账户页收敛为三余额账户;详情中待审核客户充值置顶并提供审核,保留流水;列表/详情提供手工充值和手工扣款,操作列固定首列 | 只消费 Finance 正式 API;审核、充值、扣款分别受写权限控制;不在前端计算或兜底余额 |
| `WALLET-BE-IAM` | 【后端4】身份权限 | `baiyue-firstleg/iam/` 及必要权限初始化 SQL、OpenAPI 和测试 | 新增并初始化客户账户查看/充值申请和平台充值审核/账户调账权限,保持列表只读与写操作分离 | 企业负责人默认获得客户账户查看和充值申请权限;平台财务角色按现有初始化规则获得审核与调账权限,不修改 Finance 业务 | | `WALLET-BE-IAM` | 【开发全流程后端】IAM权限 | `baiyue-firstleg/iam/` 及必要权限初始化 SQL、OpenAPI 和测试 | 新增并初始化客户账户查看/充值申请和平台充值审核/账户调账权限,保持列表只读与写操作分离 | 企业负责人默认获得客户账户查看和充值申请权限;平台财务角色按现有初始化规则获得审核与调账权限,不修改 Finance 业务 |
完成门禁:Finance、IAM 定向测试通过,Admin/Client 定向测试、类型检查和生产构建通过,跨端 DTO 与权限码一致;专项不提交、不推送、不部署、不操作数据库或真实 HTTP,由开发总控统一集成后再进入开发环境部署与验收。 完成门禁:Finance、IAM 定向测试通过,Admin/Client 定向测试、类型检查和生产构建通过,跨端 DTO 与权限码一致;专项不提交、不推送、不部署、不操作数据库或真实 HTTP,由开发总控统一集成后再进入开发环境部署与验收。
@@ -80,10 +73,10 @@
| 工作包 | 执行任务 | 写入范围 | 交付目标 | 依赖与集成边界 | | 工作包 | 执行任务 | 写入范围 | 交付目标 | 依赖与集成边界 |
|---|---|---|---|---| |---|---|---|---|---|
| `P0-BE-LASTLEG` | 【后端7】Lastleg海外业务 | `baiyue-firstleg/lastleg-service/` | 补齐客户海外采购、本土卡、本土散板、海外入库订单所需客户 API;核对并补齐 PDA 盘点、移库、换标、库存/库位/托盘查询专用 API、OpenAPI 与测试 | 先冻结 DTO、权限码和状态机并通知 Client、海外 PDA、IAM;不修改 `iam/`、统一 SQL或前端 | | `P0-BE-LASTLEG` | 【开发全流程后端】Lastleg | `baiyue-firstleg/lastleg-service/` | 补齐客户海外采购、本土卡、本土散板、海外入库订单所需客户 API;核对并补齐 PDA 盘点、移库、换标、库存/库位/托盘查询专用 API、OpenAPI 与测试 | 先冻结 DTO、权限码和状态机并通知 Client、海外 PDA、IAM;不修改 `iam/`、统一 SQL或前端 |
| `P0-BE-IAM` | 【后端4】身份权限 | `baiyue-firstleg/iam/` 及必要 `common-security/` | 补齐并核对客户海外业务、海外入库查询和海外 PDA 现场作业的权限资源、角色初始化、OpenAPI 与模块 SQL | 消费 Lastleg 冻结的权限码;不修改 Lastleg、统一 SQL或前端 | | `P0-BE-IAM` | 【开发全流程后端】IAM权限 | `baiyue-firstleg/iam/` 及必要 `common-security/` | 补齐并核对客户海外业务、海外入库查询和海外 PDA 现场作业的权限资源、角色初始化、OpenAPI 与模块 SQL | 消费 Lastleg 冻结的权限码;不修改 Lastleg、统一 SQL或前端 |
| `P0-FE-CLIENT` | 【前端2】client | `apps/client-web/` | 将海外采购、美国本土卡、美本土散板和海外入库订单从占位收敛为真实页面;修正首页快捷入口;覆盖权限、加载、空态、错误态、幂等与测试 | 只消费客户正式 API,不调用平台/内部接口,不模拟成功;“我的订单”统一查询不在本批 | | `P0-FE-CLIENT` | 【开发全流程前端】Client | `apps/client-web/` | 将海外采购、美国本土卡、美本土散板和海外入库订单从占位收敛为真实页面;修正首页快捷入口;覆盖权限、加载、空态、错误态、幂等与测试 | 只消费客户正式 API,不调用平台/内部接口,不模拟成功;“我的订单”统一查询不在本批 |
| `P0-FE-OVERSEAS-PDA` | 【前端4】海外PDA | `apps/pda-overseas-uniapp/` | 接通库存盘点、商品移库、换标收货/执行/复核、库存/库位/托盘查询共 8 项现场能力,完成扫码、恢复、并发冲突、幂等、错误态和构建测试 | 只调用 `/api/pda/**` 正式接口;不得通过 `available: true` 掩盖未接通能力,不改后端或其他前端 | | `P0-FE-OVERSEAS-PDA` | 【开发全流程前端】海外PDA | `apps/pda-overseas-uniapp/` | 接通库存盘点、商品移库、换标收货/执行/复核、库存/库位/托盘查询共 8 项现场能力,完成扫码、恢复、并发冲突、幂等、错误态和构建测试 | 只调用 `/api/pda/**` 正式接口;不得通过 `available: true` 掩盖未接通能力,不改后端或其他前端 |
完成门禁:四包定向测试与构建通过,跨端契约一致,所有 P0 页面或 PDA 入口均不再是 `prototype`、`available: false` 或模拟成功。专项本批不提交、不推送、不部署、不执行数据库和真实 HTTP;总控汇总差异并处理现有文档改动后,再按各仓库最新测试分支同步门禁统一集成。 完成门禁:四包定向测试与构建通过,跨端契约一致,所有 P0 页面或 PDA 入口均不再是 `prototype`、`available: false` 或模拟成功。专项本批不提交、不推送、不部署、不执行数据库和真实 HTTP;总控汇总差异并处理现有文档改动后,再按各仓库最新测试分支同步门禁统一集成。
@@ -152,29 +145,10 @@
| 工作包 | 执行任务 | 写入范围 | 交付目标 | 依赖与集成边界 | | 工作包 | 执行任务 | 写入范围 | 交付目标 | 依赖与集成边界 |
|---|---|---|---|---| |---|---|---|---|---|
| `HOLD-BE-FIRSTLEG` | 【后端3】Firstleg头程履约 | `baiyue-firstleg/firstleg/` 的扣货命令、历史查询、履约门禁、模块 OpenAPI、模块 SQL 与测试 | 提供扣货/解除扣货接口,落实客户归属、独立权限、幂等、乐观并发、不可变历史和实物作业前置门禁;所有下游履约写入口按服务端权威扣货状态失败关闭 | 先冻结平台接口及内部统一订单 DTO 字段并通知 Order、Admin;不修改 Order、IAM、前端或统一增量 SQL | | `HOLD-BE-FIRSTLEG` | 【开发全流程后端】Firstleg头程履约 | `baiyue-firstleg/firstleg/` 的扣货命令、历史查询、履约门禁、模块 OpenAPI、模块 SQL 与测试 | 提供扣货/解除扣货接口,落实客户归属、独立权限、幂等、乐观并发、不可变历史和实物作业前置门禁;所有下游履约写入口按服务端权威扣货状态失败关闭 | 先冻结平台接口及内部统一订单 DTO 字段并通知 Order、Admin;不修改 Order、IAM、前端或统一增量 SQL |
| `HOLD-BE-ORDER` | 【后端2】Order订单域 | `baiyue-firstleg/order/` 的 Firstleg 内部客户端 DTO、统一订单响应、Order OpenAPI 与测试 | 将 Firstleg `holdFlag/currentHoldReason` 透传到统一订单列表/详情,删除未落地的旧字段语义,不复制扣货状态机 | 只消费 Firstleg 冻结 DTO;不提供扣货写接口,不修改 Firstleg、IAM、前端或统一增量 SQL | | `HOLD-BE-ORDER` | 【开发全流程后端】Order订单域 | `baiyue-firstleg/order/` 的 Firstleg 内部客户端 DTO、统一订单响应、Order OpenAPI 与测试 | 将 Firstleg `holdFlag/currentHoldReason` 透传到统一订单列表/详情,删除未落地的旧字段语义,不复制扣货状态机 | 只消费 Firstleg 冻结 DTO;不提供扣货写接口,不修改 Firstleg、IAM、前端或统一增量 SQL |
| `HOLD-FE-ADMIN` | 【前端1】admin | `apps/admin-web/src/modules/unified-orders/`、必要 `modules/inbounds/` API 暴露与对应测试 | 在订单详情“其他”页签增加独立扣货控制、状态标识、原因/凭证弹窗和历史展示;尚未生成入库单或无权限时只读;成功后刷新详情与列表 | 快递信息、内部备注、箱子计费不并入扣货统一提交;只消费正式 Firstleg/Order API,不在前端推导可扣货状态 | | `HOLD-FE-ADMIN` | 【开发全流程前端】Admin | `apps/admin-web/src/modules/unified-orders/`、必要 `modules/inbounds/` API 暴露与对应测试 | 在订单详情“其他”页签增加独立扣货控制、状态标识、原因/凭证弹窗和历史展示;尚未生成入库单或无权限时只读;成功后刷新详情与列表 | 快递信息、内部备注、箱子计费不并入扣货统一提交;只消费正式 Firstleg/Order API,不在前端推导可扣货状态 |
| `HOLD-BE-IAM` | 【后端4】身份权限 | `baiyue-firstleg/iam/` 的权限资源、默认角色授权、模块 OpenAPI、模块 SQL 与测试 | 新增 `platform:firstleg:inbound:hold` 独立写权限并按现有平台管理员规则初始化;保持查看权限与扣货写权限分离 | 不修改 Firstleg、Order、统一增量 SQL或前端;权限码冻结后通知 Firstleg、Admin | | `HOLD-BE-IAM` | 【开发全流程后端】IAM权限 | `baiyue-firstleg/iam/` 的权限资源、默认角色授权、模块 OpenAPI、模块 SQL 与测试 | 新增 `platform:firstleg:inbound:hold` 独立写权限并按现有平台管理员规则初始化;保持查看权限与扣货写权限分离 | 不修改 Firstleg、Order、统一增量 SQL或前端;权限码冻结后通知 Firstleg、Admin |
| `HOLD-BE-FILE` | 【后端6】File打印审计 | `baiyue-firstleg/file/` 的通用业务文件类别与测试;Firstleg 专用文件客户端由【后端3】Firstleg头程履约负责 | 提供客户作用域的扣货凭证上传、精确引用校验和已关联凭证下载,拒绝跨客户、跨入库单及未进入历史的文件 | File 只保存文件与精确归属,不读取 Firstleg 业务表;凭证可见性和不可变历史仍由 Firstleg 决定 | | `HOLD-BE-FILE` | 【开发总控】全流程开发 | `baiyue-firstleg/file/` 的通用业务文件类别与测试、Firstleg 专用文件客户端和归属校验 | 提供客户作用域的扣货凭证上传、精确引用校验和已关联凭证下载,拒绝跨客户、跨入库单及未进入历史的文件 | File 只保存文件与精确归属,不读取 Firstleg 业务表;凭证可见性和不可变历史仍由 Firstleg 决定 |
完成门禁:Firstleg、Order、IAM 定向测试通过,Mapper 与模块 SQL/OpenAPI 合同通过,Admin 定向测试、类型检查和生产构建通过;开发总控统一维护业务契约与统一增量 SQL、执行跨端 DTO/权限核对和 Git 集成。当前各仓库在本批下发前由开发总控恢复到 `dev`,按登记门禁获取并合并最新测试分支;专项不自行切换分支,不提交、不推送、不部署、不操作数据库或真实 HTTP。本批代码门禁完成后再单独决定开发数据库、Jenkins 开发部署与真实 HTTP/1920×1080 人工验收。 完成门禁:Firstleg、Order、IAM 定向测试通过,Mapper 与模块 SQL/OpenAPI 合同通过,Admin 定向测试、类型检查和生产构建通过;开发总控统一维护业务契约与统一增量 SQL、执行跨端 DTO/权限核对和 Git 集成。当前各仓库在本批下发前由开发总控恢复到 `dev`,按登记门禁获取并合并最新测试分支;专项不自行切换分支,不提交、不推送、不部署、不操作数据库或真实 HTTP。本批代码门禁完成后再单独决定开发数据库、Jenkins 开发部署与真实 HTTP/1920×1080 人工验收。
## 当前节点:一件代发国内清点组托与整托分柜(2026-09-08)
### 临时梳理会话说明(2026-09-08)
开发环境登记核对和一件代发全流程梳理属于一次性治理、分析会话,不登记为长期前端或后端专项,也不占用正式编号;工作结论进入本表后归档。长期工作只向上方正式登记的总控、4 个前端专项和 10 个后端专项下发。
本节点由【开发总控】全流程开发负责节点总控。客户一件代发订单继续经过审核、测量和计费;测量审核后进入国内 PDA 拆箱清点与组托。箱码与系统托盘码允许任意先后顺序扫描:先扫托盘时后续箱子进入当前托盘,先扫箱时箱子进入已清点待绑托区,后扫托盘再批量绑定。合理作业顺序不得被拦截,但封托和进入 `WAIT_SPLIT` 前必须保证箱码唯一归托、托盘码有效唯一、清点差异有结果且不存在未绑定箱。智能分柜和装柜以已封托托盘为最小不可拆单元,不再按一件代发入仓单箱数任意拆分,也不在装柜阶段重新打托。
| 工作包 | 执行任务 | 写入范围 | 交付目标 | 依赖与集成边界 |
|---|---|---|---|---|
| `DROPSHIP-BE-FIRSTLEG` | 【后端3】Firstleg头程履约 | `baiyue-firstleg/firstleg/` | 收敛清点、待绑托、托盘绑定、封托、`WAIT_PALLETIZE → WAIT_SPLIT`、托盘维度智能分柜、整托装柜与事件快照;同步 DTO、Controller、Mapper、模块 OpenAPI/SQL 和测试 | 先冻结箱、SKU实收、托盘和装柜计划契约;不修改前端、Order、IAM或统一增量 SQL |
| `DROPSHIP-FE-DOMESTIC-PDA` | 【前端3】国内PDA | `apps/pda-uniapp/` | 新增一件代发任务、逐箱清点、两种扫码顺序、待绑托箱、换托/撤销、封托及整托装柜交互;覆盖硬件广播、草稿、幂等、断网和测试 | 只消费 Firstleg 冻结 API;不模拟成功,不修改后端或其他前端 |
| `DROPSHIP-FE-ADMIN` | 【前端1】admin | `apps/admin-web/src/modules/inbounds/`、`apps/admin-web/src/modules/container-loading/`、`apps/admin-web/src/modules/loading-lists/` 及对应测试 | 入库详情展示权威清点/托盘结果;智能分柜按整托展示、加入和移除;预装与正式装柜详情继续展示封托托盘快照;一件代发不提供箱数拆分输入 | 只消费 Firstleg 正式 DTO;普通头程现有箱数分配行为保持不变 |
| `DROPSHIP-FE-CLIENT` | 【前端2】client | `apps/client-web/src/modules/first-leg/` 及对应测试 | 按逐步确认的 Client 原型补齐一件代发下单字段、回显和客户可见状态 | 只消费正式 Order/Firstleg 客户契约,不暴露平台或 PDA 内部操作 |
| `DROPSHIP-BE-ORDER` | 【后端2】Order订单域 | `baiyue-firstleg/order/` | 按需冻结并透传一件代发货物、SKU、箱明细和订单状态,不复制 Firstleg 清点/托盘状态机 | 仅在 Firstleg 冻结跨服务 DTO 后启动 |
| `DROPSHIP-BE-IAM` | 【后端4】身份权限 | `baiyue-firstleg/iam/` 及必要 `common-security/` | 按需补齐国内 PDA 清点、组托和整托装柜权限及默认仓库角色授权 | 权限码由 Firstleg 先冻结;不修改业务服务或前端 |
完成门禁:各专项先完成定向测试、类型检查或构建,开发总控统一处理共享文档、统一增量 SQL、Git 集成和提交。代码门禁通过后,本节点已获授权操作开发数据库、使用 Jenkins 部署开发环境、执行开发环境真实 HTTP,并使用内置浏览器按 Admin/Client `1920×1080`、国内/海外 PDA `390×848` 验收样式、交互、控制台与请求量;环境配置只从 `C:\Users\BY-OY\.codex\env\chongchong-global` 读取,不把密钥、Token或环境地址写入源码和指引。发现问题后回到对应唯一写入专项修复并重复验证,直至节点全部门禁通过;授权不扩展到测试或生产环境,不包含数据库清空、重建或无主键批量删除。
+10
View File
@@ -0,0 +1,10 @@
# 文档归档
这里保存已经完成开发阶段、当前不作为日常流程入口的历史文档。归档只改变文件位置,不删除内容;需要追溯旧决策、旧验收或旧开发计划时再进入对应子目录。
## 归档目录
- [头程到尾程](头程到尾程/README.md):全流程操作手册、旧现状全景、AI 上下文和易用性方案。
- [国内货柜履约归档](../国内货柜履约/归档/README.md):开发规划、进度、门禁、验收矩阵、审计和旧确认材料。
当前流程只从 [头程到尾程流程节点梳理](../头程到尾程流程节点梳理.md) 开始查找。
+11
View File
@@ -0,0 +1,11 @@
# 头程到尾程历史文档
本目录只保留历史操作说明、旧版现状盘点和流程优化材料。它们不再作为当前流程或开发计划入口;当前节点关系以[头程到尾程流程节点梳理](../../头程到尾程流程节点梳理.md)为准,分段细节见[头程到尾程分阶段流程](../../头程到尾程分阶段流程/README.md)。
## 文件
- [全流程操作手册](头程下单到尾程出库全流程操作手册.md)
- [现状流程全景清单](头程下单到尾程出库现状流程全景清单.md)
- [AI 流程优化上下文包](头程到尾程AI流程优化上下文包.md)
- [易用性与数据流转优化方案](头程下单到尾程出库流程易用性与数据流转优化方案.md)
@@ -5,7 +5,7 @@
> 当前口径:以现行服务端模块指引、页面入口和代码状态机为准。历史设计与当前实现冲突的地方集中列在第 11 节,旧文档不能直接作为操作依据。 > 当前口径:以现行服务端模块指引、页面入口和代码状态机为准。历史设计与当前实现冲突的地方集中列在第 11 节,旧文档不能直接作为操作依据。
> 不在主链内展开:换标、仓储转运、货物废弃、退货换标、异常退回、客户回访、海外采购和本土散板;这些能力在第 9 节说明如何接入出库。 > 不在主链内展开:换标、仓储转运、货物废弃、退货换标、异常退回、客户回访、海外采购和本土散板;这些能力在第 9 节说明如何接入出库。
> 完整现状流程目录:见[《头程下单到尾程出库现状流程全景清单》](头程下单到尾程出库现状流程全景清单.md)。该清单以 F01~F40 覆盖主链、并行流程、条件分支和异常流;本文侧重一票主链如何实际操作。 > 当前流程基线:见[《头程到尾程流程节点梳理(重构版)》](../../头程到尾程流程节点梳理.md)。[《头程下单到尾程出库现状流程全景清单》](头程下单到尾程出库现状流程全景清单.md)仅保留旧版 AS-IS 证据;本文侧重一票主链如何按最新报关/送港并行流程实际操作。
## 1. 一张图看完整主链 ## 1. 一张图看完整主链
@@ -23,10 +23,11 @@
创建模拟柜/订舱 → 智能或人工排柜 → 预装确认 创建模拟柜/订舱 → 智能或人工排柜 → 预装确认
↓ ↓
国内 PDA 拣货装柜 → 五类证据和铅封 → 装柜完成 LOADED 国内 PDA 拣货装柜 → 五类证据和铅封 → 装柜完成 LOADED
├─ 报关线:通知报关行 → 客户资料 → 报关行回执 → 客户确认/打回重做
│ → 所有客户通过 → 整柜正式申报 → 查验/放行
└─ 送港线:拖车 → 离仓 → 送港/进港 → 甩柜/改配(如发生)→ 实际开船
↓ ↓
整柜出口报关完成 → 系统自动收敛或平台确认国内出仓 实际开船后进入海运节点:装船/离港 → 在途 → 到目的港 → 卸船 → 可提柜
↓
船节点:离开国内仓 → 起运港 → 装船 → 在途 → 到目的港 → 卸船 → 可提柜
↓ ↓
装柜完成事件跨区 → 海外生成 PENDING_ASSIGNMENT 尾程订单 装柜完成事件跨区 → 海外生成 PENDING_ASSIGNMENT 尾程订单
↓ ↓
@@ -43,9 +44,10 @@
主链有三个不能混淆的“出库/出仓”: 主链有三个不能混淆的“出库/出仓”:
1. 国内装柜完成:入库单为 `LOADED`,表示货已经装入国内出口柜,不等于柜已离开国内仓。 1. 国内装柜完成:入库单为 `LOADED`,表示货已经装入国内出口柜;同时启动报关线和送港线。
2. 国内出仓:整柜通过报关等门禁并确认离仓,系统开始船节点跟踪。 2. 国内送港:送港线记录拖车、仓库离开、进港和甩柜;客户报关确认不阻断送港,进港不等于报关完成。
3. 海外尾程出库:海外仓库存经排车/PDA 作业离仓,出库单为 `OUTBOUNDED`。 3. 海运起点:承运船舶真实开航后才进入海运节点,预计 ETD 不推进海运中。
4. 海外尾程出库:海外仓库存经排车/PDA 作业离仓,出库单为 `OUTBOUNDED`。
### 1.1 操作与交接总表 ### 1.1 操作与交接总表
@@ -63,10 +65,10 @@
| 8 | 国内履约运营 / Admin | 创建模拟柜,选择候选,人工/智能排柜 | 生成稳定柜次、预装计划、分配明细和容量占用 | 订舱/柜务运营 | | 8 | 国内履约运营 / Admin | 创建模拟柜,选择候选,人工/智能排柜 | 生成稳定柜次、预装计划、分配明细和容量占用 | 订舱/柜务运营 |
| 9 | 订舱/柜务运营 / Admin | 建订舱草稿、补资料、放舱,关联柜次并录入真实柜号 | 冻结订舱和运输快照,建立订舱需求与柜次分配关系 | 国内履约运营 | | 9 | 订舱/柜务运营 / Admin | 建订舱草稿、补资料、放舱,关联柜次并录入真实柜号 | 冻结订舱和运输快照,建立订舱需求与柜次分配关系 | 国内履约运营 |
| 10 | 国内履约运营 / Admin | 核对预装清单并确认 | 固化预装快照,生成或开放国内 PDA 任务 | 国内 PDA | | 10 | 国内履约运营 / Admin | 核对预装清单并确认 | 固化预装快照,生成或开放国内 PDA 任务 | 国内 PDA |
| 11 | 国内 PDA | 扫箱/整托拣货,批量提交,拍四步照片和铅封,完成装柜 | 计划 `COMPLETED`、入库单 `LOADED`,发布最终实装事件 | 报关/出仓运营 | | 11 | 国内 PDA | 扫箱/整托拣货,批量提交,拍五类证据和锁码,完成装柜 | 计划 `COMPLETED`、入库单 `LOADED`,发布最终实装事件并启动报关/送港两条线 | 报关/送港运营 |
| 12 | 报关运营 / Admin | 上传出口报关资料并完成报关 | 报关状态完成;系统自动尝试收敛国内出仓门禁 | 出仓运营/系统 | | 12 | 报关运营 / Admin、Client | `LOADED` 后收集客户资料、发报关行、上传回执、发客户确认;打回则重做,所有客户通过后提交整柜正式申报 | 每客户确认轮次可追溯;整柜正式申报后记录查验/放行,不把回执上传当成客户确认 | 报关运营/客户 |
| 13 | 出仓运营 / Admin | 自动未收敛时,在柜次门禁面板点击“确认离仓” | 整柜进入已离仓事实,自动建船节点任务和 `DEPARTED_WAREHOUSE` | 船务/海外运营 | | 13 | 送港运营 / Admin | 独立安排拖车、离仓、送港和进港;容量不足记录甩柜/改配 | 写入 `DEPARTED_WAREHOUSE`、`PORT_RECEIVED` 或 `ROLLED_OVER`,不等待报关客户确认 | 船务/海外运营 |
| 14 | 船务 / Admin、第三方 | 查看自动轨迹,缺失时按权限补录真实节点 | 实际节点单调推进;到 `PICKUP_READY` 后开放海外 PDA 候选 | 海外计划运营、海外 PDA | | 14 | 船务 / Admin、第三方 | 只在承运船舶真实开航后查看/补录船节点 | 写入 `VESSEL_DEPARTED` 并进入海运节点;到 `PICKUP_READY` 后开放海外 PDA 候选 | 海外计划运营、海外 PDA |
| 15 | 海外计划运营 / Admin | 在尾程订单按柜预览阻断项并确认转换入仓计划 | `PENDING_ASSIGNMENT → INBOUND_PLANNED`;逐票建计划并生成/绑定托盘资源 | 海外 PDA | | 15 | 海外计划运营 / Admin | 在尾程订单按柜预览阻断项并确认转换入仓计划 | `PENDING_ASSIGNMENT → INBOUND_PLANNED`;逐票建计划并生成/绑定托盘资源 | 海外 PDA |
| 16 | 海外 PDA | 选柜锁定,拍车牌/封签/开柜照片,确认签收 | 建立柜级收货会话,冻结实际接柜仓和操作员 | 海外 PDA | | 16 | 海外 PDA | 选柜锁定,拍车牌/封签/开柜照片,确认签收 | 建立柜级收货会话,冻结实际接柜仓和操作员 | 海外 PDA |
| 17 | 海外 PDA | FBA 按 SKU+箱数收货,OVERSEAS 按箱唛逐箱收货,完成整柜 | 尾程进入 `INBOUND_COMPLETED`;生成库存余额、仓位、托盘、流水并回写国内 | 海外排车运营 | | 17 | 海外 PDA | FBA 按 SKU+箱数收货,OVERSEAS 按箱唛逐箱收货,完成整柜 | 尾程进入 `INBOUND_COMPLETED`;生成库存余额、仓位、托盘、流水并回写国内 | 海外排车运营 |
@@ -239,43 +241,37 @@
装柜证据: 装柜证据:
- 空仓、半仓、满仓、锁仓四步照片; - 空仓、半仓、满仓、锁仓、带锁码照五类证据和锁码文本;
- 带有效铅封号的铅封证据;
- 同类可追加,错误证据作废并保留审计,不硬删除历史。 - 同类可追加,错误证据作废并保留审计,不硬删除历史。
最终完成门禁:全部计划明细核平、五类有效证据齐全、铅封号存在且真实柜号已就绪。完成后装柜计划为 `COMPLETED`,来源入库单为 `LOADED`。 最终完成门禁:全部计划明细核平、五类有效证据齐全、铅封号存在且真实柜号已就绪。完成后装柜计划为 `COMPLETED`,来源入库单为 `LOADED`。
### 6.3 出口报关与国内出仓 ### 6.3 报关线与送港线
入口:Admin → 货柜管理 → 柜次详情/国内出仓。 入口:Admin → 货柜管理 → 柜次详情;客户确认入口为 Client → 头程订单 → 报关资料。
当前整柜出仓门禁: **报关线**按客户案例推进:
| 门禁 | 要求 | 1. `LOADED` 后通知报关行,按客户/入仓码收集资料并发送;
|---|---| 2. 授权人员上传报关行本轮回执,客户查看并确认;
| 扣货 | 柜内入库单均未被扣货 | 3. 客户打回时保存原因,重新上传/替换资料,重新发送报关行并生成新回执轮次;
| 入库单 | 所有绑定入库单为 `LOADED` | 4. 柜内所有客户均确认后,冻结整柜资料并提交报关行正式申报;
| 装柜计划 | `COMPLETED` | 5. 记录查验、不查验放行、补件/退回等海关结果。
| 国内 PDA | 拣货任务 `COMPLETED` |
| 订舱 | 已放舱并分配当前柜次,状态 `RELEASED` |
| 装柜证据 | 四步照片和有效铅封齐全 |
| 出口报关 | 整柜报关 `COMPLETED` |
拖车状态和独立船期当前只作为参考,不属于服务端硬门禁。出口报关完成后,系统会在全部门禁满足时自动尝试确认离仓;若未自动收敛,平台可在“国内出仓门禁”面板点击“确认离仓”。 **送港线**独立推进:
成功结果: 1. 校验 `LOADED`、真实柜号、订舱和拖车条件,安排车辆离仓、送港和进港;
2. 写入唯一 `DEPARTED_WAREHOUSE` 和 `PORT_RECEIVED` 事实;
3. 船舱不足时写入 `ROLLED_OVER`,保存原船次、改配船次、滚动次数和客户通知;
4. 送港线不等待客户报关确认,报关线也不等待送港完成。
- 整柜出仓状态进入 `WAITING_FOR_LOADING`(现有内部编码,业务含义是已确认离开国内仓); 只有承运船舶真实开航才写入 `VESSEL_DEPARTED` 并进入海运节点。预计 ETD、已离仓或已进港不能显示为海运中。
- 只写一次整柜离仓历史;
- 自动创建唯一船节点查询任务和第一条实际 `DEPARTED_WAREHOUSE`;
- 尝试完成同订舱关联的国内拖车单;
- 已产生实际离仓节点后不得撤销。
## 7. 阶段四:海运节点、跨区尾程建单和海外入仓 ## 7. 阶段四:海运节点、跨区尾程建单和海外入仓
### 7.1 船节点推进 ### 7.1 船节点推进
船节点任务由国内出仓自动创建,不能由操作员另造一套。标准实际节点按以下顺序单调推进: 船节点任务在承运船舶真实开航后幂等创建,不能由操作员另造一套。标准实际节点按以下顺序单调推进:
`DEPARTED_WAREHOUSE → AT_ORIGIN_PORT → LOADED_ON_VESSEL → DEPARTED_ORIGIN_PORT → IN_TRANSIT → ARRIVED_DESTINATION_PORT → DISCHARGED_FROM_VESSEL → PICKUP_READY → PICKED_UP → EMPTY_RETURNED` `DEPARTED_WAREHOUSE → AT_ORIGIN_PORT → LOADED_ON_VESSEL → DEPARTED_ORIGIN_PORT → IN_TRANSIT → ARRIVED_DESTINATION_PORT → DISCHARGED_FROM_VESSEL → PICKUP_READY → PICKED_UP → EMPTY_RETURNED`
@@ -481,8 +477,8 @@ OVERSEAS:
1. 费用不再阻断待分柜。旧测量文档把“发送费用给客户”写成入库成功节点;当前 Firstleg 口径是测量审核通过后直接进入 `WAIT_SPLIT`,费用独立版本化。 1. 费用不再阻断待分柜。旧测量文档把“发送费用给客户”写成入库成功节点;当前 Firstleg 口径是测量审核通过后直接进入 `WAIT_SPLIT`,费用独立版本化。
2. 跨区事件不自动建海外入仓计划。旧海外验收手册曾写“装柜完成事件直接生成入仓计划”;当前只生成 `PENDING_ASSIGNMENT` 尾程订单,平台必须按柜预览并确认转换。 2. 跨区事件不自动建海外入仓计划。旧海外验收手册曾写“装柜完成事件直接生成入仓计划”;当前只生成 `PENDING_ASSIGNMENT` 尾程订单,平台必须按柜预览并确认转换。
3. 国内出仓硬门禁不含拖车和独立船期。当前服务端硬门禁是未扣货、入库单 `LOADED`、装柜计划/PDA完成、订舱 `RELEASED`、装柜证据与出口报关完成;拖车和独立船期仅展示参考。 3. `LOADED` 只校验物理装柜。报关线按客户回执确认、整柜正式申报和海关结果推进;送港线按拖车、离仓、进港和甩柜推进,两条线互不替代。
4. 国内出仓既有自动收敛也保留人工入口。出口报关完成后系统会自动尝试确认;未收敛时平台可在柜次或国内出仓页手工确认,二者共享同一服务端门禁与幂等结果。 4. 只有实际开船才进入海运节点。`DEPARTED_WAREHOUSE` 和 `PORT_RECEIVED` 是送港事实,`ROLLED_OVER` 是船次异常,预计 ETD 不推进海运中。
5. 真实柜号最迟时点存在历史指引差异。当前代码允许在 `EDITING/LOADING` 补录,但最终 PDA 完成前必须存在;为避免页面入口差异,正式操作统一要求预装确认前补齐。 5. 真实柜号最迟时点存在历史指引差异。当前代码允许在 `EDITING/LOADING` 补录,但最终 PDA 完成前必须存在;为避免页面入口差异,正式操作统一要求预装确认前补齐。
6. 尾程主状态与子单状态分开。入仓后主流程固定在 `INBOUND_COMPLETED`,排车、出库、派送、换标和转运的精确状态保存在子单,不得互相覆盖。 6. 尾程主状态与子单状态分开。入仓后主流程固定在 `INBOUND_COMPLETED`,排车、出库、派送、换标和转运的精确状态保存在子单,不得互相覆盖。
@@ -510,7 +506,10 @@ OVERSEAS:
- [ ] 模拟柜、订舱、真实柜号、预装计划和订单分配关系一致 - [ ] 模拟柜、订舱、真实柜号、预装计划和订单分配关系一致
- [ ] 国内 PDA 全部拣货,五类证据和铅封齐全 - [ ] 国内 PDA 全部拣货,五类证据和铅封齐全
- [ ] 装柜计划 `COMPLETED`,来源入库单 `LOADED` - [ ] 装柜计划 `COMPLETED`,来源入库单 `LOADED`
- [ ] 整柜出口报关完成,国内出仓成功并生成船节点任务 - [ ] 每个客户完成“资料→报关行回执→客户确认”,打回客户已重新上传、重新发送并生成新回执
- [ ] 所有客户确认后,整柜资料已提交报关行正式申报,并记录查验/放行结果
- [ ] 送港线已记录 `DEPARTED_WAREHOUSE`、`PORT_RECEIVED` 或 `ROLLED_OVER`
- [ ] 承运船舶实际开航后才生成 `VESSEL_DEPARTED` 和船节点任务
- [ ] 实际船节点到 `PICKUP_READY` 后海外 PDA 才看到柜号 - [ ] 实际船节点到 `PICKUP_READY` 后海外 PDA 才看到柜号
- [ ] 海外只先生成 `PENDING_ASSIGNMENT` 尾程订单,平台按柜转换计划成功 - [ ] 海外只先生成 `PENDING_ASSIGNMENT` 尾程订单,平台按柜转换计划成功
- [ ] 海外 PDA 三类签收照片齐全,FBA/OVERSEAS 按正确模式实收 - [ ] 海外 PDA 三类签收照片齐全,FBA/OVERSEAS 按正确模式实收
@@ -526,7 +525,7 @@ OVERSEAS:
- `docs/业务快速索引.md` - `docs/业务快速索引.md`
- `docs/订单与客户/订单与客户头程订单闭环设计.md` - `docs/订单与客户/订单与客户头程订单闭环设计.md`
- `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md` - `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md`
- `docs/国内货柜履约/货柜管理全链验收矩阵-2026-08-13.md` - `docs/国内货柜履约/归档/货柜管理全链验收矩阵-2026-08-13.md`
- `docs/海外仓业务/README.md` - `docs/海外仓业务/README.md`
- `docs/海外仓业务/虫虫出海全流程人工验收手册.md` - `docs/海外仓业务/虫虫出海全流程人工验收手册.md`
- `baiyue-firstleg/order/AGENTS.md` - `baiyue-firstleg/order/AGENTS.md`
@@ -536,3 +535,4 @@ OVERSEAS:
- `apps/pda-overseas-uniapp/AGENTS.md` - `apps/pda-overseas-uniapp/AGENTS.md`
本文用于统一业务操作和评审口径;接口字段、权限码、并发版本和错误码仍以对应 Controller、DTO、OpenAPI 与服务端状态机为最终依据。 本文用于统一业务操作和评审口径;接口字段、权限码、并发版本和错误码仍以对应 Controller、DTO、OpenAPI 与服务端状态机为最终依据。
@@ -461,3 +461,4 @@ P0 不改变核心状态机,主要是聚合查询、反馈和导航,风险
5. 国内/海外 PDA 接入稳定错误原因、恢复动作和操作回执。 5. 国内/海外 PDA 接入稳定错误原因、恢复动作和操作回执。
6. 完成 P0 人工验收和埋点基线后,再做表单向导、自动带出和批量体验。 6. 完成 P0 人工验收和埋点基线后,再做表单向导、自动带出和批量体验。
7. 最后基于真实操作数据决定 P2 的智能推荐和 SLA 预警,不凭主观增加自动化。 7. 最后基于真实操作数据决定 P2 的智能推荐和 SLA 预警,不凭主观增加自动化。
@@ -1,5 +1,7 @@
# 头程下单到尾程出库现状流程全景清单 # 头程下单到尾程出库现状流程全景清单
> **历史现状声明(2026-09-24)**:本文记录旧版 AS-IS 盘点,报关/送港的单线门禁、柜前资料和“四步证据”等内容不再作为当前业务依据。当前流程以 [头程到尾程流程节点梳理(重构版)](../../头程到尾程流程节点梳理.md)、[报关资料与船期价格接入梳理](../../国内货柜履约/报关资料与船期价格接入梳理.md) 和最新需求确认表为准:`LOADED` 后报关线与送港线并行,客户回执确认完成后整柜正式申报,甩柜独立记录,实际开船才进入海运节点。
> 文档性质:现状流程盘点(AS-IS),先描述现在业务怎么走,不在本文讨论页面改版或技术优化。 > 文档性质:现状流程盘点(AS-IS),先描述现在业务怎么走,不在本文讨论页面改版或技术优化。
> 覆盖起点:企业具备下单资格。 > 覆盖起点:企业具备下单资格。
> 主链终点:海外仓完成尾程出库;为保证交接完整,附带记录派送、异常退回和国内最终完成回写。 > 主链终点:海外仓完成尾程出库;为保证交接完整,附带记录派送、异常退回和国内最终完成回写。
@@ -568,7 +570,7 @@ INBOUND_COMPLETED
- `docs/入库测量与计费/README.md` - `docs/入库测量与计费/README.md`
- `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md` - `docs/入库测量与计费/入库测量与计费需求优化版-v2-测量计费入库主流程.md`
- `docs/国内货柜履约/README.md` - `docs/国内货柜履约/README.md`
- `docs/国内货柜履约/货柜管理全链验收矩阵-2026-08-13.md` - `docs/国内货柜履约/归档/货柜管理全链验收矩阵-2026-08-13.md`
- `docs/海外仓业务/README.md` - `docs/海外仓业务/README.md`
- `docs/海外仓业务/虫虫出海全流程人工验收手册.md` - `docs/海外仓业务/虫虫出海全流程人工验收手册.md`
- `baiyue-firstleg/order/AGENTS.md` - `baiyue-firstleg/order/AGENTS.md`
@@ -579,3 +581,4 @@ INBOUND_COMPLETED
- `apps/client-web/AGENTS.md` - `apps/client-web/AGENTS.md`
- `apps/pda-uniapp/AGENTS.md` - `apps/pda-uniapp/AGENTS.md`
- `apps/pda-overseas-uniapp/AGENTS.md` - `apps/pda-overseas-uniapp/AGENTS.md`
@@ -1,5 +1,7 @@
# 头程到尾程 AI 流程优化上下文包 # 头程到尾程 AI 流程优化上下文包
> **规则基线声明(2026-09-24)**:本文中的旧状态表和阶段合同可能保留历史口径,不能覆盖当前流程。当前分析必须先采用 [头程到尾程流程节点梳理(重构版)](../../头程到尾程流程节点梳理.md) 和 [报关资料与船期价格接入梳理](../../国内货柜履约/报关资料与船期价格接入梳理.md):`LOADED` 后报关线、送港线并行,客户逐轮确认后整柜正式申报,送港可甩柜,实际开船后才进入海运节点。
> 用途:给 AI、产品、业务和技术提供同一份优化输入规范。本文不替代六阶段现状文档,也不直接改变状态机;它定义分析顺序、术语、证据、指标、输出格式和实施门禁,防止 AI 只根据局部页面提出脱离业务事实的建议。 > 用途:给 AI、产品、业务和技术提供同一份优化输入规范。本文不替代六阶段现状文档,也不直接改变状态机;它定义分析顺序、术语、证据、指标、输出格式和实施门禁,防止 AI 只根据局部页面提出脱离业务事实的建议。
## 1. 第二轮完整性审计结论 ## 1. 第二轮完整性审计结论
@@ -34,7 +36,7 @@
优化分析的默认入口: 优化分析的默认入口:
- 总览:[分阶段流程目录](头程到尾程分阶段流程/README.md) - 总览:[分阶段流程目录](../../头程到尾程分阶段流程/README.md)
- 操作:[全流程操作手册](头程下单到尾程出库全流程操作手册.md) - 操作:[全流程操作手册](头程下单到尾程出库全流程操作手册.md)
- 现状:[现状流程全景清单](头程下单到尾程出库现状流程全景清单.md) - 现状:[现状流程全景清单](头程下单到尾程出库现状流程全景清单.md)
- 方案:[易用性与数据流转优化方案](头程下单到尾程出库流程易用性与数据流转优化方案.md) - 方案:[易用性与数据流转优化方案](头程下单到尾程出库流程易用性与数据流转优化方案.md)
@@ -294,3 +296,4 @@ AI 应优先:复用服务端权威动作与门禁、减少重复输入、显
10. 国内离仓、海外入仓、海外出库和最终签收的客户可见进度语义。 10. 国内离仓、海外入仓、海外出库和最终签收的客户可见进度语义。
每项决定应记录:结论、负责人、确认日期、影响阶段、是否改变接口/状态/权限,以及需要更新的文档。未决定项保持“待确认”,不能由 AI 默认选择。 每项决定应记录:结论、负责人、确认日期、影响阶段、是否改变接口/状态/权限,以及需要更新的文档。未决定项保持“待确认”,不能由 AI 默认选择。
@@ -182,7 +182,7 @@ baiyue-firstleg/
## 6. 自动编号和文件命名 ## 6. 自动编号和文件命名
SQL 迁移使用每个 schema 内递增的整数序号,由创建工具生成。业务版本、Git commit 和 Jenkins 构建号只用于发布追踪,不参与 SQL 序号计算。无需开发人工决定“这次是 0.0.10 还是 0.0.11”。 2026-09-22 确认:SQL 迁移保持 `V1、V2、V3、V4、V5……`,每个 schema 独立递增,由创建工具生成,不采用时间戳编号。序号随变更自然增长,不因位数增加而重置、归零或重新编号。生产发布版本、Git commit 和 Jenkins 构建号只用于发布追踪,不参与 SQL 序号计算。
```text ```text
migrations/cn/baiyue_order/V1__add_order_reference.sql migrations/cn/baiyue_order/V1__add_order_reference.sql
@@ -225,6 +225,24 @@ migrations/cn/baiyue_auth/V1__create_login_audit_table.sql
- 同一库内按完整版本链推进,不按某个服务或某个文件跳过中间版本。该库随包包含的其他待执行变更必须一并评审;尚不具备发布条件时阻断本候选,不通过删文件、临时降低目标或开启乱序绕过。 - 同一库内按完整版本链推进,不按某个服务或某个文件跳过中间版本。该库随包包含的其他待执行变更必须一并评审;尚不具备发布条件时阻断本候选,不通过删文件、临时降低目标或开启乱序绕过。
- 例如只发布 Auth,且与 Firstleg 无依赖,则只核验并迁移 Auth 的必要库。同一提交中 Firstleg 的待执行 SQL 不被带入;若 Auth 确实依赖 Firstleg 的新结构,则先补齐发布范围和测试证据再发布。 - 例如只发布 Auth,且与 Firstleg 无依赖,则只核验并迁移 Auth 的必要库。同一提交中 Firstleg 的待执行 SQL 不被带入;若 Auth 确实依赖 Firstleg 的新结构,则先补齐发布范围和测试证据再发布。
### 6.3 功能分支与生产发布编号
以下为确认的发布工作流;跨分支检查和发布编号自动分配尚待流水线实现,不代表当前工具已经提供这些门禁。
| 记录 | 示例 | 增长规则 |
|---|---|---|
| 单库 SQL 迁移编号 | Auth 的 `V1`、`V2`;Order 的 `V1`、`V2` | 该库新增数据库逻辑变更时自动生成;普通提交、重复构建和重复部署不增加 |
| 生产发布版本 | `release-1`、`release-2` | Jenkins 为新的生产发布候选自动分配,不要求开发手工维护版本文件;只有发布成功才更新当前生产版本 |
生产发布版本与 SQL 编号不绑定。例如 `release-12` 可以对应 Auth `V3`、Order `V7`;纯代码发布仍有新发布版本,但数据库目标不变。发布编号须在受保护记录中唯一分配,失败编号不回收;同一制品重试沿用原发布编号,修改代码、SQL 或其他制品内容后分配新编号并重新验证。`release-13` 失败时保留失败记录,当前生产版本仍为最近成功版本;各库和服务的实际状态另行记录,不能据此假定没有发生部分更新。
1. 功能分支从最新 `main` 创建,代码与 SQL 在同一分支维护;这里约定后续团队流程,不自动创建或切换本次工作区分支。
2. 进入共享测试前,拉取并合并最新 `main`,检查同库重复编号和执行顺序。冲突只调整尚未冻结、未在保留历史环境执行的草稿;成功文件不改内容、不改编号,修复使用新增迁移。冻结失败候选只能按第 13.2.1 节处理。
3. 两人可以并行开发;共享测试同一时间只验收一个待合并功能。前一功能测试通过、合并并完成发布或处理失败后,下一功能同步最新 `main` 再进入测试,避免未合并 SQL 污染其他功能的验证起点。
4. 测试结果绑定提交和 SQL 哈希;合并前重新检查 `main` 是否变化,变化时同步并重新验证,不能仅凭“以前拉取过 main”放行。
5. 合并后的 `main` 构建正式候选并再次自动验证;生产使用该正式候选原制品。功能分支测试证据不自动等同于合并后候选证据;已成功的 SQL 保持原编号及内容,由数据库历史决定跳过或执行。
6. 发布记录绑定 `release-N`、`main` 的完整提交、镜像 digest、SQL 清单及各库版本,并保存成功发布的 Git 标签。`main` 表示已合并代码,实际生产版本以成功发布记录为准,不通过分支名称推断数据库历史。
## 7. 迁移类型 ## 7. 迁移类型
### 7.1 版本迁移 ### 7.1 版本迁移
@@ -581,7 +599,7 @@ MySQL DDL 可能已隐式提交,不能假定整个文件自动回滚。按以
- Jenkins 构建号。 - Jenkins 构建号。
- Git commit 和镜像标签。 - Git commit 和镜像标签。
- 发布身份、清单/SQL 包 SHA-256、各镜像 digest、审批及发布锁状态。 - 发布身份、清单/SQL 包 SHA-256、各镜像 digest、审批及发布锁状态。
- 候选制品身份、可选的业务发布标签,以及对应测试通过记录;不维护独立手工 SQL 发布版本。 - 候选制品身份、生产发布版本 `release-N`、发布状态及对应测试通过记录;不维护独立手工 SQL 发布版本,编号规则见第 6.3 节。
- 环境与区域。 - 环境与区域。
- schema 名称。 - schema 名称。
- Flyway 镜像版本。 - Flyway 镜像版本。
@@ -651,6 +669,7 @@ MySQL DDL 可能已隐式提交,不能假定整个文件自动回滚。按以
- 实现 `plan/run` 及分阶段校验配置,在获授权的隔离数据库验证原始 SQL、首次执行、重复执行、结构断言与失败恢复;验证单服务范围隔离,并用应用预期结构及实际读写测试发现漏写迁移。 - 实现 `plan/run` 及分阶段校验配置,在获授权的隔离数据库验证原始 SQL、首次执行、重复执行、结构断言与失败恢复;验证单服务范围隔离,并用应用预期结构及实际读写测试发现漏写迁移。
- 单服务 Job 先支持构建与部署解耦;总控固定为“全部目标镜像就绪 -> SQL 阶段 -> 同批镜像部署”,此能力必须先于共享测试接入完成。 - 单服务 Job 先支持构建与部署解耦;总控固定为“全部目标镜像就绪 -> SQL 阶段 -> 同批镜像部署”,此能力必须先于共享测试接入完成。
- 全部独立部署入口纳入环境锁和候选资格校验,补齐归档保护、镜像保留、未决状态及撤销记录;禁止旧 Job 绕过新的 SQL 门禁。 - 全部独立部署入口纳入环境锁和候选资格校验,补齐归档保护、镜像保留、未决状态及撤销记录;禁止旧 Job 绕过新的 SQL 门禁。
- 接入第 6.3 节的 main 同步检查、分支编号冲突检查和合并后候选验证;自动分配并保护 `release-N`,同一候选重试不换号,成功后更新生产版本和发布标签。
- 对从未成功、未进入生产的失败候选验证第 13.2.1 节修订链;对已成功或生产尝试过的文件验证例外被拒绝。 - 对从未成功、未进入生产的失败候选验证第 13.2.1 节修订链;对已成功或生产尝试过的文件验证例外被拒绝。
### 阶段 D:共享测试完整演练 ### 阶段 D:共享测试完整演练
+42 -150
View File
@@ -1,159 +1,51 @@
# 开发/测试环境 Jenkins API 自动部署指南 # TEST 环境 Jenkins 部署指南
> 最后核对:2026-08-25 更新日期:2026-09-29。本指南描述唯一 TEST 单机目标;仓库配置已收敛不表示实际服务器已部署。统一架构切换与验收以[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md)为准。
>
> 只适用于当前开发、测试阶段。生产环境启用后必须重新收紧权限、轮换并移除开发 Token。
## 1. 使用场景 ## 授权与边界
本指南用于长时间全量测试或夜间任务。用户在当前对话明确要求“持续修复并部署”“自动部署并测试”或等价表述后,工具可以在本次授权范围内循环执行: 默认只做本地修改与离线检查。实际Jenkins构建发布、Nacos发布、SQL和清理分别落实本轮授权范围;本指南不授予持续部署权限。不得读取或覆盖其他任务维护的真实生产/测试凭据。运行事实与本目标不一致时先核对,不自行改名或删除运行环境。
`定位失败 → 修改代码 → 本地门禁 → 提交并推送 → API 部署 → 等待终态 → 健康/业务验收 → 继续修复` ## 唯一发布入口
同一轮任务不需要每次提交或重试都重新询问。以下情况仍必须停下确认: | 对象 | 入口 |
- 涉及预发布或生产环境。
- 需要执行 SQL、初始化数据库、修改真实数据或清理容器/数据。
- 需要跳过测试、停止他人构建或扩大到未授权服务。
- 缺少环境凭据,或连续三次遇到同一个外部阻断。
## 2. 本机一次性配置
Jenkins API 信息固定保存在以下未提交文件:
`C:/Users/BY-OY/.codex/jenkins-api.env`
文件格式:
```dotenv
JENKINS_URL=https://jenkins.example.com
JENKINS_USER=admin
JENKINS_API_TOKEN=replace-with-current-development-token
DEV_GATEWAY_URL=https://dev-api.example.com
TEST_GATEWAY_URL=https://test-api.example.com
```
工具直接读取该文件,不把 Token 输出到 commentary、最终回复、命令日志或仓库。使用 API Token 的 Jenkins 请求不需要 CSRF Crumb。
连通性检查:
```bash
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
"${JENKINS_URL%/}/api/json?tree=nodeName,mode"
```
## 3. Job 对照
| 环境 | 后端总控 | Admin | Client | 后端分支 | 下游前缀 |
|---|---|---|---|---|---|
| 开发 | `backend-java-dev` | `admin-web-dev` | `client-web-dev` | `dev` | `baiyue-firstleg-dev-` |
| 测试 | `backend-java` | `admin-web-test` | `client-web-test` | `test` | `baiyue-firstleg-` |
后端可部署服务:
`gateway`、`gateway-overseas`、`auth`、`iam`、`firstleg`、`finance`、`order`、`warehouse`、`file`、`print`、`integration-service`、`lastleg-service`、`warehouse-overseas-service`、`event-bridge-service`、`audit-service`。海外安全投影随 `lastleg-service` 部署,不再有独立 Job。
正常从总控 Job 发起。只有重跑同一提交的单个失败服务时,才直接触发下游 Job。
## 4. API 触发
### 4.1 前端
```bash
curl -fsS -X POST \
--user "$JENKINS_USER:$JENKINS_API_TOKEN" \
-D build.headers -o /dev/null \
"${JENKINS_URL%/}/job/admin-web-dev/build"
```
按目标环境和应用替换 Job 名称。
### 4.2 后端
开发环境选择两个服务的示例:
```bash
curl -fsS -X POST \
--user "$JENKINS_USER:$JENKINS_API_TOKEN" \
-D build.headers -o /dev/null \
--data-urlencode 'BUILD_MODE=SELECT' \
--data-urlencode 'SERVICE_GATEWAY_OVERSEAS=true' \
--data-urlencode 'SERVICE_LASTLEG=true' \
--data-urlencode 'ENVIRONMENT=development' \
--data-urlencode 'DEPLOY=true' \
--data-urlencode 'SKIP_TESTS=false' \
--data-urlencode 'EVENT_BRIDGE_REGION=BOTH' \
--data-urlencode 'DOWNSTREAM_JOB_PREFIX=baiyue-firstleg-dev-' \
"${JENKINS_URL%/}/job/backend-java-dev/buildWithParameters"
```
规则:
- 日常优先 `AUTO`;明确修复单个或少量服务时使用 `SELECT`。
- `SELECT` 只把目标 `SERVICE_*` 设为 `true`,其余保持 `false`。
- `ALL` 只用于用户明确授权的全量部署。
- 开发环境固定 `ENVIRONMENT=development`;测试固定 `ENVIRONMENT=test`。
- 开发/测试默认 `DEPLOY=true`、`SKIP_TESTS=false`。
- 事件桥默认 `BOTH`;单区故障重跑才使用 `CN` 或 `OVERSEAS`。
- 不在 API 参数中传密码、数据库凭据或服务 Token。
## 5. 自动等待终态
触发响应的 `Location` 是队列地址:
```bash
QUEUE_URL="$(awk 'BEGIN{IGNORECASE=1} /^Location:/{gsub("\r",""); print $2}' build.headers)"
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
"${QUEUE_URL%/}/api/json?tree=id,why,cancelled,executable[number,url]"
```
出现 `executable.url` 后,将其作为 `BUILD_URL`:
```bash
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
"${BUILD_URL%/}/api/json?tree=number,building,result,url,duration,estimatedDuration"
```
每 5–10 秒轮询一次。只有 `building=false` 且 `result=SUCCESS` 才成功;进入队列、拿到构建号或 HTTP POST 成功都不算完成。后端总控还必须确认每个下游 Job 都是 `SUCCESS`。
失败时读取:
```bash
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
"${BUILD_URL%/}/consoleText"
```
删除本次产生的临时 `*.headers` 文件,不提交。
## 6. 夜间自动闭环
1. 记录目标环境、服务和远端 commit。
2. 运行直接受影响的本地测试;签名变化必须编译测试源码。
3. 只提交当前修复文件并推送目标分支。
4. 用 API 触发对应 Job,保存队列 URL、构建 URL 和构建号。
5. 等待总控及全部下游进入终态。
6. 失败时读取第一个有效错误,修改后使用新 commit 再部署。
7. 网络抖动、镜像拉取等瞬时基础设施错误允许同一提交重试,最多两次。
8. 部署成功后检查 Gateway `/actuator/health`,再执行本轮真实 API/全量测试。
9. 全部通过后汇总 commit、构建号、服务结果和验收结果。
不要因为某个服务失败就盲目重跑全量;优先修复并只重跑失败服务。部署脚本会在新容器不健康时自动回滚,任务仍视为失败。
## 7. 快速故障判断
| 现象 | 处理 |
|---|---| |---|---|
| `401` | 检查本机 API Token 和反向代理 `Authorization` 头 | | 后端总控 | `backend-java`,仓库 `baiyue-firstleg/Jenkinsfile` |
| `403` | 检查 Job Read/Build 权限;不要关闭 CSRF | | 后端单服务 | `baiyue-firstleg-<module>`,`Jenkinsfile.service` |
| `400` | 参数名或 Choice 值与当前 Job 不一致 | | 构建/部署节点 | `java-builder` / 同机 `java-test` |
| 队列长期等待 | 查询队列 `why`,检查节点、执行器和部署锁 | | 环境凭据 | Jenkins Secret File `firstleg-test-env`,真实值不入库 |
| Maven/测试失败 | 修复代码并产生新 commit,不跳过测试 | | 服务与镜像列表 | [service-map.yml](../baiyue-firstleg/deploy/service-map.yml) |
| 容器不健康 | 读取 Job 自动采集的容器日志和回滚结果 | | Compose | [docker-compose.yml](../baiyue-firstleg/deploy/docker-compose.yml),项目 `firstleg-test` |
| 镜像被其他任务覆盖 | 核对同服务部署锁和实际运行镜像标签 | | 环境模板 | [.env.test.example](../baiyue-firstleg/deploy/env/.env.test.example) |
| 总控成功但下游失败 | 整体仍按失败处理,只重跑失败服务 | | Nacos | [config/nacos/test](../baiyue-firstleg/config/nacos/test/README.md),14个Data ID、一个实际Namespace ID |
| 执行顺序与恢复 | [TEST单机部署执行清单](../baiyue-firstleg/deploy/TEST单机部署执行清单.md) |
## 8. 完成记录 保留13个服务:gateway、auth、iam、order、firstleg、finance、warehouse、warehouse-overseas-service、lastleg-service、file、print、audit-service、integration-service。Gateway Overseas、两区Event Bridge不在新发布清单。停旧服务必须等统一认证、直接投递、撤销和四端切换验证完成;源码退役不等于获准停止当前服务。
最终只需记录:环境、Job、服务、分支、commit、Jenkins 构建号、最终结果、健康检查、业务验收及剩余阻断。不得输出 Token、Cookie、Jenkins Credential 或环境文件内容。 旧开发/生产Job不再匹配当前流水线,不能借环境参数使本版本执行生产部署。已有其他环境应由其独立明确授权任务处理,不在本次TEST发布中操作。
参考:[Jenkins Remote Access API](https://www.jenkins.io/doc/book/using/remote-access-api/)、[Jenkins CSRF Protection](https://www.jenkins.io/doc/book/security/csrf-protection/)。 ## 参数与门禁
总控支持AUTO、SELECT、ALL。AUTO保留失败服务重试与直接依赖识别;架构首次切换使用审核后的完整匹配发布清单,不以AUTO遗漏服务。ENVIRONMENT仅test,下游前缀仅baiyue-firstleg-。DEPLOY默认false;IMAGE_REPOSITORY必须替换为已核镜像仓库,DOCKER_BASE_IMAGE由构建节点可访问的Java17镜像提供。不得将凭据拼入参数、URL或日志。
默认执行Maven测试;仅明确选择SKIP_TESTS时跳过执行,仍编译测试源码。总控先统一测试,再向固定commit的单服务任务传递跳过重复执行。发布前还须完成网关路由、部署拓扑、失败回滚和受影响前端合同。离线检查不能证明镜像健康或HTTP闭环。
同机测试代理的执行器数量固定为1,避免构建与其他重任务挤占业务服务。总控测试和单服务打包还必须共用 `firstleg-test-maven` 跨Job锁,经 `deploy/scripts/run-ci-maven.sh` 执行;仅 `disableConcurrentBuilds()` 不能限制不同Job并发。入口按同一构建账号使用本机flock,控制端掉线后已有任务仍持锁时拒绝再起Maven,不删除锁文件绕过互斥。部署的SOURCE_COMMIT必须包含此入口及 `ci-bounded` POM配置,旧提交缺少防护时应失败,不能回退到裸mvn。
当前初始预算:Maven堆768MiB、测试堆1GiB、单测试fork,并分别限制元空间和直接内存;Surefire保留JaCoCo,启用父进程心跳检查、停止时kill、fork运行20分钟和退出30秒上限。宿主机GNU timeout提供45分钟期限及30秒强制终止,Jenkins内部另设50分钟上限。预算不是总RSS保证,须在真实Linux节点核对代理内存、memory.events/pressure和完整服务测试峰值;不足时按证据调整,不能重新放开三个Maven并发,也不能仅提高MemoryHigh挤占业务服务。代理服务保持 `KillMode=control-group`、`SendSIGKILL=yes`;代理掉线或构建中止后,先检查该服务cgroup是否仍有构建/测试子进程,确认退出再恢复,不把Job的ABORTED当作进程已清理。
单服务任务在取目标节点执行器前锁定对应服务,目标节点通过同一env文件拉镜像并更新容器。没有HEALTHCHECK、启动失败、不健康、退出或超时均判失败。只有同协议同Schema版本才可显式启用ALLOW_SAME_CONTRACT_ROLLBACK;架构切换保持false,恢复原则见执行清单。
## 配置与端侧
容器共用firstleg-test-network;同网络Web Nginx使用http://gateway:9000。Gateway宿主机发布仅127.0.0.1,业务服务只内部expose。Auth使用http://auth:9100,不能把Nacos应用名当Docker DNS。宿主机中间件通过host.docker.internal访问,不能使用容器localhost。
所有服务使用同一Nacos Namespace ID/Group、Redis DB与会话前缀。Auth独占签名私钥;JWKS和内部会话验证共用Auth。EVENT_OPERATIONS_TOKEN独立于内部业务令牌,留空禁用运维操作。现有文件卷和非桥业务MQ保留,topic/group使用test-前缀。
Admin与Client各自Compose项目共接后端网络,发布必须给出CLIENT_WEB_URL/VITE_ADMIN_WEB_ORIGIN;两个PDA保留独立产物及仓绑定。域名、Namespace ID、MQ范围、数据卷和主机容量必须据实际清单核实,不能用模板默认值充当验收。
## 发布与验收
按执行清单记录镜像、配置、SQL与四端版本,在停写窗口发布完整匹配版本。SQL不由Compose/Jenkins自动运行,初始化脚本仅接受两份显式审核的空库基线并受授权开关保护。禁止整机清空Redis/MQ/文件。
启动就绪后先验证统一登录/撤销/隔离/仓绑定、资源查询和文件,再用新造数据验证装柜至尾程、资金指令结果回传及故障恢复。真实API通过后还需页面/PDA验收。未部署、未验证项目必须明确标记;不能以Job成功替代整条业务链完成。
File diff suppressed because it is too large Load Diff
+91 -9
View File
@@ -1,10 +1,9 @@
# 海外仓业务范围与快速索引 # 海外仓业务范围与快速索引
## 已确认业务边界 ## 已确认业务边界
- 当前开发环境按端到端全流程交付,不再用开发批次切断上下游。订单与客户、入库测量与计费、国内货柜履约、海外仓业务和财务共同组成一条连续业务链。 - 当前开发环境按端到端全流程交付,不再用开发批次切断上下游。订单与客户、入库测量与计费、国内货柜履约、海外仓业务和财务共同组成一条连续业务链。
- 海外仓业务从国内装柜完成及确认出仓后的船节点开始,覆盖海运在途、海外接柜、卸货入仓、库存与托盘、换标、转运、废弃、退货、排车、PDA 拣货与出库、发车、转派送、派送完成、异常退回、客户回访和一件代发。 - 海外仓业务从国内装柜完成及确认出仓后的船节点开始,覆盖海运在途、海外接柜、卸货入仓、库存与托盘、换标、转运、废弃、退货、排车、PDA 拣货与出库、发车、转派送、派送完成、异常退回、客户回访和一件代发。
- 海外采购、本土卡车、本土散板、海外仓报价、汇率和车辆主数据属于同一海外业务域,并统一经 `gateway-overseas/` 访问。 - 海外采购、本土卡车、本土散板、海外仓报价、汇率和车辆主数据属于同一海外业务域,并统一经当前 `gateway/` 访问。
- 功能是否可用以正式路由、Controller/OpenAPI、权限、数据库结构和验收证据为准;历史规划只用于追溯,不再用于排除已经纳入全流程的能力。 - 功能是否可用以正式路由、Controller/OpenAPI、权限、数据库结构和验收证据为准;历史规划只用于追溯,不再用于排除已经纳入全流程的能力。
## 人工验收入口 ## 人工验收入口
@@ -13,19 +12,79 @@
## 功能快速路由 ## 功能快速路由
- [排车列表统一作业改造契约](排车列表统一作业改造契约.md):五阶段排车、一单一趟、跨客户同车、派送安排及四块排车详情的当前改造入口。
- [排车流程修复规划](排车流程修复规划.md):排车撤销、派送状态、换标全托、合托来源及草稿交互的修改范围、分工与回归要求。
- [采购订单样品履约流程变更需求](采购订单样品履约流程变更需求.md):采购样品购买、装箱、面单、交寄、国内核费与寄客户的变更入口。
- [美国预约管理统一总览与优化方案](美国预约管理统一总览与优化方案.md):提柜、用车、FBA及普通送货等统一展示的需求梳理与设计建议。
- [预约工作日历 V13 变更说明](预约工作日历V13变更说明.md):已确认的多客户共车、分批后送、改期取消、重新预约、未定日期及下一步操作规则和验收场景。
- [预约工作日历开发协作契约](预约工作日历开发协作契约.md):工作日历的接口、数据归属与唯一文件写者;不是已实现或环境验收说明。
### 预约送仓
本轮变更行为以[预约工作日历 V13 变更说明](预约工作日历V13变更说明.md)为主入口。下述接口用于定位既有业务归属;涉及整票占用、分批、取消及重约的实现须按 V13 收敛,不能由接口入口存在推定本轮规则已全部实现。
内部历史展示读取仓库元数据使用`POST /internal/warehouses/platform-metadata/batch`,由Warehouse权威提供,内部服务令牌鉴权且不经公网Gateway。每批1至2000个不重复正数ID,只读平台公共仓的编号、名称、类型、国家、原时区和状态,包含停用仓;不存在、非公共或已删除的ID统一列为缺失,不返回联系人及客户数据。调用方不得把原固定偏移或缺失时区猜成IANA地点时区;国家/时区不明时单列待定位,不放入美国当地日期格。接口合同见Warehouse `warehouse-v1.yaml`。
仓库主档时区使用IANA地点标识(如`America/New_York`),不以固定UTC偏移表示当地时间。国内默认`Asia/Shanghai`;明确单一时区的美国州可自动选择,多时区或存在地方例外的州须按实际地址确认。新增、编辑和导入在Warehouse共用校验。初始化地址资料无法确定地点时区时保留为空并阻止正式预约确认;不根据旧偏移批量猜测或迁移现有主档。参考[IANA时区数据说明](https://www.iana.org/time-zones)。
- 预约以同一美国起运仓和目的FBA仓组织,允许多个客户的真实货源统一安排。未建入仓计划也可保存;同仓不同日期/时段、不同货物可以分别建约。主单不归属单一客户,客户归属保留在每票货物明细,库存、订单、费用及派送的客户隔离不随合并改变。
- 预约管理日历和入仓单中的预约操作共用 Lastleg 的 FBA 预约记录。平台可读取完整预约;客户只能经自己的订单/入仓单读取本客户货物,不开放跨客户预约详情。
- FBA日历按地点当地时段与查询范围相交读取,跨日安排在覆盖的每一天展示同一业务记录;午夜结束不占次日,仅日期安排只占当天。确认时段与计划时段成对选用,不用旧计划结束时间补齐未知确认结束时间。卡片保留完整起止日期,切换已加载日期不追加查询。
- 系统生成全局唯一AP业务单号,外部确认号单独保存并按目的FBA仓唯一。创建和编辑携带持久化幂等键、操作者及请求摘要,同键同内容返回原命令快照,即使后来编辑也不改变原结果;异内容拒绝。主单、明细和命令记录同事务。本轮分批后的占用按 V13 逐来源数量及有效批次身份收敛,不能继续用整票唯一占用阻断合法部分分配;取消后恢复原单或重约仍须重新核对当前占用。
- 计划日期、可选计划时段、对方确认时段分别保存;仅有日期不补09点/零点,未定日期进入未定时列表。PENDING允许外部约号及箱数暂缺,不伪造值;SUCCESS必须有真实货量、FBA货件号或追踪号、外部确认号以及目的仓权威IANA时区,校验夏令时并保存对应UTC时间点。结束时间未知保持空。预计装车归运输安排,不再作为FBA预约写入字段;没有权威装车事实的关联查询明确返回未知。
- 入仓明细入口仅用lineIds选择业务货物,服务端批量转换成原ORDER/BOOKING整票来源;外接来货后仍保持BOOKING键,禁止同时以ORDER别名建约。主表和明细只有一套,不并行维护“提前预约”副本。仓储转运的目的地和货件资料读取实际转运主记录,不能把未填充的尾程展示投影误报为目的地变化。
- 取消/未约成须记录原因,解除失效预约的有效覆盖/绑定,并保留原计划、确认事实和历史;仍需送货的批次数量与后续需求按 V13 第六至七节保留,不回退库存或使同一货量再次可选。已有有效排车时先核对并处理运输安排。编辑使用版本校验,已确认预约不能直接退回待确认。
- 用车计划来源读取Fleet日期范围接口,一车一条,保留计划/实际出发及司机任务预计结束的UTC时间点,不表示收货预约已确认。前端最多显示42个起运仓当地日期,通过前后各14小时的UTC检索余量覆盖跨日,已发车按实际出发时间、未发车按计划出发时间检索并逐条按权威地点时区落格,原计划保留供核对,改期不移动已执行事实;缺仓库、国家或时区时独立展示待定位记录,不用浏览器时区猜测。服务端UTC保护窗口最多44天,超过2000条明确拒绝并要求缩小范围,不逐页扫描或静默截断。读取仍需车次列表权限,正常一个车次SQL和一次内部仓库元数据批量调用;目录失败不可当作空结果。
- 提柜日历读取Firstleg原码头拖车记录,入口为`GET /api/platform/v1/terminal-drayages/calendar`,同时要求预约列表与码头拖车列表权限。按启用目的仓国家筛选美国业务范围,不推断港口国家;已提柜按船节点权威实际日期、未提柜按预约日期检索和展示,原预约时间独立保留,改期不移动已执行事实;原业务日期无时区事实时显示待核实,不套用收货仓时区或转为UTC。日期范围最多42天,预约来源和船节点实际来源分别有界读取并按柜去重;任一来源超出1000条或目的仓无法分类时标记统计不完整,目录失败报错,不能假装无预约。详情回到原清关提柜业务,不由日历直接写原状态。
- Admin 入口为 `../../apps/admin-web/src/modules/appointment-calendar/`,既有入仓单入口为 `modules/overseas-warehouse/`。日历读取权限为 `platform:appointment:list`,既有预约写权限独立;API 合同见 `../../baiyue-firstleg/lastleg-service/src/main/resources/openapi/fba-appointment-calendar-v1.yaml`。合并预约不表示已经排车或发车,运输执行继续按既有排车与共享车次流程处理。
#### 在途货源与拼车外接货的预约跟进合同
本节规定来源解析、人工跟进和已有预约覆盖的共同边界。美国全类型预约的总体目标见[优化方案](美国预约管理统一总览与优化方案.md);本节接口不代表总体目标、环境发布或整链验收已经完成。
| 事实 | 唯一来源与规则 |
|---|---|
| 头程已开船货 | `ORDER:<尾程订单ID>`;依据真实船节点和美国接仓点/FBA目录读取,不要求先建入仓计划。建计划后仍是同一来源,不重复计票。内部ID仅用于关联,不作为业务编号展示。 |
| 拼车外接货 | `BOOKING:<原登记号>`;Fleet提供客户、目的地、接仓点、承运阶段、版本及可空的实际订单关联。确认承运后尚未来货可记录联系;生成订单后保持BOOKING键,禁止同时以ORDER别名重复计货。未知箱数保持空值。 |
| 时间 | 在途列表的预计到港/到仓是订单保存的快照;船节点观察时间不代表实时ETA。预约已确认时间只读,不被预计时间更新覆盖。原预约缺少时区时明确待核实,不按操作者浏览器时区猜测。 |
| 人工跟进 | `ll_appointment_followup`保留追加历史,跟进人取登录主体;允许没有入仓计划、约号、车辆时保存。提柜联系与码头申请按稳定柜次共享,接仓联系按柜次及实际接仓点共享,FBA联系按ORDER/BOOKING货源及客户保存;各事项独立,不推进正式确认或作业状态。 |
| 预约覆盖 | `AppointmentCoverageService.query`按稳定来源及客户批量读取FBA预约,数量核对未覆盖、部分覆盖、待确认、已确认和待复核。外接货尚无订单但已保存安排时返回待确认及资料缺项,不返回假确认。正式确认号、地点时区和已核实来源版本分别读取;来源版本变化仅提示复核,不声称已完成精确船期影响分析。仓储转运的目的地与货件资料以转运主记录为准,缺少资料与实际目的地变化分开表达。 |
| 运输和容量 | 车次、正式排车关联、容量、余位及发布由Fleet维护。预约侧读取其真实结果,不以联系记录生成库存、托盘、车次或容量,也不在前端扣减余位。 |
HTTP入口为`/api/platform/v1/last-leg/appointment-planning`,包括`GET /cargo`、`GET /sources/resolve`及`GET/POST /sources/{sourceKey}/follow-ups`;请求和响应定义见[预约筹划OpenAPI](../../baiyue-firstleg/lastleg-service/src/main/resources/openapi/appointment-planning-v1.yaml)。深链进入预约页时须由后端重新核对客户、来源与目的仓,不能信任URL赋予资格。读取同时要求`platform:appointment:list`与`platform:overseas-warehouse:last-mile-order:list`,追加跟进另需`platform:appointment:followup`;仅平台主体可用,客户端不暴露跨客户货源。
整柜入口为`GET /containers`、`GET /containers/{containerId}`与`GET/POST /containers/{containerId}/follow-ups`,沿用上述权限。未传`warehouseId`记录整柜提柜或码头联系,传入时仅记录该柜实际接仓点的接仓联系。共享来源键由服务端生成`CONTAINER:<柜次>`或`CONTAINER:<柜次>:WAREHOUSE:<仓库>`,技术平台作用域不接收客户端客户参数,也不在界面展示内部键。原货源写入口仅接受FBA联系,不能逐客户重复登记整柜事项。
整柜列表读取实际已开船且仍有效的头程货物,覆盖美国接仓点的各种目的地类型;不要求先建入仓计划。关键词命中某票后仍统计同柜全部美国范围货物,接仓点一次批量分组加载。任一票箱数未知则汇总箱数显示待核实;同柜另有未知或非美国接仓点时明确标记范围不完整并禁止新联系记录。来源预计到港仍是订单快照,不能当作实时船期或预约确认。已有联系历史在来源离开活动列表后保留可读。
跟进写入携带事项版本和持久化幂等键。同键、同操作者、同内容重试返回原记录;异内容或不同版本冲突拒绝,未知结果重试保持原请求。跟进保存成功不代表预约申请或确认成功。仓库目录失败必须报错;日历某来源失败时保留其他来源结果并标注统计不完整。
跨客户合批核对入口为`POST /batches/preview`,读取权限与来源查询相同,单批最多100票。服务端批量核对ORDER/BOOKING来源、客户归属及真实订单,拒绝重复别名、不同起运仓/目的FBA仓、暂扣、多目的地及已有有效预约;未知箱数保留缺项。`POST /appointments`重新核对后保存同一FBA预约聚合,另需既有FBA预约写权限;`GET /appointments/unscheduled`按预约列表权限分页读取无日期安排。允许未建计划及已确认承运但尚未来货的真实来源,不能信任浏览器预览作为写入依据。两种创建入口均自动提交选择时的接仓点和目的FBA仓,服务端在锁定货源后与当前事实比对;任一变化返回冲突并要求重新核对,不静默改约至新仓,也不增加人工填写字段。备妥窗口无权威依据时明确待核实,不能用预计到港或到仓替代。部署与真实验收状态见环境主契约。
已确认承运的外接货从原登记深链或`GET /external-candidates`服务端分页列表进入,必须经服务端核对后才能加入既有预约合批工作区;使用同一预览/创建接口,与同起运仓、同目的FBA仓的头程货共同保存,保留原BOOKING键,不生成ORDER别名。来源已有有效预约时不再提供新增入口;未形成入仓码或箱数未知仍可保存待确认安排,正式确认继续核验资料。
外接候选由Fleet只读适配器按原登记分页发现,限已确认承运/已实收/已绑定、车次未取消或完成、权威启用美国接仓点和FBA目的仓范围;支持登记号、车次号、客户名称及来货号检索,每页最多100票。预约侧对当页来源和覆盖批量核实,保留客户归属、原登记、真实订单关联及未知箱数;目录失败显式报错。Admin仅打开外接货源列表时请求,切换头程/外接保留同一合批选择,保存后刷新覆盖。它不提供承运确认、车次容量或发布写入。
共同样例:两柜头程货送同一美国接仓点再送ONT8,提柜分别按两柜联系,FBA货源保留各票ORDER来源;同一车次接入外部登记B-1时保留BOOKING:B-1。B-1确认承运但尚未来货时可以跟进和保存安排,不伪造入仓码或对方确认;实际来货在原登记行锁和同一事务内,将已有有效预约明细关联到真实订单及入仓码,继续通过同一BOOKING键读取覆盖;关联失败则来货事务一起回滚。该关联不自动改写预约数量快照、确认时间或来源版本,也不扫描补填历史记录。预约保存按登记号和订单号的稳定顺序锁定货源,并在订单锁定后清除查询缓存、重新核对来源,防止使用锁定前的旧事实。客户不符、目的仓变化、重复别名或已取消承运均不能借用其他货物的预约结果。跨来源筹划、正式确认和变化处理遵循总体方案,读取或核对成功不能代替保存和正式确认成功。
| 业务域 | 能力范围 | 原型入口 | | 业务域 | 能力范围 | 原型入口 |
|---|---|---| |---|---|---|
| 海外仓 | 尾程订单、入库单、换标单、托盘管理、库存管理;箱号管理与产品库当前暂不进入海外仓业务正式入口;Admin 入口 `../../apps/admin-web/src/modules/overseas-warehouse/` | 原型 `../悦/货代SAAS平台后台/prototype-src/modules/03-overseas-warehouse.html`;Backend `../../baiyue-firstleg/lastleg-service/`、`../../baiyue-firstleg/warehouse-overseas-service/`,经 `gateway-overseas/` | | 海外仓 | 尾程订单、入库单、换标单、托盘管理、库存管理;箱号管理与产品库当前暂不进入海外仓业务正式入口;Admin 入口 `../../apps/admin-web/src/modules/overseas-warehouse/` | 原型 `../悦/货代SAAS平台后台/prototype-src/modules/03-overseas-warehouse.html`;Backend `../../baiyue-firstleg/lastleg-service/`、`../../baiyue-firstleg/warehouse-overseas-service/`,经统一 `gateway/` |
| 海外仓排车与智能预排 | 平台查看排车列表/详情,按入仓计划或已收托盘创建预排,并完成编辑、取消、拣货、出库、发车和转派送 | Admin `../../apps/admin-web/src/modules/overseas-warehouse/pages/DispatchesView.vue`、`api/dispatches.ts`;Backend `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/` | | 海外仓排车与智能预排 | 平台查看排车列表/详情,按入仓计划或已收托盘创建预排,并完成编辑、取消、拣货、出库、发车和转派送 | Admin `../../apps/admin-web/src/modules/overseas-warehouse/pages/DispatchesView.vue`、`api/dispatches.ts`;Backend `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/` |
| 海外仓客户自助服务 | 客户工作台正式开放贴标申请、仓储转运、货物废弃和退货换标;所有查询和写入只使用登录态客户范围 | Client `../../apps/client-web/src/modules/overseas-warehouse/routes.ts`、`views/WarehouseServiceView.vue`、`api/warehouseServices.ts`;Backend `../../baiyue-firstleg/lastleg-service/` 的 `relabel/`、`transfer/`、`discard/`,经 `gateway-overseas/` | | 海外仓客户自助服务 | 客户工作台正式开放贴标申请、仓储转运、货物废弃和退货换标;所有查询和写入只使用登录态客户范围 | Client `../../apps/client-web/src/modules/overseas-warehouse/routes.ts`、`views/WarehouseServiceView.vue`、`api/warehouseServices.ts`;Backend `../../baiyue-firstleg/lastleg-service/` 的 `relabel/`、`transfer/`、`discard/`,经统一 `gateway/` |
| 海外仓 PDA 柜号签收与退货入库 | 独立应用 `../../apps/pda-overseas-uniapp/`;拆柜收货完成柜号认领、三类照片、按目的类型实收与全柜完成;退货入库支持扫描退货单号或 SKU 候选并按本包实收生成退货箱和计费批次,签收后可按同客户退货单合箱 | 拆柜前端 `src/api/inbound.js`、`receiving-adapter.js`、`pages/operation/operation.vue`;退货前端 `src/api/return-receipt.js`、`src/api/return-packing.js`、`pages/return-receipt/return-receipt.vue`、`pages/return-packing/return-packing.vue`;Backend 分别为 `inboundplan/pda/` 与 `returnreceipt/controller/PdaReturnReceiptController.java`、`PdaReturnInventoryController.java`,经 `gateway-overseas/` | | 海外仓 PDA 柜号签收与退货入库 | 独立应用 `../../apps/pda-overseas-uniapp/`;拆柜收货完成柜号认领、三类照片、按目的类型实收与全柜完成;退货入库支持扫描退货单号或 SKU 候选并按本包实收生成退货箱和计费批次,签收后可按同客户退货单合箱 | 拆柜前端 `src/api/inbound.js`、`receiving-adapter.js`、`pages/operation/operation.vue`;退货前端 `src/api/return-receipt.js`、`src/api/return-packing.js`、`pages/return-receipt/return-receipt.vue`、`pages/return-packing/return-packing.vue`;Backend 分别为 `inboundplan/pda/` 与 `returnreceipt/controller/PdaReturnReceiptController.java`、`PdaReturnInventoryController.java`,经统一 `gateway/` |
| 海外仓 PDA 库内、托盘、换标与查询 | Lastleg 提供盘点、同仓整托移库、托盘组拆换绑、换标和库存/库位/托盘查询能力;当前终端入口按工作台能力开关启用,未进入 PDA 的操作由 Admin/Client 正式页面承载 | Backend `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/stocktake/`、`pda/move/`、`pda/warehouse/`、`palletops/`、`relabel/pda/`;契约 `src/main/resources/openapi/overseas-pda-operations-v1.yaml` | | 海外仓 PDA 库内、托盘、换标与查询 | Lastleg 提供盘点、同仓整托移库、托盘组拆换绑、换标和库存/库位/托盘查询能力;当前终端入口按工作台能力开关启用,未进入 PDA 的操作由 Admin/Client 正式页面承载 | Backend `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/stocktake/`、`pda/move/`、`pda/warehouse/`、`palletops/`、`relabel/pda/`;契约 `src/main/resources/openapi/overseas-pda-operations-v1.yaml` |
| 海外仓出库与派送 | 排车编辑/取消、PDA 排车拣货、出库任务、发车门禁、转派送、客户派送单和派送完成 | Admin `../../apps/admin-web/src/modules/overseas-warehouse/`;Overseas PDA `../../apps/pda-overseas-uniapp/src/pages/dispatch/`、`src/pages/outbound/`;Backend `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/`、`delivery/` | | 海外仓出库与派送 | 排车编辑/取消、PDA 排车拣货、出库任务、发车门禁、转派送、客户派送单和派送完成 | Admin `../../apps/admin-web/src/modules/overseas-warehouse/`;Overseas PDA `../../apps/pda-overseas-uniapp/src/pages/dispatch/`、`src/pages/outbound/`;Backend `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/`、`delivery/` |
| 异常退回与客户回访 | 异常建档、派送退回入仓、派送状态、签收/回访附件和客户回访 | Admin `ExceptionOrdersView.vue`、`CustomerVisitsView.vue`;Backend `exceptionorder/`、`customervisit/` | | 异常退回与客户回访 | 异常建档、派送退回入仓、派送状态、签收/回访附件和客户回访 | Admin `ExceptionOrdersView.vue`、`CustomerVisitsView.vue`;Backend `exceptionorder/`、`customervisit/` |
| 一件代发 | 国内订单强制 SKU 与每箱数量快照、逐箱清点组托、`SEALED` 整托分柜、海外 SKU/箱唛库存和一件代发出库 | Backend `order/`、`firstleg/`、`lastleg-service/dropship/`;跨区事件见 `common-event-contract/` | | 一件代发 | 国内订单强制 SKU 快照、装柜工作托盘、海外 SKU/箱唛库存和一件代发出库 | Backend `order/`、`firstleg/`、`lastleg-service/dropship/`;跨区事件见 `common-event-contract/` |
| 海外业务 | 本土散板、采购订单、本土卡车;Admin 入口 `../../apps/admin-web/src/modules/overseas-business/` | 原型 `../悦/货代SAAS平台后台/prototype-src/modules/07-overseas-business.html`;Backend `../../baiyue-firstleg/lastleg-service/` 的 `procurement/`、`trucking/` 及后续本土散板子域 | | 海外业务 | 本土散板、采购订单、本土卡车;Admin 入口 `../../apps/admin-web/src/modules/overseas-business/` | 原型 `../悦/货代SAAS平台后台/prototype-src/modules/07-overseas-business.html`;Backend `../../baiyue-firstleg/lastleg-service/` 的 `procurement/`、`trucking/` 及后续本土散板子域 |
| 仓库主数据与海外资源 | 仓库 ID、类型、状态、地址、能力统一由国内仓库主数据维护;海外服务只维护库位、托盘和资源锁 | Admin `../../apps/admin-web/src/modules/warehouses/`;国内权威 `../../baiyue-firstleg/warehouse/`;海外资源 `../../baiyue-firstleg/warehouse-overseas-service/` | | 仓库主数据与海外资源 | 仓库 ID、类型、状态、地址、能力统一由国内仓库主数据维护;海外服务只维护库位、托盘和资源锁 | Admin `../../apps/admin-web/src/modules/warehouses/`;国内权威 `../../baiyue-firstleg/warehouse/`;海外资源 `../../baiyue-firstleg/warehouse-overseas-service/` |
| 通用资料 | 海外仓报价、汇率管理、车辆列表;Admin 入口 `../../apps/admin-web/src/modules/overseas-master-data/` | `../悦/货代SAAS平台后台/prototype-src/modules/10-general.html` | | 通用资料 | 海外仓报价、汇率管理、车辆列表;Admin 入口 `../../apps/admin-web/src/modules/overseas-master-data/` | `../悦/货代SAAS平台后台/prototype-src/modules/10-general.html` |
| 车辆管理、司机资质与保养加油 | 业务范围见[车辆管理原型梳理与任务规划](车辆管理原型梳理与任务规划.md);后端 `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/fleet/`,OpenAPI `fleet-drivers-v1.yaml`、`fleet-trips-v1.yaml`、`fleet-vehicle-records-v1.yaml`;证照和运维照片复用 File | Admin 接入目录 `../../apps/admin-web/src/modules/overseas-master-data/`;原型来源和页面 ID 按规划第 1、2 节定位 |
| 内部拼车需求池 | [内部拼车需求池首版开发契约](内部拼车需求池首版开发契约.md):车次余位发布、销售意向、确认占位、本土订单关联及统一我仓上车 | 复用上述车辆管理及本土业务入口;不开放客户端运力市场 |
| 国内出仓后船节点 | 对已确认离开国内仓库的订舱/柜次定时查询船节点,保存最新节点、异常和查询历史,贯通目的港提柜至还柜事实 | 标准语义见[船节点标准化契约](船节点标准化契约.md);Admin `../../apps/admin-web/src/modules/port-schedules/`、`ocean-bookings/` 及货柜详情;Backend `../../baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/portschedule/`、`../../baiyue-firstleg/integration-service/` | | 国内出仓后船节点 | 对已确认离开国内仓库的订舱/柜次定时查询船节点,保存最新节点、异常和查询历史,贯通目的港提柜至还柜事实 | 标准语义见[船节点标准化契约](船节点标准化契约.md);Admin `../../apps/admin-web/src/modules/port-schedules/`、`ocean-bookings/` 及货柜详情;Backend `../../baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/portschedule/`、`../../baiyue-firstleg/integration-service/` |
## 原型页面定向索引 ## 原型页面定向索引
@@ -74,12 +133,35 @@
- 现有“每 3 天一次、窗口最多 3 次”、六家船公司来源、最近有效结果和过期标识是同一查询能力的既有约束,归海外仓业务继续核对;后续若调整自动轮询频率、供应商额度、退避或停止规则,应只修改海外仓业务契约和这套任务。 - 现有“每 3 天一次、窗口最多 3 次”、六家船公司来源、最近有效结果和过期标识是同一查询能力的既有约束,归海外仓业务继续核对;后续若调整自动轮询频率、供应商额度、退避或停止规则,应只修改海外仓业务契约和这套任务。
- 当前原型没有独立的“船节点定时查询”页面;涉及页面展示时从订舱、船期或货柜详情进入,不得为了匹配原型菜单把它归入海外派送。 - 当前原型没有独立的“船节点定时查询”页面;涉及页面展示时从订舱、船期或货柜详情进入,不得为了匹配原型菜单把它归入海外派送。
## 本土卡车与散板统一前端下单
- 同一业务在 Admin 新增/编辑和 Client 下单使用一致的字段、顺序、控件、默认值、校验及提交转换;Admin 新增额外选择客户,编辑固定原订单客户;Client 的客户仅由登录会话确定,业务请求体不携带客户标识。
- 业务表单统一为运输信息、货物信息、费用与时效和备注。起运地/目的地、两端联系人、电话及详细地址左右对应;件数、预计托数、重量和体积默认零,预算默认为空、币种 USD,空预算和零预算分别保留。车辆只在卡车填写,商品与预计托数只在散板填写。
- 两端统一使用数字控件和 USD/CNY 选择;重量支持三位小数、体积六位小数、预算两位小数;取送时间按当地分钟输入并提交秒为零的值,不进行时区转换。四项联系信息及两个时间均必填,送货不能早于取货。
- 各应用内部由 `TransportDemandForm.vue` 和 `transportDemandForm.ts` 复用表单、校验与业务请求转换;两端对应源码按同一内容核对,不建立跨应用目录依赖。创建保留稳定幂等键;平台编辑保留客户、业务单号和版本,受状态及只读承运来源限制。
## 本土散板简化下单
- 平台代客创建必须显式选择客户;客户端客户范围只取认证会话。新增、编辑保持现有独立页面;平台普通编辑仍只允许待接单且非拼车来源订单,池来源继续只读展示真实承运安排。
- 下单移除运输方式及柜型字段,不再要求选择自送或我司提货。拼车或优先拼载属于内部安排,不再冒充交货方式或作为下单必填项;运输类型和是否打盘不在新增主表单要求填写,未知安排保持空,不自动补造。散板移除柜型字段。
- 需求保存取货地、目的地、可选详细地址补充、起运地联系人及联系电话、目的地联系人及联系电话、商品名称、预计托数、件数、总重量、总体积、预算总价、币种、取货与送达时间和备注。商品名称、预算和备注选填;四项联系人信息与取货、送货时间全部必填;预计托数、件数及重量体积可为零,不能为负。件数、地址补充和备注按统一前端下单表单展开填写。
- `estimatedPalletCount` 是下单预计托数;`packageCount` 是件数,二者独立。下单不生成实物托盘,不把预计托数写成实际收货或实占托位;拼车来源沿真实询价的货名与预计托数保存。
- `pickupAt` 与 `deliveryAt` 保存不带时区的当地日期时间,按分钟输入、原值显示,不进行 UTC 转换。取货与送货时间均必填;送货时间不能早于取货时间。预算明确显示 USD 或 CNY,金额空值与零值区分。
- 平台和客户接口共用 Lastleg `looseboard/dto/LocalLooseboardRequests.java`、`LocalLooseboardResponses.java` 及 `overseas-business-v1.yaml`,不保留旧运输枚举或要求日期别名。现有 API 路径与权限复用,空库结构同步模块基线及海外统一初始化,不回填测试存量,不自动执行 SQL 或部署。
## 美国本土卡独立下单
- 客户端和平台新增/编辑共用同一服务端需求合同:移除运输类型、柜型、下单预报托盘数及原要求时间;车辆类型为必选的“15拖”(`PALLET_15`)或“30拖”(`PALLET_30`)。车辆主档仍独立维护实际容量,车型不等于本票货量。
- 起运地联系人、起运地联系电话、目的地联系人、目的地联系电话、取货时间和送货时间全部必填。时间按日期及小时分钟填写,不进行时区转换;送货不能早于取货。列表、详情与平台编辑展示同一份保存值,客户端不提交客户标识。
- 独立下单不生成预报托盘,首次实际收货确定确认托数;已有拼车来源的真实预报及实际履约继续独立记录。拼车来源未提供的车型、目的地联系人/电话、送货时间保持未知,页面显示“—”,不捏造数据。美本土散板按本文“本土散板简化下单”使用独立需求合同。
- 接口及字段唯一实现合同为 Lastleg `trucking/dto/UsTruckOrderRequests.java`、`UsTruckOrderResponses.java` 与 `src/main/resources/openapi/overseas-business-v1.yaml`;数据结构同步模块基线及海外统一空库初始化。页面承载核对见 Client `cross-border/PROTOTYPE_MATRIX.md` 和 Admin `overseas-business/PROTOTYPE_MATRIX.md`。
## 系统边界与索引维护 ## 系统边界与索引维护
- 托盘管理提供当前托盘单张标签 PDF:Admin `PalletsView.vue` → `warehouse-overseas-service` 的 `GET /api/platform/v1/warehouse-admin/{warehouseId}/pallets/{id}/label`。有 FBA 仓码的托盘与国内统一使用 Print `FBA_PALLET_A4_LANDSCAPE_V1`(297×210 mm):顶部 SCK8 等仓码,中间 Code 128、底部完整托盘号,141 等内部编号保留在托盘号中;其他托盘使用 `INBOUND_MARK_V1`(100×100 mm)。只按真实托盘编码打印,不重新生成编号;模板约束、服务接入与权限见海外资源服务 `AGENTS.md`。 - 托盘管理提供当前托盘单张标签 PDF:Admin `PalletsView.vue` → `warehouse-overseas-service` 的 `GET /api/platform/v1/warehouse-admin/{warehouseId}/pallets/{id}/label`。有 FBA 仓码的托盘与国内统一使用 Print `FBA_PALLET_A4_LANDSCAPE_V1`(297×210 mm):顶部 SCK8 等仓码,中间 Code 128、底部完整托盘号,141 等内部编号保留在托盘号中;其他托盘使用 `INBOUND_MARK_V1`(100×100 mm)。只按真实托盘编码打印,不重新生成编号;模板约束、服务接入与权限见海外资源服务 `AGENTS.md`。
- 海外仓合作仓是现有头程仓库主数据的类型扩展,需同步核对 Admin `warehouses`、Warehouse Service 的 DTO/Controller/OpenAPI/SQL 及实际消费者;不得因此把海外库存业务写入国内 Warehouse Service。 - 海外仓合作仓是现有头程仓库主数据的类型扩展,需同步核对 Admin `warehouses`、Warehouse Service 的 DTO/Controller/OpenAPI/SQL 及实际消费者;不得因此把海外库存业务写入国内 Warehouse Service。
- 海外库存、库内作业和海外本土业务已有明确服务入口:`gateway-overseas/` 是海外 API 网关,`lastleg-service/` 拥有尾程订单、入仓计划、换标、库存业务、采购和本土卡车;国内 `warehouse-service` 是仓库主数据唯一权威,`warehouse-overseas-service/` 只拥有库位、托盘及资源锁并引用国内 `warehouseId`。不得把海外库存业务塞入国内 `firstleg/` 或 `warehouse/`。 - 海外库存、库内作业和海外本土业务已有明确服务入口:`gateway/` 是统一 API 网关,`lastleg-service/` 拥有尾程订单、入仓计划、换标、库存业务、采购和本土卡车;国内 `warehouse-service` 是仓库主数据唯一权威,`warehouse-overseas-service/` 只拥有库位、托盘及资源锁并引用国内 `warehouseId`。不得把海外库存业务塞入国内 `firstleg/` 或 `warehouse/`。
- 国内装柜完成事件只在海外生成 `PENDING_ASSIGNMENT` 尾程订单、冻结快照和 `FIRST_LEG` 在途库存,不自动生成入仓计划。平台通过 `GET /api/platform/v1/last-leg/orders/container-summaries` 按稳定 `sourceContainerBookingId` 服务端聚合全柜订单、入仓码、计划数、未操作数和 `allPlansReady`,分页返回全部稳定来源柜,已生成计划的柜仍保留供接柜仓查询与修改;`pendingPlanCount` 区分待建计划,`resourcePendingPlanCount` 区分托盘资源待生成,后者仅用于自动生成异常后的重试;详情 `/{sourceContainerBookingId}` 返回柜内全部订单与计划且不受订单分页截断。`plannedArrivalAt` 只来自装柜完成事件 `estimatedWarehouseArrivalAt` 冻结到 Lastleg `ll_order.estimated_warehouse_at` 的计划到仓事实,不得使用创建时间、预计到港或当前时间替代,并按该时间升序、空值最后排序。确认后调用 `POST /api/platform/v1/last-leg/inbound-plans/convert-container`;服务端一次锁定整柜、每票独立生成一个计划,整批原子且幂等。转换成功才将尾程订单推进为 `INBOUND_PLANNED`,并把库存余额的来源入仓码展示快照替换为各自 `planNo`。 - 国内装柜完成事件只在海外生成 `PENDING_ASSIGNMENT` 尾程订单、冻结快照和 `FIRST_LEG` 在途库存,不自动生成入仓计划。平台通过 `GET /api/platform/v1/last-leg/orders/container-summaries` 按稳定 `sourceContainerBookingId` 服务端聚合全柜订单、入仓码、计划数、未操作数和 `allPlansReady`,分页返回全部稳定来源柜,已生成计划的柜仍保留供接柜仓查询与修改;`pendingPlanCount` 区分待建计划,`resourcePendingPlanCount` 区分托盘资源待生成,后者仅用于自动生成异常后的重试;详情 `/{sourceContainerBookingId}` 返回柜内全部订单与计划且不受订单分页截断。`plannedArrivalAt` 只来自装柜完成事件 `estimatedWarehouseArrivalAt` 冻结到 Lastleg `ll_order.estimated_warehouse_at` 的计划到仓事实,不得使用创建时间、预计到港或当前时间替代,并按该时间升序、空值最后排序。确认后调用 `POST /api/platform/v1/last-leg/inbound-plans/convert-container`;服务端一次锁定整柜、每票独立生成一个计划,整批原子且幂等。转换成功才将尾程订单推进为 `INBOUND_PLANNED`,并把库存余额的来源入仓码展示快照替换为各自 `planNo`。
- 尾程订单的 `inboundCode` 只保存并展示真实来源入仓码;换标申请、本土散板等没有入仓关系的海外本土业务保持为空,由页面显示 `—`,不得用换标单号、本土散板单号或内部 ID 冒充入仓码。 - 尾程订单的 `inboundCode` 只保存并展示真实来源入仓码;换标申请、本土散板等没有入仓关系的海外本土业务保持为空,由页面显示 `—`,不得用换标单号、本土散板单号或内部 ID 冒充入仓码。
- 平台可按单票尾程订单入库计划(托数、托盘类型、分配/可合托/加急和备注);入库仓、入仓码和预计到仓时间均展示冻结事实,不允许人工改写。预计到仓日期由服务端锁定来源柜全部订单的 `estimated_warehouse_at`,缺失或同柜不一致时阻断,人工与自动计划统一写入该柜日期。写入时校验订单版本、客户归属、仓库主档和幂等键;一票柜保存后立即自动生成并绑定托盘码、海外仓托盘和资源锁,多票柜在最后一票计划齐全时自动为全柜完成同一动作。`resourcePendingPlanCount` 只用于自动生成失败后的显式重试,不是正常人工步骤。分配、可合托、加急必须随入库单列表和海外 PDA 入仓码作业返回并展示,其中“可合托”只向现场提供选择:合托时扫描同目的仓已使用的托盘码,独立收货时扫描新托盘码,不作为实收或完成门禁。新增暂扣只允许货物完成入库后执行;暂扣只作用于该票并仅阻断排车和出库,不阻断入库计划或入库作业,同柜其他订单不受影响。 - 平台可按单票尾程订单入库计划(托数、托盘类型、分配/可合托/加急和备注);入库仓、入仓码和预计到仓时间均展示冻结事实,不允许人工改写。预计到仓日期由服务端锁定来源柜全部订单的 `estimated_warehouse_at`,缺失或同柜不一致时阻断,人工与自动计划统一写入该柜日期。写入时校验订单版本、客户归属、仓库主档和幂等键;一票柜保存后立即自动生成并绑定托盘码、海外仓托盘和资源锁,多票柜在最后一票计划齐全时自动为全柜完成同一动作。`resourcePendingPlanCount` 只用于自动生成失败后的显式重试,不是正常人工步骤。分配、可合托、加急必须随入库单列表和海外 PDA 入仓码作业返回并展示,其中“可合托”只向现场提供选择:合托时扫描同目的仓已使用的托盘码,独立收货时扫描新托盘码,不作为实收或完成门禁。新增暂扣只允许货物完成入库后执行;暂扣只作用于该票并仅阻断排车和出库,不阻断入库计划或入库作业,同柜其他订单不受影响。
@@ -90,8 +172,8 @@
- 手动还柜以真实海外卸柜完成且尚未还柜为准,仍校验独立还柜权限;无需事先存在车队、预约或提柜时间。首次命令使用版本 0 创建拖车记录,车队字段可为空,不补造提柜事实。还柜时间不得早于卸柜完成时间或已有提柜时间,成功后同步标准还柜节点并解除报空预警。 - 手动还柜以真实海外卸柜完成且尚未还柜为准,仍校验独立还柜权限;无需事先存在车队、预约或提柜时间。首次命令使用版本 0 创建拖车记录,车队字段可为空,不补造提柜事实。还柜时间不得早于卸柜完成时间或已有提柜时间,成功后同步标准还柜节点并解除报空预警。
- 船节点是头程海运在途事实与海外接柜之间的衔接能力,业务聚合继续由 Firstleg 按 `containerBookingId` 柜级持有,不绑定客户;跨区域事件使用 `tenantId=0` 平台技术范围,到港/可提柜结果通过明确契约提供给海外区域,不复制第二套轮询任务。 - 船节点是头程海运在途事实与海外接柜之间的衔接能力,业务聚合继续由 Firstleg 按 `containerBookingId` 柜级持有,不绑定客户;跨区域事件使用 `tenantId=0` 平台技术范围,到港/可提柜结果通过明确契约提供给海外区域,不复制第二套轮询任务。
- Admin、Client 仍使用统一账号体系,并按根 `AGENTS.md` 的双区域 API、海外 Token 和跨区域事件约定接入;业务页面不自行实现第二套登录。 - Admin、Client 仍使用统一账号体系,并按根 `AGENTS.md` 的双区域 API、海外 Token 和跨区域事件约定接入;业务页面不自行实现第二套登录。
- 海外仓 PDA 使用独立 `apps/pda-overseas-uniapp/` 工程和发布身份,但账号仍由国内 Auth 唯一签发;真实作业请求必须经海外 Gateway 的显式 PDA 路由。工作台只展示已注册并启用的现场作业,其他业务通过 Admin/Client 完成,不以某个终端是否承载全部操作判断端到端流程是否完成。 - 海外仓 PDA 使用独立 `apps/pda-overseas-uniapp/` 工程和发布身份,但账号仍由国内 Auth 唯一签发;真实作业请求必须经统一 Gateway 的显式 PDA 路由。工作台只展示已注册并启用的现场作业,其他业务通过 Admin/Client 完成,不以某个终端是否承载全部操作判断端到端流程是否完成。
- 海外 PDA 的实际收货仓是国内 `warehouse-service` 中 `tenant_id=0`、类型为 `OVERSEAS`、状态 `ACTIVE` 且启用 `RECEIVING` 能力的平台共享物理仓,并由 `WAREHOUSE_PICKER` 的 Token Claim 固定;海外数据库只保存相同 `warehouseId` 引用。PDA 不接收仓库 ID,也不能切换柜号。海外 Gateway 对每个 `/api/pda/**` 请求在本地验签后向 Auth 实时核对账号 `token_version` 与当前仓绑定,换仓或清空绑定后旧 Token 立即失效,Auth 不可用时拒绝请求。待收柜在首次准备时原子认领到该仓,入仓计划、尾程订单和收货会话冻结实际仓 ID/名称;国内装柜事件的仓库仅作为来源仓快照,目的仓/FBA 仓也不得冒充实际收货仓。 - 海外 PDA 的实际收货仓是国内 `warehouse-service` 中 `tenant_id=0`、类型为 `OVERSEAS`、状态 `ACTIVE` 且启用 `RECEIVING` 能力的平台共享物理仓,并由 `WAREHOUSE_PICKER` 的 Token Claim 固定;海外数据库只保存相同 `warehouseId` 引用。PDA 不接收仓库 ID,也不能切换柜号。统一 Gateway 对每个 `/api/pda/**` 请求在本地验签后向 Auth 实时核对账号 `token_version` 与当前仓绑定,换仓或清空绑定后旧 Token 立即失效,Auth 不可用时拒绝请求。待收柜在首次准备时原子认领到该仓,入仓计划、尾程订单和收货会话冻结实际仓 ID/名称;国内装柜事件的仓库仅作为来源仓快照,目的仓/FBA 仓也不得冒充实际收货仓。
- 海外 PDA 接柜候选、认领会话、国内五类装柜照片对照、海外三类签收照片与整柜完成均按 `sourceContainerBookingId + containerNo` 聚合,不保存客户并允许同柜多个客户。国内照片在签收阶段展开、收货阶段折叠,只读加载失败不阻断拆柜。签收后为柜内每个计划按其自身客户生成任务;入仓码解析、SKU 实收、托盘占用和库存入账继续按该票真实客户隔离,整柜完成需全部计划核平且只发布一次柜级完成事件。 - 海外 PDA 接柜候选、认领会话、国内五类装柜照片对照、海外三类签收照片与整柜完成均按 `sourceContainerBookingId + containerNo` 聚合,不保存客户并允许同柜多个客户。国内照片在签收阶段展开、收货阶段折叠,只读加载失败不阻断拆柜。签收后为柜内每个计划按其自身客户生成任务;入仓码解析、SKU 实收、托盘占用和库存入账继续按该票真实客户隔离,整柜完成需全部计划核平且只发布一次柜级完成事件。
- 新增实际代码模块、API、权限、OpenAPI 或数据库入口后,同步更新根 `AGENTS.md`、对应应用/服务 `AGENTS.md` 和本文件;不把排期、完成比例或临时任务状态写入快速索引。 - 新增实际代码模块、API、权限、OpenAPI 或数据库入口后,同步更新根 `AGENTS.md`、对应应用/服务 `AGENTS.md` 和本文件;不把排期、完成比例或临时任务状态写入快速索引。
@@ -0,0 +1,226 @@
# 内部拼车需求池首版开发契约
日期:2026-10-07。当前版本:V5,五轮开发前审核修订完成,进入开发。本文为本功能唯一范围与实现契约;审核记录随文维护。部署和实际验收结论仅写入两份环境主契约,不能用本文的方案代替已实现证明。
## 1. 目标与首版范围
### 2026年10月9日操作简化开发定稿与预约交接
本次已收到开始开发指令,采用《拼车数据入口与操作简化评估草案》第七、八节的完整范围:已有车次接货,分阶段登记、服务端缺项及角色提示、原登记连续履约、合格排车候选、共用车次准备与实收排入。保留直接外接预订来源,不新增独立待配货池、虚拟运力或跨车改配。本文记录规则,发布与实际验收继续归环境主契约。
文件归属:本侧维护 Admin `overseas-master-data/`、其公开出口和所需 `overseas-warehouse` 排车消费者;Backend `fleet/`、`dispatch/fleet/`、相关既有排车候选 Mapper 及 Fleet OpenAPI/测试。预约实施侧维护 `appointment-calendar/`、预约服务、预约投影及其 OpenAPI,并统一整合 `lastleg.sql`、公共导航和新增权限种子;本侧不重叠写这些共享文件。不改变已存在的财务修改。
预约交接的稳定身份:成交前为 `bookingNo`,成交后关联 `businessOrderNo`;安排来货后增加 `incomingNo`,实收依据为 `receiptHash + warehousePalletId + packages`;正式排车以 `dispatchNo` 及其完整来源组成核对。货物上车资格以同客户、同起运仓、同真实来货来源、完整实收托盘组成、未绑定其他车次为准。来源尚未形成合格排车或实际托盘时,预约侧只能保存筹划,不能通过本侧创建假托盘或实载。
现有共用 API 前缀为 `/api/platform/v1/last-leg/fleet`:`/trips` 维护真实车次;`/trips/{tripNo}/assignment` 分配资源;`/trips/{tripNo}/dispatches/bind` 关联合格排车;`/trips/{tripNo}/capacity-plan` 核对计划;`/capacity-offers` 及发布命令维护每车次唯一发布。当前 UI 以车次详情及 `CapacityOfferSettingsDialog.vue` 为入口;新增共用入口实现后通过模块 `index.ts` 导出,不允许预约侧直接引用内部组件。预约侧覆盖投影尚待交接,以正式来源查询结果为准,不在本侧新增预约状态。
共同样例:两柜真实货物的合格排车进入同一30托位车次,自有计划占18,确认外接登记8后同区间余4;外接实收排入后,8由预留转入真实计划,仍只计一次。来货绑定导致旧计划失效时,余位返回待核对,不能继续展示旧余4或自动恢复发布。托位、重量、体积逐段同时校验,三类阶段(预约筹划、外接保位、正式排入)不互相替代。
登记保存即对获准调度可见,不保位;后续必填与始终选填分区展示。`Inquiry.progress` 为只读派生的阶段、保位说明、负责角色、主要动作及缺项,不能被前端写成状态。承运资格同时检查本票资料与目的站余位,最终写命令仍锁定并复验。后续履约读取和操作以原登记身份进入,查看本人记录不授予整车其他客户或司机资料的读取权限。
用户场景:调度约定30托位车辆去目的仓A,自有货占18托位,将剩余12托位发布给内部销售;销售联系外部客户、登记意向,调度确认承运和占位,客户订单随后走真实到仓、装车、配送和签收。
本功能的“需求池”是**已发布车次的剩余运力目录**,不是客户待配货需求库。一条发布对应一个车次;销售从具体车次登记意向,不新建无车次撮合平台。
首版边界:
- 仅内部Admin展示运力池,Client不开放余位市场。客户只查看自己的本土订单和获准的承运安排。
- 所有外接货统一在我仓上车。客户自行送仓,或我方在线下安排提货回仓,均从实际到仓后开始系统收货。可记录两种交货说明,不能宣称已有独立提货任务闭环。
- 沿途提货直送、行驶途中新增承运、独立提货车调度及交接、自动撮合、销售临时限时锁位、整单拆分到多个干线车次均不在首版。
- 询价不占位,调度确认承运才占位。订单预算不等于成交运费,承运确认不等于收款。
- 本轮用户已授权TEST部署、测试数据库、真实HTTP和内置浏览器验收,Admin/Client固定1920×1080、100%缩放。操作目标为TEST,不沿用上轮灰度配置;密钥仅从私有配置读取。
## 2. 单一事实来源与复用
| 内容 | 权威来源与本轮处理 |
| --- | --- |
| 车次、线路、时间、车辆容量 | 现有FleetTrip及当前车辆主档;不建立第二套车次 |
| 自有货计划占位 | 当前有效capacity-plan及货物hash,保留三维容量 |
| 外接占位 | 复用外接预订CONFIRMED/RECEIVED;BOUND后由实际货物计入,不双扣 |
| 发布信息 | 新增每车次唯一的发布记录:业务编号、状态、交货截止、公开给销售的联系人/备注、版本和审计 |
| 客户意向 | 复用外接预订DRAFT,增加发布关联、服务端销售负责人、交货说明及本土业务类型 |
| 本土订单 | 本土散板/本土卡车保存客户委托;预订关联真实业务单号,不再重复产生无关商业订单 |
| 实收与发运 | 现有外接来货→WarehouseTransfer→库存→客户排车→共享车次→派送链 |
| 费用 | 沿现有实际派送费用来源发布,需求/询价阶段不新增应收。成交价、预算与实收款独立展示 |
开发前源码缺口记录:当时没有发布列表,预订没有销售负责人/发布来源,本土订单没有真实外接履约关联;本土散板create会另建逻辑尾程单,不能直接再调用外接来货形成两个来源;本土卡车原库存动作尚不等于外接真实库存链。此段说明本次设计起因,当前实现及验收结果以测试环境主契约为准。
## 3. 发布与余位
### 页面发布操作简化(2026-10-09)
车次关联排车单时,在同一事务按真实货物目的地标识自动补齐卸货站;去重,不按同名合并,不改变已有有效站点顺序与索引。仅新车默认的“待确定卸货点”占位由真实目的地替换;外接预订路线门禁、缺失目的地拒绝与绑定变更后的重新审核继续生效。多目的地的行驶顺序仍由调度在车次计划确认。
车次“发布拼车余位”使用1080px居中窗口,同窗展示计划容量与交货截止;唯一匹配卸货站直接显示,不重复选择。已有计划数值自动带入,只补缺失的预计重量、体积并核对托位;尚无可靠实托测量字段时不拿计费重量或零值填充。交货截止默认计划发车时间,可提前;公开联系人与交货说明收起为选填,不将司机联系方式自动公开。
“确认发布”依次复用容量确认、发布信息保存、发布/恢复接口,传递各步最新版本,保留服务端权限、容量、状态及幂等检查;已有有效且未编辑的容量直接复用。保存草稿与发布不再要求两次点击。发布失败不宣称成功;未知发布结果保留原键续试,已成功的保存步骤不重做。发布完成提供“查看需求池发布”。暂停与关闭继续显式确认。尚未自动匹配的车次可在同窗“按货物补齐卸货站”,不能自由输入标识绕过货物来源。
发布由有调度管理权限的用户在车次详情执行。前提:车次PLANNED,已分配可用车辆和司机,有真实起运仓及规范卸货站,发车/交货截止有效,容量计划有效。发布不替代调度审核、司机资质门禁或发车前理货审核。
本轮不新增“车牌司机尚未落实的虚拟运力”模型,沿用已分配资源的现有车次。计划容量或任何必须数据未就绪时给出具体阻断原因,不能以车型名字推算30托。
发布状态为DRAFT、OPEN、PAUSED、CLOSED。满位、超过交货截止、已发车/取消、容量待核对为服务端计算的接单资格,不另维护可手改的余位数字。暂停/关闭不取消已确认预订或删除客户订单;恢复发布必须重新校验。首版车次发车后不再新增承运。
状态转换为DRAFT→OPEN,OPEN→PAUSED/CLOSED,PAUSED→OPEN/CLOSED;CLOSED为终态,同车次不能另建发布规避关闭。OPEN但事实失效时允许调度显式“重新核对并恢复”更新事实指纹,仍须完整资格校验。
时间以服务端Clock的Instant为准,开放新询价/编辑须OPEN且`now < cutoff <= plannedDepartureAt`、车次仍PLANNED;询价不承诺运力,可在满位或待核对时保留草稿并明确提示,确认承运则必须所有资格有效。关闭、截止或发车后,销售仍可经“我的意向”只读跟踪本人已登记/成交业务;暂停不接受新询价或编辑,仅允许既有规则下的查看/取消。
容量按起运仓至选定卸货站的每段最小可用量校验,托位、重量和体积同时满足。列表展示分目的站的可接量,不能用全车某一个余位数字代表所有运输区间。30−18−已确认8=4仅为同一区间同规格例子。
读取可接资格、发布、确认承运均复验车辆当前启用状态和实际容量与计划是否一致;当前车辆停用或容量变更使旧计划不可承诺。改派/改线/新增自有货/绑定或解绑货物导致计划失效时,显示“待调度核对”、余位为未知并拒绝新确认,不回退到旧计划或显示0。确认承运仍由服务端在车次锁内重新计算。
发布保存本次核对的路线/发车时间、车辆容量和有效容量计划的事实指纹。仅询价、确认预订导致的版本变化不使发布失效;实际货物/容量计划或上述承诺事实变化则待核对,重新确认计划后由调度显式恢复接单,不静默恢复。GET只计算资格,不修改发布状态。表格采用“已关联货物计划占用 + 未关联外接预留(CONFIRMED/RECEIVED) + 可接余位”;BOUND外接已在计划内,若另示外接总量,只作信息列,绝不再次相加。
所有发布和预订写命令先锁车次,再按需锁实时车辆,随后锁发布记录、预订及商业关联;暂停/关闭与承运确认也共用该车次锁。实际实现须与现有车次/资源锁顺序一致。权限、登录身份与来源归属校验不能省略;已成功命令的同键同载荷重放在重新评估截止/OPEN等业务资格之前返回原结果,异载荷仍冲突。
## 4. 销售与调度权限
- 新增独立发布池列表权限,包含发布详情和不含敏感信息的只读辅助投影;不要求销售拥有trip:list。
- 销售可查看OPEN发布的线路、时间、容量、调度联系信息;登记并查看/修改/取消本人DRAFT意向。销售负责人取登录userId,不接受浏览器冒充,不按姓名判定归属。
- 调度管理权限可查看各销售意向、发布/暂停/关闭、确认承运和处理取消;不能通过一般销售写权限确认占位。
- 当前IAM无稳定销售客群ACL,只有salesOwnerName文本。本轮不新增CRM归属体系。授予本功能意向登记权限即允许在用途限定的客户候选中选择公司ACTIVE客户,仅返回ID、客户编号、名称,不返回电话/证照/财务资料;必须在文档与接口中明确该公司共享选单目录口径。
- 他人意向的直接编号访问、修改及取消须在服务端拒绝;发布总余位可以包含全部预订,但不向销售返回他人客户名称、货物、价格、司机私人信息或采购成本。
- Client根据自身客户身份查询本土订单,不提供发布池接口或其他客户预订详情。
建议权限族:`platform:fleet:capacity-offer:list/manage`与`platform:fleet:capacity-offer:inquiry-create/inquiry-edit/inquiry-cancel`。manage授权调度读取全部意向并确认承运,普通list只读取本人意向;列表和详情只读语义一致。最终路径与权限同步Controller、OpenAPI、IAM种子、导航和测试。
读取发布/本人意向允许list或manage;销售写操作同时要求list和对应inquiry写权限,manage可管理全部。所有查询/写入都由服务端取销售身份;池来源预订经既有trip booking接口操作时也必须执行一致的来源、权限、发布、订单桥和取消门禁,不能借旧接口绕过。
## 5. 意向、成交与本土订单
销售从发布详情登记意向:客户、本土散板或本土卡车类型、当前路线卸货站、货名、预计箱数/托位/重量/体积、交货方式、预计到仓、联系人、报价方式/币种/金额、备注。未完成询价允许缺预计载荷或价格;确认承运前必须完整且与本轮计划匹配。空值不等于0,报价库引用与手填成交价按既有权限规则处理。
首版每条外接意向整单绑定一个干线车次,不提供销售拆分数量。仅可选择本车现有卸货站,新增目的地须调度先改车次路线并重核计划;不能以自由文本地址伪造目的仓匹配。
确认承运采用一次服务端命令:验证发布/车次/预订版本、登录权限、客户资格、路线、时间、实际有效余位及成交价→创建本土商业订单及唯一桥关联→确认预订占位→返回新版本及业务单号。不可由浏览器串行三次写入拼接“成功”;使用稳定幂等键,同键同载荷返回原结果,同键异载荷拒绝。未知结果保留原键与内容,不能生成新单重试。
确认成交只新建一张池来源商业主单,不接受任意已有独立订单号。LOCAL_LOOSEBOARD通过专用内部方法创建主单与历史,不执行原独立下单生成占位ll_order的分支;US_TRUCK同样只建商业主单,不生成模拟实托记录。独立下单保持其合法业务入口,池内订单走真实运输桥,不以“兼容”保留两套同单行为。
唯一桥表`ll_fleet_pool_order_link`以booking_id唯一,保存客户、business_type、商业单ID/业务号和桥状态;来货生成后再绑定唯一incoming_no和lastleg_order_id。预订DTO商业号来自桥投影,不在两处维护可写副本。登记来货由现有FleetIncomingAdapter创建唯一WarehouseTransfer及真实尾程来源,并在同事务反绑商业单;客户、目的地或来源不符则回滚,不产生第二张尾程单。
尾程订单列表、详情与导出通过同客户、同尾程单的正式关联展示商业来源:池来源为“本土散板/本土卡车 · 拼车需求池”,独立散板为“本土散板 · 独立下单”,未关联商业单的外接来货为“仓储转运 · 外接来货”。`orderType` 继续表示履约类型,不改写为商业类型。`businessSource` 返回商业类型、来源中文说明、关联商业单号及外接预订号;缺少关联显示“—”,禁止解析备注。`businessType` 筛选本土散板时覆盖独立与池来源两条路径;商业单号和预订号支持服务端包含匹配。Admin 商业单号仅在具备目标列表权限时链接到带该单号筛选的既有本土业务列表,池来源继续从“承运安排”查看。
实托数与托位分开:询价提供可空的预计实托数;US_TRUCK确认前必须有正数预计实托数,不能拿palletSpaces当palletCount。预计箱数同样允许未知,确认前须补完整真实预报;不以0或1伪造未知。实收时以去重后的真实仓库托盘数记录实际实托,按核准每托占位合计记录托位。商业单预算仍是独立可空预算,不自动写入成交金额。
池询价未采集柜型或是否委托打盘服务,商业桥须将这两项保留为未知:卡车/散板的`containerType`及散板的`palletRequired`为null,不套用40HQ或YES。实托数、占用托位及实际托盘存在均不能证明客户委托打盘;Admin/Client列表和详情将未知显示为“—”。响应允许空值或省略空字段,详情经summary承载;普通独立Create/Update请求的必填、枚举及默认规则保持原合同。
池来源商业单状态映射:成交为WAITING_INBOUND;真实收货开始为RECEIVING;实收并核量确认后为WAITING_CONSOLIDATION(散板新增对应状态);完整关联客户排车后为PENDING_DISPATCH;整车实际出库/发车为IN_TRANSIT;全部实际货物签收为COMPLETED;安全取消为CANCELLED。不得把绑定车次标为已发车。状态与历史由实际来源事务推进并带来源业务号/时间;退回、部分签收保持未完成,并展示实际派送摘要。重复保存回执不得重复追加完成历史。
真实出库/签收需要本地桥回传:现国内完成Outbox只覆盖FIRSTLEG来源,不能依赖它完成本土单。按桥中唯一来源和同客户派送/实际货量核对后回写主单;不得创建第二笔运费。池来源散板编辑/手工状态、卡车编辑/审核/手工收托/超托审核/分配/发车/完成/取消等入口必须识别来源后拒绝旁路,并返回当前应操作入口;不能只在页面隐藏按钮。
运费仍由真实转派送的`FLEET:{bookingNo}:{dispatchNo}:FREIGHT`唯一来源发布;商业主单、发布池、来货和签收回传均不重复发布该费用。全外接货不能另填一份派送应收。成交价、实际约定运费、Finance应收/实收各自表达,零价沿现有正式规则处理,不能绕过费用门禁。
成交/取消锁顺序沿第3节:车次→资源→发布→预订→商业关联/商业单。实际收货/签收在既有作业锁之后仅锁商业关联/商业单,不反向锁车次/发布/预订。商业单旧手工入口在本单锁内识别池来源直接拒绝,不反向协调车次。已有池来源来货也不得独立从旧来货取消入口取消而留下有效承诺;本轮登记来货后的取消/跨车改配明确阻断。
Admin和Client自己的本土订单列表/详情返回同一批查询产生的`fleetArrangement`摘要:来源类型、真实商业单号、预订号、计划发车、起运仓和目的地、交货说明、实际履约阶段/时间、约定运费(非实收)及只读原因,并提供已签/未签/退回数量和异常摘要;独立订单该字段为null。不返回发布池内部ID、余位、他人货物、司机私人信息或采购成本。原列表/详情不得逐行额外调用池接口。首版不额外建设任意存量订单批量导入/撮合。
## 6. 真实到仓、变更与取消
已确认后复用登记来货、PDA实际收货、运营核量确认、生成客户排车并关联本车、调度审核、PDA拣货、实测装载、理货审核、整车发车、目的仓签收、结案及资源释放。需求池提供关联业务跳转和实时摘要,不再建立一套“手填已发车”状态。
实收托位/重量/体积改变,须重新核量、检查本车剩余容量和确认费用;超量不可自动覆盖承诺。整单价和按托价保持既有口径,不静默把预算写为应收。BOUND预订由真实货物占位替代预订,不能叠加扣减;对应容量计划失效时停止继续接单,待重核。
DRAFT由本人或调度取消;池来源CONFIRMED仅在尚未登记来货时由调度一体取消商业关联、预订及占位。已有incoming、实收或BOUND拒绝池内快捷取消,进入既有实际作业处理;现有booking.cancel允许RECEIVED的行为不能旁路该池来源门禁。不可通过关闭发布或取消意向删除库存、清除已拣货或把已发车货物变回草稿。首版不提供实收后跨车次改配,遇到该请求明确拒绝并保留原单据,不自动重造。
## 7. 页面、请求预算与错误处理
Admin「车辆管理」的「拼车接货」包含“可拼车次”“我的登记”两个独立页签,仅加载激活页签;调度默认进入“待我处理”登记范围,销售默认进入“可拼车次”。调度可选全部登记范围,服务端拒绝销售越权该范围。主列表一行一发布车次:操作、发布号/车次号、起运仓、目的站/路线、发车/交货截止、已关联货物计划占用、未关联外接预留、各目的地可接托位/重量/体积、接单状态和调度联系信息;多目的站在同一行分行展示,详情展开分段表。查询起运仓/目的地使用文本条件,日期和状态使用本地选项,不为筛选增加目录请求。“我的登记”跨发布状态可读历史,不依赖OPEN列表。可拼车次默认使用 `scope=AVAILABLE`,在数据库分页前按 `OPEN + PLANNED + now < cutoff <= plannedDepartureAt` 筛选,管理员也遵循同一默认范围;满位或容量待核对但允许草稿登记的发布仍保留。管理员显式选择“全部发布(含历史)”时使用 `scope=ALL`,普通销售不得请求该范围。车次发布设置查找已有发布显式使用ALL,避免遗漏草稿或过期发布。详情页有登记权限时保留“登记意向”按钮,业务资格不足则置灰并展示服务端原因;无登记权限不显示按钮。
发布详情为独立页,首个响应带运输摘要、分段余位及获准意向首20条、total/page/size;意向翻页单独1次请求。池接口只返回专用offer/inquiry DTO,不复用含司机或客户联系信息的TripDetail/FleetCustomerOption。offer独立返回canCreateInquiry、canConfirm和blockReason,满位或待核对不错误禁用允许的草稿登记;未取得有效容量时显示“待调度核对”,已知满位才显示0。
操作承载矩阵:发布详情独立页;登记/编辑/查看意向为1080px居中;车次详情内“发布设置”采用居中表单;确认承运复用1080px登记窗口,同窗补齐资料、核对并通过save-and-confirm一次保存确认,不追加独立确认框;取消采用现有确认框,明确对象和影响。当前新增操作没有外部原型,按用户授权、本文矩阵及已确认车次高密度样式实现,不能拿方便的抽屉替换。未保存提醒覆盖取消、X、Esc及路由离开;结果未知时保留原请求键和载荷。
Admin本土订单池来源行增加“承运安排”只读入口(1080px居中),原编辑深链也只能展示只读原因和安排;正常独立订单保持原操作。关联车次/来货/排车跳转逐项检查目标权限,无权限只显示业务号。Client沿原详情展示同一客户摘要,不新增公开池。两端同步散板新状态标签和筛选,不能显示裸内部状态码。
未知预计箱数与预计实托数的可空类型须同步既有bookingTypes、tripBookings normalizer、TripBookingPanel及对应测试,旧面板不得把pool询价解析失败或自动补成1。池来源确认/修改操作同样使用服务端允许动作;管理面板不得将未完成商业关联的旧确认视为成功。
样式复用Admin高密度、integrated DataTable、操作列左置、统一查询/分页/按钮/错误态;不接入演示假数据。Client只在自己的订单响应中增加承运安排摘要,沿既有列表详情展示,无新公开拼车菜单。
| 操作 | 业务请求预算(登录/公共外壳另计) |
| --- | --- |
| 任一页签进入/切换/查询/重置/翻页 | 每动作1次活动页签分页;不预加载另页签,不逐行查询车次或容量 |
| 打开发布详情 | 1次详情,含分段余位和获准意向首20条及total/page/size;后续翻页各1次 |
| 打开登记表单 | 复用详情事实;客户候选首次聚焦/搜索才请求,输入防抖,取消迟到响应 |
| 报价候选 | 仅用户显式查询/翻页各1次,走池作用域专用候选接口;无报价权限0次,手填价不附加报价权限 |
| 确认/修改/取消意向 | 1次写命令返回新摘要;必要时最多1次当前详情刷新,不全表逐项刷新 |
| Admin/Client本土订单列表/详情 | 仍各1次,不逐单补查运力或预订;Admin行内打开已有承运摘要额外0次 |
加载时保留上下文;区分无发布、筛选无结果、本人无意向、候选为空及接口失败;网络错误显示诊断和重试,不伪装空数据;版本冲突要求重新核对;写入处理中禁重复提交。切页/关闭/切发布时忽略旧响应。筛选重置和页码watch只能有一个实际加载入口,避免重复请求。真实请求计数包含非第一页重置、快速切页和写成功后的刷新,不能只测首屏。
普通运力列表由数据库执行起运仓、目的地、日期、状态和文本筛选及分页,仅核对当前页的实时容量。显式启用`canConfirm`接单资格筛选时,先统计基础筛选后的候选;超过100趟即返回缩小起运仓、目的地或日期范围的提示,不展开逐车容量查询。100趟以内计算实时资格并返回精确总数,不能按当前页过滤后伪造总数或在后台扫描全部车次。
## 8. 实现归属与部署
Backend仍归Lastleg,Gateway复用现有fleet/last-leg通配路由;按API变更执行gateway-route-contract。新增持久化Mapper须显式@Mapper并跑注册合同。数据库基线、权限种子和测试环境差异SQL统一维护,不清库、不重复执行已成功未知结果SQL。
部署单元预计Lastleg、Admin及受DTO展示影响的Client;IAM若仅新增库内权限种子则核对实时权限刷新,不无故部署全服务;必要时按实际依赖补充清单。TEST单机Maven只使用现有锁及单执行器,禁止并发构建挤压服务。部署与数据库写入由当前对话串行操作,内部协作仅分文件实现与只读/离线核对。
## 9. 必验场景
### 冻结的接口和实现分工
服务前缀为`/api/platform/v1/last-leg/fleet/capacity-offers`;Admin浏览器HTTP基址已经含`/api`,消费路径省略该前缀,避免重复。新增接口沿既有Lastleg Gateway路由,不暴露内部接口。
| 方法与相对路径 | 语义 |
| --- | --- |
| GET / | 当前用户获准的发布分页,含逐目的站余位和资格;text起运/目的地、日期、状态、可接筛选 |
| POST /,PUT /{offerNo} | 调度创建发布草稿及编辑公开信息,校验车次/发布版本 |
| GET /{offerNo} | 发布详情及获准意向首20条;非OPEN仅调度或本人已有意向者可读受限投影 |
| POST /{offerNo}/publish、pause、resume、close | 显式发布状态命令,版本和持久幂等 |
| GET /inquiries,GET /inquiries/{bookingNo} | 本人意向及单条详情;调度可选择全部范围,销售不能用参数越权 |
| POST /{offerNo}/inquiries,PUT /inquiries/{bookingNo} | 登记/编辑草稿,登录人冻结销售负责人 |
| POST /inquiries/{bookingNo}/confirm、cancel | 调度成交与适用范围的取消,唯一桥及容量事务 |
| GET /customer-options | 用途限定ACTIVE客户ID/编号/名称目录,不返回联系人或电话 |
| GET /{offerNo}/quote-candidates | 公开给该场景的销售报价候选,需额外quote:list,按本车及客户/卸货站/币种/计价方式过滤 |
offer写入携带tripNo、tripRecordVersion、存在时offerRecordVersion、cutoffAt、公开联系信息、remark和idempotencyKey;意向含offer/trip/booking版本、customerId、businessType(LOCAL_LOOSEBOARD/US_TRUCK)、deliveryMode(SELF_DELIVERY/MANUAL_PICKUP_TO_WAREHOUSE)、estimatedArrivalAt、独立expectedPalletCount、cargo、quoteRef、idempotencyKey。Cargo.packageCount可空,确认前完整校验;可空不以虚假默认数替代。对象主身份使用发布号、预订号等业务编号;ID仅用于明确接口关联。
Admin路由:`/overseas-master-data/capacity-offers`及`/overseas-master-data/capacity-offers/:offerNo`。菜单与路由允许list或manage;销售写另需对应inquiry权限。客户端不增加运力路由。
持久化:每trip唯一`ll_fleet_capacity_offer`、持久命令记录(作用域/动作/键/请求hash/原结果)、预订新增发布/销售负责人/业务类型/交货方式/预计到仓/独立实托数字段、唯一`ll_fleet_pool_order_link`。桥表booking_id、booking_no、(business_type,business_order_id)唯一,incoming_no/lastleg_order_id为nullable unique;来源未发生保持null。不得只保存“最后一次键”而丢失旧成功请求的重放事实。Mapper/基线/统一空库SQL/本轮精确结构补齐/权限种子分别核对,无清库、存量修复或双写兼容。
实现分工:运力池工作包独占fleet发布及预订服务和其测试;订单桥工作包独占fleet/business、商业订单/来货/实际作业回写及其测试;前端工作包独占业务页面/API/types/tests和矩阵。当前对话集成共享路由/导航/权限、SQL、OpenAPI与部署。跨包调用FleetPoolOrderBridge在已有事务中执行,不另开事务、不双写费用;源码签名先在实现者间固定,禁止两个工作包同时改同一服务文件。
### 验收用例
1. 自有18/总30,同路段外接8确认后余4;另一客户再确认5失败,原已确认事实不变;重量或体积先满同样拒绝。
2. 两名调度同时确认来自不同销售的最后余位意向,最多允许容量内的承诺;销售自身调用确认必须拒绝;原键重放不增加订单、预订或费用。
3. 两个不同登录账号但同姓名仍相互隔离;销售猜测他人意向编号、调用调度确认或车次敏感接口被拒绝;Client不能查看运力池。
4. 暂停、关闭、截止、发车/取消、改派/路线/自有货变化、车辆停用/缩容均不能沿旧余位继续接单。
5. 意向到本土订单/来货/排车/派送保持同客户和唯一来源;实收超量阻断、预订转实载不双扣、允许的取消释放且不删除事实。
6. 本土散板和本土卡车分别从池内成交走到签收,本土订单真实终态回传;不制造第二张虚假尾程来源,不重复收费。
7. Admin按调度和销售最小权限、Client按本票客户,在1920×1080检查列表、详情、表单、加载/空/错态、动作门禁和网络请求次数;保留截图与脱敏网络计数证据。
8. 保留当前车次自有货链的核心回归:审核、拣货、改派后复审、整车发车、签收及资源分别释放;新需求池不得旁路这些规则。
## 10. 五轮审核记录
每轮必须有实际发现、修订和复核依据,前一轮改完再检查下一轮;五个“通过”标题不能代替审核。五轮结束后冻结开发版,发现实现与合同冲突仍须修正并补测。
| 轮次 | 检查重点 | 当前记录 |
| --- | --- | --- |
| 1 | 用户范围、池的对象、延期功能与现有实现差距 | 已识别“车次余位池”被误解为“待配货客户需求池”的偏差,纠正为每车次发布、销售从具体车次登记;三种完整愿景与统一我仓首版分开;不引入沿途提货门禁改造 |
| 2 | 容量/并发/权限/状态与车辆实时事实 | 审核V1后修订V2:补齐统一锁序、暂停与确认竞争、服务端截止及成功重放顺序、关闭后本人历史可读、池来源未登记来货才可取消、BOUND不重复扣位、旧接口旁路及事实指纹失效后显式恢复;依据FleetBookingService、FleetTripService.persist、capacityPlan及Reservations |
| 3 | 本土订单唯一来源、实际履约、状态和费用 | 审核V2后修订V3:确认仅创建池来源商业单,散板不再建独立占位来源;新增唯一桥、来货反绑、实托/托位分离、真实状态回写、旧手工入口和来货取消防旁路、唯一运费来源及回传不反向锁车次;依据LocalLooseboardService、UsTruckOrderService、FleetIncomingAdapter、DeliveryTransfer及国内完成事件范围 |
| 4 | Admin/Client交互、最小权限、请求预算与验收 | 审核V3后修订V4:补独立我的意向历史入口、Admin本土单只读承载、offer/inquiry/fleetArrangement专用投影、可空箱数直接消费者、两端状态标签/筛选、逐动作请求预算/分页上限、未知与满位区分、完整弹框关闭保护;按现Trips/Booking/TransportOrders及Client消费者核对 |
| 5 | 全文一致性、接口/SQL/权限/测试/部署可执行性 | 总核对V4并冻结V5:去除“任意既有单关联”残留,明确关闭终态与显式恢复;补接口/字段/路由及数据库唯一约束、持久重放、实现归属;Admin/Client请求预算统一,测试覆盖两类商业单、权限及取消旁路;本轮只授权TEST,部署与浏览器证据不由文档通过替代 |
### 预约侧可直接使用的来源解析边界
`FleetPoolSourceResolver.resolve(List<SourceRef(customerId, bookingNo)>)` 在同一服务内批量只读,每次最多100条;返回 bookingNo、tripNo、bookingStatus、warehouseId、destinationKey/Label、incomingNo、lastlegOrderId、businessOrderNo、fulfillmentStage 和登记recordVersion。未成交也保留登记来源;没有对应别名时返回null,不能计作另一票货。不返回私人联系方式。调用侧先校验每个来源的权限;不匹配客户或不存在的来源不返回,调用侧须比较请求/返回集合并提示缺失。
本侧期望预约覆盖以 `customerId + bookingNo` 查询并返回同一键、覆盖状态、预约业务号/确认号列表、缺项、sourceVersion及changeReviewRequired;别名由上述解析入口提供,预约侧负责归一化及货量去重。实际生产者签名由预约侧确定后本侧接入,不使用假覆盖结果。
来源解析补充:`Source` 同时返回 nullable `packageCount`、`expectedPalletCount`(均为预报,不是实收)、`estimatedArrivalAt`(数据库UTC LocalDateTime,到我仓预计到仓,不是目的地预约)。货量未知保持null。
B接受由A在 `appointmentplanning` 公开包建立唯一预约覆盖生产者。建议Java入口 `AppointmentCoverageQuery.query(List<SourceRef>)`,SourceRef为customerId、sourceKey(BOOKING:业务号或ORDER:订单标识)、destinationKey;结果以相同键返回status、appointments(预约业务号/外部确认号/确认时间)、missingFields、sourceVersion、changeReviewRequired。必须按同客户正式别名归一化;无真实货件资料可返回待补,不可伪造已确认。B在生产者存在后消费其公开DTO/服务,不维护第二套覆盖判断;若A采用不同签名,以A公开实现和测试为准收口消费者。
### 共用准备和连续处理接口定稿
- `POST /fleet/trips/prepare`:新建(计划、车辆、司机、排车单)或加入已有车次(车次号、版本、排车单)两种输入互斥;一次事务全部完成,失败不留下半成品车次。持久幂等复用现有命令记录,重试不得重复建车。共用UI `TripPreparationDialog`参数为warehouseId、warehouseName、dispatchNos,通过模块index.ts导出,实际仓库/来源由服务端再校验。
- `GET /fleet/trips/{tripNo}/dispatch-candidates`:本仓、未绑定、未开始执行且无其他车次外接承诺的候选,数据库分页;`TripDispatchSelector`替代手填编号。
- `POST /capacity-offers/inquiries/{bookingNo}/save-and-confirm`:同窗核对后一次命令更新资料、创建商业关联并保位,全部回滚或全部成功,保持原MANAGE权限;不自动生成来货。
- 原登记下`/fulfillment`按需只读本票;`/incoming`、`/receipt-confirmation`和`/arrange-dispatch`分别明确安排来货、确认实收、排入本车。池manage并不自动获得原车次booking-edit/booking-confirm/trip-edit或智能排车权限;服务端和前端同时校验对应权限。
- 实收排入优先复用唯一的同客户同来源完整排车;没有时使用真实实收计划托盘调用原预排。多张、混入其他来源、实收不完整或被其他车次绑定时整体拒绝。不创建假库存,不自动改配,不重复扣减预留;关联后旧容量失效须核对,审核/装载/发车仍独立。
- “待我处理”使用scope=TODO,仅调度可读;未完成候选超过100条要求按客户或登记号缩小范围,实时投影后返回准确total并分页,普通列表仍数据库分页。仓库尚未实收的记录由仓库负责,不混入调度核量待办;收货阶段以批量权威状态读取,不逐行请求详情。
- 后续输入/返回和权限完整定义在`baiyue-firstleg/lastleg-service/src/main/resources/openapi/fleet-preparation-v1.yaml`;本次复用现有表,无新增SQL结构或权限码。
@@ -0,0 +1,313 @@
# 拼车数据入口与操作简化评估草案
日期:2026-10-09;状态说明更新:2026-10-10。本文保留优化目标与评估依据,后续用户已授权按建议实施;已选定的开发规则以正式拼车契约为准,未选定建议不自动成为本批需求。
**已确认的业务起点:已有车次,销售为余位寻找客户货物。** 本批围绕“选车登记 → 调度确认 → 安排来货 → 实收后排入本车”简化,不建设独立的待配货需求池。
目标是让用户打开页面就能回答:**这票货保位了吗?现在轮到谁?下一步点哪里?** 同一份资料只录入一次,同一票货始终能从原登记记录跟进。
本草案供业务评估和交付对照,不替代[内部拼车需求池首版开发契约](内部拼车需求池首版开发契约.md)。以下目标不表示均已实现;原文档整理阶段“仅修改草案、不启动开发”的限制已被后续实施授权替代。部署及验收结论以[测试环境单机部署与配置契约](../测试环境单机部署与配置契约.md)为准。
与预约优化并行时,本文负责拼车接货和共用车次操作简化;[美国预约管理统一总览与优化方案](美国预约管理统一总览与优化方案.md)负责在途筹划、对外预约与变化跟进。跨方案职责、交接及先后顺序统一见该文[第九节](美国预约管理统一总览与优化方案.md#九-建议实施顺序与协同分工),本草案不再维护另一套整链排期。当前已进入实施;拼车常用路径与预约扩展分别核对,不能以预约日历全部完成代替拼车易用性验收。
## 评估先看这里
**建议把用户操作收敛成两条路径:调度准备车次并发布余位;销售选车登记客户货物,再由原记录持续跟进。** 系统负责带出资料和关联单据,人员只负责需要业务判断的确认。以下为目标方案,具体边界见后文,不代表测试或灰度环境已全部具备。
### 数据从哪里进来
| 业务起点 | 用户从哪里操作 | 系统应带入什么 | 人员仍需确认什么 |
| --- | --- | --- | --- |
| 已有待运货物,需要安排车辆 | 排车列表选择合格货物,点击“安排车次” | 起运仓、所选排车单、客户归属和目的地 | 使用已有车次还是新建;车辆、司机、时间及多站顺序 |
| 已有车次,希望利用余位接货 | 车次详情点击“发布拼车余位” | 本车路线、计划发车、有效容量及已有货物占用 | 交货截止、缺失资料,以及是否正式对外接货 |
| 销售已有客户,想搭这趟车 | 拼车接货列表直接点击“登记客户货物” | 所选车次、起运仓、路线、截止时间;单一目的地自动选中 | 客户;多目的地时选卸货站,已知货量可先填 |
| 客户确认要送货 | 原登记记录继续处理 | 已登记的客户、货量、报价及交货资料 | 调度确认承运;明确安排来货 |
| 客户货物已实际到仓 | 仓库按原收货流程操作,调度从原记录查看 | 真实收货结果、原车次和订单关联 | 实收差异、容量和费用;确认排入本车 |
**创建车次、绑定排车单,并不等于已经发布余位。** 在用户提供的车次截图中,路线仍显示“待确定卸货点1”,登记窗口也没有可选卸货站。这可以说明该操作位置缺少可选站点,但不能单凭截图判断是数据未补齐还是程序异常。目标交互应在车次准备时就列出缺项并提供“完善卸货站”,避免用户到登记窗口才遇到“无数据”。
### 哪些操作可以省掉
| 现有操作负担或需要避免的做法 | 建议处理 | 保留的业务边界 |
| --- | --- | --- |
| 为找入口先进入详情,再寻找登记按钮 | 在可拼车次每行直接放“登记客户货物” | 不符合登记条件时,原位置展示原因和下一步 |
| 反复录入仓库、车次、目的地和已填货量 | 从来源带入,同一登记连续复用 | 来源变化后提示重新核对,不覆盖人工确认结果 |
| 只有一个卸货站还要再选一次 | 自动选中并展示 | 多站时仍需用户选择 |
| 初次接触客户就填写全部货量、价格和交货信息 | 先登记,确认承运前再补齐必要信息 | 未知数量留空;保存登记不保位 |
| 再点一次“提交调度”才进入待办 | 建议省去;保存后调度可见,按缺项分配待办 | 页面明确告知保存后的可见范围 |
| 确认承运后再手工创建关联本土订单 | 系统沿正式承运命令生成唯一关联 | 失败不能显示已保位,重试不能重复建单 |
| 查找、复制、粘贴排车单号完成关联 | 使用合格候选;实收后按真实来源复用或生成并关联 | 来源冲突、部分已安排、候选不唯一时停止自动处理 |
| 销售查看容量计算和全部专业单据 | 默认只看可接货量、当前进度、负责人和下一步 | 调度仍能查看容量依据和关联单据 |
| 将承运、来货、排入、发车压成一次“完成” | 不建议省略这些事实节点,只简化各节点的录入 | 防止未到货就生成实收、未审核就发车 |
### 最少需要填写多少
这是建议目标,不是当前表单的实测字段数量。自动带入值也应可见,避免用户不知道系统选了什么。
- **首次登记:**单目的地车次,最低只选择客户;多目的地再选择卸货站。允许同时填写已知货量,不强制分两次录入。
- **确认承运:**只补缺失的货量、价格和交货资料,已填有效内容无需重填。托位、重量、体积的容量核验不能仅用其中一项替代。
- **安排来货:**复用已核实的预计到仓和交货说明,只补本阶段缺项。没有可靠来源的到仓时间不能自动猜测。
- **实收后排入:**展示实收结果和差异,正常情况下不手输订单号、来货号、排车号;有异常由调度明确处理。
### 可行性及实施成本判断
| 优化类别 | 初步判断 | 需要核对的关键点 |
| --- | --- | --- |
| 文案、字段分组、单站自动选中、列表直接登记 | 相对容易,优先改善可发现性 | 隐藏字段不能隐藏必填缺项;不同角色可见范围正确 |
| 数据复用、角色待办、同一记录跟进 | 可行,需要页面与服务端共同提供事实 | 谁负责、缺什么、能做什么不能仅由前端猜测 |
| 一次完成建车关联、补齐资料并承运 | 可行,但涉及多项写入,不能只合并按钮 | 全部成功或明确续办;并发、版本和原请求重试正确 |
| 实收后复用或生成排车并关联原车次 | 可行,业务校验较多 | 实收来源唯一、库存真实、外接预留只替换一次、审核继续有效 |
| 自动报价、自动选多站路线、自动改车或拆分运输 | 本次不建议默认自动化 | 商业承诺、路线和货物拆分规则需单独确定 |
### 建议您重点评估的五个问题
1. **业务起点是否覆盖日常工作?** 当前以“有车找货”为主;如果大量客户先报货、暂时没有合适车次,应另评估“待配货登记”,不能让这类货物被迫绑定一趟不确定的车。
2. **保存后直接让调度看见是否合适?** 建议省去单独提交步骤;资料不全交销售补,资料齐全才成为调度承运待办。
3. **确认承运前的资料是否都必要?** 第四节逐项说明阶段。评估时可调整采集时点,但涉及容量、价格和真实交货的必要信息不能直接取消。
4. **承运确认与安排来货是否保留两个动作?** 建议保留,因为“答应接货”与“确定何时到仓”可能不是同一时刻;信息齐备时可以在同一窗口连续完成。
5. **异常流程的覆盖是否足够?** 首批先覆盖正常接货、缺资料、满位、实收差异和重试;拆运、来货后的取消与跨车改配,需要明确业务规则后再扩展。
建议先用第九节的新人操作任务验证常用路径,再决定是否扩展分支。不要仅按按钮减少数量评价效果,还要看用户是否知道“是否保位、轮到谁、下一步做什么”。
### 本批范围收口
先对照“选车登记 → 确认承运 → 安排来货 → 实收排入”验证少填写和连续处理。首次登记默认展开客户与卸货站;已知货量可展开填写,业务类型默认值明确可见并可在确认前调整。调度默认进入待我处理,销售默认进入可拼车次。原登记突出一个符合当前阶段和权限的主要动作,其余操作及关联单据放次要位置。
预约覆盖作为必要关联结果保留;统一日历、船期变化影响及其他预约来源按预约方案单独交付,不作为继续扩大本轮拼车界面的理由。本文不宣称代码、部署或1920×1080验收已完成。
## 一 简化方向
1. **一个直白入口。** 建议菜单使用“拼车接货”;销售看到“可拼车次”和“我的登记”,调度直接看到“待我处理”及发布入口。保留现有菜单位置,不额外增加并列菜单。
2. **一票货持续跟进。** 登记后从同一记录查看资料、处理当前事项和跟踪进度;本土订单、来货、排车等放入“关联单据”。不要求销售理解单据关系,也不再重复下单。
3. **每次只突出当前要做的事。** 页面显示当前进度、下一步负责人、具体缺项和一个主要动作;其他合法操作保留在次要位置。
4. **资料已知就能填,未知不强填。** 区分“现在必填”“确认前待补”和“始终选填”,不把后续必填统称为选填,不用虚假默认数补齐。
5. **简化录入和关联,保留真实作业。** 容量校验、实际收货、调度审核、拣货、实测装载、理货审核及PDA发车继续有效。
销售新增外部货源、等待匹配车辆的独立“先有货、后找车”登记、虚拟运力、自动撮合和实收后跨车改配不在本批。已有头程在途货的提前筹划属于预约方案,不受上述外部需求池边界排除;它仍须通过真实货源和排车资格进入共用车次能力。若以后业务改变,再单独评估,不让这些分支影响本次常用路径。
## 二 首页让人一眼看懂
### 销售看可拼车次
一行一趟已发布车次,操作列在左,主要按钮为“登记客户货物”。默认突出以下信息:
| 信息 | 展示要求 |
| --- | --- |
| 起运仓、目的地 | 使用业务名称;多目的地分别展示,不让销售猜哪一站能接货 |
| 计划发车、最晚送仓 | 两个时间分别标注,不能只写含义不明的“截止”;最晚送仓对应现有交货截止,不另造一套时间 |
| 可接货量 | 按目的地同时展示剩余托位、重量、体积,不用全车单一数字代表所有路段 |
| 当前能做什么 | 可登记时显示登记入口;暂不能承诺但仍允许登记时,明确“可先登记,待调度核对,尚不保位” |
展示示例,仅说明文案,不代表真实容量:
> 目的仓 A:余 4 托位|最多 2.5 吨|18 m³;三项须同时满足。
> 可登记客户货物,调度确认承运后保留货位。
未知容量显示“待调度核对”,已知满位才显示0。能否登记与能否确认承运分别由服务端判断,不能用“暂不可确认承运”代替销售的登记资格。暂停、关闭、截止等限制继续遵循正式契约。
销售默认列表不展开分段计划占用、外接预留和容量计算过程,这些放入调度详情。业务单号及调度公开联系信息仍可查看;不得展示司机私人信息或他人客户货物。
发布时调度核对交货截止,结合实际收货、理货和装载安排预留时间。当前截止默认与发车一致只是已有默认值,不代表来货可在发车时才开始收货;本批不凭空规定统一提前时长。
### 同一登记记录持续跟进
“我的登记”跨发布状态保留本人记录,车次关闭或已发车后仍能跟踪获准的历史。记录顶部突出“客户+目的地”、车次业务号、当前阶段、是否保位及下一步负责人。
当前可执行的资料补充、承运确认和来货安排尽量在同一处理窗口完成;需进入仓库或排车专业页面时,直接定位对应业务,避免重新搜索和输入编号,并提供返回原记录的路径。仓库继续使用现有收货页面和PDA,不另建一套作业入口。
关联单据按权限提供链接,无目标权限时只显示业务号。底层仍复用同一意向、预订及正式业务关联,不新建另一张独立“拼车单”。
## 三 常用操作路径
```mermaid
flowchart LR
A[调度发布本车余位] --> B[销售登记客户货物]
B --> C[销售补齐待确认资料]
C --> D[调度确认承运并保位]
D --> E[调度明确安排来货]
E --> F[仓库实际收货]
F --> G[调度核对实收与费用]
G --> H[确认排入本车]
H --> I[审核 拣货 实测装载 理货 发车]
```
资料已齐时无需再做一次补充操作。该图表示本票货的衔接,不要求整车所有货物齐备后才开始每张排车单的审核。
### 销售登记与补齐资料
销售直接从车次列表点击“登记客户货物”。先选客户;只有一个卸货站时自动选中并展示,多个站时明确选择。货量已知就填,未知允许先保存;多站不能替用户猜目的地。
本批建议只有“保存登记”,暂不新增“提交调度”命令。**保存后调度可见,不是仅自己可见的私人草稿;保存也不保位。** 使用现有DRAFT及资料完整性,区分以下处理提示:
- 资料未齐:显示“待补资料”,具体列出销售还需补充的内容。
- 资料已齐:在调度待办中显示“待调度确认”;若容量、路线或资源存在阻断,则显示“待调度核对”及具体原因。
- 已确认承运:才显示“已保留货位”。资料填齐不能替代承运成功。
资料完整性、缺项和动作资格由服务端提供或按正式合同补充,不能只靠前端判断。它们是处理提示,不新增可手改的业务状态。若以后确需销售明确提交后调度才可见,须另行定义交接命令、权限和撤回规则,不能只增加一个按钮。
销售负责补充客户货物预报、约定价格、交货联系人和交货资料;调度负责车辆、路线、容量及承运资格。有权限的调度可代补已核实资料,但不凭猜测代填。
### 调度确认承运与安排来货
调度从“待我处理”进入,在一个窗口核对客户、目的地、完整预报货量、约定价格与币种、交货安排及本车有效余位。已填内容直接复用;缺资料明确指向销售,缺容量或路线则由调度处理。
点击“确认承运”成功后,系统保留货位并生成唯一关联本土订单,提示“已保留货位,尚未安排来货”。保存资料与确认结果分别反馈,不能把保存成功当成承运成功。
“客户货物登记”和预约侧的“预约安排”是不同记录。确认承运只证明本车保位,不表示FBA/收货方已接受这票货;需预约的目的站应关联预约侧返回的覆盖结果,缺货件资料或需补充/改约时引导有权限人员处理。可预约阶段和核对时点在共同交接阶段确定,不能用现有登记DRAFT充当预约状态,也不能自行创建第二套收货预约。
确定客户来货安排后,由有权限的调度明确点击“安排来货”,沿用客户、目的地、预计到仓和交货说明,补齐本阶段必要资料。承运确认不自动生成仓库待办;“线下安排提货回仓”只是交货说明,不表示系统已生成独立提货任务。
### 实收后确认排入本车
仓库按现有流程实际收货,系统展示预报与实收差异。调度核对实际货量、占用托位及约定运费;有差异先处理,不能以预报覆盖实收。
核量完成后提供“确认排入本车”,整合合格排车单选择或生成及车次关联。成功提示“已排入本车”,并显示服务端返回的下一待办;通常仍需调度审核。**排入本车不等于已经装车或发车。** 后续审核、拣货、实测装载、理货和PDA发车继续按真实事实推进。
## 四 字段按阶段展示
| 阶段 | 默认展示和需要确认的内容 | 自动带入或延后 |
| --- | --- | --- |
| 首次登记 | 客户、目的地;已知的预报货量可直接填 | 本车仓库、路线、发车和交货截止带入;单站自动选中。单站时允许只选客户先保存 |
| 确认承运前待补 | 箱数、托位、重量、体积、按业务类型要求的预计实托数、约定价格与币种、必要联系人和交货安排 | 已填内容复用;业务类型明确可见。收起时仍显示“确认前还差哪些项”,不得标成普通选填 |
| 始终选填 | 货物备注及额外说明 | 收起展示,不挤占首屏;已知的后续资料仍允许提前填写 |
| 安排来货 | 核对预计到仓、交货说明;私人地址补全必要收件资料 | 沿用客户、目的地、商业订单和车次关联,不重复建单 |
| 核对实收 | 实收与预报差异、实际占用托位、实际约定运费及容量影响 | 箱数、实托、重量、体积来自真实收货;调度只补必要核对项 |
| 确认排入本车 | 实际货物、目标车次及关联后的容量、审核影响 | 系统选择或生成排车并关联,无须手输编号 |
“确认前待补”与“始终选填”分区显示,已填字段不重复录入。必要项按业务类型及正式契约校验,例如本土卡车确认前要求正数预计实托数。
- 预计箱数、实际托盘数和占用托位分别表达,不能互相替代。托位可解释为“占用车上多少个标准托盘位置”。
- 未知数量保持未知,不用0或1补齐;计费重量不能替代真实装载重量。
- 仅从可靠来源带入默认值,允许查看来源;币种、计价方式、业务类型在确认摘要中可见。
- 客户联系人不能取司机私人联系方式;客户候选目录也不应被假定包含联系人资料。
- 来源变化时提示差异和影响范围;无效的路线、报价或容量须重新核对。
## 五 当前进度、负责人和主要动作
下表是目标展示示例,最终动作须同时满足实际阶段、服务端资格和当前用户权限;销售只处理本人获准记录。
| 当前情况 | 谁处理 | 提示示例 | 主要动作 |
| --- | --- | --- | --- |
| 预报或成交资料不全 | 销售 | 待你补充重量和约定运费,尚未保位 | 补充资料 |
| 资料已齐,等待承运决定 | 调度 | 待你确认是否接货,尚未保位 | 核对并确认 |
| 路线或容量需要复核 | 调度 | 本车货物已变化,需重新核对余位 | 核对容量或路线 |
| 承运已确认,来货未安排 | 调度 | 已保留货位,尚未安排来货 | 安排来货 |
| 已安排来货,货物未到仓 | 销售跟进客户;仓库等待来货 | 已安排来货,等待实际到仓 | 查看来货安排 |
| 仓库收货进行中 | 仓库 | 仓库正在收货 | 销售、调度查看进度;仓库沿原作业继续收货 |
| 实收与预报有差异 | 调度,必要时销售联系客户 | 实收比预报多1托,待核对容量和运费 | 核对差异 |
| 实收已核对,满足关联资格 | 调度 | 本票已核对,可排入原车次 | 确认排入本车 |
| 已排入本车,审核待办存在 | 对应审核人员 | 已排入本车,待调度审核或理货审核 | 打开对应审核事项 |
| 实际已发车 | 原派送作业人员 | 已发车,按实际派送状态跟进 | 查看运输进度 |
同一事实对不同角色采用对应文案:销售看到“等待调度确认”,调度看到“待你确认”。无权操作时展示负责角色及进度,不以无权限按钮作为唯一下一步。
非本角色待办仍可跟踪,但不混入“待我处理”。暂停、截止或关闭后不能继续编辑的登记,只显示获准的查看、取消等实际可用动作,不能一直提示销售去补一个已无法保存的表单。
## 六 异常时也要知道怎么办
| 情况 | 当前处理边界 | 页面应给出的下一步 |
| --- | --- | --- |
| 资料不足 | 未确认、不占位 | 列出销售待补字段,回到对应输入处;容量问题单独交调度 |
| 满位或容量待核对 | 仍可登记时允许保存,禁止越过容量门禁确认承运 | 明确“尚未保位”;已知满位等待调度决定,计划失效由调度重新核对并按资格恢复接单 |
| 发布暂停、关闭、截止或车次事实变化 | 按服务端资格限制登记、编辑和承运;发布关闭不等于取消已确认业务 | 说明具体原因,保留已登记业务跟踪;已确认承诺由调度核查影响,不宣称自动改车或恢复接单 |
| 已确认但尚未登记来货,需要取消 | 由调度按正式命令一体取消预订、商业关联并释放占位 | 显示取消对象和影响,确认成功后反馈;不要求分别取消多张单 |
| 已登记来货后需要取消或跨车改配 | 登记来货后,池内取消及跨车改配按正式契约明确阻断;不得通过旧来货取消入口旁路 | 明确限制及负责调度,保留原单据和库存;仅链接实际存在且允许的作业,不展示虚假的“去改车”按钮 |
| 部分货物未收齐 | 本批不自动把一条意向拆到多车,不将未到货算成实收 | 仓库继续收货,销售跟进缺货;若客户确认不再送齐,交调度核查现有可用处理方式,不能直接点完收货 |
| 实收超量或价格变化 | 重新核量,检查托位、重量、体积及费用;不能自动扩大承诺 | 展示预报、实收和差异,调度核对;超出本车容量时阻断排入,明确当前不支持自动改配 |
| 已排到其他车次、来源不一致或候选不唯一 | 不重复创建排车,不把任意已有库存接成本意向 | 显示冲突业务号及原因,交调度核查;不自动解绑或绕过改配限制 |
| 保存部分成功、超时或他人已修改 | 保存不等于承运成功,结果未知不等于失败 | 说明已完成步骤;未知结果保留原请求续试,版本冲突保留填写内容并要求重新核对 |
不支持的动作要明确说明边界和负责角色,不能用笼统“查看待处理事项”掩盖没有处理能力的情况。
## 七 调度准备车次与发布余位
本批以已有车次为主,准备车次保留两种现有业务起点,不让销售参与车次资源配置。
本节是两份方案共用车次操作的唯一设计展开处,由拼车/车次实施职责负责。预约页带入已核对来源后,复用同一候选、资格、建车/关联和发布入口;不另建表单、容量算法或写命令。预约筹划关联、外接确认保位、实收后正式排入本车分别通过各自资格,不能因共用入口合并门槛。
- **已有待运货物:**在排车列表勾选合格排车单,点击“安排车次”,选择加入已有车次或新建车次。仓库、货物、目的地自动带入;车辆、司机、计划发车及预计任务结束由调度确认,多站顺序由调度确认。
- **先有运输安排:**保留车次新建入口,再用候选列表添加本仓待运货物,替代查找和手输排车号。
- **发布余位:**同窗展示自有货占用、有效容量和截止时间,只补缺失数据;明确“确认发布”,保留部分成功后的续办能力。
不同仓库、已绑定其他车次或状态不允许的排车单不能混选提交。允许跨客户共享车次,但货物归属和每单审核独立。自动补齐卸货站不等于自动优化路线。
无自有货、仅准备接外部货的完整发布能力仍需定向核对;不能用空货单假定已有有效的零占用计划。没有落实车辆、司机的虚拟运力不在本批。
## 八 实施顺序与必要边界
以下是拼车侧内部交付包,不是工期承诺或独立于预约方案的发布排期。第一批主要对应共同顺序的并行工作,第二批对应共用车次接入,第三批对应外接履约衔接;具体依赖以[共同工作包](美国预约管理统一总览与优化方案.md#工作包与先后依赖)为准。
| 顺序 | 建议交付内容 | 完成判断 |
| --- | --- | --- |
| 第一批:先让常用流程走得明白 | 入口文案、销售简明列表、直接登记、分阶段字段、单站自动选择、缺项及角色待办、同一记录进度、来货资料复用;把合格排车单候选选择前移,减少手输编号 | 从选车到后续履约,每阶段知道是否保位、谁处理、从哪里继续;已有排车单可选择关联。无排车单时可直达现有作业,尚不能宣称已实现一键生成并关联 |
| 第二批:减少调度的跨页准备 | 勾选排车单安排车次、同窗补齐资料并确认承运、准备与发布的连续操作 | 新建、分配、绑定或保存部分成功时能继续,不重复建车、建单或宣称占位成功 |
| 第三批:整合实收后排入本车 | 一次业务操作复用或生成合格排车并关联,协调库存、预留替换、容量及复审 | 正常实收排入无需手工组织中间单据;异常、超时、并发及复审均有明确结果 |
“确认排入本车”的已有排车复用必须同时满足:**同客户、同一真实来货来源、覆盖本次全部实收货物、未绑定其他车次,并通过现有库存及排车资格校验。** 没有合格排车时才按真实来源生成;候选不唯一或已有部分安排时先核查,不自动另建重复单。其他已有在仓货继续从正常待运货物入口处理,不导入任意独立订单或库存来拼接本意向。
- 客户商业订单、来货及真实尾程来源保持唯一关联;外接预留转为真实货物计划占用时只计一次,不重复占位或收费。
- 一次用户操作涉及多个写入时,需要相应服务端编排或明确的部分成功续办机制;承运确认中的订单创建与占位必须保持正式契约的一次命令,不由前端拼接成功。
- 资料完整性、负责人提示和候选列表若缺少服务端数据,需补相应合同;不把全部优化误判为纯前端改文案。
- 列表不逐行请求详情,详情和候选按需读取;写命令继续复验权限、版本、来源及资格。重复点击和未知结果重试不重复创建、占位或收费。
- 直接外接预订是否有不经销售发布的独立用途仍需核对;本批保留入口,对池来源标记“来自拼车登记”,不强行合并不同业务来源。
### 交给拼车与车次实施对话的任务说明
- **目标:**完成本文选车登记、确认保位、安排来货、实收后排入本车的连续操作,并提供预约侧可复用的车次准备、容量和发布能力。
- **先交付:**具体文件写入清单、货源/排车资格、逐站余位与发布资格的交接示例;明确外接预留如何在实收关联后被替换,并与预约侧核对外接货进入FBA预约的阶段和来源。
- **独占业务:**销售登记、外接预订、商业/来货关联、车次与排车关联、容量和发布。预约候选/覆盖/确认结果由预约侧提供,本侧维护消费与跳转。
- **依赖:**读取预约侧的来源关联、时间/材料摘要、预约覆盖及变更结果;共同接口确定后可以先做不依赖对方实现的表单和流程简化。
- **交付物:**选定正式契约改动、受影响接口/类型/权限/SQL清单、实现与定向验证结果、供预约侧接入的实际入口,以及尚未部署/人工验收的事项。公共文件按共同分工交单一写入者整合后,本侧复验其业务。
- **完成条件:**既有货源可通过唯一车次能力组织运输;外接货从原登记跟进到实际履约,确认保位/安排来货/排入/发车含义清楚,预留替换不双扣,不重复建单或收费,来源、容量、权限和失败重试均可核对。
该工作包已由用户安排实施;环境操作仍按对应授权与统一执行窗口处理。
## 九 用新人实际操作验收
以下是建议验收目标,尚不是测得的效果。Admin按1920×1080、浏览器100%缩放,由人工操作并提供截图,AI核对证据;没有截图时标记“待人工截图确认”,自动检查结果单独报告。
找一名未参与开发的业务人员,不先讲解“意向、预订、预排、绑定”的区别,让其完成以下任务:
| 任务 | 应能独立完成的动作 | 应能准确说出的结果 |
| --- | --- | --- |
| 销售选车并登记 | 找到目的地、发车、最晚送仓及三维余位;单站自动带入,未知货量仍可保存 | 保存后尚未保位,调度可见;知道缺什么、由谁补 |
| 调度确认接货 | 找到需要自己处理的登记,同窗核对已填资料和容量,再确认承运 | 已保位并关联本土订单;尚未安排来货时仓库没有因此收到新来货待办 |
| 跟进实际收货 | 从原登记查看来货及收货进度,识别当前负责角色 | 知道是否需要自己操作;不把预报当实收 |
| 实收有差异 | 看懂预报、实收和差异,找到核量及容量处理入口 | 知道超量为什么不能排入;不会误认为能自动改车或拆运 |
| 确认排入本车 | 按当前实施批次选择已有合格排车,或使用已实现的生成并关联操作 | 已排入不等于已装车、已发车;知道下一审核或作业环节 |
每次操作前让试用者回答:**保位了吗?轮到谁?下一步点哪里?** 记录答错、停顿、求助、重复填写、跨页找单和复制编号的位置,再据此调整,不预先承诺节省比例或完成时间。
同时检查以下底线:
1. 主操作和下一步提示首屏可见;后续必填与选填能区分,缺项不藏在笼统的“补充资料”里。
2. 单目的地不重复选择;多目的地不自动误选;所有数量未知与0分开,容量三项及各目的地口径正确。
3. 已保存且有效的客户、目的地、到仓及交货信息沿链路复用;业务编号用于识别,不把内部ID显示给用户。
4. 第一批已有排车选择无需复制编号;第三批正常实收排入无需另行查单建单。各批按实际交付范围验收,不提前声称全链已打通。
5. 满位、暂停、过期、路线变化、实收超量、冲突和结果未知均给出具体原因及实际可用动作。
6. 确认承运只生成一份关联商业订单;重复操作不重复创建、占位或收费;取消和改配不越过正式边界。
7. 每单调度审核、真实收货、实测装载、整车理货审核和PDA发车门禁继续有效。
## 十 当前数据关系与实现依据
当前“拼车需求池”是已发布车次的余位目录;尚无独立待配需求池。本节用于开发定位,不要求销售学习这些对象。
| 当前对象 | 沿用关系 |
| --- | --- |
| 排车单与车次 | 多张客户排车单可关联共享车次,各客户归属及审核保留 |
| 运力发布 | 每车次一条发布,余位依据有效计划和已确认外接占用计算 |
| 客户意向与外接预订 | 复用同一预订,保存发布来源和销售负责人;未确认不占位 |
| 本土订单 | 确认承运时自动生成唯一关联订单,不需独立再下单 |
| 外接来货 | 由明确操作创建,关联真实收货来源及库存,不能以预报代替实收 |
| 外接货排车 | 实收核量后关联原车次,由真实计划占用替代外接预留,不能重复扣减 |
当前已有单站匹配、容量与发布同窗、未知货量暂存和承运自动生成本土订单等能力。主要待优化的是同时展示过多字段、角色待办不清、跨页查找编号,以及实收后的连续处理;这些调整不能仅凭既有接口存在认定已完成。
- [内部拼车需求池首版开发契约](内部拼车需求池首版开发契约.md):当前范围、权限、容量、订单及取消规则。
- [海外车辆模块指引](../../apps/admin-web/src/modules/overseas-master-data/AGENTS.md):车次、预订及履约入口。
- [拼车列表](../../apps/admin-web/src/modules/overseas-master-data/pages/CapacityOffersView.vue):当前销售列表、字段与资格展示。
- [车次计划表单](../../apps/admin-web/src/modules/overseas-master-data/components/TripPlanDialog.vue):当前建车与路线输入。
- [意向表单](../../apps/admin-web/src/modules/overseas-master-data/components/CapacityInquiryDialog.vue):当前同时展示的字段及保存操作。
- [外接履约窗口](../../apps/admin-web/src/modules/overseas-master-data/components/TripBookingFulfillmentDialog.vue):当前来货、实收及手填排车号关联。
进入开发定稿时,将选定的交互、字段责任、资格投影及实施范围同步到唯一正式契约;本草案不作为已实现或已验收证明。
@@ -0,0 +1,361 @@
# 排车列表前端原型核对
## 本轮范围与结论
2026-10-19,前端任务 `01a1524f-52c7-7cc3-9b08-d34ad24c172a` 按总控 `01a15230-a9d6-7503-a8a9-d70691df49e5` 的首轮准备派工形成本文。工作区为 TEST 项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host local、`C:/Users/BY-OY/Desktop/code/chongchong-global`;三项已经通过本机项目清单和cwd核对。首轮仅写文档;随后总控按共同契约第八至十节解锁前端生产代码和离线验证,本文同步维护实施切片。始终不提交/推送/部署/运行环境SQL或真实HTTP,不操作真实业务,不建分支/worktree或项目副本,不跨对话发信或递归委派。
业务目标唯一见[排车列表统一作业改造契约](排车列表统一作业改造契约.md)。其最新第八至十节覆盖本文首轮矩阵中的历史待裁定表述;以下“当前实现”记录首轮读取快照,实施结果单列,不把旧快照当作仍未修改的事实。日历新增预约已分离,不由本任务设计、编写矩阵或实现;仅保留整车改造影响的已有预约直接消费者接线。
首轮主要差异:Admin先创建客户排车再安排共享车次,审核进入旧车次详情;列表缺派送中、派送完成阶段。首轮排车详情为连续分区,首批现已改为独立页面四个彩色图标页签,真实数据对象仍待统一接入。PDA仍以 `tripNo/tripRecordVersion/tripDispatchCount` 执行旧多排车整车发车;目标语义已按正式契约确定,实际请求需等待公开提供者补全后原子替换,不用骨架冒充全链完成。
本文行号绑定本轮读取的工作区文件;其他任务后续修改可能移动行号,实施时用同列符号重新定位。
## 证据与优先级
| 编号 | 证据 | 使用方式 |
| --- | --- | --- |
| P | `C:/Users/BY-OY/Documents/WXWork/1688854456873012/Cache/File/2026-10/悦/悦/新版.html`;SHA-256 `844B6A602FBDD7382EFCF3C71A0F67018F5481C5B3189F3A6997CDF274A643C4` | 仅定向读取 `page-outbound-vehicle`、`page-outbound-vehicle-detail` 及其关联弹框、函数。下文 `P:行号` 均指此文件。 |
| S1 | `C:/Users/BY-OY/AppData/Local/Temp/codex-clipboard-d961dfb7-bc3d-4d7b-95ac-6045d05ca279.png`;SHA-256 `C2567DABA3DFE91345CDBA043F5DEB50E1496821218BA8CAE46AEF2BEE5D4DE5` | 已用 `view_image` 核对:车辆信息、排车信息、单据信息、关联订单明细四块;字段和表列依据。截图截到了表格前部,不推断截断区域的行数或数据。 |
| S2 | `C:/Users/BY-OY/AppData/Local/Temp/codex-clipboard-cb9010b0-8ce8-43e5-b40f-70f4a4d13150.png`;SHA-256 `72FC5CA97D8BA7FA717C201EDA135DAE18C2AE2608088C49E531F1D861D144AD` | 已用 `view_image` 核对现有横向彩色图标、激活底色及下划线。八个旧车次页签仅作样式参考,不作为本批详情内容。 |
| C | 本批统一作业契约第一、二、三、六节 | 一单一车、五阶段、两种建单、临时外配、PDA 核平、四页签及附加能力保留优先于原型旧行为。 |
| V | `docs/Admin-Client前端原型还原验收规则.md`;`docs/Admin高密度界面规范.md` 的样式维护边界和新模块接入规则 | 按逐操作判断承载方式;采用公共密度、白底紧凑字段、原有字号与页签,不照搬灰卡。真实页面待人工在 `1920×1080`、100% 缩放下截图确认。 |
原型存在必须由 C 覆盖的行为:`P:18656 completeOutboundVehicleLoading` 同时写装车完成时间和 `depart`,不可复制;`P:18744–18746` 完成页从 `vehicleBusinessRecords` 取自营记录并有演示值拼接,必须改为排车自身的服务端正常签收汇总;`P:18840 saveBol` 一次只生成一张演示派送单,不满足按客户+目的仓拆分;`P:18960 saveVehicleEdit` 禁止无订单保存,与本批允许空单冲突;原型手工车辆状态、浏览器时间和示例附件均不能成为业务事实。原型派送异常入口 `P:18791–18807` 不在本批扩展线上闭环。
## Admin 逐操作矩阵
以下实现路径均相对 `apps/admin-web/src/`。原型尺寸作为业务承载依据,密度及公共样式沿 C/V;没有明确原型的新增行为列为总控冻结项,不自行选抽屉或增加页面。
| 页面/操作 | 原型承载方式、尺寸与依据 | 当前实现与差异 | 本批结论与所需后端事实 |
| --- | --- | --- | --- |
| 排车列表/装车前 | `P:4489–4501` 独立列表,操作首列;`P:4492–4493` 主阶段+车辆信息/调度审核/理货员审核三个子区,`switchOutboundVehicleTab/BeforeTab` 在 `P:18605–18606` | `overseas-warehouse/pages/DispatchesView.vue:54–79, 688–708` 有阶段和审核子区,但额外“全部/已取消”,默认全部;子区只改变展示列,未传审核子阶段;审核和资源依赖 `workflow.tripNo` | 五阶段作为主流程,装车前保留三个审核子区;“全部/取消”如何作为辅助筛选由总控冻结,不冒充第六阶段。需分页支持阶段、审核子阶段及总数;每行返回审核事实、车辆资源和独立动作资格,不在当前页做过滤后冒充总数。 |
| 列表/装车中 | `P:18655, 18706–18707, 18757–18760` 同列表阶段、查看及管理资料;装车前理货通过转入装车中 `P:18643` | 现有 `LOADING` 筛选,旧流程却是调度通过后先 PDA 拣货、平台实测装载、再理货审核,顺序与 C 不同 | 理货通过后才进入装车;PDA 扫码仍是真实事实来源。行显示核平进度与阻断;不得仅改状态标签放行。需服务端阶段、审核顺序、核平进度、可确认装车完成资格。 |
| 列表/装车后 | `P:4492, 18655–18656, 18750–18753` 同列表阶段,实际装车完成时间、管理资料 | 现有 `AFTER_LOADING` 依赖旧车次投影;`DispatchesView.vue:595, 609–679` 按 `canTransfer` 执行转派送,没有独立装车完成命令或后台发车动作 | 装车完成进入装车后;在此安排派送,完成后才能后台或 PDA 发车。需 `loadedAt` 类真实时间、安排派送进度及资格;不得将装车时间当发车时间。字段名待共同冻结。 |
| 列表/派送中 | `P:18739` 动态插入派送中页签,`P:18681–18683` 轨迹;`getOutboundVehicleLoadStage` 在 `P:18655` | `DispatchQuery.stage` 和列表枚举均没有派送中;现有 `DEPARTED` 只是排车执行状态,不足以代表五阶段 | 新增服务端阶段筛选,读取真实发车时间、各派送单状态及异常提示。轨迹与异常功能不因原型存在而扩大本批。需全部派送单关联及状态汇总,不以某一单签收结束整车。 |
| 列表/派送完成 | `P:18738, 18741–18747` 动态完成页签(原文“配送完成”) | 当前没有对应阶段;原型从另一业务记录取数据、显示值也有不一致 | 统一文案“派送完成”。只读服务端全部正常签收的汇总,部分签收/拒收/退回不自动完成;不增加人工“标记完成”按钮,不释放车辆/司机资源。 |
| 新建/先选货建单 | `P:4491` 新建排车按钮;关联预排生成 `P:18575–18582`;现有智能预排的独立原型尺寸不在本次指定两页中确定 | `SmartDispatchDialog.vue:322–419, 499` 当前为宽 `min(1800px,100vw-40px)` 居中智能排车弹框,从 `InboundOrdersView.vue:17,249` 进入;非空装车容器分组原子提交,换标走整单专用提交;排车列表只有“安排车次” | 保留先选同起运仓可排来源/托盘建单,列表需有入口。新建入口如何复用现有宽弹框由总控冻结;不以 1120px 编辑框推定大型预排工作区尺寸。需创建直接产生一张整车单,显式多容器时返回逐组整车结果;跨客户货物保留归属,无需用户再安排共享车次。 |
| 新建/先建空单 | `P:4491` 仅按钮,无空单表单和处理函数;`P:18960` 反而禁止空关联订单 | 当前 `SmartDispatchDialog.vue:336–339,674` 禁止无托盘,`TripPreparationDialog.vue:50–56` 也必须已有排车及主档资源 | C 明确允许,需新增空单创建模式;承载建议复用“维护车辆信息”的居中表单,精确字段和按钮由总控冻结,不伪造货物。需独立空单创建请求、起运仓和返回业务号/版本;空单可保存但不可审核进入作业/装车/派送/发车的确切门禁由后端返回。 |
| 编辑/维护车辆及预约信息 | `P:12414–12446` 居中宽表单,最大1120px、96vw;三列规则 `P:12380–12389`,页头、正文滚动、固定底部;`P:18858–18875 editVehicle`,`P:18942 saveVehicleEdit` | `DispatchesView.vue:446–465,505–529,718` 居中900px三列;仅自由文本车牌/司机/电话/车队和时间预约,无主档切换、附件、加货;请求无版本和幂等;`departAt` 可编辑 | 本轮沿1120px维护弹框核对,不恢复原型手改状态/发车时间。计划时间和实际时间必须明确区分。需最新整车版本、编辑资格、资源模式、预约字段、备注;货物/关键资源变化后旧审核失效事实由服务端返回。 |
| 车辆/司机主档选择 | 指定两页编辑原型只有手填 `P:12424–12426`;现有 `TripPreparationDialog.vue:38–44,77–80` 提供聚焦远程主档候选 | 现有选择器位于“安排车次”,不是排车维护;车型预排选项 `SmartDispatchDialog.vue:677` 只是360px车型选择,不是真实车辆档案 | C 明确支持主档。复用已公开候选能力、按需搜索,不在列表逐行查资源;容量/占用/证照由后端复核。需候选权限、主档ID及显示快照、允许选择状态、容量/证照阻断和提醒;保持长ID字符串。 |
| 车辆/司机临时外配 | `P:12424–12426` 直接填车牌/车队/司机/电话 | 排车自由文本存在,但主档车次安排仍强制 vehicleId/driverId,无法闭环 | 明确主档与临时外配模式;临时模式不创建主档、不传伪造关联,不能靠前端把文本填回一个任意ID。需资源来源枚举、临时快照、服务端完整性/占用校验及模式切换时清除旧关联规则。 |
| 加货 | `P:12438–12441` 维护弹框的关联订单页签;`P:12451–12457` 居中980px候选弹框,`openOutboundVehicleOrderSelect/confirmOutboundVehicleOrderSelection` 在 `P:18921,18935` | 现有编辑只能移除,API 没有加货命令;智能预排是新单,不可拿新建接口冒充已存在单加货 | 保留维护弹框内关联货物入口,候选居中980px;需同起运仓跨客户可排候选、来源锁/版本、追加及去重、返回整车新版、变更后审核重置。后端决定变更开放阶段与在途阻断,前端不自行放开。 |
| 移除货物 | `P:12441,18917–18919` 关联订单删除为草稿移除,无明确确认 | `DispatchesView.vue:530–559,718` 居中危险确认后按真实明细ID移除,刷新快照与路线 | 保留确认、服务端 `canRemovePallet` 和失败上下文,不能照搬浏览器数组删除。需版本、幂等和原子返回;换标全托/同托来源/批次分配不能在前端合并或丢失。 |
| 调度审核/通过 | `P:12436` 居中760px、95vw、88vh审核弹框;`P:18617–18627` 显示车辆、预约和附件;`P:18644` 通过后进入理货员审核 | `DispatchesView.vue:581–607` 跳车次;`TripDetailView.vue:135–149` 通过直接发请求,驳回另开简单prompt,未展示同一审核弹框 | 在本批排车流程内760px审核弹框承载,显示整车资源/货物摘要/附件、审核意见;通过意见可选,不加虚构审核清单。需调度独立资格、当前审核事实、版本和幂等请求、通过后最新单据。 |
| 调度审核/驳回、原因查看与重提 | `P:12436–12437` 审核与被驳回详情两个760px居中弹框;`P:18629–18645` 驳回必填,回维护 | 当前审核依赖车次,列表可显示workflow原因,但没有原型被驳回详情与原位重提 | 驳回理由保留;维护后显式按新版本重提,不把保存自动当审核通过;需审核阶段/轮次、原因、时间、已失效事实和重提动作资格。驳回后的精确流转由共同契约冻结。 |
| 理货员审核/通过 | 与调度复用 `P:12436,18622,18643`,标题为理货员审核,通过后装车中 | 旧车次 `reviewTripLoading` 在确认实载后执行;旧指引要求理货后才能发车,未把它作为开始装车前置 | 按 C 移到装车前,独立权限及动作资格;通过后允许PDA拣货并进入装车中,不能用旧 `canPick` 仅调度通过的规则。需两审核序列事实和剩余阻断。 |
| 理货员审核/驳回、重提 | 同 `P:18640–18645`;驳回原因必填并回维护 | 现有车次prompt仅版本/结论/原因,无幂等及新顺序 | 在审核弹框内驳回;按服务端重提状态刷新,不能本地保留旧调度结论继续装车。需版本/轮次/事实失效及已开始PDA作业后的服务端禁止条件。 |
| 装车完成/后台 | `P:18656 completeOutboundVehicleLoading` 有直接修改模型函数,未找到本页对应完整确认承载;它错误同时写发车时间 | 旧 `TripLoadingPanel.vue:62–82` 是实测容量确认,不是统一整车装车完成;Admin排车无该动作 | C第八节已明确确认装车弹框接入既有实载核对,有依据自动带出、缺项确认;必须PDA真实核平,不补录拣货数量,不新增第五页签。消费实际骨架LoadingComplete及其公开实载读取DTO后实施。 |
| 装车完成/PDA | 指定Admin原型没有PDA承载;C 为行为依据 | `dispatch.vue:70,182–185` 只有“完成排车拣货”并调用 `/complete`,仅提交幂等键 | 已按第九节及实际骨架明确:最后扫码仅形成pickingReconciled,双端使用loading-complete独立确认装车,旧complete协议直接替换。PDA核平后、后台先确认、PDA重入应显示服务端已装车事实,不重复扣货。 |
| 安排派送/费用 | `P:28480–28570 modal-bol` 居中1080px,三列派送字段、费用和货物表;`P:18808–18850` 打开和保存 | 现有1120px三列 `AppDialog`,`DispatchesView.vue:466–503` 打开后各一次读取运费和覆盖,`609–679` 提交整单一个 `fees[]`;返回deliveries按目的仓,缺客户维度 | 名称及行为为装车后“安排派送”;用共同后端预览按客户+目的仓逐组核对派送资料、原费用覆盖、新增费用。建议沿现有宽版模态框容纳分组,宽度1080/1120差异由总控冻结;不得前端平均分费、复制整车费用到每组或先发车后补派送。需分组版本/hash、客户显示、货物来源、币种、覆盖明细、新费用及全组安排完成事实。 |
| 实际发车/后台 | 指定两页没有明确后台发车确认表单,C明确新增两端能力 | 排车无按钮;旧 `TripDetailView.vue` 和AGENTS明确PDA发车,需随本批收敛 | 建议小型居中确认,展示车牌、司机、排车号和全组派送就绪,待总控冻结承载;必须独立于装车完成,消费服务端 `canDepart` 类能力。需统一版本、幂等、操作时间、真实发车后状态及两端重复结果。 |
| 实际发车/PDA | C;现有设备页作为直接消费依据 | `dispatch.vue:75–81,187–195` 显示“车次+共N张排车”,验证 `IN_TRANSIT + tripNo + dispatches包含当前单` 后再GET任务释放键 | 改为“一张排车单整车发车”;不能继续强迫用户理解多个客户排车。等待后端冻结业务号和响应模型,再校验同一整车及真实阶段,保留未知结果恢复,不伪造 `DEPARTED`。 |
| 附件上传/预览 | `P:12430` 司机照片、车辆图片、驾驶证;`P:18882–18891` 居中900px图片预览/非图片下载;`P:18763–18790` 管理资料居中960px,图片图库和PDF文件 | 本批排车维护无附件API;旧BOL `DispatchesView.vue:407–423` 已用鉴权Blob新标签PDF;PDA交接状态为只读独立组件 | 审核与维护需要真实三类附件及按需鉴权预览,图片900px模态、PDF沿新标签预览;具体File提供者触点由总控分配。装车照片、BOL司机签收等管理资料角色/必填不由原型5张写死规则自动引入。需文件ID、角色、名称、媒体类型、权限、上传后绑定/替换语义及鉴权下载;列表不逐行下载附件。 |
| BOL读取 | `P:18648–18653` 调度通过后下载演示HTML | 现有正式PDF读取路径,`getDispatchBolPdf` `dispatches.ts:203–207`,有弹窗拦截和失败反馈 | 保留真实PDF,不改回原型HTML。新整车BOL应覆盖多客户货物且正确隔离;调度审核后可读的准确资格需返回,不能以按钮永远显示推定允许。 |
| 独立四页签详情 | `P:9448–9456,21711–21732,21751–21754` 独立页面,业务号、状态、返回、三字段块+关联表;S1/C改为四页签,S2仅样式 | `DispatchDetailView.vue:79–135,153–165` 独立路由已存在;同页分区,无页签;单据信息用“关联订单”,更新时间/备注恒“—”;订单表集装箱恒“—”,按 `orderRefs` 将同托重量体积复制给多个订单 | 保持正式路由及返回上下文,四页签细则见下表;需服务端真实单据信息和订单级准确汇总。不得将同托整托重量重复归到每个订单,不以ID、样例或零替代未知。 |
| 取消/删除 | 指定两页未定义删除/停用;C只要求保留附加能力、聚焦主流程 | `DispatchesView.vue:561–579` 已有取消危险确认和托盘释放提示,没有删除单据 | 保留现有取消能力、独立权限与服务端资格,配合新版版本/幂等;不新增删除/停用。新状态下的取消与资源释放边界交后端和总控冻结,不以“测试可丢弃”授权删除。 |
## 四页签内容与数据缺口
页头保留排车单号、服务端阶段/状态、返回原入口及获准的主要操作;四页签顺序固定如下。采用 `el-tabs.density-element-tabs.density-contained-tabs`、`density-tab-icon`,页面不重定义公共字号/高度/底色/下划线。第一项车辆图标沿S2的 `🚚`,其余复用现有语义图标:`📋`、`📝`、`📦`(见 `DeliveryOrderDetailView.vue:75,92,118`);具体映射是本轮建议,交总控冻结,不新增图标系统。
| 页签(建议图标) | 固定字段/列顺序 | 现有来源与缺口 | 消费要求 |
| --- | --- | --- | --- |
| 车辆信息 `🚚` | 车牌号、司机、联系电话、拖车公司名称、车辆状态 | `DispatchSummaryDto.vehiclePlate/driverName/driverPhone/carrierName/status`;当前 `status` 是排车状态,是否作为车辆显示状态须明确 | 返回主档或临时外配的真实显示快照和明确车辆状态文案;紧凑白底4–6组短字段,长车队名跨列。不拿内部主档ID或“待分配”示例代替缺失值。 |
| 排车信息 `📋` | 路线、发车时间、预计到达时间、FBA预约、车辆预约 | 已有route/departAt/estimatedArrivalAt/fbaAppointmentStatus/vehicleAppointmentStatus;整车多目的仓只有一个预约号/状态不足 | 路线由货物目的地真实事实生成,不手输演示“30托盘”;发车只显示实际时间。多目的仓预约需真实逐目的仓/批次事实或服务端明确整车摘要,不能显示一个仓已约即全车已约;冻结精确展示。 |
| 单据信息 `📝` | 排车单号、关联派送单、创建时间、更新时间、备注 | `DispatchDetailView.vue:93–101` 使用orderNos且缺updatedAt/remark;现有 `TransferDeliveryItem` 不含客户归属,详情没有deliveries | 返回所有真实派送业务号、对应客户+目的仓及状态供关联;多单号完整换行/明确链接,读取目标仍受各自权限;创建/更新时间与备注从服务端返回。关联订单不能代替关联派送单。 |
| 关联订单明细 `📦` | 订单号、重量kg、托数、目的FBA仓、体积m³、集装箱号 | `DispatchItemDto` 无客户/containerNo,只有托级weight/volume及orderRefs;现有多订单循环重复累加整托载荷,containerNo恒空;bolLines有containerNo但不是订单级汇总映射 | 后端返回有客户归属的订单汇总行或足以准确归属的明细;同托多订单的重量/体积不可由浏览器猜分;未知显示“—”。只读通栏表,不为套规范新增操作列;订单业务号可完整展示,客户身份保留在模型,是否增显示列由总控决定,不自行改变S1六列。 |
仅以上四页签。现有 `TripDetailView.vue:201` 的分配与货物、外接预订、计划容量、实际装载、结案与任务结束、在途交接、直接成本、历史八项不移入新详情;其代码和对应后端能力先保留。不得把“派送完成”等同“资源任务结束”,不得因隐藏页签自动释放资源。既有路线地图若继续入口,放在排车信息的明确操作位置,不新增路线页签,需总控冻结最小接线。
## 后端消费者要求与实际骨架接入
首轮已读取两后端准备稿:[排车列表接口与数据设计](排车列表接口与数据设计.md)(主流程,首读快照SHA-256 `F4D8AE6D46DEC5A1AC36BDE6926DD495F7E3180FCE5691AE36BA3BDA386156D0`)与[排车列表派送费用接口设计](排车列表派送费用接口设计.md)(派送费用,首读快照SHA-256 `9BEE01228045D8C7A54BB3D1D4202ED52B6B550C36212EBA049BFB7DE4E536B5`)。两稿随后按正式契约收敛;实施以共同契约第八至十节及提供者实际Java公开DTO为准,首读哈希仅用于追溯差异,不作为最新接口冻结值。以下消费者要求保持为接入核对清单,已确定部分见下一节。
| 范围 | 主流程后端必须明确 | 派送与费用后端必须明确 |
| --- | --- | --- |
| 一单一车及身份 | 唯一用户可见排车业务号;旧tripNo与新排车是否仍有技术关联、唯一关系及各直接消费者更新方式;不保留用户必须多单绑定车次的流程 | 派送关联回同一整车业务号,各组保留客户及目的仓归属;同仓、同目的仓不同客户不能合并收费 |
| 详情/分页投影 | 五阶段、审核子阶段、业务状态分开;列表分页一次取动作摘要、审核、资源、货物统计;详情真实时间、备注、订单级载荷、集装箱、关联派送;动作资格缺失fail-closed | 每组计划/派送号、客户业务显示、目的仓、状态、费用覆盖摘要、正常签收与异常事实;不要求前端逐票查状态拼汇总 |
| 命令及版本 | 创建空单/选货建单、加减货、资源维护、提交/重提、两审核、完成装车、实际发车的精确方法/路径/请求/响应;所有必要写动作稳定幂等、版本0有效;PDA拣货是否需单/明细/库存位置版本 | 安排派送预览和原子确认;版本/hash包含全部分组、来源、货物及收费基线;返回全组结果与整车安排完成事实,不部分成功后由浏览器补写 |
| PDA真实核平 | 服务端返回计划/实拣/未拣、pickingReconciled及允许完成装车资格;旧complete替换为loading-complete;后台不能提交假的已拣数补齐,空单不可核平;两审核顺序服务端保证 | 装车后才可安排;未安排全组不可发车;同一拣货事实进入后续出库不得再拣一次、再扣一次或按派送拆分重复扣减 |
| 资源和附加能力 | 主档与临时外配请求及切换、容量/占用/证照规则、已保留附加能力对版本/资格的影响;不让旧实际装载/理货入口绕过新阶段顺序 | 外接约定运费仍是冻结事实;直接成本与客户应收分开,不因本批未展示而删除或自动收费 |
| 费用组归属 | 明细customer与source/destination/batch关系稳定,服务端跨客户权限;PDA只取Token仓,不收客户/仓范围入参 | 逐组原覆盖项、来源ID/版本/hash、金额币种、剩余新增费用、外接quote;`fullyCoveredServices`须按本组判断,不能用整车全覆盖隐去另一客户未覆盖费;不让前端平均分摊整车费 |
| 完成/异常 | 发车后的整车阶段及最终正常完成事实投影;资源释放继续独立;审核失效后可操作资格同步 | 全部正常签收才完成;部分、拒收、退回、取消、空组不得误算正常完成。返回明确数量/异常摘要,不以 `remaining=0` 或任意terminal判断完成 |
| 并发/未知结果 | 同命令同键同载荷重放、同键改载荷拒绝、版本冲突/业务失败/权限失败与未知网络结果的区分;返回业务号、最新版本、动作证据;可按原键核对或安全重放,不要求浏览器生成新键猜测 | 与完成装车/发车共用整车锁与一致性;费用基线变化冲突后重新预览,未知安排结果可原键恢复,不能生成第二批派送/费用 |
| 附件/权限 | 附件元数据/绑定与审核关系、专属下载;前端既有dispatch/trip写权限如何收敛,list包含详情只读,命令权限独立;File触点交总控分配 | 客户只可读自己的货物、派送和费用;整车跨客户平台投影不能直接复用给客户。共同权限、SQL和OpenAPI均由总控集成 |
现有Admin精确API基线:`api/dispatches.ts:188–286` 的平台排车列表/详情/更新/取消/移除、候选、预排和草稿;`293–345` 的转派送、约定运费和费用覆盖。现有PDA精确基线:`src/api/fulfillment.js:3,86–111` 的 `/pda/v1/last-leg/dispatches` 列表、详情、逐明细pick、complete、depart。这里只记录现状,目标是否复用或删除路径由共同接口冻结决定;不增加旧新别名或回退链。
### 两后端准备稿交叉核对与正式收敛
首轮记录的两稿差异已由共同契约第七至九节裁定,以下为现行执行基线,不再要求用户重复确认。Java公共骨架现位于 `lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/port/`;这里只读取实际DTO,不修改Java、不依据草稿猜API。
| 事项 | 正式结论及实际骨架 | 前端执行要求 |
| --- | --- | --- |
| 整车与四页签 | 一张dispatch自动一对一Fleet资源记录;`DispatchViews.Detail`为vehicleInfo/dispatchInfo/documents/orderDetails;每客户一出库、每客户目的仓一派送 | dispatchNo为唯一主操作业务号;完整outbounds/deliveries数组,不保留单个outboundNo别名。附加能力代码保留,不移入四页签。 |
| 状态、阶段与版本 | `DispatchTypes.Status=ACTIVE/CANCELLED`,Stage为五项;ReviewState和ReviewStatus独立;所有已有单写请求统一recordVersion,0合法 | status不再混用拣货/车次状态,取消不是第六阶段;列表按真实Query及Statistics筛选统计,不按当前页长度计算。 |
| 临时外配证据 | 第八节已确认:空单先保存,审核前补齐本趟容量、司机证照和预计任务结束,调度核实;实际Vehicle/Driver分别有mode,DriverEvidence含证照号、到期、fileIds、expectedTaskEndAt | 两资源分别可MASTER/EXTERNAL;不创建主档、不伪造ID,不要求用户再次确认规则。附件提供者和公开候选读取仍须真实DTO。 |
| 实载与零扫码变更 | 确认装车弹框接入真实实载;`LoadingComplete`要求manifestHash/measurements。`RETURN_TO_REVIEW`保留原号,仅零扫码可退回重审 | 核平与装车确认分开,缺项只确认真实重量/体积/卸货点,不补拣货数量;未读到实载公开读取DTO前不补造manifestHash。 |
| 命令与业务摘要 | 全局唯一idempotencyKey,原主体/动作/单号/原版本/载荷绑定commandHash;安排单另有arrangementBusinessHash。`CommandResult`含action/key/status/stage/effect/result/replayed/alreadyArranged | 原键不换主体或载荷;新有权限主体以新键当前版本引用原安排,不再收费建单;校验同单同动作同键结果后GET当前事实,不用旧结果覆盖新阶段。 |
| 库存与发车 | 库存SHIP已在真实扫码执行;安排/装车/发车均不再扣一次。发车只推进来源订单、客户出库及派送计数和事实 | 只消费排车公共版本和真实动作结果;PDA不再以trip版本和多客户子排车成员判断发车,不发起第二遍出库拣货。 |
| 锁序 | 根trip→涉及的车辆→司机/资源→dispatch;扫码来源→库存且不锁派送;安排/发车先全部客户出库派送后来源费用;签收delivery→来源→持久信号 | 超时保留原键与载荷,不以换键自动重试掩盖死锁;不把列表资格快照当写入复验结果。后端对尚未核实的提供者锁点继续核对,前端不声称全域无死锁。 |
| 正常完成 | 签收提交后可靠持久信号;派送保存和数据访问,主流程有界消费/退避/重扫;父锁下读取已提交事实,阶段CAS与信号确认同事务 | 页面只显示已提交真实stage;签收成功不直接本地改DELIVERED,刷新读取最终汇总;部分/退回/拒收不当正常完成,资源结束仍独立。 |
| 组合安排 | `DispatchDeliveryModels.ArrangementPreview`含groups/arrange/cargoHash/loadingCompletionHash/arrangement;ArrangeDelivery公开recordVersion,逐组费用与证据 | 打开弹框一次组合GET;不再两辅助GET拼快照。严格组级覆盖,不跨客户免单、不平均分费。缺失字段交提供者补,不能客户端猜hash。 |
| Client与预约边界 | 第八节已确认平台安排这类整车派送;本任务取得Client直接消费者移除权。日历新增预约已单列排除 | Client旧创建页/API/按钮移除,读及合法资料保留;共享routes/权限由总控已接管。已有WorkDispatchForm/WorkExistingDispatchForm/WorkSharedTripForm仅列影响,未取得精确移交前不写。 |
接入前仍缺的公开消费事实(不是要求用户重新裁定业务):①确认装车前的既有实载读取端点及DTO(manifestHash、真实测量行、卸货点);②候选sourceVersion和草稿转换请求/结果的实际对外DTO;③新Detail与既有预约三表单使用的appointmentBatches、仓库和workflow差异及唯一写者;④临时证据上传/读取的真实File契约。主流程只产出port骨架不等于上述Controller/DTO及消费者均已完成。请求接入按实际提供者完成快照推进。
## PDA接口差异与恢复要求
路径相对 `apps/pda-overseas-uniapp/`。
| 问题 | 源码证据/当前行为 | 目标及接口差异 |
| --- | --- | --- |
| tripNo/tripRecordVersion | `src/api/fulfillment.js:27–29,107–111` 将车次版本转字符串,接受0;depart请求用trip版本,不是排车版本 | 冻结唯一整车版本及业务身份;不把dispatch版本误当trip版本。若模型移除trip相关字段,直接同步API/页面/草稿/测试,不做双协议解析。若仍保留技术关联,不在UI要求另一车次操作。 |
| 多排车整车响应 | `dispatch.vue:75,189–194` 显示共N张排车,按trip与dispatches成员验证整车 `IN_TRANSIT`,随后GET排车期待DEPARTED | 新单本身即整车,改验新响应的同一业务号、真实阶段和动作事实;不得保留“多张客户排车”UI或把IN_TRANSIT直接灌进旧单status。 |
| 真实拣货与两审核 | `dispatch.vue:120–123` 拣货和complete均依赖canPick;提示“调度审核后拣货”;明细以scheduled/picked、库位、退货箱作业 | 服务端canPick须包含调度+理货通过及当前版本;本地数量只做交互校验,不替代核平。保留真实托盘业务码、退货箱唛、同托多来源选择;禁止目的仓码代替实物码。需可信进度、空单阻断、作业失效事实。 |
| 完成拣货/装车/发车 | `dispatch.vue:102,118,182–185` 多个完成状态别名,complete仅幂等;`187–195` 发车独立但缺装车后派送安排的明确事实显示 | 冻结唯一状态集与complete语义。装车完成、派送已安排、发车三事实分明;新增资格严格消费boolean true;后台完成后PDA刷新直接显示事实,不能再次complete。 |
| 拣货未知结果 | `submitPick:174–179` 键按单/明细/position或carton/数量生成,POST后GET成功才释放 | 保留稳定请求键与原载荷;POST超时或GET失败时禁止改数量再重放旧键。若业务GET已反映拣货但没有动作证据,不能仅用“数量已增”判定原请求是谁执行;需原键回放/查询确定结果,避免滞留旧键误吞下一次相同数量拣货。 |
| 完成/发车未知结果 | complete键只含dispatchNo;depart键含tripNo和版本;store只保存signature→key,不存完整请求,刷新取得新版本会生成另一signature | 必须保存操作类型、单号、原版本/hash、原载荷、幂等键及未知结果标记;未知时先查服务端/重试原请求。不得因为刷新版本变大而生成新键重发旧动作。已证实成功后清理原pending;明确业务失败后才允许按新快照重新决策。 |
| Admin与PDA竞争 | 当前只有本页busy阻止双击,不能协调跨端;PDA pick/complete请求缺统一recordVersion | 两端同一服务端规则。并发确认只一次推进,失败方刷新读取已完成事实,不将合法重复误报成新成功;货物/资源变更造成旧审核和旧核平资格失效时服务端拒绝旧请求。 |
| GET迟到与切任务 | `openTask:148–150` 一次读取后覆盖current;`run:198` 全局busy/loading防重复;没有独立目标请求序列 | 新恢复流程需要请求代次/单号校验,迟到旧详情不能覆盖当前任务、当前版本或pending键;成功提示属于确认过的原操作单,不依据已切换current。 |
| 草稿隔离与进入方式 | `stores/fulfillment.js:30–45` 按操作员+绑定仓隔离;`dispatch.vue:125–152` 默认任务列表,仅 `resume=1` 显式恢复;closeTask不清pending | 保留隔离、上次作业标记和显式恢复;草稿是交互状态,不是库存/核平事实。退出详情可保留未决操作,重入优先核对,不跨单重放;权限撤回、主体/仓变化继续由会话层清理。 |
| 出库和附加能力 | `dispatch.vue:41` 发车后挂载 `DispatchHandoverStatus.vue`;其只读get及版本watch;出库扫码可显式跳转排车 | 保留组件实现;新阶段的挂载条件和trip标识映射交总控冻结,不把交接新增为详情页签。`outbound`共用API/store域保持完整,整车安排派送后出库扫码必须定位同一新排车,不增加重复拣货。 |
## 直接消费者及受保护接线
| 触点 | 已核实引用/最小调整 | 写入边界 |
| --- | --- | --- |
| Admin排车主链 | `DispatchesView.vue`、`DispatchDetailView.vue`、`SmartDispatchDialog.vue`、`api/dispatches.ts`、`types.ts:103`、直接测试;`InboundOrdersView.vue:17,249` 当前智能排车入口 | 本轮只读;接口冻结解锁后再按精确文件实施。 |
| 旧车次强制步骤 | `DispatchesView.vue:41–47,77–79,585–603,689`;`TripPreparationDialog.vue:46–83`;`api/trips.ts:81–87,122–125`;`tripTypes.ts:35–56`;`TripDetailView.vue:135–149,201` | 本批主流程不再跳转强制安排/审核车次。旧附加能力代码保留;若技术模型改变这些API,先由总控裁定最小接线,不能删除八页签能力或只改标题假装完成。 |
| 预约按批排货 | `appointment-calendar/WorkDispatchForm.vue:5–6,88–102,117–123` 提交准确batchAllocations后再安排车次;成功跳旧trip详情 | 保留batch/source/destination/packageCount事实;新创建直接返回整车后跳排车详情,去掉第二次安排步骤的接线由总控协调。当前预约文件有他人在途修改,本任务不覆盖。 |
| 预约已有排车 | `WorkExistingDispatchForm.vue:19–26,34,41–42` 校验批次后用TripPreparationDialog,“尚未关联车次”与旧trip跳转 | 保留批次一致性校验及外部跳转关闭事项弹窗语义;改用新整车资格和详情目标,交总控/当前写者处理。 |
| 预约跨客户共车 | `WorkSharedTripForm.vue:23–36,42–48` 明确要求各客户分别备排车,再两单共车 | 与一单一车冲突,不能继续作为本批主入口。最小建议改为同一排车加同仓货物,保持已有批次分配、前置货物状态与返回上下文;交总控协调,不自行删表单。 |
| 到港/排车日历 | `tripCalendar.ts:36–38,56–80` 读取fleet/trips/calendar,按tripNo去重,`sourcePath`指向旧trip;`AppointmentCalendarView.vue:64–68` 使用trip:list权限;`AppointmentCalendarPanel.vue:77` 只按sourcePath打开 | 后端冻结投影中的排车业务号与整车唯一关系后,最小更新去重键、标题、深链和权限;保留起运仓当地计划/实际发车时间语义、取消与缺资料投影,不改变其他日历业务。只读交总控。 |
| 共享装配/密度 | `routes.ts:38–44` 已有排车列表及详情;导航、根路由、permissions、`src/styles/adminDensity.test.ts` | 根路由、导航、权限与公共密度由总控协调;adminDensity.test.ts已有他人未提交修改,不接管。详情只选择现有公共类,若需更新显式消费者清单由总控安排唯一写者。 |
| PDA直接链 | `pages/dispatch/dispatch.vue`、`api/fulfillment.js`、`stores/fulfillment.js`、`utils/dispatch-error.js`、`components/DispatchHandoverStatus.vue`、出库扫码恢复入口、直接测试 | 后续解锁前明确必要新增写权;共用fulfillment文件的outbound/cargoDiscard能力不得丢失,不扩大其他业务整页。 |
2026-10-19准备时 `git status --short`:Admin存在预约日历、工作事项、schedule相关文件、`self-operated/pages/OverviewView*` 及 `styles/adminDensity.test.ts` 的其他未提交修改;PDA未报告未提交修改。本轮没有覆盖、暂存、回退或格式化它们。
### 既有预约三表单的精确替换清单(只读交总控)
本表仅为整车改造造成的直接消费者接线,不涉及日历新增预约。以下路径相对 `apps/admin-web/src/modules/appointment-calendar/`,三个文件及其测试本任务均未写入。
| 文件/符号 | 现有字段/请求或分支 | 最小替换及须由提供者补全的真实事实 |
| --- | --- | --- |
| `WorkDispatchForm.vue` imports、result、pending、save | `DispatchSummaryDto`;旧drafts/pre-arrange返回`response[0].dispatch`;pending仅token/containerId/rows;创建后再TripPreparationDialog | 改成正式草稿转换命令结果,验证`dispatchNo/action/idempotencyKey`再GET新Detail;冻结原key/recordVersion/完整cargo和batchAllocations后重试。实际草稿结果DTO目前未公开,不能假定CommandResult数组外壳;仍保留容器对应和批次来源完整性校验。 |
| 同文件 `load/select/save` | 单客户自动全选条件、选择时不同customer拒绝、save用`new Set(customerId).size!==1`拒绝;按钮“创建本客户排车单” | 删除这三处单客户限制,改为同一起运仓和服务端来源资格;仍保留批次来源、allocations customer断言、托位限制及实物去重。BatchDispatchCandidate需返回真实warehouseId/sourceVersion,缺失不凭相同批次推仓;文案改为创建整车排车单。 |
| 同文件 result模板、tripSaved | `result.overseasWarehouseId/Name`、TripPreparationDialog、WorkSharedTripForm和旧trip详情路径 | 创建已自动关联Fleet,删后续“继续安排本批车辆/两单共车”步骤和对应import/ref;直接沿dispatchNo打开正式排车详情并保留emit external/update及事项弹窗关闭。剩余可排实物继续使用既有批次读取,不触及新增预约。 |
| `WorkExistingDispatchForm.vue` load.matches | `row.id`拼`DISPATCH:${row.id}`、`row.appointmentBatches`做batchKey/customerId核对 | 必须保留真实批次+客户关联验证。实际新Detail尚不含该关联;由主后端公开权威BatchReference及DISPATCH批次关系后改读,不以orderDetails客户清单、展示号或空数组替代;不继续从客户端内部ID拼权威批次键。 |
| 同文件 prepare/writable、selected、saved、模板 | `PENDING_DEPARTURE`、`!workflow`、`overseasWarehouseId`、顶层`packageCount`、TripPreparationDialog、旧trip:list/edit权限 | 新单`status=ACTIVE`、`stage`五项,操作资格读`actions.EDIT/ADD_CARGO/RETURN_TO_REVIEW`相应Gate;数量读counts.packageCount,资源不再另建车次。Detail需真实起运仓投影;使用正式排车详情入口办理资源/加货,移除prepare弹框与旧trip跳转,保留readonly/ready事件和批次不一致失败。 |
| `WorkSharedTripForm.vue` prepare/saved及整段双单交互 | 输入otherNo、同时get两排车、比较旧status/workflow/overseasWarehouseId、`dispatchNos=[A,B]`后prepareTrip | 一单一车不能把两张整车再合为一车;移除双单共车操作及TripPreparationDialog调用。在同一dispatchNo下打开“添加同仓货物”,消费真实AddCargo(recordVersion/key/cargo/batchAllocations),或最小链接到该单加货;不得迁移另一张已排单货物或自动解锁其占用。按钮是否保留为加货由总控协调原写者,不在本任务直接改。 |
| 三文件共同权限/恢复 | 旧smart-dispatch、trip:list/edit及useWorkDraft;部分unknown键不含完整最终请求 | 创建权限收敛由总控IAM/前端权限集成;加货/资源沿排车edit及服务端Gate,不给日历读取权限追加整车写能力。保留useWorkDraft、原请求未知结果、当前批次分配与已保存预约关系,禁止结果未明就重新建单。 |
| 直接测试 | `WorkDispatchForm.test.ts`、`WorkExistingDispatchForm.test.ts`、`WorkSharedTripForm.test.ts`,`WorkBatchContinuation.test.ts`及`WorkDetailPanel.test.ts`中的实际引用 | 更换Mock及断言为正式整车结果/批次事实;补同仓跨客户、未决请求、批次客户不符、零扫码退回重审;原事项关闭、原单跳转、剩余实物恢复和错误后禁止重复创建回归继续保留。只读列明,写者由总控核对。 |
## 后续回归设计(首轮设计,按实施切片记录执行)
| 场景 | 输入/竞争方式 | 必须观察到的结果 | 拟落点 |
| --- | --- | --- | --- |
| 五阶段及子审核分页 | 切换五阶段与装车前子区,旧请求后返回;含空页、失败重试、无权限 | 服务端筛选/总数一致,旧响应丢弃;加载/空态/错误可用;动作资格缺失关闭写入;不逐行查详情 | Admin `pages/DispatchesView.test.ts`、`api/dispatches.test.ts` |
| 两种建单 | 空单保存后再加货;先选同仓两客户两目的仓;另加跨仓候选 | 两种方式均直接取得整车业务号;不要求第二次安排车次。空单不得产生核平或发车事实;跨仓由服务端拒绝,表单上下文保留 | Admin新建/加货行为测试及API精确载荷;后端对应场景由后端执行 |
| 资源模式 | 主档切临时再切回,延迟候选响应,过期证照/资源占用 | 不混传主档ID和临时快照;不建主档;警告与阻断区分;旧候选不覆盖新模式 | Admin维护组件测试、API类型检查 |
| 审核通过/驳回/重提 | 两审核各通过、驳回空理由、重提;期间加货/更换资源 | 顺序正确;驳回必填;旧审核失效;理货通过前PDA不可拣;权限只读可看但不能写 | Admin审核弹框行为、PDA canPick门禁、后端命令测试 |
| 真实拣货核平 | 未扫物、部分拣、重复扫码、错码、同托同仓不同来源、多行同palletNo、退货箱 | 只能按真实明细/实物码提交;不静默取第一行、不按目的仓码匹配;后台不能补数量绕核平;空单不算全部拣完 | PDA `tests/fulfillment-workflows.test.mjs` 中现有计算/方法注入harness扩充;后端核平事实验证 |
| 装车完成与发车分离 | 全部PDA核平→后台完成装车→PDA刷新;尚未安排派送时两端尝试发车 | 完成装车只进入装车后、loadedAt有值、实际departAt仍空;派送未就绪canDepart=false;PDA不重复complete | Admin动作测试、PDA页面方法行为测试 |
| 两端并发完成/发车 | Admin与PDA同版本同时确认,各种响应先后及一端409 | 服务端只推进一次;两端最终同阶段及真实时间;失败方刷新而非换新键盲试;不二次扣库存或生成派送/费用 | 双端Promise可控Mock行为;服务端并发验证不能由Mock通过代替 |
| 版本0与大版本 | 首版0、缺失、负值、非数字、精度边界;旧trip版本与单版本不同 | 0有效,错误/缺失版本关闭操作;长ID不转Number;严格只用冻结版本域,不解析旧别名回退 | PDA API请求单测、Admin类型/序列化测试 |
| POST未知与GET失败 | pick/complete/depart/安排派送:POST已执行但超时;POST成功后GET失败;关闭/重进/刷新 | 保留同一键、原载荷、原版本;按原请求安全核对后清pending;新快照不生成新键重放旧动作;相同数量下一次拣货不得被旧键吞掉 | PDA store与真实页面方法注入;Admin分组派送/动作组件延迟Mock |
| 同键载荷变化 | 未知期间修改数量/费用/资源,再点提交 | 冻结未决载荷,提示先核对原结果;不能同键改内容,也不能用新键制造重复命令 | 双端未知结果测试;服务端幂等合同 |
| 多客户费用 | 同仓客户A/B都送ONT8,另送LAX9;仅A有原派送费覆盖,含外接报价变化 | 按客户+目的仓独立组;B仍需未覆盖费;原费用不新增重复行;hash变化重取;未知重试仍同批单据 | Admin费用分组测试、后端派送/费用测试 |
| 正常完成及异常 | 三组仅两组正常签收;最后一组分别拒收/退回/取消/正常签收 | 前三种不自动派送完成;只有全部正常签收汇总完成,资源仍按原独立生命周期;不伪造退库/账务 | Admin阶段投影测试;后端正常完成事实测试 |
| 四页签与长数据 | 四页签、长排车/派送号、多单号、多订单同托、未知重量、缺集装箱 | 只有四项且顺序固定;真实字段不混用;重量体积不重复分摊;无内部ID回退、无假零;表格只读无新增操作列 | `pages/DispatchDetailView.test.ts`;人工1920×1080截图 |
| 附件 | 图片/PDF、403、网络失败、替换失败、关闭后迟到响应 | 鉴权按需读,业务错误不当图片;失败保留已绑定文件;关闭/卸载释放Blob、旧响应不打开已关闭预览;审核可读不等于可上传 | 新附件组件/API行为测试;人工预览 |
| 入口/返回与附加能力 | 入仓预排、预约批次、已有单、跨客户货物、日历深链、出库扫码resume、发车后交接 | 进入同一整车且来源/批次不丢;返回原上下文;默认PDA列表和显式resume保持;旧附加实现保留且不绕过新门禁 | 现有直接消费者测试,预约写者集成;PDA navigation/workbench/trip-handover测试 |
解锁实施后的最低检查按实际改动执行:Admin定向 `pnpm test`(上述页面/组件/API及 `prototypeContract.test.ts`、实际直接车次消费者),`pnpm typecheck`,最终全量 `pnpm test` 和 `pnpm build`;公共密度合同由总控安排;PDA运行 `node --test tests/fulfillment-workflows.test.mjs tests/business-identifiers-ui.test.mjs` 及实际受影响的navigation/project-contract/workbench/trip-handover测试,最终 `npm test`、`npm run build:h5`、`npm run build:app`。具体不重复跑未变输入;离线通过不等于真实HTTP、页面或PDA硬件通过。
## 首批实施结果(14:36前历史检查点)
已按共同契约第八至十节解锁,不再停在仅准备阶段。2026-10-19当前可独立集成的切片:
| 实际文件 | 变化与结果 |
| --- | --- |
| Admin `pages/DispatchDetailView.vue` | 保持独立路由与返回语义,将连续四块改为仅四个Element彩色图标页签:车辆信息、排车信息、单据信息、关联订单明细;使用density-element-tabs、density-contained-tabs、density-tab-icon,删除旧分区布局样式,不写公共CSS、不改附加能力。当前数据读取仍待原子接入新DTO,不声称字段缺口已解决。 |
| Admin `pages/DispatchDetailView.test.ts` | 增加真实Element页签顺序、激活状态、可见内容和不重复请求的行为回归。6项通过。 |
| Admin `layoutAcceptance.test.ts` | 将已被本批四页签取代的document-section CSS断言改为公共页签及精确四页签合同;其他页面断言保留。 |
| Client `views/DeliveryOrderCreateView.vue` | 删除旧客户直接创建这类派送的生产页面,不保留跳转别名或假成功页。 |
| Client `views/DeliveryOrdersView.vue` | 移除创建按钮、入口事件和独立创建权限消费,保留全部本客户列表/详情/筛选。 |
| Client `api/deliveryOrders.ts` | 移除createDeliveryOrder、DeliveryTransferPayload/Result,保留本客户分页、详情、费用读取、签收资料及鉴权二进制下载。 |
| Client `deliveryOrders.test.mjs` | 改为平台专属安排边界,确认无客户POST、无创建页/按钮/路由/权限映射,保留客户读取隔离、签收数量、文件和负向权限回归。 |
| 总控集成,非本任务写入 | 总控已移除Client `order-management/routes.ts`中的orders/delivery/create整段,以及 `tenant-management/contracts.ts`中该创建权限的分组/映射。`clientNavigation.test.mjs`旧权限仅负向用例保留。 |
已执行证据:Client全量 `pnpm test` 601/601通过,`pnpm typecheck`通过,`pnpm build`通过;Admin `pnpm typecheck`和`pnpm build`通过。最终定向命令 `pnpm test src/modules/overseas-warehouse/pages/DispatchDetailView.test.ts src/modules/overseas-warehouse/layoutAcceptance.test.ts src/modules/overseas-warehouse/pages/DispatchesView.test.ts src/modules/overseas-warehouse/pages/prototypeContract.test.ts src/modules/loading-lists/components/LoadingListsView.creation.test.ts --maxWorkers=2` 为5文件66/66通过(9.62s)。首次Admin全量406文件、3386测试中3384通过、2失败:本批旧布局CSS断言(已更新且定向通过)及未改装柜创建用例5秒超时(隔离通过);`pnpm test --maxWorkers=4`最终406文件中397通过/9失败、3386测试中3375通过/11失败(557.59s);11项全部报5秒超时,分布为audit/CustomerAuditLogsPanel、customers/CustomersView、finance/FinanceG3G4Views三项、container-loading/GlobalSmartLoadingView、ocean-bookings/OceanBookingDetailView.release、overseas-warehouse/DispatchesView、RelabelOrdersView、warehouses/WarehousesView、warehouse-resources/pallets/PalletsView。没有放宽超时或修改这些生产页,不能声称全量通过。共享工作区其他写者仍有在途变更,上述结果绑定当时读取输入,不代表整车新接口或未来集成候选通过。真实视觉仍“待人工截图确认”,未做真实业务或PDA硬件验收。
上述为14:36前首批历史输入。后续原生DTO、五阶段和PDA接入已按第0/0.1节实际骨架推进,当前切片、验证和未关闭缺口统一见本文末“原生接口接入交付检查点”;首批Admin typecheck/build成功不代表当前集成候选通过。
本任务保持当前分支和工作区,不触及appointment-calendar、adminDensity.test.ts、自营等他人在途修改;只在自身对话报告,由总控主动读取。后续按公共提供者实际DTO和总控精确移交推进,不自行扩大日历新增预约、客户内部平台操作或附加功能整页。
## 本轮原生类型接入的受保护编译断点(总控接线)
2026-10-19总控14:36正式绑定13个公共port文件后,已删除旧DispatchSummaryDto、PreArrangeDispatchDraftPayload及preArrangeDraftDispatch导出,没有保留旧状态或字段别名。当前真实typecheck在下列保护中的文件报错;这些文件及测试仍未写入,本表供总控按精确写者处理。
| 文件/符号 | 真实断点与最小接线 |
| --- | --- |
| WorkDispatchForm.vue:imports/result/save | DispatchSummaryDto与preArrangeDraftDispatch已移除。改用CommandResult、DispatchDetail、DispatchDraft/ConvertDraft及convertDispatchDraft;后续读新详情。createDispatchDraftContainer改为一个对象{recordVersion,idempotencyKey,draftToken,capacity}返回完整Draft,容器标识为draftContainerId;lockDispatchDraftPallet改为DraftSelection(当前草稿版本、原键、容器、真实CargoSelection.sourceVersion);releaseDispatchDraft也携草稿版本/键。 |
| WorkDispatchForm.vue:load/select/save | 三处单客户限制应移除,保留逐来源batchAllocations的客户断言;同仓由服务端Candidate.warehouseId/sourceVersion及原子转换复验;不能按客户拆若干旧客户排车再共车。 |
| WorkExistingDispatchForm.vue:load.matches | getDispatch现返回DispatchDetail。appointmentBatches实际在dispatchInfo.appointmentBatches;客户逐batch的校验留在此数组,不提升到旧顶层字段。`DISPATCH:${row.id}`已无row.id,需原域权威批次引用校验,不重加内部ID或拼编号回退。 |
| WorkExistingDispatchForm.vue:prepare/template | 删除旧PENDING_DEPARTURE、workflow、overseasWarehouseId/Name和packageCount消费;新status ACTIVE/CANCELLED,stage五项、actions的EDIT/ADD_CARGO等Gate,数量在counts。直接打开同一dispatchNo的独立详情继续维护资源,不再调用TripPreparationDialog;起运仓如需展示,从真实ListRow按dispatchNo精确匹配获取,不从订单目的仓推导。 |
| WorkSharedTripForm.vue:prepare/template | getDispatch现返回四块详情,不存在workflow与旧仓字段。整段“两张客户排车安排同一车次”与新模型冲突,改为同一排车加同仓真实货物(AddCargo)或指向该单加货;不保留双单prepare/bind写协议。 |
| 三个同名.test.ts | Mock从旧客户Summary切换真实Detail/Page/Draft/CommandResult;缺版本拒绝、0合法、完整batch/source/货物归属、原事项关闭/原单跳转及未知请求恢复继续回归。WorkBatchContinuation/WorkDetailPanel实际受影响用例由总控一并协调。 |
上表是保护中文件的接线清单,实际原生切片已完成到下节检查点;整体typecheck尚未通过,不把局部测试通过当成集成完成。日历新增预约不在该接线范围。
## 原生接口接入历史检查点(2026-10-19 15:25,后续状态见文末)
本节替代前述首批检查点中的待实施状态。按总控14:36派工完成本任务独占的Admin/PDA原生接入切片;整体集成仍未通过。再次逐个核对实际13个公共Java port文件SHA-256,全部与主流程设计第0节一致(13匹配、0变化)。本任务17个生产文件候选聚合SHA-256为`15931a9917bb562068eebfa7583288b41d653cbeb1819abe5dc17e74eb22239d`:按完整仓库相对路径字典序,将每项“路径+LF+文件原始字节+LF”顺序输入SHA-256;清单为Admin本表13个排车生产文件、Master Data index.ts和PDA三个生产文件,测试与本文不计入。自查和验证绑定此候选。
不改Java,不保留旧DispatchSummaryDto、PENDING_DEPARTURE、旧trip版本发车、旧complete路径或旧参数别名。
| 本轮实际文件 | 已实现行为 |
| --- | --- |
| Admin `dispatchContracts.ts`、`api/dispatches.ts` | 对应实际四块Detail、Page/Statistics、CandidateList、Draft/ConvertDraft、LoadingPreview、ArrangementPreview及动作判别CommandResult。已有单写入严格recordVersion,缺失/null/负数/非整数字符串/不安全number拒绝,显式0合法;长标识不转Number。预约更新仅支持referenceNo和预约自身recordVersion。移货实际为POST remove,装车完成为loading-complete;草稿转换完整组提交,不调用旧standalone pre-arrange。保留原预约域getBatchDispatchCandidates提供者,不伪造第三套协议。 |
| Admin `dispatchPresentation.ts`、`pages/DispatchesView.vue` | 原生五阶段、独立ACTIVE/CANCELLED/ALL、装车前三个分区(车辆信息、调度审核、理货审核);分页/统计由服务端返回,丢弃迟到旧查询。写按钮同时核对严格boolean Gate和独立权限。审核、重审、加货、实载、安排与发车直接弹框;BOL鉴权Blob与按需路线读取保留,不逐行请求详情。列表提供跨筛选范围的原请求恢复入口。 |
| Admin `pages/DispatchDetailView.vue` | 独立详情仅四个彩色图标Element页签,公共密度样式;真实vehicleInfo/dispatchInfo/documents/orderDetails,显示全部客户派送单及实际更新时间/备注。订单表保留服务端来源归属、客户、入仓码、真实集装箱与未知测量,不前端分摊或用内部ID回退。 |
| Admin `components/SmartDispatchDialog.vue`、`smartDispatchWarehouseTab.ts` | 明确真实起运仓、空单建单、候选完整性/来源版本校验、显式恢复服务器草稿、逐组加货/移货/释放/原子转换。保留仓库展示Tab、来源单号/入仓码/托盘码/目的地地址邮编、集装箱及参考重量体积。每个容器分别维护车辆/司机/时间/备注,允许同仓跨客户;预约分配仍核对逐来源客户。草稿未知请求冻结原完整body/key/version,转换成功凭据先保存,全部新单详情核对后才清除;后续GET失败不再次转换。 |
| Admin `components/DispatchResourceFields.vue`、`overseas-master-data/index.ts` | 通过实际公共候选API分别按权限查询车辆/司机,分别支持MASTER/EXTERNAL及混用,模式切换只清本资源。外配容量、证照号/到期/预计结束直接维护,不创建主档;保留已绑定证据。已关联主档选择器显示车牌/姓名或明确待核实,不泄露长ID。附件提供者仍未接入,见下表。Master Data只增加实际候选/类型公共导出,未删改原成本、容量、预订、交接、释放实现。 |
| Admin `components/DispatchWorkflowDialog.vue` | 1120px维护/加货/实载/安排,760px两审核;驳回、退回、取消明确原因。实载只自动使用actual=true证据或相同manifest的confirmedLoad,参考分摊不填实测;逐托正数重量体积、整数托位及已匹配卸货序号验证。装车完成与实际发车独立。弹框目标变化立即重读,不能拿旧单版本/资料提交另一单。 |
| Admin `components/DispatchArrangeFields.vue` | 一次组合GET,不再两个辅助GET拼快照;按客户+目的地显示全部货物、派送字段、真实报价和原费证据。每服务显式覆盖选择并携版本/hash,外接报价匹配同客户+入仓来源;部分覆盖仍保留未覆盖费用,不能跨客户免单。只显示适用服务的新增费用;不填伪零,不平均分摊整车费。一次POST发送全部组。 |
| Admin `dispatchCommandRecovery.ts` | 同一登录主体共享一个完整未决命令,sessionStorage留原动作/业务号/body/key/version。未知结果先按原键查询,真实404才同键原请求重放;校验同单/动作/键及原装车/发车结果。先持久原结果,再GET当前详情并确认版本不早于命令版本后清pending;原结果不覆盖最新阶段。首次明确4xx业务拒绝可重新核对,5xx和网络结果未知、或前次未知后的迟到拒绝均不能丢键重建。CREATE与已有单动作恢复分开,不会将原DEPART发到建单API。 |
| Admin直接测试及类型/索引 | 重写原API、列表、详情、Smart与仓库Tab测试;新增Workflow/Resource/Arrange、命令恢复、原生fixture测试。prototypeContract、layoutAcceptance、types合同只更新本批被替代的排车断言,其他页面断言保留。`index.ts`导出实际新公共类型,`types.ts`删除旧DispatchListItem。 |
| PDA `src/api/fulfillment.js` | 只消费原生PdaTask/actions/items/positions/returnCartons,0版本合法,缺版本拒绝;pick/loading-complete/depart各自带原生版本,新增loading和commands GET。删除旧completeDispatchPicking和tripDepartureRequest,不提交客户/仓作用域;普通outbound与cargo-discard API保持。 |
| PDA `src/stores/fulfillment.js` | 排车保存完整pendingCommand,按登录人+冻结仓隔离恢复;不再用“同内容同键”吞掉下一次相同数量的实拣。结果确认才清命令,普通outbound保留原pendingKeys语义。 |
| PDA `src/pages/dispatch/dispatch.vue` | 原生五阶段与Gate;真实实物码/退货箱唛拣货,错码清旧选择,同托多客户明细不能静默取首行。仓位选择跳过已拣分配,本次量同时受该位置可用量、分配余量和本明细余量限制。空单不核平;全部真实拣货+服务端pickingReconciled才可打开实载。实测确认独立于发车;未知重试与成功后GET失败保留原命令,支持另一端已推进阶段时读回最新事实。默认任务列表、显式resume、只读在途交接组件继续保留。 |
| PDA直接测试 | 同步fulfillment-workflows既有有意义断言,保留普通出库/收货/退货测试;新增dispatch-workflow真实页面方法harness,覆盖版本0、物理来源、分配上限、两级资格、未知POST、GET失败、跨端新阶段、5xx未知、旧详情版本和下一次等量扫码新键。 |
验证输入为当前工作区未提交候选,无隔离分支/副本,未提交、推送或部署:
- Admin定向12文件96/96通过(15:23,14.23s):api/dispatches、dispatchCommandRecovery、DispatchDetailView、DispatchesView、SmartDispatchDialog、DispatchWorkflowDialog、DispatchArrangeFields、DispatchResourceFields、prototypeContract、smartDispatchWarehouseTab、layoutAcceptance、types。随后本地版本校验错误改为明确DispatchInputError,受影响API/恢复/Workflow再跑3文件38/38通过(15:25)。
- Admin最新完整`pnpm typecheck`仍失败,错误仅在保护中的WorkDispatchForm、WorkExistingDispatchForm、WorkSharedTripForm及其同名测试;本任务原生实现/直接测试无剩余类型错误。精确符号见前表。`pnpm build`前置即vue-tsc,当前不再重复打包或宣称构建通过;总控完成受保护接线后再验。未通过的全量11项5秒超时保留在历史记录,本轮依指令未重跑全量追绿、未放宽超时。
- PDA最终`npm test`280/280通过;最后代码输入的`npm run build:h5`和`npm run build:app`均成功,H5初轮样式@import顺序警告已修正并重编译确认消失。App仅资源编译,不代表APK签名或设备验收。
- Client代码本轮未变;此前601/601、typecheck/build通过记录仍绑定此前切片,不重新触发全量。
- Admin/PDA独占变更`git diff --check`通过(仅Git LF/CRLF提示);构建产物不纳入源码。自查覆盖实际13个公共Java records、请求序列化、直接消费者和失败/恢复分支,未冒充独立代理审查。
| 15:25时尚未关闭事项(非当前结论) | 当时事实与接线边界 |
| --- | --- |
| 三个预约表单与同名测试 | 当前仍引用被删除的DispatchSummaryDto、preArrangeDraftDispatch、旧draft id/签名、PENDING_DEPARTURE/workflow/顶层仓及appointmentBatches。保持只读,由总控/精确写者同步到同一原生接口;不得恢复旧类型别名遮盖断点。当前Admin尚不能作为可发布集成候选。 |
| 附件取证/预览 | Vehicle.evidenceFileIds和Driver.evidence.fileIds已真实保留,但公共骨架无本趟证据上传/绑定/鉴权下载元数据提供者;页面明确未接入。不编造File路径、不允许手填内部文件ID,不以空证据声称审核闭环。 |
| 实载卸货序号 | LoadingPreview已有deliveryIndex,双端只使用真实返回值;没有目的地/路线选择及更新提供者。缺值时明确阻断loading-complete,不猜顺序、不用行下标替代。 |
| 装车前移除货物UI | 已接实际POST items/{itemId}/remove及版本/原因API测试;平台Detail只有orderDetails/sourceKey,无可移除dispatchItemId。LoadingPreview是逐托实载,ArrangementPreview.cargo明确为不可变实际拣货来源,不能假设它覆盖装车前未拣明细,也不能借PDA任务接口取平台数据。故未伪造移货按钮或用sourceKey/仓托盘ID冒充itemId,需主流程提供装车前权威明细读取后补UI。 |
| 权限/入口/最新指引 | 本任务直接动作消费create、loading-complete、depart以及既有审核/edit等权限,统一IAM/SQL/导航由总控集成;入仓旧smart-dispatch权限消费者也需同步,不加OR旧权限降级。PDA AGENTS的旧canPick/tripDepartureRequest说明、Admin局部指引相关旧模型说明应由总控在最终索引维护批次更新;本任务未争写AGENTS。 |
| 真实验收 | 未调用真实HTTP、未写测试业务数据、未运行环境SQL/部署。双端Mock证明前端不重复发送和正确恢复,不证明服务端并发事务/库存/费用唯一性;后端及全链验收另核。Admin/Client仍待人工1920×1080、100%截图确认;PDA扫码枪/音效/离线重连/安装仍待真机。 |
仅在本对话交付供总控主动读取;没有跨对话回复、创建新聊天或内部代理。新增日历预约仍在本任务范围外。
## 六表单有限接线检查点(2026-10-19 15:50)
总控按主契约第九节精确移交WorkDispatchForm、WorkExistingDispatchForm、WorkSharedTripForm及三个同名测试;修改前逐文件git status无差异,并记录原SHA-256。六文件没有发现其他写入,当前继续为本任务唯一写者;其他日历文件仍未修改。
- WorkDispatchForm改为从真实ReceivingContext.batch.originWarehouseId限定同仓,将原批次实物与原生Candidate.sourceVersion精确关联,一个服务器草稿容器直接转换一张跨客户整车;逐来源batchAllocations保留客户/批次/目的地/数量,错客户/错来源/重复实物/未知数量/跨仓/不完整候选阻断。服务器草稿token和版本真实取得,不再客户端造token或按客户拆单。
- 草稿各步完整body/key/version和转换CommandResult按登录人及批次范围持久;未知响应只重放原步骤,原成功结果先保存再读详情,GET失败不再转换;事项关闭后的只读面板仍可核对原未决请求。首次明确拒绝才可显式读取本拥有者草稿新版本并释放,不以迟到冲突清除原未知命令。
- WorkExistingDispatchForm消费dispatchInfo.appointmentBatches逐客户验证。DISPATCH批次通过实际resolveBatchWork核对批次与业务号,不从内部ID拼字段回退;原单只读/继续维护均导航独立详情。
- WorkSharedTripForm保留文件名与父组件事件边界,内容改为同一排车ADD_CARGO,严格消费Gate/阶段/版本并复用实际WorkflowDialog及全局原命令恢复。删除另一客户子单输入和TripPreparationDialog共车写流程,不搬已扫码货物。
- public overseas-warehouse/index.ts只补实际原生API/类型/Workflow和命令恢复公共导出,未恢复旧别名。原批次分批、已有单恢复、原事项更新/跳转、剩余实物显式读取和unknown导航保护继续回归。
已运行:三个表单、WorkBatchContinuation、WorkDetailPanel及本任务原12个排车直接测试共17文件142/142通过(20.67s);完整pnpm typecheck通过;pnpm build包含再次vue-tsc和Vite构建均成功(Vite5.33s,仅已有大chunk提示)。此前三个表单造成的Admin类型阻塞已解除,不能把15:25的阻塞记录继续当作当前结论。该点后按总控新移交读取DispatchWorkModels与实际items/route/evidence端点,继续补三个此前缺提供者的UI,不把端点存在当作真实HTTP验收。
## 历史候选检查点(2026-10-19 16:03,已由下方 Long 修正候选替代)
六表单检查点后,已按总控追加移交完成原Admin独占范围的移货、既有路线排序及本趟附件UI。读取实际新增`dispatch/port/DispatchWorkModels.java`(SHA-256 `1e91da656e38aebbc554b4b4275b080d387e6bdb2eefaa14d5ae1ebd5b1aec64`,比较时忽略大小写)、DispatchAggregateController、DispatchAggregateService、DispatchEvidenceGateway/HttpDispatchEvidenceGateway,以及FleetTripService真实站序校验;未修改这些Java提供者。
| 本次生产变化 | 已完成的实际行为 |
| --- | --- |
| `dispatchContracts.ts`、`api/dispatches.ts` | 精确接入DispatchWorkModels.Items/CargoItem、Route/Stop/RouteCommand和File元数据;GET items、GET/PUT route、POST multipart evidence/{VEHICLE或DRIVER}、GET文件元数据及/content。上传FormData只有file,不伪造业务类型、客户/仓范围或文件归属;所有版本化请求继续拒绝缺版本并接受0。 |
| 移货UI | 列表和四页签详情直接动作打开真实items清单,展示客户/订单/入仓码/托盘/应装/真实已拣及逐项remove Gate;只允许选服务端允许且pickedPackages=0的真实dispatchItemId。原因必填,POST path使用该真实明细ID;原itemId作为本地恢复目标与原body/key/version一起保留,不放进ReasonCommand JSON,不用sourceKey或仓托盘ID冒充。换标整源/已扫码等阻断原样保留。 |
| 路线UI | 原列表/详情增加“调整卸货顺序”居中弹框,仍只有四个详情页签;起运仓只读,只对实际Route.stops中的既有目的地上/下移。保存检查完整唯一目的地集合、版本、原因和Route.edit Gate;不能新增、删除、猜目的地,包含外接点。请求只交原destinationKeys顺序,后端保留真实名称地址。完成提示明确重新核对两级审核。 |
| 路线未知结果 | 后端实际账本动作是EDIT,前端只增加本地operation=ROUTE标记来保留原端点选择;该标记不进入公开请求。重放仍原动作/键/body/version,不能把路线原请求发送到资源Update;原CommandResult核对及GET当前详情规则继续复用。 |
| `components/DispatchEvidenceFiles.vue` | 新增本车、两种实际证据类型的上传/替换/移除引用/鉴权预览组件。限PDF/JPG/PNG、10MiB;成功且元数据校验后才更换待保存引用,失败保留旧引用。上传本身不伪装成主单保存,随后通过原生版本化EDIT保存Vehicle.evidenceFileIds或Driver.evidence.fileIds,不自动删除File对象。 |
| 附件接入点 | 车辆维护弹框可上传并保存本趟证据;两级审核弹框及车辆详情页签只读预览。空单建单时尚无整车身份,提示先保存再维护附件,不编造创建前文件归属。Resource主档切换、模式、容量和证照输入保持。 |
| 图片/PDF与失败保护 | 当前弹框按需读取元数据,只有用户预览才GET本车/content Blob;图片900px居中,PDF用户点击时先开新窗再放入鉴权Blob URL。JSON业务错误不能当图像;身份/内容类型/大小不符拒绝预览;权限/网络错误保留code/requestId/traceId。切单、关闭、卸载后迟到响应不绑定/打开;撤销图片和卸载时回收URL,PDF URL定时回收。无匿名存储地址或内部ID显示回退。 |
本轮最终离线证据:
- Admin相关18文件155/155通过(15:59,22.12s):六表单对应三个测试、WorkBatchContinuation、WorkDetailPanel、原生排车API/恢复/列表/详情/Smart/Workflow/Resource/Arrange/Evidence、原型/密度/仓库Tab/类型合同。新增有意义回归包含真实itemId恢复、已扫码禁止移货、外接目的地不得丢失、路线原端点重放、只读附件、替换失败、切单迟到上传、JSON错误、关闭后迟到内容、PDF与弹窗阻断等。
- 路线成功提示与资格禁用最后收口后,受影响Workflow与WorkSharedTripForm再跑2文件13/13通过(16:01,3.96s)。
- 完整`pnpm typecheck`通过;当前最后`pnpm build`再次包含完整vue-tsc并成功打包(Vite4.09s)。只有大chunk常规提示,没有放宽类型或测试超时。`git diff --check`通过,仅Git行尾转换提示。
- PDA本轮源码未变,沿用此前280/280和H5/App资源构建通过证据;Client仍为此前未变601/601及typecheck/build证据。未新增全量Admin追绿运行,历史11个超时不因此宣称消失。
自查/验证绑定21个本任务生产文件,聚合SHA-256为`4d27e7fef94948d7169703c008a35e3e9ce86af8b2a0bc09effaff76842c32bd`;算法仍为完整仓库相对路径字典序,每项路径+LF+原始字节+LF。清单为前一17文件、DispatchEvidenceFiles.vue及三个预约生产表单;测试、指引和本文不计入。此前17文件聚合只表示15:25历史输入,不能代替此候选。
当前结论:本任务已解除此前三个预约表单的类型阻塞,并完成三个新增提供者的UI消费,可以交总控集成;仍未提交/推送/部署、未启动后端、未写测试数据/SQL、未执行真实HTTP。尚需主后端对运行端点、批次关联、路由、版本/幂等/并发及完整持久化链统一验收,文件/货物/路线真实提供者运行状态由其实际检查证明。LoadingPreview若仍缺deliveryIndex或真实测量,双端继续阻断,不因路线UI存在而猜值补齐。Admin/Client视觉仍待人工1920×1080、100%截图,PDA硬件/安装仍待真机。统一权限/OpenAPI/索引由总控维护;WorkDetailPanel、WorkCreateAppointmentForm、AppointmentCreatePanel、planningApi、日历面板和adminDensity.test.ts均未修改。
## 历史候选:Long 响应边界修正(2026-10-19 16:39,已由下方批次版本候选替代)
已按总控授权解除本任务原有生产文件与直接测试的冻结,仅处理已确认的 Long 响应问题。common-web 的 Long/long 序列化实际输出十进制字符串,公共 JSON 解析器保留引号内的字符串;此前 WorkDispatchForm 的可用箱数严格比较、Workflow 的已拣数量零判断,以及附件元数据/Blob 大小比较因此错误阻断。本候选在排车 API 响应边界统一修正,保留既有组件业务判断,不向各页面散落 Number 转换。
- 新增 `dispatchWire.ts`,明确区分 HTTP Wire DTO 与应用内模型。统一校验并归一化全部实际 Long 数量:列表分页、Counts、统计/审核计数、候选、草稿 sources、明细应装/已拣、装载预览应装/已拣、文件大小、安排派送货物箱数/件数与出库/派送引用计数,以及 PICK/DEPART/ARRANGE_DELIVERY 命令结果、转换草稿内嵌结果。各实际 GET/POST/PUT/DELETE 消费边界均接入对应转换;Blob 内容仍走原鉴权下载。
- 仅接受非负安全整数,字符串必须是规范十进制整数;缺失、null、布尔值、空白、带符号、前导零、小数、指数写法、NaN/Infinity 和超出 MAX_SAFE_INTEGER 的值明确失败。ID、sourceVersion、recordVersion、reviewRound 均保持无损;Java int/Integer 的容量、站序、批次分配箱数,以及可空托数、BigDecimal 测量/金额不按 Long 数量转换。未修改共享 JSON 解析器、DataTable 或规划 API。
- PDA 仅加强原 normalizeDispatchTask 的已有转换:明细、库存位置和退货箱件数使用相同非负安全整数边界;既有数字和规范数字字符串均可读取,缺失及越界值阻断。ID 和 recordVersion 原样保留,出库等其他业务适配未动。
- 三个组件回归经真实 parseApiJsonResponse 和实际排车 API 执行:候选 availablePackages=字符串12 对接批次 Integer12 后可整车创建;pickedPackages=字符串0 可以移除权威未拣 itemId;sizeBytes=字符串3 可通过附件元数据与 Blob 校验、预览并替换,长文件ID不变。API 测试样例已按真实 items/loading/evidence/draft/converted 响应结构收敛,原版本、端点、幂等与分组断言保留。
- 同批较大回归发现附件预览 AppDialog 根缺少公共密度类,已仅在本任务 DispatchEvidenceFiles.vue 补 admin-density-dialog;未修改密度合同测试或其他共享样式。修复后密度与附件2文件38/38通过。
最终离线验证绑定本候选:Admin受影响19文件209/209通过(16:38,24.24s),其中新增 Wire 边界与三条真实字符串组件链;完整 pnpm typecheck 通过,最终 pnpm build 再次包含完整 vue-tsc 并成功打包(Vite4.22s,仅已有大chunk提示)。PDA npm test 282/282通过,build:h5 与 build:app 顺序完成;git diff --check 通过,仅Git行尾转换提示。没有调整超时、使用 any 或执行真实HTTP;此前 Admin全量11项超时没有在本轮重跑或宣称消失。Client本轮未变,先前601/601及构建证据仍仅代表先前输入。
当前聚合 SHA-256:`63feb551c2325450ddd0bd7840c81191620372aa2cf64ea2dfb97027282c429f`,共22个本任务生产文件。算法为完整仓库相对路径按字典序排序,每项依次写入“路径 + LF + 原始文件字节 + LF”后计算 SHA-256;测试和本文不计入。精确清单:
`apps/admin-web/src/modules/overseas-warehouse/` 下:dispatchContracts.ts、dispatchWire.ts、dispatchPresentation.ts、dispatchCommandRecovery.ts、api/dispatches.ts、pages/DispatchesView.vue、pages/DispatchDetailView.vue、components/SmartDispatchDialog.vue、components/DispatchWorkflowDialog.vue、components/DispatchArrangeFields.vue、components/DispatchResourceFields.vue、components/DispatchEvidenceFiles.vue、smartDispatchWarehouseTab.ts、types.ts、index.ts;另含 apps/admin-web/src/modules/overseas-master-data/index.ts,apps/admin-web/src/modules/appointment-calendar/ 下 WorkDispatchForm.vue、WorkExistingDispatchForm.vue、WorkSharedTripForm.vue,以及 apps/pda-overseas-uniapp/ 下 src/api/fulfillment.js、src/stores/fulfillment.js、src/pages/dispatch/dispatch.vue。
最新源码只读核对表明,SmartDispatchController 已采用 destinationWarehouseCode 与原生 drafts/pre-arrange 契约,DispatchPdaController 已采用原生任务/装载完成/发车/命令结果入口,平台 DispatchAggregateController 也已有 /{dispatchNo}/depart 并调用 DispatchDepartureService;旧检查点关于这些源码仍未迁移的描述不能作为当前结论。本文只证明本任务消费与离线验证,没有修改 Java、共享权限/OpenAPI或环境配置。
可交总控集成;尚未提交、推送、部署、启动后端、写入测试数据/SQL或执行真实 HTTP。后端真实路由、权限、完整持久化和幂等并发链仍由总控统一验收;Admin/Client 人工1920×1080、100%截图与 PDA 真机扫码/安装仍待确认。本任务自查不冒充独立复核。
## 当前可集成候选:既有批次版本与权限接线(2026-10-19 17:38)
按总控本轮精确授权,仅解除原排车模型/API/wire、SmartDialog、Workflow ADD_CARGO和既有Work排车表单对此版本字段的冻结;不触及日历新增预约、planningApi、面板生产逻辑、公共密度、PDA、Java或Maven。修改前已核对公共Java实际签名:DispatchContracts.BatchAllocation(..., Long recordVersion)、BatchReference(..., Long recordVersion)都要求显式非负版本且零合法;BatchReference的自动DISPATCH引用使用其真实主单版本。该文件读取摘要为73b5b83fcd0155bf09b18c18b1bd6a5bbb0175221102a13101248f92ca84f641。预约Provider的Allocation随后也实际增加recordVersion;AppointmentWorkDispatchCandidates第43行已用appointment.version().longValue()返回权威版本,前端不从Result.version、显示约号或默认零补造字段。
本次生产变化:
- dispatchContracts.ts的两个批次模型均增加必填Version字段;requireBatchVersions只校验并比较同批次版本,不改变原始值。0、字符串0及超过JS安全整数范围的长整数字符串均无损;缺失/null/非法/不安全number版本阻断,并提示重新读取候选。同一批次出现不同版本也阻断。
- dispatchWire.ts在真实候选、草稿sources和原车详情批次引用的响应边界检查版本;沿用公共JSON解析器,大整型裸JSON经公共解析器安全转成字符串后保留,不把合法长版本当数量做Number转换。批次箱数仍是Java int,原Long数量校验保持。
- api/dispatches.ts在直接创建、加货、全部组草稿转换前统一校验嵌套分配版本,跨组比较同批次版本;既有batch dispatch-candidates的分配必须带真实版本才交给组件。原请求对象与版本均原样发送。
- SmartDispatchDialog和DispatchWorkflowDialog将每个真实BatchReference.recordVersion原样写入对应BatchAllocation;创建/加货仍使用原来源/客户/目的地/数量,整车顶层recordVersion独立。原键恢复保留完整原body和嵌套批次版本,候选之后变化不能改写未知原请求。
- WorkDispatchForm使用原批次候选返回的allocation.recordVersion,核对同批次及原生引用版本一致后提交;不以Result.version代填。WorkExistingDispatchForm与WorkSharedTripForm生产无需改动:原详情经wire校验,既有加货经Workflow消费。index.ts仅公开本应用内部实际跨模块使用的版本校验入口。
- 原入仓单入口前批已单独获准收口:InboundOrdersView.vue要求dispatch:list与dispatch:create,并在打开方法再次守卫;permissions.ts删除旧inboundOrderSmartDispatch键、增加dispatchCreate。直接3文件30/30已通过,该输入本轮未再改动。
- 总控追加交付的CapacityInquiryTable.vue和CapacityInquiryDialog.vue修改前均无未提交差异,未见重叠写者;各只把bind动作旧smart门禁换成dispatch:create,capacity-offer:manage、booking-edit、trip:edit及业务/样式保持。负面测试继续证明旧smart权限无效,缺少其余任意一项也不能出现排入本车动作。
直接测试修改为dispatchWire、dispatches API、SmartDialog、Workflow、WorkDispatchForm和WorkExistingDispatchForm的合同样例及回归;TripAppointmentPanel.test.ts是类型检查发现的直接模型消费者,仅补一处样例recordVersion,不改面板生产文件。CapacityOffersBehavior.test.ts新增两入口共享的四权正负矩阵。WorkSharedTripForm和CapacityInquiryDialog直接测试按实际影响重跑但未改断言。
最终离线证据:批次包8文件145/145通过(17:34,30.52s),外接入口2文件38/38通过(17:36,4.39s),共10文件183项;包含零/长版本、缺失/非法版本、同批多版本拒绝、原键重试不换版本、已有关联读与加货、四权正例及旧权限负例。完整pnpm typecheck通过;最终pnpm build再次包含完整vue-tsc,Vite4.46s成功。git diff --check通过,仅Git行尾提示;没有重跑无变化的PDA全量和构建,也未重做全量Admin209或声称真实HTTP通过。
候选指纹:原22文件清单的当前聚合为709936a8236fee3a20e3facf6b07d5a8590ac7f0784e4a3deefa1e475fb33fb4;合并前批2个入仓入口权限文件及本批2个外接入口后的完整26生产文件聚合为2047b6dd54146fb394e63ae433e569e6079110864116f7f56a6deeff48cf9351。算法仍为完整仓库相对路径按字典序排序,依次写入path+LF+原始字节+LF后SHA-256;测试和本文不计入。完整26路径:
```text
apps/admin-web/src/modules/appointment-calendar/WorkDispatchForm.vue
apps/admin-web/src/modules/appointment-calendar/WorkExistingDispatchForm.vue
apps/admin-web/src/modules/appointment-calendar/WorkSharedTripForm.vue
apps/admin-web/src/modules/overseas-master-data/components/CapacityInquiryDialog.vue
apps/admin-web/src/modules/overseas-master-data/components/CapacityInquiryTable.vue
apps/admin-web/src/modules/overseas-master-data/index.ts
apps/admin-web/src/modules/overseas-warehouse/api/dispatches.ts
apps/admin-web/src/modules/overseas-warehouse/components/DispatchArrangeFields.vue
apps/admin-web/src/modules/overseas-warehouse/components/DispatchEvidenceFiles.vue
apps/admin-web/src/modules/overseas-warehouse/components/DispatchResourceFields.vue
apps/admin-web/src/modules/overseas-warehouse/components/DispatchWorkflowDialog.vue
apps/admin-web/src/modules/overseas-warehouse/components/SmartDispatchDialog.vue
apps/admin-web/src/modules/overseas-warehouse/dispatchCommandRecovery.ts
apps/admin-web/src/modules/overseas-warehouse/dispatchContracts.ts
apps/admin-web/src/modules/overseas-warehouse/dispatchPresentation.ts
apps/admin-web/src/modules/overseas-warehouse/dispatchWire.ts
apps/admin-web/src/modules/overseas-warehouse/index.ts
apps/admin-web/src/modules/overseas-warehouse/pages/DispatchDetailView.vue
apps/admin-web/src/modules/overseas-warehouse/pages/DispatchesView.vue
apps/admin-web/src/modules/overseas-warehouse/pages/InboundOrdersView.vue
apps/admin-web/src/modules/overseas-warehouse/permissions.ts
apps/admin-web/src/modules/overseas-warehouse/smartDispatchWarehouseTab.ts
apps/admin-web/src/modules/overseas-warehouse/types.ts
apps/pda-overseas-uniapp/src/api/fulfillment.js
apps/pda-overseas-uniapp/src/pages/dispatch/dispatch.vue
apps/pda-overseas-uniapp/src/stores/fulfillment.js
```
共享提供者仍在途,不能把上述前端离线证据当预约—排车端到端接通:17:38读取的DispatchAggregateService与DispatchDraftService候选构造仍分别在第158/265行传入空appointmentBatches;尤其Smart草稿逐托选择/恢复后需由真实Provider保留引用和版本,前端不能拿旧显示约号或旧候选补造。总控/主后端继续处理实际候选/草稿提供、数据库锁内批次版本、完整持久化和发车复验。尚未提交、推送、部署、执行真实HTTP或写环境数据。新增日历预约及车辆预约权威提供者不在本前端包。
@@ -0,0 +1,526 @@
# 排车列表接口与数据设计
> 2026-10-19 已按[正式契约](排车列表统一作业改造契约.md)第八至十节进入首批实现,替代仅准备门禁。四项业务选择已确认;公共Java契约骨架见第0节。运行端点、持久化主流程和集成尚未完成,骨架不表示已部署。仅在独占范围实现及离线验证,不提交、部署、执行环境SQL或真实HTTP;共同SQL/OpenAPI/权限由总控集成。其余尚未实现的设计文字不能覆盖正式契约。
唯一写者:排车后端 `01a1524f-4f11-70c2-8a46-8e06e73a2d86`。总控 `01a15230-a9d6-7503-a8a9-d70691df49e5`;TEST 项目、host、cwd 按协作登记 2026-10-19 节。派送设计由 `01a1524f-56a9-7320-a5fd-8ff76fa4356b` 独占[另一设计文件](排车列表派送费用接口设计.md),双方不并写。本文创建前该文件及本文均不存在,未发现本文其他写者;源代码工作区已有其他未提交改动,未覆盖。
## 0 公共Java契约骨架交接
以下文件已经实际新增,均位于 `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/port/`,仅依赖JDK17,无业务Entity或对方实现类。所有下游以实际record组件/端口方法为准,不以旧准备稿伪造同义DTO。Execution与Completion已进入实际实现,草稿由总控分配的唯一写者实现;当前代码/验证交接以10.3为准,公共骨架不表示整链上线。
| 文件 | SHA-256 |
| --- | --- |
| DispatchTypes.java | ecd710d123747fa28f1c39c6fbafcd58f7bbe8656717135b81c80ff0736177d2 |
| DispatchContracts.java | 1c96bc5d4e471714a5f5829a5dd264aedd78d08deaa376ad5e8a11d59e2cac5e |
| DispatchCommands.java | f487b7bf7c21aac194b3525aa706da4fa6ab8ba0852de7eed3c68282d5a8497c |
| DispatchResults.java | 2355f33a878c8aba599122b4d94fb97f88db1b27622f541f3082dadc27dc1e94 |
| DispatchViews.java | f5f8a273e693496f27075fb8d2e839ee33f6b35317e107048025dbcb96664b85 |
| DispatchDeliveryModels.java | a8452477225b71400996992896f0a8a3ed385118cf988d5c4ed7b014c4e85896 |
| DispatchExecutionPort.java | 06ab14af3879ba90a7f4e5d6b2c56a8142bbdc3068911c8eaa9336807c8c8457 |
| DispatchPlanningModels.java | 33e3512544ec49aa6d9dd332cfc2e271303519058f8aac978125d91fa3c72f8d |
| DispatchPlanningPort.java | 2ecc408b6d5adb31fab23fa677916608e4434013716bade9a88dbd2655f64b88 |
| DispatchDeliveryPort.java | 1963618f71d831482a1a8527da68467773721db980c84b5c970832b1c3dafbd6 |
| DispatchCompletionPort.java | 4a222f0d3b3a34267f7469aa0242cf62486f70496c15481838ac889b5e64a76d |
| DispatchSignalPort.java | 85b26c63d98f87abbc9ddbbcd5b18961ac32c4bb60e5cb74832997a4ff233c07 |
| DispatchApi.java | 584a973627365c4987e4fad05bb26ca8dbea538c779472f0df83b9ee81302c25 |
实际端口精确签名(类型均为同包对应容器内record):
- `DispatchExecutionPort`:`Context preview(Actor,String)`;`LoadingPreview loading(Actor,String)`;`Context lockForArrangement(Actor,String)`;`Optional<CommandResult> replay(Context,Actor,CommandIdentity)`;`void requireFreshArrangement(Context,long recordVersion)`;`CommandResult recordArrangement(Context,Actor,CommandIdentity,ArrangementFact,boolean alreadyArranged)`。lock方法只取得顺序锁及身份上下文,原命令恢复先于新命令资格;新命令必须调用fresh方法,不能以拿到Context视为已允许。
- `DispatchDeliveryPort`(派送实现):`ArrangementPreview preview(Context)`;`CommandResult arrange(Actor,String,ArrangeDelivery)`;`DepartureFacts departureFacts(Context,boolean lock)`;`DepartureResult markDeparted(Context,Actor,Instant,String commandKey)`;`NormalDeliveryFacts normalDeliveryFacts(Context)`。markDeparted仅改客户单据事实,不执行库存SHIP。
- `DispatchCompletionPort`(主流程实现):`CompletionResult reconcile(Signal)`,新事务内主阶段CAS与signal确认同提交。
- `DispatchSignalPort`(派送实现):`List<Signal> due(Instant,int)`;`void acknowledge(Signal,Instant)`(MANDATORY,同汇总事务);`void failed(Signal,Instant nextRetryAt,String errorCode)`(父事务回滚后REQUIRES_NEW);`void enqueue(String dispatchNo,String deliveryNo,long deliveryVersion,Instant occurredAt)`(原签收事务内)。due不持信号锁进入父事务;主流程唯一负责调度/退避/重扫。
字段/端点对应:所有端点常量在DispatchApi。平台POST根→DispatchCommands.Create;PUT单号→Update;POST items→AddCargo;remove/cancel→ReasonCommand;submit-review→SubmitReview;dispatch-review/loading-review→ReviewCommand;return-to-review→ReturnToReview;双端loading-complete→LoadingComplete(新增真实measurements和manifestHash,不含补录packages);双端depart→Depart;PDA items/pick→Pick;平台transfer-delivery→DispatchDeliveryModels.ArrangeDelivery。所有命令响应统一DispatchContracts.CommandResult,严格区分replayed与alreadyArranged;arrangement数组在result中,不保留单outboundNo。GET列表/详情分别为DispatchViews.Page/Detail,PDA为PdaTask,组合预览为ArrangementPreview。公开参数均recordVersion,0合法;Actor和CommandIdentity均服务端内部类型,不绑定HTTP请求体。
实际列表统计record字段采用lowerCamelCase:ReviewCounts为notSubmitted/pending/approved/rejected,Stage键仍是五项枚举。实际详情VehicleInfo为vehicle/driver两个显式mode快照,DispatchInfo/Documents/OrderDetails保持四对象;以这些实际字段取代准备稿中的展示性伪代码。数值ID沿项目Long序列化约定输出,内部ID不作业务号回退。
已运行JDK17 `javac --release 17` 编译上述全部生产骨架及 `src/test/java/com/baiyue/lastleg/dispatch/port/DispatchPortCompileContract.java`,随后离线合同输出 `PASS`,不启动Spring/HTTP/数据库。此结果只证明共享类型编译、五阶段/版本域/整车客户边界/完整单据数组及端口方法可静态引用,不证明持久化、鉴权或事务行为。Maven暂未运行,待派送写者稳定后由本任务统一执行。总控已提供路由合同5/5和Lastleg依赖合同既存9通过3失败(pickup→transfer未审阅边)的基线;本任务不修改pickup或豁免,后续分别报告新增结果。
### 0.1 骨架修订:缺版本、既有预约、实载与草稿
公开已有单/草稿写请求的recordVersion均改为Long并在record紧凑构造器拒绝null/负数,显式0合法;创建主单/草稿没有既有版本。不是仅依赖Controller @Valid或Jackson对primitive的默认0。Update.vehicleAppointment已收敛为`DispatchCommands.AppointmentReference(referenceNo,Long recordVersion)`,没有status/appointmentAt写字段,保存时必须读取权威已有预约并复验版本;读模型仍可显示实际确认状态/时间,本批不新建预约流程。没有关联提供者解锁时该写接线待总控分配,不能拼一个本地确认状态替代。
新增实际种子及端口见 `DispatchPlanningModels.java/DispatchPlanningPort.java`,源数据生产者已沿原方法核对,前端按下表接入;当前尚无新Controller映射或可调用运行端点,不以端点常量冒充实现。
| 方法/路径 | 实际请求/响应类型 | 权威来源及边界 |
| --- | --- | --- |
| GET D/candidates | CandidateQuery→CandidateList(含Candidate.sourceVersion、selection、真实客户/起运仓/来源/目的地/参考测量/批次) | 原DispatchCandidateMapper/ReturnDispatchCandidateMapper及专用换标来源;sourceVersion将由服务端以稳定sourceKey、客户/仓/目的地、当前业务资格、真实来源库存组成版本及箱数、测量依据组成规范化SHA256,选择/转换锁内重算;不存在可靠摘要时不得填0 |
| GET D/drafts;POST D/drafts | List<Draft>;CreateDraft→Draft | 当前操作者拥有的持久草稿;服务端生成token,主单和草稿版本分开、均不信任布局赋权 |
| POST D/drafts/containers;POST D/drafts/snapshot | CreateContainer/DraftSnapshot→Draft | 带draft recordVersion及原请求键,保存类型化containers/sources;不继续使用raw containersJson作另一写协议 |
| POST D/draft-locks/lock、unlock、release | DraftSelection或DraftRelease→Draft | 选择携sourceVersion,先复验仓、真实来源、实托排他,再保存;不释放其他拥有者占用 |
| DELETE D/drafts/{draftToken}/containers/{containerId} | ReasonCommand(含草稿版本及键)→Draft | 原容器/拥有者/版本下释放,禁止无版本覆盖新选择 |
| POST D/drafts/pre-arrange | ConvertDraft→ConvertedDraft | groups每项DraftVehicle(draftContainerId,Create dispatch),每组一个真实整车;全部组一个事务,失败全回滚。vehicles每项为容器ID及完整CommandResult;不按客户拆单、不保留原客户PreArrange DTO |
| GET D/{dispatchNo}/loading;GET P/{dispatchNo}/loading | LoadingPreview | 双端分别检查平台list权限或PDA角色/绑定仓;返回当前排车recordVersion、manifestHash、逐实托scheduled/picked、真实实测值/证据、缺项、confirmedLoad及loadingComplete资格。只读、不新增页签 |
| GET详情 | Detail.dispatchInfo.appointmentBatches | 读取现有AppointmentWorkDispatchPort.references的真实batchKey/batchNo/customer/sources,不新增日历预约权威模型 |
实载数据必须区分证据:`FleetTripExecutionService.loading/confirmLoad`已有load_json(manifest匹配时)是CONFIRMED_LOAD;`RelabelPalletMeasurementService.snapshots`有库存组成stockVersion的真实测量是RELABEL_MEASUREMENT,组成过期必须缺项。普通候选grossWeightKg来自订单/入仓快照按托分摊、volumeCbm来自allocated_volume_cbm,是ORDER_SNAPSHOT_ALLOCATION参考,MeasurementEvidence.actual=false,只显示suggested值,不自动填真实weightKg/volumeCbm;未知托位/卸货段也明确missingFields。LoadingComplete仅接受用户核对的measurements,不接受PDA箱数补录。候选摘要计算及这些真实服务适配尚待主流程实现,不声称GET已可调用。
`dispatch/service/DispatchCommandCodec.java`已提供按Action封闭解码:Saved/Picked/Loaded/Departed/ArrangementResult具体类型由动作决定,拒绝缺结果字段或错误动作数据;复用正式时间/Long配置,树解析使用BigDecimal保留原精度,避免实测或费用经过double。其SHA256为`0e61307658495fb05e6dfed3b7029e89d1f92ab100bae777be8f4f7ef35871f4`。`DispatchPublicJsonContract`已实际通过15类请求missing/null/negative拒绝及显式0、预约伪造字段拒绝、全部Action持久JSON跨Codec/ObjectMapper实例恢复和原键重放;`DispatchPublicContractTest`供后续Maven统一执行同一组真实合同。此处是跨实例JSON恢复证据,未声称数据库事务/实际进程重启全链验收。
本轮依赖合同重新运行仍为9通过3失败,仅输出总控已登记的3条pickup→transfer.entity及fleet出向变化,无本批新增类型边违规;不扩大到pickup修复或豁免。编译最初受到Windows命令行长度限制,已改用target内javac/java参数文件;随后发现并修复中间JsonNode导致实测BigDecimal精度/scale变化,最终合同通过。测试产物仅在target,不纳入源码。
### 0.2 严格摘要及命令账本首片实现
独占新增 `dispatch/service/DispatchCommandHasher.java`、`DispatchCommandLedger.java`、`dispatch/entity/DispatchCommandRecord.java`、`dispatch/repository/DispatchCommandRepository.java`、`dispatch/mapper/DispatchCommandMapper.java`。摘要绑定actor/action/原版本/排车/规范载荷;业务摘要排除actor/版本/键,无序货物/费用/组排序而路线stops保持顺序。账本全局查询原键后先拒绝异主体,再判断动作/版本/摘要,结果恢复用真实Codec;保存只insert,不更新旧结果,唯一键冲突抛失败让外层回滚。方法MANDATORY,Repository/Mapper分层,不接入旧按customer分片幂等。
总控SQL精确需求:`ll_dispatch_command`字段为`id BIGINT PK`、`dispatch_id BIGINT`、`dispatch_no VARCHAR(64)`、`action VARCHAR(40)`、`operator_id VARCHAR(128)`、`idempotency_key VARCHAR(255) NOT NULL UNIQUE`、`record_version BIGINT NOT NULL`(原请求版本)、`command_hash CHAR(64)`、`result_json LONGTEXT`、`created_at DATETIME(3)`(UTC);各成功记录业务字段实际均应NOT NULL,创建前不落半成品行。dispatch_id/dispatch_no在创建成功结果产生后一起落账本。索引建议dispatch_id+created_at辅助审计,不以客户/操作者拆全局唯一键;中文备注由总控与基线/统一SQL一起集成。本任务未写共享SQL,也未执行环境SQL。
新增真实 `dispatch/service/DispatchCommandLedgerPersistenceTest.java`:H2内存表+实际MyBatis Mapper/Repository保存、提交,关闭Session并换Codec/ObjectMapper实例后读取原结果;异主体/换版本/换单拒绝,以及严格摘要和安排业务摘要区别、无序组与有序路线差异均已独立编译运行PASS。测试仅覆盖此首片持久/业务身份,不表示Spring事务代理、并发主单CAS、所有客户费用回滚或完整HTTP通过;完整Maven仍待另一后端稳定后统一运行。公共13个port文件保持本次哈希,后续主单/审核/装车/发车及Controller集成尚未完成。
## 1 已核对的现状及必须收敛点
以下 Java 路径相对 `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/`。
| 实际入口 | 当前事实 | 本批影响 |
| --- | --- | --- |
| `dispatch/service/DispatchService.java` 的 `preArrangeContainer/preArrangeDraft/requireSingleCustomerScope` | 主表 `DispatchOrder.customerId` 单客户;草稿每组也强制单客户;一组一张客户单 | 真实改为整车主单和跨客户明细,删除单客户头部推导,不能生成若干客户排车再仅在 UI 合并 |
| `fleet/trip/FleetTripPreparationService.java`、`FleetTripService.bindDispatch` | 先建客户排车,再建/选共享车次,循环绑定多张排车;调度审核落在绑定记录 | 新建排车一次完成内部车次关联,审核归整车;不让用户先去车次页 |
| `dispatch/dto/DispatchRequests.Stage` | 装车前对应 `PENDING_DEPARTURE`;装车中包含 `READY_TO_DEPART`;装车后实际映射到已发车 | 替换为五阶段真实状态,不能继续用旧映射表示装车后 |
| `FleetTripExecutionService.reviewLoading/confirmLoad` | 理货通过要求实际装载 hash;实际装载又读取拣货就绪 manifest | 理货审核改到装车前,不能保留“先拣货才允许审核”的循环;实载事实核对独立在装车完成门禁 |
| `dispatch/pda/service/DispatchPdaWorkflowService.pick` | 普通仓位依次 allocate/pick/ship;扫码成功是当前库存扣减点;逐入仓归属落在 `ll_dispatch_pda_pick_order` | 保留扣减时点和真实来源,装车完成、实际发车均不得再扣一次库存 |
| 同类 `pick/completePicking` | 最后一条扫码自动将 task 设为 `COMPLETED`、排车设为 `READY_TO_DEPART`;`complete` 无版本且仅 PDA | 拣货核平事实与用户确认装车完成分开;最后扫码只开放确认资格,后台/PDA调用同一确认服务 |
| `delivery/service/DeliveryTransferService.transferResolved` | 从主单 customer 生成一张客户出库单及按目的地拆分派送单,可在待发车/拣货中提前转派送 | 仅装车后安排,全车一次命令按客户再按目的地拆分;由派送后端实现 |
| `dispatch/fleet/DispatchFleetAdapter.completion` | 签收或真实退回核平都可满足旧车次结案 | 保留旧附加结案能力;排车五阶段的“派送完成”单独只认全部正常签收,不能复用“退回也完成”的布尔值 |
| `inboundplan/work/AppointmentWorkDispatchBinding/Mapper` | 分配事实带真实客户;但 bind 内按 dispatch 全量删除重建,部分 SQL 以 `d.customer_id` Join | 不可逐客户循环旧 bind,否则后一个客户覆盖前一个;须一次保存整车完整分配且以明细客户关联 |
上一批修复保留:取消历史与活动关联分开;已拣货/发车不得取消;普通和退货换标按整申请全部应排托盘;同托多来源按拣货归属核算外接承诺和费用;退货箱不伪造普通库存仓位。工作区 `exceptionorder/service/ExceptionOrderDispatchReturnSourceTest.java` 有其他未提交修改,本任务只读。
## 2 推荐模型:排车是真主单,Fleet 保留资源与附加能力
### 2.1 主单与资源的唯一关系
推荐继续使用 `ll_dispatch_order`,将其改为平台整车作业主单,删除 `customer_id`;不填写 0、假客户或所谓共享客户。每张整车主单自动且唯一关联一条 `ll_fleet_trip`,后者继续承载车辆司机占用、逐段容量、外接预订、成本、交接、资源结束及其历史。两个编号是不同职责的业务编号,排车列表只要求用户使用排车号;不能由前端按客户创建多张子排车后再隐藏。
保留 `ll_fleet_trip_dispatch` 作为排车与资源记录的一对一关联,删除其中 `customer_id/review_json`,保留 `dispatch_id/dispatch_no/trip_id/trip_no/package_count/bound_by/bound_at`。增加 `trip_id` 唯一约束、原 `dispatch_id` 主键及 `dispatch_no` 唯一约束;本批绑定对象只有整车主单。`tripPurpose=PICKUP` 的接货流程不是本批排车流程,冻结前核实其直接调用,不能因收敛配送车次误改接货能力。
整车新建事务内同时建立上述两条记录及关系;空单允许 Fleet 的未分配资源、未确定卸货点和未知计划时间,不通过虚构站点、计划时间或容量去调用旧 Create DTO。起运仓必须真实存在;空单没有 PDA 拣货事实、实际装载、出库单或派送单。Fleet 的 `PLANNED/IN_TRANSIT/COMPLETED` 继续只表示资源运输生命周期;排车 `stage` 是五阶段的唯一事实,排车 `status` 仅表达 ACTIVE/CANCELLED 生命周期,详见第3节。正常签收汇总不自动执行 Fleet 结案或资源释放。
### 2.2 主单字段
| 字段 | 语义与约束 |
| --- | --- |
| `id/dispatchNo` | 内部关联键/全局唯一排车业务号;不将 id 当展示编号 |
| `overseasWarehouseId/Code/Name` | 唯一起运仓及目录快照;有货物后禁止换仓;空单换仓如开放需同事务更新 Fleet,不得单改展示 |
| `status`、`stage` | status仅ACTIVE/CANCELLED;stage仅BEFORE_LOADING/LOADING/AFTER_LOADING/DELIVERING/DELIVERED。取消保留实际停止阶段,不再推进;无第六阶段、无两字段同义状态映射 |
| `recordVersion` | 主流程公共版本,所有前台可写命令必须提交并 CAS 递增;不再让 PDA 用 tripRecordVersion 代替排车版本 |
| `cargoRevision/cargoHash` | 货物集合、真实来源/箱数、目的地与有效批次分配的修订号及稳定摘要;用于审核/装载/派送快照有效性,不与每次扫码计数混用 |
| `reviewRound/reviewBasisHash` | 审核轮次与当轮关键事实摘要;摘要包括 cargo、资源身份/能力、计划/目的地及批次版本;无关备注不改变审核依据 |
| `dispatchReview/loadingReview` | 当前轮状态、决定、原因、操作者、时间、依据摘要;历史追加保存,不能覆盖旧驳回记录 |
| `vehicle/driver/carrier` | 详情读取内部 Fleet 权威分配及临时资源快照;不再允许排车、派送请求分别覆盖出两套司机车牌 |
| `plannedDepartureAt/estimatedArrivalAt` | 可空计划时间,推荐 API 统一 ISO-8601 Instant、数据库 UTC DATETIME(3);不把计划发车保存为实际发车 |
| `loadingCompletedAt/loadingCompletionHash/departedAt/deliveryCompletedAt` | 服务端实际动作时间及装车事实摘要;摘要绑定cargo修订、真实pick/归属集合和实载快照,确认命令不接受客户端伪填实际时间 |
| `itemCount/palletCount/packageCount/pickedPackageCount/shippedPackageCount` | 全车计数;托数按实物托盘去重;逐订单展示不可重复计算同一托盘 |
| `remark/createdAt/updatedAt` | 详情所需备注及时间;updatedAt 当前 DTO 缺失需补齐 |
`departAt` 旧混合语义在 API 中直接拆为 `plannedDepartureAt/departedAt`,同步消费者,不保留双字段别名。路线从起运仓和真实目的地按稳定顺序生成;请求不允许任意改路线字符串。
### 2.3 货物、客户及来源
`ll_dispatch_item` 保留真实 `customer_id>0`,保留计划托盘、实物托盘、退回入仓、换标申请及目的地字段。一次货物选择以来源键表达,客户端不提供权威客户。服务端批量解析选中来源,复验客户、仓、暂扣、可排箱数、实物及有效占用后写入;允许同车不同客户/目的地,不允许跨起运仓。
同托多来源不能用 `orderNo/orderRefs/inboundCode` 展示快照作为分摊依据。复用 `ll_dispatch_pda_pick_order` 的逐入仓/退回来源和真实箱数,不另造第二套逐箱库存模型;拣货前的容量/预约/候选读取真实库存组成,拣货后派送和费用读取不可变拣货来源。每条 pick 的客户必须等于对应 item 和真实来源客户。普通、退回入仓、`RELABEL`、`RETURN_RELABEL` 四类实际分支均保留;来源阶段不是客户端随意传入的业务状态。
原来源锁 `ll_dispatch_pallet_lock` 保留真实客户与来源;实物托盘的全局唯一占用防止两个来源别名被分配两车,PLAN 与 RECEIVED 不能成为同一实物的两个有效锁。现有 `(customer_id,active_key)` 不足以单独证明实物全局排他,建议增加可空 `active_warehouse_pallet_id` 唯一索引,仍保留来源占用键;取消只释放属于当前主单的活动锁,不碰其他新单占用。
PDA 每车一个平台作业 task,删除 task 的 customer 头部;pick 与 pick_order 继续每条真实客户。task 业务号沿正式编号生成器生成,不能继续 `DPDA + 内部ID` 展示。主流程操作/幂等归平台整车,不借客户表承载。
### 2.4 主档与临时外配
推荐车辆、司机分别使用显式联合类型,支持一个选档案、另一个临时填写:
- `vehicle: { mode: MASTER, vehicleId }` 或 `{ mode: EXTERNAL, plate, carrierName, capacity: { palletSpaces, maxLoadKg, maxVolumeCbm } }`。
- `driver: { mode: MASTER, driverId }` 或 `{ mode: EXTERNAL, name, phone }`。
MASTER 的状态、区域、能力、证照及占用由服务端主档复验;请求不能覆盖主档快照。EXTERNAL对应ID必须为空,不生成主档、不造资源ID,不进入主档ID占用锁。按已确认规则由建单人补齐本趟真实容量、证照证据及预计任务结束,调度审核核实;空单可先保存、审核前补齐,快照进入审核依据及发车历史。临时车牌与既有主档占用的交集仍须核对正式资源规则,不以mode跳过必要校验。
## 3 五阶段与审核/动作资格
| 阶段 | 当前事实及允许的正常主操作 | 推进条件 |
| --- | --- | --- |
| 装车前 `BEFORE_LOADING` | 新建/加货/移除未拣货货物、修改资源与计划、提交调度审核、调度决定、理货决定 | 有货且资源等必需事实齐备才可提交;调度通过后才可理货;理货通过原子进入装车中 |
| 装车中 `LOADING` | PDA逐托/来源拣货,后台/PDA确认装车完成 | 两审核当前轮有效;每条明细 PDA 真实箱数等于应装数量、正数、有完整来源且未超量;确认完成后进入装车后 |
| 装车后 `AFTER_LOADING` | 后台安排派送,后台/PDA实际发车 | 派送/客户出库/费用核对完整且对应当前 cargoHash;资源、审核、批次接收资格再次有效;发车一次性进入派送中 |
| 派送中 `DELIVERING` | 派送侧真实执行与正常签收、读取异常提示 | 所有当前有效派送均正常签收且逐客户逐来源数量覆盖本车实发后,自动汇总派送完成 |
| 派送完成 `DELIVERED` | 只读本次作业;附加结案/资源结束保留原权限和入口 | 不自动释放车辆/司机,不把财务入账或成本结算当成完成条件 |
审核流程字段为 `reviewState=DRAFT|DISPATCH_PENDING|DISPATCH_REJECTED|LOADING_PENDING|LOADING_REJECTED|APPROVED`,每张审核记录自己的 `status=NOT_SUBMITTED|PENDING|APPROVED|REJECTED`。正常为DRAFT→DISPATCH_PENDING→LOADING_PENDING→APPROVED;调度/理货驳回分别进入对应REJECTED状态,两种拒绝不改变五阶段,仍停装车前。驳回原因必填。修改后显式重新提交,从调度开始新轮次,不复用旧理货通过。审核变更不自动补 PDA 或装车事实。
公开主单语义只保留一套:`status=ACTIVE|CANCELLED` 表示作业单是否有效,`stage` 表示唯一实际作业阶段,`reviewState` 表示审核子流程;不能再把Fleet状态、PDA task.status或单张delivery.status写到主单status。取消令status变CANCELLED,stage保留最后真实阶段供历史查询,所有主动作关闭;不生成CANCELLED阶段。主单新建为ACTIVE+BEFORE_LOADING,正常完成为ACTIVE+DELIVERED。数据库和DTO同步替换旧PENDING_DEPARTURE/READY_TO_DEPART/DEPARTED等主单状态,不保留旧字段别名。车辆状态、审核状态等嵌套字段均使用明确对象命名。
审核有效性不以 `review.recordVersion == 当前版本` 判断:审核命令及扫码本身都会加版本,应以 `reviewRound + reviewBasisHash` 判断。货物集合/来源数量/目的地、关键资源或资格/能力、关键计划及批次变化使相关审核和装载/派送快照失效。装车前编辑直接回草稿;已进入装车后的变更策略见第 10 节,不以后台编辑偷偷回滚状态或重新扣库存。
最后一次 PDA 扫码可记录 `pickingReconciled=true`,主单仍为 LOADING;后台/PDA再调用 `loading-complete`。后台没有数量补录字段,不允许用“全车总数相等”代替逐 item/source 核平。确认装车不要求已生成派送单,避免与“装车后才能安排派送”形成循环。
服务端统一返回 `actions`,每个动作为 `{ allowed, blockCode, blockReason }`,覆盖 create/add/remove/edit/cancel/submit/dispatchReview/loadingReview/pick/loadingComplete/arrangeDelivery/depart。列表批量计算阶段/审核/派送摘要,不逐行查详情;详情返回同一资格函数。资格包括当前用户权限和仓范围,按钮隐藏不替代写入时复验。
## 4 提议 API 与 DTO(待冻结)
统一 Gateway 前缀仍是 `/api`;Admin 客户端一般调用 `/platform/v1/...`,由 http base 拼接 `/api`;PDA同理。以下列完整公网路径。全部业务拒绝沿统一 ApiResponse 约定,不把代码内 ResponseStatusException 推定为最终 HTTP 响应。
### 4.1 平台接口
令 `D=/api/platform/v1/last-leg/dispatches`。
| 方法与路径 | 请求/响应提案 | 调整 |
| --- | --- | --- |
| `GET D`、`GET D/{dispatchNo}` | Query及统计见4.5;公开status/stage按第3节唯一定义,ListRow/Detail均带recordVersion | 保留路径,替换旧三阶段;平台customerId仅以真实item筛车,不改变主单归属 |
| `GET D/candidates` | 按仓、来源类型、订单/目的仓过滤,返回真实 customer/sourceKey/availablePackages/sourceVersion/blockReasons | 保留路径,移除多客户 planIds 的单客户推断;有界批量读取 |
| `POST D` | `Create { idempotencyKey, warehouseId, vehicle?, driver?, plannedDepartureAt?, estimatedArrivalAt?, remark?, cargo[], batchAllocations[] }` → CommandResult | 新入口;cargo为空建空单,非空同事务选货建车;没有customerId/tripNo字段;未取得服务端生成号时通过原POST同键恢复 |
| `PUT D/{dispatchNo}` | `Update { recordVersion,idempotencyKey,vehicle?,driver?,plannedDepartureAt?,estimatedArrivalAt?,vehicleAppointment?,remark? }` | 保留路径;关键字段修改触发审核失效;不接收 status 或实际时间 |
| `POST D/{dispatchNo}/items` | `AddCargo { recordVersion,idempotencyKey,cargo[],batchAllocations[] }` | 新入口;可继续在空单加货;批次分配提交最终完整快照,来源锁和保存原子 |
| `POST D/{dispatchNo}/items/{itemId}/remove` | `{ recordVersion,idempotencyKey,reason? }` | 替换旧无版本 DELETE,保留删除历史与占用证据;不物理删除已执行事实 |
| `POST D/{dispatchNo}/cancel` | `{ recordVersion,idempotencyKey,reason }` | 替换旧无版本 DELETE;取消前真实未拣货、无活动派送/出库;保留原取消历史及资金作废语义 |
| `POST D/{dispatchNo}/submit-review` | `{ recordVersion,idempotencyKey,remark? }` | 新入口,建立审核轮次及当前依据 |
| `POST D/{dispatchNo}/dispatch-review` | `{ recordVersion,idempotencyKey,decision: APPROVED或REJECTED,reason? }` | 调度审核归整车;不再按客户子单调度 |
| `POST D/{dispatchNo}/loading-review` | 同上 | 理货审核在拣货前;不要求派送或实际拣货 |
| `POST D/{dispatchNo}/loading-complete` | `{ recordVersion,idempotencyKey,remark? }` → CommandResult | 后台/PDA共享服务,后台没有拣货数量字段 |
| `POST D/{dispatchNo}/depart` | 同上 → CommandResult | 新增后台入口,与PDA同一版本/命令持久化语义 |
| `GET D/{dispatchNo}/prints/bol` | 全车真实来源、单据与客户分组的PDF | 保留路径,SQL去除主单 customer 假设;只读list权限 |
| `GET D/{dispatchNo}/external-freight`、`POST D/{dispatchNo}/transfer-delivery` | 由派送设计冻结,主流程建议保留已有路径,POST带整车版本/请求键及逐客户目的地费用数据 | 只在 AFTER_LOADING 开放写;由派送后端独占,本文不定义费用具体字段 |
`CargoSelection` 建议为判别联合类型:`{ sourceType: INBOUND_PLAN,planPalletId,sourceVersion }`、`{ sourceType: RETURN_RECEIPT,returnReceiptId,sourceVersion }`、`{ sourceType: RELABEL,relabelNo,warehousePalletId,sourceVersion }`;服务端再识别 RELABEL/RETURN_RELABEL,不信任客户传入阶段。sourceVersion 用于识别选择后事实变化;若当前来源没有可靠单行版本,应定义其真实组成摘要,不能常量填0。
`batchAllocations` 保持 `planPalletId/batchKey/customerId/sourceKey/destinationKey/packageCount` 当前语义,customerId 是待复验的分配断言,不是写入客户权威。混合客户一次校验完整集合再保存。换标全申请选择门禁保留,不自动开放分批。
### 4.2 智能草稿与旧车次操作
草稿能力保留:`GET /drafts`、`POST /drafts/snapshot`、`/drafts/containers`、`/draft-locks/lock|unlock|release`。草稿及每个装车容器不再带单客户归属,锁保留真实客户。每个容器最终生成一张整车主单,跨客户是同一 cargo[],不是先按客户拆子单。正式转换建议由现有 `POST D/drafts/pre-arrange` 接收每组完整 Create 内容和持久请求键,组装车元数据可空;沿同一 create 服务实现。直接 `POST D/pre-arrange` 的生产消费者全部改用 `POST D` 后删除旧入口,不保留双建单协议。
`fleet/trips/prepare`、`/{tripNo}/dispatches/bind|unbind`、客户单调度审核旧路径不再用于配送排车主流程,直接调用者同步收敛。旧“多张排车共车”入口必须替换为给同一主单加货;不能把旧操作留为绕过新状态门禁的写入通道。车次容量/外接/成本/交接/资源结束等非该旧协议能力继续保留,进入 DELIVERY 关联主单时遵守共同锁和审核失效规则。PICKUP及独立附加能力的精确接线由总控裁定,不能笼统删整个 Controller。
### 4.3 PDA 与恢复
令 `P=/api/pda/v1/last-leg/dispatches`。`GET P`、`GET P/{dispatchNo}` 保留,返回本绑定仓整车 task,加入 `recordVersion/stage/reviews/actions/pickingReconciled`;items 保留真实来源、业务号、应装/已拣箱数。移除要求用户操作旧子单的 `tripDispatchCount`,内部 tripNo 可在附加追溯中读取,不能作为主动作请求身份。
- `POST P/{dispatchNo}/items/{itemId}/pick`:现有 positionId/packages/productQuantity/cartonMark/remark/idempotencyKey 加 `recordVersion`;客户、起运仓均从服务端明细和Token取得。
- `POST P/{dispatchNo}/loading-complete`:与平台同 `LoadingComplete` DTO;替换旧 `/complete` 的仅PDA完成协议,两端调用同服务。返回装车后阶段及动作结果。
- `POST P/{dispatchNo}/depart`:保留路径,改用整车排车 recordVersion;与平台同 Depart DTO、结果和持久命令。
- 两端均提供 `GET D或P/{dispatchNo}/commands/{idempotencyKey}`;按当前身份/动作权限/仓绑定及第6.2节授权表读取原结果。未知键返回业务错误 `DISPATCH_COMMAND_NOT_FOUND`(data为空,非成功结果),不把未找到解释成动作未执行;原POST同键同载荷可安全恢复。数据库提交中途尚不可见也可能暂未找到,客户端继续保留原键及payload,不能立即换键。跨主体键不返回原结果。
统一公开 `CommandResult { dispatchNo,action,idempotencyKey,recordVersion,status,stage,occurredAt,effect,counts,result,replayed }`:recordVersion是该命令完成时排车版本(0有效),status/stage是该时刻事实;effect为APPLIED或EXISTING;result为动作判别联合类型(CREATE/EDIT返回已保存身份及变化,PICK返回item/source核平事实,LOADING_COMPLETE返回loadingCompletionHash,DEPART返回departedAt/逐客户实发单据,ARRANGE_DELIVERY返回完整outbounds[]/deliveries[]/arrangementKey)。不得只返回布尔成功或单个outboundNo。所有平台/PDA命令及GET命令结果使用同一schema;原结果除replayed标记外不可变,禁止将后来阶段塞进旧动作快照。前端校验同一dispatchNo/action/idempotencyKey后,再GET当前详情恢复UI;旧结果证明原动作,不覆盖新详情。响应不再要求用Fleet IN_TRANSIT加客户子排车数组猜当前排车成功。
### 4.4 详情字段供四页签使用
ListRow 返回业务号、五阶段、审核和装车/派送摘要、车辆司机、起运仓、计划/实际发车、数量、版本及动作资格;不装载完整订单/附件集合。Detail补充:
- `vehicleInfo { vehicleMode,vehicleId?,plate,driverMode,driverId?,driverName,driverPhone,carrierName,vehicleStatus? }`;临时车辆没有主档状态时显示“—”,不虚构启用状态。
- `dispatchInfo { route,plannedDepartureAt,departedAt,estimatedArrivalAt,fbaAppointments[],vehicleAppointment }`。多目的仓不能只返回一个 FBA 约号;预约从有效批次读,保留未知与待复核,不用头部可编辑约号覆盖正式预约。
- `documents { dispatchNo,deliveries:[{customerId,deliveryNo,destinationKey,status}],createdAt,updatedAt,remark }`;完整返回业务单号,列表摘要批量读取。
- `orderDetails[]`:真实客户、订单号/入仓码、重量kg、托数、目的FBA仓、体积m³、集装箱号及来源键。按真实订单组成批量组装,不把同托全量重量/体积复制到每个订单;没有可信分摊则对应字段null。`containerNo`、updatedAt、remark、多派送单当前排车DTO缺失需补齐。
### 4.5 列表审核分区、分页和统计
完整Query提案:`{ page>=1,size=1..200,dispatchNo?,vehiclePlate?,warehouseId?,customerId?,fbaAppointmentNo?,status=ACTIVE|CANCELLED|ALL,stage?,beforeLoadingSection?,reviewStatus? }`。status缺省ACTIVE;ALL仅为查询选项,不是保存值/第六阶段。stage严格五项;beforeLoadingSection为`VEHICLE_INFO|DISPATCH_REVIEW|LOADING_REVIEW`,仅在status=ACTIVE且stage=BEFORE_LOADING时合法,其他组合拒绝参数错误,不能静默忽略。reviewStatus仅在某个审核分区存在时合法。
三个装车前分区保留同一整车集合和不同列投影,不能擅自将“车辆信息”解释成未提交队列并隐藏已审核单。`VEHICLE_INFO`不接reviewStatus;`DISPATCH_REVIEW`按本轮dispatchReview.status过滤;`LOADING_REVIEW`按本轮loadingReview.status过滤,均支持NOT_SUBMITTED/PENDING/APPROVED/REJECTED,未传reviewStatus时不过滤该状态。尚未提交/尚未轮到的审核是NOT_SUBMITTED,不伪造PENDING;旧轮失效通过history/invalidatedReason展示,当前轮重新待提交,不将旧APPROVED算入当前。
返回 `DispatchPage { records,total,page,size,pages,statistics,snapshotAt }`;statistics结构固定为:
```text
statistics {
matchedTotal, activeTotal, cancelledTotal,
stageCounts: { BEFORE_LOADING, LOADING, AFTER_LOADING, DELIVERING, DELIVERED },
beforeLoadingReviewCounts: {
vehicleInfoTotal,
dispatchReview: { NOT_SUBMITTED, PENDING, APPROVED, REJECTED },
loadingReview: { NOT_SUBMITTED, PENDING, APPROVED, REJECTED }
}
}
```
`total`是当前status+stage+审核筛选后的整车总数,与分页records一致;客户筛选通过EXISTS item.customerId选车,每车只计一次。statistics的共同基集只套当前用户范围及dispatchNo/vehiclePlate/warehouse/customer/正式预约号等搜索条件,排除分页、status/stage/分区/reviewStatus;matchedTotal=activeTotal+cancelledTotal,stageCounts仅ACTIVE且五项之和=activeTotal。beforeLoadingReviewCounts只统计ACTIVE+BEFORE_LOADING,vehicleInfoTotal=该阶段数;两审核状态各四项之和同样等于该阶段数,三个分区不是三份互斥货物。零项明确为0,不返回当前页长度冒充总数。
页面、数量及动作投影在同一只读一致快照事务读取,statistics不逐行查详情。stage筛选影响records/total,不影响顶部各阶段计数;审核筛选不影响同基集的审核分布。用户选择客户筛选仍是平台整车查询,行数量为全车数量;若需要仅本客户数量,必须另名customerMatchedPackages,不能把全车总量悄悄改成筛选客户量。本节是后端可实现的查询提案,分区是否默认只看待审属界面默认值,不新增业务阶段。
## 5 派送后端可读取事实和共同端口提案
端口不共享持久化Entity,不让派送方从 `DispatchOrder.customerId` 推导归属。建议在本任务 `dispatch/port/` 新增只包含 DTO/接口的契约,由总控冻结后移交派送方实现其端口;实现仍遵守各自唯一写权。所有端口同 Lastleg 本地事务,不新建HTTP内部调用。
| 端口 | 签名/事实语义 | 实现者 |
| --- | --- | --- |
| `DispatchExecutionPort.lockForArrangement(actor,dispatchNo)` | 返回Context:dispatchId/no、tripId/no、warehouse、recordVersion、cargoRevision/hash、stage、审核/装车事实、当前资源及cargo;先锁定和核对身份供命令恢复,首次写入另调requireFreshArrangement | 主流程后端;先统一锁,不能派送方先锁delivery再回头锁主单;不得在查原结果前拒绝旧版本 |
| `Context.cargo()` | 返回CargoLine:dispatchItemId、真实customer、来源与pick/attribution、退货/换标/实托、Destination、packages及批次;精确字段见实际Java | 主流程提供稳定身份;逐来源查询可由派送方沿现有DispatchCargoSourceQuery/DispatchFeeCargoMapper适配,只保留一份来源权威 |
| `DispatchExecutionPort.recordArrangement(context,actor,identity,fact,alreadyArranged)` | 首次安排CAS递增整车版本并记录公共命令,阶段仍AFTER_LOADING;已存在同业务仅记当前新键EXISTING结果,不重建单据 | 主流程后端;派送服务全部客户成功后同事务调用,字段/签名以第0节为准 |
| `DispatchDeliveryPort.departureFacts(locked,lock)` | 返回 arrangementRevision/hash、客户出库单和逐客户目的地派送单、覆盖箱数、费用核对有效性及 blockReasons;逐来源精确覆盖,不能只比总数 | 派送后端 |
| `DispatchDeliveryPort.markDeparted(locked,departedAt,commandKey)` | 所有客户出库/派送推进,返回逐客户实发事实;不扣已扫码库存、不更新排车阶段 | 派送后端,与主流程发车同事务,任一失败全车回滚 |
| `DispatchDeliveryPort.normalDeliveryFacts(context)` | 批量普通读NormalDeliveryFacts,返回全部本车派送原实发/签收/退回/异常、expectedDeliveryNos、allNormallySigned、factsHash及正常签收最大时间;不加历史来源订单锁 | 派送后端;空集合不是真,拒签/退回不得正常完成 |
| `DeliveryFactsChanged(dispatchNo,deliveryNo,deliveryVersion)` | 签收事务内记录唯一持久待核对事实,签收提交后消费/重试 | 派送后端保存事实,主流程在新事务汇总;不在原签收子锁下申请父锁 |
| `DispatchCompletionPort.reconcile(signal)` | 主流程新事务先取得trip/dispatch锁,再普通读全部已提交签收事实,CAS stage DELIVERING→DELIVERED并递增recordVersion,记录唯一汇总依据和完成时间,signal确认同事务 | 主流程后端;重复提醒无副作用,失败回滚后记录退避;写权按6.5 |
`allNormallySigned` 至少要求:当前有效派送单非空、没有缺项/取消/异常,全部有真实正常签收事实且逐客户/目的地/来源覆盖本车实发;分批签收仍未完成。原 `FleetCompletionModels` 中“正常签收或真实退回可结案”继续只服务附加结案,不能替代此端口。
本稿完成后已只读核对派送稿第6节:采纳其“签收保持本派送→来源订单锁、提交后持久提醒再汇总”的建议,以保留已有跨多趟来源完成证明并避免扩大签收锁范围。正常签收后另发退货不重开本趟完成,完成时间取本趟最后真实签收;不能只因当前派送状态后来出现退货就否认已完成的原运输。汇总不二次发布来源完成事件、回访或费用。提醒待处理记录归派送域,主流程消费/重扫归dispatch域,确切存储和调度入口仍由总控冻结。
发车事务按6.4精确链:trip根锁→原命令恢复或新命令资源锁→dispatch→全部客户outbound/delivery→task/批次→真实来源订单和业务行→单据及订单统计推进→写唯一DEPART历史、stage=DELIVERING及不可变命令结果;status保持ACTIVE。库存扣减已在PDA扫码,不在此事务再ship;资料核验可普通读,不允许适配器在锁齐派送前提前取得来源订单锁。
派送服务安排事务按6.4先取得父级及安排行、outbound/delivery锁(首次为先完成子单插入),再取需要的来源/费用锁和写Outbox,最后recordArrangement及共同命令结果同事务提交;首次命令只允许ACTIVE+AFTER_LOADING。相同目的仓不同客户不合单;逐客户目的地费用具体由派送设计定义,不由本任务猜测。
## 6 事务、版本、幂等与锁顺序
### 6.1 共同命令与两种摘要
公开写命令统一 `recordVersion`(创建无既有单版本除外),不存在公开expectedVersion。新增 `ll_dispatch_command { id,dispatch_id,dispatch_no,action,operator_id,idempotency_key,command_hash,result_json,created_at }`,`idempotency_key`平台全局唯一,operator作为不可改的所有者字段,不能用`(operator,key)`分片后让另一个操作者重建同键动作。Admin/PDA共享表、schema及当前身份权限规则;渠道不进入命令身份,同一账号从另一端恢复仍先核验该端权限/绑定仓。
- **commandHash**:绑定可信主体operatorId、动作、目标业务号、原recordVersion及规范化完整业务payload(含真实证据版本/hash);排除随机键本身和传输字段。Create无目标号时使用CREATE作用域及完整创建内容,结果绑定服务端生成业务号。对象属性排序、集合按稳定业务键排序、金额精度固定,不能因显示顺序不同误判;集合只有确认为无序时才排序。原键不能改变主体/动作/单号/原版本/任一业务字段。
- **arrangementBusinessHash**:仅安排派送有此业务去重摘要,包含dispatch身份、cargoHash、loadingCompletionHash、逐客户目的地完整组、资源快照、费用/报价/覆盖证据及全部业务字段;排除operatorId、recordVersion、idempotencyKey、客户端显示顺序等纯命令身份。另一操作者/另一键也不能创建第二套安排或费用。它不用于吞掉两次数量相同但实际不同的PDA扫码,不代替commandHash。
- `ll_dispatch_delivery_arrangement`以dispatchId唯一保存业务摘要、单据集合和原事实状态;派送域独占写,本地command与安排事实、子单、费用及Outbox同事务。首条Arrange命令的不可变原结果保存在共同命令表;不能在delivery再建立一套不同授权的命令键协议。
既有命令查验在版本/阶段门禁之前;当前权限和仓绑定校验始终在结果披露之前。新命令使用CAS及当前recordVersion;版本冲突整体回滚,不将换版本当成同一未决命令重试。原结果恢复不递增版本、不重复扣库存/发布费用。没有持久成功命令的未知结果继续以原payload重试;失败或超时不自动改键。
### 6.2 授权、恢复与不同请求键判定表
| 场景 | 权限和判断顺序 | 结果/副作用 |
| --- | --- | --- |
| 原键、原主体、原完整payload;当前阶段/版本已推进 | 先核验当前端身份、原动作权限及PDA绑定仓;再校验commandHash和业务号;先于旧版本拒绝 | 原不可变CommandResult,replayed=true;不重新执行;再GET当前详情 |
| 原键、原主体但改recordVersion/动作/单号/数量/费用等 | 当前权限后检查严格commandHash | `DISPATCH_COMMAND_CONFLICT`,不覆盖原记录、不返回“按新版本成功” |
| 原键、不同主体,即使有同等权限或同样安排业务 | 当前身份后比较命令所有者,不披露原payload/结果 | `DISPATCH_COMMAND_FORBIDDEN`;必须用自己的新键走当前事实授权流程;不复用他人命令身份 |
| 原主体同键,但权限已撤销、角色不符或PDA已换仓 | 先检查当前授权范围 | 拒绝读取/重放;历史成功不授予当前访问权 |
| 新键、原主体或另一有权限主体、同一有效安排业务 | 先核验平台安排写权限和全车范围,再校验新命令recordVersion;锁内比较全车唯一安排的businessHash及有效状态 | 不新建单据/费用;保存属于新主体/新键的严格命令及EXISTING结果,返回原完整单据集合,replayed=false;同一新键再次请求则replayed=true |
| 新键同安排业务但recordVersion过期 | 新命令不享受旧命令重放豁免 | `DISPATCH_VERSION_CONFLICT`;GET当前事实后另起明确命令,不静默替换未决payload |
| 新键同车但安排业务不同,或原安排已取消/失效 | 复验当前唯一安排及businessHash/状态 | `DISPATCH_ARRANGEMENT_CONFLICT/INACTIVE`;返回可公开的阻断原因,不重建、不重复发布;原键仍只能恢复其历史结果 |
| 新键重复装车完成/发车 | 即使载荷看似相同,也无第二次动作;有权限者可读当前事实 | `DISPATCH_ALREADY_LOADING_COMPLETED/ALREADY_DEPARTED`;不插第二执行事实。需恢复成功证明时用原键查询 |
| GET原键不存在/尚未提交可见 | 当前身份/权限/仓后查询 | `DISPATCH_COMMAND_NOT_FOUND`且无成功data;保留原payload同键POST核对,不把“未找到”等同“可重新生成” |
| GET他人键/仅有list权限但没有原写动作权限 | list仅允许读当前业务事实,不允许冒充原命令所有者 | 原结果拒绝;另有已定义审计端口时走独立审计权限,不在本次泛化开放 |
以上错误码是设计提案,由总控统一映射ApiResponse。业务错误沿项目HTTP200+body.code规范;真实认证/基础设施拒绝按现有401/403等规则,不把表内业务冲突强制解释成HTTP409。命令查询与当前详情都不会将内部ID作为业务编号。
### 6.3 本轮沿实际Java核对的锁点
以下是当前源码事实,不是新设计已证明无死锁;`→`表示同一事务中先取得/执行,括号“读”不表示行锁。
| 操作与实际方法 | 已核对顺序和边界 |
| --- | --- |
| `FleetTripService.assign` | `planned→repository.lockTrip` → `vehicles.lockById` → `DriverService.requireDispatchable→drivers.lockById` → resource reserve/release DML → `DispatchFleetAdapter.lockForAssignment`锁dispatch → 锁outbound → 锁task → assign再锁相关deliveries。资源占用`FleetResourceMapper.find`只是SELECT,不能当成FOR UPDATE;新增/删除占用由唯一键及DML串行化 |
| `FleetTripExecutionService.depart` | trip行锁 → vehicle档案锁 → occupancy普通读 → driver档案锁 → `manifests(true)`逐dispatch行锁、outbound锁、task锁,manifest末尾`DeliveryExecutionGuard.departureBlockReason(...,true)`锁deliveries → `AppointmentWorkDispatchBinding.requireDeparture`批次锁 → 真发车子操作。不可改写成“先来源再派送” |
| `DispatchPdaWorkflowService.depart`(MANDATORY,外层已持Fleet父锁) | 重入dispatch锁 → binding锁 → outbound锁 → `DeliveryExecutionGuard.requireDeparture`派送锁 → task锁 → `DispatchPickOrderAttributionService.depart`按订单数字ID锁来源订单并更新订单计数 → 转运/换标业务更新 → 来源占用释放/DML。此处没有inventory.ship;订单计数移动不等于库存移动 |
| `DispatchPdaWorkflowService.pick` | dispatch行锁 → task行锁 → binding锁 → `preparePicking`按orderId锁真实来源订单/已有退回收据 → inventory的allocate/pick/ship;每个`InventoryCommandService.execute`先查/插幂等operation(唯一键DML),再`locked`取得position行锁→balance行锁。随后写pick/归属;没有outbound/delivery行锁。RETURN_RELABEL先`prepareNativeReturn`锁来源订单,再`ReturnRelabelDispatchStock.pick`锁真实退货箱;不伪造position |
| `DeliveryTransferService.platformTransfer/transferResolved` | dispatch行锁 → 活动outbound锁/原键查询 → binding锁 → bindReceivedPallets更新item(DML锁)→ freight/coverage及费用证据校验 → 插入outbound/子单及费用/来源更新。不是天然trip父锁入口,必须接新上下文端口;安排流程不得照搬旧提前转换资格 |
| `DeliveryTransferService.cancelOutbound` | 非锁读定位 → dispatch锁(有关联时)/独立relabel锁(对应类型)→ outbound锁 → binding锁及未执行资格 → delivery集合锁 → 按业务分支的退货/转运/任务/来源更新;普通dispatch分支后续按订单ID锁tailOrders。不能从outbound锁后才请求trip锁 |
| `DispatchService.cancel` | repository.lockOrder锁dispatch → binding锁且当前requireUnbound → outbound锁 → 来源换标/退货释放及活动锁DML。新一对一主单恒有关联,须改为父级协调取消,不能保留“必须unbound”造成永远不能取消;不等于授权已拣/已装车撤销 |
| `DeliveryDocumentService.save`及`SourceDeliveryCompletionQuery.proveAll` | 显式READ_COMMITTED,先本delivery行锁;outbound以普通读判断已出库,避免反向outbound锁;随后proveAll按orderId锁相关真实来源订单,普通读历史发运证明,不锁历史delivery/dispatch/exception/inventory。不可持这些子锁再调trip/dispatch汇总 |
源码证据还表明已有逐来源订单记账方法 `LastlegOrderMapper.transferPickedToShipped` 是尾程订单picked/shipped统计移动,普通扫码调用的 `InventoryCommandService.ship` 才是仓位/库存实际扣减。新设计分别命名 `finalizeSourceOrderShipmentCounters` 与“库存SHIP事实”,不再写含糊的picked→shipped。装车完成、安排、发车只核对并消费已存在pick/attribution/SHIP流水;发车仍要按真实来源更新订单/出库/派送计数,不能因不再ship就漏掉订单统计。
### 6.4 新实现逐操作锁协议(待冻结,替换相反提案)
共同根为trip行锁,沿现有Fleet顺序固定为 **trip→必要vehicle档案→必要driver档案/占用DML→dispatch**。不能本任务保留trip→dispatch→资源而另一任务保留资源→dispatch。身份只读解析不加锁,锁trip后重读一对一关系;所有会改主单的原Fleet/后台/PDA/派送入口必须走同一根,旧直锁dispatch入口不得遗留。原键命令可在trip锁后直接授权重放,不能先要求当前司机仍可派车才允许恢复过去结果;新命令才按下列顺序取得资源及子锁并复验。
| 新操作 | 根以后实际需要的链 | 不能做的事 |
| --- | --- | --- |
| 装车前编辑/审核/资源变更 | 根→资源(涉及才取)→dispatch→binding;涉及批次/来源变更再按batchKey及真实来源ID锁,触及预建出库时先取出库/派送再取来源 | 不将审核前置查询直接解释为来源已锁;不在库存锁后改批次或派送 |
| PDA扫码 | 根→必要资源校验→dispatch→binding→task/item→真实来源订单升序→退回来源行(对应分支)→position→balance,库存命令和pick归属同事务 | 本链不请求outbound/delivery行锁,不写整车派送完成;否则会与签收的delivery→source相反 |
| 装车完成 | 根→必要资源→dispatch→binding→task/item;批次/装载快照按当前事实复验,读取既有pick/归属;若需要来源锁则按ID升序且不再申请delivery锁 | 不先造派送以满足装车门禁;不执行allocate/pick/ship |
| 安排/发车/关联出库取消 | 根→资源→dispatch→binding→整车安排行/命令检查→全部客户outbound(客户/ID排序)→全部delivery(客户/ID排序)→task/item(需锁才取)→相关预约批次→真实来源订单/转运/换标等来源行→费用来源/Outbox及DML | 所有需取得的delivery行必须在第一个来源订单锁之前取得;不在持来源锁后补锁另一张派送,不再扣库存;取消只适用已有未执行合法分支 |
| 签收资料/来源完成证明 | 本delivery→来源订单升序(保持既有显式READ_COMMITTED链)→业务完成/Outbox/待汇总信号提交 | 不取得trip/dispatch/outbound行锁;来源证明只读历史证据,不以父锁替代跨趟来源序列化 |
| 主流程汇总 | 新事务trip→dispatch(不请求资源锁)→普通读全部已提交本趟签收/异常事实→CAS主stage→acknowledge本信号→同事务提交 | 不调用SourceDeliveryCompletionQuery.proveAll、不锁来源/历史派送;资源不因汇总释放;失败阶段与ack同时回滚 |
关键交集论证:发车和签收都将需要的delivery置于来源订单之前;扫码只持来源/库存而不再申请delivery,持有来源锁的扫码最终可提交,不等待签收持有的delivery;汇总不持子锁申请父锁。仅trip共同根不能解决跨trip共享来源的反向等待,以上限定正为此而设。安排内若费用/报价/来源适配器提前锁来源,必须后移至全部delivery锁已取得(首次新建子单也先完成插入),不把当前旧调用顺序原样当新协议。
多客户统一排序:客户用已验证客户ID的数值顺序(现有API字符串只做传输),内部订单/出库/派送/仓位用Long数值顺序,batchKey按稳定字符串排序。不是把`"10"`放在`"2"`前的随意字典序。跨车资源替换应预先按资源类型/数值ID锁定本次全部旧/新主档,再执行占用变化,避免两车交换资源相互等锁;额外主档/交接入口仍需精确写权。
未证实的锁边界保留为实施门禁:预约编辑/取消/替换与来源/费用的外部入口是否会在持batch/source/fee锁后回头申请本车父锁,尚未遍历验证;对这些已列直接消费者须由总控分配后逐一核对,不允许靠一句“顺序统一”宣称全局无死锁。新增测试要覆盖跨车同来源签收/发车、两车资源交换及预约变更竞争;本轮只静态核对,未运行并发验证。
出站费用与业务事件只写本地Outbox并随事务提交,远程成功不等于本地事务原子性;资金/文件/其他服务继续正式端口协作,不跨Schema Join。
### 6.5 正常签收持久信号的唯一写者
派送任务独占 `delivery/` 下拟新增 `DeliveryFactsChangedSignal`、Repository/Mapper及 `DeliveryReconcileSignalPort` 实现:签收提交前在同事务插入 `(dispatchId,deliveryId,deliveryVersion)` 唯一信号,保存PENDING、attempts、nextRetryAt、lastError;相关结构由总控统一SQL集成。纯内存afterCommit可作唤醒加速,不能代替持久信号。
主流程任务独占 `dispatch/service/DispatchDeliveryCompletionWorker.java`、`DispatchCompletionService.java`及直接重试/并发测试;使用服务已有调度能力有界扫描due信号,逐车调用新事务reconcile。端口返回信号时不持delivery/source/signal行锁跨入父锁事务;多实例可重复处理,父锁/CAS及唯一汇总依据保证幂等。按正式契约第九节,阶段CAS和本次signal acknowledge在同一汇总事务提交,禁止旧稿“先提交阶段再另事务markProcessed”;任一失败两者均回滚。失败后才独立短事务记attempts/nextRetryAt/错误;未核齐的合法部分签收已完成本次核对,可在同汇总事务确认该信号,后续签收会发新信号。
增加有界修复性重扫只读定位“DELIVERING且存在未处理签收信号/已具备全签候选”的本车,仍调用相同reconcile,不写造签收事实;它是本功能可靠消费重试,不是测试存量回填。信号记录/markProcessed端口由派送写,消费/调度/重试决策/重扫由本主流程写,Maven仍本任务唯一执行。普通最终一致窗口内页面读真实stage=DELIVERING,不在签收POST成功后由前端直接置DELIVERED。
## 7 权限与隔离提案
平台入口限定 PLATFORM 且 tenantId=0;列表详情及只读候选使用正式list权限,写权限分别检查。真实客户只来自来源,平台头部不是一位客户。客户已有派送/出库读取继续Token客户隔离:按客户明细/单据读投影,不向客户暴露整车客户清单、其他客户费用、附件或完整整车详情。按用户已确认规则,由派送任务移除旧merchantTransfer创建此类派送的写入口,客户继续合法读取本客户单据/资料,不保留客户改整车旁路。
建议具体权限如下,由总控统一维护 `OverseasPermissions`、IAM/SQL及前端,不由本任务写共享文件:
| 动作 | 权限提案 |
| --- | --- |
| 整车列表/详情/BOL | 既有 `platform:overseas-warehouse:dispatch:list`,不因可读详情而可调用写命令 |
| 命令结果GET及同键POST恢复 | 当前原动作写权限+原主体+业务范围/PDA绑定仓,按6.2;list不授予恢复他人命令的权利 |
| 新建/选货建单 | 新增 `platform:overseas-warehouse:dispatch:create`;旧智能排车权限消费者由总控映射/收敛 |
| 修改/加货/移除/提交审核 | 既有 `platform:overseas-warehouse:dispatch:edit`;提交是申请,不是审核通过 |
| 取消 | 既有 `platform:overseas-warehouse:dispatch:cancel` |
| 调度/理货决定 | 推荐沿用既有 `platform:fleet:trip:dispatch-review/loading-review`,总控同步排车操作资源,不新增一套同义审核权限 |
| 后台装车完成/实际发车 | 建议新增 `platform:overseas-warehouse:dispatch:loading-complete/depart`,不借edit或PDA角色授权后台 |
| 安排派送 | 既有 `platform:overseas-warehouse:dispatch:transfer-delivery`,费用确认权限另按派送设计 |
| PDA列表/扫码/装车完成/发车 | `lastleg:pda:operate` 加海外PDA角色和Token绑定仓;不接收customerId/warehouseId改变范围 |
已有车辆主档/司机资格/资源占用仍由服务端验证,不能因为排车详情不显示附加能力而省略。主单、task、每条货物、出库派送所属起运仓一致;PDA跨仓读/写和同键恢复都拒绝。后台目前没有PDA的绑定仓事实,不从客户端PDA token或伪造身份调用PDA Controller;后台使用平台权限并复用领域服务。
## 8 精确实施清单与直接消费者
### 8.1 本任务后续独占生产触点
| 路径 | 计划变更 |
| --- | --- |
| `dispatch/controller/DispatchController.java`、`DispatchQueryController.java`、`SmartDispatchController.java` | 上述平台API、五阶段过滤、整车跨客户建单、删除单客户推断 |
| `dispatch/dto/DispatchRequests.java`、`DispatchResponse.java`、`DispatchDraftGroupResult.java` | Create/Add/版本命令、资源联合类型、五阶段、四页签事实、全车结果;禁止别名兼容 |
| `dispatch/entity/DispatchOrder.java`、`DispatchItem.java`、`DispatchDraft.java`、`DispatchPalletLock.java` | 主单/草稿去客户头部、主单版本/审核/实际节点、明细真实客户与实物排他 |
| `dispatch/mapper/DispatchOrderMapper.java`、`DispatchItemMapper.java`、`DispatchCandidateMapper.java`、`ReturnDispatchCandidateMapper.java`、`DispatchPalletLockMapper.java`、`DispatchDraftMapper.java` | 全车查锁、按明细客户过滤、来源解析批量化、保留真实客户库存条件和退回来源 |
| `dispatch/repository/DispatchMutationRepository.java`;拟新增 `DispatchRepository.java`、`DispatchCommandRepository.java` 与 `dispatch/mapper/DispatchCommandMapper.java` | 接管触及服务直调Mapper、主单和命令持久化;不把SQL搬进Service |
| `dispatch/service/DispatchService.java`;拟新增 `DispatchExecutionService.java`、`DispatchReviewService.java`、`DispatchCompletionService.java`、`DispatchDeliveryCompletionWorker.java` | 创建/加货/审核/五阶段状态机;双端共同装车与发车;主流程唯一消费持久签收信号、重试与重扫,不两端各写一套 |
| `dispatch/pda/controller/DispatchPdaController.java`、`dto/DispatchPdaRequests.java`、`DispatchPdaResponses.java` | 整车身份/版本、仓绑定、替换complete协议、恢复结果 |
| `dispatch/pda/service/DispatchPdaWorkflowService.java`、`DispatchPickOrderAttributionService.java`,以及 `dispatch/service/ReturnRelabelDispatchStock.java` | item真实客户、全车核平、扣减一次、归属/换标退货事实;不改变已修库存规则 |
| `dispatch/pda/entity/DispatchPdaTask.java`、`DispatchPdaOperation.java` 及对应Task/Operation/Pick/PickOrder Mapper | task去客户头部、命令集中;pick继续真实客户,查询不能再按单一头部customer过滤全task |
| 拟新增 `dispatch/pda/repository/DispatchPdaRepository.java` | PDA读写经Repository;逐来源账本与库存命令保留其领域入口 |
| `dispatch/fleet/DispatchFleetAdapter.java`、`FleetDispatchPlanningAdapter.java`、`FleetDispatchPlanningMapper.java` | 快照不再单客户;manifest分解为拣货核平/实载/派送三个事实,保留sourceCargo/交接/成本直接消费者 |
| `dispatch/service/DispatchBolPrintService.java`、`dispatch/mapper/DispatchBolMapper.java` | 全车BOL、按明细真实客户取来源;补Repository边界 |
| `fleet/trip/FleetTripEntity.java`、`FleetTripDispatch.java`、`FleetTripModels.java`、`FleetExecutionModels.java`、`FleetTripReview.java` | 一对一关联、去客户绑定审核、临时资源快照、内部和外部版本区分 |
| `fleet/trip/FleetTripService.java`、`FleetTripExecutionService.java`、`FleetTripPreparationService.java`、`FleetDispatchBindingGuard.java`、`FleetDispatchGateway.java`、`FleetDispatchWorkflowQuery.java` | 自动资源记录、统一阶段/审核资格、消除多客户子单绑定流程;保留附加能力及其服务端验证 |
| `fleet/trip/FleetTripRepository.java`、`FleetTripMapper.java`、`FleetTripDispatchMapper.java`、`PlatformFleetTripController.java` | 一对一关系和明确旧接口删除、附加API仍可用;新建资源不伪填旧必填值 |
| `fleet/trip/FleetTripCompletionService.java`、`FleetTripCostService.java`、`FleetTripCostBasis.java`、`FleetTripHistory.java`、`FleetTripHistoryMapper.java` | 按真实客户货物读取,原结案/成本历史与资源结束保持;不将资源COMPLETED当五阶段完成 |
| `fleet/trip/VehicleFulfillmentMapper.java`、`FleetTripCalendarService.java`、`fleet/trip/work/AppointmentWorkTripMapper.java` | 已发现b.customer_id连接需改按派送/货物真实客户;日历保留真实时间和空单缺项,不再假定计划时间全非空 |
新增文件名为推荐落点,冻结时可按既有层次合并;不能为少建Repository继续跨层SQL。`FleetBookingFreight.java` 归派送任务,本任务只提出 SourceCargo/绑定关系变化,不修改。
### 8.2 必须由总控分配或集成的外部触点
| 精确触点 | 必须处理的影响/写者 |
| --- | --- |
| `delivery/service/DeliveryTransferService.java`、`DeliveryFeeCoverageService.java`、`DispatchCargoSourceQuery.java`、`delivery/repository/DispatchCargoSourceRepository.java`、`delivery/mapper/DispatchFeeCargoMapper.java` | 派送后端;所有 dispatch.getCustomerId 消费改为真实分组,签名不能留旧头部参数 |
| `delivery/service/DeliveryDocumentService.java`、`DeliveryExecutionGuard.java` 及客户Controller/DTO、Outbound/Delivery Mapper | 派送后端;共同锁在单据锁之前;正常签收汇总端口、跨客户出库覆盖与唯一键 |
| `inboundplan/work/AppointmentWorkDispatchBinding.java`、`AppointmentWorkDispatchMapper.java`、`appointmentwork/AppointmentWorkDispatchPort.java` | 超出本任务当前生产写权,总控分配唯一写者;必须一次校验/保存全车各客户分配,移除d.customer_id Join;保留稳定batch/source/customer/目的地和已接收门禁 |
| `exceptionorder/service/ExceptionOrderService.java` | 已发现DispatchOrder直接消费者;改用派送/拣货真实客户归属,保留 RETURN_RELABEL 原箱回溯;总控分配,不能覆盖在途测试修改 |
| `fleet/exception/FleetHandoverPdaQuery.java` 及直接交接事实调用 | 客户从派送事实而非整车头部获取;保留未完成派送资源和完成时历史快照,总控分配 |
| `customervisit/service/CustomerVisitService.java`、`delivery/model/DeliveryStatusPolicy.java` | 已修状态门禁继续有效,签收/状态写入需共同锁入口;总控确认派送后端接管范围 |
| `src/main/resources/db/lastleg.sql`、`deploy/sql/头程数据库统一增量-MySQL8.sql`、IAM权限资源 | 总控唯一集成;按新基线收敛,不迁移/回填测试存量,不执行SQL |
| OpenAPI `overseas-business-v1.yaml`、`fleet-trips-v1.yaml`、`fleet-preparation-v1.yaml`、`appointment-work-v1.yaml`、必要新增 dispatch 文档 | 总控唯一集成;删除旧协议与消费者同批完成;统一Gateway既有last-leg通配应离线验证,不能凭路径推定运行可达 |
| `file` 附件提供者 | 共享整车BOL/附件若改变授权归属,先列出正式接口由总控分配;不把客户附件改为平台公共附件,本轮不改file代码 |
前端直接消费者已定位:Admin `overseas-warehouse/api/dispatches.ts`、`pages/DispatchesView.vue`、`pages/DispatchDetailView.vue`、`components/SmartDispatchDialog.vue`,以及 `overseas-master-data/api/trips.ts`、`components/TripPreparationDialog.vue`、`components/TripBookingPanel.vue`;PDA `src/api/fulfillment.js`、`src/stores/fulfillment.js`、`src/pages/dispatch/dispatch.vue`。归前端任务。
预约在途消费者只读列明:Admin `appointment-calendar/WorkDispatchForm.vue` 当前调用 drafts/pre-arrange 后弹车次准备和同仓共车,`WorkSharedTripForm.vue`要求两张客户排车,`WorkExistingDispatchForm.vue`仍以旧PENDING_DEPARTURE/workflow判断“继续安排本批车辆”。三者必须接入同一整车创建/加货及actions,保留事项弹窗关闭、原单跳转和已操作批次事实;总控分配接线,不由本任务覆盖。
脚本直接消费者已发现 `scripts/admin-test-env-modules/{grouped-dispatch-acceptance,dispatch-repair-acceptance,fleet-cross-customer-acceptance,fleet-cross-customer-fixture,fleet-external-dispatch-acceptance,fleet-fee-coverage-acceptance,fleet-booking-reservation-acceptance,fleet-return-redispatch-acceptance,fleet-handover-acceptance,fleet-trip-cost-acceptance,fleet-trip-fulfillment,phase3-outbound-dispatch,phase4-overseas-dispatch,phase5-overseas-fulfillment}.mjs` 等及其合同。这里只登记实际路径命中,不读取历史报告或执行真实HTTP;协议冻结后总控定向分配旧请求/状态更新,不能让旧fixture继续构造客户子排车。
### 8.3 结构变更给总控的清单
1. `ll_dispatch_order` 去customer,新增stage五阶段列、status收敛ACTIVE/CANCELLED、主版本、cargo修订/摘要、当前审核轮/依据、装车/发车/正常派送完成实际时间、备注;索引改仓/status/stage/计划时间及业务号,客户检索走item索引。审核详情可JSON但历史不可覆盖。
2. `ll_fleet_trip_dispatch` 去customer/review;一对一唯一约束;`ll_fleet_trip`新增临时资源快照/模式,允许新建草稿时计划、资源、卸货点未知,检查直接DTO/Mapper均不伪造默认值。
3. `ll_dispatch_item`保留customer,新增或明确稳定来源键/摘要,补全详情真实来源字段;索引按dispatch+customer+目的地及来源核对。物理托数与来源明细数分开统计。
4. `ll_dispatch_pda_task`去customer且dispatch唯一;pick/pick_order继续真实客户与来源;新增公共command(idempotencyKey全局唯一且operator不可改)及主单历史表,废除重复PDA整车命令记录协议。派送域持久待汇总信号表按6.5由派送任务设计、总控集成。
5. `ll_dispatch_draft`去客户头部,锁明细保留客户,补实物唯一活动锁;转换请求原子创建对应整车及Fleet。
6. `ll_dispatch_appointment_allocation`保留客户与逐来源箱数,不改成整车客户;全量替换时原子校验全车,必要索引加dispatch+customer+item。
7. 派送方同步将出库活动唯一键确定为 `(dispatch_order_id,customer_id)`,派送按客户+目的地;取消历史保持可追溯,不能以删除历史满足唯一键。费用和单据结构具体由另一文档给总控。
8. 全部中文表/字段备注、主外关联和索引同时进模块最新基线及统一结构脚本。无迁移、双写、别名、回填或测试存量修复;本清单不是执行数据库授权。
## 9 实施后的最小验证包(本轮未执行)
已有测试精确触点(相对 `lastleg-service/src/test/java/com/baiyue/lastleg/`):
| 测试 | 必须覆盖 |
| --- | --- |
| `dispatch/service/DispatchServiceTest.java`、`DispatchRepairWorkflowTest.java` | 同仓多客户多目的地一张真主单、空单再加货、来源不可伪造、跨仓拒绝、取消只释放本单、上一批换标全托/退货/合托修复 |
| `dispatch/controller/SmartDispatchControllerTest.java`、`DispatchQueryControllerTest.java`、`dispatch/DispatchSchemaContractTest.java` | 新API/五阶段/权限和去客户头部结构;草稿每容器一整车、不同客户同组 |
| `dispatch/controller/DispatchQueryControllerTest.java`及新增真实Mapper分页/统计用例 | status/stage正交,取消保留最后阶段;审核分区+状态SQL过滤、NOT_SUBMITTED不算PENDING、多客户一车只计一次、分页total和全基集统计/零值/一致快照 |
| `dispatch/DispatchCandidateMapperContractTest.java`、`DispatchPalletLockPersistenceContractTest.java`、`DispatchPhysicalWeightTest.java` | 实物别名排他、真实来源客户、重量未知不填零或材积重 |
| `dispatch/pda/service/DispatchPdaWorkflowServiceTest.java`、`DispatchPickOrderAttributionServiceTest.java`、`ReturnedDispatchAllowancePersistenceTest.java` | 未审核禁扫、后台不能补录、逐项核平、只扣一次库存、最后扫码不自动装车完成、跨客户来源、错仓/超量/同键异内容 |
| `fleet/trip/FleetTripPersistenceTest.java`、`FleetTripAuthorizationTest.java`、`FleetTripApiContractTest.java`、`FleetDispatchWorkflowQueryTest.java`、`FleetTripMatchedStopsTest.java` | 自动唯一关系、审核重提/关键修改失效、主档占用与资格、保留站点顺序/外接容量、临时ID为空及审核依据 |
| `dispatch/service/DispatchAppointmentCancellationPersistenceTest.java`、`inboundplan/work/AppointmentWorkDispatchBindingTest.java` | 跨客户batch不互删,旧取消后重排不占用失效批次,改批次版本拒绝,已接收门禁;后者写权需总控分配 |
| `fleet/trip/FleetTripCostPersistenceTest.java`、`FleetTripCostContractTest.java`、`FleetTripCalendarServiceTest.java`、`FleetTripCalendarMapperTest.java` | 附加能力保留;空计划不伪时间;成本实发事实及资源结束仍独立 |
| 拟新增 `dispatch/service/DispatchExecutionConcurrencyTest.java`、`DispatchReviewServiceTest.java`、`DispatchCommandPersistenceTest.java` | 双端同版本竞争只有一次装车/发车;同键原快照恢复;先派送后发车原子性;任一客户失败全车回滚;审核前后及取消/发车竞争 |
| 拟新增 `dispatch/service/DispatchDeliveryCompletionWorkerTest.java` | 信号提交后崩溃恢复、阶段CAS后ack前故障两者均回滚、重复信号/多实例、部分签收、重试/重扫、最后全签只CAS一次;签收持子锁期间不得回调申请父锁 |
派送方测试由其独占:`DeliveryTransferServiceTest`、费用覆盖/来源持久化、正常/部分/异常签收和汇总回调。共同集成应证明:未安排不可发车;部分/拒签/退回不自动DELIVERED;全部正常签收只推进一次且不释放资源;多客户同仓费用、来源和客户只读不串。
实现全部集成后,由本任务唯一串行执行后端 Maven `mvn -pl lastleg-service -am test-compile` 和对应行为测试(最终 `mvn -pl lastleg-service -am test`);先核对本批测试/基线稳定。总控集成后运行 Gateway 路由合同,新增Mapper运行 mapper-scan,跨包端口变化运行 lastleg-dependencies 检查。输入未变不重复跑。代码检查、真实HTTP、人工截图/PDA真机分别记录;本稿仅做源码只读分析,全部这些验证尚未执行。
## 10 需要总控冻结或裁定的具体问题
### 10.1 四项业务选择已确认,不再待问
正式契约第八节用户确认“四项都按建议执行”,替代前两轮选项表。本任务执行以下唯一基线,不再请用户重复决定。
| 场景 | 当前确定行为 | 本任务影响 |
| --- | --- | --- |
| 临时外配取证 | 建单人保存本趟真实容量/证照资料及预计任务结束,调度核实;空单可先保存,审核前补齐 | MASTER/EXTERNAL明确分离,不造主档;证据提供者变更交总控逐文件分配 |
| 实际装载核对 | 确认装车弹框接入既有实载,有依据数据带出、缺项按真实事实确认 | LoadingComplete携manifestHash和measurements;必须先核平PDA,不新增第五页签、不代填拣货 |
| 零扫码变更 | 保留原业务号,显式退回装车前,修改后两审重提 | ReturnToReview命令及历史;已有任何真实扫码/库存SHIP则不开放本批退装/回库 |
| 客户旧创建入口 | 整车安排仅平台执行,移除旧客户创建此类派送入口,客户保持自己单据读取 | 派送任务和前端任务按各自写权处理;不实现客户意图第二协议 |
新增预约明确属于日历,不在本任务设计、矩阵或实现范围;只保留整车改造影响的既有预约读取/关联,提供者未解锁前不修改。
### 10.2 总控工程冻结清单(无需用户重复裁定技术细节)
- 本稿已依据共同契约统一公开recordVersion、平台全局唯一请求键绑定主体、严格commandHash与arrangementBusinessHash及6.2授权恢复表;派送稿若尚保留expectedVersion或“同键跨主体也返回原结果”,由总控同步其唯一写者收敛,不让前端拼第三套协议。
- status/stage按第3节正交唯一语义、审核查询统计按4.5、命令GET及结果按4.3确定一套共同OpenAPI,前端移除旧状态和trip版本协议;这是数据/接口选择,不要求用户再选技术字段名。
- 锁协议采用6.3源码事实及6.4逐操作新顺序;其中库存position→balance、发车delivery→来源、签收delivery→来源已核对。预约/费用/其他主档入口反向加锁尚未逐一验证,须分配后验,不能标注“已无死锁”。
- 签收信号记录归派送,主流程worker/消费/重试/重扫及直接测试归本任务(6.5);接口包名选一套消费域端口,禁止双向具体实现依赖或为了编译加循环豁免。
- `AppointmentWorkDispatchBinding/Mapper/Port`及`WorkSharedTripForm`等预约触点、Client、File、脚本和共享SQL/OpenAPI/权限仍需总控精确分配唯一写者;保留预约保存/事项关闭/原单跳转及上一批真实来源修复。
- 旧多单Fleet prepare/bind/unbind配送协议收敛,PICKUP和外接/容量/成本/交接/资源结束保留原能力;原独立取消“必须unbound”改成父级协调,不新增已扫码撤销路径。本稿已只读比对派送稿,不修改另一文档、不跨对话发消息。
下游按第0节已落地骨架接入,不再以准备稿猜字段;实现范围以正式契约第九节为准,额外文件仍需总控精确分配。公共类型后续变更先更新交接点和哈希,再同步已发现直接消费者。
### 10.3 真实主单切片与精确集成依赖(2026-10-19)
2026-10-19补充作业公开DTO:新增`dispatch/port/DispatchWorkModels.java`,SHA256=`1e91da656e38aebbc554b4b4275b080d387e6bdb2eefaa14d5ae1ebd5b1aec64`。原13文件未改;新文件仅JDK依赖,确切record以实际源码为准:`Items(dispatchNo,recordVersion,status,stage,List<CargoItem>)`,CargoItem含真实dispatchItemId、真实客户、sourceKey/sourceVersion/sourceType、planPalletId/returnReceiptId/relabelNo、warehousePalletId/palletNo、orderNo/inboundCode、destination、scheduledPackages/pickedPackages/remove Gate;不能从orderDetails.sourceKey或warehousePalletId替代删除身份。`Route(dispatchNo,recordVersion,List<Stop(index,name,address,destinationKey)>,edit Gate)`使用真实Fleet持久顺序,0为起运仓,其余index可直接对应LoadingMeasurement.deliveryIndex;`RouteCommand(recordVersion,idempotencyKey,List<String> destinationKeys,reason)`只重排完整既有目的地,服务端保留真实名称/地址、起点及外接卸货点,采用既有Action.EDIT严格幂等。
新增已接线平台端点(D=`/api/platform/v1/last-leg/dispatches`):`GET D/{dispatchNo}/items`返回Items,`GET D/{dispatchNo}/route`返回Route,`PUT D/{dispatchNo}/route`接收RouteCommand返回CommandResult;读权限dispatch:list、改路线dispatch:edit。四详情对象不加第五页签。`GET D/{dispatchNo}/loading`及`POST D/{dispatchNo}/loading-complete`使用已冻结LoadingPreview/LoadingComplete/CommandResult;后者权限dispatch:loading-complete,显式确认前保持LOADING。
附件正式入口已接线:`POST D/{dispatchNo}/evidence/{kind}`,kind=`VEHICLE|DRIVER`,multipart字段`file`,权限dispatch:edit,返回`{fileId,fileName,contentType,sizeBytes}`;上传不自动替换主单引用,后续使用当前recordVersion的Update保存evidenceFileIds/evidence.fileIds。`GET D/{dispatchNo}/evidence/{kind}/{fileId}`返回同一元数据,`GET .../{fileId}/content`返回鉴权代理字节、inline Content-Disposition及no-store,读权限dispatch:list;不能使用匿名URL。内部File按平台0+新类别+真实dispatchId+fileId核验。File类别由总控新分配的派送后端补齐,本任务不修改File源码;本域新入口仍待离线/真实验收分别核对。
主单新增`loading_confirmation_json`精确字段,已纳入DispatchAggregate和saveState Mapper;内容是已冻结ConfirmedLoad完整快照。DispatchExecutionPort现由DispatchAggregateService实际实现,preview/lock/replay/fresh/recordArrangement使用同一主单、逐项真实扫码和不可变归属;新的DispatchExecutionReadMapper/Repository批量读取,不用计划数量凑核平。装车完成沿原Fleet容量策略并核对外接预订,保存实载但不调用库存SHIP。以上新输入测试正在运行,不用前一轮通过结果替代。
已经实施`DispatchAggregate`及其Mapper/Repository、`DispatchAggregateService/Controller`、`DispatchReadMapper`、`DispatchSourceMapper/Repository`,并沿允许的Fleet原生应用入口建立真实一对一资源记录。主单没有customer字段;同仓多客户只在真实明细保留归属。空单、选货建单、加货、分页和四对象详情、命令持久恢复已接线。候选返回共同`CandidateList`,按真实起运仓在SQL取有界多客户集合,来源摘要由当前库存版本、仓、收货组成、目的地及换标轮次生成。两级审核、驳回重提、资源编辑与零真实扫码退回已进入本域实现,新增验证仍进行中。
共享SQL精确输入:主单字段以`DispatchAggregate`实际属性为准,移除customer_id,trip_id唯一;Fleet计划、资源允许空值,`ll_fleet_trip_dispatch`移除customer_id/review_json并唯一trip_id;明细新增customer_name/source_key/source_version/source_snapshot_json;来源锁新增nullable且唯一active_warehouse_pallet_id,与customer_id/active_key唯一键共同防别名重复占托;不可变`ll_dispatch_history`字段id/dispatch_id/record_version/action/operator_id/reason/snapshot_json/occurred_at;命令表见0.2。路线须容纳多目的地真实地址,不能沿用短VARCHAR截断。未写共享DDL、未执行SQL。
本域新增临时资源证据适配`dispatch/gateway/DispatchEvidenceGateway`及`HttpDispatchEvidenceGateway`,只读写File现有通用内部业务文件路径。File提供者精确触点是`file/src/main/java/com/baiyue/file/service/BusinessFileCategory.java`:需要两个平台固定0、businessId为真实dispatchId、PDF/JPG/PNG、10MiB、POSITIVE_LONG类别`OVERSEAS_DISPATCH_VEHICLE_EVIDENCE`与`OVERSEAS_DISPATCH_DRIVER_EVIDENCE`,以及直接类别/归属测试和必要OpenAPI。该提供者未分配给本任务,未修改;由总控分配唯一写者。Lastleg按平台0+类别+本车ID+文件ID复验,不复用司机主档证照类别,不为临时输入自动建主档。公开上传/读取入口尚待接线;File类别和真实调用未验收,不把测试夹具的文件提供者模拟视为真实文件验证。
预约精确触点仍是`AppointmentWorkDispatchPort.bind/Binding/Mapper`:现接口按单客户调用且会删除整车所有分配,查询仍以头客户联接;不能跨客户循环调用或静默丢掉已有批次。本域暂明确拒绝有既有批次的建单/加货和车辆预约编辑;需要总控分配提供者最小适配后解除,不表示业务取消预约能力。候选appointmentBatches尚未填充,后续读取须同一权威提供者接通。
离线证据:首轮生产与全部测试源码编译通过,主单/公共合同/账本/查询及派送交付的19个直接类共144项中143项通过;唯一Merchant OpenAPI残留由总控处理,之后复测推进到第133行旧POST残留。主单3项实际MyBatis/H2事务测试通过,证明空单一车一记录、同仓多客户多目的地一头、过滤不缩减整车、原结果恢复及后项冲突全事务回滚;选货 authority 提供者当时为受控输入,不证明完整来源链。补跑旧回归66项有3项旧夹具缺新依赖,修夹具后Fleet57项全部通过,DispatchRepair还需补真实dispatch_no关联继续验证。Gateway路由合同5/5;Mapper扫描389个/10模块。新增审核和候选改动待下一次串行Maven,不把既往结果覆盖新输入。依赖分析旧fleet/pickup三项基线未改。
2026-10-19后续实现:`DispatchAggregateService`实际实现Execution端口,`DispatchCompletionService`实际实现Completion端口;`DispatchDeliveryCompletionWorker`有界读取到期信号、逐车新事务汇总、失败回滚后独立退避、按真实已签收版本重扫缺失信号。主阶段CAS、唯一完成历史、指定信号ack同事务;合法部分签收只ack本次通知,后续版本独立产生新信号;全部正常签收才DELIVERED,不释放资源、不二次发布来源/费用。
PDA实际Controller已切到共同DTO:GET根与单号返回DispatchViews.PdaTask;列表query使用stage;POST items/{itemId}/pick接收DispatchCommands.Pick;新增GET loading、POST loading-complete、GET commands/{idempotencyKey};POST depart接收DispatchCommands.Depart并返回CommandResult;旧/complete不再注册。身份由DispatchActorFactory.pda→PdaWarehouseIdentity取操作者及唯一绑定仓,请求不接受客户/仓。DispatchPdaQueryService+DispatchWholePdaReadMapper批量装配多客户明细/仓位/原生退货箱/真实归属,列表不逐车查详情。整体taskNo明确以排车业务号识别;底层任务现按dispatch唯一且不含customerId;taskNo直接使用dispatchNo,真实客户继续留在pick/pick_order及库存命令。
新增DispatchPickingService与DispatchDepartureService。扫码沿原InventoryCommandService、DispatchPickOrderAttributionService和原生退货生产者执行;实际来源订单先于库存锁,最后一箱只核平、阶段仍LOADING。版本化发车先根锁,再收齐所有出库/派送锁,再锁全部实际来源订单;调用原来源计数及转仓/换标/FleetPool生产者,不再扣库存;原命令恢复先于阶段资格。旧DELETE移货/取消已退出Controller,使用POST items/{itemId}/remove和POST cancel+ReasonCommand,释放精确原占用,旧键重放不能释放新车占用。实际扫码、发车及原提供者整链正在验证,不能将编译视为这些生产者已证明。
草稿唯一写权已移交原派送后端:Draft/Container实体及Mapper、SmartDispatchController、Draft专用Service/Repository/占用Mapper及直接测试;本任务停止写入。按派送设计第12节已补最小桥接:`DispatchService.lockDraftSources(String,List<CargoSelection>): List<WholeSource>`,MANDATORY,允许草稿逐托暂存换标但正式create仍要求完整申请;`DispatchAggregateService.lockDraftCreationResources(Actor,List<Create>): void`,MANDATORY,锁齐全批车辆升序→司机升序→车辆占用升序→司机占用升序,再取全批来源。转换里的新trip是当前事务创建且外部不可见的身份,正式create只重入已持资源身份锁,不在第二组取新资源。已移除旧DispatchService草稿读写/占用/分组转换公开方法及对应旧测试,不恢复Draft.customerId;旧单客户建单/Fleet适配尚待整体退出。
新增离线证据:最新完整Lastleg Maven在固定输入下生产及442个测试源码编译通过,53项中52项通过,包含主单/审核/真实明细与路线/显式实载/失败归属8项SQL测试、Schema中文注释3项;唯一Merchant第133行由原写者修正路径块提取,保留其他业务合法POST,后续新候选待复验。JDT曾把错误字节码写入target/classes,javap确认含Unresolved compilation problems;只对Lastleg target运行一次mvn clean后恢复编译,没有修改转仓/本土卡车源码或停止IDE。
随后在草稿在途输入之外,使用明确19个生产文件的javac独立输出及JUnit 1.10.3实际启动器运行本域23项直接测试全部通过:9项根/版本/审核/路线/实载/移货取消SQL、2项完成CAS与ack共同回滚及重试/部分签收、1项worker退避顺序、2项真实来源订单/库存/实收SQL与锁序、2项持久账本、5项证据归属/模拟HTTP下载MIME长度签名及业务错误、2项公共合同(16类请求缺/null/负/零版本、全部Action重启恢复)。这是固定本域快照,不是新增PDA/草稿完整Maven,也不把受控库存/归属/文件提供者当真实环境证明。后续新增PDA查询与扫码测试正在进行。
共享验证:IAM四类24项全部通过,输入未变不重复;File新证据测试在145/146/171/175行未处理IOException导致测试源码编译失败,已给原写者精确定位,本任务不改File。Gateway路由5/5、Mapper390个/10模块通过;依赖分析仍为原fleet/pickup三项失败,未加豁免,后续新Mapper输入需重新核对。
主要未闭环:既有预约/车辆预约权威写提供者仍按总控保护,禁止循环旧bind或静默丢批次;FleetTripDispatch旧customerId/reviewJson及旧单客户适配/直接消费者尚未完全收敛;草稿新候选及全域测试编译、实际PDA扫码/发车与全部正常签收联合验证尚未完成。所有结果均不表示已部署、真实HTTP、人工页面或PDA真机验收通过。
2026-10-19 16:58本域继续收口:`DispatchPdaTask`已移除customerId,TaskMapper只按dispatch读取,PickingService按根锁创建唯一任务并以dispatchNo作taskNo。新增双客户实扫用例验证一张任务、两条真实客户扫码、各自库存命令及最后扫码仍LOADING;H2用例有dispatch唯一约束。`FleetTripDispatch`已移除customerId/reviewJson,DispatchBinding/PreviousDispatch去客户头,新增FleetDispatchGateway.workflows批量从本域真实主单读取两级审核;Fleet详情/历史投影、拣货门禁不再读取绑定级审核。已撤下PlatformFleetTripController旧调度审核、理货审核及独立实载确认写入口;原公开Fleet资源/计划入口对已关联主单拒绝写,必须走共同主单版本与审核。公共原13文件和WorkModels未修改。余下旧手工绑定/prepare、外接来货入车及旧DispatchOrder适配正继续调整,不视为本批完成。
稳定草稿输入上的Maven:1056个生产源码及450个测试源码test-compile通过;31个直接类共178项,176通过,两项草稿失败为SmartDispatchControllerTest:65把非路由方法计入权限遍历,以及DispatchDraftPersistenceTest:151转换重启恢复的抽象Payload反序列化失败;失败报告交原写者,不修改其文件。主单双端发车竞争及源生产者失败全事务回滚2项均通过,明确源发布生产者在该用例受控模拟。File七类串行命令再次停于DispatchEvidenceFileTest:145/146/171/175四个IOException测试编译错误,未执行测试,输入未变不重复。
上述模型收口后PDA Maven34项出现13项非法DispatchPdaTask.class字节码VerifyError(本机JDT写target产生),不能视为业务失败或通过。随后在固定本域显式源码列表的独立javac输出中重编译受影响实体/Mapper/Service,运行JUnit真实启动器36/36通过:根SQL/审核/资源/路线/实载/取消移货9,完成事务/worker3,真实来源SQL2,共同账本2,模拟HTTP证据5,公共JSON/依赖2,PDA真实读1,PDA扫码3,批量资源锁2,PDA路由/DTO6,实际发车事务2。此轮Fleet历史审核已通过真实DispatchFleetAdapter.workflows→AggregateRepository→MyBatis/H2读取,不再模拟绑定级旧审核。仍需稳定后的全域Maven、最新正式SQL合同与附加能力集成验证。
保护范围精确触点:`inboundplan/work/FbaAppointmentExecutionAdapter.java:78`仍用TerminalEvidence.customerId决定整车归属且状态仍使用旧DEPARTED/PENDING_DEPARTURE/PDA_PENDING;`FbaAppointmentTransportAdapterTest.java:48`旧DispatchBinding构造器含客户参数,需原提供者在唯一写权下同步。TerminalEvidence本身尚未改,不能设置0、首客户或空值当整车客户完成收敛。实际客户仍必须从逐条TerminalDelivery/扫码/归属取值。
2026-10-19 17:08 File冻结修复验证:`DispatchEvidenceFileTest.java`当前SHA-256=bba87946457fb1290960218127087552de95b59f443eb6d5dacf354084d04a19,与总控候选匹配。唯一串行命令`mvn -pl file -am '-Dtest=DispatchEvidenceFileTest,BusinessFileStorageTest,InternalBusinessFileServiceTest,InternalBusinessFileControllerTest,DriverLicenseFileTest,TripOperationEvidenceFileTest,VehicleCarePhotoTest' '-Dsurefire.failIfNoSpecifiedTests=false' test`实际49/49通过,其中证据新类别12/12。输出`.logs/dispatch-file-fixed-tests.log`,JUnit报告`file/target/surefire-reports/`,输入未变不重跑。草稿当前稳定摘要b0db1bb5191fa3578dacfa0f07c7c2a6a30346f0198047e34fc1fe3a99b0e554及17项待下一Lastleg编译窗口,不将写好当通过。
36项固定输出证据位于`lastleg-service/target/dispatch-owned-compile/model-tests.log`(SHA-256 325ccd6c326aee5465639e5b017c46ba5f641b8f9268e81b6b7e9238e3046084)、`model-36-evidence.json`(当时仍未变化的10份PDA/测试源码指纹及范围说明)、`verified-36-classes.jar`(SHA-256 43d626ac44389dbbe9ee522a832b980e0a6b85dbedb9b6cb7f2c20d68dcd7ff9)。后续Fleet适配/附加能力接线不由该结果覆盖。
Fleet现继续按真主单收敛:`FleetDispatchGateway.Snapshot(dispatchId,dispatchNo,warehouseId,packageCount)`与`TerminalEvidence(dispatchNo,warehouseId,shippedPackages,deliveries)`、`FleetTransitEvidence(dispatchNo,warehouseId,shippedPackages,deliveries)`均去客户头;逐行TerminalDelivery/Delivery.cargo保留真实客户。SourceCargo结构未变,读取改为`sourceCargo(dispatchNo,customerId)`,客户参数仅由服务端真实货物/预订归属传入;`customers(dispatchNo)`返回本车真实明细客户。DispatchFleetAdapter不再读旧DispatchOrder或旧客户PDA任务,交接/结束读取所有客户出库及所有派送并逐客户核平,先全部outbound后全部delivery锁。正常全签后退回仍保留原已履约,不从主单客户裁切全车。在途更换只更新对应未终结客户派送。
旧Fleet主流程写协议已撤下:POST fleet/trips、POST /prepare、GET /{tripNo}/dispatch-candidates、POST /{tripNo}/dispatches/bind、POST /{tripNo}/dispatches/unbind、POST /{tripNo}/dispatches/{dispatchNo}/review、POST /{tripNo}/loading-review、POST /{tripNo}/loading。旧PreparationService及旧PDA list/task/pick/complete/depart应用方法退出,PDA SourceWorkflow仅保留真实来源发车计数/状态生产者。外接预订bind/arrange保留,但只核对/加入该Fleet已唯一关联主单,不创建或挂入第二张客户排车;普通取货createPickup保留。`PlatformFleetCapacityOfferController`arrange-dispatch已把旧smart-dispatch改为当前dispatch:create,并继续要求原capacity-offer manage、booking-edit、trip-edit。共同OpenAPI/保护中的预约提供者/外部前端入口由总控协调,当前尚未全域编译/回归完成。
受保护生产直接消费者新增精确交集:`FbaAppointmentTransportAdapter.java:95/102`调用已退役FleetTripService.unbindDispatch/bindDispatch;`FbaAppointmentExecutionAdapter.java:87`调用已移除TerminalEvidence.customerId。不得恢复旧头字段、循环旧bind或加成功空实现。旧手工H2与Fleet/预约直接测试必须按新模型继续调整,当前36项不能替代这些回归。外配任务结束现在不对不存在的主档ID释放占用或修改主档状态,仍保存真实结束时间/地点与状态;待直接测试。
2026-10-19 既有预约接线取得用户授权后的公共合同:`DispatchContracts.BatchAllocation(planPalletId,batchKey,customerId,sourceKey,destinationKey,packageCount,Long recordVersion)`及`BatchReference(batchKey,batchNo,customerId,sources,Long recordVersion)`末尾增加权威记录版本,compact constructor拒绝缺失/null/负数、0合法,不提供旧签名重载。FBA引用取原预约版本;自动DISPATCH引用取实际对应整车recordVersion,不伪造FBA版本,也不接受客户端以自动引用替代FBA分配。DispatchContracts.java SHA-256=73b5b83fcd0155bf09b18c18b1bd6a5bbb0175221102a13101248f92ca84f641。其余原公开DTO当前未改,原13文件“全部不变”指纹表从本次字段变更起只作历史基线,不再代表当前。
新增JDK内部端口`dispatch/port/DispatchAppointmentAmendmentPort.java`,SHA-256=45aca62fa8a52f3b97a3e666c87b85d2ae0ca5372ca46e1c29ef76f27887b238。精确方法为`void lockExistingAppointmentDispatches(Actor,List<String> dispatchNos)`和`CommandResult applyExistingAppointmentChange(Actor,String dispatchNo,ReasonCommand identity,List<PhysicalItem> touchedItems,List<BatchAllocation> expectedAllocations,List<BatchAllocation> nextAllocations,boolean removePhysicalItems)`;PhysicalItem为`(Long itemId,String customerId,Long planPalletId,String sourceStage,Integer packages)`。两方法MANDATORY内部协作、不注册HTTP;先全范围trip→全部资源→全部dispatch,再全部必要子单→批次→来源→协调guard。ReasonCommand为本车公共版本+原父预约命令键,内部按父键/真实操作者/本车派生稳定子键,共用公共账本并优先恢复原结果。expected/next只接原权威scope,必须逐项核DB真实明细/原分配及完整实物,BEFORE_LOADING/零真实扫码/无下游执行;移客户货物不解绑或取消整车。端口源码先交付,实际实现和主流程接入正继续,不能据接口存在推定已完成。
获得最小写权的ExceptionOrderService.java:548已将任务查找改为findByDispatch(dispatchId),后续本客户pick/item/归属过滤保持;直接ExceptionOrderDispatchReturnSourceTest仅移除两个任务头客户setter并收敛两个mock调用,保留该文件此前未提交业务修改。异常原箱Mapper、客户进度、库存发运证明及派送Mapper中旧头客户SQL仍需总控独占分派,不顺手扩写。
本次公共版本字段变更前的独立1052份源码构建(明确排除原预约ExecutionAdapter/TransportAdapter及当时未获写权的ExceptionOrderService,不是全服务Maven)运行62项,57通过,仅Fleet权限类5项缺新增Gateway测试Bean;补真实方法安全上下文依赖后该5项单独5/5通过。草稿新17项、主单/PDA/发车、SQL实体合同3项及Fleet审核只读1项在57通过之内;输出`target/dispatch-owned-compile/fleet-draft-tests.log`、`fleet-auth-tests.log`、输入`draft-input-evidence.json`(实际13/13及聚合b0db...554匹配)。后续公共预约版本字段、Provider及Fleet在途适配修正未由该结果覆盖,最终Maven仍须串行重跑。
2026-10-19 17:39 IAM权限新输入串行验证:`mvn -pl iam -am '-Dtest=Phase5DeliveryPermissionSqlContractTest,Phase5DeliveryPermissionSqlExecutionTest,AuthorizationSnapshotServiceTest,IamOpenApiContractTest,OverseasPhase4PermissionSqlContractTest' '-Dsurefire.failIfNoSpecifiedTests=false' test`实际29/29(1+5+7+5+11)通过。源码与target/classes/db/lastleg-permissions.sql SHA-256均为9deef80d2bcf383918b5ad48a63bea893ced2d9a32528e33268c02e73bbd4f67。输出`.logs/dispatch-iam-retired-smart-tests.log`;报告`iam/target/surefire-reports/`。File49当前输入未变,本轮未重跑。
预约接线正在实施:已新增`DispatchAppointmentAllocations`按Provider实际record字段顺序逐字段映射(Provider版本在第3字段,公共DTO在末尾),一次合并当前保留分配+新请求版本预锁,缺失/负数/同批混版本拒绝;create/add与草稿全groups预锁位于来源锁前。仅将已保存DispatchItem的真实客户传给bindItems,touched增量保留他人。源码已增加Fleet全范围父级/全部资源预锁及主单排序锁、内部预约改量端口实现:原主版本/零真实扫码/BEFORE_LOADING、完整实物及原分配集合复验、稳定父键子命令恢复,移出不解绑/取消整车,主单/来源/审核/历史随父事务回滚。新测试与整体验证尚在补齐;候选真实批读仍待Provider实际薄签名后接入,不能将这些源码视为已编译通过或链路完成。旧DispatchService.preArrange及两个私有单客户创建实现已移除,不恢复Provider旧bind/requireReplay;BOL仍待从旧platformDetail读取切到整车投影,旧测试和残留DTO同步继续。
@@ -0,0 +1,620 @@
# 排车列表派送费用接口设计
> 2026-10-19 已按正式契约第八至十节解锁首批实施。本文保留设计依据,实际骨架与本轮实现交接见第10、11节;与旧准备措辞冲突时以正式契约及实际共享骨架为准。Java编译/单测由主后端统一执行,尚无本轮部署或真实验收结论。
业务唯一基线为[排车列表统一作业改造契约](排车列表统一作业改造契约.md)。本任务为 `01a1524f-56a9-7320-a5fd-8ff76fa4356b`,总控为 `01a15230-a9d6-7503-a8a9-d70691df49e5`;主流程后端为 `01a1524f-4f11-70c2-8a46-8e06e73a2d86`。本文件只提出 `delivery/`、必要 `financefee/` 和 `FleetBookingFreight.java` 的接口、数据及验证方案;共同 OpenAPI、权限、SQL 由总控集成,主流程类由主流程任务实现。
## 1 改造前核对与本批差异
下表路径相对 `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/`,记录实施前的源码定位,不是当前实现或部署完成证明;旧单客户转换类/DTO已按第10节清除。
| 当前入口 | 当前行为与必须调整之处 |
| --- | --- |
| `delivery/service/DeliveryTransferService.platformTransfer/transferResolved` | 先锁全局排车,以 `DispatchOrder.customerId` 作为所有明细、出库和费用的客户;一个排车生成一个 `WAIT_OUTBOUND` 出库头,再按目的地生成派送单。当前未要求先确认装车完成,与新阶段不一致。 |
| 同类 `validateTransferFees`、费用发布循环 | 全请求按 `direction:feeType` 去重;普通费用只挂第一张或第一个相关目的地派送单,不能表达同车多客户多目的地分别收费。 |
| `delivery/mapper/OutboundOrderMapper` | `findByDispatch/lockByDispatch` 带客户且 `LIMIT 1`,可作为“每客户一张出库单”查询,不能充当新整车唯一出库查询。 |
| `delivery/service/DispatchCargoSourceQuery`、`DispatchFeeCargoMapper` | 普通整托按库存组成及本次已拣恢复来源,核平每条排车箱数;换标、退货使用专用事实,不能改回展示入仓码或计划托单一来源。 |
| `fleet/trip/FleetBookingFreight.preview` | 单客户参数;按真实入仓码找外接预订,检查 BOUND、车次/排车、目的地、实收托盘及数量、确认版本、约定币种和价格,返回报价及摘要。明确零约定只记商业事实,不发布零费用。 |
| `delivery/service/DeliveryFeeCoverageService` | 单客户查询 Finance;核对费用 ID/版本/hash/状态和货物 hash。引用服务仅为派送、装车、买约;全相关货物已覆盖才免新增应收,供应商应付独立。 |
| `delivery/service/DeliveryExecutionGuard` | 按一张客户出库核对派送覆盖、客户、数量和未执行状态;新整车应遍历完整客户出库集合并核对来源集合,不能只比较总箱数。 |
| `delivery/service/DeliveryDocumentService.save` | 显式 READ_COMMITTED,先锁本派送;首次签收资料保存要求真实 OUTBOUNDED,校验文件归属及版本/请求键,写 signedAt/signedPackages、资料版本、完成 Outbox、回访。存在真实退回时可签剩余部分。 |
| `delivery/service/SourceDeliveryCompletionQuery` | 调用方先锁自己的派送,再一次锁齐同客户全部相关来源订单(数字 ID 升序);历史派送/排车/异常/库存只读,不反向加锁。用于跨多次发运证明头程来源全签,不能用一趟车全签替代。 |
| `dispatch/fleet/DispatchFleetAdapter.completion`、`fleet/trip/FleetTripCompletionService` | 旧结案允许实签加真实退库等于实发;不是本批五阶段“全部正常签收”的判据。保留附加结案及资源释放能力,但不拿该结果自动映射本批派送完成。 |
| `delivery/service/DeliveryTransferService.cancelOutbound` | 按 dispatch→outbound→delivery 锁序;已拣/已发禁止取消,车次须先解除;恢复来源原状态、清空关联、增加版本;只申请作废未履行的有效派送费应收,其他费用保留。 |
| `delivery/controller/MerchantDeliveryController` | 客户列表/详情/签收资料严格取身份客户;当前另有客户 POST 创建接口,直接调用单客户转派送。该写入口与本批“后台安排整车派送”需要总控裁定收敛,不能悄悄开放整车操作。 |
已观察到 `DeliveryTransferService`、`DeliveryFeeCoverageService` 有 Service 直调 Mapper,`OverseasFeeBusinessGuard` 有 JDBC。实施触及的方法须按后端指引收敛为 Service→Repository→Mapper,并补中文方法/关键规则注释;本轮未整改,不扩展无关财务业务。
## 2 推荐单据结构与归属
### 2.1 整车、客户出库、目的地派送
推荐保留客户出库头模型:**一张整车排车 → 每客户一张出库单 → 每客户每目的地一张派送单**。不把出库头或费用的 customerId 写成平台 0,也不选第一个客户代替其他客户。
示例仅说明数量关系:同车 A/ONT8、A/LAX9、B/ONT8 三组货物,产生 A、B 两张出库单和三张派送单。同一目的仓的不同客户永不合单;每张费用的客户必须与其业务派送单一致。
- `ll_outbound_order` 保留真实 customer_id、dispatch_order_id/dispatch_no、仓及 `DISPATCH_DELIVERY` 类型。冻结提案为 `UNIQUE(dispatch_order_id,customer_id)`,约束语义与现有反序唯一键相同,不同时新增冗余反序索引;整车出库集合的 customerId 必须精确等于货物客户集合,每客户恰好一张,仓及排车引用一致。所有整车读取改为集合查询,不使用第一张出库单代表全车。
- `ll_delivery_order` 保留真实 customer_id、所属客户出库、整车排车、目的地、地址及联系信息。保留 `UNIQUE(customer_id,outbound_order_id,delivery_group_key)`;每个“客户+目的地”恰好一张,客户与所属出库相同,整车派送组集合与货物组集合精确相等。取消历史不删除、不靠清空关联绕唯一键;本批没有取消后新建第二次安排的协议。
- 明细必须保存原排车明细标识及不可变实际来源关联;出库及派送都能由该关联还原每个客户、来源订单、来源入仓、实际箱数。不得仅从 `ll_order.outbound_order_no/delivery_order_no` 当前指针还原历史。
- `deliveryGroupKey` 延续既有目的地键:FBA `CODE:<大写仓码>`,私人地址 `PRIVATE:<trim地址>:<trim邮编>`;仅有内部目的仓 ID 的情况需由主流程提供真实目的地,缺失阻断,页面不能展示 ID 回退。避免同时存在旧 CODE 和新 FBA 两套键;外接 `destinationKey` 与派送键只做显式、可测试的领域映射。
- 对外预览的 `groupKey` 是客户与上述目的地的稳定摘要,包含 customerId;请求不能靠换 customerId 或 destinationKey 把一组货物移给另一客户。服务端完整重算分组,组集合必须与实际货物精确相等。
- 物理托盘数按真实仓托盘 ID 去重;逐客户、逐目的地货物行不可当整车物理托数直接相加。实际重量/体积沿主流程确认值,不拿计费材积重补实测值。
- 安排时只映射已完成的真实 PDA 拣货事实,不生成第二套 PDA 出库任务。普通 `DispatchPdaWorkflowService.pick` 已在扫码事务调用 `inventory.allocate/pick/ship`;退货换标由专用库存入口完成实际扣减。安排、装车完成和实际发车均不得再次调用这些已完成数量的库存 `ship` 或其他扣减命令。
- 本稿的 **picked→shipped 仅指 `ll_order` 业务履约计数及单据快照转换**:`DispatchPickOrderAttributionService.depart` 锁来源订单,再调用 `LastlegOrderMapper.transferPickedToShipped` 将订单 picked_package_count 减少、shipped_package_count 增加、设置出库关联;它不是库存余额/仓位变更。发车仅对真实归属拣货执行一次该业务更新、更新客户出库/派送和整车阶段,全部客户同事务,任一失败全车回滚;扫码已经提交的库存事实保持,不因失败重做或伪造退库。
- 出库明细已拣计数只来自对应客户、明细及来源的真实拣货,不能直接把计划箱数填成已拣,也不可表单补录。发车更新此类快照不增加任何第二笔库存流水。
### 2.2 整车安排记录(提交总控的结构提案)
已落地delivery域 `ll_dispatch_delivery_arrangement` 的Entity/Mapper/Repository:唯一 `dispatch_order_id`,保存整车依据、business_hash、首次请求键及操作者、完整结果与来源JSON;具体列见第11节SQL提案。严格commandHash及每次请求结果使用主流程全局唯一键共同账本,不在安排表复制第二套命令协议。
结果引用各客户出库和各组派送;出库头不新增冗余arrangement_id。出库明细保存dispatch_item_id及真实source_attribution_id、source_order_id、source_inventory_position_id、source_return_receipt_id、source_return_carton_id,避免混托/退回消费者仅凭展示入仓码猜来源。完整结果和cargo_json用于整车精确集合核对。不得仅以“有任意出库单”表示安排完成。
必须有同一排车唯一安排、全局请求键共同账本和子单唯一约束三层防重复。正式契约已选定全局唯一idempotencyKey,不按客户/操作者分片;安排表original_command_key也唯一。键对应原主体、动作和排车不可更改,复用别人的键拒绝;新键同业务经当前权限及版本核验只引用原事实。实际调用DispatchExecutionPort.replay/recordArrangement,不在delivery自建主体校验账本。
## 3 待冻结 API 与 DTO
下列均为拟议契约。统一平台前缀 `/api/platform/v1/last-leg`,复用 Gateway 已有 Lastleg 路由;本轮未改 Controller/OpenAPI/权限。
| 方法与路径 | 请求/返回及权限建议 |
| --- | --- |
| GET `/dispatches/{dispatchNo}/delivery-arrangement` | 新增组合预览及业务事实恢复入口,`dispatch:list`。返回阶段、recordVersion、装车完成事实、canArrange/blockReason、cargoHash、groups、各组外接报价/原费候选/应填服务、已存在的安排结果。一次 GET 内共享同一 Lastleg 只读快照,前端只调用这一次,不再并发两个辅助 GET 拼不同版本;恢复不依赖客户端重组结果。严格命令原请求/原结果另受命令主体授权,不因 list 权限开放别人的原请求。 |
| POST `/dispatches/{dispatchNo}/transfer-delivery` | 复用路径,替换旧单客户 DTO 为整车安排请求,独立 `dispatch:transfer-delivery` 权限。只允许平台且装车后、未发车;不接收顶层 customerId、货物数量或车辆司机覆盖值。 |
| GET `/dispatches/{dispatchNo}/external-freight` | 现有只读辅助入口按客户和目的地分组返回,报价增加真实 customerId/groupKey。与组合预览共用同一查询,不维护第二种算法。 |
| GET `/dispatches/{dispatchNo}/fee-coverage` | 现有只读辅助入口按客户和目的地返回货物/原费用候选;保持平台权限,不能将整车 Finance 费用候选暴露给客户。 |
| GET `/delivery-orders`、`/delivery-orders/{deliveryNo}`及资料接口 | 平台沿现有权限与客户定位,客户沿身份客户过滤;新结构不改变单张派送资料的归属。客户只读响应不带其他客户出库、派送或原费用快照。 |
拟议记录(名字和 JSON 字段供总控冻结,整数 ID 对外按既有 Long 字符串约定):
```text
ArrangeDeliveryRequest {
idempotencyKey, recordVersion, cargoHash, loadingCompletionHash,
groups: [ {
groupKey, groupCargoHash,
plannedDeliveryAt, deliveryMethod, waybillNo, carrierName, pickupMethod,
loadingType, vehicleType, vehicleSize, appointmentAccount, sellerName, remark,
externalFreightHash, feeCoverageCargoHash,
feeCoverage: [{ financeFeeId, sourceVersion, sourceHash, services }],
fees: [ FeeItem ]
} ]
}
ArrangementResult {
dispatchNo, recordVersion, arrangementKey, cargoHash, arrangedAt,
outbounds: [{ customerId, customerName, outboundNo, status, packageCount, palletCount }],
deliveries: [{ groupKey, customerId, customerName, outboundNo, deliveryNo,
destinationWarehouseCode, destinationWarehouseName,
destinationType, deliveryAddress, status, packageCount, palletCount }],
}
CommandResult { dispatchNo, action, idempotencyKey, recordVersion, status, stage,
occurredAt, effect, counts, result: ArrangementResult, replayed, alreadyArranged }
```
- `FeeItem` 复用现有费用字段:类型、名称、方向、币种、金额、数量/单位/单价、期间、供应商、结算方式、直接已付信息及凭证;按组确认,不再把整车总金额默认挂第一客户或第一目的地。每组 `(direction,feeType)` 唯一,整车不同组可重复同类型。
- 对外安排请求只用 `recordVersion`,0 是合法首版;无 `expectedVersion` 别名。内部锁/CAS 参数如叫 expectedVersion 仅表示预期含义,不进入公开 JSON。派送资料等本批实际触及 DTO 的版本命名也由总控统一收敛,不把当前源码字段当作新契约别名。
- 车辆司机只从主流程已确认快照复制(包括真实临时外配信息和空主档关联),安排请求无权改派。`carrierName` 等派送字段不得反向修改整车资源。
- 返回所有出库和派送单,不保留单个 `outboundNo` 作为多客户响应别名;Admin、恢复逻辑及脚本同批更新。`replayed` 仅表示原严格命令重放;`alreadyArranged` 表示查到既有整车安排而未再次建单,两种情形按第5节区分。不可变动作结果中的 recordVersion 是原动作版本;组合 GET 的顶层 recordVersion/stage 才是当前事实,前端不能用旧结果覆盖当前详情。缺失业务编号显示“—”,内部 arrangement ID 仅用于技术关联。
- 既有费用更正继续走正式来源更正,不通过换请求键重新安排、重发外接报价或重建单据。
- 用户已确认本类整车派送仅平台安排。本轮已删除Merchant创建POST及merchantTransfer服务入口,保留客户列表、详情、签收资料及下载。Client直接消费者由前端任务删除,共同权限/OpenAPI与脚本由总控集成,不保留另一套客户部分安排协议。
组合 GET 拟在一层 `REPEATABLE_READ, readOnly=true` 事务里一次读取整车上下文、全部客户货物、子单、费用本地快照,再按该上下文生成分组与本地摘要;内部查询必须加入同一事务,不各开快照。Finance 远程候选无法参与 Lastleg 数据库快照,按客户带费用版本/hash及读取时间返回,POST重新确认,不声称跨服务同刻快照。组内缺来源/报价变化/候选不可用分别返回结构化 `blockReasons`、`sourceComplete`、`feeCoverageStatus`,不把失败转成已覆盖;需要该证据的确认必须阻断。前端不能在同一弹框重复辅助 GET 另拼资格。
## 4 来源、报价与费用校验
### 4.1 实际货物摘要
主流程提供不可变、已核平来源行:`customerId, dispatchItemId, sourceStage, orderId, sourceRegion, sourceInboundId, inboundCode, warehouseId, warehousePalletId, palletNo, destinationKey, packages, pickId/attributionId, inventoryPositionId, receiptId/returnReceiptId`,以及退货/换标所需真实箱和数量引用。不能因为某类没有头程来源 ID 就伪造一个。
排车明细箱数、真实拣货箱数、来源归属箱数按“客户+排车明细”逐条相等,明细集合也相等;同托多来源全部保留。排除展示 `MIN(inboundCode)`、订单声明 SKU 箱数、FIFO 猜来源。装车后费用范围以本趟冻结拣货为准,不能把该托后来新进的可用库存算入本次派送。
`cargoHash` 应按稳定字段、明确 null 语义及固定排序计算;排序至少按 customerId/dispatchItemId/attributionId。分组 hash 包含客户、目的地、实际来源及数量;装车 hash/事实版本单独保留。规范化仅对契约声明无序的组、费用及选择集合排序、金额固定精度序列化;不能把有业务意义的顺序或原载荷值丢掉。
两类摘要职责严格分开:
- **commandHash**:动作 ARRANGE_DELIVERY、排车号、可信原请求主体(userId/appCode/客户范围/PDA绑定仓如适用)、原始 recordVersion、完整规范化请求载荷(含所有业务与证据字段)。请求键作为独立唯一键;除该键外不删除 recordVersion、操作者或请求字段。角色/权限每次读取实时验证,不把旧角色 hash 当当前授权。原键要求主体、动作、单号、版本、载荷全部相同。
- **arrangementBusinessHash**:排车号+货物/装车依据+全部客户目的地派送信息+费用内容和引用证据,移除请求键、操作者及纯并发 recordVersion。仅用于同车已有安排与另一请求键的业务等价判定及防重复;不能用它验证原命令重放、越权主体或旧版本。
请求 DTO 不接受客户端自报上述两个可信摘要;由服务端计算。前端保留原载荷、原 recordVersion 和键,未知结果不自动改版本再重试。
### 4.2 外接实收报价
- `FleetBookingFreight` 以真实客户分片接收来源和绑定上下文;Quote 增加 customerId/groupKey,按 `(customerId,inboundCode)` 识别,不能用全车 inboundCode 集合跨客户免收费。
- 保留 BOUND、排车及车次身份、预订 recordVersion、实收记录、完整托盘数量、目的地、PALLET/整单计价和 CNY/USD 校验。预览 hash 包含客户及主流程货物 hash;确认前在整车父锁协议内重验,报价/实收变化一律冲突,不补造库存。
- 正数约定只发到同客户同目的地派送,费用键基于真实 bookingNo+本趟排车+组+FREIGHT,稳定且与操作者无关;现有费用命令即使包含 operatorId,整车安排唯一事实也必须阻止换人重复发布。
- 明确零约定保存确认操作和来源版本,不发布零费用。全部为外接已约定来源的组禁止另填派送应收;混托普通来源仍按该组未覆盖的真实普通货物收费,不能整托免单。
- `priorInboundCodes` 按客户查询原有效派送应收;未确认作废前保持阻断。申请撤销、超时、拒绝均不能当作已作废再次收费。
### 4.3 原费用覆盖与新增收费
- Finance 仍按既有内部批量只读契约,每客户查询真实头程 sourceInboundId;不跨库、不扩大 Finance 账务模型。只有请求确实选择原费覆盖时才强制 Finance 可用,不能在失败后静默认定已覆盖;未选择覆盖的预览也应明确候选加载失败。
- 确认复核 financeFeeId、customerId、sourceInboundId、sourceVersion、sourceHash、原费类型/状态/币种及实际货物摘要;跨客户费用或过期证据直接拒绝。该协议是确认时有效快照,之后财务更正不追溯改写发运,不声称拥有跨服务数据库原子锁。
- 覆盖选择在客户内按 `(sourceInboundId,service)` 去重;同一真实原费覆盖的来源分到多个目的地时允许分别引用证据,不能据此复制原费用。每组计算未覆盖来源,不能用“全车 coveredServices”免除另一客户或目的地应收。
- 原费只证明明确服务覆盖,不复制费用、不按原金额抵扣、不生成伪零费用。新增派送应收仅针对未覆盖普通来源;散装/混装装车费、买约费沿现有规则逐组核对,买约仍要求卖家。
- 供应商应付独立,不能因客户原费覆盖而免掉。金额必须正数,费用币种 CNY/USD,已付凭证继续按真实客户/来源校验,不伪造支付。
- 每笔费用 `businessType=DELIVERY_ORDER`、businessId/businessNo 为本组派送;customerId 与该派送相同。只有来源唯一时附 orderId/inboundCode/集装箱引用;多来源不借第一票展示码冒认归属,由派送及冻结来源明细证明范围。
- 费用来源、自动审核、不可变 Outbox 与安排单据处于同一 Lastleg 事务;Finance 入池经现有投递、幂等和 ACK。安排成功只代表本地费用与 Outbox 已保存,不代表 Finance 已到账、已收款或已结算。
## 5 事务、幂等与锁顺序
### 5.1 安排与发车
采用显式READ_COMMITTED写事务;正式契约第九节已选定 **trip→车辆→司机/资源→dispatch**,取代准备稿的相反序列。先非锁定定位父身份,锁后重验一对一关系;delivery只调用实际DispatchExecutionPort.lockForArrangement,不自行取得或重排父/资源锁。安排与发车先收齐全部客户出库/派送锁,再来源/费用;尚未完成联合并发验证,不能宣称全域无死锁。
严格命令与业务重复的处理:
| 场景 | 授权与结果 |
| --- | --- |
| 同键、同主体、同原版本/完整载荷 | 每次先核验当前平台写权限及合法范围;commandHash一致才返回该命令原不可变结果,`replayed=true`。命令恢复在首次写入版本/阶段检查前,允许原命令后阶段已变化;不再创建单据、递增版本或发布费用。 |
| 同键、不同动作/单号/原版本/载荷 | 409,不能拿相同 businessHash 豁免严格冲突。 |
| 同键、不同操作者/主体 | 403或不泄露原内容的冲突,禁止读取或借用原请求。其他操作者即使有安排权限,也不能重放别人的命令;正式审计读取如有既有独立权限只读原证据,不获得执行身份。 |
| 新键、同车同业务、同或不同操作者 | 当前主体须具有安排写权限,recordVersion须为当前版本;锁内比 arrangementBusinessHash。既有安排完整有效则只引用原事实,`alreadyArranged=true,replayed=false`,在共同命令账本保存本主体此次“引用既有安排”不可变结果,不增加主版本、不产生新费用。以后重放此新键仍按其自身 commandHash。 |
| 新键、同车不同业务或旧版本 | 409,费用调整另走正式流程,不能第二次建单。新键使用旧版本即使业务相同也先冲突,不自动刷新版本;用户读取当前事实后才形成明确的新请求。 |
| 原安排取消/失效/缺子单 | 严格原键仍可取原不可变动作证据,当前状态通过GET另查;新键不得把它报作有效已安排,也不补建残缺集合。GET返回实际状态/缺项并阻断新写,等待正式业务处理。 |
安排首次写入顺序:当前身份授权→父锁→严格命令恢复/全局键归属→recordVersion与装车后资格→核对全车来源快照/分组→锁或创建**全部**客户出库及派送→锁齐本次需要更新的来源订单/换标/转运→来源关联→逐组费用/Outbox→主流程 `finishArrangement`→完整命令结果。不能每组“锁来源、写费用后再去锁下一组派送”;全部子行先于任何来源写锁。新建子单此时未提交不可能合法签收,已有安排在恢复分支返回,不对同一事实重复执行此链。
发车顺序:父锁→命令恢复/当前版本→资源/审核/PDA核平及预约批次复验→锁齐完整客户出库/派送并核对来源集合→`DispatchDeliveryPort.markDeparted` 写已锁子单→主流程 `DispatchPickOrderAttributionService.depart` 按真实来源逐单转换**订单履约计数**及换标/转运/Fleet履约事实→整车阶段/唯一历史/命令结果。后段不得再获取一张此前未锁定的派送行;安排、装车、发车均不执行普通扫码已经完成的库存 ship。
所有客户、所有目的地、全部来源绑定、费用来源/Outbox和主单CAS均在一个 Lastleg 事务内;任意一笔失败全体回滚,不能逐客户 REQUIRES_NEW 提交。数据库唯一键竞争用当前读确认 commandHash/业务hash及完整数组结果,不能依赖旧快照或吞掉部分写失败。未知结果保留原键,业务组合 GET 可查既有单据,原命令查询/POST重放才证明该次操作归属;404或查到相似单据不能当原命令成功。
列表和组合预览批量查询,不逐行请求详情/附件;资格只是展示,写入必须重验。不得在锁内投递 Finance HTTP 写命令。Finance 原费只读确认如放在锁内必须有现有超时并失败回滚;可先预检,再在锁内做最终只读复验,不把锁前结果冒充确认结果。
### 5.2 本轮沿代码核对的实际锁点与拟收敛执行链
| 入口及当前实际锁点 | 本批精确收敛要求/唯一写者 |
| --- | --- |
| `FleetTripExecutionService.depart` 当前先trip,后车辆及资源,再 `DispatchFleetAdapter.manifest` 的 dispatch→outbound→task→delivery;随后子发车 | 正式共同根锁保持trip→车辆→司机/资源→dispatch,预约批次按batchKey固定顺序,完整客户子单先于来源锁。主流程所有入口须复用同序列,不能回退准备稿trip→dispatch→资源。 |
| `DispatchPdaWorkflowService.pick` 当前 dispatch→task→`requirePickingApproved`内binding;`preparePicking`再锁来源订单数字ID升序及退回实收记录,库存内部 `locked()` 为position→balance;退货换标先 `prepareNativeReturn` 来源订单再锁箱 | 主流程共同根锁为trip→车辆→司机/资源→dispatch;随后task/binding→来源订单/实收→position→balance(或退货专用箱锁)。扫码不申请出库/派送行锁,结束前不进入派送回调。保留库存内部顺序和真实扣减;不能改成balance→position。 |
| 旧 `DeliveryTransferService.platformTransfer` 为dispatch→已有outbound→binding,按目的地循环创建再绑定来源;新Controller已改接DispatchDeliveryService | 新服务只通过主流程父端口取得trip→车辆→司机/资源→dispatch,再完成全部子出库/派送创建或锁定,最后才统一锁来源/绑定/费用。普通UPDATE也产生行锁,不能仅统计显式FOR UPDATE。旧内部实现与跨域旧测试的最终清理由后续联合收口列明。 |
| `DispatchPdaWorkflowService.depart` 当前 dispatch→binding→outbound→`DeliveryExecutionGuard.requireDeparture`锁派送→task→`DispatchPickOrderAttributionService.depart`锁来源订单 | 主流程与本任务协作:父级→task/只读核平→全部客户outbound→全部delivery→来源。`markDeparted`先于来源更新,来源更新只触及已锁的单据集合;不重新请求其他派送锁。 |
| `DeliveryTransferService.cancelOutbound` 当前先dispatch/相关relabel,后outbound→delivery,之后费用来源、来源恢复 | 有整车关联的合法未执行取消,先非锁定定位,再父级/必要批次→全部目标outbound/delivery→来源/相关relabel→费用及历史;已拣直接拒绝。其他独立出库类型维持其已确认协议,不伪造trip。父级改动归主流程,取消实现归本任务,跨relabel/转运的真实锁点实施时定向复核。 |
| `CustomerVisitService.updateDeliveryStatus` 当前 outbound→delivery,不申请dispatch;`DeliveryDocumentService.save` 当前delivery→`SourceDeliveryCompletionQuery.proveAll`的来源订单 | 普通状态变更若与发车竞争需先取得共同父级再outbound→delivery,由总控分配该类写权。签收资料保持delivery→来源,不拿outbound写锁、不反向父锁;仅提交后持久提醒。 |
| `FleetPoolOrderBridge.signed/departed` 在来源处理后 `links.lockDispatch`,再由 `move` 锁本土卡车/散板商业单;不申请父trip | 这两条既有直接副作用保留来源→pool link→商业单顺序,不在其后回取派送/父锁;全部相关来源应在进入商业事实更新前收齐锁。主流程/Fleet商业域写权不足的触点交总控,不能以“只写历史”忽略商业单真实行锁。 |
约束是分命令的有向次序,不是把所有领域拼成一条虚构的全局序列:**扫码为父级→task/binding→来源→库存,且不再取派送锁;安排/发车/相关取消为父级→完整子出库/派送→来源→费用;签收为本派送→来源→本地提醒,始终不取父锁。** 来源订单对多客户使用统一数字ID升序(ID全局唯一),同一客户下也保持现有数字顺序;子单按customerId数字值、业务ID升序,明细/来源集合一次收齐,不边持后序锁边发现新前序行。
预约批次/资源提供者、换标和转运的直接调用是否会回头取父/派送锁仍属实施审查项,触点未分配不得改;若发现反向锁必须由总控调整唯一入口或分配写权后再实施,不能以“整车已串行”忽略跨历史来源并发。现阶段只是完成上述代码锁点核对,未运行并发测试或证明全域无死锁。
### 5.3 取消、修改和财务竞争
- 本批安排发生在真实拣货并装车完成后,既有“已拣禁止直接取消出库”仍成立;不能为新流程放开取消或伪造退库。装车后取消/退装的新增业务流程尚未授权,不提供快捷撤销接口。
- 既有其他尚未执行出库类型的取消保留其业务限制;有整车父关联时按第5.2节父级→出库/派送→来源取得锁,禁止子单自行解除全车。物流取消不释放另一客户占用或自动恢复实发库存。
- 来源原状态只从真实本次转换历史恢复,清空关联和版本规则保留;混托来源各自核对。费用只申请作废本派送当前有效 DELIVERY_FEE 应收,装车费、买约费、供应商应付及其他来源不自动作废。
- 费用调整/撤销保留现有 READ_COMMITTED、来源行锁和未决撤销检查;Finance APPLIED/DUPLICATE 且 hash 匹配才确认 VOIDED。若调整与整车证据变化会影响发车,主流程须按安排事实失效规则阻断,不能静默重写原安排费用。
- 改货物、目的地、关键资源后如何使审核/装车/安排失效由主流程提供单一规则;delivery 不解锁修改、不隐式删除派送。冻结时需说明是否在存在安排事实后直接拒绝这类修改,或如何经过明确重审动作;不得保留“修改了车、货但派送仍旧可发”的窗口。
## 6 正常签收汇总与异常边界
`NormalDeliveryFact` 建议包含:`customerId, dispatchNo, arrangementKey, outboundNo, deliveryNo, groupKey, deliveryVersion, originalPackages, signedPackages, signedAt, outboundCompleted, returnedPackages, activeReturnCount, status`。来源为真实出库、派送签收字段、资料修订及退回事实;不以附件数、状态文字或最后更新时间单独判定。
整车正常完成必须同时满足:已真实发车;安排组集合和实际派送集合精确相等;全部客户出库已 OUTBOUNDED;每张原实发大于零;每张具有真实 signedAt 且 signedPackages 等于本张原实发;本趟没有以退回替代正常签收的数量及未处理异常;签收时间不早于实际发车且不晚于当前时间。完成时间取本趟最后实际签收时间,空集合/部分签收绝不完成。
- `DeliveryDocumentService.save` 保留 READ_COMMITTED、本派送锁、版本、请求 hash、文件客户+业务+类别归属;首次签收仍先验证实际出库和活动异常。BOL/装车资料可提前准备,签收资料不能提前伪造完成。
- 一张单发生拒收、RETURN_PENDING、真实退回,或退回后仅签剩余部分,本趟仍不能汇总“派送完成”。既有异常单及真实退库能力保留,本批不新建异常闭环,也不把线下处理意见当作全量正常签收。
- 已经全量签收后再另发起退货,保留原运输不可变签收事实,不重开已正常完成的本趟;核对退回事实是否发生在本次全签之前,不能只看当前状态或任何历史退货存在就否认原运输完成。
- 整车正常完成不代替 `SourceDeliveryCompletionQuery` 跨全部历史发运的头程来源证明;跨次拆发、实退再派必须沿真实来源及流水证明,防止提前发布头程整来源完成事件。
- 现有 `FleetPoolOrderBridge`、完成 Outbox 和回访只消费各客户真实签收;不因整车汇总二次发布费用或重复扣库存。车辆/司机释放仍是独立事实,不随五阶段完成自动释放。
### 汇总调用建议:提交后重读,避免反向锁
当前签收锁序为本派送→全部相关来源订单。**不要在该事务持有派送或来源锁时回调申请父车次/排车锁。** 采纳主流程稿第5/6节持久 `DeliveryFactsChanged` 方向,具体持久化边界提案如下,等待总控冻结表名/调度入口,不留“靠内存通知”分支。
| 环节 | 具体提案及唯一写者 |
| --- | --- |
| 记录结构 | delivery域新增 `ll_delivery_facts_changed`,字段 `id,customer_id,dispatch_id,dispatch_no,delivery_id,delivery_no,delivery_version,facts_hash,occurred_at,state,attempt_count,next_attempt_at,last_error_code,processed_at`;状态仅PENDING/PROCESSED,唯一 `(customer_id,delivery_id,delivery_version)`。只作同Lastleg本地待核对事实,不新增跨服务事件类型;DDL交总控集成。 |
| 事实写入 | 本任务在 `DeliveryDocumentService.save` 正常签收事实落库、来源证明/完成Outbox/回访成功的**同一事务**插入PENDING;回滚则提醒也不存在。原资料命令重放在写入前返回,无第二条提醒。未来其他合法入口改变正常完成依据,也须同事务写提醒,由总控分配其文件写者,不让本任务越权修改异常/回访。 |
| 数据访问 | 本任务独占 delivery内Entity、Repository、Mapper及直接持久化测试;通过共同端口提供 `pendingCandidates(limit,now)` 普通读、`ackProcessed(ids)`、`recordFailure(id,code,nextAt)`,不从签收线程调用主流程Service。消费端不直调delivery Mapper。 |
| 消费与汇总 | 主流程唯一维护 dispatch内有界任务/调度入口(拟 `DispatchDeliveryCompletionJob`)及 `DispatchCompletionPort.reconcile`。先普通读已提交PENDING候选;每趟另起READ_COMMITTED事务,trip→dispatch锁,调用 `DispatchDeliveryPort.normalDeliveryFacts` 批量普通读全部已提交事实,再CAS五阶段及唯一完成依据,最后经delivery端口确认本次已核对的候选。整个事务不锁历史来源、不执行库存/费用/回访完成副作用。 |
| 领取和确认顺序 | 不先锁/持有提醒行再申请父锁。候选扫描不使用FOR UPDATE、也不在父事务外预持PROCESSING锁;两个执行器可看见同一候选,由父锁/CAS与幂等汇总串行。提醒确认置PROCESSED与主单汇总处于同一事务,顺序为父→普通读事实→主单写→提醒行;不能先标处理完再更新阶段。未全签但已核对完的候选也可确认,后续客户签收会产生自己的新提醒。 |
| 失败和崩溃恢复 | 主流程负责重试、退避/批量上限及有界重扫已发车未正常完成整车;本任务提供提醒持久化操作。汇总或确认失败整体回滚、PENDING保留;错误次数/下次时间只能在回滚后独立短事务记录,不持提醒锁回头申请父/来源锁。进程提交前退出仍为PENDING,签收提交后通知丢失靠持久扫描恢复,重复消费没有二次阶段/历史副作用。无需新增长期调度平台或依赖内存afterCommit;如用afterCommit只作唤醒优化。 |
| 测试边界 | 本任务写“签收与提醒原子、签收重放无重复、提醒Repository及状态操作”测试;主流程写“两个最后签收、重复消费、消费中断/重试、确认回滚、未完成整车有界重扫、父锁汇总不反向子锁”测试并统一运行Maven。跨两包集成fixture由总控指定唯一写者。 |
`facts_hash` 仅证明触发时的派送事实版本;消费必须重新读取全部客户,不将消息中的allSigned结论直接落主单。只确认已扫描且确实核对过的事件ID,不能批量吞掉扫描后新产生的提醒。组合GET可返回已提交当前阶段,签收提交到汇总提交之间允许短暂保持派送中,前端不直接写成完成;故障可观测字段若需公开由总控另冻最小schema。
主流程汇总只普通读客户出库/派送,不调用会锁来源订单的 `SourceDeliveryCompletionQuery`。来源全签证明继续在签收自己的事务完成,整车汇总不重复发布原来源事件。以上是有明确写者的提案,尚未写记录、调度器或运行恢复测试。
## 7 实际主流程端口与共同实现核对
本次差异修订选用主流程稿第5节的一套 `dispatch/port/` 契约名作为冻结提案;该包仅放DTO/接口,不依赖任一实现/Entity,delivery实现派送端口、消费主流程执行端口,不再并建初稿的ContextPort/ArrangementQuery/Departure/NormalFacts四套同义接口。主流程类不得注入派送具体实现反向调用其公开Controller;依赖分析仍待实施验证,包名最终由总控冻结。以下不是已存在代码。
| 方向 | 拟议端口 | 必须保证 |
| --- | --- | --- |
| delivery→主流程 | 实际 `DispatchExecutionPort.preview(actor,dispatchNo)`,来源在Context.cargo | 加入组合GET同一只读事务;返回全车/逐客户已核平来源、仓、recordVersion、阶段、装车事实及车辆司机快照,真实临时外配无需伪造档案。cargo使用唯一权威来源,不能两域各推一份数量。 |
| delivery→主流程 | 实际 `DispatchExecutionPort.lockForArrangement(actor,dispatchNo)` | MANDATORY,trip→车辆→司机/资源→dispatch;先只锁及复验身份/关联供严格命令恢复,新命令才验证recordVersion和阶段,不能在恢复前拒绝旧版本。这里只取得父/资格事实,不先锁来源后让delivery反向锁子单。 |
| delivery→主流程 | 实际 `DispatchExecutionPort.replay(context,actor,identity)`、`requireFreshArrangement(context,recordVersion)`、`recordArrangement(context,actor,identity,fact,alreadyArranged)` | 严格命令恢复先于新版本阶段校验;首次全部客户成功才CAS/历史及安排引用,阶段仍装车后;不写派送表。新键同业务只复用事实,不增版本或重复收费。 |
| 主流程→delivery | `DispatchDeliveryPort.departureFacts(locked,lock)` | 全部客户出库/派送/费用确认事实及精确来源集合;lock=true仅在父锁写事务中,按第5.2节一次锁齐子单,之后才能请求来源写锁。 |
| 主流程→delivery | 实际 `DispatchDeliveryPort.markDeparted(context,actor,departedAt,commandKey)` | MANDATORY,更新已锁全部客户出库/派送执行快照,返回逐客户实发业务事实;不调用库存ship、不转换ll_order计数、不更新整车阶段。主流程随后唯一调用订单归属发车更新,任一失败所有客户同事务回滚。 |
| delivery→持久记录→主流程 | `DeliveryFactsChanged(dispatchNo,deliveryNo,deliveryVersion)`、提醒数据访问端口 | delivery保存提醒及Repository实现;主流程扫描/消费/重试,经端口确认;明细及ack边界见第6节,无签收线程同步reconcile。 |
| 主流程→delivery | 实际 `DispatchDeliveryPort.normalDeliveryFacts(context)` | 批量普通读所有本趟客户出库/派送、正常签收/异常/缺项,返回expectedDeliveryNos、数量、allNormallySigned、factsHash及最后正常签收时间;空集合为false,不锁来源,不分页漏项。 |
| 主流程消费入口 | 实际 `DispatchCompletionPort.reconcile(signal)` | 主流程新事务父锁后读取已提交正常签收事实,幂等CAS阶段和完成时间/依据;最后经DispatchSignalPort确认已核对提醒,不能回原签收事务执行。 |
| 主流程→FleetBookingFreight | 权威整车绑定/客户来源上下文 | 逐客户真实派送来源+统一父身份、预订/实收版本;`FleetBookingFreight` 不在子锁后反向申请父锁。其他 fleet 文件改动归主流程。 |
共同实现核对项:
1. 一对一fleet父行及trip→车辆→司机/资源→dispatch已由正式契约确定;公开dispatchNo、recordVersion及五阶段以实际DispatchContracts/DispatchTypes为准,主流程来源由共享Context.cargo提供。
2. 逐客户 `dispatchItemId`、实际来源/拣货/退货/换标事实字段、目的地规范与组键;尤其父排车头平台范围时,`DeliverySourceEvidenceMapper` 当前 `ds.customer_id=d.customer_id` 的联查必须同步调整为权威整车关联+明细客户隔离,不能直接删客户校验。
3. 装车完成事实/hash、严格commandHash与arrangementBusinessHash、全主体安排键注册与共同命令账本的唯一约束;原键恢复先于新版本/阶段判断,新键复用须当前recordVersion和当前写权限。旧严格命令跨主体不可重放。
4. 具体采用本稿每客户一出库及每客户目的地一派送、全数组响应与组合GET单一快照的提案;缺项/加载失败schema及HTTP 409/403/404;单客户DTO/单出库消费者同批替换。
5. delivery只更新子出库/派送;主流程唯一更新订单履约计数和整车阶段;扫码已完成的普通库存ship不再调用。全部客户发车原子回滚,预约批次/工作事项及外接BOUND守卫保留。
6. 第6节持久提醒表/端口及主流程任务类名称、重试/重扫上限和唯一写者;第5.2节所有父/子/来源锁序,预约/换标/转运附加锁点还需对应写者审查;旧fleet结案只作为附加事实保留。
7. 客户旧创建入口已获批准移除;Client由前端任务、脚本/权限/OpenAPI由总控集成。临时外配证据、实载弹框和零扫码退回重审已按第八节确认,不再待用户重复裁定。日历新增预约按第十节排除,不新增其设计、API或矩阵。
已读取主流程实际dispatch/port骨架并接入DispatchExecutionPort、DispatchDeliveryPort、DispatchSignalPort;它们覆盖早期提案的签名。主根锁、全局键及客户创建去向已由正式契约冻结;剩余为真实实现及联合验证,不能沿用准备稿相反序列或另造DTO。
## 8 直接生产者、消费者和文件写权
| 文件/范围 | 本批关系及归属 |
| --- | --- |
| Lastleg `delivery/controller/DeliveryTransferController.java`、`PlatformDeliveryFeeCoverageController.java`、`MerchantDeliveryController.java`、DTO/Entity/Repository/Mapper/Service及本域测试 | 本轮已按解锁范围实施,实际差异见第10节;其他独立出库业务保留。 |
| `fleet/trip/FleetBookingFreight.java`、`FleetBookingFreightTest` | 本任务独占;其引用的 FleetBookingMapper/Reservations/DispatchGateway 变化由主流程提供端口,不能顺手修改其他 fleet 文件。 |
| `financefee/service/OverseasFeeSourceService.java`、`OverseasFeeBusinessGuard.java`、相关 Repository/Mapper/直接测试 | 仅发生真实归属/幂等或必须分层整改时修改;既有 Outbox、撤销 ACK、币种/供应商校验保留,不扩大 Finance。 |
| `dispatch/pda/service/DispatchPdaWorkflowService.java`、`dispatch/fleet/DispatchFleetAdapter.java`、`fleet/trip/FleetTripExecutionService.java`、`FleetTripCompletionService.java` | 主流程唯一写者:当前依赖单客户、单出库、旧完成规则的主消费者。 |
| `delivery/mapper/DeliverySourceEvidenceMapper.java`、`SourceDeliveryCompletionQuery`、完成 Outbox | 本任务同步新父关联/分组和历史实际来源证明;跨次来源锁协议保留。 |
| `customervisit/service/CustomerVisitService.java`、`exceptionorder/`、File 提供者 | 直接相关但本任务未获生产写权;单据归属/签收事实若要求触及,列精确方法给总控分配。不能删除异常、回访或附件权限。 |
| Admin `overseas-warehouse/api/dispatches.ts`、`pages/DispatchesView.vue`及测试 | 前端任务处理组合预览、逐客户目的地费用、完整数组响应与恢复;详情仅消费已冻结契约。 |
| Client `order-management/views/DeliveryOrderCreateView.vue`、`api/deliveryOrders.ts`、`deliveryOrders.test.mjs` | 已由正式契约批准移除,前端任务负责直接消费者;客户列表/详情/签收下载继续真实客户隔离。 |
| PDA `fulfillment.js`、dispatch 工作流 | 前端及主流程任务同步全车结果/版本,保持真实拣货、装车与发车动作分离;不消费平台整车费用候选。 |
| `src/main/resources/openapi/overseas-business-v1.yaml`、安全权限、基线及统一 SQL、Gateway | 总控统一集成。派送资料/客户契约的 schema 引用一并核对,不由本任务并写。 |
| 后端 `scripts/overseas-relabel-fulfillment-acceptance.mjs`、`prod-release-overseas-stage.mjs`、`admin-test-env-modules/phase5-root-fulfillment.mjs`、`phase5-overseas-fulfillment.mjs`、`fleet-external-dispatch-acceptance.mjs`、`fleet-fee-coverage-acceptance.mjs`、`fleet-test-env-acceptance.mjs`及其合同测试 | 已命中旧转派送路径或单出库形态,需总控分配脚本同步;本轮不执行、不假定未命中的脚本都无需修改。 |
既有工作区还有其他模块未提交修改,包含 `ExceptionOrderDispatchReturnSourceTest.java`;本任务未写这些文件,后续跨域测试冲突交总控协调。
## 9 用例与后续验证命令
以下为待实施的行为测试清单,不是本轮通过结果。Maven 全部交主流程任务串行执行。
| 组 | 必覆盖行为与证据 |
| --- | --- |
| 单据与客户 | A/ONT8、A/LAX9、B/ONT8 得两出库三派送;同目的仓不串客户;所有子单来源集合完整;客户 B 查询/附件/原费引用不能访问 A;伪造 groupKey/customer/destination 被拒。 |
| 阶段与空单 | 空单、拣货未齐、未确认装车、装车 hash 过期、已发车禁止首次安排;装车后安排成功才能发车;不能通过普通状态编辑绕过。 |
| 真实来源 | 普通多入仓混托、混普通/外接、换标、退货换标及真实退回重派;扫码库存只扣一次,安排/装车/发车没有新增ship流水;发车只变订单picked/shipped计数及出库事实,同托后到货不改变已冻派送;实际SKU/箱来源不从声明推定。 |
| 原费 | A 引用 B 原费、过期版本/hash、Finance 不可用、同源同服务重复选择拒绝;部分覆盖仅免对应来源;全覆盖不造新/零费用;不同目的地引用同源证据不复制原费;供应商应付独立。 |
| 外接 | 两客户相同或相似入仓码不串价;预订/实收/目的地/数量/绑定改变拒绝;明确零只记事实;普通混货仍收未覆盖部分;前笔撤销未 ACK 不重收。 |
| 事务与竞争 | 同键同主体严格原载荷恢复;同键改recordVersion/动作/单号/操作者拒绝;新键同业务仍核当前权限/版本,只引用既有事实不重收;已撤权/换仓恢复拒绝;第N组失败所有客户及费用/Outbox/主单CAS全回滚;安排与Admin/PDA发车、改车/货竞争,发车一处失败全回滚;验证真实Mapper与唯一约束,不能仅靠Mock。 |
| 组合GET与数组 | 一次GET共享本地只读快照,无单出库别名;过程中本地版本变化不拼接新旧组,Finance候选保留版本并POST复核;来源不全/候选失败明确表达;数组覆盖全客户目的地,业务GET不泄露原命令请求或凭它冒认当前操作者成功。 |
| 签收 | 未出库不准首次签收;部分签收、异常/退回和签剩余不汇总完成;全部原实发正常签收自动汇总且完成时间取实际最后签收;签后另退不改原运输;重复保存和本地提醒不重复 Outbox/回访。 |
| 并发汇总 | 两客户同时最后签收、签收与提醒原子提交、提交后通知丢失、消费前/汇总中进程中断、重复扫描/消费、汇总CAS或提醒确认失败;父与ack同事务回滚,未扫描新提醒不被误确认,有界重扫最终恢复;无签收子锁回父,跨多趟来源证明保持RC+来源锁协议。 |
| 取消与撤销 | 保留已拣禁止取消、未执行合法取消原状态/关联恢复、仅派送应收申请作废、其他费用保留;与发车竞争只允许一个合法结果;请求撤销不当作确认作废。 |
复用/扩充现有测试:`DeliveryTransferServiceTest`、`DispatchDeliveryFeesTest`、`DispatchFeeCargoMapperTest`、`FleetBookingFreightTest`、`DeliveryExecutionGuardTest`、`DeliveryDocumentServiceTest`、`PlatformDispatchOutboundContractTest`、`MerchantDeliveryControllerTest`、`DeliverySourceEvidenceMapperTest`、`DeliverySourcePublicationPersistenceTest`、`SourceDeliveryCompletionConcurrencyTest`、`OverseasFeeCancellationPersistenceTest`。主流程的 `DispatchRepairWorkflowTest`、PDA/FleetTrip 直接测试由其唯一写者同步;新增整车安排持久化/竞争测试放本任务 `delivery/` 测试包,不与主流程测试并写。
主流程可采用以下后端根命令,具体 Test 类以最终实际新增为准:
```powershell
mvn -pl lastleg-service -am test-compile
mvn -pl lastleg-service -am test '-Dtest=DeliveryTransferServiceTest,DispatchDeliveryFeesTest,DispatchFeeCargoMapperTest,FleetBookingFreightTest,DeliveryExecutionGuardTest,DeliveryDocumentServiceTest,PlatformDispatchOutboundContractTest,MerchantDeliveryControllerTest,DeliverySourceEvidenceMapperTest,DeliverySourcePublicationPersistenceTest,SourceDeliveryCompletionConcurrencyTest,OverseasFeeCancellationPersistenceTest' -Dsurefire.failIfNoSpecifiedTests=false
mvn -pl lastleg-service -am test
node --test scripts/gateway-route-contract.test.mjs
node scripts/mapper-scan-contract.mjs
```
新增端口/依赖边界后按服务指引执行 `node --test lastleg-service/scripts/analyze-lastleg-dependencies.test.mjs`,核对依赖基线,不登记临时循环豁免。总控同步 SQL 后运行 Schema/中文注释合同;Client、Admin、PDA 的直接调用和构建由其获权执行者完成。真实 HTTP、部署、SQL、人工页面/真机验收仍待各自单独授权及证据。
## 10 本轮交付与停止点
首批实现已写入delivery域:DispatchDeliveryService实现实际DispatchDeliveryPort,DispatchDeliveryFees处理逐组报价/覆盖/发布,DeliveryCargoGroups与NormalDeliveryCompletionPolicy核对来源及正常签收。已复核总控14:36就绪的共享骨架,ArrangeDelivery按实际Long版本构造,缺失/负数拒绝、0合法。新安排事实/信号均有独立Mapper→Repository;DeliveryDocumentService触及的数据访问收进DeliveryDocumentRepository,签收经实际DispatchSignalPort入队、不回调父流程。
Controller的整车POST已使用共享ArrangeDelivery并返回CommandResult,新增组合GET返回ArrangementPreview;原辅助GET共用组合服务和PreviewGroup。Merchant创建POST和merchantTransfer服务入口已删除,客户读取及签收资料下载保留。未改SQL/OpenAPI/权限/主流程/预约在途文件;未提交、部署、执行环境SQL/HTTP或跨对话发信,未执行Maven。
已执行:Mapper扫描合同通过(10持久化模块、384 Mapper);Gateway路由合同5/5通过;git diff --check无空白错误。Lastleg依赖合同12例中9过3失败,均指出工作区fleet/pickup三类对WarehouseTransferOrder的新依赖,超出本任务写权,未放宽基线。该结果绑定当次工作区快照,不替代后续集成复验。
Java新增直接用例:DeliveryCargoGroupsTest、NormalDeliveryCompletionPolicyTest、DispatchDeliveryFeesTest、DispatchDeliveryServiceTest、DispatchDeliveryArrangementPersistenceTest、DeliveryFactsChangedPersistenceTest;另更新Merchant、资料、平台合同及来源持久化直接测试。全部尚未由Maven执行,不能声称编译或行为测试已通过。
旧单客户平台转换内部实现、DeliveryFeeCoverageService及旧Transfer/FeeItem/TransferResult DTO已清除;原行为用例由新整车领域用例承接,其他出库及取消用例保留。取消已接共同父锁端口,触及的数据访问收进DeliveryCancellationRepository;全部子单锁后先锁来源、再费用,保留费用撤销ACK及原状态恢复,不放开已拣取消。
联合收口事项:主流程DispatchExecutionPort实现、共同命令账本/阶段CAS/消费器;Context逐行实测重量/体积须为实际归属值、不能重复整托总量;主流程独占DispatchRepairWorkflowTest、FleetTripPersistenceTest手工fixture需注入新DispatchExecutionPort和DeliveryCancellationRepository,并补出库明细新来源字段。异常退回消费者须按新增不可变来源字段核对真实行;ExceptionOrderService超出本任务写权,交总控分配。真实转仓/换标及预约提供者的交集锁审查同样由总控分配唯一写者。共同SQL/OpenAPI/权限及真实跨客户竞争由总控集成、主后端串行验证。
本稳定点提供本域代码及测试供主后端统一编译/运行;接口实现/结构及外部消费者尚未联合完成,不标整体验收通过。日历新增预约始终在本任务范围外。
## 11 给总控的精确结构、API与验证提案
### 11.1 SQL(仅提案,未写共享SQL、未执行)
以下表/列与本轮Mapper完全一致。保留现有出库客户唯一键和派送客户目的地唯一键,不并加反序冗余索引;共同全局命令表由主流程提供。
```sql
CREATE TABLE IF NOT EXISTS ll_dispatch_delivery_arrangement (
id BIGINT NOT NULL COMMENT '安排事实内部主键',
dispatch_order_id BIGINT NOT NULL COMMENT '唯一整车排车主单ID',
dispatch_no VARCHAR(128) NOT NULL COMMENT '真实排车业务号',
arrangement_key VARCHAR(128) NOT NULL COMMENT '本次唯一安排业务事实标识',
business_hash CHAR(64) NOT NULL COMMENT '排除操作者及纯并发版本的安排业务摘要',
cargo_hash CHAR(64) NOT NULL COMMENT '本车实际拣货来源摘要',
loading_completion_hash CHAR(64) NOT NULL COMMENT '装车完成事实摘要',
original_command_key VARCHAR(255) NOT NULL COMMENT '首次安排的全局请求键',
original_operator_id VARCHAR(128) NOT NULL COMMENT '首次安排操作主体',
result_json JSON NOT NULL COMMENT '全部客户出库及客户目的地派送不可变结果',
cargo_json JSON NOT NULL COMMENT '逐客户逐拣货归属的不可变真实来源',
created_at DATETIME(3) NOT NULL COMMENT '本次安排实际创建时间',
PRIMARY KEY (id),
UNIQUE KEY uk_dispatch_arrangement_dispatch (dispatch_order_id),
UNIQUE KEY uk_dispatch_arrangement_key (arrangement_key),
UNIQUE KEY uk_dispatch_arrangement_command (original_command_key)
) COMMENT='整车排车唯一派送安排事实';
CREATE TABLE IF NOT EXISTS ll_delivery_facts_changed (
id BIGINT NOT NULL COMMENT '持久信号内部主键',
customer_id VARCHAR(128) NOT NULL COMMENT '真实签收货物客户ID',
dispatch_id BIGINT NOT NULL COMMENT '整车排车主单ID',
dispatch_no VARCHAR(128) NOT NULL COMMENT '真实排车业务号',
delivery_id BIGINT NOT NULL COMMENT '本客户派送单ID',
delivery_no VARCHAR(128) NOT NULL COMMENT '真实派送业务号',
delivery_version BIGINT NOT NULL COMMENT '触发信号的真实派送版本',
facts_hash CHAR(64) NOT NULL COMMENT '该版本真实签收事实摘要',
occurred_at DATETIME(3) NOT NULL COMMENT '签收事实实际发生时间',
state VARCHAR(16) NOT NULL DEFAULT 'PENDING' COMMENT '待核对PENDING或已核对PROCESSED',
attempt_count INT NOT NULL DEFAULT 0 COMMENT '已记录的汇总失败次数',
next_attempt_at DATETIME(3) NOT NULL COMMENT '下次可重试时间',
last_error_code VARCHAR(64) NULL COMMENT '最近失败诊断码不保存敏感异常正文',
processed_at DATETIME(3) NULL COMMENT '与主阶段汇总同事务确认时间',
PRIMARY KEY (id),
UNIQUE KEY uk_delivery_fact_version (customer_id,delivery_id,delivery_version),
KEY idx_delivery_fact_due (state,next_attempt_at,id),
KEY idx_delivery_fact_dispatch (dispatch_id,state,id)
) COMMENT='正常签收事实变化的本地持久待汇总信号';
ALTER TABLE ll_outbound_pallet_item
ADD COLUMN dispatch_item_id BIGINT NULL COMMENT '本次排车作业明细ID',
ADD COLUMN source_attribution_id BIGINT NULL COMMENT '不可变PDA拣货归属ID',
ADD COLUMN source_order_id BIGINT NULL COMMENT '本行真实来源尾程订单ID',
ADD COLUMN source_inventory_position_id BIGINT NULL COMMENT '本行实际拣货库存仓位ID',
ADD COLUMN source_return_receipt_id BIGINT NULL COMMENT '本行实际退回再派实收记录ID',
ADD COLUMN source_return_carton_id BIGINT NULL COMMENT '本行实际退货换标来源箱ID',
ADD UNIQUE KEY uk_outbound_source_attribution (customer_id,source_attribution_id);
```
本轮不为开发存量设计迁移/回填或自动删重;总控在最新基线及统一结构脚本按列存在性集成,以上ALTER仅字段提案,不能直接当成可重复执行脚本。新来源字段在其他正式独立出库类型可空,排车来源按共享CargoLine逐行填真实值;同一真实归属不能在两次出库重复使用。主流程消费者必须先父锁,再普通读取事实,再阶段CAS及ack同事务;失败后调用DispatchSignalPort.failed独立短事务退避。due上限当前200,调用者使用1—200有界批量。
### 11.2 OpenAPI与权限
- 新增GET `/api/platform/v1/last-leg/dispatches/{dispatchNo}/delivery-arrangement`:dispatch:list,ArrangementPreview及其共享嵌套记录;顶层recordVersion/stage为当前快照,arrangement为不可变原结果。
- POST同前缀 `/{dispatchNo}/transfer-delivery`:dispatch:transfer-delivery,完整共享ArrangeDelivery请求;响应为DispatchContracts.CommandResult,result是ArrangementResult,replayed/alreadyArranged在外层,不保留单个outboundNo。
- 两个既有辅助GET external-freight、fee-coverage当前返回 `List<PreviewGroup>`,复用组合查询;前端弹框仅用一次组合GET,不再拼两个快照。
- 删除Merchant集合POST及其创建schema/权限资源;保留Merchant集合GET、单单GET及签收资料/下载。精确Client消费者见第8节,脚本由总控分配,不在本任务改动。
- 统一Gateway已有Lastleg通配覆盖,上述源码路由合同已通过;运行时部署及共享OpenAPI仍待总控集成,不推定已可访问。
- 服务AGENTS当前仍指向已删除的DeliveryFeeCoverageService;由总控在共享指引同步时改为DispatchDeliveryService/DispatchDeliveryFees及全局安排模型,并按整批指引门禁统一检查,本任务未并写AGENTS。
### 11.3 主后端串行运行包
```powershell
mvn -pl lastleg-service -am test-compile
mvn -pl lastleg-service -am test '-Dtest=DeliveryCargoGroupsTest,NormalDeliveryCompletionPolicyTest,DispatchDeliveryFeesTest,DispatchDeliveryServiceTest,DispatchDeliveryArrangementPersistenceTest,DeliveryFactsChangedPersistenceTest,DeliveryTransferServiceTest,DeliveryDocumentServiceTest,DeliverySourcePublicationPersistenceTest,MerchantDeliveryControllerTest,PlatformDispatchOutboundContractTest,DispatchFeeCargoMapperTest,FleetBookingFreightTest,SourceDeliveryCompletionConcurrencyTest,OverseasFeeCancellationPersistenceTest' -Dsurefire.failIfNoSpecifiedTests=false
```
主流程旧直接fixture签名与共享OpenAPI完成后再运行本包及Lastleg全量;尤其Merchant OpenAPI测试当前明确要求旧POST/create权限已删除,不能用旧共享文件使测试放宽。旧来源证明并发用例、外接报价、费用撤销ACK与取消竞争沿第9节纳入最终回归。
### 11.4 本域稳定文件快照
本轮固定delivery主源码和测试39个变更路径(37个现存文件、2个删除路径),不含本设计文档。统一编译反馈后,总控先解除`delivery/controller/MerchantDeliveryControllerTest.java`测试文件冻结,随后授权修正`delivery/PlatformDispatchOutboundContractTest.java`的当前Controller/DTO直接消费者;生产文件不变,测试类/路径集合不变。当前候选摘要采用**JavaScript `paths.sort((a,b) => a.localeCompare(b))`,不传locale/options参数**:
`90b54852f18e5f1244aeee81313f99bee50cb5abf405e372718c322ad60427c2`
此次测试文件SHA-256为`c45c68d01b54a67dab7f1fc7e3c55b4511530eb0aad716561ae84d6cda94dcb6`。派送列表/详情以及签收资料/下载均按精确路径块提取,到下一同级路径或根章节停止;保留禁止客户创建、Token客户隔离和签收资料只读的全部断言。新增一个相邻业务POST不误入、派送自身POST仍可检出的回归方法。未删除共享OpenAPI中的合法仓储转运和弃货POST。File三文件哈希与上一交付一致。
`PlatformDispatchOutboundContractTest.java`当前SHA-256为`e59a2bb29d3122aeb93a5dc0618bad8831ca83b5621a5a07d8316dfb5475b619`。取消反射及直接调用使用`DispatchAggregateController.cancel(user,dispatchNo,DispatchCommands.ReasonCommand)`,校验`POST /{dispatchNo}/cancel`和请求体;更新反射及字段集合使用`DispatchCommands.Update`。保留各动作独立权限、无customerId参数、客户在业务查找前拒绝,客户取消按公共身份工厂的`BizException(FORBIDDEN)`核对且验证整车Service零交互。草稿切片中按总控反馈进一步将旧vehicleSize整份YAML字符串断言改为当前DispatchArrangeDelivery的公共版本、完整groups及分组身份/费用证据,并核对结果outbounds/deliveries两数组、禁止旧DeliveryTransfer schema;未改共同OpenAPI。取消修正时的中间候选90778a9b…由本候选取代。
首版候选摘要`ab2a553af145d7a2c708f1b44d88eb2c349970d81295bbbe4504af5f55ed2f81`以及仅修正Merchant测试的中间候选`ef2d6bd5063f2aa9b030d68faef950582ac956e09a5ca349a615efc2f45ac130`均由当前候选取代。首版曾与Ordinal排序摘要`932c52c825613ae020ea60538a7cb8efa4941c905975b67644c7c926fae4bda1`有排序差异:小写controller子目录与大写Delivery文件的先后不同;该历史对照不代表当前测试输入。
精确重算算法(在后端根由Node执行,只读文件;这里保留为候选输入定义,不是新增测试入口):路径统一使用Git返回的正斜线相对路径;Set精确去重后按上述localeCompare排序;每行 `path + U+0020 + 小写文件SHA256`,删除路径后缀为DELETED;LF连接、末尾无换行;无BOM的UTF-8字节再做SHA-256。
```javascript
const { execFileSync } = require('node:child_process');
const { existsSync, readFileSync } = require('node:fs');
const { createHash } = require('node:crypto');
const scope = [
'lastleg-service/src/main/java/com/baiyue/lastleg/delivery',
'lastleg-service/src/test/java/com/baiyue/lastleg/delivery',
];
const changed = execFileSync('git', ['diff', '--name-only', '--', ...scope], { encoding: 'utf8' });
const untracked = execFileSync('git', ['ls-files', '--others', '--exclude-standard', '--', ...scope], { encoding: 'utf8' });
const paths = [...new Set((changed + '\n' + untracked).split(/\r?\n/).filter(Boolean))]
.sort((a, b) => a.localeCompare(b));
const rows = paths.map(path => path + ' ' + (existsSync(path)
? createHash('sha256').update(readFileSync(path)).digest('hex') : 'DELETED'));
console.log(createHash('sha256').update(rows.join('\n'), 'utf8').digest('hex'));
```
当前测试类集合仍为第11.3节列出的15个测试类,编译反馈后只更新其中Merchant与Platform两份合同测试。精确路径离线提取检查和`git diff --check`通过;JUnit/Maven未运行,由主后端串行重跑`mvn -pl lastleg-service -am '-Dtest=MerchantDeliveryControllerTest,PlatformDispatchOutboundContractTest' '-Dsurefire.failIfNoSpecifiedTests=false' test`。本次未修改生产代码、SQL、OpenAPI或File文件。
该快照只用于总控确定本次待统一编译/测试的候选,不是提交、构建通过或部署证据。主后端实际编译发现接口或用例问题时再修改并更新快照;当前本域文件继续固定,等待统一验证反馈。
### 12 有界草稿实现输入(2026-10-19)
本任务新接管SmartDispatchController、DispatchDraft/Container及其Mapper,新增专用Draft Service/Repository、占用Mapper和持久命令记录及直接测试;共享port、AggregateService、DispatchSourceMapper、旧DispatchService、PDA/Fleet仍由原写者维护。公开请求/返回严格使用DispatchPlanningModels/Port及Admin现有dispatches.ts:GET/POST drafts、POST drafts/containers及snapshot、draft-locks lock/unlock/release、DELETE空container(ReasonCommand请求体)、POST drafts/pre-arrange;旧standalone pre-arrange不再注册。
共享SQL由总控唯一同步,精确模型输入:`ll_dispatch_draft`增加`warehouse_id BIGINT NOT NULL`、`record_version BIGINT NOT NULL DEFAULT 0`、`sources_json LONGTEXT NOT NULL`(服务器解析的Candidate数组),保留operator_id、token唯一、plan_ids_json、status ACTIVE/RELEASED/CONVERTED及真实created/updated/expires/released时间;草稿头无客户语义。`ll_dispatch_draft_container`增加`source_keys_json LONGTEXT NOT NULL`,保留draft_id/token、sequence_no、capacity(15/30)、时间,唯一`(draft_id,sequence_no)`。新增`ll_dispatch_draft_command(id BIGINT PK,idempotency_key VARCHAR(128) NOT NULL UNIQUE,operator_id VARCHAR(64) NOT NULL,action VARCHAR(32) NOT NULL,target_token VARCHAR(128) NOT NULL,request_hash CHAR(64) NOT NULL,result_json LONGTEXT NULL,created_at DATETIME(3) NOT NULL)`;命令预占与结果同事务,绝不提交未完成命令,原键全载荷/主体/动作/原版本一致才恢复原结果。草稿占用复用`ll_dispatch_pallet_lock`,dispatch_order_id对草稿允许NULL,draft_token、draft_container_id、operator_id、expires_at必须填写,source/实托两个活动唯一键沿主流程现有规则;释放仅匹配本token/owner且dispatch_order_id IS NULL,不触碰已转换正式占用。
写事务顺序为命令唯一行→本owner草稿根→容器普通读;选择时真实来源订单升序→来源托盘/收据→库存→活动占用。布局JSON只允许移动当前已锁来源,不新增来源资格;全布局必须精确覆盖原容器/来源集合,序号唯一,单仓,按物理实托去重计算capacity。移除只允许空容器。释放/取消选择在草稿根之后仅释放本占用,不反取资源父锁。
转换先校验所有非空容器恰好一组、每组cargo精确等于该容器服务器选择及原sourceVersion、每组warehouse同草稿;再锁齐全批资源→全批来源→本草稿占用,释放草稿原键,逐组调用真实Aggregate.create(每组一张整车、不按客户/目的地拆),全部结果和草稿CONVERTED及命令结果同事务提交。任一失败回滚全部来源占用、主单/Fleet/历史/命令,不先提交部分组。
需要主后端唯一写者接线的最小方法:①`DispatchService.lockDraftSources(String warehouseId,List<DispatchCommands.CargoSelection> selections): List<DispatchService.WholeSource>`,MANDATORY,沿现有lockWholeSources的真实身份/仓/订单/库存/版本核验,草稿选择允许换标申请逐托暂存,正式create继续要求完整申请;②`DispatchAggregateService.lockDraftCreationResources(Actor actor,List<DispatchCommands.Create> creates): void`,MANDATORY,一次按正式资源全局顺序锁齐所有新建车辆/司机及关联资源,不能在锁完一组来源后才去取下一组资源。新增草稿服务不会自行改这两个提供者。旧DispatchService草稿方法及旧DTO的最终清理由其唯一写者负责;本轮Controller不再调用旧客户拆单链。
当前桥接已由主后端落地并接入。草稿头`customerId`已从本包实体移除,不恢复旧字段以维持编译;旧Service存量草稿方法已由主后端移除。`plan_ids_json`已由总控在两份共享SQL中改为LONGTEXT:公开筛选允许最多500个正数Long,JSON可能超过原VARCHAR(4000)。候选参数唯一为`destinationWarehouseCode`。按总控最终确认的正式权限口径,候选及草稿两个GET均为`platform:overseas-warehouse:dispatch:list`,八个草稿写入口均为`platform:overseas-warehouse:dispatch:create`;不保留旧入仓权限,不添加OR,不修改共享角色/IAM。
容器序号交换在同一草稿根事务内先将原正序号变为负数,再写全部新正序号,避免`(draft_id,sequence_no)`的临时碰撞;失败与草稿命令一起回滚。直接测试使用真实MyBatis/H2/Spring事务代理验证命令恢复、拥有者/旧版本拒绝、真实共享唯一占用竞争、同版本并发、序号互换、布局不能新增来源、单仓/容量、退回/换标选择字段互斥,以及第二辆车失败使全批与原占用释放回滚。来源和整车提供者在边界隔离,生产端到端创建/来源资格仍由主后端集成测试验证,不用该夹具冒充完整联调通过。Maven仅由主后端执行。
### 12.1 草稿切片稳定输入
草稿包精确13路径(10个生产文件、3个直接测试),当前修复候选聚合指纹`b0db1bb5191fa3578dacfa0f07c7c2a6a30346f0198047e34fc1fe3a99b0e554`,取代首轮`db84f7527d8ee88a5b893ed291081041c5a1461d7dbdafc66716014c575d3ac0`。按第11.4节同一localeCompare排序、path加空格加文件SHA256、LF连接无尾换行算法生成;不含设计文档、共享端口/桥接/SQL/OpenAPI,也不把原39路径并入草稿包。原39路径指纹保持第11.4节值;本批另仅修改原File包的DispatchEvidenceFileTest两处受检异常声明,File类别和独占契约未变。
```text
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/controller/SmartDispatchController.java 63cf9f9644a8fb1b08cbbff66ef646943bba23950c5662232ae540bb470195fc
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchDraft.java 4f1509204cfff1a6993f75cfc7dd2ab62b8a56c3217c58e2e00326958db76a12
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchDraftCommand.java 38366ac363927ada62a25e1ea1cd3cb39bd76df10242e3fa5ff8dd4d3745c14f
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchDraftContainer.java deded482497de649ae66600f372c4ed2d9450f4cfe08da249feaacaa3008d619
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchDraftClaimMapper.java f23aa194955b7058da25992e43ee786ce3cde0c3ba9025a9ae13440c36aafc66
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchDraftCommandMapper.java e63f642901fbb0a0f1b3895e871c3c93539cea9b7928a86899073bee05a46920
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchDraftContainerMapper.java 4a752ec506f3dbd7f86ad41b5f9fc1751b166e0b25f5d394b8d9c588e1b2c142
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchDraftMapper.java 141df6769ed0c9399a59a550204998c8d0b0c23e935e108f96602d1729c319dd
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/repository/DispatchDraftRepository.java 6ee39efc395352f43ce36003545956c917990e2f2913dd2be5ca7c19dea9675d
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchDraftService.java 4a97ba8a592278ab635317a54f525268c51a7ac7f0ed04699085712e534af0c3
lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/controller/SmartDispatchControllerTest.java d577703bafa8cd51fd877c613b38c4bfcf16455a2cd4e8cb539b26f1bb418ef4
lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchDraftPersistenceTest.java d9ff50b04abddd54fba5c8c7528cb10c08dc7df8e3eecf43bc5172f7b20aeeec
lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/SmartDispatchOpenApiContractTest.java cab62da8a36e47f8f2c923f43429fa2565f242ac7e568f43640aff2f7b9404ea
```
主后端报告首轮输入test-compile通过(1056生产/450测试),直接178项176通过、2失败,失败为本包路由权限反射和转换结果重启恢复;本任务未自行执行Maven。独立只读审查另确认等待来源锁跨到期的占用漏洞,纳入同一修复。当前三份草稿测试共17个用例(DispatchDraftPersistenceTest 10、SmartDispatchControllerTest 6、SmartDispatchOpenApiContractTest 1),修复后尚未重跑。Mapper扫描393项及原静态检查是首轮证据;本轮已完成差异检查、构造器直接消费者核对、两个GET/八个写入口精确权限静态核对。共同OpenAPI的草稿业务必填列表已由总控补齐,不再作为待处理项。
请主后端在本输入上统一执行`mvn -pl lastleg-service -am -DskipTests test-compile`及`mvn -pl lastleg-service -am '-Dtest=DispatchDraftPersistenceTest,SmartDispatchControllerTest,SmartDispatchOpenApiContractTest,PlatformDispatchOutboundContractTest' '-Dsurefire.failIfNoSpecifiedTests=false' test`。本任务不启动Maven,不执行环境操作,不将静态核对写成编译、事务或并发通过。
### 12.2 首轮反馈修复范围
本批仅解除13包中Controller、Service、Repository、ClaimMapper及两份直接测试的冻结,原派送生产/其他测试保持不变。权限测试先按真实HTTP映射筛选并核对仍为10个路由,再逐项校验精确权限字符串,不能跳过正式路由鉴权。转换恢复注入现有DispatchCommandCodec,对每个嵌套车辆结果按原action解码;仅外层批次标记replayed,子车的原版本/时间/Saved载荷不变,不执行create、不读取当前快照、不注册第三套多态协议。
到期修复在阻塞来源/占用锁返回后重新核对原deadline,变更/转换最后写入后再次核对;续期后在锁内逐项核对选择集合、owner/token/容器/客户/实托和统一expiresAt,不能只延长草稿根。保留renew原拥有者、ACTIVE、尚未到期及未转换谓词,不复活过期行;更新行数与真实有效行集合联合核对,允许驱动对未改变值返回0,但不允许缺失/过期占用冒充成功。新增firstSelectionWaitingAcrossExpiryRollsBackSelectionClaimAndCommand:真实H2来源行锁、共享原子UTC测试时钟,从原到期前1ms跨至后1ms,要求失败无新选择/占用/命令且原版本不变,之后其他拥有者能唯一取得有效占用。该回归尚未运行。
File七类验证此前被DispatchEvidenceFileTest受检IOException编译阻塞;本批仅为uploadsKeepPlatformDispatchScopeAndImmutableObjects与metadataAndDownloadEnforceEveryScopeKeyBeforeReading补throws Exception,未改变断言。该文件新SHA-256为`bba87946457fb1290960218127087552de95b59f443eb6d5dacf354084d04a19`;BusinessFileCategory仍`b274532a0e4a263c56558eae68eb5717182791dec8e399e21bd459f6dffd32ff`,dispatch-evidence-v1.yaml仍`b3bc23d9f25513b258f0282886743e4323cb65b89c0203d4d2921ac89da08d14`。File七类测试此前尚未执行,本轮仍交主后端唯一Maven窗口。
### 13 既有预约整车接线只读提案
本节仅为总控决定唯一写者的提案。没有修改生产/测试/共享SQL/OpenAPI,没有运行Maven/HTTP,没有接管日历新增预约;草稿13路径与File包继续冻结。以下代码位置绑定本节末SHA快照,后续原写者继续改动的文件不是稳定实现承诺。
#### 13.1 优先解除的真实编译与运行交集
- FbaAppointmentExecutionAdapter.eligibility约87行仍调用TerminalEvidence.customerId(),当前FleetDispatchGateway.TerminalEvidence已只有dispatchNo/warehouseId/shippedPackages/deliveries,客户在TerminalDelivery与Outcome明细中。不能补回头客户或取首客户;按当前member.customerId过滤全部明细,再按destinationKey核齐本客户原实发/真实签收退回。read仍按旧DEPARTED判断是否读取证据,eligibility仍判断PENDING_DEPARTURE;应读取TransportRow的正交status/stage/主单recordVersion,保持现行执行资格,不给ACTIVE一个“待发车”别名。
- FbaAppointmentExecutionAdapterTest.proof约60行仍用5参数TerminalEvidence,改为实际4参数并增加同车多客户明细。FbaAppointmentTransportAdapterTest约46行仍用7参数DispatchBinding(含已移除customerId),实际为6参数;Detail当前6参数并未过期,不应盲目改它。
- FbaAppointmentTransportAdapter.apply约95/101/102行分别调用已移除的FleetTripService.unbindDispatch、FleetDispatchGateway.removeItem、FleetTripService.bindDispatch,直接测试的同名mock也已失效。不能恢复这些旧入口;原预约运输调整必须委托整车命令,不能自行解绑/重绑共享车次或更新数量表。原测试以A/B/C三张客户排车共用一车且头部存customer_id,须改为一张整车、真实明细客户、一个整车PDA任务;逐客户出库只在其真实阶段存在。
- AppointmentWorkDispatchMapper.references/transportRows仍联接d.customer_id;InboundFbaAppointmentQueryMapper.countActiveDispatches约47行也一样。后者由InboundFbaAppointmentService.batchContext直接调用,故不只是分配引用,既有批次候选读取在无头客户的新基线上也会失败。
- DispatchAggregateService.create/addCargo的requireBatchProvider以及addResolved的activeAppointments均是明确保护门禁。不能只删第一个门禁就宣称接通:旧bind(customer,...)在50/79行按dispatch_id删整车所有分配,循环A/B调用会互相覆盖;空分配加货也会因整车原有别的客户FBA分配被误拒绝。
#### 13.2 最小分配Provider合同
建议由原唯一写者替换旧按头客户bind,不加旧签名重载或兼容分支。复用原physical/pickedPhysical、AppointmentWorkPhysicalSources.canonical、真实batchContext与收货权威:
```java
record PhysicalItem(Long itemId, String customerId, Long planPalletId,
String sourceStage, Integer packages) {}
// MANDATORY;所有预期批次按既有统一字符串顺序一次锁齐、逐批核对当前版本。
void lockBatches(Map<String, Long> expectedBatchVersions);
// MANDATORY;仅替换touchedItems,Provider在DB核对它们属于该整车及真实明细客户。
void bindItems(long dispatchId, List<PhysicalItem> touchedItems,
List<Allocation> allocations);
// 这两个整车读取/校验签名可保留。
Map<Long, List<BatchReference>> references(List<Long> dispatchIds);
void requireDeparture(String dispatchNo);
```
PhysicalItem.customerId必须从已保存DispatchItem读取,不能从头部、请求customerId或Allocation反向推定。Allocation中的客户只作为必须匹配的断言。排车选择键PLAN:/RETURN:/RELABEL:也不能直接当预约逐票sourceKey;后者仍由真实订单规范化为BOOKING:/ORDER:,连同destinationKey核对。
创建时touched为本车全部新明细;加货时仅为新明细。Provider先读整车原分配,形成effective=原未触及行+本次新增/替换行,再按(batch,customer,source,destination)校验“其他整车已分配+effective本车量”不超真实批次。不能沿用allocated(... exclude dispatch)+仅本次增量的公式遗漏本车原量。删除限定dispatch_id与touched item IDs;A原分配应保持原样,给B加无批次/客户仓货物不能清空或要求重填A。客户仓自动DISPATCH:引用继续原规则,不伪造FBA预约版本。
版本是当前明确合同缺口:AppointmentWorkDispatchCandidates.Result已有version,但现Allocation、DispatchContracts.BatchAllocation和Admin DispatchBatchAllocation均不携带;当前sourceVersion摘要也不含预约版本,不能声称校验了用户选中时的原版本。若要满足该保证,最小补充是给两端Allocation增加嵌套recordVersion(明确指batchKey的权威版本,Long,0合法),并给候选BatchReference返回该版本;同批次多行版本必须一致,锁后比较真实FBA版本。该公共合同补充由总控/主后端与原前端写者统一决定和同步,不能本任务暗加字段。若不补,只能称“锁内当前权威核验”,原预览版本门禁不能宣告完成。
Aggregate候选当前appointmentBatches为空;应由既有来源逐票关联批次的只读Provider补真实引用/版本,不让前端猜批次或拿显示约号造绑定。可在既有DispatchCandidates读能力上增加有界批量“真实客户+planPalletId→相关批次”内部查询,不新增预约创建接口。
SQL最小修正:a→d按dispatch_id,a→i按dispatch_item_id+dispatch_order_id+真实customer_id;outbound按dispatch_id+a.customer_id,PDA按dispatch_id;transportRows增加d.stage与d.record_version。references/countActiveDispatches同样由明细证明客户。候选占用查询还应计入expires_at及全局实托占用,不能把已过期ACTIVE草稿永久判为占用,也不能遗漏RETURN/RELABEL别名对同一实托的占用。GET只筛选有效状态,不做清理写入。
#### 13.3 原运输调整消费者的最小桥接,不恢复旧绑定流程
ExecutionAdapter按TerminalDelivery.customerId与Outcome.customerId投影;completed必须来自本客户全部实发目的地的真实终态,不能用全车shippedPackages替代本客户数量,也不能用其他客户完成代替。批次范围版本摘要仍覆盖同批所有真实事实,不能因只选择客户B而漏掉A变化。
TransportAdapter.inspect按真实整车stage/计数和批次客户投影,Vehicle行至少按(dispatchNo,batchKey,customerId)分组,不能取首行客户再合并全车量。apply保留完整实物选择/原数量/同事务scope一致性守卫,但把旧unbind/bind/removeItem换成原主流程拥有的窄内部整车命令。建议接口形状如下,仅供唯一写者实现/审定,不是新增公开API:
```java
CommandResult applyExistingAppointmentChange(
Actor actor, String dispatchNo, ReasonCommand identity,
List<PhysicalItem> touchedItems,
List<Allocation> expectedAllocations,
List<Allocation> nextAllocations,
boolean removePhysicalItems);
```
其输入只能来自原批次与本事务lockAndInspect已核对的scope;主流程再核当前主版本、BEFORE_LOADING、零真实扫码、无下游执行、明细客户和原分配精确集合。移出只按已核齐完整item处理,不接受部分箱数猜实物;原绑定/来源/审核/版本/历史/资源投影与原预约改量同一事务。不得先删关联来绕过现有removeCargo保护。整车主单/资源关联保留当前统一规则,不能把“客户B退出”误作整车解绑/取消;所有明细退出也由当前空单/取消命令规则处理,不在Provider自动结案/释放资源。把父预约命令键透传为可验证的子命令身份,不能编造新随机键重做未知结果。为此FbaAppointmentTransportPort.apply及FbaReceivingService的直接调用需透传原idempotencyKey;沿用现有原命令账本,不新增第三套业务幂等协议。
此桥接之前,原预约改量消费者应显式保持未接通/不可执行,不恢复旧Fleet方法追求编译或放宽守卫;同样不能把只读/绑定修复当作该写链已完成。
#### 13.4 统一锁序与已确认反序
建议统一为:全范围trip父记录→全部车辆/司机/资源(同域稳定顺序)→全部dispatch→全部客户outbound→全部delivery(需要时)→全部既有预约批次(现有batchKey字符串排序)→来源自身既有申请/订单/实托/库存/占用稳定顺序→收货组等业务行→工作协调guard;命令键唯一记录沿各域原事务协议。锁后复读真实集合与版本,范围新增则拒绝并重试完整范围。
已有发车DispatchDepartureService约44行先requireDispatchDeparture取批次锁,46行才锁来源订单;原FBA分批/收货改量同样先batch后resolveForWrite的ll_order锁。若在Aggregate.addResolved取来源后直接补旧bind,将形成“源→批次”对“批次→同一源”的确定反序。可复现场景为一事务加同来源另一托,另一事务持原批次分批/发车后等待该来源。修法是Aggregate.create/add在来源之前预锁“原未变分配+本次请求”的全部批次;草稿转换已在调用create前锁来源,因此主后端lockDraftCreationResources必须在返回草稿域前就预锁全批groups的预约,不能只在后面的create补锁。不改冻结草稿服务来循环取另一批次锁。
FbaTransport.lockAndInspect目前只先锁trip、再dispatch,没有完整车辆/司机资源预锁;需复用主流程有界“全范围根/资源锁”入口,不循环单车方法形成trip1→resource1→trip2。当前DispatchFleetAdapter.completion已是dispatch→全部outbound→全部delivery,不能继续引用旧实现推断其仍反向取父锁。
协调锁方面,changes.requirementsChanged会UPDATE单行guard;FbaReceiving.resolve约115行seedFollowup经store.lock先拿guard,121行才transport.apply,后续可能继续取业务锁。应先收齐原运输/批次/来源/收货行与主流程变更,再做继承/失效协调写;不能把guard搬到整条业务入口后再取得父级/来源。当前guard-first同步/事项读取的直接查询未发现相反FOR UPDATE链,但这不是全域无死锁证据;新增接线必须做两会话锁竞争验证。
发车仍复用requireDeparture整车签名:批次锁内对每个实际(batch,customer)重读pending、ACTIVE agreement、SUCCESS及真实预约时间、唯一成员、source+destination覆盖/数量和替代批次状态,再核真实pickedPhysical。按(customer,item,pallet)核物理量,不能因某客户成功就放行另一个客户。发车核对当前权威,不机械冻结为初次绑定版本;后续真实收货确认可以产生新版本,结构/数量变化则按真实核对结果阻断。
#### 13.5 精确写入候选与直接回归(均待授权/未执行)
原预约消费者必需文件:AppointmentWorkDispatchPort、inboundplan/work下DispatchBinding/DispatchMapper/DispatchCandidates、InboundFbaAppointmentQueryMapper、FbaAppointmentExecutionAdapter/TransportAdapter及它们两份直接测试。主流程接线由其唯一写者处理DispatchAggregateService、必要的DispatchReadMapper/共享BatchAllocation与BatchReference,以及上述内部整车变更端口/实现;发车现有FleetTripExecutionService.requireDispatchDeparture入口可复用,不另建发车接口。原改量桥接才触及FbaAppointmentTransportPort、FbaReceivingService(父命令身份/协调顺序)。公共字段同步涉及原Admin dispatchContracts.ts、主后端共享port及总控OpenAPI;不能由本只读任务抢写。
车辆预约:当前只定位到旧DispatchOrder.vehicleAppointmentStatus/旧请求手填状态、新AppointmentReference(referenceNo,recordVersion)、DispatchInfo空投影及Aggregate.update显式拒绝;Lastleg实际业务入口/直接调用中未定位到可验证的独立车辆预约权威记录。不能用FBA批次、外接FleetBooking或旧手填状态代替。接线所需最小契约为“verifyExisting(AppointmentReference requested, Context dispatch)→原权威referenceNo/recordVersion/status/appointmentAt及可核归属”;如为远程仅能声明版本快照,不能声称跨服务原子锁。原提供者未明确前保持该门禁;持久关联位置、详情版本与审核/发车复验也需随真实提供者明确,不能只删reject然后丢弃请求。本批排除任何新的车辆预约权威表、创建API、日历新建/表单和新的预约业务流程。既有FBA收货确认/改量及其已存在后送批次属于原预约消费者,不等于本轮新增预约。
建议直接回归:①无头customer的新基线能读batchContext/references/transportRows,fixture一车多客户一PDA;②加B保留A原分配逐行不变,含A已有FBA而B无FBA/客户仓;③effective含本车原量,跨车/同车超分配均拒绝;④批次原版本0合法、缺失/混版本/替代/旧预览拒绝;⑤A已确认B未确认或pending必须挡车,B补齐后核全部真实拣货/数量,不能用头部SUCCESS;⑥同车A完成不伪造B完成,终态读使用四字段TerminalEvidence明细,未发车保持真实阻断;⑦B退出保留同车A/C与主单编号,不调用旧bind/unbind,部分110不能匹配实物时全部回滚;⑧加货/发车/原预约分批/收货确认两会话按批次→来源锁序竞争,资源与guard不能反向;⑨父命令/主版本/后续写失败时主单、原分配、来源占用、审核/历史与原批次改量全回滚,未知结果只恢复原账本。以上仅清单,没有执行。
本次读取SHA-256(源码随原写者继续变动时须重核):
```text
lastleg-service/src/main/java/com/baiyue/lastleg/appointmentwork/AppointmentWorkDispatchPort.java 45d1b7bdcb675cc6ef2f0020eac1651dd778538296913cf8d517380157ca954a
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchBinding.java 26db8a78d747d4cf25204255bbc5c2fdcde9efc0adebaea35dadec872d684e64
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchMapper.java 856a0fa618ecb143b6591cfd2ccde982c161b36181c4dc5bdf177973dd0f3351
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchCandidates.java bbd2bbdcaab8b418ef0f4732e44b765da7f9bc919c6492bc770e6ba7fc4c8c9a
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentExecutionAdapter.java fc7be6a167dd279d02b0055f8425703343eb763f2beabfd43de21ced6fa0b245
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentTransportAdapter.java e07c8049206927fe47b24734ac071f80ca3000174891053dcd86967f5376484b
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundFbaAppointmentQueryMapper.java ca61cb28603aa8a922bec4b3f8caab39fb29d6eb818fdf151e34856a378b5980
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchAggregateService.java 4dae88abe91fd872c0d0441d0ffa9f10574623bb4effdfaa9c3031cfa5d5d93b
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchDepartureService.java 3123fe0e2beb47caa30c8ecc262efc084b42fd96c1f04eb7e08ca7f54a0c0878
lastleg-service/src/main/java/com/baiyue/lastleg/fleet/trip/FleetDispatchGateway.java c71831f0af4330622a30a7f304b8ceeda91e58f982f27a5542f4d23bf64677e9
lastleg-service/src/main/java/com/baiyue/lastleg/fleet/trip/FleetTripModels.java d3419d0cb473b9cd688d8eab2bced47fcc4b073dfb23c30ac930948c09dbdaeb
lastleg-service/src/main/java/com/baiyue/lastleg/fleet/trip/FleetTripService.java 703f2a844486b484396db68f694b1c441901fec54ad66a7b9a66bef41e9ab91b
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentTransportAdapterTest.java 86a0e46ef135db7b9a89b9f33d33d62c61b28b77547f058a477bfb2ea504dda6
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentExecutionAdapterTest.java 736901b404d085447f676a5cd049a225d998519d5358ee30c506d9bc42a0d14e
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundFbaAppointmentService.java e917cced0f40b7475bb3310754a4b3dc37bc26117f6c99f697d6db3b5941ddb0
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/receiving/FbaReceivingService.java 34f4ae02c448d0abcdef0b37c163ea7214b35c92819367c995436eda7d35635d
```
#### 13.6 总控可审批的两层范围(只读,不代表获权)
编译最小包精确四文件:inboundplan/work/FbaAppointmentExecutionAdapter.java、FbaAppointmentTransportAdapter.java,以及test/java对应FbaAppointmentExecutionAdapterTest.java、FbaAppointmentTransportAdapterTest.java。前者用当前四字段TerminalEvidence的明细客户,不恢复customerId getter;后者删除三处不可编译旧调用及对应mock。若整车变更桥接尚未实施,apply应明确保持未接通并拒绝写入,保留scope/版本/执行守卫,不让测试模拟旧写成功;不能补回旧bind/unbind/removeItem追绿。测试按当前TerminalEvidence四参数、DispatchBinding六参数,并淘汰头客户/旧主状态夹具。该包只能证明编译和失败关闭,不能宣告原预约改量业务恢复。
完整接线包在上述四文件外,核心必须圈定AppointmentWorkDispatchPort、AppointmentWorkDispatchBinding、AppointmentWorkDispatchMapper、AppointmentWorkDispatchCandidates、InboundFbaAppointmentQueryMapper、DispatchAggregateService;如实施既有改量写链,再圈定FbaAppointmentTransportPort、FbaReceivingService及主后端内部整车变更端口/实现。建议新增的有界父锁方法为void lockExistingAppointmentDispatches(Actor actor,List<String> dispatchNos),同事务一次锁全范围trip/车辆司机资源/dispatch,不能逐车交错获取。其后适配器读原Mapper复核完整scope,才取批次和来源。applyExistingAppointmentChange中的removePhysicalItems只能由已核齐原scope的服务端决定,不能新增为用户可随意选择的公开字段;expected/nextAllocations必须来自原权威与本次真实核心改量结果,不以删除关联绕过守卫。
严格原批次版本若采用13.2的Allocation.recordVersion补充,须另外精确圈定dispatch/port/DispatchContracts.java、DispatchReadMapper、FleetTripService等已知直接BatchReference构造者、原Admin dispatchContracts.ts及总控OpenAPI;不因此授予目录级扩写。候选/绑定/发车只消费原预约,不新增预约权威表、日历表单或创建API。车辆预约权威当前未定位,列为外部契约依赖,保持门禁;停止扩大搜索,不为填空自建Provider/表。
总控另转交ExceptionOrderService.java约548行dispatchPdaTasks.findByDispatch(customerId,dispatchId)属于独立旧PDA消费者,待总控协调原唯一写者;未纳入本只读包写权、未读取或修改该文件。
## 14. 第13节既有预约接线实施包(2026-10-19)
本轮授权后实际实现包为下列19个后端路径;主流程公共合同、Aggregate桥接和锁实现由主后端独占,根接走的旧查询3+1不在本包。File冻结;草稿仅解除DispatchDraftService候选/视图及其直接测试,生命周期、命令重放、到期修正保持。此处仅是实施交接,编译和回归仍由唯一Maven执行者确认,不将新增测试或静态检查记为通过结果。
- 原Provider:`Allocation(planPalletId,batchKey,Long recordVersion,customerId,sourceKey,destinationKey,packageCount)`;`PhysicalItem(itemId,customerId,planPalletId,sourceStage,packages)`;`BatchReference(batchKey,batchNo,Long recordVersion,customerId,sources)`。版本显式必填,零合法;移除旧bind/requireReplay。批次预锁固定String键排序,一次锁齐,事务后续只能复用已经声明的集合。
- 候选实际入口:`Map<CandidatePhysical,CandidateBatches> candidateBatches(List<CandidatePhysical>)`;`CandidatePhysical(String customerId,Long planPalletId)`;`CandidateBatches(List<BatchReference> appointmentBatches,List<String> blockReasons,boolean occupied)`。最多1000个输入,整页两次本地SQL,来源去重后遵守原100票边界分块规范化;不逐候选循环batchContext。真实客户/计划托盘、BOOKING/ORDER、批次版本、目的地、跨车原分配余量与全来源有效实托占用共同决定结果。sources.packageCount由本托逐票实物和该批余量共同限定,零余量不伪装成可选项;缺失/陈旧归属返回阻断。occupied含本草稿自身,调用方仍按真实草稿身份核占用,不能直接阻断自己的已选来源。
- 增量绑定:逐项重查真实DispatchItem客户、托盘、阶段和数量;保留未触及实物,将保留行与新行共同计入本车批次余量。只按明确item删除,不再整车清空。发车按真实客户/item/pallet分组,重新检查当前收货确认、替代批次和实际逐票拣货。
- 原运输:消费实际DispatchAppointmentAmendmentPort。锁定方法增加真实operator;apply增加parentCommandKey。expectedAllocations只含touched原分配,next为空、removePhysicalItems=true表示完整实物移出本车;主流程派生稳定子键。没有恢复旧Fleet bind/unbind/remove别名,不凭某客户退出解绑整车。
- 执行判断:当前ACTIVE/BEFORE_LOADING等真实阶段,TerminalEvidence使用四参数结构;客户身份取TerminalDelivery/Outcome,整车发运总数不能替代客户完成量。
- guard:跟进seed移至批次、来源、运输和收货组全部写完后;Provider失效标记在同一原事务beforeCommit统一写入,避免逐item移货时先拿guard、再释放后续来源。失效失败仍使原事务回滚,无异步补偿或第三套账本。
- 草稿:整页批读当前预约投影,显式映射公共DTO末尾recordVersion;不推进草稿版本,不改来源摘要、占用和转换逻辑;同键重试仍恢复原命令结果,当前GET允许反映最新预约版本。
新增/调整直接回归覆盖同车280箱(101=80、202=100+60、303=40)、B退出剩120、完整60移出剩220、无法完整匹配110拒绝、后续失败整体回滚、同车其他客户/同客户其他实物保留、跨车并发批次余量、伪客户/版本缺失或过期、真实BOOKING来源、有界候选批读、过期草稿及RETURN/RELABEL同实托占用、草稿投影刷新与原键结果不变。原批次/来源或主流程边界被测试替身隔离的用例不等于这些生产者自身集成验收。
本轮仅执行静态直接引用核对、无BOM/尾随空白核对和git diff --check,均通过;未运行Maven、javac、HTTP、SQL环境或部署。建议唯一执行者直接运行:
```powershell
mvn -pl lastleg-service -am '-Dtest=AppointmentWorkDispatchBindingTest,AppointmentWorkDispatchPersistenceTest,FbaAppointmentExecutionAdapterTest,FbaAppointmentTransportAdapterTest,AppointmentWorkPreArrangementPersistenceTest,FbaAppointmentPersistenceTest,FbaReceivingPersistenceTest,DispatchDraftPersistenceTest' '-Dsurefire.failIfNoSpecifiedTests=false' test
```
车辆预约未定位权威提供者,现有拒绝门禁保持;未新增预约权威表、预约创建API或日历表单/面板。
19路径聚合SHA256:`a1ebcebf57812efcab400b49f8681f596941e0a3864ea2f48d937991d604fdd7`。按JS默认localeCompare排序,使用`path + 空格 + 小写SHA256`以LF连接,末尾无换行、UTF-8无BOM:
```text
lastleg-service/src/main/java/com/baiyue/lastleg/appointmentwork/AppointmentWorkDispatchPort.java 33f2ec5f8a19eaa814a9f618dc7e91908dfb609174912a98224fb89be47cd653
lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchDraftService.java 0330fe2f78484a0a744b4d5fbdb5471dd1ad1fbe5360af190040377419114d46
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundFbaAppointmentQueryMapper.java 018193279a361234401dee825d255e2c72e557b08a0fd4edb5a1c58cdf38e280
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/receiving/FbaAppointmentExecutionPort.java 64b0dab0e5a8ad74dc2b1412cd2d628b9f7f5850da72c121bb265e654b288efd
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/receiving/FbaAppointmentTransportPort.java c9cba7c2688fc0621d127b83ba0dca1693201bdff711f962e2eddc34a30b8083
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/receiving/FbaReceivingService.java 17cba0f20cb3ff2c13c8c6ad9cd38843e05aab8954f885a1e08685f36b541310
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchBinding.java a9b6c9004960f9ad0b763b156a68dc4ca59f9cbdc2646fe612a6d7a9f78be3a1
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchCandidates.java b43ced699717dfd8eafb429e67b95109d0b5189281ec37902cc70c318f1e84bc
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchMapper.java 1d0dc2a6d27eead02730fbe90263dc78435dfc258f1760e65cd5e6263375d015
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentExecutionAdapter.java eb7b3069c8557043d573cfaa96eec068047bda93a1701f9e4f0886ab7372fd43
lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentTransportAdapter.java 4124e454ea63d6803cf1d82f5376a009806088ce8213f2d736759edf369f2c9c
lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchDraftPersistenceTest.java 846aa50bb8af260a16f806cb92686f155bf5c81d2dc607f94216965e66220e96
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/AppointmentWorkPreArrangementPersistenceTest.java 8300008cda492a6be58542e1ec5e22409ebb2b22caec315b797a2c5dd83643a2
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/FbaAppointmentPersistenceTest.java dd31a3bad09797cc4c60cdaa199978deb1f217608b98590ecc823cfc932d0596
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/FbaReceivingPersistenceTest.java 0b33acb5ad56882f11746909167178d4e802c4d9e4d1885cd6f0ff35414836ed
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchBindingTest.java df2b0e6a7f86f2678ae8c857a20016e1ce9a7ed2adf6870571e0577974212e61
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/work/AppointmentWorkDispatchPersistenceTest.java 06b3fb5da55e373f874e6f700a699f60f5edd1c8d1a33498be2da3e154853f27
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentExecutionAdapterTest.java 076198846409ee929853807d3e822c9cbf106bf26fb09a69def7bbe2d715774f
lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/work/FbaAppointmentTransportAdapterTest.java f84644e00665b1579d960ae9a6378490b1f325f862c6beccbbef9291f5b7d533
```
@@ -0,0 +1,159 @@
# 排车列表统一作业改造契约
本契约规定排车列表五阶段、整车与客户货物归属、派送安排及 Admin 和海外 PDA 的共同目标。2026-10-19 用户确认一张排车单代表一趟车,并指定当前对话为本批总控;经逐项问答确定本契约的业务和界面基线,再下发三个任务做技术准备,共同接口冻结后才解锁生产代码实现。本契约描述目标及实施边界,不表示代码、部署或真实验收已完成;部署与真实验收事实仍维护在两份环境主契约。
本批规则优先于旧车次独立列表及多张客户排车关联共享车次的交互说明。旧缺陷修复规划仅用于核对已修复行为,不覆盖本批目标。
## 一 用户已确认的业务目标
1. 排车列表一次覆盖装车前、装车中、装车后、派送中、派送完成五个阶段。
2. 一张排车单就是一趟车,允许同车多个客户、多个目的仓;各票货物、库存、单据和费用必须保留真实客户归属。
3. 装车前包含车辆信息、调度审核、理货员审核;维护车辆信息后提交调度审核,再经理货员审核进入装车中。
4. 装车完成与实际发车是两个动作,均允许后台和 PDA 确认;两端使用相同服务端规则、版本和防重复约束。
5. 装车完成进入装车后;后台在装车后、实际发车前办理安排派送,核对派送信息及各客户费用,按客户和目的仓拆分派送单。派送安排完成后才允许后台或 PDA 确认发车。
6. 实际发车进入派送中;全部正常派送签收完成后自动汇总派送完成。拒收、退回等作为异常,先线下人工处理,不自动视为正常签收完成,不在本批新建线上异常闭环或伪造库存恢复、签收、账务结果。
7. 本批聚焦排车列表、详情、直接关联操作及必要生产者和消费者。车辆列表、司机管理、自有业务、外配业务、出车记录的整页改造后续逐页处理。
8. 同时支持先选同一起运仓的可排货物/托盘再生成排车单,以及先创建空排车单再添加货物;空单不能伪造货物、拣货、装车或发车事实。
9. 车辆和司机既可从已有档案选择,也允许临时填写外配车辆和司机;临时填写不伪造车辆或司机档案关联,不自行创建主档。
10. 后台确认装车完成必须以PDA真实拣货核平为前提。后台不提供替代PDA的拣货数量补录来绕过此条件;PDA和后台均可确认装车完成及实际发车的既有确认保持。
11. 用户随后澄清本次“新增预约”是预约日历的功能需求,先与本批排车改造分开整理。本批不新增日历预约创建或独立约车流程;排车已有FBA预约、车辆预约字段及权威关联继续保留。此前确认的先保存后关联意见保留为日历需求输入,不作为本批扩大实现范围的授权。
## 二 原型依据与详情四块
原型为用户提供的新版 HTML,页面 `page-outbound-vehicle`、`page-outbound-vehicle-detail`,以及本轮最新排车详情截图。HTML 位于用户提供的本机原型路径,实施者沿本契约和目标模块矩阵定向读取,不扫描原型其他模块。截图最新确认优先于前一条“三块”的描述。
排车详情继续使用独立页面、页头排车单号、状态和返回入口。用户在最新确认中明确将下列四块分别作为四个彩色图标页签,样式沿用现有后台横向页签;此确认取代此前同页四分区的布局描述。原型灰色卡片仅保留业务字段依据,具体字号、密度、底色、边线与页签使用现有公共规范。不新增路线或操作记录页签:
| 分区 | 截图字段或列 | 布局 |
| --- | --- | --- |
| 车辆信息 | 车牌号、司机、联系电话、拖车公司名称、车辆状态 | 第一个彩色图标页签;紧凑字段布局 |
| 排车信息 | 路线、发车时间、预计到达时间、FBA预约、车辆预约 | 第二个彩色图标页签;紧凑字段布局 |
| 单据信息 | 排车单号、关联派送单、创建时间、更新时间、备注 | 第三个彩色图标页签;多单号完整展示 |
| 关联订单明细 | 订单号、重量kg、托数、目的FBA仓、体积m³、集装箱号 | 第四个彩色图标页签;通栏只读表格 |
页签复用当前详情的 `density-element-tabs`、`density-tab-icon` 及公共密度令牌,保留图标、激活底色、下划线、字号和间距的一致规则;页面不另写第二套页签样式。图标优先从现有对应语义复用,具体映射在逐操作矩阵中列明。新增、编辑和审核等操作按新版原型对应弹框分别核对,详情四页签不授权改变弹框承载方式。
原型示例编号、路线示例、日期和数量仅作为样式及字段参考,不写入真实数据或作为缺失值回退。长编号和多派送单不能省略成内部ID;缺失显示“—”。样式沿现行高密度规范,保持上述业务分组。真实视觉验收由用户在1920×1080、100%缩放下提供截图。
## 三 现有附加能力的保留边界
用户明确要求外接预订、计划容量、直接成本、在途交接、车辆和司机任务结束等能力先保留,后续再接入。本批不删除这些能力及实现,不把它们新增为排车详情分区或页签,不扩展为全面车队产品改版。
排车主流程不再要求用户先进入独立车次管理建立或关联车次。车辆管理侧栏中的“车次管理”通过hidden退出菜单,日常作业从“排车列表”进入;原车次详情路由与外接预订、容量、成本、交接、资源结束等附加代码先保留。“出车记录”是实际发车后的运营查询入口,继续保留,不与独立车次管理一起移除。既有容量、资源占用、司机证照和客户隔离等必要服务端校验须随主流程保留。技术模型收敛方案由后端提出,总控核对并冻结后实施;不能仅改页面名称而继续要求用户执行旧的多单关联流程,也不能因暂不展示资源任务结束而自动释放车辆或司机。
原附加能力的直接引用若与新主流程冲突,先列明精确调用点,由总控裁定最小接线;不自行删除旧附加能力或重做其他整页。
### 下发基线与问题处理
上述三项新增规则已经由用户逐项确认,准备任务按确认结果提出技术设计。原型未定义或代码与已确认规则冲突时,执行者列出具体场景、当前行为和最小建议交总控处理,不自行添加业务限制、删除能力或改变用户操作。
所有任务以本契约、目标模块指引、用户新版原型和最新详情/样式截图为共同输入;不把旧车次交互、历史缺陷修复终点或演示值改写成本批规则。
## 四 实施任务与唯一写者
所属项目为测试环境 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`,host为local,工作区为 `C:/Users/BY-OY/Desktop/code/chongchong-global`。全部任务留在当前工作区和分支;不创建worktree、分支、项目副本或复制依赖。
总控为当前对话 `01a15230-a9d6-7503-a8a9-d70691df49e5`。旧排车对话已归档、派工未送达;用户随后明确新建三个独立任务。依后端工作量采用两个后端和一个Admin/PDA联合前端任务。技术准备和两后端交接点修订已经完成;本轮按第九节分阶段解锁,未解锁的预约在途文件及额外提供者仍保持只读。新批次不继承上一批发布、SQL或环境验收授权。
| 对话与task_id | 本批唯一职责 | 文件写入边界 |
| --- | --- | --- |
| 排车后端 `01a1524f-4f11-70c2-8a46-8e06e73a2d86` | 排车主单与货物客户归属、建单/加货、五阶段、审核、装车/发车共同执行规则;后端Maven唯一执行者 | Lastleg `dispatch/`、`fleet/trip/`及实际直接引用的Repository、Mapper、DTO与测试,`FleetBookingFreight.java`除外;不写`delivery/`及`financefee/`。后端共同接口设计文档由本任务唯一维护;File等提供者先列触点由总控分配 |
| 排车派送与费用后端 `01a1524f-56a9-7320-a5fd-8ff76fa4356b` | 装车后安排派送、按客户和目的仓拆单、费用归属/覆盖/发布及正常签收汇总事实 | Lastleg `delivery/`、必要`financefee/`、`fleet/trip/FleetBookingFreight.java`及对应测试;不写`DispatchService`、排车DTO/Mapper、`FleetTripExecutionService`。先在独占设计文件提出给主流程的事实查询与事务约定 |
| 排车前端与PDA `01a1524f-52c7-7cc3-9b08-d34ad24c172a` | Admin排车列表、四页签详情、直接弹框、API/类型、PDA装车/发车及直接测试 | Admin `overseas-warehouse`排车页面/API/类型/直接组件、`overseas-master-data`经核实的直接触点;海外PDA `src/pages/dispatch/`、`src/api/fulfillment.js`、`src/stores/fulfillment.js`及直接测试/组件。预约日历在途文件先只读列明接线,不覆盖;不写Java |
| 当前总控 | 业务范围、共同契约、任务协调、共享文件及集成检查 | 本契约、协作登记、必要索引;最终共享导航/根路由/权限/统一SQL/Gateway接线;修改前核对相关文件现有写者 |
任何任务不递归委派、不新建对话、不跨项目操作、不覆盖其他未提交修改。执行者在自身对话报告,由总控读取;收到派工不自动获得向其他对话发消息的授权。两个后端不并写同一Java类、DTO或Mapper;共同OpenAPI、权限及SQL由总控按各自提案集成。
## 五 就绪顺序与交付要求
1. 主流程后端提供共同接口和数据设计:整车编号与明细客户归属、五阶段及异常事实、每阶段可操作资格、审核/装车/发车请求、版本/幂等、历史与权限、结构变更及直接消费者。派送后端并行提出按客户目的仓拆单、费用与签收事实接口;两者先对齐主单/明细、动作资格、完成事实、事务边界与锁顺序。API路径和模型未冻结前,不让下游按猜测实现。
2. 前端任务同步完成Admin逐操作原型矩阵、字段缺口,以及PDA真实拣货、装车完成、发车和两端竞争的接口差异及回归场景。此时可并行只读分析,各任务在自身对话交付准备结果;不启动真实环境验收脚本。
3. 总控核对共同设计后更新本契约的接口补充,明确解锁各实现任务。技术例行选择不再请用户重复批准;遇到改变业务行为或截图分组的问题及时向用户确认。
4. 两个后端各自实现与自身测试,前端统筹Admin及PDA实现与测试;同一文件一个写者,后端Maven由主流程后端统一串行执行并覆盖另一后端的直接测试。共享导航/SQL/权限等由总控统一集成。
5. 交付需包含实际差异、直接消费者、已执行检查、未验证项及待发布单元。代码通过、真实HTTP通过、人工页面及PDA真机通过分别记录,不互相替代。
## 六 必须覆盖的验证
- 同一仓多个客户、多个目的仓装一车;同一目的仓不同客户的派送及费用不串客户,客户只读只能访问自己的货物和单据。
- 调度审核与理货员审核的正常通过、驳回与重提;未通过不能进入装车,改货物或关键资源后旧审核不得误用。
- 装车完成与发车分离,未安排派送不得发车;后台与PDA对同一版本同时操作只产生一次合法结果,未知结果按原请求键核对和重试。
- 全部正常签收才汇总派送完成;部分签收仍未完成,异常不伪造完成、退库或费用结算。
- 普通入仓、换标/退货来源、同托多来源及既有预约批次/工作事项的直接调用不丢来源、不重复扣库存或收费;保留上一批修复约束。
- 加载、空态、错误、无权限、附件预览及四页签长编号展示;不逐行查询列表详情或附件。
- 后端受影响测试与测试源码编译、网关路由合同、必要Mapper扫描;Admin类型检查/直接及全量测试/构建;PDA测试及H5/App资源编译按实际改动执行。
本批授权覆盖代码开发及必要离线检查。没有本轮额外授权,不提交推送、不部署、不执行环境SQL、不操作测试业务数据、不启动本地Java/Nacos/数据库。环境主契约只在存在真实证据时维护,不把本契约作为发布完成证明。
## 七 技术准备的共同对齐要求
三份独占准备文档不能代替本契约或自动解锁生产实现。准备阶段的共同对齐要求如下;本轮已按第九节明确解锁的范围进入实现,其他范围仍只读。
1. 公开写命令的版本字段统一为 `recordVersion`,包括安排派送;`expectedVersion` 如有需要仅作内部参数含义,不形成第二套公开字段或兼容别名。
2. 严格命令请求摘要与派送安排业务摘要分开:原键不能改操作者、动作、单号、原版本或载荷;另一请求键也不能重复创建同车派送或重复发布费用。全局唯一安排事实与跨操作者授权/重放边界须在两稿使用一致定义。
3. PDA已经形成的真实库存扣减与拣货来源只执行一次。安排、装车完成及实际发车不得二次扣库存;派送稿中的 `picked→shipped` 必须明确究竟更新单据计数还是执行库存命令,不能留下两种解释。
4. 正常签收资料保存维持派送到来源的原事务链,不能持子锁回头申请整车父锁。采用持久可恢复的待汇总事实,在提交后由主流程取得父锁读取已提交真实签收;两稿明确记录、消费、重试/重扫及测试的唯一写者。
5. 安排、发车、取消及扫码的实际锁点须沿代码逐一核对,明确父记录、资源、排车、客户出库/派送、来源、库存之间的具体顺序。不能各自保留一条相反序列,也不能仅靠文档宣称已无死锁。
6. 临时外配取证、实载核对、零扫码变更和客户旧创建入口按第八节用户已确认规则实施;日历新增预约按第十节留待独立整理,不再派给本批。未确认的新业务行为继续单列问题交总控,不自行扩大范围、加必填、放松校验或删除能力。
## 八 用户已确认的执行细则
用户明确回复“四项都按建议执行”,以下四项自本轮起作为开发基线;不再重复请求相同业务确认。
| 事项 | 确定规则 | 决策影响 |
| --- | --- | --- |
| 临时外配取证 | 建单人补齐本趟车辆容量、司机证照和预计任务结束,由调度审核核实;空单可先保存,审核前补齐 | 临时输入、证据上传、资格快照及审核必填;不自动建车辆或司机主档 |
| 实际装载核对 | 在确认装车弹框接入既有实载核对,有依据的实际数据自动带出,缺项再确认;保持PDA真实拣货核平前置 | 实载来源/字段/弹框及双端核验;不新增第五个详情页签,不代填拣货箱数 |
| 零扫码变更 | 保留原排车单号,显式退回装车前,修改后两级审核重提 | 新审核轮次、权限和历史;已经扫码的退装/回库不在本批新增 |
| 客户直接创建派送 | 本批整车安排仅由平台执行,客户继续查看自己的派送单,移除旧客户直接创建这类派送入口 | 派送后端移除对应Merchant创建写入口;前端任务按第九节更新Client直接消费者,保留本客户读取及合法资料操作 |
工程事项仍由总控负责:公开版本字段、请求摘要与业务摘要、真实库存扣减点、子单与来源锁序、签收持久提醒的写入和消费职责等不要求用户裁定技术细节。尚未核实的资源/预约提供者反向锁点必须在实现前补齐证据,不能用业务确认替代代码和并发验证。
## 九 工程基线与首批实现解锁
本节为总控在用户确认业务后下发的工程基线,优先于三份准备稿中仍标“待用户裁定”、旧版本字段或相反锁序的段落。精确Java/TypeScript记录、端口签名及对外Schema由唯一接口提供者先产出,消费者读取实际骨架后接入,不自行补第三套协议。
1. 采纳主流程稿的真整车主单:`ll_dispatch_order`不再以单客户头部代表全车;客户归属保留在真实货物/来源/子单。主单自动一对一关联Fleet资源记录,保留附加能力,不要求用户建立多张客户排车或操作旧绑定流程。派送采用每客户一张出库单、每客户每目的地一张派送单;公开返回完整数组,不保留单个outboundNo别名。
2. 公共主单`status=ACTIVE|CANCELLED`,`stage=BEFORE_LOADING|LOADING|AFTER_LOADING|DELIVERING|DELIVERED`,审核子流程按主流程稿第3节;取消不是第六阶段。公开版本唯一`recordVersion`,0合法。Admin/PDA均以dispatchNo识别本车;车辆/司机主档和临时填写分别使用明确mode,用户可先保存空单,审核前补齐已确认依据。
3. 公网前缀继续`/api/platform/v1/last-leg/dispatches`和`/api/pda/v1/last-leg/dispatches`。主流程API/查询统计/四页签对象采用主流程稿第4节语义,派送组合GET及整车POST采用派送稿第3节语义,依用户第八节补实载确认、零扫码退回重审及临时证据。详情仅vehicleInfo/dispatchInfo/documents/orderDetails四块;不把接口提案当已上线。
4. 采用全局唯一idempotencyKey的共同持久命令账本,绑定原主体/动作/排车及严格commandHash;同键不得换主体或载荷。安排业务另有整车唯一事实及arrangementBusinessHash,当前有权限的主体用新键、当前版本引用同一已安排业务,不再生成单据或收费;`replayed`与`alreadyArranged`语义分开。原动作结果不可变,前端随后GET当前事实。
5. 共同根锁按已核对Fleet顺序为trip→涉及的车辆主档→司机/资源→dispatch;不采用准备稿早期trip→dispatch→资源的相反序列。扫码只走来源→库存链且不取派送锁;安排/发车先收齐全部客户出库/派送锁,再取得来源/费用锁;签收保持delivery→来源→持久信号、始终不回头申请父锁。装车/安排/发车不重复执行扫码已完成的库存SHIP。未核实的预约/资源提供者交集仍须补源码和竞争测试,不宣称已证明全域无死锁。
6. 共享契约只定义在`dispatch/port/`的DTO/接口,主流程后端唯一写入。采用DispatchExecutionPort、DispatchDeliveryPort、DispatchCompletionPort及明确的提醒数据访问端口;实现分别归dispatch和delivery,不跨域共享Entity或注入对方具体Controller/Service。派送任务保存持久信号及数据访问实现,主流程负责有界消费/退避/重扫;主阶段CAS和本次已核对信号确认在同一汇总事务中完成,失败回滚,错误记录在回滚后独立短事务更新。
7. 平台新增排车、确认装车完成和确认实际发车分别使用`platform:overseas-warehouse:dispatch:create`、`platform:overseas-warehouse:dispatch:loading-complete`、`platform:overseas-warehouse:dispatch:depart`,列表/详情仍为dispatch:list,两级审核沿用既有独立审核权限。整车草稿及选货候选GET统一使用dispatch:list,草稿全部写动作统一使用dispatch:create;前端既有入仓单选货建排车入口同样核对排车查看与新建权限,不再依赖旧入仓单智能排车权限,不增加OR别名或通过补授旧权限绕过。客户仅保留本客户派送读取,不再登记或默认授予`merchant:warehouse:delivery:create`;海外PDA继续使用其独立作业角色、权限和仓绑定,不通过后台按钮权限进入作业。正式权限目录和角色关联以IAM源码及国内统一基线为准。
### 首批解锁和停止点
| 任务 | 当前允许实施 | 依赖与停止点 |
| --- | --- | --- |
| 排车后端 | 先产出公共枚举、DTO/端口精确骨架及对应编译合同,然后实施主单/来源模型、版本幂等、五阶段和审核/装车/发车本域逻辑与测试 | 公共骨架完成在自身对话提交文件/签名/哈希供总控读取;下游按骨架接入。不得擅改delivery或预约在途文件;共同SQL/OpenAPI/权限提供精确提案交总控集成 |
| 排车派送与费用后端 | 实施本域分组/单据/费用/持久提醒模型、Repository/Mapper及测试;实际整车适配读取主流程公开骨架后接入;按已确认规则移除旧merchant创建写入口 | 不更改主流程公共骨架,缺字段交总控;不执行Maven,稳定交付点把用例交主流程统一运行。不承担日历新增预约设计或实现,不抢写预约提供者 |
| 排车前端与PDA | 四页签独立详情、五阶段列表/动作弹框与双端请求按实际公共DTO接入;同时移除Client这类派送创建直接消费 | Client范围为order-management的DeliveryOrderCreateView.vue、api/deliveryOrders.ts及真实入口/直接测试,修改前读Client指引;共享路由/导航交总控。预约页面与adminDensity.test.ts在途改动保持,不承担日历新增预约矩阵;不猜API或临时兼容旧版本 |
所有任务先保留现场未提交修改;各自独占文件内可开展生产代码和必要离线验证,不提交、不部署、不执行环境SQL或真实HTTP。后端Maven仍由主流程唯一执行,测试前核对另一后端的文件稳定;中间编译/单测结果不代表全链完成。
### 当前并行收口分工
用户检查发现仅主后端执行后,总控核对两个已交付任务及实际文件,复用三个既有任务推进剩余接线,不新建任务。以下为有限实施包,覆盖对应文件的此前只读等待,不接管日历新增预约:
- 派送后端暂接File证据登记,唯一写入`file/src/main/java/com/baiyue/file/service/BusinessFileCategory.java`、新增`file/src/test/java/com/baiyue/file/service/DispatchEvidenceFileTest.java`及`file/src/main/resources/openapi/dispatch-evidence-v1.yaml`。仅登记主后端实际网关已使用的`OVERSEAS_DISPATCH_VEHICLE_EVIDENCE`和`OVERSEAS_DISPATCH_DRIVER_EVIDENCE`,平台0/整车内部主键归属,沿既有PDF/JPG/PNG、10MiB和内容签名规则;不改通用存储/Controller,不放宽其他类型。代码和用例就绪后交主后端串行执行File检查,仍不独占运行Maven。
- 前端任务取得三个既有排车消费者及同名测试的唯一写权:`appointment-calendar/WorkDispatchForm.vue`、`WorkExistingDispatchForm.vue`、`WorkSharedTripForm.vue`及三个`.test.ts`。只收敛整车创建/加货/已有单跳转和原命令恢复,消除旧客户子单/共车协议及真实类型断点;不改新增预约、WorkDetailPanel、日历面板、planningApi或公共密度测试。上述六文件移交前已核对无未提交差异;若实际遇到新写入立即停止该文件并报告。
- 总控继续集成时确认旧草稿生产链尚未收敛,主后端明确释放有限草稿包,交由既有派送后端任务唯一维护:`dispatch/entity/DispatchDraft.java`、`DispatchDraftContainer.java`、对应两个Mapper、`SmartDispatchController.java`及新增专用草稿Service/Repository/Mapper、命令持久记录和直接测试。候选仍委托主后端真实提供者;按已冻结PlanningModels及前端真实调用处理草稿版本、拥有者、来源占用及全部容器原子转换,不保留单客户旧协议。共享port、AggregateService、DispatchSourceMapper、旧DispatchService不移交;必要本域桥接由主后端写入。原派送生产及File文件仍冻结,SQL/OpenAPI交总控,草稿任务不启动Maven。
- 主后端继续唯一维护上述草稿移交包以外的`dispatch/`、`fleet/trip/`和共享端口,补审核/装发、实际来源、PDA、Fleet一对一收敛及真实读写合同;不新增页面或业务规则。主后端保留唯一Maven执行权,按稳定输入覆盖File和派送用例。前端冻结后的只读差异核对已发现Long数量/附件大小字符串造成的真实阻断,总控仅解除其原有独占范围冻结以修正响应边界、直接消费者和真实wire回归;ID/版本继续无损,不改共享解析器、DataTable、导航或新增预约。
- 总控直接承担共享数据库基线、OpenAPI、权限及根入口收口,其他任务不写这些文件;File上述独占契约除外。索引/AGENTS最终统一维护,避免另建重复状态文档。
### 既有预约接线的本轮授权
2026-10-19用户明确批准按《排车列表派送费用接口设计》第13节接线,新增预约不动。本段覆盖下列既有消费者的此前只读限制,不接管日历新增预约或建立车辆预约权威表。
- 派送后端唯一维护`appointmentwork/AppointmentWorkDispatchPort`、`inboundplan/work/AppointmentWorkDispatchBinding`、`AppointmentWorkDispatchMapper`、`AppointmentWorkDispatchCandidates`、`FbaAppointmentExecutionAdapter`、`FbaAppointmentTransportAdapter`、`inboundplan/mapper/InboundFbaAppointmentQueryMapper`,以及原`FbaAppointmentTransportPort`、`FbaReceivingService`和实际受影响的直接测试。先产出批量预锁和仅替换本次明细的薄合同供主流程消费;不写主流程公共port或AggregateService。
- 主后端继续唯一维护`dispatch/port/`和主流程,给既有批次候选引用、分配补权威`recordVersion`(0合法、缺失及同批混版本拒绝),提供版本化的窄内部原预约变更命令;负责创建、加货以及草稿全批转换在来源锁之前预锁完整批次集合。另取得`ExceptionOrderService`及其直接测试的最小适配权,仅修正新共享PDA任务接口消费并保留明细/扫码/订单按真实客户隔离,不新增异常功能。
- 前端只在原排车模型/API/wire/弹框、三个已授权既有Work排车表单及直接测试内,按实际Java合同透传批次版本;原冻结候选仅对此接线解除冻结,其他部分保持。不得猜版本、补0或改日历新增预约、面板、planningApi及公共密度文件。
- 批次分配采用本次触及明细的增量替换,保留其他客户与未变明细的原分配,并以整车有效总量复核。统一锁序为全部父trip/资源/dispatch及必要的全部客户outbound、delivery,再全部既有批次、来源及实物/库存占用,协调guard在业务锁与变更之后;不能形成来源→批次反序。原命令身份、两级审核失效、主版本、零真实扫码、完整实物及整事务回滚规则不变,不补回退役Fleet绑定/移货别名。
- 车辆预约仍须明确原权威记录、版本和归属提供者。当前未定位到该提供者时保持显式门禁,不能用FBA批次、外接预订或旧手填状态替代;此授权不包含新的车辆预约表、创建API或日历业务。
共享SQL、OpenAPI、权限仍由总控集成,Maven仍由主后端唯一执行;不增加任务、不部署、不执行环境SQL或真实业务写入。
## 十 日历新增预约的范围分离
用户澄清“新增预约”应放在预约日历,并指定由对话 `01a15231-2507-7802-8015-34b01f5eb2c4` 处理,明确本总控不用接管。三个排车任务不修改预约日历的新增预约表单、权威预约模型或预约新建API,也不承担其设计和矩阵;本批只处理整车改造确实影响的既有预约读取/关联消费者,有限接线写权见第九节,不自行接管新增预约或跨对话派工。
此前关于FBA预约可先保存、后关联真实货物和排车,以及车辆可先独立预约、后关联排车的答复仅保留为日历需求输入,其后续规则和实现由用户指定对话处理;此处不继续整理日历方案、不创建新任务、不跨对话转派,也不删除已经存在的预约功能或关联。
+145
View File
@@ -0,0 +1,145 @@
# 排车流程修复规划
本规划覆盖海外仓预排、客户排车、共享车次、PDA 拣货出库、派送及撤销之间的衔接。目标是修复取消后的占用死路、派送状态旁路、换标漏排及合托来源识别,补齐与服务端一致的前端操作入口。
2026-10-18 用户明确:当前规划对话只维护文档和分工,由指定的三个修复对话实施。本文是修改目标、文件边界和验收要求,不表示修复完成。部署状态、实际验证结果和未关闭环境验收项继续唯一维护在[测试环境主契约](../测试环境单机部署与配置契约.md)及适用的[统一认证与服务通信契约](../统一认证与服务通信契约.md)。
## 一、保持的业务主链
1. 从入仓单或已确认可出库的换标货选择托盘,创建预排分组和客户排车单。
2. 同起运仓的客户排车关联共享车次,分配车辆、司机和卸货站;跨客户共车保留各自库存与费用归属。
3. 每张客户排车单分别完成调度审核,PDA 才能拣货并逐明细核平。
4. 转派送可在待发车、拣货中或待发车就绪阶段执行,须早于发车;生成一张出库单和按目的地拆分的派送单,费用按原覆盖及外接约定复核。
5. 确认实际装载并通过理货审核,PDA 按车次统一发车;任一子单失败,全车事务回滚。
6. 签收或真实退回核平后结案,车辆、司机分别记录实际结束事实并释放。
本批保留预约稳定批次、逐票分配、工作事项通知、真实来源、客户隔离和仓绑定,不改为独立排车直接发车,不引入自动路线优化或换标分批履约新功能。
## 二、必须修复的问题与落点
下列路径中的 `java/` 指 `../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/`,`admin/` 指 `../../apps/admin-web/src/modules/overseas-warehouse/`。行号以评估时源码为定位参考,开工以当前符号和实际调用核对。
### DR-01 取消出库后释放排车并重新安排
**触发与后果:** 未拣货排车转派送,解除车次关联并取消出库后,出库记录仍关联排车。排车取消和移托只判断出库记录存在,再次转派送又重放旧取消单,形成占用死路。
**主要修改位置:**
- `java/delivery/service/DeliveryTransferService.java`:`cancelOutbound`、`transferResolved`、`replayTransfer`。
- `java/delivery/mapper/OutboundOrderMapper.java`:`findByDispatch`、`lockByDispatch` 及直接消费者。
- `java/dispatch/service/DispatchService.java`:`cancel`、`requirePalletEditingAllowed`、草稿正式锁释放。
- `java/dispatch/fleet/DispatchFleetAdapter.java` 和 `java/dispatch/pda/service/DispatchPdaWorkflowService.java`:核对取消单不可被发车、结案查询当作有效单据。
- `admin/pages/OutboundsView.vue`、`admin/pages/DispatchesView.vue`:取消顺序、下一步和失败提示。
**本批目标:** 先解除未执行车次关联,再取消出库,最后取消原排车并释放占用;货物可通过新预排重新安排。保留原取消单据、来源、费用处理与操作历史,不删除历史以绕过关联。不要求复用已取消排车重新生成出库;相同请求重放必须明确返回原取消结果,不能提示重新建单成功。活动关联判断与历史查询应分清语义,不能全局过滤取消记录后破坏审计。
**通过条件:** 完整执行上述顺序后,原活动排车锁和有效预约运输占用释放,原单据仍可追溯;同货物可重新预排。重复取消不重复撤销费用、不释放新排车占用;已有拣货、发车、其他客户或仍有车次关联时正确拒绝并保持事务不变量。财务作废仍以 Finance 确认结果为准。
### DR-02 派送状态必须服从实际出库事实
**触发与后果:** 发车未自动进入派送中时,派送仍为 `WAIT_DELIVERY`,普通状态编辑允许直接改 `CANCELLED`。后续签收、退回和车次结案均受阻;提前取消派送也可能未被发车门禁发现。
**主要修改位置:**
- `java/customervisit/service/CustomerVisitService.java`:`updateDeliveryStatus`。
- `java/delivery/model/DeliveryStatusPolicy.java`:人工状态转移和 `allowedActions`。
- `java/delivery/service/DeliveryTransferService.java`:统一取消入口及列表/详情能力返回。
- `java/dispatch/fleet/DispatchFleetAdapter.java`:`manifest`、`completion`。
- `java/dispatch/pda/service/DispatchPdaWorkflowService.java`:发车前一致性复核。
- `admin/pages/DeliveryOrdersView.vue`、对应 API/类型及直接测试。
**本批目标:** 取消统一经未执行出库的聚合命令,不能由普通派送状态编辑单独制造取消终态。已出库/发车禁止直接取消;开始派送、拒签应核对实际出库事实。发车要求关联派送完整且均可执行。签收仍由合法签收资料触发,拒签仍经真实退回处理,不开放人工直接完成或任意恢复终态。
**通过条件:** 未出库提前开始/拒签、已发车取消均被后端拒绝且页面不提供误导入口;并发取消与发车只能有一个合法结果,不能出现已发车加取消派送。正常签收、部分退回、签收后另退货、车次结案和原键重放保持原语义。
### DR-03 普通换标必须完整选择本申请托盘
**触发与后果:** 一张普通换标单有两托,只选一托也能预排;服务端随后把整张申请改为 `PRE_DISPATCH_CREATED`,剩余托盘从候选中消失。
**主要修改位置:**
- `java/dispatch/service/DispatchService.java`:`preArrangeRelabel`。
- `java/dispatch/mapper/DispatchCandidateMapper.java`:`relabelAvailable`、`markRelabelPreDispatched`、`restoreRelabelPreDispatch`。
- `admin/components/SmartDispatchDialog.vue`:换标候选、提交检查和提示。
**本批最小修复目标:** 沿用当前整单状态机,普通换标与退货换标均须一次选择本申请全部应排托盘。服务端锁定申请后重新计算完整集合并校验,前端提示不能替代服务端检查。拒绝部分选择时不得建排车、推进申请或残留占用;不在本批扩展换标分批发运。
**通过条件:** 两托选一托拒绝且零副作用;完整两托成功;重复托盘、候选变更、不同申请混选正确拒绝;取消原未执行排车后可完整重排。确认前后并发提交只能产生一张有效排车。
### DR-04 合托后按真实来源绑定外接货和约定运费
**已确认代码缺口:** 候选的入仓码为展示性单来源,箱数却为整托实际库存;`sourceCargo` 和外接运费预览继续用这组值识别原承运登记。同客户、同目的地的普通货与外接货合托后,存在漏识别外接来源或误报实收量不符的风险。实际整条混托发运后果尚需组合测试证明。
**主要修改位置:**
- `java/dispatch/fleet/DispatchFleetAdapter.java`:`sourceCargo`。
- `java/fleet/trip/FleetBookingReservations.java`:`bindIncoming`。
- `java/fleet/trip/FleetBookingFreight.java`:`preview`。
- `java/delivery/service/DeliveryTransferService.java`:`externalFreight`。
- 按实际引用核对已有 `DispatchFeeCargoMapper`、库存组成与拣货来源接口;需要持久查询时按现有分层新增最小 Repository/Mapper,不跨库读取。
- `java/palletops/service/PdaPalletOperationService.java` 只在证据证明需要维护承运实收的拆合托约束时修改,不扩展通用库内业务。
**本批目标:** 先用可执行测试固化普通来源/外接来源分别成为展示来源的两种场景。绑定和运费按实际客户、来源、目的地和本次箱数核对,展示入仓码不能替代真实组成。承运托盘证据因拆合托变化时,给出已有业务可执行的重新核对路径,不放宽承诺车次和完整实收量限制。
**通过条件:** 外接承诺不得遗漏或错误跨车绑定;逐来源数量守恒,容量不重复占位;约定运费不遗漏、不重复发布,普通货仍执行其独立费用规则。不能只修展示名称或把无法识别的外接货当普通货静默通过。
前端还须核对 `overseas-master-data/components/TripBookingPanel.vue` 的实收确认入口:服务端允许尚未绑定排车的 `RECEIVED` 重新核对时,页面应按相同状态、权限和车次限制开放,并复用现有确认接口、当前版本和新请求键。拆合托后的新实托、重量/体积及原承诺须重新核验,不因仅扩大按钮可见条件就认定整链完成。
### DR-05 页面动作与服务端门禁一致
**主要修改位置:** `admin/pages/DispatchesView.vue` 的 `canEdit/canCancel/canTransfer`、移托和车次跳转;`admin/pages/DispatchDetailView.vue`、`admin/api/dispatches.ts` 及必要 DTO;派送/出库页面只沿受影响操作跟进。
**本批目标:** 已绑定车次、已有有效出库、已拣货等限制在进入写操作前明确展示,提供处理原车次/出库的准确入口。优先消费已有服务端能力;缺失时由后端统一补充最小动作资格与阻断原因,前端不得另建一套状态机。转派送成功重放不应冒称新生成单据。
**通过条件:** 列表、详情和服务端一致;只有列表权限的用户保持只读;已取消、已关联、已转派送和并发刷新场景不能出现误导性的成功提示。保留已确认页面承载方式和操作列位置。
### DR-06 换标草稿锁定与恢复必须真实
**主要修改位置:** `admin/components/SmartDispatchDialog.vue` 的移入/移除、关闭重开、草稿查询错误处理及“已锁定”提示;如接入统一换标草稿锁,由后端任务独占对应 `DispatchService`、DTO、Mapper 和契约实现。
**本批目标:** 不再对仅存浏览器的换标选择显示服务端已锁定。后端先明确是否能在现有统一草稿模型中锁定该来源,再由前端接入;未持久化的选择必须明确其状态,不增加第二套占用协议。草稿读取失败显示独立错误和重试,不得用空数组伪装无草稿并丢失原选择。
**通过条件:** 普通、退货、换标三个来源的展示与实际锁行为相符;刷新/关窗/重开、超时、锁冲突和查询失败时原选择及占用可解释、可恢复或明确释放;后端最终防重复能力仍保留。
## 三、需先证实的来源边界
`RETURN_RELABEL` 拣货以 `returnCartonId` 记账,而 `ExceptionOrderService.appendDispatchPickSources` 跳过无 `inventoryPositionId` 的拣货记录。独立审查任务应核实是否存在当前正式替代入口,并尝试用组合测试证明拒签后能否取回原箱来源。
如确认缺口,由后端任务在既有异常退回链中补真实来源、客户/数量校验及原子入账,前端只接入同一候选契约;不可虚构普通库存仓位替代退货箱。尚未证实前不登记为普通排车全局故障,也不扩展一整套新退货流程。
`PLAN` 提前预排能力、自动配车优化、换标分批和页面全面重做不在本批实施范围;发现相关事实时只记录依赖或另列业务决策。
## 四、三个对话的唯一分工
所有任务固定使用 TEST 项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host `local`、工作目录 `C:/Users/BY-OY/Desktop/code/chongchong-global`,保持当前分支。任务身份与授权集中维护在[独立任务协作登记](../独立任务协作登记.md)。
| 对话 | 唯一职责 | 写入范围与交付 |
| --- | --- | --- |
| 排车修复 | 后端实现和代码集成负责人 | DR-01 至 DR-06 涉及的 Lastleg 生产代码、直接测试、DTO/OpenAPI及必要数据库结构定义;先修前三项,再收口已证明的来源问题。唯一维护共享后端文件、后端契约和必要公共测试支撑;组织串行 Maven 检查。不得修改前端或本规划。 |
| 排车修复-2 | Admin/PDA 前端实现 | 本文列出的海外仓页面、组件、API/类型和相邻测试;必要时沿公开入口修改车次组件、海外 PDA 门禁消费。先修独立草稿错误提示,再接入稳定后端契约。不修改后端和共享基础样式,不扩大到预约页面。 |
| 排车修复-3 | 独立审查和连续场景回归 | 只读审查后端/前端差异;唯一可新增或修改 `baiyue-firstleg/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchRepairWorkflowTest.java`。该文件先核实不存在其他写入者;不改生产代码、已有测试、共享 fixture、POM、SQL或前端。回归使用现有测试框架与真实被测行为,不能用替身把待验证门禁模拟为成功。 |
当前规划对话唯一维护本规划、协作登记和最小文档路由,读取三个对话的交付,不接管代码、SQL或构建。各执行者在自己的对话报告;可只读查看本批另外两个指定对话的进展及冻结交付,避免等待已经具备的输入。本轮未授权它们主动向其他对话发消息,接口与测试窗口由规划对话转达。独立审查不等于真实环境验收。
### 文件重叠与并行事项
- 先读取各自适用 AGENTS 和当前差异,保留所有未提交修改。`DispatchService`、`DeliveryTransferService`、`DispatchFleetAdapter` 等后端热点始终只由“排车修复”写入;前端热点只由“排车修复-2”写入;独立组合测试只由“排车修复-3”写入。
- 本批最新分工仅适用于本文缺陷,不接管预约核心、工作事项、来源同步性能或其他在行任务。不得删除已有预约批次分配和工作通知接线。
- 派工时已知“预约”对话正在执行固定 18 文件的提交、TEST Lastleg 发布及有限采样。其环境授权不传递给本批。开工重新核对活动写者、实际差异和构建进程;与活动任务重叠的文件或共享构建先保持只读,继续无冲突工作并报告精确范围,不能覆盖或使用全目录暂存混入其发布。
- 后端 Maven 仅由“排车修复”执行,运行前确认没有其他任务占用同一后端构建目录;独立测试作者交付代码后停止写入,负责人再统一编译执行。Admin检查由“排车修复-2”执行,避免同应用并行全量构建。
- 公共 IAM、统一 SQL、Gateway、根导航等共享入口不因本次派工自动转移写权。若确需调整,先交付精确变更提案,由规划对话协调唯一写者后再由代码负责人落实;规划对话自身不修改这些文件。
- 不创建新用户可见对话、分支、worktree 或项目副本;不复制依赖,不提交或推送,不启动本地服务,不执行 SQL、真实 HTTP、部署或环境数据修改。
## 五、依赖顺序与交付门槛
1. 后端先冻结取消路径、人工派送动作、整单换标集合校验及最小能力字段;前端可先处理不依赖接口的错误提示和误导文案;审查任务先建立连续场景与缺口清单。
2. 前端只按实际后端契约接入;新增/改名/删除接口或访问域时,由后端同步 Controller、DTO、OpenAPI、权限及 Gateway 合同,不以 Mock 通过代替真实契约。
3. 三个执行者交付精确文件清单、修改行为、验证命令和限制。审查绑定稳定差异/哈希;审查期间相关文件停止修改,发现由原唯一写者修复。
候选冻结是复审交接点,不能代替本批完成。有已知失败时区分测试夹具、生产缺陷和环境待验,交给唯一写者继续处理;不得删除有效正向断言或把仍可离线验证的事项全部转成环境待验。测试作者先修自有夹具并明确停止写入,后端负责人再运行;各自阶段结果与下一依赖在本对话明示。
4. 至少覆盖 DR-01 至 DR-03 的完整连续场景,以及 DR-04 两种合托来源、DR-05 状态/权限一致、DR-06 草稿失败恢复。失败、重放、并发和客户隔离不只检查最后状态,还要检查单据、占用、库存和费用副作用。
5. 后端负责人运行受影响测试及会编译测试源码的检查,前端运行相邻测试、类型检查和应用要求的完整门禁;API/Mapper/索引变化按适用指引补门禁。未改输入不重复跑无关检查。
6. 本地实现、离线测试、独立审查、环境部署、真实 HTTP 和人工视觉验收分别报告。页面视觉留待用户提供 1920×1080、100% 截图;本轮不自行生成“视觉通过”结论。未经后续环境授权,不安排部署或写入式验收脚本执行。
## 六、执行者回报格式
每个对话在自身最终回复列明:处理的 DR 编号;实际改动文件与关键行为;接口/Schema/权限是否变化;已运行命令和结果;独立审查发现与未处理项;需要其他写者配合的精确文件或契约;建议部署单元及尚未执行的环境验收。不要把计划写成已实现,不复制密钥、Token、环境凭据或客户数据。
@@ -1,253 +0,0 @@
# 海外仓库位与 A0 溢出位补齐方案(评审稿)
## 1. 目的与范围
当前海外仓可以完成接柜、收货、组托和库存入账,但尚未形成与国内仓一致的“库位—托盘—库存”闭环。本方案只讨论海外仓库位、托盘位置、A0 共享溢出位及入库后的上架/移库,不扩展海外仓主档、客户自助仓储服务或新的库存业务模型。
## 2. 当前实现与缺口
### 已有能力
- `warehouse-overseas-service` 已拥有海外库位、托盘、资源锁和托盘物理流转能力。
- 海外入库计划托盘已保存 `warehousePalletId`、`warehouseLocationId` 和资源锁。
- PDA 入库库存落账会读取托盘库位,并写入库存 position 的库位 ID/编码。
- Lastleg 已有 PDA 商品移库能力,且海外 PDA 已有移库页面和路由。
- 海外资源服务已经有平台库位 CRUD:`/api/platform/v1/warehouse-admin/{warehouseId}/locations`;缺的是 Admin 正式海外库位页面和完整业务接入。
### 主要缺口
- 真实库位分配通常没有进入入库业务,托盘会落到虚拟收货位。
- 海外库位没有国内仓已有的 A0 共享溢出语义。
- `wh_location` 没有 `shared_overflow` 标识,普通位和 A0 的并发占用规则未建立。
- Admin 现有 `/platform/v1/locations` 是国内仓页面接口,不能作为海外库位接口复用。
- 海外入库详情不展示当前库位,也没有平台移库入口。
### 2.1 评审发现的实现偏差
- 当前资源服务、资源锁和托盘流转代码只把 `VIRTUAL` 当作非独占库位;仅增加 `shared_overflow` 字段不会让 A0 生效,`reserve/release/scrap/transition/resolve/reservationBlockReason` 以及 PDA 库位查询都必须改用统一的“非独占库位”判定。
- 当前柜级转换会调用 `ensurePalletBatch` 并把返回的 `locationId` 写入入库计划托盘。新建托盘通常得到虚拟位,但复用已有托盘时可能已经带有普通位。因此“转换阶段不锁普通位”只对新建资源成立,复用托盘的行为必须在接口契约中明确,不能把所有转换都描述成虚拟位。
- 当前 PDA 移库把 `PROCESSING` 记录、远程物理变更和本地库存更新放在同一个 Lastleg 事务中。远程成功而本地失败时,`PROCESSING` 记录也会回滚,现有实现不具备方案中所称的可重放 Saga;必须先补持久化命令/Outbox 或独立事务状态机。
- 当前 `locationType` 仍允许任意字符串,现有测试和数据使用过 `STORAGE`。本方案采用 `NORMAL` 后,需在最新基线中直接收敛并同步 OpenAPI、Fixture 和测试,不保留 `STORAGE` 的双重语义。
## 3. 目标规则
### 3.1 库位类型
- `VIRTUAL`:虚拟收货位,仅用于收货阶段临时承载。
- `NORMAL`:普通库位,例如货架位、地面位,默认一托一位。
- `SHARED_OVERFLOW`:系统共享溢出位 A0,每个海外仓默认一个。
- `UNKNOWN`:仅用于发现历史缺失或不一致时的诊断返回,不是可创建或可移动到的库位类型。
### 3.2 A0 规则
1. 普通库位有可用位置时优先使用普通库位。
2. 普通位候选竞争失败且现场确认后,托盘进入同仓 A0。
3. A0 可同时承载多个托盘,但每个托盘必须有独立 `resourceLockId` 和 `reservation_key`。
4. A0 是系统保留编码,不可由后台编辑、停用或删除。
5. A0 中的单个托盘可以换绑到普通库位,不影响 A0 中其他托盘。
6. A0 是合法的实际落位,不等于未上架;只有虚拟收货位是 `putawayStatus=PENDING`。
### 3.3 库位状态矩阵(必须固定)
| 库位 | `locationType` | `shared_overflow` | `status` | 占用事实 |
|---|---|---:|---|---|
| 虚拟收货位 | `VIRTUAL` | 0 | 永远 `ACTIVE` | 不以库位状态计数,按托盘和资源锁区分 |
| 普通库位 | `NORMAL` | 0 | 空闲 `IDLE`、占用 `OCCUPIED` | 一个活动托盘;由服务端 CAS/占用事实保证唯一 |
| A0 | `SHARED_OVERFLOW` | 1 | 永远 `ACTIVE` | 多个活动托盘;按托盘、资源锁和 reservation key 区分 |
`locationType` 与 `shared_overflow` 不得出现不一致组合;不一致时查询、预留和流转均失败关闭。A0 不得通过把库位状态改成 `OCCUPIED` 表示“已占用”,否则第二个托盘会被错误拒绝或释放掉其他托盘。普通位才允许使用 `IDLE/OCCUPIED` 的库位状态机。
### 3.4 分配与物理落位必须分离
服务端可以返回普通位优先、A0 兜底的候选目标,但候选不是实物已落位。只有“扫描托盘 + 扫描目标库位”的物理变更成功,并且托盘、资源锁、库存位置和操作记录同步成功后,才把该托盘视为已上架。普通位没有候选时可以返回 A0 候选;第一期不得在没有现场确认的情况下把库存自动改写为 A0,避免把虚拟收货位误报成实际库位。
普通位候选必须由服务端选择,至少按 `warehouse_id`、启用状态、库位类型和确定排序(建议 `zone_code、location_code、id`)返回建议;候选读取本身不占用库位,最终上架/移库命令锁定目标并执行 CAS。竞争失败后重选,重选仍无普通位才返回 A0。前端提交的 `locationId` 只能作为扫描结果,不能绕过候选和同仓校验。若未来需要提前占位,必须另建带命令 ID 和 TTL 的预留表,不能提前把普通位改成 `OCCUPIED`。
最终命令仍需在服务端复验“普通位优先”:普通位仍有可用位时,直接提交 A0 必须返回稳定阻断原因;若业务确需越过普通位,只能使用独立的 overflow override 权限并要求填写原因,不能由前端隐藏候选来代替门禁。
### 3.5 分配时机
入库计划转换阶段对新建托盘继续使用虚拟收货位,不提前锁死未来数日可能需要的普通位;复用已有真实托盘时必须保留其真实当前库位并在返回中标明“已有落位”。收货完成后由正式上架命令返回候选,现场确认后再按“普通位优先、A0 兜底”提交真实位置。
平台海外实物资源的虚拟位也统一使用 `customer_id=0`。历史上按客户作用域创建的虚拟位不得继续生成新资源;迁移后若仍被引用,先完成资源锁和托盘归属收口,再允许进入新流程,不能让公共 resolve 因作用域不同找不到位置。
## 4. 目标流程
```text
柜到仓 / PDA 签收
↓
拆柜收货、扫描箱码、组托
↓
托盘暂在虚拟收货位
↓
库存入账
↓
服务端返回普通位候选;无可用普通位时返回 A0 候选
↓
扫描托盘 + 扫描目标库位完成上架/移库
↓
更新托盘、资源锁、库存 position 和移库流水
↓
必要时将 A0 托盘换绑到普通库位
```
复用已有 `NORMAL` 或 A0 实际托盘时,不再经过“虚拟位→候选”分支:库存入账直接沿用当前位置并标记该托盘 `putawayStatus=COMPLETED`;只有当前位为 `VIRTUAL` 且状态为 `PENDING` 的托盘才进入上架候选。
## 5. 改造范围
### 5.1 `warehouse-overseas-service`
#### 数据库
在 `wh_location` 增加:
```sql
shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否为系统共享溢出位A0'
```
字段本身不构成完整约束。A0 必须使用公共资源作用域 `customer_id=0`、固定库位码 `A0`、固定分区 `OVERFLOW`、`location_type=SHARED_OVERFLOW`、`shared_overflow=1`、`status=ACTIVE`;客户端不能提交或覆盖这些值。每个海外仓只能存在一个 A0,A0 的 ID 和编码永久稳定。`max_load_kg` 固定使用 `999999999.000` 哨兵值并在页面显示“不参与容量判定”,候选逻辑不得读取该值。懒创建必须在国内仓目录确认 `OVERSEAS + ACTIVE + RECEIVING` 后执行,并用固定编码唯一键加并发锁保证幂等;编码冲突、重复 A0、仓库失效或目录不可用均失败关闭。
A0 的懒创建只由候选命令(使用写语义)或正式落位命令触发;普通列表 GET 不产生写副作用。初始化失败必须返回明确的 `A0_NOT_READY`/`A0_CONFLICT` 阻断原因,不得静默把托盘留在一个不存在的 A0。
同时补齐:
- 按 `warehouseId` 懒创建且幂等的 A0;
- A0 编码冲突、仓库失效、并发创建的失败规则;
- 普通库位活动占用唯一约束;
- A0 允许多托盘共享但按托盘锁区分;
- 按 `resourceLockId/reservationKey` 单独释放;
- 基线 SQL、增量 SQL、中文字段注释和 schema 合同测试。
不能只增加 `shared_overflow` 字段:现有资源服务大量以 `locationType=VIRTUAL` 判断非独占位置,需要统一改为“虚拟位或 A0 均为非独占位置”,覆盖 reserve、release、scrap、transition、resolve、reservationBlockReason 和状态校验。A0 的 `status` 永远保持 `ACTIVE`,任何托盘进入或离开 A0 都不能修改 A0 的状态;普通位才执行 `IDLE/OCCUPIED` CAS。
当前 `wh_resource_lock` 的真实字段名是 `reservation_key`,不是 `reservationId`。它可以作为托盘级锁基础,但必须明确 `location_id` 的语义:本方案将其定义为当前物理库位,并要求移库时与 `wh_pallet.location_id` 在资源服务内原子更新;`wh_pallet_batch_item.location_id` 改为 `reserved_location_id` 快照,不再被当作当前库位。普通位唯一占用必须通过占用事实表,或带 `shared_overflow` 快照的生成列/唯一索引明确保证,不能只依赖查询后再写入。A0 的多托盘释放、报废必须按托盘和 reservation key 精确匹配,不能释放整个位。
建议复用国内仓二期的模式:保存共享标识快照,普通位用条件唯一约束保证一个活动托盘,A0 不写独占占用状态;海外实现仍以本服务的 `wh_` 表和内部接口为准,不跨库复制仓库主档。
库位解析、批量托盘响应、Lastleg Gateway、PDA/Admin DTO 和 OpenAPI 必须贯穿返回 `zoneCode`、`locationType`、`sharedOverflow`、`status`、`version`;批量转换不能只返回 `locationId`,还要让 Lastleg 区分新建虚拟位与复用的真实落位。
#### 接口边界
已有资源 CRUD 继续使用:
```text
/api/platform/v1/warehouse-admin/{warehouseId}/locations
```
该服务负责库位、托盘资源和内部物理位置变更;不负责更新 Lastleg 库存或入库业务。资源服务的物理变更必须同时更新 `wh_pallet`、活动资源锁、普通位占用事实和 `wh_pallet_operation`;Lastleg 只在远程成功后更新自己的库存和业务快照,不能直接写 `wh_` 表。
### 5.2 `lastleg-service`
- 增加或扩展平台移库命令,Admin 不直接调用 PDA 权限接口。
- 入库计划/托盘 DTO 增加库位编码、库位类型、`sharedOverflow`、库位状态和上架状态。
- 增加服务端库位候选查询和同仓校验,前端不能任意提交 `locationId`。
- 资源 Gateway 的 `locationId` 使用可空类型兼容历史无库位托盘;库位返回必须显式携带 `sharedOverflow`、`locationType` 和 `status`,调用方不得猜测 A0 语义。
- 复用 `ll_pda_inventory_move` 作为平台/PDA 共用移库命令记录,扩展 `PREPARED/REMOTE_APPLIED/LOCAL_COMMITTED/COMPENSATION_REQUIRED`、租约和远端 operation 快照;平台与 PDA 使用不同的操作人/幂等键命名空间。
- 移库时同步更新 `ll_inventory_position`;计划托盘的 `warehouse_location_id` 只作为当前值冗余字段并在成功移库后同步,`wh_pallet_batch_item.location_id` 改名为 `reserved_location_id` 历史快照,收货凭证和库存流水中的位置只读不可变。
- `wh_resource_lock.location_id` 定义为当前物理库位;普通位、A0、虚拟位换绑都必须与 `wh_pallet.location_id` 在资源服务同一事务内更新。任何锁、托盘、库存 position 或计划当前字段不一致时,新的移库、排车和出库均失败关闭并进入对账队列。
- 合托按实物托盘级移动,同一托盘内多个入仓单的库存明细一起移动;不得只移动某个客户或某条库存 position。若要部分移动,先使用既有拆托/换绑能力形成新实物托盘,再执行整托移库。
- 移库前锁定同仓该托盘全部库存 position,要求所有 position 的库位一致,保持 `available/hold/allocated/picked/receiving` 数量桶、客户集合和托盘号不变,并写零差额库存流水。正在收货、拣货、出库、换标冻结或存在未完成命令时返回 `canMove=false` 和稳定 `blockReason`;零库存托盘和孤儿 position 先对账处理。
- 混托场景要同时锁定该物理托盘的全部活动业务锁和业务引用;移动时所有客户的库存 position 一起更新。一方客户库存清零不能释放公共托盘,只有全部库存、活动锁和未完成业务引用均结束后才能释放或报废。
跨服务不使用分布式事务,但不得在持有 Lastleg 数据库事务时调用资源服务。移库命令先独立提交 `PREPARED`(请求哈希、租约、托盘版本、源位置快照和目标快照),再调用资源服务 transition;远程按 operation key 重放后进入 `REMOTE_APPLIED`,随后本地锁定全部 position/计划当前字段并提交 `LOCAL_COMMITTED`。本地失败进入 `COMPENSATION_REQUIRED`,补偿必须核对远端 afterVersion/afterLocation 未被后续作业修改;无法补偿进入人工对账和告警。批量移库按托盘逐项返回结果,不声称跨托盘全局原子。验收必须覆盖“远程成功、本地失败、重放、后续作业后拒绝补偿”。
同一 move command 重试必须保持原 `targetSnapshot` 和 `requestHash`;目标普通位被其他托盘占用时原命令返回冲突,由新候选命令重选,不能用同一幂等键静默改投 A0。只有确认远端 operation 已成功时,才允许按 operation key 恢复本地提交。
优先复用 `pda/move` 的核心逻辑,不新增绕过资源服务的直接写库接口。
### 5.3 Admin Web
新增海外仓库位正式页面、route、navigation/menu、权限和接口类型,接入已有海外 locations API,不能复用国内 `/platform/v1/locations`。
页面支持:海外仓、分区、库位编码、类型、状态、A0 标识、占用摘要;A0 禁止编辑/停用/删除。普通库位改码、改类型、改分区、停用或删除前检查托盘、库存、活动锁和未完成移库,有任何当前引用时阻断。
海外入库详情的托盘明细增加:
- 当前库位编码和库位类型;
- A0 标识;
- 上架状态;
- 单托/批量移库;
- 移库历史。
Admin 只调用 Lastleg 平台移库命令,携带当前托盘版本、源位置版本、幂等键、操作原因和源位置快照,并消费服务端返回的 `canMove/blockReason` 及每托结果。该命令经 `gateway-overseas` 的平台路由暴露,使用 `lastleg:inventory:manage` 等后台权限,与 PDA 的 `lastleg:pda:operate` 分离;请求不接收 `customerId`,客户集合由服务端从整托库存 position 解析。
### 5.4 海外 PDA
现有 PDA 已有扫描移库入口。第一期不新增完整“上架任务”体系,但需补充:
- A0 目标库位展示;
- `sharedOverflow` 文案和状态;
- 虚拟位、普通位、A0 的目标校验;
- A0 到普通位的换绑。
一件代发当前存在客户作用域的专用虚拟托盘。该特例不能直接套用公共 A0 规则;如后续需要把一件代发托盘转入 A0,必须先完成公共资源归属和锁模型迁移,并单独验收。
## 6. 状态与门禁
位置类型和流程状态分开:
```text
locationKind: VIRTUAL / NORMAL / SHARED_OVERFLOW / UNKNOWN
putawayStatus: PENDING / COMPLETED / RECONCILIATION_REQUIRED
```
`putawayStatus` 当前没有现成字段,第一期建议由当前物理位置派生,并在 DTO 中统一返回:`VIRTUAL → PENDING`,`NORMAL/A0 → COMPLETED`,位置为空或多份位置不一致 → `RECONCILIATION_REQUIRED`。后者必须阻断排车、拣货、出库和再次移库,进入修复队列,不能当作普通的未上架。若为了查询性能落库,只能在 `ll_inbound_plan_pallet` 增加一个唯一权威字段,由上架命令写入;`wh_pallet.location_id` 和 `ll_inventory_position.warehouse_location_id/code` 仍是当前位置事实,计划字段只是同步冗余,`ll_inbound_stock_receipt` 与库存流水只保留不可变快照。不能让三处各自推进状态。
允许 PDA 收货完成后仍有托盘暂留虚拟位,但虚拟位的 `PENDING` 必须阻断智能排车、PDA 拣货、出库和发车候选;只有物理落到普通位或 A0 后才进入这些履约候选。`INBOUND_COMPLETED` 仍表示库存入账完成,不等于已经完成上架。
允许的物理流转为 `VIRTUAL→NORMAL/A0`、`NORMAL↔NORMAL`、`A0↔NORMAL`;`NORMAL/A0→VIRTUAL` 一律拒绝(仅人工对账恢复命令例外),同一 A0 的 `A0→A0` 是幂等 no-op,不增加托盘版本、位置占用或库存流水。平台和 PDA 必须共用这套门禁。
## 7. 容量边界
第一期按“一托一普通库位”判断普通位是否可用,A0 只解决普通位数量不足,不实现重量/体积累计容量。A0 不是无限容量,也不改变托盘自身 `capacity_cbm`;至少维护当前托盘数、最早进入时间和可配置的软阈值告警,超过硬阈值时停止返回 A0 候选并返回稳定阻断原因。
若后续需要按承重或体积判断,还需增加当前库位占用重量/体积、托盘实际重量/体积快照、并发容量扣减和超限转 A0 的事务门禁。
## 8. 权限、审计与跨客户
库位查询、库位维护、平台移库、A0 换绑和 PDA 现场移库分别定义权限。平台资源实体仍使用公共资源作用域 `customer_id=0`,资源锁使用真实业务客户 ID;A0 共享不等于跨客户越权。普通库位和 A0 的查询、候选、库存过滤均必须以 `warehouseId` 为边界,不能让客户端传入客户或跨仓位置。
移库写入当前版本、幂等键、请求哈希、操作原因、操作人、源/目标库位快照和跨服务关联 key。优先复用现有 `wh_pallet_operation`、Lastleg 移库记录和库存流水,不新建无关联的第二套历史。增加定时或人工对账,核对托盘当前位置、活动资源锁、库存 position、计划当前冗余字段和普通位占用事实;发现不一致时记录 `COMPENSATION_REQUIRED`/人工处理,不静默覆盖后续作业。
## 9. 验收重点
1. 新建托盘转换阶段使用公共作用域虚拟位;复用已有真实托盘时保留其当前位,且不提前占用新的普通位。
2. 普通位候选仅读,最终命令原子竞争;普通位全部竞争失败后由操作员确认进入同仓 A0。
3. 多托盘并发进入 A0,A0 始终 `ACTIVE`,互不覆盖、互不误释放。
4. 覆盖 `VIRTUAL→A0`、`A0→NORMAL`、`NORMAL↔NORMAL`;同一 A0 的 `A0→A0` 返回幂等 no-op,`NORMAL/A0→VIRTUAL` 失败关闭。
5. A0 单托换绑普通位不影响其他 A0 托盘;普通位并发竞争只能一个托盘成功。
6. 合托实物托盘移动后,所有入仓单库存位置一致,数量桶守恒并写零差额流水。
7. `wh_resource_lock.location_id`、`wh_pallet.location_id`、计划当前冗余和库存 position 一致;批次 `reserved_location_id` 仍明确为快照。
8. `PENDING` 虚拟位库存不进入排车、拣货或出库候选;部分收货按已形成的实物托盘逐托落位,失败可幂等重试。
9. 位置为空或多份位置不一致时返回 `RECONCILIATION_REQUIRED`,阻断履约和再次移库并进入修复队列;远程物理成功、本地更新失败时可重放/补偿,后续作业已修改远端时补偿必须拒绝并进入对账。
10. 平台与 PDA 并发同托、停用/改码/改类型/删除被引用库位、跨仓库位、错误版本和幂等键复用均失败关闭。
11. A0 缺失、重复、编码碰撞、仓库失效、非公共作用域和阈值超限均失败关闭;A0 永远不可编辑、停用或删除。
12. Admin、库存查询、托盘管理和 PDA 展示同一业务库位码及 `sharedOverflow`;`NORMAL/SHARED_OVERFLOW` 枚举、OpenAPI、Gateway、Fixture 和测试已同步。
13. 验收夹具至少准备 1 个可用 `NORMAL`、系统 A0 和 2 个托盘;另覆盖无普通位/普通位全停用时进入 A0,以及普通位竞争时只有一个托盘成功。
## 10. 待评审决策
1. 是否采用“一托一普通库位,普通位不足时由现场确认进入 A0”?建议采用。
2. 是否允许收货完成但未上架的托盘暂留虚拟位?建议允许,但 `PENDING` 必须阻断排车、拣货、出库和发车。
3. A0 是否视为合法正式落位并允许履约?建议允许;A0 与普通位一样进入履约候选,受 A0 阈值和现场安全门禁约束。
4. 第一期是否同时开放 Admin 平台移库,并复用现有 PDA 移库补 A0 语义?建议同时开放,但共用同一 Lastleg 平台移库命令和物理状态机。
5. 是否每个海外仓固定一个 A0,还是按库区配置多个 A0?建议第一期每仓一个,ID/编码永久稳定。
6. 第一期是否暂不做重量/体积容量校验?建议暂不做累计容量计算,但保留托盘数/时间阈值告警和超限阻断。
## 11. 建议结论
建议第一期采用:每个海外仓一个使用公共作用域、按仓库 ID 幂等懒创建的 A0;新建托盘计划阶段使用虚拟位,正式上架时普通位候选优先、现场确认后 A0 兜底;A0 作为合法正式落位并允许履约;Admin 和 PDA 共用 Lastleg 平台移库命令;位置、资源锁、库存和计划当前字段按同一事实同步;跨服务使用可持久化的 Saga 状态机、补偿和对账;暂不实现重量/体积累计容量,但保留 A0 数量阈值和告警。
## 12. 开发前置清单
开发开始前应先把以下合同一次性冻结,避免各端按自己的理解实现:
1. 冻结库位枚举和迁移规则:`VIRTUAL/NORMAL/SHARED_OVERFLOW`,将现有 `STORAGE` 统一收敛为 `NORMAL`,同步基线 SQL、增量 SQL、OpenAPI、Fixture、Gateway 和测试。
2. 冻结 A0 常量和作用域:`customer_id=0`、`location_code=A0`、`zone_code=OVERFLOW`、`status=ACTIVE`、`max_load_kg=999999999.000`;冻结懒创建入口、冲突码和阈值阻断码。
3. 冻结资源服务状态机和占用事实:A0/虚拟位不改库位状态,普通位 CAS 独占;`wh_resource_lock.location_id` 是当前值,按托盘和 `reservation_key` 精确释放;移库同步锁、托盘、占用事实和操作记录。
4. 冻结 Lastleg 事实字段:`wh_pallet` 与 `ll_inventory_position` 为当前物理位置事实,计划托盘为同步冗余,`wh_pallet_batch_item.reserved_location_id` 为预留快照,收货凭证/库存流水为不可变历史;`putawayStatus` 由位置派生或只落在一个唯一权威字段。
5. 冻结平台/PDA 共用移库 API、权限、请求哈希、版本快照、幂等键命名空间和 Saga 状态;先持久化 `PREPARED`,禁止在 Lastleg 事务中直接调用资源服务。
6. 冻结履约门禁:虚拟位 `PENDING` 不得进入排车、拣货、出库和发车候选;A0 与普通位均可履约;整托移动保持所有库存桶、客户集合和活动业务锁一致。
7. 冻结验收数据夹具:至少一个普通位、一个系统 A0、两个托盘,覆盖混托双客户、部分收货、普通位竞争、A0 并发、A0→A0 no-op、远端成功本地失败、补偿被后续作业拒绝、A0 缺失/冲突和普通位改码阻断。
满足以上清单后,开发可以按 `warehouse-overseas-service → lastleg-service → gateway/OpenAPI → Admin/PDA → 端到端验收` 的顺序拆分实现;任何偏离都应先回写本方案,而不是在代码中引入第二套语义。
@@ -0,0 +1,457 @@
# 美国预约管理统一总览与优化方案
日期:2026-10-09
文档性质:需求梳理与设计建议。统一展示美国段各类预约是原方案整体方向;本轮用户进一步提出开船后提前安排提柜、到仓、FBA送仓与车次余位拼车的目标。下述页面、状态、字段与实施方式供产品评审,不代表已确认全部细则、已实现或已发布。现行预约、到仓与拼车规则仍以各自维护入口为准;需要调整的合同在本文明确列为设计缺口。部署与验收状态仍以[测试环境单机部署与配置契约](../测试环境单机部署与配置契约.md)为准。
本文维护在途筹划、对外预约与变化跟进;[拼车数据入口与操作简化评估草案](拼车数据入口与操作简化评估草案.md)维护销售接货及共用车次操作简化。两份文档保留独立业务范围,跨方案职责与交接顺序仅在本文[第九节](#九-建议实施顺序与协同分工)维护;不另建重复总方案。用户后续已安排A/B实施,原“仅整理文档、不启动开发”的阶段限制已被该授权替代;本方案仍是目标定义,实际部署与验收只以环境主契约为准。
2026-10-15 本轮预约工作日历已授权并行开发,接口及文件边界见[预约工作日历开发协作契约](预约工作日历开发协作契约.md)。本文早期的整票限制描述用于定位实现缺口,不限制本轮分批目标;第九节原 A/B 分工不覆盖本轮三任务登记。
2026-10-16 用户已确认 V13,并要求按现有任务继续开发。日历首屏、多客户共车、分批后送、改期取消、重新预约和未定日期跟进的正式规则统一维护在[预约工作日历 V13 变更说明](预约工作日历V13变更说明.md)。以下 V11—V13 评审记录保留当时状态,不再代表尚待原型确认,也不代表实现或环境验收完成。
## 2026-10-16 · V13 后送与重约评审(待用户确认)
V13 原型沿用下方同一路径。本轮下述浏览器路径及此前 24 项原型回归已通过。本节仅为原型评审记录,正式变更文档待用户确认,不代表业务代码、接口或环境完成验收,也不新增开发授权。
- 乙 160 箱移出后,可重新约仓、安排新车并登记发车;甲、丁原车仍为 120 箱,原预约不变。本次取消安排仍保留货物及送货需求。
- 后送 60 箱可单送至签收结束,也可与另一客户 40 箱组成新车并走完整条执行链。若仅从这 60 箱中安排 40 箱,原车客户卡片分别显示 20 箱待排和 40 箱新批,各一次;沿分配去向追踪,不显示失效的 0 箱事项。确认后原车仍为 220 箱,乙的各批合计保持 160 箱。
- 整份共约取消后清除失效目标,可在原批次、原车上一次办理重新共约或分别预约,明确本次覆盖范围;新共约形成新分组,再次改期、取消按新范围处理,已另约客户自动排除。退出的乙若复用甲、丁仍在使用的旧约号,会被阻止。
- 新增“与同仓待排货物一起安排”,只预选当前后送 60 箱,再由用户选择其他货物。尚未落实的单客户新批次隐藏多余变化入口;独立车辆的下一步使用本批车辆文案,不再称为共用车辆。
## 2026-10-16 · V12 共车变化原型评审补充(待用户确认)
原型沿用下方同一路径,点击“演示场景 → 共车后:客户改期 / 取消 / 缺货”。本轮新增 10 项原型浏览器检查通过,结论仅限原型;正式变更文档待用户确认,不代表业务代码、接口或测试环境完成验收,也不新增开发授权。
- 新变化场景使用 CC020 / TR020,甲 80、乙 160、丁 40,共 280 箱;原 CC001 / CC003 多客户选货流程保留,两段演示分别评审。
- 独立预约下,乙改期或取消本次安排后,160 箱移出原车继续跟进;甲、丁合计 120 箱的预约不变。乙先送 100、后送 60 时,原车为 220 箱,逐来源数量守恒;填 0 可整批移出。本次取消仅取消该次安排,保留货物和送货需求,不表示订单取消或客户撤销运输需求。
- 共用预约下,单客户移出须明确取得仓库同意;整份预约改期同步 3 个客户,整份取消列出 3 客户加 1 车的影响,已取消预约不能再选择保留。原车安排核对一次,无实际变化的保存不重复触发复核。
- 执行页货未齐可直接进入对应客户处理;尚未获回复可保存待确认内容及勾选,原值保留并阻止发车,再进入可直接续办。本轮夏令时切换中不存在的当地时间样例已验证阻塞;这些演示结果不代替完整权限、并发或时间规则验收。
## 2026-10-16 · V11 原型评审补充(待用户确认)
原型入口:`C:/Users/BY-OY/.codex/visualizations/2026/10/14/01a13a8d-e968-7962-906b-1a514792d921/appointment-calendar-guided.html`。本节仅供 V11 原型评审,不是正式变更文档,不新增开发或部署授权;原方案正文、已完成实现及技术验收事实保留。
**现有能力:不同客户同目的仓可以共用一车。** 本轮改善预约页一次选货、连续办理预约与共车的操作,各客户来源、数量与结果仍分别保留;同车不等于共用预约号,已有核实、分批和返回上下文也不列为新增。
**原遗漏**指前两轮原型中海上提前安排、取消后跟进、延期逐项处理及部分失败续办的交互分支;**操作改善**指多客户一次选量、多行分批、计划回复确认连续填写和保存后下一步,不代表既有业务功能不存在。
### 五条可走通的原型评审路径
1. **演示场景 → 海上提前安排。** 打开 CC007,核对已有预排起止窗口,填写意向车队和联系结果后保存,再用下一步继续;该柜已有目标,不属于未定日期。此场景码头尚未开放正式预约,可以留计划和回复,不能登记为已确认。
2. **演示场景 → 中转分批 / 多客户共车。** 选择 CC001 / CC003 示例货物,共 280 箱(甲 80、乙 160、丁 40),按来源选量后统一填写车辆;默认分别保留客户预约号,只有仓库明确允许才选择共用约号。保存后逐客户查看结果并继续车辆安排;另可独立评审原批分成 3 批,核对逐来源自动余量、各批目标和总量守恒。
3. **演示场景 → 整柜直送 / 还空。** CC002 的 TR002 同时承担提柜和直送,仓库收货确认独立办理,不重复约车。沿下一步查看执行条件:实际目的仓卸空前不能还空;还空转交新车队后须再次明确接手,不能沿用原车队的接手结果。
4. **演示场景 → 未定日期 / 取消。** 打开 CC004 客户仓收货,目标日期留空,先保存资料或回复;取得结果后登记确认,再取消预约,核对事项回到未定日期且继续保留跟进。客户仓按真实要求选择是否预约,不强迫填写 FBA 货件号;无需预约时补收货要求,不伪造约号或确认结果。
5. **演示场景 → 延期逐项处理。** 模拟 CC003 备货延期,已完成提柜、卸柜保持原事实,只核对未执行的送仓与用车。逐项选择“保留原安排”“重新约时间”或“调整本批货物”;调整货物仅把部分数量移出至未定日期,剩余货量重新取得确认,不是任意换入新货。处理当前项后继续其他影响项;无实际变化的保存和关闭本项复核不重复触发关联复核。
### 待确认边界与未演示规则
- 当前异常演示仅有共车表单的“第二客户组已保存货物,但关联车辆失败”和“模拟当前账号无写入权限”。前者只重试失败关联,保留已保存货物与数量占用;后者保留输入,不代表完整权限与异常验收。
- 请求结果未知、并发版本冲突、原幂等请求重试及新影响版本保护属于实施建议,尚无原型实际模拟,待实现验证。各类型动态开放条件也未完整模拟,当前仅演示 CC007 海上码头未开放阻塞与确认字段校验。
- 默认负责人、跟进日期、分批行数和选择范围仍待用户确认;负责人仅有 3 名授权示例,DST 仅有特定演示日期的歧义选择。原型通过不代替接口、权限、数量或真实执行门禁验收。
## 一 页面定位与核心结论
“预约管理—预约列表”应成为美国段提前筹划和预约跟进的统一入口。从真实开船及在途货物清单出发,让运营知道:哪些柜快到了、各目的仓有多少待送货、何时有望备妥、现在该联系谁、哪些已经约成、哪些车还有可发布的余位。
范围包括提柜、海外仓接仓卸柜、用车、FBA及其他送货、还空等美国段事项。保留现有菜单名称,页面标题使用“预约工作日历”;默认日历首屏,待办、货柜和送货批次明细承接具体操作。尚未约到时间及未定日期的工作必须能被看到。
统一的是查看入口、关联信息和操作入口。提柜、车次、派送、收货仍由各自业务模块保存权威事实;总览读取和联查这些记录,修改时回到对应业务命令,避免运营在多个页面重复维护同一事实。
需要区分三种事情:
| 事项 | 例子 | 总览如何表达 |
|---|---|---|
| 对外预约 | 码头提柜时段、FBA收货时段、客户现场收货约定 | 显示预约状态、当地时间、地点、对方确认信息 |
| 内部作业计划 | 安排车辆司机、预计装车、计划发车 | 显示执行准备和资源安排,不冒充对外预约成功 |
| 参考节点与提醒 | 预计到港、实际到港、还柜截止 | 单独图层或待办提示,不计入预约成功数量 |
**“约车送FBA”通常同时涉及运输安排和FBA收货预约。** 车已安排不代表仓库已确认收货;仓库约好也不代表货齐、车到、可以发车。页面应把两者关联展示,分别保留状态。
### 1.1 从开船开始并行筹划
| 阶段 | 系统应提供的信息与建议动作 | 人工负责的决定 |
|---|---|---|
| 已开船、货在海上 | 读取真实柜内货物、接柜海外仓、目的FBA仓、最新ETA及来源;形成提柜联系待办和送仓货量预览 | 核对接仓地点、货量和预计时间,指定负责人 |
| 预计到港前 | 展示目标提柜/到仓窗口,按目的仓和货物可备妥窗口汇总;准备联系资料和约车需求 | 联系拖车公司、接仓方、送货承运商;允许先记录意向和对方反馈 |
| 对方开放预约且资料满足 | 提示可申请、缺资料、等待开放或等待对方回复;保留申请时的货物范围 | 人工提交预约,取得对方结果后登记确认时段、确认号及凭据 |
| 货到仓前后 | 核对实际提柜、到仓、卸柜/理货与预计货量差异;把已选在途货关联到后续真实作业单据 | 确认送货批次、承运车次和时间;处理少货、换标未完或延期 |
| 车次具备发布条件 | 带入有效的自有货计划占用和逐目的站剩余容量,链接现有拼车需求池 | 调度确认发布;销售登记意向,调度确认承运才占位 |
提柜沟通、收货仓排班、FBA预约准备和承运商询车可以并行。正式提柜、实收入库、拣货和发车仍按实际作业条件执行,不因提前安排而推进完成状态。
### 1.2 时间按用途分开,预约按对方规则办理
建议展示一条可追溯的时间链:**预计到港 → 预计可提柜 → 预计到海外仓 → 预计货物可备妥 → 目标送达 → 对方确认时段**。前三项也不能相互替代。
- ETA来自当前权威船节点,保留来源、更新时间和变更前后值。未查到ETA时进入“待补到港预报”,不直接用开船日加固定航程伪造。
- 预计可提柜需考虑卸船、清关/放行及码头可提信息;预计到仓还涉及拖车与接仓安排;货物可备妥还涉及卸柜、理货、打托或换标。可以由运营维护预计区间和依据,不要求首版建设复杂预测引擎。
- 目标送达需在预计备妥后留出装车、行驶和业务缓冲。先做可解释的区间预排;按港口、仓库、线路维护经验参数时,应允许人工核对,不能全美国统一写死“到港后两天送FBA”。
- 将“希望约的时间”“已申请的时间”“对方确认的时间”分开;可以提前联系,但正式可申请时间取决于具体码头、仓库和承运商。
- 每个预约地点按需维护预约方式、联系人、当地时区、开放条件、所需材料、改期/取消要求和规则核对日期。外部账号凭据不放在预约备注里。
外部规则核对(2026-10-09):[APM Terminals洛杉矶预约说明](https://akamai.apmterminals.com/en/los-angeles/online-services/truck-appointment-system)要求进口柜卸船后才能设置提柜预约,说明“提前安排拖车”和“码头正式约号”可能发生在不同时间;不能将这一家码头的条件推广为所有港口。[Amazon美国Carrier Central手册](https://images-na.ssl-images-amazon.com/images/G/01/magicarp/common/Carrier_Central_Manual_USAmazon.pdf)区分申请日期与授予时段,要求承运商有把握按约送达,并禁止使用货件资料建立占坑或重复预约。本文据此建议先做好内部预排,再按对应机构条件确认,不预设“开船当天即可拿到所有正式预约”。
### 1.3 以送货批次连接货物、预约和车次
建议在现有业务内补齐“送货批次”的计划关系:按**实际接货海外仓 + 目的FBA仓/准确收货地址 + 可备妥时间窗口 + 运输与收货要求**组织候选,再由运营选择。它表示这批货打算一起送,不能代替客户订单、库存、车次或对方预约。优先复用现有预约、货物和排车关系承载,选货与保存安排意向一次完成,不要求运营额外手工建一张中间单;是否需要新增持久化实体在实现评审中确定。
- 同一柜按目的仓拆成不同候选组;不同柜可以在同一接货仓、相容时间窗口内合并。首版默认只合并同一目的站,跨站同车由调度沿既有路线能力明确安排。
- 同时展示在途预报、已到仓未备妥、已备妥三类货量,以及已有安排与尚待安排量。箱数、预计实托、预计托位、重量、体积分别表达;未知保持未知,不以头程托数冒充海外最终托位。
- 选货必须关联稳定来源货物明细及本次数量,并检查已有有效安排;建入库计划或收货后延续同一来源关系,不再把这批货计为新增需求。现行模型不能拆分同一明细行时,首版仍整行选择,不在页面虚构拆批能力。
- 对FBA申请,系统准备已有货件号、目的仓、箱/托等清单;缺少该机构要求的资料时显示缺项,不能只凭“有多少托去ONT8”就标记可正式申请。
- 内部预排允许货未到仓、司机未定、外部约号未取得;这些缺项应作为跟进事项。转成正式承诺和现场执行时,再核对对应阶段条件。
例如:两个在途柜分别有同一接仓点、相近备妥窗口的ONT8货物,预计占10和8托位,可人工合成一个18托位送货批次。选用实际容量为30托位的车后,还须校验重量、体积和已确认外接占位;若同一路段三维容量均允许,才可能发布12托位。一个柜延期时应明确指出受影响的这10托位、预约及车次,由调度决定等货、换货或改期,不能自动拆单或更改对方约定。数字只作业务示例,不是默认车型或固定容量。
## 二 当前能力与缺口
以下为当前源码入口盘点,属于实现结构判断,不代替环境验收。
| 业务 | 已有承载 | 当前信息基础 | 统一总览的缺口 |
|---|---|---|---|
| FBA送仓预约 | Lastleg入仓计划预约;Admin预约日历 | 预约号、目的仓、开始/结束时间、预计装车时间、状态、跨客户货物明细 | 当前总览主要覆盖这一类;排车的预约字段与预约主记录分开维护 |
| 船舶到港 | Firstleg到港日历 | 预计/实际到港、柜号、船名航次 | 已显示,但属于参考节点,需要来源与类型标识 |
| 码头拖车提柜 | Firstleg目的港码头拖车;海外清关提柜 | 车队、预约提柜时间、实际提柜、还空信息、允许操作 | 尚未接入预约日历;现有查询主要按柜次ID读取,不能直接当全美国按日期查询 |
| 海外仓预计到仓 | Lastleg柜级到仓接口 | 预计到仓、PDA实际到仓、版本 | 预计到仓不等于收货仓确认的预约时段;不能直接标成“已预约” |
| 车辆和司机安排 | Lastleg共享车次 | 计划发车、预计司机结束、车/司机、站点、审核、实际装载 | 尚未接入总览;车次是运输执行载体,不是单一收货预约 |
| 普通送货及FBA派送 | Lastleg派送单 | 计划送达、目的仓/地址、关联排车、承运资源、签收 | 派送计划时间不能直接作为对方确认时间;需关联具体收货预约 |
| 外接货承运预订 | 车次外接预订 | 客户、货量、既有卸货站、确认承运、来货实收 | 确认承运不等于目的地预约确认;不应重复生成一条同义送仓预约 |
| 本土卡车、本土散板 | 海外业务订单 | 需求日期、目的地、联系信息、订单及车次关联 | 需求日期不是精确预约时段;缺少时段时应显示“待确认时间” |
| 内部拼车需求池 | 共享车次余位发布、销售意向与外接预订 | 已有专门开发契约和实现入口 | 预约页缺少与车次发布资格、余位和销售跟进的衔接;应复用现有池,不能再建一套 |
当前页面主要从“已经有日期的预约”出发;用户需要从“还在海上的货及尚未约好的工作”出发。关键缺口是开船后的待办生成、按目的仓归集的在途货量、可备妥窗口、人工联系记录,以及船期变化对既有安排的影响。
本轮已读到的当前规则还提示两个实施边界:FBA预约以入仓计划明细为选择对象;柜级预计到仓在已有入库计划后锁定。提前规划不能靠提前伪造收货,也不能直接把持续变化的ETA写进已冻结的到仓字段。相关源码核对与建议见第八节。
## 三 统一展示的业务范围
### 核心范围
| 类型 | 一条记录代表什么 | 关联对象 | 创建或维护方式建议 |
|---|---|---|---|
| 码头提柜预约 | 某柜在某码头的一次提柜预约 | 柜次、集装箱、码头、承运车队,必要时关联运输任务 | 选择已有货柜,自动带入柜与港信息;填写时段及确认信息 |
| 海外仓接仓预约 | 接仓方接受某柜/批来货的到仓卸货时段 | 接柜海外仓、柜次或来货单、运输安排 | 预计到仓作为参考;人工联系仓库,单独登记仓库确认的接收时段 |
| 用车与装车安排 | 一个车次的装车/出发安排 | 车次、车/司机或外包车队、起点、站点、客户排车 | 选择或关联车次,复用资源分配、审核和容量校验 |
| FBA收货预约 | 某FBA仓在某时段接收一批货 | 多客户入仓货物、预约主记录、承运车次/站点 | 搜索仓库,选择同仓货物,登记收货预约 |
| 普通客户送货预约 | 某客户地址或非FBA仓的一次收货约定 | 派送单、地址、收货联系人、车次/站点 | 从派送目的地带入信息,补充收货时段与确认结果 |
### 同一总览应覆盖的扩展事项
以下应纳入分类设计;缺少正式预约模型的部分,需要补齐业务合同后接入,不能直接把现有日期换个标题就当作预约。
| 类型 | 建议处理 |
|---|---|
| 还空柜安排 | 还柜预约与还柜截止提醒分开,实际还空由原业务事实更新 |
| 客户自提/承运商提货预约 | 按出库或派送来源建约,区分对方来我仓提货与我方送货 |
| 仓间转运/退货提送 | 有实际运输和收货时间约定时纳入;库存移库、退货申请本身不生成运输预约 |
| 临时其他预约 | 最后考虑受控兜底类型,至少有事项、地点、时间或待定标识、负责人;能归到正式业务类型的必须归类 |
“美国所有可预约数据”指系统经营范围内、业务地点属于美国的预约和计划,不是承诺接入全美国所有仓库或码头的外部预约平台。第三方代约、查号与自动确认需各自接口、账号和验收支持。
国内订舱拖车继续留在国内业务。美国范围应由业务地点的国家主档确定,不能把全部海外记录或所有FBA仓一律当成美国。
## 四 预约 货物 车次之间的关系
### 一次预约可以关联多个客户和入仓码
例如A、B、C、D、E五个客户送ONT8同一时段:建立一张收货预约,货物明细保留各客户归属,再关联承运车次。预约卡片展示“ONT8 · 09:00–11:00 · 20票 / 5客户”,不拆成五张重复预约。
同仓同时间并不自动等于同一预约。是否合并还应核对对方预约要求、货物资格及实际承运安排;操作员明确勾选后由服务端校验。
### 一辆车可以有多站 不同站分别预约
车次T先去ONT8,再去LAX9:用车安排只有一条;ONT8和LAX9分别保留收货预约,均关联车次T及对应站点。总览可以按车次分组展开,不能把两站合成一条没有明确地点的预约。
一个入仓单后续若允许拆批或多车配送,关联必须落实到本批货物/数量,防止整票重复占用。目前FBA预约按入仓明细行占用,不能未经模型调整就宣称支持同一行拆分预约。
### 多条业务单据不重复计算同一个预约
预约、排车、派送引用同一收货预约时,总览只显示一个收货预约事件;卡片内列出关联车次、排车和派送数量。用车计划作为不同类型的关联事件保留,不与收货预约混成一个状态。
建议明确:FBA预约号和预约状态由预约主记录维护;排车、派送展示按货物关系读取。一张排车覆盖多站、多预约时,展示预约列表或“2个预约”,不能把单个字符串覆盖成最后一次预约。
当前排车预约字段独立维护的问题必须在实施前收敛,否则页面会同时出现“预约成功”和“排车待预约”。此项是建议的修正方向,尚未代替现有业务合同。
### 车次余位与现有拼车池衔接
沿用[内部拼车需求池首版开发契约](内部拼车需求池首版开发契约.md):一车次一发布,外接货统一在我仓上车;询价不占位,调度确认承运才占位。预约页只增加发布资格摘要及进入原发布操作的入口,销售继续在原需求池工作。
**建议允许提前做用车需求和送货批次,但保持正式余位发布条件。** 尚无车辆/司机、真实起运仓/卸货站或有效容量计划时,显示“预排中,暂不可发布”及具体缺项。承运商仅口头表示“预计有车”不能当作可发布运力;如以后要销售尚未落实车辆的远期运力,应另行评审,而不是本轮放松现有门禁。
车次准备、容量核对、发布窗口及部分成功续办统一由[拼车优化草案第七、八节](拼车数据入口与操作简化评估草案.md#七-调度准备车次与发布余位)细化;预约页读取车次服务返回的逐目的站余位、资格与缺项,不实现第二套计算或发布表单。船期/货物变化由预约侧提供影响依据,车次侧重新核对运输承诺;不自动扩大余位或静默取消已确认外接订单。实际规则继续以拼车正式契约为准。
拼车新增货物后,预约侧按稳定来源核对目的仓、货件材料及预约覆盖,车次侧展示同一结果并引导处理。确认承运保位不能推定收货方已经接受新增货物;需要补充货件或改约时交预约负责人,不自动再建一张同义预约。两类货源的可预约阶段与检查时点须在第九节的首次交接中明确。
## 五 页面和交互优化
### 总览布局
建议在同一菜单内使用三个工作视图,避免把所有业务字段塞进一个通用大表:
| 工作视图 | 一行/事件的组织单位 | 首屏信息与主要动作 |
|---|---|---|
| 提柜与到仓 | 一个来源货柜 | 操作、柜次/柜号、港口→接仓点、ETA及更新标识、目标提柜/到仓窗口、拖车联系/码头约号结果、当前缺项、负责人/下次跟进;进入原货柜业务维护 |
| 送仓与排车 | 尚未安排的同仓同窗口候选组,或已建立的送货批次;二者明确标识 | 操作、起运仓→目的仓、预计备妥窗口、货量/可用状态、收货预约、承运安排、余位发布资格、负责人;选货保存安排、登记预约结果,带入共用车次入口,不另建建车/发布表单 |
| 预约日历 | 去重后的预约事件;内部作业及预报可选显示 | 按日/周查看对方确认时段及待确认安排,可切换列表;按类型、地点或车次查看,不用一条综合状态覆盖所有事项 |
日常进入预约工作日历,顶部全局待办显示全部、今日跟进、超期、未定日期和需复核,不受月份、流程与类型勾选影响。点击后进入对应明细。每条待办展示负责人、下一步和下次跟进日期;同一柜或批次的多个问题合并提示,展开后逐项处理,避免提醒数量淹没实际货量。
“送仓与排车”增加目的仓货量汇总,默认按实际起运仓及未来可备妥窗口查询,可按需要切换7/14/30天。每个目的仓分别展示在途、在仓未备妥、已备妥货量及待安排量;未确定备妥日期的货物单列“日期待定”。已安排货物不再次进入未安排候选,跨窗口统计不能重复累计同一批货。
顶部保留日期、类型、地点/仓库、状态和关键词搜索。日期条件需注明当前筛选的是“预计到港”“预计备妥”还是“预约时段”;不能切换视图后无提示地把同一个日期变成另一种含义。关键词支持预约号、柜号、入仓码、车次号及客户业务名称;车牌、司机、负责人等放入更多筛选。
前两个视图使用工作列表;第三个统一承载月/周/日历及对应时间安排列表,不为每个工作视图再建一套日历。月视图负责概览,周/日视图负责排班,列表负责搜索、批量核对和导出。统一日历与其列表切换时保留筛选;跨业务视图保留通用条件并清楚显示各自日期口径。操作列按Admin规范放在第一列;大量货物明细只在展开或详情按需读取。
月历单格固定高度,按已勾选工作类型聚合数量,点击类型或状态数量进入当天明细,不随事项数量堆叠卡片。明细按实际、确认或目标日期与时间展示;未定日期事项进入独立待办,不伪造09:00或00:00占位。
到港参考通过独立开关显示,不计工作量;还空属于必需工作类型。工作数量包含未安排、已确认、无需预约、需复核及已完成,并明确统计口径;预约取消保留原记录、工作需求与继续安排入口,不能从待办漏掉。
以上为信息结构建议,尚不是已冻结视觉原型。实施时逐操作核对现有新增、详情、编辑的承载方式;未定义操作形成评审矩阵,人工按1920×1080、100%缩放确认,不以本方案代替视觉验收。
### 卡片内容
首屏只展示类型、地点、时段与时区、预约状态、运输安排摘要、货物统计和需要处理的问题。联系人、附件、操作历史、客户与货物明细按需展开。
入仓码独占一行区域,默认3条并显示总数,展开后独立滚动;大量货物使用可搜索、可分页的关联明细,不能一次拼接数百个编号到卡片中。备注缺失不占一整格;长备注默认摘要。
卡片提供“查看来源单据”“查看关联车次”等操作。编辑、改期、取消是否可用由来源业务权限和当前状态决定,不因用户能看总览就允许修改所有类型。
### 新增流程
1. 优先从货柜或目的仓货量发起,自动带入业务对象与货物;通用“新增”入口再选择提柜、接仓、FBA或普通送货等类型。
2. 先保存“预约安排”:目标日期/窗口、负责人与下一步;允许对方约号、车辆和司机暂缺。原有待办应直接补充,不另建一份重复事项。这与拼车侧的“客户货物登记”分别命名、分别维护,不能共用一个含义不明的“意向状态”。
3. 人工通过电话、邮件或外部预约平台沟通,记录联系对象、方式、结果及下次跟进;系统可整理/导出既有货柜与货件资料,不能把资料导出当作已发送或已申请。
4. 申请后登记申请时间及反馈;对方确认后再记录确认时段、外部号或适用的确认凭据。回到关联批次核对承运和货物是否就绪。
新增入口可以预先带入当前选中的日期,但时间应由用户确认;地点改变后重新核对时区、可选货物及资源,清空不再匹配的选择。继续保留并发版本校验和稳定幂等,避免重复点击创建重复预约。
## 六 减少填写项的具体规则
| 信息 | 建议 | 约束 |
|---|---|---|
| 仓库/码头 | 主档搜索选择,显示编码与名称;码头可由货柜带入 | 不接受自由文本冒充已存在地点;地点未维护时给出维护入口 |
| 客户/入仓码/柜号 | 选业务对象或货物后带入 | 不能让运营在预约表单再手填一遍;保留真实归属 |
| 箱数/托数 | 从所选货物汇总,计划值和实收值分别标识 | 不允许为了少填而拿预计值冒充实际值 |
| 车辆/司机/电话 | 关联车次后读取,外包运输复用承运车队信息 | 不在FBA预约中重复编辑司机档案;允许预约先于派车 |
| 预约日期与时段 | 核心操作信息;支持“时间待确认” | 待定事项不计入已确认时间表,确认预约时按类型校验 |
| 预约结束时间 | 选填;对方给出时间窗时填写 | 不自动假定两小时,不用司机任务结束时间替代 |
| 预计装车时间 | 移到车次/装车安排;在预约详情作为关联信息查看 | 当前FBA接口与表结构要求非空,实施要同步调整,不能仅隐藏字段或伪造默认值 |
| 预约状态 | 根据确认操作更新,普通新建可默认待确认 | 保存表单不等于对方确认;执行完成以来源事实为准 |
| 预约编号 | 区分系统业务号与外部确认号 | 建议系统生成内部业务号,外部号在取得时补录;现有appointmentNo语义与唯一约束需先明确,不能把随机号当码头/FBA确认号 |
| 联系人/地址 | 从目的地或来源单据读取,缺失时按类型补充 | 美国客户地址不强制伪装成FBA仓;变更需要留痕 |
| 负责人/联系记录/下次跟进 | 默认带入当前操作者,可按权限分派;一次联系只补结果和下一步 | 拖车承诺、码头确认、收货仓确认分别记录对应公司,不能用一个“对方已确认”混用 |
| 货物预报与预约材料 | 从柜内货物、来源订单及后续入仓计划读取已有内容,只补实际缺项 | 内部入仓码不能代替对方要求的FBA货件号、BOL或其他预约资料 |
| 备注/附件 | 默认收起,异常、改期等动作按需要求原因或凭据 | 不删除业务真正需要的例外说明;文件仍遵守原权限 |
| 运费/成本/账单 | 留在报价、运输和财务流程,可关联查看 | 不放进通用预约新增表单要求运营重复填写 |
目标是“系统已有的不用再填,只填本次预约新增的信息”,而非简单删除所有字段。
## 七 时间 状态与提醒
### 美国当地时间
预约录入和确认以业务地点时区为准,使用主档中的IANA时区,界面显示时区标签。存储和聚合需要同时保留可比较的时间点及业务地点时区;仅有无时区日期字符串时,必须先确认来源时区,不能按操作者电脑时间自行解释。
单地点视图默认当地时间。跨时区总览明确展示所选总览时区,卡片同时保留地点当地时间;日历分组和查询范围使用同一明确时区,避免日期错一天。夏令时切换时重复或不存在的当地时刻要明确校验,不静默偏移。
仅有日期的本土运输需求显示“当日待定时段”;没有日期的事项显示在待安排列表,不凭空推算。预计、已约、实际时间分别保存和展示。
### 状态分开表达
建议预约确认状态归纳为待安排、已申请待回复、已确认、已取消、未约成;“待联系、未开放、缺资料”作为待办原因,不增加大量互斥状态。作业执行显示未执行、进行中、已完成及异常提示;货物准备与承运安排各自显示摘要。各来源已有状态需建立显式映射,不直接替换所有服务的状态机。拖车公司承诺可提、码头给出约号、接仓方接受到仓时间属于不同确认对象,不能互相代替。
改期是一项有前后时间和原因的操作,不应覆盖掉原确认历史;已发车或执行中的改期要检查影响的收货站、司机任务及派送计划。取消预约不能自动取消车次或回滚已发生的库存。
异常优先展示:缺时间/地点、预约未确认、已约未安排承运、货物未就绪、资源冲突、已过约定时间未完成。冲突有完整资源与时段依据时才判断;缺少行程耗时不能断言车辆一定赶不到。
还柜截止必须使用现有业务服务返回的规则结果。当前内部72小时预警口径不能等同所有船公司、码头的免箱期或费用规则,也不能拿预计还柜时间当实际还柜。
### 船期与货量变化后的处理闭环
上游变化后更新有来源依据的最新预测,重新比较下游安排,形成“变化原因 → 受影响对象 → 建议动作 → 负责人 → 处理结果”。建议至少覆盖:
| 变化 | 需要提示的影响 | 人工处理 |
|---|---|---|
| ETA或预计可提柜推迟 | 提柜意向、接仓窗口、受影响货物的预计备妥窗口 | 再联系车队/仓库;尚未形成正式约号时调整意向 |
| 预计备妥晚于计划装车或目标送达 | 具体送货批次、收货预约、车次及关联外接承诺 | 判断等货、取消本批或按合法命令调整货物/申请改期;正式约定保留至取得新结果 |
| 实收箱托/重量体积与预报不同 | 车次容量、剩余可接量和需要更新的预约资料 | 调度重核容量及对方资料;已确认外接货不能被静默挤出 |
| 对方改期、拒约或取消 | 关联装车/车辆安排及货物等待情况 | 指定下一次联系、补资料或另申请;保留原结果和原因 |
| 船期来源过期或关键资料缺失 | 当前计划判断依据不足 | 标为待核实,负责人补充;不能继续显示无条件“可送达” |
首版提醒先做有明确依据的日期先后、资料缺项、超时未回复与来源变更。缺少可靠装卸/行车耗时,只能提示“需要核对”,不能自动判定违约。若变化可能影响运输承诺且暂无完整重算依据,先要求调度复核再确认新的外接承运;不改写已确认订单或凭空计算新余位。
跟进事项以同一来源与事项保持稳定身份,更新后保留处理历史,不在每次船期刷新时新增重复待办。待办完成要对应实际反馈或已处理的安排,不能仅因运营打开过详情就消失。首版岗位建议:提柜负责人跟进车队/码头,仓库负责人核对接仓和备妥,送仓调度跟进FBA/收货方及车次,销售在原拼车池跟进外接意向;具体人员由组织分工确定。
## 八 数据与接口实现建议
### 提前筹划必须补齐的当前接口边界
以下为2026-10-09只读源码核对,不代表已部署验证:
| 当前事实 | 对本目标的影响 | 建议调整 |
|---|---|---|
| `InboundFbaAppointmentQueryMapper`从入仓计划及其明细查候选,预约创建未要求入库完成 | 已有计划的海上货可以提前约;尚无计划的在途订单不在该入口 | 在既有Lastleg业务内提供在途货量及预约准备关系,直接引用真实来源明细;后续关联计划行,不为凑候选而伪造收货或重复建货源 |
| `BatchFbaAppointmentRequest`要求预约号、预约时间及预计装车时间;关联仅接收完整`lineIds` | 刚开始联系时无法真实填写;不支持同一明细自由拆量 | 支持先保存筹划信息,再补确认结果;首版按完整来源明细组织,拆批数量分配另行定义后才开放 |
| `LastlegOrderService`在同柜任意入库计划生成后禁止修改柜级预计到仓 | 提前建计划后无法持续修订该字段,不能仅靠预约页面解决 | 先区分来源最新预测与入库计划确认时的时间快照;明确各自来源和显示,预测变化走影响提示。若要修订已确认计划日期,需同步修改当前到仓合同和实际消费者,不能直接移除锁定校验 |
| `FleetTripExecutionService`从已关联客户排车读取计划货源,要求货物、托盘、车辆与目的地;`FleetCapacityOfferService`发布还校验司机及有效容量计划 | 已支持拣货前核对容量,但不能直接把海上FBA汇总当成可售余位 | 复用现有排车/车次关联;先验证计划货源可在哪个阶段合法形成这些事实,补齐在途批次到现有货源的关联闭环;尚未具备事实时仅预排,不许前端凭空发布 |
“开船后提前筹划”与“开船后立即发布远期可成交余位”是不同交付要求。前者是本轮明确目标;后者只有满足现有资源、容量及履约条件的车次才能开放。若业务要求更早发布,必须在本方案中明确新的可承诺条件,再调整拼车主契约。
### 聚合读取 原业务写入
总览提供按日期范围、类型、地点和权限过滤的聚合读取能力。Firstleg负责码头提柜/还空及船节点,Lastleg负责FBA、车次、派送和仓库收货相关业务,Warehouse提供地点主档。服务端通过明确接口聚合,不跨服务Schema查询。
先接已有事实,不为每种来源复制一套预约数据。不具备预约状态或确认时段的业务,补充自己的模型后再作为正式预约接入;仍可先以“待安排计划”展示。
建议统一返回:稳定事件标识、来源类型和业务号、预约类型、地点与时区、时间含义/开始/结束、确认状态、执行状态、货物统计、关联单据摘要、可执行动作、版本及来源更新时间。内部ID用于关联但不作为用户可见业务编号。
事件按来源及业务阶段建立稳定去重键,不能按客户复制,也不能用会随改期改变的日期作为唯一标识。改期更新同一业务事件,保留历史;跨日时段按与查询区间相交纳入,不能只查开始日期。
在途预报、已建计划和实收入库应按稳定货源关联去重。建议新增的筹划信息仅保存负责人、目标窗口、联系记录、批次关联等现有业务没有的事实,归Lastleg相关业务承载,不建设独立预约微服务或通用工作流引擎。提柜/船节点继续由Firstleg提供;筹划查询不跨服务Schema取数,不把来源快照复制成第二套可编辑货物清单。
### 性能与错误处理
按时间范围批量查询并分页读取当天明细,禁止先加载所有业务单据再在浏览器过滤,也禁止日历每个卡片再请求一次详情。现有FBA和到港接口可复用;提柜现有按柜次ID接口需要新增按范围的读取合同,不能假设它已支持。
某一来源失败时,明确显示该分类暂不可用及重试,不把整个页面清成“当天无预约”。所有分类的总数必须说明是否完整,避免部分结果冒充全部。筛选和切换日期时丢弃迟到响应。
### 权限与审计
统一入口按平台员工权限过滤各来源,后端同时执行数据范围和动作权限校验。仅有总览权限不自动取得提柜、排车或取消权限。聚合失败、无权查看和确实无数据应区分处理。
跨客户预约只在平台完整展示;客户仍只能看到自己的货物和获准公开的信息。改期、取消、关联/解除记录操作人、时间、原因和原新值。发送车队邮件属于显式业务操作,不因新增日历卡片自动发送。
## 九 建议实施顺序与协同分工
### 两份文档 两个实施职责
建议由用户安排两个实施对话:A负责预约并协调本次集成,B负责拼车接货及共用车次能力;可以复用已有对应对话,不额外创建第三个协调对话。A/B仅为待分派的职责代号,不是已登记或已创建的任务;本次文档整理对话不承担A或B开发职责。本文维护跨方案分工,拼车草案只链接本节并保留自己的操作细节。正式规则仍回到各自当前契约,评审稿不能代替开发定稿。
| 工作范围 | 唯一实现职责 | 另一侧如何使用 |
|---|---|---|
| 在途货量、ETA/备妥窗口、提柜与接仓联系、预约安排 | A | B读取获准的货物/时间摘要,不另建预测与联系记录 |
| FBA/收货预约、货物关联、确认/改期、预约覆盖结果、日历 | A | B展示同一预约结果,缺项进入预约操作;不独立维护预约状态 |
| 车次创建、车辆司机、路线、排车关联及正式排入本车 | B | A带入真实来源,使用同一候选、资格与业务命令;不另建运输单或排车命令 |
| 计划容量、占位、余位、发布与恢复资格 | B | A只展示摘要和进入共用操作的入口,不在浏览器重算 |
| 销售登记、确认承运、安排来货、实收后连续处理 | B | A按稳定来源联查货物及预约,不复制拼车登记或商业订单 |
| 船期/货量变化影响 | A识别时间及预约影响;B维护车次容量/发布资格 | 各自维护自己的事实,通过明确关联衔接,不互相覆盖状态 |
| 本次共用文件集成与整链核对 | A协调单一写入者,保留既有项目文件归属 | B提交精确改动并对其业务复验;不因此将B的业务责任移交A |
实施前按目标文件列出写入范围,不能只写“前端归A、后端归B”。A通常涉及`appointment-calendar`、预约服务及所需船节点/提柜读取,B通常涉及`overseas-master-data`、Fleet及排车关联;同在Lastleg不等于可同时修改同一服务文件。排车中的预约展示/关联由A定义预约事实,B修改其负责的排车消费者。
实际重叠的`lastleg.sql`、导航、根路由、权限种子、公共导出/类型、OpenAPI和相邻合同测试须逐文件指定唯一写入者;已有项目负责人持有的文件沿用其归属。B负责的公共变更由B提供精确变更清单或补丁,单一写入者在当前工作区串行整合,B复验业务行为。普通工作仍在当前工作区、当前分支,不复制项目或创建worktree。
#### 已选定的预约与拼车交接文件
实施交接的来源、权限与跟进规则维护在[业务主入口的预约跟进合同](README.md#在途货源与拼车外接货的预约跟进合同),HTTP定义维护在预约筹划OpenAPI;本表只明确文件写入归属。
| 文件或精确目录 | 写入方 | 边界 |
|---|---|---|
| Admin `src/modules/appointment-calendar/` | A | 在途列表、来源深链、跟进、覆盖展示及预约日历 |
| Lastleg `appointmentplanning/`及同包测试、`openapi/appointment-planning-v1.yaml` | A | `AppointmentExternalSourceGateway`由A定义;`AppointmentCoverageService.query`提供共同只读结果 |
| Lastleg `fleet/business/FleetPoolSourceResolver.java`、`FleetAppointmentSourceAdapter.java` | B | B适配原登记真实来源到A的端口,A不直接依赖Fleet实现 |
| Admin `overseas-master-data/`、Lastleg `fleet/`与排车消费者 | B | B消费覆盖投影,提供共享车次候选、安排和容量;不复制预约写命令 |
| Admin `core/navigation/adminNavigation.ts`及对应测试、`overseas-master-data/routes.ts`菜单标题 | A串行整合 | 此次仅“拼车接货”标题调整由A写入;B保留其页面及路由功能改动 |
| `lastleg-service/src/main/resources/db/lastleg.sql`、`deploy/sql/海外区域统一增量-MySQL8.sql` | 按新增表块串行 | A仅写`ll_appointment_followup`块;B维护Fleet块,其他业务负责人持有的块保持原归属 |
| `iam/src/main/resources/db/lastleg-permissions.sql`、`deploy/sql/头程数据库统一增量-MySQL8.sql` | A整合预约权限行 | A维护`platform:appointment:followup`及平台管理员授权,保留其他任务的种子变化 |
深链为`/appointment-calendar?sourceKey=BOOKING:<登记号>&customerId=<客户ID>&destinationKey=FBA:<仓码>`,各参数须编码。它进入核实后的来源跟进与覆盖展示,不等价于外部预约确认。B的原登记入口必须满足读取权限,写入另受跟进权限约束。共用Lastleg编译目录串行使用,不能两侧同时运行Maven并将编译产物竞争误判为源码故障。
### 开工前先确定六项交接
1. **货物来源与数量:**已有头程在途货、拼车外接货分别如何关联来源明细、来货、入仓计划和实收;避免入库前后重复计货,首版不默认拆分同一明细。
2. **时间与状态:**预测、计划快照、对方确认时间分别归谁;预约安排、拼车登记、确认保位、实收后排入各自允许什么操作,不互相推进状态。
3. **预约资格与覆盖:**两类货源分别在哪个阶段可以准备/正式申请FBA预约,需要哪些资料;新增拼车货如何进入候选、核对原预约货件及检查时点。预约服务给出结果,车次侧消费,不在最终联调才补来源支持。
4. **车次接入:**A传真实来源及计划关系,B返回可用候选/阻断原因、关联车次和版本;无正式排车资格时只保留筹划,不生成假托盘或实际装载。
5. **余位与变更:**B提供各目的站可接量、发布资格、缺项和版本;A传递预测/货物变化依据,双方明确哪些变化触发人工复核,不自动重约或替换已确认承诺。
6. **权限、失败与重试:**查看和写入分开,变更使用版本与幂等;明确部分保存成功、结果未知和重试行为,同一次动作不生成重复业务。
以“两柜已有货合送同FBA,再接一票外部货”为共同样例,给出上述输入/返回示例、来源关联、可用动作及失败情形。选定规则在实现前同步到对应唯一正式契约与接口定义;本节只规定交接项,不提前宣称新接口或状态已经存在。
### 工作包与先后依赖
| 顺序 | A:预约与集成 | B:拼车与共用车次 | 进入下一步的条件 |
|---|---|---|---|
| 0 先确定共同边界 | 明确在途及外接货预约来源、预测/确认时间和关联结果 | 明确三类占用阶段、车次资格、容量和发布结果 | 六项交接有样例;正式契约、具体文件归属和受影响检查已明确 |
| 1 两侧独立工作并行 | 在途货量、提柜/接仓列表、负责人、联系记录、无约号的预约安排 | 销售简明列表、分阶段字段、单站带入、同一登记记录、角色待办和已有排车候选 | 各自定向验证通过;不编造约号、数量或资源;独立改动不等待对方全部完成 |
| 2 共用能力只做一次 | 实现对外预约/改期及货物关联,按已确定接口接入车次和资格展示 | 完成共用安排车次、排车关联、容量核对与连续发布,提供实际消费者可用的接口和操作入口 | A/B复用同一车次能力;源码、类型、OpenAPI、权限及必要SQL一起收敛,不能靠临时兼容接口拼接 |
| 3 接通变化与外接履约 | 完成统一日历、船期影响、外接货预约覆盖和待补/改约提示 | 完成安排来货、实收核量、排入原车次及预留替换;消费预约结果 | 从原登记可跟踪整链;延期可定位影响;不重复占位、建单或收费 |
| 4 统一验收本轮闭环 | A组织整链核对和问题归属,各侧修复自己负责的部分 | B复验共享车次及外接履约,保留原审核/拣货/发车门禁 | 必要自动检查完成;真实环境和人工截图按授权执行,代码、部署与验收分别报告 |
第1—3步共同交付首个完整闭环,不以一个更大的日历或仅改表单文案替代。B的内部操作细节及局部分批见拼车草案第八节,不另排一条互相冲突的整链发布顺序。可以按可独立验证的工作包推进;本表不是工期、上线或环境写入授权。
共同回归至少覆盖:已有货在途预约;合格车次发布后接外部货并补齐预约覆盖;外接实收后预留替换只算一次;一个柜延期时关联预约/车次/已接货均可追踪;三维容量不足、重复提交、版本冲突与权限拒绝。自提、还空、转运/退货提送的扩展仍保留总体范围,排在主链后,不占用第一轮共同接口建设。
### 交给预约实施对话的任务说明
- **目标:**完成从已有在途货开始的提柜/接仓跟进、按目的仓筹划、对外预约、日历及船期变化影响,并接入拼车侧提供的共用车次能力。
- **先交付:**具体文件写入清单,已有头程货和拼车外接货的稳定关联、可预约阶段、时间语义、预约覆盖与失败情形;与B共同确定六项交接,不等到最后才处理外接货来源。
- **独占业务:**在途/备妥预测展示、人工联系、预约安排与确认/改期、预约货物关联和覆盖结果。车次创建、排车命令、容量及发布由B提供,本侧只接入。
- **依赖:**B提供真实货源进入车次的资格、车次/排车关联、各目的站余位、发布资格和对应操作入口;本侧不得为提前完成页面而自建同义接口或虚假资源。
- **交付物:**选定正式契约改动、受影响接口/类型/权限/SQL清单、实现与定向验证结果、公共文件串行集成记录和整链核对结果;部署与人工验收分别列出,不由源码测试推定完成。
- **完成条件:**货在海上且未建入库计划时可真实筹划,未取得约号仍能跟进;两类货源的预约覆盖可追踪,预测变化能定位下游影响,预约和车次结果一致,未重复占货、建车或发布。
拼车实施职责的交接说明见[拼车草案第八节](拼车数据入口与操作简化评估草案.md#交给拼车与车次实施对话的任务说明)。上述工作包供用户分派给其他对话;本轮只交付文档,不创建对话、发送开发任务或修改业务代码。
## 十 验收场景
1. 同一美国日期包含提柜、用车、FBA和客户送货,列表/日历均可找到且类型明确;国内拖车不混入。
2. 五客户二十票同仓同批预约只计一张,客户统计正确,入仓码默认三条;每个客户只读到自己的货物。
3. 一车两站两个收货预约,在车次视图可以关联查看;车次计划不会被重复算成两个用车安排。
4. 预约成功后,排车和派送显示同一来源事实;多预约排车不会丢掉其中一站,不能再出现无依据的独立“待预约”。
5. 选仓自动加载货物;换仓清空旧选择;不可预约货物有原因;仓库接口失败不允许自由输入假仓库绕过。
6. 新建待确认事项无需编造外部确认号、装车时间、司机或费用;转为已确认时按业务类型核验必要资料。
7. 提柜时间、预计到仓、实际到仓互不覆盖;实际作业只由原业务事实推进。
8. 改期更新原记录而不新增重复事件;取消保留历史;已执行业务不被日历操作回滚。
9. 跨时区、跨日、只有日期、无时间及夏令时边界正确显示;地点时区缺失明确待补。
10. 日格三条预览、大量当天安排和大量关联货物保持有限高度,展开可用键盘操作;关键业务号可查看完整内容。
11. 来源接口部分失败、无权限、版本冲突和重复提交均有明确行为,统计不把缺失来源当零。
12. 车次调度/理货、PDA拣货发车、库存和客户费用隔离继续有效,预约页面不能跳过这些门禁。
13. 柜已开船但尚未生成入库计划时,真实货物出现在在途货量及预约准备中;无需假约号、假实收或假司机即可分派跟进。
14. 同起运仓、同FBA、相容备妥窗口的两柜货可人工组织批次;起运仓不同、日期不相容或已占用的货不得被无提示合入。同一来源建计划/入库后不重复累计。
15. 码头尚未开放正式申请时,保留拖车沟通与待开放事项;车队答应不自动标记码头已确认,接仓方和FBA确认也不互相替代。
16. ETA延后时展示旧/新预测及来源,准确指出受影响批次与预约;已确认外部时间和已冻结计划不被覆盖,待办有负责人及处理结果。
17. 海上预排货量不能直接发布可成交余位;达到现有车次、资源、有效计划容量条件后复用原发布。托位有余但重量/体积不足时,不发布虚假可接量。
18. 在同一路段30托位车辆、自有18、有效外接预留8的示例中,剩余为4;外接货转为已关联货物后不再额外扣8。计划失效则显示待核对,不继续承诺旧余位。
19. 联系资料可由已有货物生成;缺少FBA所需资料显示缺项。记录、导出资料、申请和取得确认是不同动作,不能相互推定完成。
## 十一 评审需要确定的事项
本轮用户明确目标:开船后依据预计到港提前人工联系提柜,同时掌握预计到海外仓的货物和各FBA仓货量,准备送货车辆,并把符合条件的车次余位接入现有拼车需求池。原方案已有方向:美国段预约统一入口、同仓跨客户合并、减少重复填写和控制卡片高度。
本次建议作为产品评审基线,尚未生效为代码合同的规则:
- 保留“预约列表”菜单和“美国预约总览”标题;以提柜与到仓、送仓与排车、预约日历三个工作视图组织,不另开一套拼车市场。
- 从真实在途货开始筹划,先保存目标窗口和人工联系结果,后补外部确认;预计装车时间由车次维护,预约按关联读取。
- 首版同起运仓、同目的地、相容窗口内人工组批,整来源明细选择;不同站点同车沿现有调度,一行货自由拆批不随页面优化默认开放。
- 最新预测与已确认入库计划时间分开;船期变化提醒人工处理受影响承诺。修订已确认计划日期的命令与权限需另在当前合同中明确。
- 正式拼车发布继续要求现有车次、车辆/司机及有效容量计划;无资源的远期运力先保留内部预排。
实施前还需结合运营习惯确定:
- 常用港口、接仓点与FBA线路的预计卸柜/备货/行车时间及缓冲;首版可由人工维护,不能给所有线路统一默认天数。
- 提柜、接仓、FBA/客户送货分别由哪些岗位联系,对方是否由承运商代约,以及超时未回复时由谁接手。
- 总览默认使用哪个业务时区,以及跨时区团队是否保存个人显示偏好。
- 尚未满足现有拼车发布条件时,仅预排是否满足经营需要;如必须提前成交远期运力,需明确范围和承诺方式,不能省略这项能力差异。
## 十二 现有实现入口
| 用途 | 入口 |
|---|---|
| 当前预约页面与字段 | [AppointmentCalendarView.vue](../../apps/admin-web/src/modules/appointment-calendar/AppointmentCalendarView.vue)、[日历读取API](../../apps/admin-web/src/modules/appointment-calendar/api.ts) |
| FBA预约现行边界 | [海外仓业务预约送仓](README.md#预约送仓)、[预约服务](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundFbaAppointmentService.java) |
| FBA必填字段 | [创建请求](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/BatchFbaAppointmentRequest.java)、[Lastleg初始化基线](../../baiyue-firstleg/lastleg-service/src/main/resources/db/lastleg.sql) |
| FBA预约货源与柜级到仓锁定 | [预约查询Mapper](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundFbaAppointmentQueryMapper.java)、[尾程订单服务](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java) |
| 码头提柜与还空 | [terminalDrayages.ts](../../apps/admin-web/src/modules/container-loading/api/terminalDrayages.ts) |
| 柜级预计及实际到仓 | [containerArrivalTimes.ts](../../apps/admin-web/src/modules/container-loading/api/containerArrivalTimes.ts) |
| 车次及运输资源 | [tripTypes.ts](../../apps/admin-web/src/modules/overseas-master-data/tripTypes.ts)、[trips.ts](../../apps/admin-web/src/modules/overseas-master-data/api/trips.ts) |
| 外接承运预订 | [tripBookings.ts](../../apps/admin-web/src/modules/overseas-master-data/api/tripBookings.ts) |
| 车次计划容量及拼车发布 | [车次执行服务](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/fleet/trip/FleetTripExecutionService.java)、[余位发布服务](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/fleet/trip/FleetCapacityOfferService.java)、[拼车主契约](内部拼车需求池首版开发契约.md) |
| 排车独立预约字段 | [dispatches.ts](../../apps/admin-web/src/modules/overseas-warehouse/api/dispatches.ts)、[DispatchService.java](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java) |
| 派送计划与实际签收 | [deliveryOrders.ts](../../apps/admin-web/src/modules/overseas-warehouse/api/deliveryOrders.ts) |
| 本土运输需求日期 | [海外业务类型](../../apps/admin-web/src/modules/overseas-business/types.ts) |
| 全流程维护入口 | [头程到尾程README](../头程到尾程/README.md) |
@@ -91,6 +91,16 @@
- `sourceReference`:不含密钥和敏感参数的可审计来源引用。 - `sourceReference`:不含密钥和敏感参数的可审计来源引用。
- `rawPayloadHash`:原始响应的 SHA-256;业务表不保存完整网页或敏感原文。 - `rawPayloadHash`:原始响应的 SHA-256;业务表不保存完整网页或敏感原文。
### 5.1 响应审计与事件幂等摘要
`rawPayloadHash` 仍是本次供应商整份原始响应的审计摘要,不作为同一 `providerEventId` 的不可变事件摘要。追加其他节点、调整其他节点的预计时间、改变网页排版或再次查询,均可能改变整份响应摘要;不得因此阻断未变化的旧事件及后续新事件。
Firstleg 对已持久化事实和本次标准化事实采用相同字段顺序计算 SHA-256 事件事实摘要并比较:节点包含柜次、供应商/事件标识、原始节点码、标准节点、预计/实际时间、地点编码/名称和来源引用;异常包含查询任务、供应商/事件标识、原始状态、异常编码、是否生效、地点编码/名称和来源引用。查询观测时间 `observedAt`、本地写入时间与整份响应 `rawPayloadHash` 不参与该稳定事件摘要。字段空值保持空值,不用查询时间或其他字段补齐。
同 ID 同事实重复查询不新增节点、异常、历史或业务事件,保留首次写入的观测时间和原始响应审计哈希;同 ID 变更上述任何事实字段必须冲突,即使供应商沿用了相同原始响应哈希也不能绕过。现有适配器的事件 ID 生成规则保持不变;预计时间变化按原规则形成独立预计事实,不推进实际节点。不得通过每轮换 ID、吞掉事实冲突或新增未知供应商状态/解除映射完成重放。
预计/实际时间参与摘要前统一按现有 `DATETIME(3)` 毫秒精度四舍五入(含跨秒进位),对输入与持久化事实使用同一规则;不采用时间差容忍窗口,仍拒绝不同毫秒事实。
供应商返回空字段时保持空值,不使用 `0`、当前时间、预计时间或其他字段伪造实际事实。 供应商返回空字段时保持空值,不使用 `0`、当前时间、预计时间或其他字段伪造实际事实。
## 6. 已确认供应商映射 ## 6. 已确认供应商映射
@@ -0,0 +1,732 @@
# 车辆管理原型梳理与任务规划
> 文档状态:原型盘点、首版执行确认与开发增量记录;更新时间:2026-10-07。
> 规划对象:Admin「车辆管理」及其与排车、海外派送、车队报价的衔接能力。
> 本文用于确定范围、现状和任务依赖,不代表代码已经完成、已经部署或已经通过真实环境验收。
> 开发已按后续授权推进;当前源码增量与未完成项见第 10 节。文档 Review、局部测试、真实部署和页面验收分别记录,不相互替代。
> Review 状态:2026-10-02 已完成本次连续 5 轮核对、修订与复查,记录见第 9 节。原型事实、源码现状和候选设计已分别标明;业务决策仍见第 4 节,不等于功能开发或环境验收完成。
> 后续业务确认:2026-10-02 用户明确“外接”为自有货物未装满时承接顺路外部货物,审核先展示详情并提供通过/打回;司机证照 30 天内到期但仍有效时允许派车并提醒,预计任务结束前过期则禁止。已确认部分与出车/金额建议见第 4.1 节,追加边界 Review 见第 4.4 节;不把建议标为用户已确认。
## 本轮首版执行确认(2026-10-02)
用户明确“按你的建议执行,我们先做一个版本出来,再优化和修改;验证可以宽一些”。本次确认替代下文先前标记为待答的首版选择:外接货先送我方起运仓,运营接洽并在后台登记;调度通过后拣货、理货通过后发车;车次采用独立列表和详情、计划居中弹框、其余操作在详情分区;维修/故障/救援增加“更新处理”。原运费按每票实际覆盖范围引用,另行确认的新增项目才计费;源码说明见第10.9节,当前部署、真实验收与未关闭项目统一见[测试环境单机部署与配置契约](../测试环境单机部署与配置契约.md)及[统一认证与服务通信契约](../统一认证与服务通信契约.md)。
首版驾驶证为必需资质,体检/培训/保险日期先作档案记录。输入校验保留必需业务数据、权限、客户归属、防重复、实际容量及已确认的证照到期规则;普通说明、地址等选填字段宽松处理,常规动作使用标准审计说明,不要求用户重复填写。原型未覆盖的上述操作已有本轮授权,不再重复等待确认。
第 4.7 节保留此前受阻时的核对经过;其“待答”状态已由本次确认解除,原目标恢复实施。实现、部署和真实验收仍分别核对,用户批准方案不代表功能已经完成。
2026-10-03 财务追加确认:用户在“车辆管理|成本与财务闭环”独立任务明确“请按你的建议来处理先”,确认维修/救援按公司车辆成本登记,不自动形成客户应收;保留CNY/USD原币,按业务月份汇率折算CNY入账。首版允许未付款费用作废重建,已付款费用禁止直接改写或作废,退款冲销后续单独确认。此项解除第4节第6项中维修/救援财务归属的待答状态;保养/加油等其他来源不据此自动扩大。费用登记、入账和付款须分别体现真实状态,不能以运维处理完成替代付款。当前实现仍由专项接入,部署及验收以两份正式主契约为准。
## 2026-10-07 增量:内部拼车需求池与三种交货方式
本功能进入文档审核与开发准备后,首版范围、接口决策、五轮审核和验证门禁统一维护在[内部拼车需求池首版开发契约](内部拼车需求池首版开发契约.md)。以下增量保留需求演变与完整业务方向,不覆盖新契约的统一我仓上车边界。
本节记录本轮需求和接入建议,不代表新功能已经实现或部署。用户先明确三种交货方式,随后提出前期先做“我仓上车”、暂不做顺路直送,以减少工作量;最新首版建议见下段,三种方式保留为完整业务方向。现有车次主链验收不能作为需求池及沿途提货已经跑通的证据。
### 最新首版收敛建议:统一我仓上车
用户提出首期只做我仓上车、顺路直送暂不做。推荐首版交付内部需求池、销售意向与报价、调度确认占位、本土订单关联,以及复用现有真实到仓收货至装车签收的闭环。所有本期实际发运货物须先进入我仓,不增加沿途提货站、非仓库货物来源或行驶途中接货确认,也不修改现有“始发前外接货已实收并关联发运”的门禁。
客户自行送仓与我方提货回仓均可最终进入该流程。为控制首版工作量,建议我方提货回仓暂由运营在线下安排,系统仅记录交货方式、预计到仓及备注,从实际到仓后开始收货;这不代表系统已有提货任务派车、提货交接或提货成本闭环。若要求提货过程也全部在线处理,再纳入下方B阶段。
下方A/B/C顺序为完整方案储备,当前推荐先实施A;B独立提货回仓作业、C沿途直送留待后续范围确认。阶段A仍须验证真实外接货与自有货同车、客户隔离、占位转实载不重复扣减、取消释放及不重复收费;不能以发布余位列表代替完整送仓拼车链。当前仅调整方案,未据此开始代码或环境变更。
### 用户已确认
- 调度已约车并安排自有货后,需将去向、时间和可接余位集中展示给销售。例如去目的地 A 的车有30托位,自有货占18托位,还能寻找12托位的外接货。
- 首期需求池只面向内部员工,销售查看后自行联系外部客户;不在此范围内建设客户公开运力市场。
- 完整业务需要逐票选择三种交货方式:客户送到我方起运仓;我方上门提货后回我仓;我方沿途提货后直接送对应目的仓。随后用户提出首版先统一我仓上车,沿途直送暂缓;不再将三种系统执行闭环同时作为推荐首版范围。
- 本土业务现有下单入口承接成交业务,需求池位于下单前,先让销售知道哪趟车、去哪里、何时出发、能接多少货。
### 建议的业务承载与流程(待按实际交互细化)
建议新增内部「拼车需求池」,由车次提供路线、发车时间和容量事实。调度核对计划后发布可接货需求,销售按起运区域、目的地、时间和交货方式筛选,并登记客户意向;调度确认承运后占位,再关联正式客户订单和该车次,按交货方式履约。询价不占位,已确认预订扣减可接容量,沿用现有外接预订规则;是否提供有时限的临时留位另行定义,不默认新增。
| 交货方式 | 建议履约路径 | 必须保留的实际事实 |
| --- | --- | --- |
| 客户送仓 | 客户送到我仓 → 实际收货、测量及入库 → 绑定干线车次 → 拣货、装车 → 目的仓签收 | 到仓实收、库内库存和出库事实 |
| 我方提货回仓 | 安排提货任务 → 客户地点交接 → 运回我仓 → 实际收货、测量及入库 → 干线装车 → 目的仓签收 | 提货交接与到仓收货分别记录;提货车辆和干线车辆可不同,费用不可重复收取 |
| 沿途提货直送 | 安排本车提货站 → 到站交接、核量及装车确认 → 按路线送目的仓 → 签收 | 客户地点实收和车上货物事实;不虚构我仓入库、库位、仓库托盘或仓库出库单 |
需求池建议展示:车次号、起运仓/区域、已有途经及卸货站、计划发车与最晚交货时间、整车容量、自有货预计占位、外接已确认占位、可接托位、剩余重量/体积、允许交货方式、调度联系人、接货状态。客户意向需记录销售负责人、客户、提货地址(需要提货时)、目的地、预计托位/重量/体积、交货时间和报价。客户业务单据、预订与车次建立明确关联,销售无需重新录入另一套容量。
### 容量与变更建议
- 30−18=12仅适用于同一运输区间且重量、体积也允许的情况。客户占8托位并确认后,同一区间余4托位;不同销售同时确认时必须由服务端避免超卖。
- 沿途提货按“提货站至卸货站”逐段预留容量。计划阶段即占用对应未来区间,不能等实提才扣可售余位;实际车上数量则在提货交接后增加、卸货签收后减少。
- 示例:我仓带18托去 A,途经 B 提12托一起送 A;我仓→B 实载18托,B→A实载30托。若这12托已确认,B→A余位已为0,不能再对该区间承诺12托。
- 回仓提货独立核对提货任务运力;回仓后的干线预订也需占位,同一批货不能在同一车次被预订和实际装载重复扣减。
- 自有货、车辆容量或路线变化后重新核对有效余位;容量计划失效时展示“待调度核对”并停止新承运确认,不能把未知显示成有空位。超出原已发布路线的提卸点需调度调整路线并复核承诺。
- 需求发布、暂停接单、满位、取消及发车后接单规则属于需求池状态,不混同车次运输状态。首期是否允许车辆出发后再接新的沿途订单,尚未确认;已在出发前确认的沿途提货必须正常执行。
### 当前源码与缺口
| 部分 | 当前核对事实 | 本次需补齐 |
| --- | --- | --- |
| 车次与容量 | Admin `TripsView.vue`已有车次列表;详情 `capacity-plan` 返回有效计划和扣除外接后的逐段余位,列表没有面向销售的余位发布入口 | 跨车次需求池查询、发布/暂停/关闭、销售意向及责任人;服务端统一返回有效可接运力 |
| 外接预订 | `TripBookingPanel.vue`及`bookingTypes.ts`已有询价、确认承运、实收、关联发运和取消 | 从需求池带入车次与路线,扩展逐票交货方式、提货站和交接事实 |
| 容量算法 | `TripCapacityPolicy.Booking`支持提货/卸货站区间;当前`FleetBookingReservations.add`固定从站点0占位 | 将真实提货站接入预订、计划变更和发车/到站复验,不能仅在页面增加选项 |
| 来货及库存 | `FleetIncomingAdapter.create`固定`CUSTOMER_DELIVERY`并调用仓储转运来货流程,实收证据来自本仓托盘 | 保留客户送仓链;增加提货回仓任务衔接,以及不经仓的沿途提货直送履约来源 |
| 本土下单关联 | 当前正式菜单名称是「本土卡车」「本土散板」;外接预订的当前来货链是仓储转运,不证明已经关联这两类订单 | 明确每票对应的业务单据及单一收费来源;从需求池转单携带预订和车次关联,禁止重复下单、占位或收费 |
验收应分别覆盖三种交货方式,并验证:30托位/自有18托位/外接12托位、并发确认不超卖、不同提卸区间、不足或超量实收、货物及路线变更、取消释放、回仓两段运输关联、直送不产生虚假仓库库存、签收回传与收费不重复。此前灰度FBA自有货主链通过,不替代这些新增场景。
### 推荐实现方案:沿现有车次接入(设计建议,非已实现)
建议仍在 Lastleg 现有车辆与本土业务内实现,复用统一 Gateway/Auth、客户隔离、File 和 Finance。不新增独立撮合服务,不复制一套车次、库存或财务账。
**页面和职责。** 在「车辆管理」增加「拼车需求池」,销售可直接进入;车次详情增加“发布拼车需求”及关联入口。需求池每条需求关联唯一车次,展示可接运输区间,余位实时来自服务端有效容量与已确认预订,不让销售手填剩余托数。建议车次先待发布,调度确认路线、时间和可承诺容量后发布;自有货或预订变化自动更新余位,计划失效则暂停承诺。多站路线不能只展示一个没有运输区间的“剩余12托”。
销售负责登记客户意向、选择三种交货方式、报价与跟进;调度负责发布、确认路线及承运占位、安排提货和车辆;仓库负责实际过仓货的收货、拣货与出库。销售看运力及自己获授权的客户资料,不因需求池访问而获得同车其他客户货物、成本或全部司机资料。发布、询价登记、确认占位及提货确认采用独立写权限,不把销售统一授为车次管理员。
**单据关联。** 建议采用“车次 → 发布需求 → 客户意向/预订 → 本土业务订单 → 履约任务”的关联。复用外接预订的询价和承运确认;内部销售成交时在同一业务动作中关联或生成本土散板/本土卡车单据,不要求再去两个页面各下一单。已有本土订单也可选符合路线的车次进行匹配,一票可依法分段运输但同一段货物不可重复占位。同一客户委托可以对应提货回仓和干线配送两段任务,仍保持同一业务来源与可追踪费用。
本土单据记录客户委托、交货方式、货物及已确认交易条件;预订记录该订单在哪个车次、哪个提卸区间占多少位;任务记录谁在何时、何处实际接货和交货。报价预算、确认成交价与财务应收/实收分别处理;预订、提货任务和最终派送引用同一已确认费用来源,新增提货费须独立确认,不能因生成新任务再收一次原运费。当前 `LocalLooseboardRequests`/`UsTruckOrderRequests` 没有这套车次关联,须连同平台和客户消费者更新正式合同。
**三种方式如何进入执行。**
1. 客户送仓:关联既有来货流程;PDA 实收、核量确认后,将已确认预订占位转换为实际发运货物占位,不能两份同时扣容量。
2. 提货回仓:从客户订单派生提货任务,记录地址、预约窗口、联系人、承运车辆、实际提货数量和交接附件;可由另一趟车执行。回我仓须重新完成真实收货事实,再承接原干线预订。提货成功不等于仓库收货成功。
3. 沿途直送:同车次添加有顺序的提货站和卸货站,增加不依赖仓库托盘的运输货物来源。出发前可保留尚未提取但已确认的后续站货物;当前站必须装车的货物仍需就绪。到提货站后核对实际托位、重量、体积及交接证据,通过下一段容量校验才允许继续;超量、少到、未到和改目的地由调度处理,不能自动超载或将未提货标成已承运。
首版建议由调度在后台维护提货任务并录入实际交接结果及附件,仓库 PDA 继续承载过仓作业;司机专用移动作业入口另定交互,不把仓库 PDA 的仓库绑定权限直接放宽为司机跨地点权限。若需司机现场自行操作,须作为同一履约任务的授权入口接入,而非另一套运输状态。
**必须修改的核心门禁。** `FleetTripExecutionService` 当前从仓库排车明细生成实际装载,并在 `hasConfirmed` 为真时阻止发车(外接货尚未关联实际发运货物)。新增沿途直送后,要按站点区分“此站应装货”和“后续待提货”,分别核对当前装载、未来预留、已发生运输段及未完成交接;不能直接删除既有外接未就绪门禁。全车结案须包含直送货签收结果,不能只检查原仓库派送单。已完成站点和历史实载不可通过修改计划重写。
**建议实施顺序与交付边界。**
| 阶段 | 交付物 | 验收重点 |
| --- | --- | --- |
| A:销售可用的需求池 | 车次发布与集中查询、线路/时间/余位筛选、销售意向、确认占位及本土订单关联;沿用送仓履约 | 30托位自有18托位,确认外接8托位后余4;多销售并发确认拒绝超卖;旧容量失效不可继续接单;已有订单匹配不重复下单/收费 |
| B:提货回仓 | 提货任务、车辆安排、交接与回仓收货、同单两段运输关联 | 提货与入仓分开确认;提货车和干线车不同;货量差异重新核量;预订与实收不重复扣位 |
| C:沿途提货直送 | 提卸站点、非仓库运输货物、分段装载与提货确认、签收/结案及统一费用来源 | 后续提货不阻断合法始发;沿途每段不超载;未提货/部分提货/改配有处理记录;不生成虚假本仓库存;直送未结束不得整车结案 |
A/B/C 为完整方案依赖顺序,按用户后续提出的收敛方向,当前推荐首版先交付A并用包含自有货和外接货的真实车次验收;这不证明B独立提货任务或C沿途直送已实现。各后续阶段单独确认范围、实施和验收。未实现的交货方式不得在可成交页面提供虚假的成功路径。
待进一步确定的业务选择仅保留会改变执行边界的项目:出发后是否允许新增外接订单、是否允许销售临时留位及有效期、提货操作是否首版由司机本人在移动端完成。以上建议未被标记为用户已确认;本节不改变已确认的内部需求池和三种交货方式。
## 1. 读取范围与事实优先级
本次原型输入是用户提供的外部文件:
`C:\Users\BY-OY\Documents\WXWork\1688854456873012\Cache\File\2026-09\新版.html`
文件读取时间为 2026-09-30。它不属于仓库事实源,文中的示例数据、模拟状态和按钮反馈只用于说明页面意图。新版文件把车辆管理拆成多个页面和弹窗,不能只按“车辆列表”一个页面排任务。
本次连续复核的原型快照 SHA-256:`D12B35F5363ED9B67A33E9D12D542DD902628BC946F75519BC7DDC049D94CD65`。行号只对应这一文件版本;后续原型变更需重新核对交互,不能仅凭同名函数认定行为相同。
实现范围按以下顺序核对:当前对话确认和正式契约,现有 Controller/OpenAPI/权限/SQL,当前 Admin 路由和页面,原型与参考资料。原型出现的功能需要补齐服务端契约和验收证据后才算有效实现。
当前架构使用统一 Gateway、统一 Auth 会话和统一测试环境。后续新增接口应沿“浏览器实际路径 → 统一 Gateway → Controller → OpenAPI → 权限”核对,不按旧资料中的独立海外 Gateway 建立第二套入口。
## 2. 原型实际包含的页面
### 2.1 页面入口总表
| 原型页面/入口 | 原型位置 | 页面职责与主要内容 | 当前原型行为 | 规划判断 |
| --- | --- | --- | --- | --- |
| 排车列表 `outbound-vehicle` | 菜单 `新版.html:1452`;页面 `4474-4486` | 装车前/装车中/装车后三阶段;装车前再分车辆信息、调度审核、理货员审核;按排车单号、车牌、车辆状态筛选;展示司机、电话、托车公司、预约号、派送单、托数、装车时间、FBA/车辆预约等 | 以原型数据和已有页面脚本渲染,审核、附件、轨迹等动作主要是页面演示 | 与正式排车模块连接,不能复制出第二套排车状态或车辆快照 |
| 排车详情 `outbound-vehicle-detail` | 页面 `9433-9445` | 排车单号、状态、车辆/排车信息,以及关联订单明细(订单号、重量、托数、目的 FBA 仓、体积、集装箱号) | 由原型数据渲染关联订单表和详情字段 | 复用现有 `/overseas-warehouse/dispatches/:dispatchNo` 与 `DispatchDetailView.vue`;车辆管理入口只做跳转,不新建排车详情 |
| 排车编辑/审核/订单选择弹窗 | `modal-outbound-vehicle-edit` `12338+`;`modal-outbound-vehicle-audit` `12396`;`modal-outbound-vehicle-rejected` `12397`;`modal-outbound-vehicle-order-select` `12411+` | 维护车辆、司机、预约和路线;上传附件;调度/理货员审核、驳回原因;选择待派送订单 | 表单、附件和审核结果主要写入原型内存并弹 Toast | 归入 VM-04a:复用现有详情/编辑,审核须补提交、通过、驳回、重提及权限/版本契约;普通编辑不代表已提交审核 |
| 车辆列表 `vehicle` | 菜单 `1453`;页面 `8819-8886` | 国内/海外区域页签;自有/外派归属页签;按车牌、司机、车型和状态筛选;新增、导出;两类车辆不同表格列;列表下方预留配送进度和运营记录 | 列表数据在 `ownVehiclesData`/`dispatchVehiclesData` 内存数组中;新增、编辑、删除、状态校验和提示均在浏览器内完成;配送进度卡片在页面 CSS 中隐藏,运营卡片在详情时被移动 | 车辆主数据沿用当前真实模块;新增字段和运营记录需先定服务端归属 |
| 车辆新增/编辑 `modal-vehicle-edit` | `8890-8935` | 归属、车牌、车型、油耗、当前公里码、电话、外派单位、区域、状态、停运原因、FBA 仓、发车时间、预计到达时间;自有车辆编辑时附带保养和加油字段 | 必填校验、派送中/停运中条件校验和本地数组更新;图片字段是字符串或示例文本 | 不直接照搬字段;公里/迈数、司机绑定、运单关联和附件归属需形成正式模型 |
| 车辆详情 `vehicle-detail` | 页面 `9024-9051` | 车辆概览、保养及加油、维修记录、紧急故障、应急救援、异常管理六个页签;概览含车辆信息和派送订单明细;各扩展页签可新增记录 | 详情由本地数组拼装派送订单;更换历史缺页面容器;维修/故障/救援/异常共用未按车辆隔离的数组,部分保存字段错配 | 当前真实车辆详情只承载车辆主数据,服务端明确不含派送履约/更换历史;扩展页签必须逐项立项 |
| 司机管理 `driver-management` | 菜单 `1454`;页面 `8798-8805` | 司机总数、即将到期、驾照过期 KPI;“当前可派”卡片在源码中保留但被 CSS 隐藏;资质提醒;按姓名/手机/司机编号、状态、归属、资质筛选;司机档案表;新增、查看、编辑、删除、驾驶证附件查看 | `driverManagementData` 内存数组;根据当前日期计算驾照到期;缺附件或未审核显示待补件;资格阻断只显示提示,未联动排车保存;保存和删除只更新数组并弹 Toast/confirm | 需要独立司机主数据、资质状态机、附件和派车资格接口,不能把司机字段继续塞进车辆表 |
| 司机详情 `driver-management-detail` | 页面 `8807-8813` | 基础信息、驾驶资质、证照与派车状态;查看驾驶证附件 | 由司机内存数据拼装 | 需要真实详情 API;资格结果必须由服务端返回,页面只展示 |
| 司机新增/编辑 `modal-driver-edit` | `8815-8816` | 姓名、电话、归属、仓库、车型、语言/区域;驾照类型/编号/签发/到期;体检、培训/安全、保险到期;审核状态;驾驶证和其它附件上传 | 强制上传驾驶证后才允许保存;文件使用 data URL 暂存 | 文件应接经评审的上传与附件归属能力,司机资格审核和附件归属需进入正式契约 |
| 自有业务 `vehicle-own-business` | 菜单 `1455`;页面 `8757-8762` | 日期范围、排车单号/车牌/FBA 仓、任务状态、仓库筛选;今日排车、装车完成、派送中、派送完成 KPI;任务明细含预约、车辆、司机、提货仓、目的仓、托数、油耗、价格、装车/到达时间 | `vehicleBusinessRecords` 内存数组;KPI 和总价/单价在浏览器计算;可查看详情、上传现场/油耗图片和实际迈数 | 应消费正式排车/派送事实和服务端 KPI;不能把业务履约复制为车辆主数据记录 |
| 自有业务详情 `vehicle-own-business-detail` | 页面 `8764-8774` | 任务与车辆信息、路线货物与现场凭证、操作记录三页签;显示预设路线、GPS、ETA、油耗、费用预算和证据清单 | 详情字段、时间线、路线和证据状态为脚本拼装;上传仅修改内存对象 | 需要与排车、PDA、派送和文件服务建立稳定关联;GPS/路线告警先确认是否纳入本轮 |
| 外配业务 `vehicle-outsourced-business` | 菜单 `1456`;页面 `8778-8796` | 待外配托数、今天外配托数、在途车辆 KPI;合作车队/异常任务卡片被 CSS 隐藏;按任务号/车队/车牌/FBA 仓和任务状态筛选;展示总托数、自有成本、自有托数/单价、外接托数/金额/单价、ETA、状态 | 与自有业务共用 `vehicleBusinessRecords`;部分操作调用自有业务详情和上传照片逻辑;示例成本、托数和报价在浏览器渲染 | 用户已明确外接为利用自有货运输的剩余运力承接顺路外部货物;原型名称保留作追溯,后续建议改称外接业务,详见第 4.1 节 |
| 出车记录 `vehicle-trip-record` | 菜单 `1457`;页面 `8941-8987` | 时间区间统计四张图(托数、派送仓库、价格、托均价);按车牌/提货仓/派送仓、车辆类型、日期筛选;添加、编辑、导出Excel占位按钮;删除函数未发现页面调用;装车/派送完成时间、用时、托数、价格、托均价、油耗、图片附件 | `vehicleTripRecords` 内存数组;派送用时、托均价和图表汇总由浏览器计算;图片使用 data URL;时间校验只在前端;导出仅弹 Toast | 先定义出车记录来源和唯一性,再决定独立事实表还是由派送单投影;“板/托”“公里/迈”“油耗单位”必须统一 |
| 派送车队报价 `delivery-fleet-quote` | 通用菜单 `1527`;页面 `8989-9021` | 按发货城市、目的 FBA 仓、车队、提货方式、状态筛选;新增/编辑、启停、删除、导出;CSV 模板下载、预览校验、批量导入 | `deliveryFleetQuoteData` 内存数组;校验必填、非负价格和“城市+仓点+迈数+车队”重复组合;导入只写浏览器数组 | 先按第 4.1 节区分外接销售价与车队采购价,再定客户/供应商关联;CSV 导入需服务端校验和重复处理规则 |
### 2.2 车辆列表和详情的字段与交互
配套弹窗也属于本轮原型范围:车辆运营记录 `modal-vehicle-ops-record`(`8937`)、车辆详情扩展记录 `modal-vehicle-detail-add`(`8938`)、司机证照查看 `modal-driver-license-view`(`8816`)、出车记录 `modal-vehicle-trip`(`8966`)以及车队报价编辑/导入 `modal-delivery-fleet-quote`、`modal-delivery-fleet-quote-import`(`9009`、`9021`)。它们不单独扩成新的业务页面,分别随 VM-02、VM-03、VM-05、VM-06 的正式契约开放。
车辆列表在原型中有两套列:
- 自有车辆:车牌、车型、油耗、当前迈数、联系人、联系电话、状态、操作。
- 外派车辆:操作、车牌、车型、外派单位、联系电话、托数。
区域页签和归属页签同时存在,形成两个主切换维度;原型还把车辆配送进度、运营属性、保养加油和路线告警放在同一页面结构中。当前代码已按正式接口将区域降为查询条件,只保留自有/外派归属页签,并把操作列固定在第一列;该布局有现有原型矩阵记录的历史确认作为依据;若本轮重新确认布局则更新相应合同,代码现状本身不覆盖新需求。
新增/编辑弹窗的原型校验包括:车牌、车型、油耗、公里码必填;状态为“派送中”时要求 FBA 仓、发车时间和预计到达时间;状态为“停运中”时要求停运原因。上述校验目前只是原型脚本行为,最终规则要由服务端状态机确认。
新版车辆详情实际有“派送订单明细”;更换历史仍保留 `renderVehicleFleetHistory` 函数,但它读取的 `vehicle-detail-history-body` 仅在该函数中出现,未找到页面容器,不能算作当前可见分区。当前真实车辆主数据合同排除派送履约及车辆更换历史:Controller 注释排除前者,OpenAPI 的车辆详情 `GET /{id}` 明确排除两者。现有 Admin 详情仍保留这两块边界提示。若新增真实历史查询,需先确定订单/排车查询与更换历史的归属,不能把旧页面提示当作新版已经提供该功能。
运营扩展也存在未闭合交互:`vehicleDetailExtraRecords` 是按记录类型保存的全局数组,保存/渲染未带车辆标识;`openVehicleDetailAdd` 生成描述和处理人等字段,而维修/救援保存分支读取不存在的 `vda-item`、`vda-place`,会丢失录入信息。救援列表列名为“付款状态”,弹窗却选“待处理/处理中/已完成”。此外,车辆属性和路线告警面板在打开车辆详情时被隐藏,不能把源码内预留字段全部当成当前可操作需求。正式设计应分别确认记录归属、各类型字段、处理状态和付款状态。
### 2.3 原型中明确出现的规则冲突
| 主题 | 原型表现 | 需要冻结的正式口径 |
| --- | --- | --- |
| 距离单位 | 车辆列表弹窗使用 km;运营卡片、路线和车队报价使用 miles/迈数 | 车辆里程、路线距离和报价距离分别定义单位;接口禁止以字段名猜单位 |
| 托数单位 | 出车记录表头初始写“板数”,脚本又改成“托数”;外配业务使用总托数/外接托数 | 统一业务词和字段名;托盘数量与板数不能在前端静默换算 |
| 油耗单位 | 百公里油耗使用 L/100km,加油记录示例使用 gal,出车记录油耗使用 L | 定义车辆档案、加油事实、出车消耗的单位与换算责任,服务端返回展示单位 |
| 车辆合作方术语 | 原型混用“外派车辆、外配业务、合作车队、车队渠道、托/拖车公司” | 冻结用户可见词和服务端枚举/字段映射,避免把司机、承运商、车队和拖车供应商当成同一对象 |
| 车辆与排车关系 | 车辆列表有配送 FBA、发车时间和 ETA;排车列表也维护车牌、司机、预约和状态 | 车辆主档只保存可复用属性;排车/派送保存任务快照和执行事实,避免双写状态 |
| 删除 | 车辆、司机、车队报价有删除操作;出车删除只有未接入函数 | 分对象确定删除、停用、作废或更正语义;没有合同的动作不开放,不能自动用停用/作废替代 |
| GPS/路线 | 原型写“GPS 轨迹监控已启用”、路线偏离和 ETA 告警 | 先确认已有设备/轨迹来源和告警服务;没有正式来源时只能展示待接入状态 |
| 资格阻断 | 页面用日期、附件和审核标识显示资格与阻断提示,未形成排车拦截 | 临近到期规则已确认:30 天内仍有效允许并提醒,预计任务结束前过期禁派;由服务端返回资格和原因。核验时点及时间边界建议见第 4.4 节 |
### 2.4 原型统计与报价口径
原型中的金额和统计还需注意以下差异(均为原型事实,不自动成为正式口径):
- `renderVehicleBusiness` 的“今日排车数”实际取筛选后的行数,不独立限定今天;外配“今日外配任务”被脚本改名为“今天外配托数”,对应数字仍是静态值。正式 KPI 需明确日期字段、仓库时区、筛选范围、单位及聚合粒度。
- `renderVehicleTripCharts` 的“派送仓库”总数是去重仓库数,图中各仓的值却是出车记录条数;托均价是总价格除以总托数,并非各行单价的简单平均。正式报表应明确两个指标的名称,混币种不能直接求和;原型同时以列表日期和统计日期过滤,需要确认正式查询与图表是否共用范围。
- 车队报价 `validateDeliveryFleetQuoteDraft` 允许三种价格仅填一种,空值表示未报价,0 是允许输入的数值;CSV 确认导入会跳过无效/重复行并插入有效行。正式合同须确认沿用部分成功还是整批原子提交,不能把空值转换成免费报价,也不能默认原型为全成功导入。
## 3. 当前代码、接口和数据现状
### 3.1 已具备的车辆主数据能力
当前 Admin 和 Lastleg 已经有一套真实车辆主数据能力,不能按旧缺口文档中的“车辆缺失”处理:
| 层次 | 当前入口 | 已有能力 |
| --- | --- | --- |
| Admin 导航 | `apps/admin-web/src/core/navigation/adminNavigation.ts:120-126` | 车辆管理下已有“排车列表”和“车辆列表”;车辆列表路由为 `/overseas-master-data/vehicles` |
| Admin 页面 | `apps/admin-web/src/modules/overseas-master-data/pages/VehiclesView.vue`、`VehicleDetailView.vue` | 真实分页、关键词/归属/区域/状态筛选、查看详情、新增、编辑、状态变更、CSV 导出;操作列固定在左侧 |
| Admin 路由/权限 | `apps/admin-web/src/modules/overseas-master-data/routes.ts`、`permissions.ts` | 车辆列表和详情使用 `vehicle:list`;创建、编辑、状态、导出权限独立 |
| 后端 Controller | `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/masterdata/vehicle/adapter/in/web/PlatformVehicleController.java` | 列表、详情、创建、编辑、状态、导出;编辑和状态使用 `recordVersion` 乐观锁 |
| OpenAPI | `baiyue-firstleg/lastleg-service/src/main/resources/openapi/overseas-master-data-v1.yaml` | `/api/platform/v1/last-leg/master-data/vehicles` 的 GET/POST、`/export` GET、`/{id}` GET/PUT、`/{id}/status` PATCH |
| 数据库 | `baiyue-firstleg/lastleg-service/src/main/resources/db/lastleg.sql` | `ll_vehicle`,车牌唯一;保存区域、归属、状态、里程、油耗、司机/外派单位、电话、备注和版本 |
| IAM | `baiyue-firstleg/iam/src/main/resources/db/lastleg-permissions.sql` | `platform:overseas-master-data:vehicle:{list,create,edit,status,export}` |
| 测试源码入口 | Lastleg 车辆 Controller/Application/SQL/OpenAPI 合同测试;Admin 车辆 API、挂载、视图和写行为测试 | 已定位到测试文件;本次未运行这些功能测试,文件存在不代表当前全部通过,也不证明部署或整套车辆管理完成 |
当前车辆主数据接口字段包括车牌、车型、百公里油耗、当前里程、司机/外派单位、电话、区域、车辆归属、状态、备注、记录版本和更新时间。本轮已增加最大标准托位、最大载重kg和可用容积m³,三项同填正数或全空待确认;车次分配不接受未知容量。服务端不提供车辆删除端点,当前 Admin 不展示删除动作。
需要保留的已有规则:车辆创建/编辑将车牌去除首尾空格并转大写,数据库对车牌做全表唯一约束;编辑时公里数不得小于原值;编辑和状态操作检查 `recordVersion`。当前状态为 `IN_SERVICE/在役`、`DISPATCHED/外派中`、`MAINTENANCE/维修中`、`INACTIVE/停用`、`RETURNED/已归还`,与原型“空闲/派送中/停运中”并不一一对应。`changeStatus` 只校验枚举与版本,没有按当前派车任务检查状态迁移;不能据此宣称已经实现车辆占用和释放。出处为 `VehicleApplicationService.create/update/changeStatus`、Admin `presentation.ts` 和 `ll_vehicle` 唯一索引。
### 3.2 原型范围与当前实现的差距
| 能力 | 当前状态 | 结论 |
| --- | --- | --- |
| 车辆主档列表/详情/新增/编辑/状态/导出 | 已有真实前后端合同 | 作为基线复用;先补字段和状态确认,再决定是否扩表 |
| 车辆运营属性(初始里程、停放位置、司机绑定、租赁状态) | 原型 `vehicleAttributeData` 和隐藏面板中预留 | 缺正式 DTO、表和权限;不能写入浏览器本地状态后宣称完成 |
| 保养与加油 | 已有独立车辆运维记录模型、文件归属、版本及历史,Admin 按车辆分页查询并接入新增/编辑和图片读取;实现边界见第 10.1 节 | 本地实现不代表环境已部署;不自动改车辆里程、占用或财务付款 |
| 维修、紧急故障、应急救援、异常管理 | 已接逐车新增/展示,异常支持编辑;修复原型字段错配并分离处理与付款状态,见第 10.2 节 | 维修/故障/救援后续更新入口仍待承载方式确认;财务闭环及真实环境验收未完成 |
| 司机主数据与资质 | 已新增司机后端、文件接入、Admin 列表/详情/编辑/审核/证照预览,补齐真实仓库关联与可选资质日期;车次分配、调时和整车 PDA 发车均复核资格;本地验证见第 10 节 | 实际命令的源码已接入,真实部署及 HTTP/PDA 验收尚未完成,不能以独立资格预览代替发车校验 |
| 自有/外接业务工作台(原型名外配) | 现有正式排车/派送模块存在,但没有原型同名工作台 | 已确认顺路拼载业务;建议按共享行程关联各客户单据,工作台展示自有/外接货物分项,详见第 4.1 节 |
| 车辆详情中的派送订单/更换历史 | 新版有派送订单展示,更换历史缺容器;车辆详情尚未接入两类记录,页面引导从现有排车/派送管理查看派送事实,明确更换记录未接入 | 车次已有改派历史,但不等于车辆详情已有跨车次履历;后续补真实查询,不以说明文字代替功能 |
| 出车记录与统计 | 原型本地数组和浏览器图表 | 需要确定事实来源、唯一键、费用归属、油耗证据和统计口径 |
| 派送车队报价 | 原型内存数组、CSV 解析和浏览器校验 | 先区分外接销售报价与车队采购报价,再决定模型复用和客户/供应商关联,不能将外接收入建成供应商应付 |
| 车辆管理新增菜单 | 当前源码已注册排车列表、车辆列表和司机管理,司机详情使用独立路由 | 自有业务、外接业务、出车记录等菜单继续随对应正式接口接入;源码注册不表示环境已发布 |
### 3.3 与现有排车和车队能力的边界
现有海外排车正式入口是 `apps/admin-web/src/modules/overseas-warehouse/`,后端入口在 Lastleg `dispatch/`;排车状态、PDA 拣货、发车门禁、转派送和派送完成属于排车/派送链路。目的港码头车队选择属于货柜聚合的码头拖车链路,使用供应商主档和独立权限。车辆主数据只维护车辆档案和可复用属性,不能成为排车状态或码头车队事实的第二个写入口。
### 3.4 已验证的现有执行顺序
本节记录共享车次接入前的执行链,作为继承关系与缺口的对比依据;当前车次增量以第 10 节为准。不表示已经完成真实环境验收,也不把新增原型审核作为既有前置条件。
1. **预排车**:候选列表可跨客户查询,但单次创建排车须选同一客户、同一海外仓的托盘。不能把“跨客户可查看”理解为“一张排车单允许跨客户混装”。依据:`DispatchService.resolveCustomerScopeForPallets`、`requireSingleCustomerScope` 和 `preArrange` 的仓库校验。
2. **维护本次排车信息**:当前请求保存车牌、司机姓名/电话、承运商名称、预约和预计时间等文本/快照;未形成车辆档案 ID、司机档案 ID 关联及资格门禁。车辆档案状态不等于本次排车状态。
3. **发车前完成两组条件**:现场 PDA 完成拣货并核平箱数;后台在允许阶段执行“转派送”。转派送可早于拣货完成,但货物必须已收货并绑定实物托盘,且必须早于发车。两组条件不是必须按固定先后完成的串行操作。
4. **转派送生成单据**:一张排车单对应一张出库单,派送单按目的地分组。FBA 仓是常见分组;当前 `DeliveryTransferService.deliveryGroupKey` 也处理私人地址与邮编,并以目的仓编码或 ID 分组,不能将能力范围仅写成 FBA。此时出库单为 `WAIT_OUTBOUND`,生成派送单本身不表示车辆已出发。
5. **PDA 发车**:当前 `DispatchPdaWorkflowService.requireVehicle` 只检查车牌非空;还检查绑定仓、拣货任务完成、全部箱数核平、排车为 `READY_TO_DEPART`、出库单为 `WAIT_OUTBOUND`。通过后扣减对应已拣库存,出库单变为 `OUTBOUNDED`,排车变为 `DEPARTED`。没有现成的车辆主档可用性、司机证照或两级审核门禁,不能将“车牌非空”表述为“车辆与司机完整合规”。
6. **目的地分别签收**:`DeliveryDocumentService.save` 在有效状态下把非空 `RECEIPT` 资料保存进正式快照,才自动完成当前派送单;单纯上传文件不触发完成。一张派送单完成不代表其他目的地同时完成,也不自动证明新增的“整次出车记录”已经结案。
并发与快照边界也有现状差异:车辆主档有 `recordVersion`,但 `DispatchRequests.Update` 没有客户端期望版本,`DispatchService.update` 使用行锁且仅允许 `PENDING_DEPARTURE` 编辑;行锁不等于能识别用户提交的过期表单。转派送会把当时的车牌/司机等信息保存到派送单,后续修改排车是否同步、是否重新审核必须单独规定。排车取消、移除托盘、出库取消是不同命令,不能将其理解为任意阶段一键撤销整条链路。新增审核和改派须同时定义并发版本、审核依据快照和关联单据处理规则。
现有执行链为:**预排车 → 维护车牌等任务信息 →〔PDA 拣货核平 + 发车前转派送〕→ PDA 发车出库 → 各目的地分别签收**。司机资质、两级审核、运维、行程汇总与自有/外配工作台如何接入,属于本次新增设计。
### 3.5 本次排查发现与纠正
以下原型行号均指第 1 节的外部 `新版.html`,通过静态脚本核对,未作浏览器视觉验收。
| 严重程度 | 先前表述的问题 | 本次核对结果与处理 |
| --- | --- | --- |
| 高 | 把“调度审核 → 理货员审核”直接接在现有 PDA 流程前,且任务写成只复用现有审核 API | 原型 `18589-18599` 确实演示调度通过转理货审核、理货通过进入装车中;已检查的 dispatch Controller/DTO/Service 没有对应审核命令。普通排车编辑 `18804-18829` 也没有重置审核阶段/驳回状态,只有散板上下文分支写待调度审核。原型本身的提交与驳回重提尚未闭合;需新增审核契约,并确定与 PDA 开工/发车的关系,不能直接复用不存在的 API |
| 高 | 把司机页面显示“已阻断派车”当成真实业务阻断 | `openDriverDetail`(`22702`)只生成提示文字,且将“即将到期”也显示为阻断,与“30 天提醒”文案不一致;排车保存未联查司机档案,当前服务端也未关联司机资格。资格计算、临近到期是否阻断、提交和发车时是否重新核验需要分别定义 |
| 高 | 把自有/外配页理解为排车生成后的现成视图,把外接金额直接解释为车队应付 | `vehicleBusinessRecords`(`22627+`)是独立示例数组;排车用另一组 `outboundVehicleData`,出车统计又用 `vehicleTripRecords`。现有脚本没有证明三者自动同步。外配行同时含自有托数/成本、外接托数/金额,且示例混用人民币与美元;只能说明原型要展示这些列,不能据此决定货源、承运关系、应收/应付或财务自动入账 |
| 中 | 把出车记录的删除函数算成可用按钮,并把导出写成原型未要求的可选扩展 | `8953` 有“导出Excel”按钮,但只弹 Toast;`renderVehicleTripRecords`(`22953`)行操作只渲染编辑;`deleteVehicleTripRecord`(`23057`)仅找到定义,未找到调用入口。更正为:新增/编辑可演示,导出是占位交互,删除存在未接入函数 |
| 中 | 默认无 DELETE 就提供停用/作废,且一律按车辆主数据合同处理 | 车辆主档当前无 DELETE;排车则有 DELETE 路径承载取消,HTTP 方法不能代表物理删除。新司机、运维、出车记录的停用、作废、删除或更正须各定生命周期,不能凭缺少端点自行增加替代动作 |
| 中 | 直接描述“司机/车辆资格齐全 → 发车”,并遗漏单客户同仓与私人地址派送 | 当前实际条件和单据关系以第 3.4 节为准。完整资格校验是新增工作;“转派送在发车前”这一结论经代码复核仍成立 |
## 4. 业务决策与剩余边界
以下为决策清单,按受影响工作包分别冻结;已有代码规则不因列入讨论而自动失效。无关问题未定不阻止已确认部分的实现;未定业务不能由页面本地字段代填:
1. 本轮是否一次纳入新版原型的司机管理、自有业务、外配业务、出车记录和派送车队报价,还是先完成车辆主档的第二阶段增强。
2. 国内车辆和海外车辆是否共用同一车辆主档;区域是否只是查询维度,还是决定所属仓、时区、单位和可派送范围。
3. 自有车辆、外派车辆和租赁车辆的归属枚举;外派车队、司机和车辆之间是否允许一对多历史绑定。
4. 车辆状态、排车状态、司机资格状态和派送状态分别由哪个服务维护,哪些状态可以相互阻断;现有五种车辆状态与原型三种状态如何映射。两级审核状态应与拣货/装车/发车的实际执行状态分别定义,不能用审核通过伪造现场开始时间。
5. 已确认采用 30 天临近到期提醒及第 20 项禁派规则。尚需确定必需资质清单和审核角色:驾驶证之外的体检、培训/安全、保险是否全部必填,不能由原型字段自动推为必需。
6. 车辆运维记录是否要进入财务费用池;保养、加油、维修和救援费用的币种、汇率、税费、结算单关联和付款状态由谁确认。
7. GPS/路线/ETA 的设备和数据来源;如果没有正式来源,原型中的轨迹、路线偏离和自动告警是否延期。
8. 按用户要求已将“一次实际出车对应一个车次,多条货物明细,出车记录自动汇总”写入方案基线,见第 4.1 节;人工历史补录、车次中途换车和取消分支的规则在开发合同中细化。
9. 已将外接应收/实收、本趟直接成本和自有/外接成本分摊分别展示写入方案。尚需确定成交价按托还是按整单、实际数量变化后的改价、币种/税费和结算引用;计算结果由服务端输出,人工更正保留原因。
10. 根据已确认外接含义,外接报价是面向委托方的销售报价,应关联客户/委托方,不能强制当作供应商采购价。原型“派送车队报价”是否另用于向外部车队采购运力、是否纳入首期仍需明确;若是采购价才关联供应商。两类报价各定适用路线、计价单位、币种、有效期、版本及导入匹配规则。
11. 司机证照、车辆运维照片、出车图片和签收凭证分别归属哪个文件业务范围、保留多久、谁有下载权限;允许的大小、MIME 类型、预览和下载规则是什么。
12. 分别定义车辆、司机、运维和出车记录的停用、作废、删除或更正语义及权限。车辆主档当前无删除端点;不能将这一现状推为所有新对象的永久规则,也不能默认创造作废接口。
13. 跨区域日期、时区和工作日边界如何计算;车辆、排车、派送和统计接口返回的时间采用什么时区。
14. 平台客户数据隔离和角色范围:车辆、司机、车队、报价及附件是平台级共享,还是按客户/仓库限制可见和可操作范围。
15. 司机和车辆是否允许多仓、多司机或多车队绑定;绑定是否保留有效期、历史和并发冲突记录。
16. 当前车牌在车辆表内全局唯一且编辑里程不能回退;是否调整唯一作用域、如何处理换牌/里程录错需要明确决策。新增状态迁移、占用/释放、冲突与更正审计须显式设计,不能无意取消已有约束。
17. 车队报价 CSV 模板的当前字段格式、单批上限、失败行处理、重复行策略和导入幂等键;不预设旧模板兼容层。
18. 出车记录原型已包含导出Excel入口,但尚未生成真实文件;需确认正式导出格式、字段、权限、范围上限及统计口径。
19. 已确认审核首期只展示详情并提供通过/打回,不预设业务检查清单;建议沿原型保留调度/理货两级并记录人员、时间、意见,打回必填原因。拣货/发车的阻断时点、改派后重审和跨单快照同步仍需在接口设计中明确;通过审核不自动代表开始装车。
20. 已确认:临近 30 天到期但仍有效时允许派车并提醒,预计任务结束前会过期则禁派;必需资料缺失、未审核、已过期禁派。提交/审核/发车的复核时点、预计结束时间缺失处理和临时换司机规则在接口设计中落实。
21. 已确认外接是利用承运自有货物的车辆剩余运力,顺路承接别人的货;属于货源/承运任务来源维度,不等于外包给其他车队。当前单客户排车规则是实现现状,新需求需要同车关联不同委托方的货物,推荐的行程与客户单据关系见第 4.1 节。
22. KPI 的“今日”、统计日期、去重仓库数、出车次数、托均价分别采用什么口径;列表/图表是否共用筛选条件。车队报价空值与零价、导入部分成功与整批失败的规则须同时定清。
### 4.1 本轮业务确认与出车方案建议
**已确认**:本模块管理车辆,同时安排自己的货物运输;车辆存在顺路剩余运力时承接外部货物,称为“外接”。一趟车可同时含自有业务货物和外接货物。原型“外配业务”的名称和外包承运暗示需要据此调整,建议用户可见名称改为“外接业务”;车辆归属(自有/外派/租赁)与货源类型分别记录,不从其中一个自动推导另一个。
**已确认**:审核先以详情展示、审核通过、打回为范围,不做未经确认的逐项业务检查表。建议保留原型两级入口,打回时填写原因,修改后重新提交;记录审核人、时间、意见和本次审核版本。司机资格不能因人工点通过就跳过服务端已确认的禁派规则。
**已确认的司机资格规则**:必需资料缺失、未审核、已过期时禁止派车。对于 30 天内到期但尚有效的证照,用户已明确选择“允许并提醒,任务结束前会过期则禁止”。计划预计结束时间用于派车校验,改派或时间变更后重新计算资格;缺少预计结束时间时不能直接判定满足该规则。具体必需资质清单和时间边界在合同中明确,不自动扩大为原型全部证照。
本次按用户“请写入后继续 Review”的要求,将该确认整理为以下判定表。表内“允许”仅表示通过此项证照校验,仍须满足车辆、审核、装载等其他派车条件:
| 证照与任务情况 | 判定 | 依据 |
| --- | --- | --- |
| 仍有效、超过 30 天到期,且有效期覆盖预计司机任务结束 | 通过此项证照校验,无临近到期提醒 | 按已确认的 30 天提醒窗口及任务全程有效要求推导 |
| 仍有效、30 天内到期,且有效期覆盖预计司机任务结束 | 允许,并展示到期提醒 | 用户明确确认 |
| 当前仍有效,但预计司机任务结束前会过期,无论是否已进入 30 天提醒期 | 禁止派车,需更换合格司机或更新并审核证照 | 用户明确确认;不能只检查“今天是否过期” |
| 必需资料缺失、未审核或已过期 | 禁止派车 | 前述已确认资格前提 |
| 未填写预计司机任务结束时间 | 草稿可保存,正式派车前要求补齐 | 第 4.4 节执行建议;不能默认为证照覆盖任务 |
证照有效截止日、时区及恰好触及截止时刻的处理仍按第 4.4 节明确,不以本表推定法定有效时刻。
下面的“一车次、多明细、分别签收、成本汇总”方案已按用户“写入后继续 Review”的要求纳入文档设计基线;表中明确标为首期建议的范围以及第 4.2 节问题仍待确认。方案写入本身不表示功能已实现,也不将未确认的边界自动定案;后续源码进度见第 10 节。
| 对象 | 建议口径 | 主要原因 |
| --- | --- | --- |
| 运输行程/车次 | 一次实际出车对应一个稳定业务编号,记录车辆、司机、起终点、计划/实际发车及完成时间;车次计划创建时即可建记录,发车后继续补齐实际事实,同一趟多目的地不拆成多次出车 | 能按真实运行统计,避免一车送多个仓被重复计次数 |
| 货物明细 | 行程下关联多条自有/外接承运明细;每条有委托方、来源单据、提卸货点、托数、重量、体积和约定费用。自有业务货物也保留原客户归属 | 同车可拼载,客户订单、库存、附件和费用保持各自归属 |
| 执行单据 | 在现有客户排车/出库/派送单之上建立共享行程关联,现有单据保持客户/仓库边界;行程只统筹物理车辆、路线和发车,不复制客户库存账 | 不直接解除现有单客户校验,也不把所有货假挂在同一个客户下 |
| 外接履约来源 | 首期建议人工录入外接委托和承运明细、分配到行程;进入本仓的外接货走真实收货/库存流程,异地提货须有独立交接证据,不虚构已入仓事实 | “接单”和“已收货”是不同事件;是否首期支持沿途提货应明确范围 |
| 剩余运力 | 先检查托位、限重和容积,预留外接货后立即占用;多点提卸按每一段在车货量核算,不能只看整趟总托数 | 防止同一空位重复出售或沿途超载;可用托数不是唯一条件 |
| 行程完成 | 所有承运明细均送达签收,或异常已按明确终态处理后,结束本次行程;一个目的地签收不完成整车。车辆是否可再次调度还需检查占用、位置和故障状态 | 支持多目的地、拒收/退回;不将付款完成或必须回原仓作为派送完成条件 |
| 出车记录 | 从行程及各客户执行单据自动汇总;人工只补充实际里程、油耗、凭证及有权限的更正,保留原因和历史 | 避免再建一张自由填写、与实际运输脱节的出车统计表 |
| 收入 | 外接货的约定运费属于向委托方收取的运输收入,区分报价、确认应收和实收;自有业务订单的原有运费不能在车辆模块重复计收 | 能分析外接贡献,同时防止重复计费 |
| 成本 | 行程记录实际燃油、司机本趟费用、通行费、停车及其他直接费用;保养、保险等固定费用后续按明确规则分摊,账务仍走 Finance | 先得到可核对的单趟直接成本,避免把未分摊成本的结果叫完整利润 |
价格展示建议替换笼统“价格”为“外接应收、外接实收、本趟直接成本、自有货分摊成本、外接货分摊成本”。同路线、同规格可先按托数分摊直接成本;距离/占位差异较大时另定按占用空间与里程的规则。分摊值用于运营分析,不等于新增客户应付,也不自动生成正式账单。
示例(统一币种、同路线同规格):一车容量 30 托,自有货 20 托,外接 10 托,外接确认运费 300,本趟直接成本 600。按托数分摊,自有货成本 400、外接成本 200,外接在该分摊口径下贡献 100;不包含固定费用,不能称为整趟净利润。托均收入只用外接收入除外接托数,整趟托均直接成本用本趟直接成本除全部实运托数,两个指标不得混用。
接入影响:当前“一张排车 → 一张出库 → 多目的地派送”仍是客户执行单据的现状;推荐增加的共享行程可能关联多组此类单据。必须另定按车统一发车的校验、失败重试和各客户状态推进协议;不能因新增行程就假定现有接口支持一次多客户出库。“空位放出去”首期建议由运营登记可接运力和外接预订,公开发布、在线接单或撮合平台需另行明确,不自动扩大本轮范围。
### 4.2 本轮 Review 后仍影响开发范围的问题
无需重新确认第 4.1 节已明确的外接含义、简化审核交互和司机临近到期规则。下面的问题按影响排序,建议均未冒充用户确认:
| 问题 | 为什么影响实现 | 建议首期口径 | 影响任务 |
| --- | --- | --- | --- |
| 外接货交到我方起运仓,还是需要司机沿途去别处提货? | 前者可用现有仓库真实收货和 PDA 出库;后者增加路线站点、提货交接、分段容量及未入本仓的履约来源 | 首期先接送到本起运仓的货,多目的地派送;沿途提货另开范围。若沿途提货是核心业务,则在本轮纳入,不能伪造入库绕过 | VM-05、VM-04a、VM-07b |
| 外接委托方是否已是系统客户,谁付款? | 单据、库存和应收需要稳定的客户及付款归属;货物原货主、委托运输的人、付款方可能不同 | 外接单选已有客户/委托企业,联系人独立记录;新委托方先按现有客户建档。是否需要工作台账号按实际需要处理,不强制外接人在线下单 | VM-00、VM-05、VM-06 |
| 两级审核分别在什么作业时点生效? | “详情 + 通过/打回”的界面已定,但阻止拣货还是阻止发车会影响 PDA | 建议调度通过后允许开始拣货,理货通过且实际拣货核平后允许发车;审核记录与实际作业状态分开。关键货物/车辆/司机变化重审,但不回滚已经发生的拣货事实 | VM-04a、VM-07b |
| 外接运费按托数还是整单报价?货到后数量变化怎么办? | 决定报价明细、成交金额、补差价与取消收费;原型单价和总价不能互相覆盖 | 首期支持按托/整单两种计价,保存成交价快照;实收数量与预订不同先重新核量并确认金额,不静默改价或放行超载。等待费/额外提货费等单独登记原因和确认 | VM-05、VM-06 |
| 外接预订何时占位、撤单后何时释放? | 未确认询价不能永久占满车辆,已装车货物也不能通过取消按钮从库存中消失 | 询价不占位,确认承运后占位;发车前未执行的撤单释放,已拣/已装走正式撤回或退仓动作;发车后拒收/退回走异常处理。临时留位的超时和取消费另定 | VM-05、VM-04a |
| 是否首期承接超规格托盘、散货或特殊货物? | “空 10 托”只对明确规格有效;现有 Admin 车型为大车 30 托/40000 LB、小车 15 托/10000 LB,不代表任意车辆都适用 | 首期建议标准托盘普通货,至少核验托数/规格、重量和体积;实际车辆容量独立维护,超规格/散货另确认计价与占位方式。重量未确认前不能按可用托数直接承诺承运 | VM-01、VM-05、VM-06 |
其他实现细节由合同设计给出具体方案,不把所有技术选择都退回给业务:同一客户执行单及同一批待发运货物不能重复绑定有效行程;不将这一限制扩大为原始客户订单永远不能按现有规则分批履约。行程与各客户执行单据保留稳定关联;整车发车需先校验所有本次发运明细就绪,保证重试不重复扣库存;客户只可见自己的货物、凭证和费用。车辆/司机的调度占用、变更历史与附件读取权限纳入相应后端门禁。
### 4.3 本轮发现的现有接口差距与修订
1. **转派送强制收费与“不重复收费”冲突**:`DeliveryRequests.Transfer.fees` 非空;`DeliveryTransferService.validateTransferFees` 要求存在正数 `DELIVERY_FEE`,地板/混装还要求装车费,购买预约要求预约费;`transferResolved` 会调用 `feeSources.publishApproved`。因此新行程不能无条件逐客户重放这套新增费用流程。建议新增明确的费用来源/覆盖关系,支持引用已确认费用与登记本次新增费用,Finance 为唯一账务事实;具体字段随 API 合同确定,不用零元或虚构费用绕过现有校验。
2. **一个平台行程不能等同于一张客户排车单**:现有 `DispatchService` 保留单客户、同仓校验,新行程统筹多个客户执行单据。需要验证某客户准备失败时整车不误发、重试不重复执行、取消只影响指定承运明细,不把平台行程 ID 当成客户归属。
3. **计划数量、实收数量与占用容量需分开**:接单时的预订不等于已到货;按实际装载检查每段托位、重量和体积。外接临时加货或少到货会改变余位和成交金额,不能让页面自行修改原出库事实。
4. **行程完成、车辆可派、费用结清为三个状态**:货物签收完成不自动代表已收到运费,也不必等待回到原仓才完成运输;车辆释放还需考虑位置、故障和下一任务时间。一次行程中途换车应保留交接/换车历史,不将原记录直接改成另一车牌而丢失追踪。
追加源码核对:转派送原先在同请求键、已转换排车及唯一键竞争三条重放路径直接返回旧结果,修改金额后可能表现为成功但仍沿用旧费用。本轮已在 `ll_outbound_order.request_hash` 保存首次业务请求摘要;仅请求键不同而业务内容一致可以重放,费用、计划时间、装载等内容不同则拒绝,原单据及已发布费用保持原事实。该修复解决请求重放误报,不代表第 1 项的费用覆盖引用已经实现。现有 Lastleg 费用查询按业务单据返回已登记来源,Finance 事件接收接口也不提供“该费用覆盖本票尾程哪些服务”的证明;后续须按实际承运明细、来源版本和明确服务范围设计引用,不能拿同客户任意已收费记录或总运费金额直接判定派送/装车/预约已包含。
本节区分接口差距与追加修复,实际实现范围和验证结果见第 10 节;未注明已实现的方案不能视作完成。第 9 节五轮 Review 是此前版本的记录,本节是随后业务确认后的追加核对。
### 4.4 司机规则写入后的追加 Review
本节记录 2026-10-02 本轮文档 Review。已确认业务规则保持第 4.1 节原意;下列边界是实现建议,不代表现有接口已经具备,也不把法定证照效力作推定。
**司机资格的执行建议:**
- 草稿可先保存缺失信息;正式分配司机、提交审核、审核通过、发车时由服务端重新计算资格。缺少预计任务结束时间时提示补齐,不允许通过正式派车/发车校验。
- 提醒按证照配置的有效时区和当地日期计算,剩余有效天数为 0~30 天时提醒。证照只有日期时,建议记录其当地有效截止日;截止日当天计划结束是否允许,取决于明确的有效截止时刻,不能由浏览器时区或固定加 24 小时推算。日期边界、夏令时和恰好到期时刻须覆盖测试。
- “预计任务结束”应覆盖该司机本次实际承担的驾驶任务;若还需返程、转场,不能仅以最后一票货物的预计签收时间代替。行程派送完成与司机任务结束分别记录。
- 更换司机、替换必需证照或调整预计结束时间时重新校验;证照关键内容修改后建议重新审核。普通联系人信息修正不应无条件推翻整车审核,重审字段由合同列明。
- 已在途时发现延误将跨过证照有效期,应提醒调度并登记处置/换司机;不得自动撤销已发车事实、回滚库存或将整趟标为已完成。实际交接保留时间、地点、双方司机和凭证。
**本轮优先澄清的业务问题:**
| 问题 | 当前结论与建议 | 不明确会产生的影响 |
| --- | --- | --- |
| 外接货从哪里装车? | 已确认首版送到我方起运仓;沿途提货留待后续版本优化。对应第 4.2 节首项 | 影响真实收货、交接证据、路线站点及 PDA 范围 |
| “空位放出去”是否需要客户可见的发布入口? | 已确认首版运营线下找货、后台登记余位和外接订单;客户工作台在线发布/申请留待后续版本,不以后台登记冒充线上接单 | 仅做后台登记不能被描述为已经完成线上发布或接单 |
| 两级审核卡在哪个节点? | 已确认详情、通过/打回交互及首版时点:调度通过后开始拣货,实际核平且理货通过后允许发车 | 影响审核详情中的数量来源,以及 PDA 开工/发车门禁 |
| 哪些司机证照属于必需资料? | 首版按驾驶证作为基础必需项执行,体检、培训/安全、保险先记录日期,不自动设为必填;这是本轮产品范围,不推定法定资质结论 | 影响缺件、未审核和过期的禁派范围;不能只确认到期算法而遗漏适用证照清单 |
这四项按本轮用户“按建议执行、先做首版”的确认推进。其余仍按第 4.2 节保留明确建议:已有客户/委托方建档、按托或整单成交快照、确认承运后占位、标准托盘普通货。未经确认不写成最终业务事实;这些问题只约束相关工作包,不重复询问外接含义或 30 天到期规则。已确认部分可继续细化和开发,但不能据此判定外接、审核及司机资格的整条流程已经冻结。
### 4.5 本次追加 Review:装载、占用与异常分支
本节是对本文方案的一致性 Review,不代表新增代码或环境验收。第 4.4 节范围问题继续待答;以下给出合同设计建议,避免重复增加业务确认问题。
| 发现的缺口或歧义 | 建议补齐的规则 | 对应任务与验收 |
| --- | --- | --- |
| 按客户货物明细直接累加托数,可能把多客户合托计算成多个实物托盘 | 装载以实物托盘和实际占用的标准托位核算;客户货量、收费托数和物理占位分别记录。同一实物托盘的重量、体积只统计一次,客户货物归属保留;不同卸货站点的货物是否允许同托须明确现场拆托方式,首期建议拆成可独立卸货的实物托盘 | VM-05:两客户同托不重复占位、不重复计重;客户费用仍分别核算 |
| 一票未到齐或被打回时,其他货已就绪,整车如何继续 | 任一当前发运明细未就绪均阻止整车发车。若要剔除该票,先完成有权限的改计划及必要撤拣/退仓,重新核算容量、费用和审核,再统一发车;不能靠忽略失败的客户单局部推进 | VM-04a、VM-05:一票失败全车不误发;剔除已拣货物不丢失库存与作业事实 |
| “货送完”与“司机任务结束”不同,过早释放会重复派车 | 货物履约结束、车辆释放和司机释放分别判断;司机仍承担返程或转场时继续占用。允许提前建下一车次计划,但正式分配须检查资源占用;换车/换司机保留交接事实 | VM-02、VM-05:全部签收但司机尚在任务中,不能分配重叠任务;不因费用未结清而无限占用 |
| 文档“一张客户单不能分配两车”的措辞过宽 | 防重复约束落在客户执行单与实际待发运货量上;原订单如按现有业务规则拆成不同批次,不因共享车次设计一律禁止分批。新增拆单能力不在本条自动承诺 | VM-04a、VM-05:重复发同一批货被阻断,合法独立批次不误拦 |
审核被打回后应展示原因并允许修改重提,已经完成的现场动作保留。装载或费用变化后,应分别确认新的装载依据与成交金额,不能用一次“审核通过”同时代表收货完成、货物发车和客户付款。
### 4.6 本次复核:承运承诺、审核范围与部分拒收
本次按“写入后继续 Review”的要求复核第 4.1 节:司机临近到期判定已经写入,继续按用户明确确认执行,不再次征求相同决定。以下三项是补充方案,尚未获得业务确认,不代表现有功能已实现;它们细化第 4.2、4.5 节,不替代其中仍待确认的范围。
| 需要补齐的边界 | 建议处理方式 | 对应任务与验收场景 |
| --- | --- | --- |
| 自有货优先是否允许挤掉已经确认的外接货 | 建议自有货在对外确认承运前优先安排;外接一经确认就占用承诺运力。之后自有货增加导致超量,应由调度协商改期、改车或撤单并留存结果,再释放或调整预留,不能自动取消外接或超载发车。外接预留与实际装载关联替换,不能在到货后把同一票重复计算两次 | VM-04b、VM-05:余位已确认给外接后新增自有货,提示容量冲突;外接从预订转实收时占位不翻倍;撤单按是否已拣/已装分别处理 |
| 审核通过究竟覆盖哪些单据和数据,修改后哪些审核失效 | 建议客户执行单保留各自调度审核,整车理货确认覆盖本次全部发运明细及装载版本;整车发车同时核对两者。增减货物、换车、换司机、改路线或延长任务后使受影响的通过记录失效,并重新检查资格、装载与容量;历史审核和已发生作业事实保留。联系人或纯备注修正不触发无关重审。审核所属对象仍需与第 4.4 节的审核时点一并确认 | VM-04a、VM-05、VM-07b:客户 A 通过不能代替客户 B 通过;旧页面提交旧版本不能批准新装载;改司机后不能沿用旧司机资格结果 |
| 多点派送中只有部分货物拒收,是否可以直接结束整车 | 建议已经签收的明细保留完成事实,拒收部分记录数量、位置、责任人和后续处置,保持未结案,直到有真实退回签收或经明确流程确认的交接终态。仅填写异常说明或关闭工单不能代替货物交接;需重派的货物另关联后续任务,不能通过改签收数量消除差异。货物结案之后仍分别判断车辆和司机是否结束任务 | VM-05:两站已签收、一站拒收时不能完成整车;部分退回的数量须与实发和已签收数量核平;异常说明保存不自动释放资源、不重复收取原运输费用 |
需要优先获得业务答复的四项已统一列入第 4.4 节:外接货装车地点、余位是否面向客户在线发布、两级审核生效节点、必需资质清单。“30 天提醒”已经确认,不等于驾驶证以外的体检、培训和保险都成为必填门禁。未决项仅约束相关工作包,不能据此宣布全模块已经具备开发或验收条件。
### 4.7 首版确认前的决策依赖记录(已由本轮确认解除待答状态)
2026-10-02 再次按当前路由、交互矩阵、车次发车服务与费用来源接口核对:核心业务及新增交互选择连续多轮仍未收到答复。已确认规则的实现和本地回归保留;不能用继续修局部缺陷或重复跑测试,代替下面的流程决策。当前未满足整模块交付条件。
| 待答入口 | 直接受影响的工作 | 当前证据与边界 |
| --- | --- | --- |
| 第 4.4 节:外接货装车地点、余位发布方式 | VM-04b、VM-05 的外接委托、收货/沿途提货、客户申请和占位流程 | 共同起运仓的客户执行单车次已有后端,但不是完整外接接单能力;不能据此排除沿途提货或 Client 发布需求 |
| 第 4.4 节:两级审核生效时点、必需资质清单 | VM-02、VM-04a 的正式派车、拣货、发车门禁 | 当前资格校验不代表审核节点已实现,也不能默认驾驶证以外所有证照都不需要校验 |
| Admin `PROTOTYPE_MATRIX.md`:车次页面承载方式 | VM-07b 的计划、分配、关联排车、装载、结案和资源释放入口 | 当前 `routes.ts` 无车次操作路由;新 PDA 发车已要求车次关联,缺少平台入口时不能按可操作闭环发布整个车辆包 |
| 同一矩阵:维修/故障/救援更新处理入口 | VM-03 的持续处理流程 | 原型只定义新增;服务端可更正记录,但页面仍未开放未经选择的新增行操作 |
| 第 4.3 节:原运费的服务覆盖与来源引用 | VM-04a、VM-05、VM-06 的不重复计费和费用展示 | 建议每票明确已含哪些服务并关联原费用来源;只对另行确认的新增项目计收。本节记录初始差距;现已接入按实际货物确认原费用覆盖,源码与验证见第10.9节 |
上述答复到齐或逐项明确后,按对应工作包继续实现;未答部分保持待确认,不代填为“通过”或通过旧行为回退发布。部署授权仍有效,不需要再次申请同范围授权;源码、配套 Schema/权限、操作入口和真实 HTTP 必须一起核对,环境状态继续只以两份正式部署/通信契约为准。
## 5. 任务拆分与依赖顺序
VM-00 的交付不是只列问题:对第 4 节每项记录“已确认现行规则 / 本轮采用方案 / 后置 / 待业务确认”、适用工作包及确认依据。司机资格和审核决策约束 VM-02/VM-04a;已确认的自有/外接含义与已写入的行程/金额设计基线约束 VM-04b/VM-05;第 4.2 节未决范围分别跟进;运维字段和附件约束 VM-03;报价匹配和导入约束 VM-06。未获得用户决策的项保留待确认,不由本轮 Review 代为批准。
以下是候选工作包,不是已批准排期。P0 表示本方案的前置工作,P1 表示后续候选实现,Gate 表示交付门禁;具体纳入范围在 VM-00 冻结。各包只同步实际受影响的前端、后端、OpenAPI、权限、SQL、测试与文档,避免重复安排页面工作。
| 编号 | 优先级 | 工作包与主要交付物 | 建议实现归属 | 依赖 |
| --- | --- | --- | --- | --- |
| VM-00 | P0 | 冻结范围、术语、单位、状态机、车辆/司机/排车边界、删除策略、文件和权限模型、各事实的服务归属与模块命名;形成确认版字段表和页面清单 | 产品/业务 + 后端/前端共同评审 | 无 |
| VM-01 | P0 | 车辆主档对齐:确认现有 `ll_vehicle` 字段;按 VM-00 结果决定是否补齐初始里程、停放位置、司机/车队关系、租赁状态、停运原因等主档字段;FBA、发车时间、ETA 和任务快照不得预设写入车辆表;按影响更新 DTO、OpenAPI、SQL、Mapper 和权限,向 VM-07a 交付字段合同;保留 `recordVersion` | Lastleg masterdata + Admin overseas-master-data | VM-00 |
| VM-02 | P0 | 司机主数据:司机档案、归属/仓库、驾照和资质日期、审核状态、附件、`canDispatch`/阻断原因;列表、详情、新增/编辑、到期提醒和独立权限;接入现有文件上传与附件归属契约,不把 data URL 当持久化方案 | Lastleg 新司机域 + 现有文件能力/IAM + Admin | VM-00;与 VM-01 并行 |
| VM-03 | P1 | 车辆运营记录:保养、加油、维修、紧急故障、救援费用、异常;记录版本、操作人、附件、里程阈值、核验/处理状态和费用边界;按车辆标识隔离记录,逐类型定义字段及处理/付款状态,向 VM-07a 交付 API | Lastleg 车辆模块(服务归属由 VM-00 确认) + Admin | VM-00、VM-01、附件/文件归属契约;可先做契约阶段 |
| VM-04a | P0 | 排车执行扩展:两级审核、驳回重提、车/司机关联与资格校验;定义 PDA 门禁、期望版本、审核后改派、转派送快照及取消联动;处理正数派送费必填与费用引用/不重复入账的差距(第 4.3 节);复用已有命令并补齐缺失契约 | Lastleg dispatch/delivery;Admin/PDA 为直接消费者 | VM-00 相关决策;车/司机联动依赖 VM-01、VM-02 |
| VM-04b | P1 | 自有/外接工作台:按已确认顺路拼载含义展示货物明细、余位和预订;推荐按共享行程统计次数,自有货成本与外接应收分别展示。按第 4.1 节行程基线补齐数据关系与查询,GPS/自动财务入账按范围决定 | Lastleg dispatch/delivery;Finance 为账务权威 | VM-00 相关决策;依赖 VM-05 的行程合同;若消费审核/资格字段,再依赖 VM-04a |
| VM-05 | P0 | 行程与出车记录(已写入方案基线):以一次实际出车为粒度关联多个客户执行单据,区分自有/外接货源;设计分段运力预留、统一发车与重试、各站点签收和异常终态;出车记录自动汇总并提供授权补充/更正与导出,不以统计页替代行程执行模型 | Lastleg 内的行程模块与既有 dispatch/delivery 协作;不预设新微服务 | VM-00 明确第 4.2 节提货/预订/计价范围;车辆关联依赖 VM-01,资格与审核依赖 VM-02/VM-04a 对应合同 |
| VM-06 | P1 | 报价:先区分外接销售报价与原型车队采购报价,按确认范围实现;外接关联委托方,采购关联供应商;明确路线、计价单位、币种、生效版本、启停、重复约束及 CSV 导入导出。外接承运明细保留成交价快照,报价后续修改不覆盖已确认成交金额 | Lastleg 业务报价 + 客户/供应商目录,Finance 为账务权威 | VM-00 确认报价用途;不以采购报价完成作为人工外接接单前置条件 |
| VM-07a | P1 | 现有车辆主档页面收口:按正式字段/状态更新 `VehiclesView.vue`、`VehicleDetailView.vue`、表单和 `routes.ts` 描述;清理“派送订单/更换记录已具备”的陈旧文案;运维/异常页签仅在 VM-03 契约就绪后开放;把排车列表继续指向现有正式排车路由 | Admin overseas-master-data | VM-00、VM-01;开放运维页签时再依赖 VM-03 |
| VM-07b | P1 | 新页面正式接入:更新 `adminNavigation.ts`、模块 routes、权限守卫、排车审核/司机/业务/出车/报价页面与弹窗,补齐加载/空态/错误态/无权限态;不复制排车页面 | Admin 前端 | VM-00 相关决策;分别依赖 VM-02、VM-04a/VM-04b、VM-05、VM-06 对应合同 |
| VM-08 | Gate | 质量与验收收口:前端定向测试、后端 Controller/Application/SQL/OpenAPI/IAM 合同、Gateway 路由合同;1920×1080/100% 页面人工验收证据;字段、状态、权限、附件和异常场景回归 | 前后端共同 | 各工作包完成后 |
### 5.1 建议的并行边界
VM-01~VM-06 负责业务合同与服务端实现,页面由 VM-07a/VM-07b 对应承接;表内提及页面是验收范围,不重复建立两份前端任务。
- 后端可以将 VM-02(司机)与 VM-06(车队报价)并行;两者分别定义司机资格和已确认用途的报价,不共享未确认的自由文本字段。
- VM-03 的记录模型可以先做契约和表设计,但在 VM-01 未冻结车辆主档主键、单位和附件边界前,不应开始页面联调。
- VM-04a 与 VM-04b 分别估算和验收;工作台只读部分不等待整套审核完成。PDA 若因新审核/资格门禁调整,应沿既有排车执行接口及应用指引修改,作为 VM-04a 直接消费端验证。
- VM-07a 可在现有车辆主档合同确认后先行收口;VM-07b 按各自 API、权限和错误码就绪情况并行接入。原型页面不能直接复制到 `src/prototype/` 作为正式功能。
## 6. 验收清单
以下是未来实现的验收要求,本次文档 Review 不表示这些功能或测试已经完成。只对本轮实际纳入的工作包执行对应验收。
### 6.1 合同和权限
- 车辆主档的列表、详情、创建、编辑、状态、导出路径与统一 Gateway、Controller、OpenAPI、权限逐项一致。
- 车辆、司机、运维记录、出车、车队报价分别定义权限资源;每类列表权限包含详情只读,写入与已纳入的导出权限独立,由服务端鉴权。
- 浏览器长整型 ID 按字符串透传;车辆主档沿用 `recordVersion`。新增审核/改派命令明确期望版本、幂等和错误码;现有排车编辑缺少客户端版本校验,若本轮涉及该命令则同步补合同与受影响调用,不能把这一缺口写成已完成。
- 页面只开放有正式合同的动作;HTTP DELETE 不等于物理删除,取消、作废、停用、更正各按对象生命周期校验并保留对应审计。
### 6.2 页面和业务
- 车辆列表支持归属、区域、关键词和状态查询,操作列固定在第一列;空态、加载失败、无权限和导出失败可恢复。
- 排车详情/编辑复用现有路由;新增审核必须验收提交、逐级通过、驳回重提、修改后重审及 PDA 门禁。各客户执行单据的单客户同仓限制、收货后转派送和发车前置条件均由服务端校验;平台行程可关联多客户单据,不能把子单限制直接套在行程上。
- 车辆详情只展示服务端真实返回的主数据;派送订单、更换历史、运维记录和异常页签只有在对应接口存在时开放。
- 路由标题、描述和页面实际数据范围一致;未提供派送履约/更换历史时不得用路由描述暗示已具备。
- 司机过期、待补件、待审核和不可派状态由服务端资格结果驱动;到期提醒不能只由浏览器当前日期计算。
- 自有/外接业务按顺路拼载口径取数;一车多个客户/目的地不重复统计出车次数。外接报价、应收、实收和车辆成本分别记录,自有业务原有收费不重复计收。按行程方案验证各客户单据与库存隔离、每段容量占用、重复预订/取消和统一发车重试。
- 出车记录的用时、托均价、油耗和图表总计使用统一单位和服务端统计口径;筛选条件由服务端参与分页和统计。
- 车队报价导入能展示逐行校验结果、重复组合和失败原因;导入具备幂等或明确的重复处理规则。
- 报价区分未报价与零价;导入按确认策略检验部分成功/整批失败及重试重复行。统计验证筛选范围、仓库数与出车次数、加权托均价、零托数和多币种分组,页面数值和导出一致。
- 司机列表/详情的到期提醒与实际命令阻断一致;审核后变更车辆或司机、临近到期、已过期、缺件、未审核分别验证,不能仅验收提示文案。
- 司机资格补验到期前第 30/31 天、到期当天/次日、计划结束恰好触及有效截止时刻、跨时区/夏令时、缺少预计结束时间及预计结束延后;所用预计结束覆盖司机承担的返程/转场。已在途发生风险只进入告警与处置,不回滚出库事实。
- 运维记录须验证车辆 A 的新增/编辑不影响车辆 B;维修项目/地点、救援项目/地点等已确认字段保存后能正确回显;处理状态和付款状态分别读写,不以共用弹窗导致字段丢失。
- 签收上传与资料保存分别验证:上传未保存不得完成派送;多目的地仅完成当前单,出车汇总按确认规则结案。原型装车完成时间与发车时间混写不得直接作为正式用时口径。
- 保留现有车牌规范化/唯一性、里程不可回退、主档版本冲突规则;新增占用及资格门禁后分别覆盖维修/停用车辆、过期司机、重复派车、审核后改派及取消。尚未确认的新状态不以页面标签代替正式迁移。
- 费用验收覆盖已收费自有业务、外接新增运费、混装/预约附加费、同车多客户及失败重试;每个真实收费来源只入账一次,不以 0 元占位或额外虚构一笔派送费通过校验。行程分摊只是运营分析,不重复发布客户账务费用。
- 预订数量与实收数量变化须重新核量和确认金额;已拣/已发运不能通过简单取消释放为未发生业务。拒收、退回、中途换车应保留关联与证据,分别核对行程结束、车辆释放和费用结清。
### 6.3 工程与人工证据
- 前端运行受影响模块定向测试和类型检查;后端运行车辆/司机/运维/报价相关单元与合同测试;跨服务接口变化补跑 Gateway 路由合同。
- Admin 视觉按 1920×1080、浏览器缩放 100% 检查,至少覆盖列表、详情、弹窗、附件、空态和错误态截图。
- 真实 HTTP、部署、数据库写入和 Jenkins 不在本规划文档中默认执行;需在对应环境获得明确授权后单独验收。
## 7. 当前不纳入本轮的实现承诺
- 不把外部 `新版.html` 复制进正式 Admin 页面,也不把原型内存数据、data URL 附件或 Toast 成功提示当作实现证据。
- 不为兼容旧原型同时保留第二套车辆接口、旧字段别名、双写或独立海外 Gateway。
- 不在未确认 GPS 数据源、路线告警规则和财务归属前实现自动轨迹告警、自动 ETA 或费用结算。
- 不把司机、保养、加油、出车和车队报价数据塞进 `ll_vehicle` 作为临时扩展;每类事实先确定权威归属和生命周期。
- 不通过车辆主档页面推进排车、PDA 拣货、发车、派送完成或码头提柜状态。
## 8. 现状证据入口
- Admin 现有车辆实现:`apps/admin-web/src/modules/overseas-master-data/`。
- Admin 现有原型核对:`apps/admin-web/src/modules/overseas-master-data/PROTOTYPE_MATRIX.md`、`CONTRACT_GAPS.md`。
- Admin 当前导航:`apps/admin-web/src/core/navigation/adminNavigation.ts`。
- Lastleg 车辆 Controller、应用层和持久化:`baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/masterdata/vehicle/`;详情排除说明见 `adapter/in/web/PlatformVehicleController.java:49-53`。
- Lastleg OpenAPI:`baiyue-firstleg/lastleg-service/src/main/resources/openapi/overseas-master-data-v1.yaml`;车辆详情排除说明见 `:158-160`。
- Lastleg 车辆表:`baiyue-firstleg/lastleg-service/src/main/resources/db/lastleg.sql` 中的 `ll_vehicle`。
- 车辆权限:`baiyue-firstleg/iam/src/main/resources/db/lastleg-permissions.sql`。
- 文件能力参考:`baiyue-firstleg/file/`(具体业务类型、大小/MIME 和权限仍需在 VM-00 冻结)。
- 现有排车/派送:`apps/admin-web/src/modules/overseas-warehouse/`、`baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/` 和 `delivery/`。
- 海外仓业务页面 ID 与路由索引:`docs/海外仓业务/README.md`(其中架构入口描述以当前统一 Gateway/Auth 正式契约为准)。
## 9. 本次连续 Review 记录
以下轮次从用户要求连续复核后重新计数,每轮在上一轮修订结果上继续;修复对象为本规划文档,原型和业务代码缺陷仅作为事实记录与候选任务。
| 轮次 | 核对范围 | 发现及文档修复 | 复查证据 |
| --- | --- | --- | --- |
| 第 1 轮 | 原型页面、可达按钮、记录读写 | 更换历史无容器;运维扩展未按车隔离;维修/救援表单与保存字段错配;处理/付款状态混用;隐藏面板不能算可操作功能。已修订第 2 节及对应范围判断 | 原型 `9024-9051`、`23196-23202`、`23240-23277`;精确搜索历史容器仅命中函数引用,扩展记录读写无车辆键 |
| 第 2 轮 | 服务端流程、状态与并发边界 | 补齐车牌规范化/全表唯一、里程不可回退;明确五种主档状态不等于原型三状态;纠正“所有编辑已有版本校验”,记录排车编辑缺期望版本;补转派送后快照变更/取消联动决策。已同步第 3、4、6 节 | `VehicleApplicationService.create/update/changeStatus`、`presentation.ts`、`DispatchRequests.Update`、`DispatchService.update/removeItem/cancel`、`DeliveryTransferService.transferResolved`;逐项核对方法体后记录现状,未声称新增约束已实现 |
| 第 3 轮 | 决策、任务依赖与验收对应 | 拆分 VM-04a 执行扩展和 VM-04b 查询工作台,取消出车统计对整套新审核的无条件依赖;明确 VM-07a/VM-07b 承担 Admin 页面,PDA 门禁变化归 VM-04a;新增逐车运维隔离/字段回显验收;VM-00 按工作包交付决策结果,未决问题不阻断无关部分 | 复查全部 VM 编号引用均有定义,前端与服务端分工可对应;第 1/2 轮发现已落到任务或验收;因仍发现实质依赖问题,扩展为 5 轮 |
| 第 4 轮 | 指标、报价与证据措辞交叉核对 | 修正“今日”标签与实际取数、仓库数与出车次数混用;补托均价、空报价/零报价、导入部分成功口径;将测试文件存在与测试通过明确区分。已补原型差异、决策 22 和验收 | `renderVehicleBusiness`、`renderVehicleTripCharts`、`validateDeliveryFleetQuoteDraft`、`confirmDeliveryFleetQuoteImport`;定向枚举测试源码,仅记录入口不报告运行通过 |
| 第 5 轮 | 全文一致性与交付审计 | 将原型统计说明移回原型章节,修正审查记录中未拆分的旧任务简称;逐项核对前四轮修订、命名页面/弹窗、决策编号、任务引用和证据路径。未发现新的阻断性文档问题 | 第 1 节原型哈希复核;页面/弹窗 ID 与原型定义对应;任务定义、依赖与引用检查;第 8 节证据入口存在;Markdown 表列和章节检查。本次不运行功能测试,不宣称原型缺陷或业务功能已修复 |
## 10. 开发增量与后续接入(2026-10-02)
### 独立任务拆分与交接(2026-10-03,已确认四任务协作)
用户已确认创建三个用户可见独立任务,加当前对话共四个一起处理,目标为车辆全流程跑通。三个专项为①车辆成本与财务闭环;②车辆报价与运营统计;③车辆在途异常与改派;当前对话负责车辆总控、集成部署与跨模块验收。稳定task_id及授权边界唯一维护在[测试环境独立任务协作登记](../独立任务协作登记.md)的“车辆管理四任务协作”段。其他旧任务仍不自动恢复。
| 独立任务 | 唯一实现范围 | 交接边界 |
| --- | --- | --- |
| 车辆成本与财务闭环 | Lastleg `fleet/trip/FleetTripCost*`、`PlatformFleetTripCostController`及直接测试/合同;后续Finance车辆成本领域与Admin独立成本组件/API | 接续当前未提交草稿:成本登记、更正、按币种汇总、DEPART实物依据及同路线托位分摊。源码test-compile及新增持久化/现有分摊政策定向测试通过;尚需API权限/合同门禁、前端、部署及真实HTTP。未执行SQL、部署或真实成本HTTP。维修救援按公司成本还是客户分摊的问题仍待用户答复,不能擅自把车辆自身费用挂给客户。Finance共享账单/结算入口修改须先列明路径交总控协调 |
| 车辆报价与运营统计 | 新的Lastleg `fleet/quote/`、`fleet/reporting/`及各自测试/合同;Admin独立报价/出车运营页面、组件/API | 报价区分外接销售与车队采购;统计基于实际车次、发运及原费用来源,一趟多目的地只计一次出车。成本通过上一任务正式契约读取,不复制成本表或估算成财务实付。不得改写车次执行命令 |
| 车辆在途异常与改派 | Lastleg车次执行/改派/结案、实际调用到的dispatch和资源边界;Admin异常操作组件及海外PDA直接操作页面 | 保留原客户单据、库存、费用和历史;涉及共享FleetTrip模型或PDA入口时先申报精确文件,独占写入后实施;不以发车前换车冒充在途交接完成 |
总控保留共享 `TripDetailView.vue`、路由、导航、权限定义、IAM权限种子、模块/统一SQL和主契约的集成写权限;独立任务提供明确的接入清单,不同时修改这些文件。Maven构建、Jenkins、数据库结构准备及共享真实HTTP/浏览器验收窗口由总控串行安排;工作在当前目录和当前分支,不创建worktree,不提交他人的未完成改动。当前成本草稿涉及的5份SQL/数据库说明文件亦暂由总控持有,不随成本实现自动转交。
成本交接追加:Admin `api/tripCosts.ts`、`components/TripCostPanel.vue`及直接测试已接草稿,`TripDetailView.vue`按页签懒加载,`permissions.ts`增加两项成本写权限;680px登记/更正和1080px历史弹框,编辑先取最新版本,不变内容不写入,未知创建响应保留原幂等键重试。金额与分摊按币种分别显示,未登记/未分摊不补零。模块103项测试通过;未将本地草稿视为已部署或真实页面验收完成。
本节仅记录本功能源码与本地检查,不维护环境部署状态。环境部署、已验证场景和未关闭验收项仍以根指引指定的两份主契约为唯一入口。整体开发目标保持第 5、6 节全范围,以下局部成果不能作为完成依据。
| 工作包 | 当前源码与验证证据 | 尚需完成 |
| --- | --- | --- |
| VM-01 车辆容量与占用约束 | `ll_vehicle` 和既有车辆API、列表/详情/编辑/CSV补齐托位、载重kg、容积m³。三项同填或全空;未知容量不能分配到车次。CSV使用车牌作为业务标识。车辆应用层通过 `VehicleAssignmentGuard` 在车辆行锁内检查占用,车次占用时禁止直接改车牌/车型/区域/归属/容量及状态,备注、电话、合法里程修正保留现有能力 | 实际运维故障、中途换车及车辆释放与签收的联动继续接入;车辆页面真实环境视觉验收待执行 |
| VM-02 司机后端基础 | Lastleg `fleet/driver/` 新增司机与不可变历史表、列表/详情、创建/编辑、启停、审核、打回重提、驾驶证上传/读取、资格预览;写入使用行锁与版本条件,关键身份/证照变化和替换附件重新待审。OpenAPI `fleet-drivers-v1.yaml`;IAM 六项独立权限;模块与统一 SQL 同步。补齐可驾驶车型、语言/服务区域、体检/培训/保险日期;所属仓库引用国内公共有效目录并保存编码/名称快照 | 其他资质是否必需不由原型自动推定;派车命令源码已接入(见 VM-04a),真实环境验收未完成。当前启停与证照审核状态不冒充行程“任务中”状态 |
| 司机文件 | File 新增 `FLEET_DRIVER_LICENSE`,固定平台 0 与司机复合归属,非空 PDF/JPG/PNG、最大 10MiB、MIME/签名验证;Lastleg仅允许当前或历史已关联附件读取;上传不会通过审核。Admin 居中弹框预览图片/PDF,关闭释放Blob并忽略迟到响应 | 文件服务真实 HTTP、权限负向及1920×1080视觉验收未完成 |
| VM-03 / VM-07a 车辆运维 | Lastleg `fleet/maintenance/` 提供保养、加油、维修、故障、救援、异常逐车分页、创建、更正和历史;两表为 `ll_fleet_vehicle_record` / `ll_fleet_vehicle_record_history`,接口 `fleet-vehicle-records-v1.yaml`。Admin按原型接入六类记录,保养/加油680px、其他四类620px居中表单;保养加油图片按原型在新标签页查看 | 维修/故障/救援的更新处理行操作已开放,异常编辑已接入。`VehicleCareModels.Incident.reportedCost`只保存申报金额;`VehicleCareService.response`对维修/救援固定返回`UNLINKED`,构造依赖及Controller没有财务关联命令,不能把记录保存或处理完成解释为已入账/付款。财务关联须补真实费用来源和Finance状态读取;删除/作废语义仍未定。环境证据见正式主契约 |
| 司机 Admin 页面/API | `DriversView.vue`、`DriverDetailView.vue`、编辑与预览弹框已接真实 API,注册导航和路由;统一 HTTP、长整型 ID 字符串、版本透传、multipart、业务错误追踪。列表一次请求包含分页和同筛选统计;后台按各证照时区分组,在只读重复读事务中取数;详情历史按需加载。修改预计结束时间或档案后提示重新校验,不伪造资格结论 | 真实页面请求量、样式/交互、部署验收未完成;客户端与PDA仍随车次/承运流程接入 |
| VM-04a 派车门禁 | 车次分配/改派与PDA整车发车均调用 `DriverService.requireDispatchable`,在事务内锁司机并复核资格与真实证照文件;延长任务时间同样重新校验。PDA返回整车门禁与30天到期提醒,预计结束前过期阻断 | 本地事务测试已覆盖发车资格,真实HTTP未验收;审核时点已按本轮首版确认落地,见调度/理货审核增量 |
| VM-05 车次计划与占用 | `fleet/trip/` 新增幂等创建、分页/详情、改计划、车/司机分配与改派、取消、历史接口;OpenAPI `fleet-trips-v1.yaml`,表 `ll_fleet_trip` / `ll_fleet_resource_assignment` / `ll_fleet_trip_history`。创建可先不分配资源;分配锁车辆和司机,唯一资源键防重复占用,失败回滚,取消释放锁行且保留历史 | 客户排车、整车发车和结案接入见下列增量;外接承运明细、正式页面、异常处置及费用闭环继续实施,创建计划不等于已出车 |
| VM-05 客户排车关联 | 新表 `ll_fleet_trip_dispatch` 以排车单为唯一有效关联;同起运仓可关联多个客户,客户归属取原单。新增带车次版本的关联/解除接口;`FleetDispatchGateway` 由dispatch适配器实现,同事务同步排车与尚未执行派送单的车/司机快照,不覆盖到达时间。关联后子排车禁止独立编辑/移托/取消,转派送禁止另填不同车辆司机;已拣货禁止直接解除或变更路线,发车前允许统一换车/司机或保持路线调整时间,保留全部拣货事实并清除旧装载确认。替换车辆检查已确认载荷,司机重新核验预计任务覆盖,失败整批回滚;取消车次前先解除关联。历史同时保存车次与关联清单 | 关联箱数不冒充实物托位;已拣货后的撤回、在途换车换司机及交接异常仍需补齐,发车前改派不等于完成全部异常处置 |
| VM-05 实际装载与整车发车 | `FleetTripExecutionService` 新增装载依据读取/确认,按实物托盘去重计量并调用分段容量政策;同托不同目的地要求先拆托,卸货站匹配来源目的键,确认记录来源hash、车次版本、实测值、人员和历史。PDA原发车入口提交车次版本,锁车次/资源及全部客户执行单;事务内逐单执行出库后统一变为IN_TRANSIT,失败整批回滚、同键重放整车结果。PDA显示车次、单数、到期提醒,发车后刷新真实状态 | 当前覆盖共同起运仓、已关联客户执行单;外接询价及预订占位已接入,来货/实际发运关联已接入源码;审核和Admin车次及装载页面已接入源码,结案/释放见下一行。H2使用真实排车/出库Mapper与事务,订单归属服务在此集成测试中隔离,实库及真实库存/费用闭环仍须HTTP验证 |
| VM-05 货物结案与资源任务结束 | `FleetTripCompletionService` 读取每票派送的签收或真实退回终态,核对数量覆盖本次实发,并冻结结案依据;退回时间读取RETURN_COMPLETED操作事实,不取可变updatedAt。车次COMPLETED只代表货物结案,车辆/司机继续分别占用;带幂等键、版本和实际结束时间/地点的独立命令释放指定资源,车辆同时确认在役/维修/停用/已归还状态。历史失败回滚资源释放及车辆状态,原请求重放不影响下一车次 | 不自动结清运费,也不重写派送/库存。当前处理正常签收及已完成退回;途中换车、货物部分撤回等异常流程继续补足,真实环境未验收 |
| Admin车次页面/API | `tripTypes.ts`、`api/trips.ts` 接入28个查询/写命令及独立权限;`TripsView.vue`、`TripDetailView.vue` 注册列表/详情路由,1080px `TripPlanDialog` 维护计划;`TripAssignmentPanel`、`TripLoadingPanel` 在详情分区维护资源与实测装载,货物结案、车辆/司机结束任务分别确认。列表一次分页请求,历史/装载/结案检查按需加载;未填写的说明使用标准动作说明 | 已按本轮确认接入首版,车次管理导航由总控集成;调度/理货审核、外接询价和占位已接入详情,外接来货/发运关联已接入,费用覆盖及环境验收仍须完成。真实环境操作与1920×1080视觉验收未完成 |
| VM-05 装载与成本政策 | `fleet/domain/TripCapacityPolicy`提供分段容量;新增未发布`FleetTripCostService`已调用`TripCostAllocationPolicy`,按不可变DEPART的实测标准托位及外接实收归属分摊。支持燃油、司机、通行、停车和其他直接成本,CNY/USD分别汇总;成本及当时整趟分摊保存历史,零金额与未登记区分,未发车/不同卸货站/归属未核平明确不自动分摊。Java持久化、并发幂等、回滚、权限和合同共13项通过,网关5项、初始化11项通过 | 当前是后端草稿,Admin成本工作台、完整发布门禁、结构准备、真实HTTP及页面验证尚未完成。运营登记不等于Finance入账或已付,不据此算完整利润。多路线分摊、成本统计及财务关联仍需完成;维修救援自身费用归属等待用户选择。环境事实继续见正式主契约 |
| VM-07a 车辆详情履约关联 | `VehicleDetailView.vue`已接`VehicleFulfillmentTable.vue`的派送与更换记录;Lastleg `VehicleFulfillmentService`/`VehicleFulfillmentMapper`提供车辆范围的分页查询。计划派送归当前车辆,实际发车后归DEPART快照车辆;换车按相邻ASSIGN快照保留原/新车辆、司机和当时排车成员,不按车牌猜归属。派送关联同时核对客户和排车身份 | 源码接通不代表部署或视觉验收完成;真实环境结论见两份正式主契约。没有车次关联的旧单不补猜历史;操作人姓名未写入现有快照时显示“—”,不把内部ID作为姓名展示。当前只读投影不等于完成在途换车命令 |
结案追加边界:原派送已签收后另发起退货,原运输按已有签收事实结案,不把后续退货改写为已完成,也不让原车辆因未及时点结案而被再次挂起;未签收的拒收/退回仍须实际退回完成证据。派送资料首次保存RECEIPT前新增关联出库单OUTBOUNDED校验,未出库时可以准备BOL/装车资料,但不能提前触发签收完成。已有LocalDateTime执行事实按服务端作业时区转换为车次Instant,避免直接当UTC导致完成时间偏移;车次自身存储继续使用UTC。
当前车次资源采用一个车辆/司机同时占用一个未释放车次的规则;其他未来计划可以先建立而不分配资源,不以预计时间已过自动释放仍未结束的任务。已实现计划、分配、客户排车关联、装载确认、整车发车、货物结案及分别结束资源任务;已装货后的取消、途中换车和其他异常处置仍须补足,不能用计划取消接口代替退仓或签收。
载重数据追加修正:`DispatchCandidateMapper` 不再用计费材积重填补毛重,来源不齐全时分摊毛重为空;该值属于计划分摊,实际装载仍须核验。`DispatchService`、出库托盘与出库/派送合计保留未知毛重,任一来源未知不展示部分重量合计。Admin 预排与排车详情显示待确认/空值,不把材积重或缺失值0当作载重。模块和统一SQL相应重量列已改为可空;尚未执行环境SQL。
司机区域复核修正:正式分配原本只接受海外司机,但分配后可以通过司机档案编辑把区域改为国内,原发车门禁只核验证照与姓名。现已在 PDA 发车预览和事务内正式发车共用区域/身份判断;档案变为国内后整车阻断,出库、车次版本及发车流水不推进,纠正档案后可用原失败请求继续。此规则复用已有海外车次范围,不把自由文本“可驾驶车型”自动解释为正式准驾车型匹配规则;车型匹配标准仍需单独明确。
共享派送服务回归修正:Lastleg 全量首次暴露 `ReturnOutboundPdaPersistenceTest` 四项失败,核对发现已有 PDA 契约要求逐退货箱扫码,但服务仍合并全部箱唛且忽略扫码载荷。现改为每个真实退货箱一条明细,详情返回箱码扫码行且不虚构托盘/仓位;扫码与重放严格核对指定箱码,执行前重新核对客户、仓库、来源退货单,日志写入失败时库存和任务同事务回滚。这是退货库存再次出库的既有链路修复,不等同于车辆拒收后退回入仓流程。
本次已运行的本地检查(按增量保留;同一门禁以最后一次明确结果为准):
- Lastleg 9 个定向测试类累计 45 项通过:三项领域政策、司机服务、文件元数据归属、数据库事务/并发/跨时区统计分页、API/SQL 契约、真实方法权限拦截、公共仓库目录。最近一轮司机相关 7 类 33 项通过;未变化的两项车次政策复用此前结果。
- File 3 个定向测试类共 27 项通过:新增证照格式与归属,以及现有业务文件存储/服务回归。
- 数据库行为测试使用 H2 与当前建表定义;仅将 JSON 列替换为 H2 可读的文本用于本地绑定验证,不等于 MySQL 实库验证。已验证历史失败回滚、清空可选字段、同版本并发只有一次成功。
- Admin 新增 API 6 项、司机交互 9 项通过;覆盖分页/筛选每次单请求、历史按需读取、只读权限、审核版本、上传失败后重试不重复建档、预览释放以及预计时间变化后清除旧资格展示。`pnpm build --logLevel warn`(含类型检查)通过;全量 `pnpm test` 268 个测试文件、2160 项通过。自动测试不替代真实服务或视觉验收。
- 车辆/车次增量:车次持久化9项、API/SQL2项、权限1项,车辆应用5项、SQL1项、Controller权限1项通过。覆盖重复/并发创建、车辆并发抢占、缺容量/缺证照、改派失败保持旧安排、延期跨证照到期、历史失败全事务回滚、取消释放与车辆主档占用门禁。
- 客户排车关联增量:车次持久化扩展为15项,使用真实H2/MyBatis及事务代理验证跨客户关联、同仓限制、并发一单抢占、历史失败回滚、派送快照同步与清空、已开工改派整批回滚。连同API/权限、排车、PDA、转派送、SQL中文注释及OpenAPI回归共106项通过。Gateway与初始化合同14项通过,Mapper扫描313个通过;fleet/车辆定向依赖3项通过,完整依赖检查及AGENTS登记旧断言仍未通过。未执行环境SQL或部署,此结果不能证明MySQL并发或真实HTTP行为。
- 实际装载/整车发车增量:车次持久化扩展为21项,覆盖两客户同托只计一次、重复/缺失测量与超重、目的站不符、装载后来源改变、某票未就绪、第二票失败全事务回滚、发车时证照复核、跨仓/旧版本、并发同键仅一次执行;连同子单PDA、转派送、订单归属及API/权限/SQL定向回归共118项通过。海外PDA全量167项通过;H5与App资源编译通过(不是APK真机验收)。车次验收助手及两个主消费模块、脚本文档合同67项通过;新助手通过正式API创建测试车辆/司机/证照/车次,实测数据明确标为受控测试输入,不用SQL补状态;这些脚本尚未运行真实HTTP。PDA列表门禁按车次复用查询,仍须在真实环境检查请求量与耗时。
- 结案/资源释放与Admin接口增量:车次持久化扩展为27项,连同结案API/权限、车辆状态、派送资料/Controller/合同及SQL中文注释回归共58项通过;覆盖货物结案不释放资源、任务分别结束、维修状态与释放一起回滚、司机过期仍能结束旧任务、旧重放不释放新占用、退回须有真实终态操作证据、签收后新退货不重开原运输、未出库拒绝签收但允许准备BOL。Admin车次API新增6项通过;全量271文件2172项通过,类型检查及构建通过。Gateway与初始化基线14项、fleet/车辆依赖3项、313个Mapper扫描通过;全局门禁未关闭项仍按下文保留。本轮未运行共享环境SQL、部署或真实HTTP。
- 载重修正补跑候选SQL、预排/排车服务、转派送、出库/派送SQL及前端实际重量/排车详情检查;SQL计算回归覆盖完全未知、部分未知及完整毛重来源。当前前端全量 `pnpm test --maxWorkers 4` 为269文件、2163项通过;先前默认并发全量出现财务页面单例5秒超时,该单例独立复验通过,随后以4个worker全量通过,未修改超时阈值或财务代码。
- Gateway 路由合同 5 项、Mapper 扫描合同、统一 SQL 初始化基线 9 项及 fleet 切片定向依赖检查通过。司机 API 复用统一 Gateway 的现有 Lastleg 路由,无新增网关配置。
- 完整 Lastleg 依赖检查已修复并通过 10 项:退役 `LastlegSecurity*` 投影改为禁止恢复或引用;25 条现有跨域类引用逐条记录理由,不授权同切片其他消费者。`DeliveryDocumentSnapshot` 移到应用服务包,消除 DTO/model 包循环;新增依赖、通配放行、车辆应用层反向引用和新增包循环均有失败测试。钱包 Outbox 的粗粒度切片聚合环仍作为耦合报告保留,不声称切片全图无环;边界说明见 Lastleg 内部模块化基线。快照工具移动后的派送服务、资料、Controller 与长 ID 回归 66 项通过。
- 车次 HTTP 验收脚本补齐结案和独立资源释放:通过正式分配命令验证结案仍占用、单独结束车辆不释放司机、资源再分配后重放旧结束命令不清除新占用。无货核对计划最终正式取消并保留历史;失败保留原请求和资源,不自动重造。两处测试车辆创建已补必填 `status=IN_SERVICE`,避免仅凭宽松模拟响应误报可运行。助手及两个直接消费模块 70 项、Gateway 5 项通过,脚本文档 4 项与三个脚本语法检查通过;仍未执行真实 HTTP。
- 车次 HTTP 验收助手追加发车前改派:仅对 `prepareFleetTrip` 本轮创建的车次执行,首次确认装载后新建等容量车辆和合格替班司机,正式改派并回查货物/客户关联、拣货数量、路线及到达时间保持一致,旧装载失效、旧版本请求拒绝且无写入,再确认新装载并返回最终发车版本。原请求、前后快照和替换资源保存在报告 `reassignment` 中;未知结果保留 `CHECKING`,不自动重试。字符串版本按整数比较,覆盖 9→10 边界。留存车次仅按原入口确认装载,不补造或改派其资源。助手 18 项、两个直接消费者及脚本文档合计 85 项离线通过;这不是已执行的真实 HTTP 或页面验收。
- 脚本文档合同 4 项通过;本次指引更新后的 AGENTS 索引合同失败,5 项均涉及测试独立任务登记必须为空的旧断言。本功能未修改或清空任务登记,也未据此自动派工;该全局检查仍未通过,不计作司机索引已完成整体验收。
- 发车前改派完整回归:`mvn -pl lastleg-service -am test -q` 成功,Lastleg 报告 1081 项,1079 项通过、2 项跳过、0 失败/错误;跳过的是 `CargoDiscardMysqlAcceptanceTest` 和 `TaillegRealConsumerAcceptanceTest`,不能计作真实环境验证。车次事务测试现为 33 项,新增发车前已拣货改派、同路线延期、容量不足/证照覆盖不足拒绝、历史失败回滚,以及改派与发车并发只能一个成功;验证拣货、到达时间、客户归属保留,旧装载确认失效并可重新确认后发车。Lastleg 依赖 10 项、Gateway 路由 5 项通过;AGENTS 索引仍有前述 5 项登记旧断言失败。本轮未改海外 PDA,不将先前其 21 项定向结果描述为本轮回归;未部署车辆功能,未执行测试环境 SQL、真实 HTTP 或浏览器验收。
- Admin 编辑会话修复:司机与车辆运维编辑器按打开状态和业务对象隔离请求;切换司机/车辆、关闭或卸载后,旧保存/上传结果不得覆盖新表单、触发成功提示或继续上传后续附件。运维不确定创建结果的幂等请求仅供原车辆/原记录范围重试,不带入另一车辆。已发出的保存命令仍以服务端结果为准,不自动回滚档案。两组复现与回归共 22 项通过,Admin 全量 273 文件、2189 项通过,类型检查及构建通过。车辆详情说明改为业务可读提示;本轮无布局或新增操作入口变更,也未进行真实页面验收。
- 转派送重放修复:三条变更金额的重放路径先复现失败,再修正为摘要校验;另验证只换请求键且内容完全相同不重复创建或发布费用。复用现有请求摘要列,无新增表/列;模块和统一 SQL 仅同步该列的用途注释,未执行环境 DDL。完整 Lastleg 回归更新为 1090 项:1088 通过、2 项环境测试跳过、0 失败/错误;转派送服务 48 项、车次事务 33 项均通过,Gateway/依赖 15 项、初始化合同 10 项通过。该次回归包含当前共享工作区的退货记账增量,退货发布事实仍由正式环境契约维护;不将其算作车辆功能已发布。
- 首版车次页面接入:模块/密度定向88项通过,新增四项关键页面流程验证分页不逐行请求、只读详情与按需历史、创建不确定结果复用原请求、实物托盘去重及人工测量提交;类型检查与构建通过。首轮Admin全量274文件2193项中2192通过、1项输入提示合同失败,补齐6处提示后该合同与新流程合计5项复验通过;未将此描述为又跑了一次全量全绿。共享导航由总控集成并单独验证14项。AGENTS索引仍有5项旧任务登记断言失败;本轮无环境部署、SQL或真实HTTP/视觉验收。
接续顺序:Admin车次/装载操作入口与自有/外接委托预订 → 审核、逐站签收/异常及资源释放 → 运维/报价/统计与费用闭环 → 按授权部署测试环境、真实 HTTP、指定视口样式/交互及请求量验收。第 4.4 节按本轮首版确认执行;审核源码增量见第10.3节;外接接单和费用覆盖仍须继续实现。当前尚无部署或真实HTTP/浏览器验收完成证据,不以本地测试代替这些交付项。
### 10.1 保养及加油接入的实施边界
本增量沿原型已经定义的车辆详情页签及居中弹框推进 VM-03、VM-07a,未代替仍待答复的车次工作台承载选择。
- 记录固定绑定车辆内部主键,使用独立 `VR-` 业务编号并保留建档时车牌快照;更换其他车辆路径不能读取、修改或下载原车附件。创建按车辆、操作人和请求键去重,更正保留版本、原因及完整历史。
- 里程明确选择公里或英里;加油量明确选择升、美制加仑或英制加仑,不把原型含义不明的 `gal` 自动按某种加仑入库。上次、记录时、下次保养里程使用同一明确单位;下次里程须大于上次,但可低于记录时里程,以保留已经超过计划保养里程的真实情况。不默认套用每一万迈阈值。
- 发生时间使用带偏移的实际时间,保存为 UTC,不得填写未来记录;历史记录里程可以低于当前车辆主档里程。运维保存不更新主档公里码、车辆可派状态或财务,核验状态仅记录“待核验/已核验”。维修、救援处理与付款状态仍按原未决项单独设计。
- 照片类型 `FLEET_VEHICLE_RECORD_PHOTO` 固定平台与记录归属,仅非空 JPG/PNG、每张最大10MiB,每条最多20张。先保存记录再逐张上传;已上传结果保留,失败重试沿用原图片请求键。File校验文件签名,Lastleg核对复合归属,图片内容接口的HTTP200 JSON错误不能作为图片返回。
- 页面进入“保养及加油”页签才分别请求两类分页;不逐行预读详情或图片。编辑时读取该记录最新版本,保存使用命令返回值更新当前行;创建后刷新当前类型列表。上传失败不重复创建记录,明确的参数错误允许改正,未知创建结果保留原请求内容和键供重试。图片按原型在新标签页查看,关闭或页面卸载释放临时地址。
- 只读沿用 `vehicle:list`;新建、更正、上传分别为 `vehicle:record-create/record-edit/record-upload`。无新增菜单、Gateway配置或独立服务。部署涉及 Admin、Lastleg、File,以及 IAM三项权限和Lastleg两表的最新初始化定义;本轮没有执行这些环境操作。
- HTTP编排已接入 `phase4-overseas-master-data.mjs` 的内部 `vehicle-care.mjs` 助手:验证创建重放、版本冲突、不可变历史、单位、照片重放及字节一致,另建本轮车辆验证跨车拒绝并在结束时停用;保留原记录、照片与失败证据,不执行SQL或修复历史造数。离线合同包含故意跨车泄露时必须阻断的反向场景;真实HTTP尚未运行。
本增量验证:Lastleg完整回归1073项(1071通过、2项环境测试跳过),File完整216项通过;新增运维持久化/权限/接口/文件归属10项及File图片策略1项包含在其中。Admin全量273文件、2181项通过,含类型检查的生产构建通过。IAM权限目录补齐原遗漏的司机6项和新增运维3项常量,目录规模68项;IAM相关12项与Lastleg权限/API补验4项通过,不改变既有仓库角色授权。Gateway、初始化、依赖24项及315个Mapper注册检查通过;运维HTTP编排离线7项、脚本文档4项通过。初始化源当前为国内223表、海外143表、385项权限及566条角色授权,未向环境执行。AGENTS索引检查仍有同一组5项任务登记旧断言失败,未修改或清空登记表。
当前交付仍缺维修/故障/救援后续处理入口确认、车次页面及未决外接/审核范围、报价/运营统计/费用闭环,以及实际部署、真实HTTP、指定视口视觉交互与请求量验收;不能以运维局部接入或自动检查通过宣布车辆管理整体完成。
### 10.2 维修、故障、救援及异常增量
2026-10-03 编辑规则补充:服务端采用 NON_NULL 响应,空的里程单位、核验状态及事件选填字段可不返回;Admin `api/vehicleCare.ts` 将这些字段统一初始化为空值,再进入编辑表单,避免将保养默认值提交到维修/救援记录。打开已保存记录后没有修改内容时,保存不产生更正命令或新版本;脏数据比较以同一个表单快照序列化,不受响应字段排列顺序影响。真实环境结论继续只维护在正式部署契约。
运维独立回归已接入 Admin 正式验收入口的可选模块 `fleet-vehicle-care`,复用六类运维助手并创建本轮车辆。覆盖历史、照片、版本、跨车隔离,以及正金额/零金额与付款事实分离;失败保留记录和原始证据,结束停用专用车辆。该回归不表示公司车辆成本已经接入 Finance。
本次继续使用同一记录、权限和历史合同,扩展 `REPAIR/BREAKDOWN/RESCUE/EXCEPTION` 四类,不新建第二套车辆或费用台账。
- 维修及救援项目、地点分别保存;原型弹框读写错配已由明确字段替代。故障/异常保存描述、处理人和处理状态;异常另有轨迹、超时、派送、车辆故障四类分类。保养加油字段与这四类事件字段互斥,不能在共享表单内悄悄串写。
- 处理状态为待处理、处理中、已完成;处理中或已完成须填写实际处理人,系统操作人另行留痕。更正仍须版本和原因,保留此前字段和金额快照。事件处理不自动改变车辆主档状态、解除车次占用或完成货物履约;这些联动尚不能被宣称已经具备。
- 维修/救援费用是本条运维申报金额,允许未登记或明确零值;登记金额须有有效币种,运维保存本身不进行汇率换算或自动入财务。当前服务端对维修/救援返回只读 `paymentStatus=UNLINKED`,页面显示“未关联财务”;处理完成不能生成已付款事实。公司车辆成本及入账规则已按文首2026-10-03追加确认实施,正式Finance关联与状态读取尚待接入。
- 页面按原型新增四个详情页签,只加载当前车辆当前页签;四类新增及异常编辑均用原620px居中弹框。原型没有维修/故障/救援后续行操作,已发出“列表更新处理、复用居中弹框”或“仅登记结果”的选择,等待答复期间不添加新行操作。未给四类事件新增原型未定义的照片预览或删除入口。
- HTTP验收助手已覆盖四类新增、处理完成、重新读取项目/地点/处理人、分类型列表;补充“处理完成被错误映射为已付款必须失败”的反向测试。该助手只通过正式接口处理本轮测试资源,不把离线模拟结果写成真实HTTP已验收。
本次验证结果:Lastleg全量1076项,1074通过、2项环境测试跳过、0失败/错误;运维持久化扩展为9项。Admin全量273文件2185项通过,类型检查与生产构建通过;新增前端回归验证项目/地点独立提交、异常编辑不提前修改原行、零费用与付款状态分别展示、未确认行操作不开放。IAM相关12项通过;Gateway/初始化/HTTP编排22项及依赖/脚本文档14项通过。无新增表、权限码或Gateway配置,初始化表数和角色授权数不变;更新了六类枚举和权限显示名称。AGENTS索引仍为同组5项任务登记旧断言失败;本次未部署、未执行环境SQL或真实HTTP,也未完成浏览器视觉和请求量验收。
### 10.3 首版调度与理货审核
排车列表以服务端分页参数 `stage` 展示全部、装车前、装车中、装车后及已取消:装车前对应 `PENDING_DEPARTURE`,装车中对应 `PICKING/READY_TO_DEPART/PARTIAL_READY_TO_DEPART`(含拣货完成待发车),装车后对应 `DEPARTED/PARTIAL_DEPARTED`。阶段与具体状态筛选取交集,不按当前页数据做本地分组。阶段不表示审核通过或实际装载确认。
二级页签为“车辆信息/调度审核/理货员审核”,位于执行阶段与查询区之间。二级页签切换当前阶段下的信息和操作视图,保留筛选、分页及服务端总数,不对当前页记录做审核状态过滤;审核视图集中展示对应审核状态、打回原因、时间和进入审核的操作。三种视图独立保存列设置。
平台列表同一响应批量返回关联车次、每单调度审核及整车理货审核的状态、打回原因和审核时间;未关联显示“未关联车次”,不伪造待审或已通过。具有车次列表权限可从列表进入车次“分配与货物”或“实际装载”,审核仍沿车次独立写权限及版本门禁。列表只读信息沿排车列表权限,前端不逐行查询车次。
按本轮确认实现两级简化审核:每张客户排车单独立调度审核,通过后才能产生新的PDA拣货或完成命令;整车实物装载确认后,再做理货审核,通过后才能整车发车。操作只有通过和打回,通过意见选填,打回原因必填;不增加审核清单、提交队列或不同审核人限制。
- 车次详情的客户排车行展示审核状态、原因和时间,支持详情跳转、通过、打回;实际装载分区提供整车理货审核。两个写权限为`platform:fleet:trip:dispatch-review`和`platform:fleet:trip:loading-review`,只读沿用车次列表权限。
- 调度审核保存于`ll_fleet_trip_dispatch.review_json`,理货审核保存于`ll_fleet_trip.loading_review_json`,为空表示待审;历史保存各次审核快照。新增两列,无新增表。
- 换车、换司机或改路线/时间后相关调度审核、理货审核和装载确认重新待处理,保留全部已发生的拣货事实;仅修改备注不触发重审。重新确认实载、关联变更或重新审核调度单后理货审核待审。客户A审核通过不能替代客户B。
- PDA展示当前单`canPick/pickBlockReason`,发车继续由服务端整车门禁决定。已经成功的同键拣货重放返回原结果,不因后续重审而重复扣库存。未知网络结果不得生成新的物理作业事实。
- HTTP验收助手已接准备阶段调度审核、发车前改派后的重新审核以及最终理货审核;发车使用最终审核返回的新版本。留存场景也须已有合法调度审核,不绕过门禁补写旧单。
统一初始化SQL已同步两列,海外保持144表;IAM模块及头程统一基线已同步5107247/5107248两个按钮权限,并授权平台管理员。当前本地Admin定向94项、类型检查及生产构建通过,新增两条API路径的6项补验通过;海外PDA定向15项及H5构建通过;Gateway/依赖/HTTP助手/脚本文档37项通过。Lastleg全量1093项首次为1089通过、2项环境测试跳过,2项新增字段/权限合同失败在统一SQL同步后已定向补验通过;补验含Fleet API/权限3项及IAM权限4项。初始化合同10项通过,精确计数为387权限、568角色授权。没有重复运行已经通过且输入未变化的行为测试。AGENTS索引仍有原5项任务登记清空旧断言失败,未擅自清空已授权登记。没有将这些本地结果视为部署或实际页面验收完成。
### 10.4 外接运力前置与收货链核对
外接货送到我方起运仓,继续使用既有仓储转运的真实收货链;`WarehouseTransferService.createAndSubmit`在未引用旧入仓时建立本次新来货来源,PDA测量/托盘绑定/完成写入真实库存,客户确认后形成可排车来源。当前本土卡车`receivePallets`仅更新其订单托盘业务记录,不能拿该状态当作库存实收完成。外接登记与该链的正式关联仍须实现,不能仅凭此复用判断宣称外接履约已接通。
本轮增加车次“计划容量”页签和`/capacity-plan`读写:在自有货尚未拣货时,按真实托盘输入预计托位、重量、体积及卸货站,服务端按每段核算剩余容量。共享实托只计一次;缺失来源、超容量、旧版本或货物hash变化拒绝提交。计划容量与实际装载的卸货站只允许选择与托盘货物 `destinationKey` 一致的已匹配站点,不以显示名称判定同一目的地。未匹配时明确提示到“分配与货物”执行“按货物匹配卸货站”;同一托盘含不同目的地标识时提示先拆托,保存的旧卸货站索引失配时不继续沿用。保存计划不会生成实载、通过审核、扣库存或发车;发车前继续单独核对实测装载。改车、改司机、计划或关联变化使计划容量待重核,纯备注保留;历史保存当时计划依据。
新增`ll_fleet_trip.planned_load_json`一列,没有新增表、权限或服务。已有trip:list/edit分别承担查询及保存权限。GET的`planValid`只表示当前货物来源与已核对计划一致;无计划或来源变化时不展示过时余位。外接预订尚未占用该余位,后续须在同一车次锁内结合已确认预订计算,不允许把这个单独查询当作已实现防重复出售。
后续接入的直接入口已核对:IAM `/internal/iam/finance-customers`支持按客户ID精确读取有效客户,`/internal/iam/tenants/{tenantId}/order-eligibility`提供下单资格;不以采购历史去重列表代替客户主档。平台代外接客户登记和确认收货仍须建立明确命令及权限,不能要求无工作台账号的委托方假登录操作。费用覆盖和新增项目收费继续按第4.3节完成,不伪造零金额费用绕过现有转派送条件。
本地验证:Admin定向96项、类型检查和生产构建通过;Gateway与Lastleg依赖合同15项通过。Lastleg全量1095项首次为1092通过、2项环境测试跳过、1项统一SQL字段同步合同失败;总控同步统一海外列后Fleet API/Schema两项定向补验通过,初始化合同10项通过,海外保持144表、权限与角色授权数量不变。计划容量行为2项已通过,包括拣货前计划、实托去重、资源变化失效、旧来源拒绝及不覆盖实际装载。AGENTS索引仍为此前5项任务登记清空旧断言失败,未清空登记或放宽断言。真实部署、HTTP及页面验收仍须后续执行。
### 10.5 外接登记与承运占位(2026-10-03)
已增加车次内外接询价列表、登记/编辑、只读详情、确认承运与取消入口,后台使用1080px居中表单。登记先填有效客户、既有路线卸货站及箱数;预计托位/重量/体积、价格和联系说明可以后补。首版自送到车次起运仓,联系人不要求特定电话格式。按标准托位或整单记录报价,约定运费仅为商业约定,不自动生成应收、实收或费用入账。
- `ll_fleet_external_booking`保存稳定FB业务号、客户编号/名称快照、货物与报价、版本及请求摘要。DRAFT询价不占位;CONFIRMED在父车次行锁内确认承运并占位;CANCELLED释放尚未执行的预订。历史直接进入既有车次历史的`externalBookings`快照,没有另外建重复台账。
- 客户候选及精确建档校验读取IAM当前有效客户主档,正式登记与确认承运核对客户下单资格;失败时不创建假客户,也不以采购历史去重列表替代。新增只读Feign使用内部服务身份,不发送浏览器Token。
- 确认承运核对仍有效的自有货容量计划、全部已确认外接预订及本次申请,每段托位/重量/容积任一超限拒绝。计划容量响应`availableSegments`扣除已确认外接占位;询价与取消不占位。自有货重新测算也不能挤占已确认外接容量,换小车须能容纳两者;同车换司机不要求为此额外先重填容量。
- 创建、确认、取消按原请求键和内容重放,不重复占位/释放;更新同时核对车次和预订版本。界面保留未知结果的原请求,刷新查到确认/取消事实后解除待重试状态;只读用户可看详情,不能执行写操作。
- 新增四项写权限为`platform:fleet:trip:booking-create/edit/confirm/cancel`,IAM资源使用总控核对后的5107260..63(5107250..52已被车辆运维占用),父5107240。模块与统一海外基线当前145表,权限391项、角色关联572条,未向环境执行。
本批仍未实现外接来货单创建/关联、实测差异重新确认、外接货与客户排车关系和费用覆盖入账。已确认但未关联实际发运的预订会明确阻止整车发车;不能用“确认承运”冒充已收货或已发运。后续须补齐这条连接后才能作为完整外接版本部署验收。
本地检查:Lastleg全量1099项(1097通过、2项环境测试跳过);新增外接占位行为含登记重放、确认后扣减/取消恢复、超卖拒绝、自有货增量不得侵占预订和历史快照。客户目录两项验证精确客户与资格、依赖失败关闭。Admin定向原99项中只读测试因将说明文字误当按钮失败,已改为核对真实按钮并补充详情/编辑,四项面板测试通过;最新类型检查及生产构建通过;同车只换司机无需额外容量重填的收尾变更经FleetTripPersistence39项补验通过。Gateway/切片依赖通过;同步依赖已精确登记新IAM只读边及此前遗漏的运维文件HTTP调用,10项合同通过;316个Mapper扫描通过。真实环境、页面视口及请求量验收尚未执行。
### 10.6 外接真实来货、实收确认与排车关联(2026-10-03)
本轮把预订连接到已有仓储转运/PDA真实收货流程,未另建库存账:
1. 已确认承运的预订由运营生成来货单,固定预订客户、起运仓、箱数及既有卸货站;首版客户自送。该操作创建并提交、审核原来货流程,只形成待PDA收货,不写实收库存;私人地址必须与原约定卸货键一致。
2. 仓库通过现有PDA转运测量、托盘绑定及完成流程写入实际库存。车次后台按需查询实托、箱数、重量、体积及receiptHash;尚未完成测量不能确认实收。
3. 运营明确核对实托占用托位和约定单价;实际数量变化会重新计算约定金额,同时按实际载荷替换原预留并重验余位。原来货确认成功且实测摘要未变后,预订才进入RECEIVED;库存不会重复写入。失败保留原报价/预留,不能先将未完成确认标成成功。
4. 来货库存经现有预排生成客户排车单,再在车次外接行关联。服务端核对客户、同一起运仓、来货来源、实托、整批实收数量及目的地。通用车次绑定入口也执行该检查,不能将已承诺货物挂到另一车次;同一排车可携带多票合法来源,每票分别核对。
5. 关联成功后预订进入BOUND,预订容量转由实际关联货物计量;容量计划/实际装载和理货审核重新待核对。后台刷新车次成员及审核状态。后续仍逐客户调度审核、PDA拣货、实际装载及整车理货审核后发车。解除未开工排车关联回到RECEIVED并恢复预留;已拣货沿既有正式撤回边界处理。
取消未执行预订仅释放承运位置,已生成来货单和已入库货物保留,不据此删除库存。预订保存来货号、排车号、实测证据及各命令请求键/摘要;原请求重放返回当前事实,不重复创建来货或关联。四个新增读写接口继续使用现有booking-edit/booking-confirm与trip:list,绑定还需trip:edit。总控已同步原预订表新增字段/索引及RECEIVED/BOUND状态,仍145表、391权限和572角色关联,未执行环境SQL。
实现入口为`FleetBookingIncomingGateway`、`transfer/fleet/FleetIncomingAdapter`和`FleetBookingService`;按精确端口引用接入,没有放宽转运切片对车队实现的依赖。沿实际收货路径移除了把内部客户ID拼成展示名称的回退,未知名称显示“—”。前端承载为`TripBookingFulfillmentDialog`,普通交货说明选填,来货和实收详情只在打开时读取。
验证:Lastleg全量1102项(1100通过、2项环境测试跳过、0失败),后续实收确认必须返回可排车状态的收尾约束已通过42项定向补验;Admin模块及密度103项通过,外接关联后刷新成员/审核的交互补验通过,类型检查及构建通过。Gateway/精确依赖15项、初始化10项通过。仍缺原运费覆盖/新增费用正式接入、其余运营闭环和真实环境全链验收,不能以预订与收货连接宣告完整车辆模块已交付。
### 10.7 外接实收报价接入派送费用(2026-10-03)
外接运费已从报价展示接到正式费用发布:排车转派送打开时读取一次`GET /dispatches/{dispatchNo}/external-freight`,复用dispatch:list只读权限;服务端核对每票真实来货、所属客户、绑定车次、目的地及完整实托箱数,返回报价版本、计价量、原币金额与货物/报价摘要。查询不会创建费用。提交沿原transfer-delivery写权限,并携带externalFreightHash;实收、报价版本或来源改变时重新核对。
- 转派送在现有事务内,按每票外接实际卸货目的地关联对应派送单,发布`OVERSEAS_DELIVERY_FEE`应收及现有费用Outbox,由Finance消费形成账务事实。约定金额、计价量、单价、实际入仓码和预订业务号随费用与操作记录保留。当前仅证明本地调用接通,未证明真实Finance已接收。
- 全部货物为已确认外接时不再要求手工填派送费,且服务端禁止重复派送应收;混合排车只要求其余货物的派送费,手工派送费归其余货物对应派送单。装车和购买预约仍单独登记。原头程运费是否已覆盖这些服务,尚未接入,不能据此宣布全部不重复收费需求完成。
- 明确约定零运费保留预订版本与派送操作事实,不伪造零金额财务费用。为与当前正式费用和汇率能力一致,确认承运仅支持CNY/USD;询价可先保存,非支持币种在承运确认时提示调整。USD正式发布仍须业务月份有效汇率。
- 既有出库唯一约束及请求摘要保证原请求重放只返回原派送单,换操作人重试也不再发布外接费用。外接预订必须先完成真实车次关联,不能从普通转派送绕过实收/承运确认。取消出库后的费用作废/更正及再次安排仍须继续接通,不将取消物流单据视为账务自动撤销。
本地验证:后端5类107项通过,覆盖报价/来源核对、分目的地费用归属、零约定、陈旧摘要/重复派送应收拒绝和换操作人重试;Admin排车交互/API/原型合同45项通过,类型检查与生产构建通过。Gateway 5项、Lastleg精确依赖10项通过,未放宽依赖基线;AGENTS索引仍有原5项登记清空旧断言失败。无新增表、权限码、Gateway配置或Finance事件结构,未执行SQL、部署、真实HTTP或视觉验收。后续优先完成每票原费用来源及服务覆盖、取消账务处理,再继续其他运营闭环与环境验收。
### 10.8 出库取消与费用撤销确认(2026-10-03)
首版取消顺序明确为:未拣货时先解除车次关联,再取消出库;仍需在原排车列表取消排车以释放该排车占用。取消不代替实物退仓或已执行货物撤回。后端按dispatch→outbound顺序锁定,并核对排车本身未拣货/发车,避免出库快照仍为待出库时误取消正在执行的货物。来源订单从本次转派送历史恢复真实原状态,显式清空已取消的出库/派送关联并递增版本,不统一写成RECEIVED;取消原因完整留在派送操作记录。
费用处理沿用现有Lastleg费用来源与可靠Outbox:
- 取消仅对本派送当前已审核有效的DELIVERY_FEE应收申请作废;装车、买约、供应商成本及其他待核对费用保留。物流取消成功不代表账务已作废。
- 作废请求先保持原来源ACTIVE,返回PENDING_FINANCE;只有Finance对同一事件ID与载荷摘要返回APPLIED/DUPLICATE,才在投递审计、Outbox完成、来源VOIDED同一事务内落账。拒绝、未知结果或确认落账失败都不能假作废;拒绝/耗尽显示FINANCE_ATTENTION,已确认显示CONFIRMED。
- VOID投递等待原版本发布成功,未满足前置的撤销在队列LIMIT之前排除,避免前50条未就绪撤销堵住后续正常费用。过期PROCESSING继续沿既有租约恢复。费用调整在来源行锁后按READ_COMMITTED核对未决撤销,不能用旧快照漏过撤销申请。
- 重新安排发运按客户及实际入仓码核对原派送应收最新版本;原费用未确认作废时不能再次发布。即使原预订已取消,仍保留其真实来货/实收的财务来源关联。新发运以预订和新排车共同形成费用请求键,原出库重放依旧只返回原结果,不重复收费。
- 派送详情和直接复用该费用接口的货柜费用面板区分待财务确认、待财务处理与已作废;待确认/待处理不开放调整或重复作废。查询批量读取确认状态,不逐行发HTTP请求;财务结算、已出账拒绝和后续人工处理仍以Finance事实为准。
本批没有新增数据库列/表、权限或事件协议;复用现有V1完整快照、严格匹配ACK与原投递审计,不表示海外费用阶段0全部完成。共享初始化基线由总控新增废弃审核权限后为海外145表、392权限、573角色关联,本批未改共享SQL。自有货原运费服务覆盖、其余车辆运营能力与真实环境全链验收仍未完成。
本地验证:最终7类69项通过,其中6项Spring/MyBatis/H2测试验证费用确认与投递审计原子提交/失败回滚、陈旧确认拒绝、原发布等待、队列不饥饿以及原费用最新版本去重;之前费用/派送10类76项已通过。契约严格解析发现智能排车候选的两处重复重量字段,已移除重复定义并通过2项合同补验。Admin派送/出库与货柜费用32项通过,类型检查及生产构建通过;Gateway/依赖15项通过。AGENTS索引原5项登记清空旧断言仍未关闭,未清空登记。没有部署、环境SQL、真实Finance撤销HTTP、指定视口视觉或请求量完成证据。
### 10.9 原运费按本次实际货物确认服务覆盖(2026-10-03)
当前部署及真实环境验收结论统一查阅[测试环境单机部署与配置契约](../测试环境单机部署与配置契约.md)和[统一认证与服务通信契约](../统一认证与服务通信契约.md),本节保留实现说明与当批本地验证边界。车辆专项编排入口为 `baiyue-firstleg/scripts/fleet-test-env-acceptance.mjs`,按真实自有货与外接来货执行费用覆盖、容量预留、PDA实收、并车、约定运费、逐单拣货、整车发车、逐目的地签收及资源分别释放。库存来源核对采用余额明细、实物位置及不可变流水;实收使用 `receivedPackages`;命令重放对比持久化后的业务记录。失败保留原命令和原样本,只允许显式核对的阶段继续,终态对账仅作只读请求;Finance消费入池与生产者ACK分别取证。具体命令与边界见该仓库 `scripts/admin-test-env-modules/README.md`。
已接通读取、运营确认、转派送校验、快照保存与详情展示。此节更新第4.3节初始差距,不把历史“尚未实现”记录作为当前实现状态。
1. 打开转派送时,并行读取一次外接约定运费和一次原费用覆盖预览,不逐行发请求。`DispatchFeeCargoMapper`按实物库存组成及本次已拣数量逐票还原,同仓/客户/排车隔离,并按计划托盘限制其真实来源;核平每条排车箱数后,使用真实尾程订单冻结的头程入仓ID,避免把合托展示的MIN入仓码当成整托来源。
2. `FinanceFeeCoverageClient`批量调用Finance内部只读`delivery-fee-coverage/sources`,仅返回该客户、这些原入仓单的FIRSTLEG已审核有效应收最新版本;作废/替代/其他客户/应付不能作为覆盖依据。AVAILABLE和SETTLED均可作为原费用事实,不把AVAILABLE显示为已付款;来源柜号不能伪装成入仓码。无匹配来源为空,调用失败或范围不一致明确报错,不能伪造已包含。
3. 平台运营在原1120px转派送弹框内,针对各票原费用明确勾选本次已含派送、装车或买约;不按费用名称、总金额或同客户其他费用自动推断。提交原费用ID、版本、hash及当前货物/目的地摘要后重新读取并核对。只有全部相关货物都已覆盖的服务才免新增应收;只覆盖其中一票时,仍须填写其余货物/服务的新费用。外接货仍按已确认实收报价生成对应运费,不能借“引用原费用”抹掉外接价格。
4. 原费用不复制入账、不做金额抵扣、不伪造零金额费用,也不直接把原全程运费总额算成本车收入。新增应收只对应未覆盖范围;多来源时不把MIN订单或已覆盖票冒充唯一收费来源。客户应收与供应商应付独立,同项目收付使用不同费用请求键;服务已含只免相应新增应收,不消除真实供应商成本。
5. `ll_outbound_order.fee_coverage_json`保存确认时实际货物、原费用版本与明确服务、操作人和时间;详情只展示当前派送所属货物的引用。原费用后续财务更正不自动改写旧发运确认,也不自动追加收费;业务更正按取消未执行单据后重新确认等正式流程处理。原成功命令重放保持原快照;无引用的null/空数组具有相同业务摘要,客户接口不能自行声明原费用覆盖。
模块和统一海外初始化已同步这一可空JSON列,没有新增表、权限或费用事件协议;普通无引用发运该列为空。发布单元包含Finance、Lastleg与Admin;Gateway沿已有路由,内部Finance入口不公开。当前服务图新增的是Lastleg→Finance只读请求边,接口实际只到Finance本库;已用单独合同约束该查询无下游调用、无账务写入。静态服务级最长链上界因此变为6跳,仍如实记录既有超两跳风险,不把服务级组合图冒充本接口实际链长。
本批只证明费用覆盖源码及本地行为,仍须真实Finance/Lastleg部署与来源引用、旧版本冲突、全覆盖/部分覆盖、取消重排和页面请求量验收。车辆运维财务关联、运营统计/报价及在途异常等未完成工作继续按原工作包推进,不据此缩小车辆管理整体目标。
本地验证:Finance与Lastleg聚合回归构建成功,Finance 223项全部通过;Lastleg 1142项中1140通过、2项环境测试跳过,0失败/错误。Admin费用覆盖相关4文件31项通过,类型检查及生产构建通过;最后的加载提示调整另经类型检查通过。Gateway、切片和同步依赖合同合计26项、初始化合同10项通过,Mapper扫描317项通过。AGENTS索引当前1094项全部通过,前述历史批次记录的5项旧断言失败已不再是当前阻塞。验证日志位于Lastleg的target/fleet-coverage-*本地输出,本批未据此宣称测试环境部署、真实HTTP、页面视觉或请求量验收完成。
### 10.10 报价、运营统计、在途交接与公司车辆成本集成(2026-10-03)
报价库按采购/销售区分供应商与客户,提供版本历史、启停、删除和整批原子CSV导入;未知价格与零价分别保存。通用菜单接入`/overseas-master-data/fleet-quotes`,不复用海外仓仓储报价。外接预订已接入可选销售报价来源,来源版本与本次成交金额分别冻结,不以原报价替代实际约定运费。
报价选用增量:候选提供端按客户、起运城市、目的仓码、币种、计价方式及服务日期筛选启用销售报价;缺价不按零价处理,不自动选择最低价或将整车价当拼载成交价。预订接入按起运仓正式详情的城市/时区和计划出发时刻生成条件,复用Warehouse已有内部详情接口,不从仓名、国家或浏览器时区推断。引用为可选项,私人地址或缺少明确仓资料可继续手填成交价。来源版本及原报价保存于独立`quote_source_json`,与本次成交单价/数量/总金额分开;确认承运前复核所选版本和有效性,承运确认后的实收改价保留原来源。实现沿`FleetBookingService`、`FleetBookingQuoteContext`及Admin `TripBookingPanel.vue`;部署及真实费用闭环仍须以主契约证据判断。
车辆菜单的出车记录`/overseas-master-data/trip-operations`从不可变DEPART汇总,每趟一次;图表与列表使用相同筛选和币种口径。实际里程/油耗只作独立补充更正,不改发车、结案或财务事实。成本通过服务内有界批量Summary读取,没有记录、无权限和未查询分别展示,不把约定外接金额当应收或收款。
实测凭证为选填PDF/JPG/PNG,单文件10MiB、每版最多20份,独立类型`FLEET_TRIP_OPERATION_EVIDENCE`按平台及车次归属。上传只创建不可变文件,保存实测记录才冻结引用;移除当前引用不删除历史,预览按当前或历史版本按需鉴权读取。上传结果未知时停止重传,可先不绑定该附件继续保存;实测内容保存重试仍使用同一请求键、版本及内容。
2026-10-05用户确认首版运营页展示Finance应收/实收:只展示Finance能够明确归属该车次的权威金额,按币种分别核对并可追溯来源;没有明确归属或付款分配的部分显示“待分配”,不能当作零元或已收。既有账单级核销不按未经确认的比例分配给车次,不把整账单金额或外接约定金额当作本车次应收/实收。成本与付款、客户应收与实收分别保持各自财务含义,不重复创建费用或资金流水。
车次详情按需显示在途交接面板,后台确认实际交接;按实际剩余货物核验接替资源,只更新未完成派送,原DEPART、库存和费用不重写。原车辆与司机各自确认实际任务结束后释放;PDA首版只读展示当前履约资源。退回处置沿`exceptionorder/`的开始处理、证据、分批实收和取消命令,真实退回流水生成独立重派凭据;通过`RETURN_RECEIPT`候选和预排进入新PDA发运,不改原实发/签收。逐来源全签才回传国内完成事件,签后退回重送不重复计数。后端可执行不等于Admin处置页面已完整接入,当前页面与环境验收缺口见测试环境主契约。已拣未发撤拣/退仓撤回和余货拆给多辆车的交接不由这条退回重派链代替。
同托退回来源按实际逐订单拣货归属核算;出库托盘明细上的主入仓码不能排除同托其他来源。排车明细与原出库明细使用物理托盘、原入仓码、目的仓和订单引用的冻结快照唯一关联;存在多个匹配时明确拒绝歧义,不能取首条猜测。退回凭据、新拣货和签收仍分别保留原来源、实际数量及时间,审核或异常工单状态不能替代实际实收与签收证据。
派送列表和详情统一返回数据库冻结的实际签收箱数 `signedPackages`:未知返回 `null`,零和正整数保留原值,不以发货箱数代替。签收时间按服务执行时区记录,完成事件转换为同一时刻的 UTC;国内完成记录与事件时刻保持一致,不能把本地时间直接标为 UTC。退回重派核平使用实际签收箱数,并保持原派送签收数量和时间不变。
公司车辆费用沿文首已确认口径进入Finance独立费用、历史和付款表,引用平台财务主体,不写入客户费用池、账单或钱包。CompanyVehicleCostSubmitted完整快照经既有Outbox直接投递Finance,匹配ACK只代表接收,入账/实际付款分别执行。费用和付款使用VC/VP业务号,公司凭证限定平台及费用归属。维修/救援页面已接来源提交、财务状态查询、入账、未付作废及付款凭证;查询、入账、作废、付款和上传独立授权。已付款不能直接作废或改写来源金额,未付款可作废重建;零申报金额可记录但不伪造实际付款。跨服务与受限账号的真实验收仍按两份主契约分别关闭。
源码合同见`fleet-quotes-v1.yaml`、`fleet-operations-v1.yaml`、`fleet-handovers-v1.yaml`、`fleet-trip-costs-v1.yaml`及Finance的`finance-vehicle-costs-v1.yaml`。代码、初始化基线、发布和真实验收分开核对;环境证据仅维护于两份正式主契约。
@@ -0,0 +1,458 @@
# 采购订单样品履约流程变更需求
日期:2026-10-09
采购订单需要从现有的下单、审核和数量记录,扩展为客户下单、海外购买、到仓装箱、国际快递交寄、国内收货核费及寄客户的完整流程。核心变更是将样品货款与快递费用分开控制:购买完成时扣样品货款,预估快递费先冻结,国内收货后再录入实际国际快递费、关税等费用。
本文是本次采购流程变更的需求维护入口。2026-10-09,用户授权按“首版简单、后续可扩展”的原则确定原第 8 节的 19 项业务规则;本版已将决定同步到操作、资金、权限和验收要求,开发按本版执行。第 2 节仅记录修改前的源码基线,第 3 至第 8 节定义目标行为;本文不表示目标功能已经实现、部署或通过环境验收。
## 1 已确认的目标流程
客户采购下单 → 国外客服购买完成,填写预计到货时间并扣样品货款 → 货物到仓核对,录入每箱箱规、重量及装货清单 → 国内客服根据清单打快递面单,冻结预估快递费 → 上传面单,国外贴单并送快递站点 → 国内收货,录入准确国际快递费、关税等费用 → 寄给客户。
| 节点 | 操作方 | 明确要求 | 需要区分的业务事实 |
|---|---|---|---|
| 客户下单 | 客户 | 创建采购订单 | 下单不代表已购买 |
| 购买完成 | 国外客服 | 填写预计到货时间,执行样品货款扣费 | 购买完成与后台审核通过不是同一节点 |
| 海外到仓及装箱 | 海外收货作业人员 | 收货核对,录入箱规、重量、每箱装货清单 | 入库总量不能替代逐箱清单 |
| 制作面单及预估运费 | 国内客服 | 根据清单制作快递面单,锁定预估快递费 | 锁定是冻结,不直接扣款 |
| 海外交寄 | 国外作业人员 | 获取面单,贴单,送快递站点 | 上传面单、贴单、交寄为不同事实 |
| 国内收货及核费 | 国内收货人员、国内客服 | 国内收货后录入准确国际快递费、关税等费用 | 预估费用与实际费用必须区分 |
| 寄客户 | 国内作业人员 | 将货物寄给客户 | 海外交寄与国内寄客户必须区分 |
## 2 当前实现与差距
以下为 2026-10-09 的源码核对基线,不作为测试环境部署或验收状态记录。部署与已验证场景仍以两份环境主契约为准。
| 范围 | 当前已有 | 本次需要变更 |
|---|---|---|
| 客户下单 | 正式创建、列表、详情入口;商品、规格、链接、数量、预算、地址和联系人;提交后待审核 | 在已有入口增加后续履约进度与业务明细 |
| 购买 | 后台审核、预计到达时间维护 | 增加独立购买完成操作及实际样品货款扣费 |
| 海外收货 | 采购仓库、手工入库数量、签收文件 | 增加收货核对、逐箱尺寸、重量和装货清单 |
| 快递费用 | 后台登记费用及凭证,发送冻结请求 | 区分样品货款、预估快递费、实际国际快递费及关税;改变结算触发时点 |
| 面单 | 只有签收文件、费用凭证分类 | 增加面单上传、受控读取、箱关联及贴单交寄事实 |
| 国内收货 | 未见采购专用国内收货节点 | 增加国内收货事实及实际费用确认 |
| 寄客户 | 国内外承运商、运单号;通用出库明细及时间 | 明确国内寄客户记录,与海外交寄分开 |
| 客户详情 | 基础商品信息、数量、预计到达时间、国内外运单、审核备注 | 增加节点进度、逐箱明细及获准展示的费用和文件 |
现有采购展示状态为待审核、已通过、已拒绝、待出库、部分出库、全部出库,不能表达购买完成、装箱、面单、海外交寄、国内收货和寄客户。
当前下单为单商品模型,仅有一份选填收货地址,联系方式允许填写电话、微信或邮箱。已有字段不能直接视为国际段和寄客户段均已具备可用于快递制单的收件资料。
### 现有资金逻辑与目标冲突
采购费用登记后发起冻结。当采购入库量达到采购数量时,系统对已冻结的采购费用发起结算;如果在全部入库后才登记费用,冻结成功回执也会继续触发结算。触发条件是全部入库,不是采购出库。
因此,在货物到仓装箱后登记预估快递费,现有逻辑会继续结算,无法保证只冻结。必须移除采购费用依赖入库数量统一结算的行为,按不同费用用途和业务节点控制。不得仅修改页面文案而保留旧触发逻辑。
## 3 首版履约范围与操作规则
### 3.1 范围与扩展边界
- 一单一个商品及规格、一次购买、一个履约批次、一个海外实际收货仓和一个国内接收地点;数量使用正整数件。一单允许多箱,国际段和寄客户段各一次整批实际交寄,可有对应不同箱的主/子运单。
- 海外、国内均允许对同一批次分次追加实收记录,例如两箱隔日到达。实收登记不自动完成收货;全部到齐或差异已处理后,由操作人员确认该段收货完成,再推进整批后续节点。
- 首版不支持多商品、追加或分批购买、分批国际交寄、分批寄客户、跨订单合箱及跨订单共用面单。购买前需要更换商品或数量时,取消原单并重新下单、审核;购买后不修改原购买对象。
- 海外收货、装箱、贴单和交寄均使用 Admin。采购数量只记履约台账,不接入 PDA,不形成或修改 WMS 可用库存,不绕过既有 PDA 入账边界。
- 商品、实收明细、箱内明细、两段运送及费用分别保留稳定业务关联;首版在服务端限制商品和履约批次数量,不把可扩展性做成未启用的流程、通用审批引擎或新的资金账本。
### 3.2 节点操作与保存信息
| 操作 | 保存的信息 | 执行与完成条件 |
|---|---|---|
| 客户下单 | 单商品、规格、链接、数量、预算单价及币种、最终收件人、联系电话及完整国内地址 | 登录客户隔离;预算非负且必须明确填写,零预算表示仅授权免费样品;提交进入待审核 |
| 平台审核 | 通过或拒绝、审核人、时间、备注、采购仓 | 保留现有单级审核;采购仓取国内仓库主档中的有效海外收货仓。拒绝结束原单,不新增退回修改流程;审核不是扣款 |
| 确认购买完成 | 已审核商品与数量快照、实际购买时间、供应商实付金额及币种、凭证、预计到海外仓时间、操作人 | 按第 4.1 节预算上限校验;真实购买事实与资金状态分开保存,触发实际货款扣费。未购买不得点击完成,也不得以预算替代实付 |
| 登记并确认海外收货 | 实收时间、实际仓库引用及编码/名称快照、逐次实收数量、合格数量、差异和处置 | 对照购买明细累计核对;已到货可先登记,未齐或异常未处理不能确认收货完成 |
| 保存并确认装箱 | 箱号、外箱长宽高、封箱毛重;箱内商品、规格、数量、实收来源 | 仅使用本单已确认可发的实收明细;各箱数量合计必须等于本批全部可发数量,不能重复分配。草稿可随收货准备;正式确认须海外收货完成、样品货款成功或确认零元 |
| 外部制单、上传与预估冻结 | 已确认清单版本、箱关联、承运商、运单号、面单文件、两端地址快照、预估国际运费 | 国内客服在外部制单后上传,填写 CNY 预估金额;系统只冻结该金额。制单与上传可先完成,冻结未成功不能交寄 |
| 确认贴单与海外交寄 | 逐箱贴单确认、实际交寄时间、本批全部箱及货物来源、承运商与运单、操作人 | 贴单与交寄分开留事实;全部有效面单与当前清单一致,预估资金已冻结或明确为零,且无阻断异常,才允许整批交寄 |
| 登记并确认国内收货 | 原国际交寄箱、逐次实收数量、合格/异常数量、实收时间、差异处理 | 不用总箱数代替逐箱来源;分次到达可以记录,全部收齐或差异已处置后确认该段完成 |
| 核定实际费用 | 国际运费、关税、国内运费、其他费用的核定情况、实际金额、凭证、业务日期、确认版本 | 国内收货完成后由有核费权限的国内客服确认并发起第 4 节资金处理;不增加客户在线确认或第二级财务审批 |
| 确认寄客户 | 国内实际交寄时间、全部可寄实收明细及数量、承运商与运单、最终收件快照、操作人 | 第 5 节资金及异常条件通过后整批交寄;生成面单、取得运单号或提交寄件信息不代表已寄出;实际交寄后进入“已寄客户” |
制单固定采用封箱毛重 kg(保留 3 位小数)和外箱长宽高 cm(各保留 2 位小数),数值必须为正。超出精度时提示按精度重新填写,不静默改变实测值;不新增净重、体积重或计费重试算。承运商计费与实测存在差异时,通过实际费用及凭证说明,不覆盖原测量值。
面单首版仅接受 PDF/JPG/PNG,沿用 File 的大小和安全限制;一个文件可覆盖本订单多个箱,但应明确每箱对应的面单页或文件。国际段同一批可有多个箱运单,国内段同样逐箱可追溯;不要求一箱一笔冻结,不新增快递商、轨迹或打印机集成。
### 3.3 修改、重制与历史保护
| 对象 | 首版规则 |
|---|---|
| 商品、规格、数量 | 审核后锁定,购买前需要变更则取消重下;购买后仅允许登记事实更正说明及异常处置,不直接改原商品或数量。预算上限调整单独按第 4.1 节处理 |
| 计划采购仓与实际实收仓 | 首次实收前由采购审核/管理人员选择或修改计划仓;首次实收冻结实际仓。实际仓录错由采购管理人员凭说明、证据更正并保留原记录;已有后续实物操作时不得通过改字段重归属,仅补充更正记录并处理异常。首版不做转仓 |
| 实收数量 | 按该实收记录本段的下游判断:海外实收已有装箱确认时,先撤回尚未交寄的海外清单再建立受控更正;国内实收在尚未寄客户时可建立受控更正,重核可寄数量、国内面单及费用依据,不回滚原国际交寄。已完成本段实际交寄时仅追加更正说明和异常处置,不改写原实物事实 |
| 未交寄装箱清单 | 修改形成新版本;箱、数量、尺寸、重量变化立即使旧面单不能用于新版本,需国内客服重新核对清单、面单与预估。旧贴单确认失效,重新贴单后才可交寄 |
| 未交寄预估金额 | 金额不变且币种为 CNY 时,核对后可由新清单版本引用原有效冻结,不新建占款;金额变化则先释放旧冻结,成功后再申请新金额冻结。释放或新冻结未完成时禁止交寄,失败显示待处理,不保留两笔重复有效占款 |
| 面单重传 | 同清单同金额只替换文件版本并保留历史,不重复冻结;换承运商、运单或收件信息须重新核对报价和箱关联,并重新确认贴单 |
| 已交寄记录 | 保留当次清单、货物、面单、运单、地址和时间快照;之后只能追加有权限的更正说明,不覆盖原事实,不以改版本重新增加可发数量 |
| 已确认费用 | 金额、币种、汇率及资金请求不能原地覆盖;处理中禁止确认更正,已结算后的增减分别走第 4.5 节调整 |
海外交寄时,服务端须按本订单、当前清单、实际箱和货物来源原子校验并保存有效交寄事实。累计有效交寄不得超过本批可交寄装箱数量,本次必须覆盖全部可交寄箱;不同操作人、不同请求、刷新或更换清单版本不能重复发出同一货物。原请求重放返回原结果,其他请求遇到已交寄货物明确提示,不新增交寄数量或国内收货来源。合法更正只修订说明或建立关联更正,不产生第二份有效交寄。
### 3.4 国内货物承接与异常
- 国内实收逐箱关联国际交寄来源,同一收货事实不重复计数,分次实收按原箱累计核对;多到的货物单独记异常,不增加本单可寄数量。
- 两端短少、破损、多货均先如实记录。未处理差异阻断收货完成及计划性发运,但不阻断继续登记真实到货。采购管理人员在本单记录“等待补齐、确认短少、破损拒收/处置、多货退回”的数量、原因、证据、操作人和时间。
- 等待补齐不生成第二个购买或发运批次。供应商补发只用于海外整批交寄前补齐本单原采购缺口;国际交寄后,国内等待补齐仅限原交寄范围内的迟到货物。需要重新采购或再次国际发运的另行下单,不在原单追加交寄。客户接受短少、破损后剩余货物继续履约,或停止履约,均由客服留存客户书面/聊天凭证,采购管理人员确认。钱款由财务关联原费用调整,不按短少数量自动退款。
- 只有已确认可寄的实收明细可继续装箱/寄出;已寄量加本次寄出量不得超过可寄实收量,且本次须覆盖本批全部剩余可寄货物。全损或无可寄货物进入异常关闭,不伪造零数量交寄。
- 国内允许一原箱对应一新包装的破损换箱,记录原因与新箱规重量,保留原箱业务标识及其来源关系;换箱不改变已经核准可寄的商品、数量。不支持拆成多箱、合并不同箱或重新组合商品;损坏商品的剔除先走差异处置。
- 购买前可由有取消权限的平台人员取消,客户通过客服提出取消;购买后不提供抹除履约的一键取消。全部实物去向明确、无需继续履约、已收费调整和冻结释放均完成且无未决资金时,采购管理人员可异常关闭。关闭保留原履约和资金事实,不自动退款,也不自动生成退货物流任务。
- 本节只是采购履约记录及最小异常处置,不产生 WMS 库存流水,不新增通用异常工单、供应商应付或索赔系统。
### 3.5 两段地址、文件与客户展示
| 内容 | 首版处理 |
|---|---|
| 国际段收寄资料 | 寄件方取实际海外仓资料,国内接收地址由国内客服每单录入或从已有资料复制;国内收件人、联系电话及完整地址在制单前必填,不新增国内接收地点主档 |
| 国内寄客户资料 | 客户下单提供最终收件人、电话和完整国内地址;国内客服寄出前核对。客户申请变更由客服凭确认记录修改;已制单须重制面单,实际交寄后不能覆盖原地址或在系统中假作改派 |
| 资料快照 | 两段分别保存当次使用的收寄姓名、电话、地址及承运商要求的信息,后续主档变更不改历史快照;仅有微信或邮箱不能代替快递电话 |
| 客户可见 | 本客户订单进度、预计到海外仓时间、装箱结构化明细、两段承运商/运单、预算上限、货款及各费用、冻结/扣款/退款结果、对客异常处理摘要 |
| 客户不可见 | 面单、供应商采购凭证、费用凭证、预算沟通凭证、内部异常附件、内部备注及原始诊断报错;首版不开放这些文件下载,也不新增客户核费审批页面 |
文件读取、下载和关联均由服务端校验客户、订单、文件分类及操作者权限。平台人员可在其采购业务权限范围内处理不同客户的订单,不强加个人仓绑定;关联的文件必须属于当前订单,不能仅凭同客户或文件标识放行。一个订单多箱共用一份面单允许,跨订单共享首版不开放。文件本体继续由 File 持有。
## 4 费用与资金规则
### 4.1 币种、预算和实际货款
- 原币仅支持 CNY/USD,钱包、资金命令及本次采购实际费用入池统一 CNY。预算单价和原币费用保留 2 位小数;USD 折算复用 Lastleg 现有月度汇率及 OverseasFeeCurrencyConverter:取费用实际发生日所在月的有效正数汇率,汇率 6 位,CNY 金额 2 位,均使用 HALF_UP。CNY 汇率固定 1.000000。
- 保存原币、原金额、实际业务日、汇率月份、汇率值和折后金额;确认后冻结快照。缺失有效汇率时不得确认资金金额,不能默认 1 或取回执/重试当天汇率;已经发生的购买仍可登记为待核定事实。
- 预算总上限等于预算单价乘已审核数量,是样品货款上限,不包含运费、关税等服务费用。核对实付时,预算与实付均以本次购买相同汇率快照折算为 CNY 比较;实际货款按供应商实付 1:1 收取,首版不加价。
- 无预算须先取得客户授权补齐;零预算只授权免费货款。超预算须在购买前取得客户书面/聊天确认,客服登记新的上限、币种与凭证,由现有采购审核人员核验后生效;保留前后上限,不新增客户在线审批或多级流程。
- 已发生的未授权超预算须记录真实事实并暂停后续确认,取得客户授权后再核定扣费,或按异常终止/退款处理;不得静默超扣、伪造金额或丢失采购事实。买错商品或数量不通过补预算授权改写原购买对象,记录异常后处理退还/关闭,正确需求另单办理。
### 4.2 费用用途与核费范围
| 用途 | 时点与资金行为 |
|---|---|
| 样品货款 | 购买完成后按确认的实际 CNY 金额扣费;明确免费时只记核定事实,不发零元资金指令 |
| 预估国际运费 | 制单阶段只冻结国际段预估 CNY 金额;零预估须记录依据,不发零元冻结。关税、国内运费及其他费用不混入该冻结,冻结不生成实际应收 |
| 实际国际运费 | 国内收货完成后按实际金额结算唯一有效的国际运费冻结,规则见第 4.3 节 |
| 关税 | 国内客服依据实际凭证核定,正额单独扣费,不适用或零元需明确确认 |
| 国内运费 | 国内收货完成后可先外部制单确定价格,核定扣费成功后再交承运方;制单不代表发货,不引入“先发货才能知道金额”的依赖 |
| 其他费用 | 默认不适用;发生时逐项填写名称、原因、凭证、业务日及金额,正额单独扣费。不得重复计入货款、国际运费、关税或国内运费 |
国内核费由有核费权限的国内客服一次确认本单费用清单,不再增加客户确认或第二级财务审核。国际运费、关税、国内运费和其他费用范围都应有明确核定结果;其他费用可标为“不适用”,不要求创建虚构收费行。
| 核定情况 | 处理 |
|---|---|
| 待核定 | 尚无明确结果,空值不视为零元;不能完成本单核费或寄客户 |
| 确认零元 | 项目适用但无需收费,保存确认人、时间及依据,不发零元扣款、冻结或结算指令 |
| 不适用 | 明确不适用于本单,保存确认说明,不伪造已付款 |
| 确认正额 | 保存金额和确认版本,发起资金处理;核费已确认与扣费成功分别展示 |
已有冻结对应的实际费用确认零元时仍须真实释放冻结。费用清单中的多笔正额分别处理,部分扣款成功不回滚已成功扣款,也不能重扣;只跟进其余未完成项,全部完成后才允许国内实际交寄。
### 4.3 扣费、差额与冻结
样品货款、关税、国内运费及其他正额费用复用 Finance 的业务冻结后立即全额结算链路,同一费用号最多一次成功实扣。中间显示扣费处理中,不要求客服手动执行两步;冻结成功不等于扣费成功。该自动结算只用于明确的实际费用用途,预估国际运费不得沿此链路自动结算,更不得由采购入库数量触发。
设预估国际运费冻结额为 E,最终实际国际运费为 A,两者均为 CNY:
| 情况 | 首版资金行为 |
|---|---|
| A = E 且 A > 0 | 结清原冻结,实扣 A |
| 0 < A < E | Finance 在同一事务内实扣 A、释放 E − A,原预估 E 与实际 A 分别保留 |
| A > E | Finance 在同一事务内校验并补占差额后实扣 A;资金/有效授信不足时整笔失败,保留原冻结和原余额,不先释放原冻结 |
| A = 0 或国际运费不适用 | 仅释放对应有效冻结;无冻结则只保留核定结果,不生成零元结算 |
| E = 0、A > 0 | 无原冻结可结算,按一笔实际国际运费执行冻结后立即结算;费用来源仍只记录 A |
按实际金额结算冻结由 Finance 原子执行,Lastleg 不能用“释放旧冻结、再冻实际金额、再结算”的串行操作代替。此规则用于最终实际结算;交寄前重新报价使用第 3.3 节“先释放旧预估、再冻结新预估并阻断交寄”的流程,二者时点不同。
资金可用额、授信期限、扣用顺序和充值归还顺序全部沿用 Finance 当前规则;采购不额外开放透支、不建立授信副本,也不套用信用卡授权有效期。冻结不因到货、时间流逝或订单页面关闭而自动结算/释放,必须关联明确的重估、结算、取消或异常处理动作。
### 4.4 请求幂等、费用版本与入池
- 每个资金请求绑定客户、费用用途、费用确认版本、原币/汇率/CNY 快照和唯一请求标识。每个费用业务事实最多一次成功扣款,不能通过新请求标识绕过该约束。
- 处理中或结果未知时,可保存更正草稿,但不能确认新版本、发起替代扣款、退款或释放同一待决资金;先查询/重放原请求直至结果明确。网络超时不能当成业务失败。
- 只有 Finance 已明确失败且确认未发生目标资金动作时,才允许对同一费用版本登记新的重试尝试;保留原尝试结果。冻结已成功但结算失败时只重试结算,不能新冻一遍。
- 旧版本晚回执只能更新原请求及其费用版本,不覆盖新金额结果,不丢弃真实扣款、冻结或释放事实。未决时尝试确认 V2 应被拒绝,V1 结果明确后才能按第 4.5 节更正。
- 本次采购的正额费用收到成功扣款回执后,才通过同一费用版本的 Outbox 发布实际应收来源。预估冻结、零元和不适用不发布实际应收;发布失败只重试来源投递,不再次扣款。
- Finance 以明确的原资金处理引用和实际 CNY 扣款金额核对来源;匹配后直接作为已结算应收入池,不能进入普通待对账候选。来源缺少资金引用、引用跨客户或金额不符时拒绝或待核对,不降级成可再次收费的 AVAILABLE 来源。
- 延迟、乱序及重放仍须安全:已扣款等待来源入池时显示该关联进度;关联不影响已经发生的资金事实,但正常寄客户前须完成实际费用入池关联,异常关闭前同样须完成关联。
上述规则按[财务费用入池 P0 闭环](../财务管理/财务费用入池P0闭环.md)的防重复结算原则执行;本次采购采用“先实扣、后发布已结算来源”的确定路径,不增加采购赊账出账选项。
### 4.5 更正、追加与退款
- 未发出资金请求的费用草稿可修改;仅处于预估冻结阶段的金额变化按第 3.3 节重估。已发出请求且结果未决时锁定确认动作,不用新费用号避开未决状态。
- 实际费用的资金请求已明确失败且尚未成功实扣时,先终止旧版本的后续重试;仍有有效冻结的须释放成功,才可更正确认新费用版本并发起关联的新请求。该情形不产生已实扣差额单或退款,旧版本不能因晚回执或人工重试重新生效。
- 已结算费用增加金额,由具有财务调整权限的人员创建仅含正差额的新调整单、独立费用号,引用原费用和原因凭证;例如原已扣 100,正确总额 120,则新增 20,不重新扣 120,也不复用原冻结号。原实际费用和差额各自关联成功资金结果。
- 已结算费用减少或应退,由财务人员创建关联原成功扣款的 CNY 退款调整,填写原因、凭证和金额。Finance 锁定原扣款,原子校验本次退款金额不超过“该原扣款金额 − 累计已成功退款”的可退余额;等价地,计入本次后的累计退款不得超过该原扣款。幂等回补客户钱包并保留不可变流水,回补遵循 Finance 现行资金归还顺序,不延长或恢复过期授信;仅冻结未扣款的款项执行释放,不做退款。
- 退款只回客户资金账户,不走外部支付原路退款,不以普通充值伪装,不发布负数普通费用。原费用保持已结算,财务净额通过原款、正额调整及退款记录计算,不能重新进入待对账池。
- 对同一原费用链的金额更正沿用原汇率快照,以“原扣款 + 已成功正额调整 − 已成功退款”计算当前净实扣,再与本次修正目标 CNY 总额求差。同一费用链有未决调整或退款时不得确认下一次更正;明确失败的旧调整须先完成,或终止其后续重试并释放仍占用的冻结后,才能按新目标更正,不能留下以后还可重试扣款的旧目标。独立新发生费用才使用新业务日汇率;退货、短少不自动推导退款金额,由财务依据已确认的客户处理方案执行。
- 已成功退款、调整和原扣款均不得覆盖;同一调整单重放返回原结果,拒绝重复、超额及零元退款。需退多笔实扣时逐笔关联,不能跨客户冲抵。
- 履约已完成后可以处理有凭证的追加或退款,资金进度单独展示,不把“已寄客户”回退成未发货;异常关闭时要求当时所有已知资金处理结束,后续新增有据调整保留关联记录。
## 5 权限、状态与节点准入
### 5.1 操作权限
沿用平台/客户两级及现有 IAM 角色;不新建国内/海外用户类型或岗位主档。采购列表权限包含详情只读,写操作独立,按下表动作赋予现有岗位,可由同一账号兼任多个动作,首版不强制双人分离。
| 动作范围 | 负责岗位及权限边界 |
|---|---|
| 客户下单和查询 | 仅本客户;不能执行后台审核、收货、发运或资金调整 |
| 采购审核、取消、预算上限核验 | 现有采购审核/管理人员,保存审核或取消事实 |
| 购买、海外收货装箱、贴单交寄 | 海外业务人员按各动作权限执行;服务端校验有效海外仓及订单冻结的实际仓,不把 Admin 用户绑定到某个 PDA 仓 |
| 面单、预估、国内实收、核费、寄客户 | 国内业务人员按对应独立动作权限执行;面单上传不同时赋予核费或资金调整权限 |
| 事实更正、差异确认、异常关闭 | 采购管理权限;资金结果不能通过此权限修改 |
| 追加收费、退款 | Finance 财务调整权限;采购服务只发起受控业务请求,不直写账户或财务单据 |
权限码、Controller、接口合同、IAM 配置与前端按钮由开发按此动作边界同步落地,不能继续用一个通用编辑权限代替所有新节点权限。平台授权人员可以处理不同客户的采购单;客户隔离及文件范围始终由服务端保证。
### 5.2 状态与准入
履约进度按事实派生:待审核 → 待购买 → 待海外到仓 → 海外收货中 → 待装箱 → 待面单及预估处理 → 待海外交寄 → 国际运输中 → 国内收货中 → 待国内核费 → 待寄客户 → 已寄客户。已拒绝、已取消、异常关闭单独记录;异常处理中作为阻断标记,不抹去最后真实履约阶段。具体枚举命名由技术设计确定,含义不得改变。
| 动作 | 首版前置条件与资金失败处理 |
|---|---|
| 正常购买确认 | 已审核,商品及数量一致,预算授权和汇率可用;购买前可查询资金资格但不提前冻结货款。已真实发生的异常购买可登记,扣费失败不回滚购买事实 |
| 登记收货事实 | 有对应购买/交寄来源即可记录实际到货,即使资金未成功;来源异常仍保留异常记录,不能伪造上游成功来放行正常链路 |
| 正式装箱确认、预估冻结 | 海外收货完成、差异处理完毕、样品货款扣款成功并完成费用来源关联,或已明确免费;资金未决/不足时可准备草稿,不能完成上述确认 |
| 海外实际交寄 | 清单、面单及逐箱贴单已确认;样品货款完成;预估国际运费冻结成功或确认零预估;所有可发货物整批一致,无阻断异常 |
| 国内核费确认 | 国内收货完成,差异处置明确;四类费用均有核定结果,国内运费可以先制单取得确定金额。可以保存草稿,未核定不能确认整单费用 |
| 国内实际交寄 | 全部可寄货物核平;全部正额货款/费用扣款及费用来源关联完成;零元/不适用已核定;多余冻结已释放;无未决退款/调整及阻断异常 |
| 异常关闭 | 全部货物有明确去向且无需继续履约;所有已知费用、退款、来源关联和冻结释放完成;采购管理人员填写原因确认 |
首版不允许客服用“继续发货”跳过资金失败或未知结果,也不新增人工透支开关。余额不足通过充值或 Finance 已有授信机制解决后重试。国内实际交寄确认即正常履约终态,不新增客户签收、物流轨迹或自动签收功能。
## 6 代码入口、能力差距与实施边界
| 范围 | 当前入口 | 本次实现重点 |
|---|---|---|
| Client | apps/client-web/src/modules/cross-border/routes.ts、views/ProcurementView.vue、components/BusinessOrdersView.vue、api/businessOrders.ts | 单商品下单校验、预算及地址、进度与费用展示;不影响共用组件中的本土卡车、散板 |
| Admin | apps/admin-web/src/modules/overseas-business/pages/PurchaseOrdersView.vue、PurchaseOrderEditView.vue、PurchaseOrderDetailView.vue;api/platformOverseasBusiness.ts | 节点动作、实收/箱明细、面单、预算凭证、核费及异常权限;通用编辑移除越过节点的写入 |
| Lastleg | baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/ | 状态和业务明细、用途驱动资金指令、版本回执、原子数量校验及审计 |
| 费用来源与汇率 | Lastleg financefee/,按采购实际引用进入;OverseasFeeCurrencyConverter | 复用月度 USD/CNY 汇率快照;成功扣款后发布实际来源,预估不入池 |
| Finance 与 File | 沿采购资金、费用和文件调用进入 | Finance 资金及关联扩展;File 文件归属、分类与授权 |
现有钱包只有全额结算/释放,不能将“按实际金额结算冻结”或“关联原扣款退款”写成已经具备。首版必须补齐以下定向能力:
1. Finance 在单事务内按实际金额结清预估冻结,并处理少收释放、超额补差、资金不足整笔不动。
2. Finance 关联原扣款的幂等钱包退款、可退余额校验及财务调整留痕。
3. Finance/Lastleg 按真实资金处理引用和实际结算金额绑定费用来源,防止预估金额与实际金额不同导致匹配失败或重复出账。
业务费用仍归 Lastleg,账户/冻结/流水/财务事实归 Finance,文件本体归 File。统一 Gateway/Auth 和业务 Outbox 直接投递不变,不新建账本或事件桥。上述定向扩展是满足本版需求的开发内容,不以新增技术平台或跨库写入实现。
开发前需完成本版对应的 DTO、状态/动作、资金命令与回执、表结构及权限合同设计。对外 API、OpenAPI、初始化 SQL、直接消费者、Mock/Fixture 和测试按仓库门禁同步;不为测试存量保留旧流程兼容分支。开发应移除“全部入库统一结算采购费用”的两处旧触发路径。
需求整理阶段仅维护文档;后续用户已授权按本文开发,并部署测试环境、操作测试数据库、执行真实 HTTP 及内置浏览器验收。该授权仅用于本次采购变更的测试环境操作,不扩展到生产环境或无关数据清理。
## 7 首版验收要求
| 场景 | 必须满足的结果 |
|---|---|
| 单商品与批次边界 | 多商品、追加购买、分批发运、跨订单合箱请求由服务端拒绝;一单多箱正常完成 |
| 审核及预算 | 未审核不得购买;无预算不得正常确认;零预算不能扣正额;超预算凭证核验前不能正常扣费;实付不能被预算替代 |
| 汇率与跨月重试 | CNY/USD 原币与 CNY 折算可还原;缺失月度汇率不伪造金额;跨月回执及重试保持原快照;金额与精度按现行转换器 |
| 购买事实与货款 | 购买完成发起货款扣费,不等到全部入库;失败保留购买事实,免费不发零元命令;重复请求不重复扣费 |
| 分次到货 | 同一批次多次实收累计正确;到货可记录,未齐或异常未处理不确认完成;海外交寄前可补原采购缺口,国内迟到只接原国际交寄货物,需要再次国际发运的另单处理 |
| 分段实收更正 | 海外实收更正撤回本段未交寄清单;国内实收更正不回滚已完成国际交寄,重新核对国内可寄数量、面单及费用;已完成本段交寄只追加说明和异常 |
| 实际收货仓 | 实收后通用编辑不得改历史仓;受控录错更正保留原记录,修改采购仓不代表实物转仓 |
| 装箱与测量 | 实收来源与箱内件数核平,不能重复分配;全部可发数量被覆盖;cm/kg 精度和正值校验正确 |
| 多人海外交寄 | 非本单/无效清单箱拒绝;两人不同请求并发或刷新重提同一箱仅一份有效交寄;换版或更正不重复增加国内来源 |
| 面单及预估 | 外部面单可按箱读取打印;上传、贴单、交寄分开;冻结成功仅减少可用额;零预估有依据;全部入库及其后新增预估均不触发扣款 |
| 交寄前重制 | 清单/面单变化后旧贴单失效;同金额重传不重复冻结;变价先释放成功再新冻结,过程及失败阻断交寄 |
| 国内实收与换包装 | 逐箱来源可追溯,重复实收拒绝;允许一对一换包装但不增加货量;拆箱、合箱及重新组合拒绝 |
| 收货差异 | 短少/破损/多货如实记录,未经处理不继续;客户接受减量有凭证;无可寄货物不能零数量交寄 |
| 核费及国内制单 | 四类费用有明确结果;国内运费可先制单再核定扣费,实际交寄在后;未知金额不当零元 |
| 零元/不适用 | 不发零元资金指令、不发布虚构应收;原冻结仍释放并跟踪实际结果 |
| 国际运费差额 | 覆盖 E=100、A=100/80/120/0 及 E=0、A>0;少收余款释放,超额不足时原冻结和余额不变,不出现重复占款或扣费 |
| 未决更正与晚回执 | V1 请求未决时 V2 只能存草稿,确认及替代请求被拒绝;晚回执归属 V1且真实资金事实保留;超时查询/重放不重复执行 |
| 明确失败后重试 | 原结果已确定且无目标资金动作后才能新尝试;已冻结只重试结算,同费用最多一次实扣 |
| 扣款与入池 | 扣款成功才发布实际来源;投递失败不再扣款;原资金引用、客户或实际金额不匹配时不进入普通待对账池;乱序重放仍不重复收费 |
| 追加与退款 | 已扣100连续改120、130、110,依次补20、补10、退款20,净实扣110;单笔原扣100已退30再退50应成功,再退超过20应拒绝;并发退款不能超原实扣;不以充值或负数普通费用替代,原费用不重新可出账 |
| 节点门禁 | 扣费失败仍可登记真实到货;不能确认装箱或计划发运;国内交寄前全部资金、来源关联、余款释放及异常处理满足要求 |
| 地址与真实发运 | 两段快照独立,改地址不覆盖旧面单;仅填写运单不显示已寄;实际国内交寄后进入正常终态 |
| 客户与文件权限 | 客户仅见自己的结构化资料及费用结果,不能下载内部文件;跨客户文件读取/错误订单挂载拒绝;平台已授权跨客户操作不误拦 |
| 取消与异常关闭 | 购买前可取消;购买后不抹除原事实;实物和资金未收口不能异常关闭;关闭不自动退款 |
| 权限与前端回归 | 节点动作由服务端独立授权,通用编辑不能越权;采购修改不破坏本土卡车、散板;客户响应无内部附件和诊断信息 |
代码和本地检查通过不代表整体验收完成。真实 HTTP 与环境写入、部署仍按仓库授权执行;Admin/Client 视觉验收按 1920×1080、100% 缩放,由人工操作并提供截图。部署与已验证场景仅维护在现有两份环境主契约。
## 8 原 19 项业务规则的首版决定
本表依据 2026-10-09 用户“按最简单可扩展方式先确认”的明确授权确定,替代原待确认清单。它是本次业务范围与行为选择,不表示实际人员已在业务单上完成审核或核费。开发按本版实施,后续改变范围需先回写本文。
| 编号 | 原决策主题 | 首版决定 |
|---|---|---|
| 01 | 多商品、购买与履约批次 | 单商品/规格、一次购买、一个批次;多箱、分次实收;两段各一次整批交寄,见第 3.1 节 |
| 02 | 购买前审核 | 保留现有单级审核;通过后购买,拒绝结束原单;不新增通用审批 |
| 03 | 预算与超预算 | 预算为货款上限;超预算先取得客户书面/聊天授权,由现有审核人员核验;不做客户在线审批,见第 4.1 节 |
| 04 | 币种与汇率 | 原币 CNY/USD,钱包及入池 CNY;复用业务日所属月汇率,快照不重算 |
| 05 | 面单方式 | 国内客服外部制单、上传 PDF/JPG/PNG;无快递商/轨迹/自动试算集成 |
| 06 | 箱规重量 | 封箱毛重 kg 3 位、外箱 cm 2 位,正值;不新增计费重试算 |
| 07 | 重制与冻结 | 同金额核对后沿用冻结;变价先释放旧冻结再新冻,期间禁止交寄;旧面单/贴单按第 3.3 节失效 |
| 08 | 事实更正 | 购买对象锁定;按本段未发运的下游撤回并受控更正,国内更正不回滚国际交寄;已交寄事实只追加说明/异常,不覆盖或重发 |
| 09 | 两段收寄资料 | 国际段国内接收资料由国内客服每单录入,最终客户资料由客户下单提供;确认及交寄保留两段快照 |
| 10 | 作业终端与仓范围 | 海外用 Admin,不接 PDA/WMS;角色复用、动作独立授权;校验有效仓与订单实际仓,不新增 Admin 个人仓绑定 |
| 11 | 国内部分实收及重装 | 同批允许分次实收,收口后才继续;仅支持一对一换包装,不拆箱/合箱/重组 |
| 12 | 实际费用确认 | 国内客服按独立核费权限一次确认四类费用;无客户或二级财务审批;未知不当零 |
| 13 | 预估冻结范围 | 仅国际快递费;关税、国内运费及其他费用实际核定后单独扣费 |
| 14 | 实际差额结算 | Finance 原子按实际金额结清预估,少退多补,不足原状保留;零实际只释放,见第 4.3 节 |
| 15 | 未决费用更正 | 只允许准备草稿,原结果明确前不确认新版本或发替代资金请求;已扣增额做正差额单、减额做关联退款 |
| 16 | 失败与节点准入 | 真实到货可记;正式装箱及计划交寄须满足资金条件;未知/不足不放行,见第 5.2 节 |
| 17 | 差异、取消与退款 | 单内最小异常处置;客户减量/停止有凭证;购买前取消,购买后收清实物和资金才能异常关闭;退款回钱包,见第 3.4、4.5 节 |
| 18 | 正常完成条件 | 国内实际交寄确认即“已寄客户”;不新增签收或轨迹。之后财务调整不回退履约事实 |
| 19 | 客户资料开放 | 展示结构化箱明细、运单和费用结果;内部面单、采购/费用/沟通凭证及异常附件不开放下载 |
### 开发交接结论
原 19 项已转为明确首版规则,正文与验收按同一范围执行,不再以待产品选择的条件场景交付。开发仍需完成 DTO、数据库、权限、资金事件和接口的技术设计,并实现第 6 节的 Finance 定向扩展;这些属于已确定业务规则下的实现工作,不是新的产品待确认项。
本版可交开发开展技术设计、任务拆分及实现。需求评审结论不替代编译、测试、环境或人工视觉验收,不表示当前代码已经满足目标。
## 9 依据与成熟软件参考
### 9.1 当前项目依据
- [海外仓业务入口](README.md)
- [财务管理入口](../财务管理/README.md)
- [财务费用入池 P0 闭环](../财务管理/财务费用入池P0闭环.md)
- [统一认证与服务通信契约](../统一认证与服务通信契约.md)
- [测试环境单机部署与配置契约](../测试环境单机部署与配置契约.md)
- [平台客户层级与权限契约](../平台客户层级与权限契约.md)
- [客户端采购详情实现](../../apps/client-web/src/modules/cross-border/components/BusinessOrdersView.vue)
- [后台采购详情实现](../../apps/admin-web/src/modules/overseas-business/pages/PurchaseOrderDetailView.vue)
- [采购服务与现有资金触发逻辑](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/service/OverseasProcurementService.java)
- [现有海外费用汇率转换](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/financefee/service/OverseasFeeCurrencyConverter.java)
### 9.2 官方产品文档对照
参考查询日期:2026-10-09。以下用于验证设计模式可行性,具体 19 项是结合本项目现状作出的首版选择,不是声称这些产品采用完全相同的业务规则。
| 官方资料 | 本次采用的模式及边界 |
|---|---|
| [Odoo 19:收发货流程](https://www.odoo.com/documentation/19.0/applications/inventory_and_mrp/inventory/shipping_receiving/daily_operations.html) | 可从较少操作步骤开始,再按质量与仓储需要扩展;本次采用简化采购台账,不引入 Odoo 的库存体系 |
| [ERPNext:Purchase Receipt](https://docs.frappe.io/erpnext/purchase-receipt) | 订单与实收分开,记录接收/拒收及短收关闭;本次允许同批多次实收和明确差异处置,不照搬其库存过账 |
| [Shopify:Understanding shipping labels](https://help.shopify.com/en/manual/fulfillment/fulfilling-orders/shipping-labels/understanding-shipping-labels) | 支持在系统外购买面单后补充运单,贴单和交给承运方是不同动作;本次保留外部制单与人工交寄确认 |
| [Stripe:授权与捕获分离](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method) | 预留与实际扣款分开,部分扣款释放余款;本项目使用自有 Finance 钱包,原子补差是本项目扩展,不接入 Stripe,也不使用信用卡期限或超额捕获规则 |
| [Stripe:幂等请求](https://docs.stripe.com/api/idempotent_requests) | 重试关联原请求,参数变化不能冒充原请求;本项目另加费用业务级防重复,不照搬外部平台的幂等记录保留期限 |
可行性结论:上述模式能够支持本版采购样品流程;实施重点是本项目的明细关系、权限、资金用途及 Finance 定向扩展,不需要先引入完整 ERP、WMS、第三方支付或通用流程平台。
## 10 技术实施合同
本节将前述业务规则映射到实现边界,不改变业务范围,也不表示对应功能已完成。开发直接在当前工作区及分支实施。
### 10.1 数据与事务边界
| 数据对象 | 归属与核心关系 | 约束 |
|---|---|---|
| 采购主单 | Lastleg,保留当前采购单号与客户归属 | 主单版本控制;商品、规格和购买数量审核后冻结;履约阶段与资金状态分开 |
| 购买事实与预算授权 | 关联采购单、原商品快照、凭证及预算授权版本 | 每单一次实际购买;异常购买事实可以先保存,但未核定金额不能扣费 |
| 两段实收记录 | 段别为海外/国内;海外关联购买,国内关联国际交寄箱 | 分次追加与更正留痕;不能重复消费实收来源;实收不直接增加 WMS 库存 |
| 装箱清单与箱内来源 | 清单版本、业务箱号、尺寸重量、实收来源及数量 | 每单唯一当前确认版;数量守恒;失效版本不得交寄;历史版本不能恢复可发数量 |
| 面单与贴单事实 | 文件归 File,关联关系归 Lastleg;绑定运输段、清单版本及箱号 | 每箱明确文件或页码;面单版本改变后旧贴单资格失效;只允许同订单文件关联 |
| 国际与国内交寄 | 每单每段唯一有效整批交寄;保存箱/来源数量、地址、运单快照 | 订单行锁内复验全部货物、资金与异常条件;两段交寄各自幂等,跨请求也不能重复发运 |
| 费用版本 | 费用用途、核定情况、原币/汇率/CNY、版本、原费用链 | 草稿可修改;确认后不可覆盖;预估、实扣及退款分别记录 |
| 资金请求尝试 | 费用版本、操作、冻结身份、事件 ID、请求幂等键、请求金额、结果 | 结果按 commandEventId 精确落到原尝试;未决时禁止替代请求,明确失败才可受控重试 |
| 费用来源关联 | 成功实扣对应的来源版本、资金引用、关联结果 | 预估不入池;资金成功与来源关联分别记录;来源投递重试不得重发扣款 |
| 差异和更正记录 | 来源对象、原事实引用、数量、处置、证据、操作者 | 追加留痕;已交寄事实不覆盖;资金更正受 Finance 独立权限约束 |
数量、费用版本、资金请求和明细关联使用结构化列及唯一约束;JSON 只承载不可变快照、地址或审计补充,不承担全部数量关系。每个节点命令使用订单版本、幂等键和请求摘要;锁定订单后复验来源、可执行动作及最新资金状态,再原子提交事实、审计和业务 Outbox。
通用 `finance-fee-sources` 接口不允许人工创建、提交、审核、调整或作废采购费用来源;采购收费与更正必须从采购节点进入,实扣成功后才由内部已结算发布入口关联来源,防止绕过节点形成第二笔收费。
采购费用记录沿用 `ll_overseas_procurement_fee`,以 `purpose + fee_item_code + fee_version` 在订单内区分确认版本;原币、汇率、实际 CNY、核定情况和资金身份保存在同一不可变费用版本上。`ll_procurement_wallet_attempt` 按 `fee_id + attempt_no` 和唯一 `command_event_id` 保存每次请求。预估与实际国际运费是独立费用事实,实际费用可引用原预估的资金身份;退款用独立费用业务号引用原成功实扣,不能改写原费用。
独立新发生费用通过 `fees/additional` 由 `finance-adjust` 权限登记,必须关联已购买订单、本单费用凭证及真实业务日期,以新业务日汇率和独立费用号处理;不覆盖原费用。费用版本记录 `confirmation_origin`(BUSINESS / FINANCIAL),资金重试沿用该入口权限。普通核费首次成功确认后只能引用已有有效版本,新增费用与失败替代由财务入口处理;未交寄时重新确认完整费用清单,已交寄时不改写原履约终态。
金额在扣款前核对采购台账、钱包和两端费用来源的共同存储边界;费用来源为 DECIMAL(20,6),单笔原币及 CNY 金额最多 14 位整数、业务输入保留 2 位小数。金额目标快照使用台账范围,正差额仍须满足单笔费用来源范围。购买金额不满足资金链容量时保留真实购买事实并显示待处理,不发起扣款。
单批节点事实由 `ll_procurement_flow` 按采购订单唯一保存;`ll_procurement_command` 保存节点请求摘要、幂等键和内部依据;预算上限变化由 `ll_procurement_budget_authorization` 留存前后金额、币种和客户凭证。购买事实与货款核定标记分开,资金结果仍从费用版本读取。节点 API 见 Lastleg `src/main/resources/openapi/procurement-fulfillment-v1.yaml`,下单与审核基础 API 继续维护在 `overseas-business-v1.yaml`。
实物明细由 `ll_procurement_receipt`、`ll_procurement_disposition`、`ll_procurement_manifest`、`ll_procurement_carton` 和 `ll_procurement_carton_source` 保存;更正只停用原实收/处置并追加新记录,历史清单及来源不删除。`ll_procurement_shipment` 以订单及运输段建立唯一约束,`ll_procurement_shipment_item` 保存当次逐箱件数、货物来源、测量、面单和运单快照。
面单版本由 `ll_procurement_label_set` 和 `ll_procurement_label_item` 保存,预估核对通过 `ll_procurement_estimate_review` 显式关联面单版本与有效预估费用。制单不修改资金,贴单不产生发运。每次交寄在订单行锁内复验当前确认清单、全部可寄原箱、实收来源和包装摘要;新面单不继承旧贴单。国内 `ll_procurement_repack` 仅允许原箱的一对一包装新版本,件数仍取原箱有效国内实收;即使新箱尺寸相同,换包装记录也使旧国内面单失效,并清除整单核费确认标记,保留已发生扣款供重新核对。
国际寄件姓名、电话及地址通过 Warehouse 的既有公共海外收货仓和有效仓详情接口读取,须有唯一作业地址及完整联系人,不由浏览器覆盖。两段交寄各自冻结收寄快照;国内寄件资料承接原国际段国内收件资料,最终客户地址变更须关联本单客户确认凭证。面单文件按本单 LABEL 分类校验,图片仅对应第 1 页,PDF 明确逐箱页码。
运输动作权限独立采用 `estimate`、`apply-label`、`ship-overseas` 和 `ship-customer`;`label` 只维护面单,不能同时获得冻结或交寄权限。上述权限均在既有采购权限前缀下,沿用现有平台角色,不引入新岗位类型。
Finance 账户操作统一按“客户账户行 → 原冻结/原扣款行”顺序加锁。结算实际金额保留原冻结金额,实际扣款取关联的 CONSUMPTION 流水;退款用独立 REFUND 流水引用原扣款,不能篡改原结算状态或使用充值类型。退款回补复用现行现金/授信归还计算,不恢复过期授信。
### 10.2 资金指令和来源合同
- `FREEZE` 预留金额;`SETTLE` 结清明确实际费用的全额冻结;`RELEASE` 释放有效冻结。
- `SETTLE_ACTUAL` 在原冻结业务身份上携带最终正额 CNY 金额,在 Finance 单事务中补差或释放余款。结果 amount 表示实际扣款,不能回传原预估。零实际费用使用 RELEASE。
- 正额货款、关税、国内运费和其他费用,由采购按费用用途在 FREEZE 成功后自动发送 SETTLE;预估国际运费绝不走该自动分支。
- 资金成功回执必须能定位原请求、客户、费用版本及实际流水;费用入池引用这笔已成功的资金事实,Finance 同客户校验实际金额后标为已结算。不得仅凭展示单号或预估金额认领资金。
- 退款业务命令需包含原成功扣款引用、独立退款编号、金额、原因和授权证据。相同退款编号换请求键不得再次回补,累计退款按原扣款串行核验。
- 已确认费用的资金请求状态与费用来源状态分开。节点准入同时检查资金终态和来源关联,不以 Outbox 已发送或 HTTP 已确认作为全部完成。
国内核费以整单节点命令确认:实际国际运费、关税、国内运费分别选择新核定值或本单已有有效费用版本;其他费用明确为不适用或逐项核定。不适用不创建虚构收费行,重新核对引用原版本不重新扣款,也不能通过省略有效费用隐藏原收费。确认时间与实际资金完成状态分别保存,寄客户仍逐笔校验资金及来源关联。
费用链更正使用 `ll_procurement_fee_correction` 保存正确原币总额、原汇率及月份、目标 CNY、确认前净实扣和差额,`ll_procurement_fee_correction_item` 关联本次产生的每笔追加或退款。输入必须是原实际费用链根;同链存在未决或尚可重试的旧调整时拒绝新目标。正差额建立独立 CNY 费用,差额费用自身汇率为 1,目标原币及原汇率完整保留在更正快照,避免由人民币分差反推原币造成误差;负差额按本链成功消费的可退余额逐笔关联,不把多次扣款合成一笔虚构原扣。退款仍由 Finance 原子校验累计上限。
未实扣费用的替代核定使用独立 `fees/{feeId}/replace-failed` 命令,要求财务调整权限。仅最新实际费用版本已明确失败、终止重试且有效冻结已释放时可替代;未决、已实扣或已有后续版本均拒绝。新费用沿用原币、业务日及汇率快照,以新的资金业务标识扣款,并由更正记录关联前后版本;原购买事实不覆盖,替代货款仍核验客户预算。普通核费不能绕过该入口重建历史费用,财务替代版本的失败重试也使用财务调整权限。
普通核费权限不能追加或退款。明确失败后的重试按原费用用途分别检查购买、预估、核费或财务调整权限;终止失败版本、目标更正及退款统一要求财务调整权限。所有命令明确携带订单版本及幂等键;缺失版本拒绝,原请求重放不能改变金额。履约已寄客户或异常关闭后,有据财务更正保留原终态,不改写历史发运。
### 10.3 服务和接口组织
Lastleg 在现有 `procurement/` 内按购买、实收装箱、运输、费用、文件及异常划分职责;统一订单查询组装详情和动作资格,不新建服务或通用流程引擎。Finance 只处理本服务账务与来源关联;采购不能直接写 Finance 数据表。
采购列表只返回订单基础信息、采购数量和履约状态,不返回旧 `inboundQuantity/outboundQuantity/inventoryQuantity` 库存式统计。删除旧 `outboundDetails` 及订单级两段承运商/运单字段;实际承运商、运单、交寄数量与时间从逐箱面单和不可变交寄记录查询,不由旧 JSON 或静态订单字段推导。初始化结构与模型同步移除这些废弃字段,实际环境结构清理由发布范围单独核对。
沿用现有平台和客户采购 API 根路径。新增操作使用明确节点命令,包含确认购买、登记/完成实收、保存/确认清单、面单维护、预估确认、贴单、两段交寄、核费、预算授权、更正及关闭。通用 PATCH 移除能绕过这些命令修改数量、运单、状态和资金的字段;不保留旧编辑行为回退。
平台详情返回服务端计算的 `actions` 与动作阻断原因,以及采购事实、箱明细、费用版本和历史。客户端使用单独的详情 DTO,仅返回第 3.5 节允许的字段,不透传平台附件、内部备注或原始资金错误。内部 ID 只用于程序关联,用户界面以采购单号、箱号、运单及费用业务编号展示。
Admin 采购保留当前独立列表/详情/编辑路由,具体操作承载按适用原型核对;Client 将采购专有详情和下单逻辑从三类业务共用组件中分离,本土卡车和散板不接受采购新增状态或字段。权限按第 5.1 节逐动作同步 Controller、IAM 种子、API 合同与前端。
异常控制保存在 `ll_procurement_control_note`:更正说明关联本单购买、实际仓、实收或交寄对象及 EXCEPTION 凭证,阻断与解除分别记录,不覆盖原说明。实际仓在已有箱明细前可受控更正当前有效仓,并保留原仓快照及原实收;已有后续实物或已结束时只追加说明和阻断,不能将货物重新归属。真实到货仍可记录,正式装箱、预估、核费和交寄校验未处理阻断。
异常关闭由 `ll_procurement_closure` 与 `ll_procurement_closure_item` 留存客户停止履约凭证、财务结论、对客摘要和每份剩余货物的去向。服务端按购买未达、原国际箱在途未达、有效实收合格/破损/多货计算待处理来源,扣除既有有效差异处置;已国际交寄的海外合格实收不再重复计为剩余货物。提交须逐来源足额覆盖且有证据,全部资金及来源关联处理结束后才能关闭。关闭不改变原购买、收货、交寄或资金事实,不新建退款、退货物流或零数量发运。
平台既有采购详情 GET 返回 `ProcurementQueryService.PlatformView`,聚合客户视图、内部购买事实、实收装箱、运输、费用/更正、异常、文件、操作记录及动作资格,页面无需逐块发起详情请求。交寄按钮的阻断原因复用实际交寄的状态校验;所有写入仍在订单锁内重新校验,详情上的可执行状态不能替代提交门禁。客户既有详情及创建响应使用独立 `CustomerView`,不再从平台详情动态删字段:只输出已确认箱明细、两段实际运单、预算/费用结果和专门填写的对客摘要,不返回内部附件、原始异常说明、审计内容和资金引用/诊断。
平台运输快照分别返回 `overseasCargo` 和 `domesticCargo`:前者为海外清单及原实收分配,后者按国内有效合格实收计算件数并使用最新一对一换包装的箱规、重量和包装记录引用。面单与交寄页面使用该权威结果;不能从海外旧箱规或采购总数推定国内可寄货物。客户 DTO 仍使用独立允许字段,不透传内部来源引用。
### 10.4 开发与验收顺序
1. Finance 原子实际结算、原扣款退款、费用来源资金关联及其事务测试。
2. 采购数据结构和命令合同,下单、审核、预算授权、购买与货款闭环。
3. 海外分次实收、差异、装箱版本、面单和预估冻结、贴单与整批交寄。
4. 国内分次实收、换包装、费用核定、实际结算和寄客户。
5. 受控更正、追加、退款、取消和异常关闭;客户端全节点和费用展示。
6. 全链路定向回归、API/权限/Mapper/SQL 合同检查,匹配版本部署后执行真实 HTTP 和两端页面验收。
各节点同时交付服务端行为、Admin 操作、Client 展示及直接受影响测试,不以“接口存在”代替完整操作。资金基础测试应覆盖账户、冻结、流水、审计及幂等记录同事务回滚,以及不同请求并发处理同一冻结/原扣款。
页面验收使用 1920×1080、100% 缩放。列表和详情按实际 Network 记录请求数:检查重复加载、逐行附加请求、重复提交、无限重试和资金处理中无界轮询;以具体页面操作和请求证据判断,不臆定所有页面统一的请求上限。本轮用户已明确授权内置浏览器登录并自动检查样式与交互,适用于本次采购流程验收。
### 10.5 客户端页面实施核对矩阵
本次页面依据为本需求第 3、5、10.3 节和现有正式路由。客户端栏目原型 `docs/悦/柏悦物流客户端/柏悦物流客户端-栏目架构图.html:977` 只定义“海外采购”业务入口,未定义新履约字段布局;不能据此宣称已有完整页面原型。按本轮“首版简单、后续可扩展”的开发授权,保留已确认独立页面承载及现有工作台视觉,扩展本次业务分区,不新增客户审批或内部文件入口。
| 页面 | 操作 | 原型/当前确认依据 | 当前实现与承载 | 本次结论 |
|---|---|---|---|---|
| 采购列表 | 查询、分页、进入详情 | 栏目原型行 977;`cross-border/routes.ts` 的采购列表及详情路由 | 共用 `BusinessOrdersView.vue` 的 QueryToolbar、DataTable,操作列在左 | 保留表格和查询布局;使用采购履约状态,去除采购库存含义的旧展示;详情通过正式路由打开 |
| 采购新建 | 新增、提交、取消 | 需求第 3.2、3.5、10.3 节;`cross-border/routes.ts` 的 `cross-border/procurement/create` | 已有独立新建路由,旧共用列表又能切换内部新建模式 | 统一由既有独立新建路由承载;明确单商品、预算和最终收件资料,白底分组表单,桌面短字段三列;取消返回列表 |
| 采购详情 | 查看、刷新、返回 | 需求第 3.5、5.2、10.3 节;既有 `cross-border/procurement/:orderNo/detail` | 独立页面、返回列表、状态及四列描述网格 | 沿用独立页面及四列资料区;增加节点时间、已确认箱清单、两段实际运单、费用及对客异常摘要;每次加载一个聚合详情请求,不自动轮询 |
| 采购详情 | 编辑、审核、核费确认、取消订单、文件预览/下载 | 需求第 3.4、3.5、5.1 节 | 客户本次无对应平台操作权限 | 不新增;客户通过客服提出变更或取消,不开放内部面单、采购/费用/沟通凭证 |
新页面按 1920×1080、100% 缩放核对。该矩阵是实施依据,不代表已经完成运行环境视觉或交互验收。
### 10.6 平台页面实施核对矩阵
按本轮用户“先修正偏移项”的要求,采购详情首屏只展示当前有权限且可执行的常规履约操作;预算/仓库更正、财务调整、取消及异常处理收纳在“更正、财务及异常处理”分组,费用更正草稿也在该组。其他不可执行的常规节点以可展开的节点及原因列表保留,不铺满首屏禁用按钮。原请求未决提示与原请求恢复入口仍直接显示,不因折叠分组隐藏;服务端资格、权限及业务门禁不变。
平台原型定向入口为 `docs/悦/货代SAAS平台后台/prototype-src/modules/07-overseas-business.html`,其中采购列表及独立编辑页承载保留;旧原型中的数量、运单和费用通用编辑方式按本需求第 3、4、5、10.3 节收敛。新增节点采用现有详情页内分区及独立操作弹框,沿用 Admin 高密度公共样式,不将原型旧字段当作新节点操作的授权。
| 页面 | 操作 | 承载与变更边界 |
|---|---|---|
| 采购列表 | 查询、分页、查看、编辑 | 保留列表及独立路由;操作列在左,使用实际履约状态;不将采购台账展示为 WMS 可用库存 |
| 采购独立编辑 | 维护内部备注、保存、取消 | 保留独立编辑页、三列只读订单摘要及备注区;只提交订单版本和内部备注,保留未保存保护及版本冲突提示;不在此修改购买对象、仓库、数量、箱单或运单 |
| 采购详情 | 查看、刷新、返回 | 单次聚合详情请求,分区显示订单、履约、费用、文件及内部历史;不自动无界轮询 |
| 采购详情 | 审核、购买、预算授权、取消 | 各自独立操作弹框;审核通过必须选择有效海外收货仓,真实购买和资金确认分开呈现 |
| 采购详情 | 分次收货、差异处置、完成收货、装箱、换包装 | 节点弹框配结构化明细表,显示原实收或原箱来源;不使用自由 JSON 输入,不将保存等同节点完成 |
| 采购详情 | 面单、预估核对、贴单、两段交寄 | 面单逐箱关联;预估冻结、贴单、实际交寄独立提交,展示服务端阻断原因;文件使用受控上传和下载 |
| 采购详情 | 国内核费、重试、费用更正、退款 | 普通核费和财务调整分别控制权限,逐项展示核定值、冻结、实扣及来源关联;待处理资金不能显示已结清 |
| 采购详情 | 更正说明、解除阻断、异常关闭 | 保留原事实,以来源、凭证和去向形成结构化记录;关闭前明确实物与资金处理结果 |
以上为页面实施边界,不表示各操作已经开发、部署或通过浏览器验收;运行验收仍按第 10.4 节逐项核对。
@@ -0,0 +1,201 @@
# 预约工作日历 V13 变更说明
## 2026-10-19 当前预约列表收敛规则
本节来自用户本次确认,优先于下文 V13 对预约列表入口、类型与承载方式的早期规定;下文数量、客户隔离、真实执行等原业务约束继续适用于各自业务模块。
- 预约列表恢复用户截图 `codex-clipboard-840bcc07-6b54-4afa-9dc7-666d09ff04f2.png` 的左侧月/周日历、右侧当天安排。类型仅为到港、排车、还柜、计划到仓;每日期格最多三条预览,完整记录在右侧查看。保留当前范围搜索和未定日期入口。
- 月视图按当月所需显示4、5或6个完整周,仅在首尾周补齐相邻月份日期,不固定追加六周。2026年10月显示9月28日至11月1日,不显示11月2—8日整周;日历查询同步采用实际展示范围,周视图仍为7天。
- 到港优先实际到港,缺实际时采用预计到港。计划到仓默认在该到港当地日期上加两个自然日,跨月和夏令时仍按日期加两天,不补造具体时刻。人工保存的整柜时间优先,已有入库计划的冻结时间保持;尚未人工维护和未建计划的默认日期随到港事实变化。该默认值属于日历日期推算,不自动写入入库计划、不充当实际到仓。人工调整复用整柜预计到仓命令、原编辑权限、版本及幂等键;已有入库计划后仍不可改。
- 排车仅指海外仓送往 FBA/客户仓的真实车次,同车多客户只展示一次;已发车按实际起运仓当地日期,未发车按计划日期,取消车次不列入活动安排。港口提柜送海外仓不作为排车类型。
- 还柜未完成按原业务截止日期提醒,完成后按实际还柜日期展示;日历不独立计算或改写还柜状态,登记进入原货柜业务。
- 用户随后明确恢复日历顶部“新增预约”:本次先支持FBA,普通客户仓不在本次范围。居中弹框选择已有货物,核对真实来源后复用原预约表单与保存接口;同起运仓、同目的FBA仓可跨客户合约,保留原写权限、版本/幂等、未知结果重试及未保存保护。货物查询栏支持可搜索、可清空的目的FBA仓下拉框;选项来自同权限范围的权威美国FBA目录,不从当前分页推算。提交查询后回到第一页,翻页沿用目的仓条件,重置恢复全部目的仓;跨页已选货物仍保留并执行同起运仓、同目的仓校验。保存成功显示真实预约编号及内容,不自动创建车次,不增加第五类日历或手工编造到港/还柜等事实。
- 入口移除全局工作待办、流程筛选、负责人分派、跟进、复核、责任交接,以及货物核实/分批/共约/共车编排入口;这些原业务在相应模块继续处理。仍由其他业务页面实际使用的精确来源或事项深链可以打开原业务表单,不恢复旧全局待办及筛选协议。
- 缺权限、来源失败或缺时区明确提示数据范围不完整,不能显示为全部完成或完整空日历。未知日期保留未定,不用浏览器当前日期、内部 ID 或假数据补齐。
代码与自动检查、部署、真实 HTTP 及人工视觉验收分别判定;本次 UI 目标仍为1920×1080、100%缩放,用户截图确认后才记录视觉通过。
确认日期:2026-10-16。用户已确认 V13 原型,并要求按现有开发分工继续实施。本文是本轮产品行为、业务约束与验收场景的正式变更依据;确认需求不表示业务代码、部署或真实环境验收已经完成。
接口和唯一文件写者继续由[开发协作契约](预约工作日历开发协作契约.md)维护。本文维护业务规则,不另建开发进度台账;实现进度由“预约”开发总控维护既有检查点,部署与整体验收事实仍归环境主契约。早期[优化方案](美国预约管理统一总览与优化方案.md)及 V11/V12 评审记录用于追溯,冲突时以本次确认和现行正式契约为准。
## 1. 确认范围与原型基线
本轮目标是:船已开后,运营从“预约管理 → 预约列表”进入“预约工作日历”,能看到所有应办事项,包括未预约、未定日期和变化后尚未处理的事项;每条工作直接给出当前可执行的下一步。
- 日历为默认首屏,提柜、接仓卸柜、送仓/FBA、用车、还空五类可勾选;日期格定高,按类型汇总,不随事项数量无限堆叠。点击数量查看并操作明细。
- 全部待办、今日需跟进、超期、未定日期、需复核不随日历月份、流程或类型筛选而遗漏。不同待办集合允许重叠;同一事项在一个结果集中只出现一次。
- 支持海外仓中转分批和整柜直送,支持不同客户同起运仓、同目的仓共用真实车次。多客户共车是已有业务能力,本轮重点补齐统一操作、变化后的续办和完整跟进。
- 不把本轮扩大成完整车队、库存或费用模块重构;不增加自动向仓库/车队发送预约、取消通知的承诺。登记联系结果与对方实际确认是不同动作。
已确认原型:`C:/Users/BY-OY/.codex/visualizations/2026/10/14/01a13a8d-e968-7962-906b-1a514792d921/appointment-calendar-guided.html`,页头 V13。确认时 SHA-256:`61902e410be755aa9cbf9fcfaa9d393bfa49dd8d592cd8773af5396e78c29836`。该文件为交互依据,不是生产 API、状态机或数据库结构;原型中的演示字段名、固定负责人、固定日期及示例数据不得直接当成业务合同。
## 2. 对象、数量与客户归属
| 对象 | 正式规则 |
| --- | --- |
| 货物来源 | 每条保留客户、稳定来源键、目的地、业务票号、货件/追踪号、柜次及核实数量/版本。沿用原 `ORDER` / `BOOKING` 来源身份,不因建订单、分批、换车而产生来源别名。 |
| 送货需求与批次 | 未约、取消安排、日期未知都不消灭仍需送货的需求。批次有稳定身份及版本;移车或重新预约不重新占一次货量。只有真实分批/合并才调整分配,并保留旧批次到当前批次的去向。 |
| 对外预约 | 预约确认号、有效覆盖范围、确认时段与预约身份分开保存。一个共同预约可覆盖多个客户的批次;不能用相同文本约号代替明确的共同预约关系。 |
| 运输 | 一个真实车次可承运多个客户、多个批次;各客户的排车/货物归属保留。送仓预约与车辆安排分别确认,不能互相冒充。后送用车待办不等于已经创建实际车次、锁定托盘或承运资源。 |
| 工作事项 | 关联权威业务对象,承担展示、跟进、复核和下一步引导,不再维护第二本可编辑数量账或另一份预约/实际完成结果。 |
按每个“客户+稳定来源+目的地”核对数量,而不是只核对总箱数:
`核实可履约总量 = 尚未分配到批次的数量 + 当前有效批次的分配数量之和`
这里的有效批次包含已经实际完成的履约数量,不能因完成后退出待办而再次变成可选余量;已被替代的历史批次不重复计入。后送批次即使没有日期或预约,其货量仍属于该批次,只能从该批次继续分配,不能再按整票新增一遍。逐来源不超分、不为负、总量不丢;未知数量保持未知,不当成 0,也不能未经核实拆分。
补箱数和各票货件号只保存预约货物核实资料,不覆盖原尾程订单;已分配数量不能被核实为更小。客户库存、托盘、订单、费用及对外可见范围仍按原客户隔离规则执行。
## 3. 两条履约流程
### 3.1 海外仓中转
开船后生成/读取本柜应办工作 → 提柜 → 海外仓接仓卸柜 → 各送货批次分别约仓及安排运输 → 真实备货、装车、发车、签收。提柜、接仓卸柜、还空按柜级稳定身份去重,不随客户数、送货批数或车次数重复生成。
实际卸柜完成后,还空按真实条件独立跟进,不等待所有送货批次完成。一柜可以分多批、多车;不同柜、不同客户的货物在符合原业务资格时也可同仓共车。
### 3.2 整柜直送
开船后 → 提柜安排及目的仓收货预约 → 同一运输链直送目的仓 → 真实卸货 → 还空。不得为了直送生成海外仓接仓/入库事项、库存或假卸柜事实。提柜和直送共用一趟运输时只计算一个真实车次,不重复约车;还空可由原车执行或转交明确接手方。
实际目的仓卸货未完成不能登记还空;交接责任不等于已还空。直接送往客户仓且对方无需预约时,保存明确的收货要求,不伪造 FBA 货件号、外部约号或“预约成功”。路线未知时先提供“确认路线”,确认后幂等生成应办清单。
## 4. 多客户同仓共车
1. “与同仓待排货物一起安排”或“按目的仓统一安排”只展示当前有资格的货物。候选以稳定起运仓/目的仓身份及真实业务资格核对,不只比较仓名;已安排或已分配的量不能重复选入。
2. 从某个后送批次进入时,只预选该批次的当前可安排量;其他客户由操作人明确加选。每票允许填写本次箱数,客户、来源和货件随货保留。
3. 共车不等于共用仓库预约。可分别保存各客户的预约结果,也可在仓库明确确认覆盖全部所选客户和数量后使用共同预约;页面必须明确显示采用哪一种方式。
4. 外部约号按目的仓执行既有唯一性规则。共约成员通过同一预约身份引用这个约号,不各自创建重复主单。其他有效预约已使用的约号不能直接填入,冒充该客户已加入共同预约。
5. 保存后逐客户显示成功、待补资料、关联失败等真实结果,提供下一步;一辆车在日历工作量中只计一次,各批送仓工作分别计数。
6. 实际车辆、司机、托盘、容量、审核、装载和发车走原 Fleet/Dispatch 资格与命令。原型中的直接登记执行仅表达流程衔接,不替代这些门槛。
## 5. 分批、缺货与后送
以甲 80、乙 160、丁 40,共 280 箱送 ONT8 为统一验收样例;每条场景独立恢复基准,不能将不同演示的数量相加。
| 变化 | 原车 | 后续需求 | 下一步 |
| --- | --- | --- | --- |
| 乙整批移出 | 保留甲 80+丁 40=120 箱;其预约不变 | 乙 160 箱保留原来源与需求,另期或未定日期 | 乙重新约仓并安排车辆;原车按剩余货量核对后继续 |
| 乙 100 箱已齐、60 箱后送 | 甲 80+乙 100+丁 40=220 箱 | 60 箱单独后送;没有目标也保留待办 | 可单送,或选择与同仓待排货物一起安排 |
| 后送 60 再选 40 安排 | 原车仍为 220 箱 | 40 箱进入新批次,20 箱仍待排;乙 100+40+20=160 | 原车客户卡片同时列出两份当前去向,各可直接继续 |
| 后送 60 与另一客户 40 共车 | 原车仍为 220 箱 | 新车共 100 箱,客户和来源分别保留 | 分别/共同约仓后确认新车,按各客户实际执行 |
“本次先送量”允许为 0,表示该客户全部移出原车留待后送;不得强迫留一箱。先送量等于全部原数量时,没有后送分配,不额外新建空批次。部分改变已经确认预约的货量,必须取得仓库对保留量和移出量的明确处理结果;剩余货物是否备妥按实际核对,不因仓库同意而自动标记货齐。
后送目标日期可空,但必须保留负责人和跟进入口。原车客户卡片追踪分配/替代关系直到当前批次;全量再分配后直接显示新安排,部分再分配后同时显示仍待排的量和已分配的去向。不能显示失效的“0 箱待办”,不能只在历史文字中记录去向,不能将同一后续批次重复列出。
## 6. 改期、取消与影响范围
普通改期、取消、缺货移出用于尚未实际执行的安排。车辆已经发车或相关货物已经执行时,进入原运输异常处理,不提供普通移车操作来抹掉事实。
### 6.1 仅处理某个客户
- 默认明确展示本客户、原车、货量、其他客户及是否共用预约;操作者选择本客户另期、取消本次安排或本次先送部分数量。
- 确认前保留原安排。已有有效预约,尤其是共同预约时,须明确仓库同意本次调整范围;未收到回复先记录待确认,不能把沟通中状态当成取消/改期成功。
- 确认后只移动该客户/该部分货物。其他客户的约号、确认时段和客户归属保持不变;原车对剩余货量及发车时间核对一次。车队已确认原时间可继续时,不无故要求其他客户重新约仓。
- 待确认变化进入持续待办;涉及当前装载或预约有效性尚未解决时,原车不能直接发车。保存输入与已确认的信息,重新进入直接续办;不能用“关闭复核”跳过未解决的业务条件。
- 原车无任何有效货物且尚未执行时,经原车辆业务取消/调整处理后关闭相应运输工作并保留历史,不留下空车待办。不能据此取消其他客户或其他仍有效的车次任务。
### 6.2 整份共同预约变更
- 页面明确区分“仅本客户”和“整份共同预约”,展示所有当前覆盖客户、数量、预约和关联车辆。以服务端当前有效成员为准,不能靠外部约号文本相等推断范围。
- 整份改期:所有覆盖成员更新为同一已确认的新时段;相关车辆核对新收货时段是否可达。无实际变化的再次保存不重复产生复核。
- 整份取消:旧预约失效,保留旧计划、确认信息、取消原因和历史;当前确认及已经失效的目标日期从活动安排中清除,未重新确定的进入未定日期。全部未完成货物需求保留,各关联车辆列为待核对。
- 已取消的预约不能选“保留原预约”直接恢复有效。车辆原安排是否仍可执行可单独核对,但发车仍须所有相关收货/备货条件成立。
- 真实变化只影响直接关联且已经安排的事项;尚未安排的继续待安排。复核动作本身不再触发另一轮复核;处理旧影响版本不得清掉后来产生的新变化。
### 6.3 取消后的占用边界
本轮“取消”指取消本次预约/运输安排,不是取消订单或客户撤销全部运输需求。
失效预约释放其有效预约覆盖和绑定;仍需履约的批次数量分配继续存在,或在同次变更中转到明确的后送批次。不能把同一箱数同时留在原批次并重新作为整票可选余量,也不能先清空需求再等待以后人工补建。已完成数量保持不可再次分配。
取消预约不回退库存,不自动注销整辆车。已有正式排车、托盘或运力占用时,由其权威业务按真实关联调整;工作事项仅读取结果。恢复/重新预约仍重新核对来源、当前分配、版本和唯一性。
## 7. 移出后的重新预约与整组重约
### 7.1 单客户或后送批次续办
结果页直接提供“继续给本客户约仓”和有资格时的“与同仓待排货物一起安排”。从未定日期、搜索或原车客户卡片再次进入,也到达同一份当前需求。
单送路径为:核对货物 → 记录仓库回复/确认 → 继续安排本批车辆 → 核对真实备货条件 → 原业务发车、签收和运输完成。未约成可以保存计划和联系结果,不必编造时间;已取得确认后直接进入车辆安排。确认后的货物不能重新从“待排货物”入口新增一遍;车辆关联沿既有安排继续。
重新预约不会重新生成一份相同货量。完成后退出未完成待办,原批次和运输记录仍能查到;其他尚未完成的后送、原车或还空工作继续保留。
### 7.2 整份取消后的重新预约
1. 提供“重新预约这组货物”,展示本次仍需重新约仓的客户、批次与数量。已退出、已单独另约、已完成或正在处理其他变化的成员不被静默纳入;页面说明其当前去向。
2. 可以一次填写一个共用的新预约,也可以一次填写各客户独立预约。共同预约必须有仓库明确确认的客户和货量覆盖依据;分别预约不能通过重复填写相同约号绕开共同预约确认。
3. 沿用现有批次及可继续使用的原车,保存新有效预约关系;不重复分批、不重复占量、不仅为重约再创建一辆车。旧取消关系留历史,新共同预约使用新的有效关联身份。
4. 退出客户不能直接填写其他客户仍使用的旧约号,生成不同时间的孤立预约。若确需加入已有共同预约,必须经显式范围调整和仓库确认;普通填写约号不完成该操作。
5. 保存后主要下一步是“核对本车发车安排”。核对全部当前客户的收货时段和车辆条件;不能让车辆先于尚未完成的重约被标记可执行。后续再次整份改期/取消只作用于新的有效覆盖范围。
## 8. 未定日期、跟进与操作简化
- “没有作业日期”和“没有跟进日期”是不同含义。有跟进日仍可属于未定日期;不能把催回复日期填成送货日期。
- 日期留空时保留需求、负责人、联系记录及下一步,显示在全局未定日期/全部待办;取消、分批、部分失败不能让它消失。缺负责人或下一次跟进安排时明确提示补齐,不假定原型中的固定人员是生产默认值。
- 日期有目标但未约成时,日历按目标展示并标明未落实;确认时间、目标窗口和实际时间分别保存。实际发生后按权威实际日期展示,改期不移动历史事实。时间、时区、跨日、DST 和缺失原事实的处理沿开发协作契约第三节。
- 每个结果页优先给一个主要下一步,其他去向为明确次要入口;缺货在车辆执行入口可直接打开对应客户的“调整本次装载/移出本车”,不绕到其他客户或目的仓总列表。
- 未落实且只涉及本批货物时展示普通计划表,不展示多余的共车变化表单;独立车辆按钮称“继续安排本批车辆”,实际共车才称共用车辆。
- 返回保留原日期、柜、批次、筛选、分页和原事项上下文。旧批次已全部转入新安排时直接到新安排;历史仍可独立查看。
## 9. 失败、重试与权限
以下是正式实现和集成验收要求,不能用原型浏览器检查代替证明:
- 按原来源核实量、批次、预约范围及车辆关系版本校验。并发编辑、分批或共车成员变化时拒绝过期提交,保留用户输入,重新展示实际范围;服务端保证不超分。
- 同一用户操作使用持久化幂等身份;同键同内容返回原结果,异内容拒绝。超时/断网导致结果未知时沿原请求查询或重试,不自动当失败新建批次、预约或车辆。
- 货物已保存但关联车辆失败时,返回成功批次及准确失败步骤;成功货物保持已占用,重试只补失败步骤,不能重新建批/建车,也不能把已退出的客户重新挂回原车。
- 一次调整中原数量、后送数量、去向和待办必须一致。跨业务步骤未全部成功时明确显示尚未完成的部分和下一步,不宣称全部成功;不得产生既无原需求又无后续需求的窗口。
- 平台列表权限包含详情只读,写权限由各权威业务核验;多客户管理仅在授权平台范围内进行,客户侧只能看自己的货物。无权限、来源不可用、校验冲突均给明确原因,不能伪造成功或“0 项”。
- 真实备货、托盘、装载、发车、签收、还空及运输完成仍由原业务事实决定。通知或联系记录不能代替这些事实。
## 10. 开发接口交接与唯一写者
不复制旧接口、不建立前端数量账、不直接照搬原型对象。已有工作事项 v1 继续使用[开发协作契约第三节](预约工作日历开发协作契约.md#3-工作事项-http-接口-v1);本轮新增语义由真实业务生产者先补 DTO/OpenAPI 与定向测试,再由消费者接入。精确 HTTP 路径、字段与错误码以生产者冻结的真实合同为准,本文不虚构已可用端点。
| 必须交付的语义 | 生产者与消费边界 |
| --- | --- |
| 当前批次逐来源分配、剩余量、全部/部分再分配去向、版本 | 预约核心提供权威数据;工作事项只读关联,前端据其显示当前去向,不凭历史文字推断。 |
| 单客户/整份共约变更的当前范围、旧安排、新安排、受影响客户/车辆、未完成原因 | 预约核心与原预约写者统一业务命令和版本;工作事项返回准确受影响事项与复核版本。 |
| 整份取消后的待重约成员、已排除成员及原因、共同/独立重约结果和新的有效预约关联 | 预约核心主导合同;保留原批次及运输关系,消费者不能自行造共同预约身份。 |
| 幂等结果、逐步骤成功/待补/失败、后续目标及可重试动作 | 各命令生产者返回真实结果;前端保留输入并继续失败步骤,工作事项不制造成功兜底。 |
| 允许动作、唯一主要下一步、缺项/阻塞原因、关联与去向 | 工作事项后端提供白名单动作和稳定目标引用;前端映射既有入口/表单。跨域业务写入不能塞进通用“改状态”命令。 |
现有三任务不增加、不更换工作区、不扩大其他业务写权:
| 现有任务 | V13 继续工作 | 依赖及停止点 |
| --- | --- | --- |
| “预约” `01a13df2-c639-7560-a3e2-30bc23a579b3` | 开发总控兼预约核心:核对已实现差异,先冻结数量/去向、预约范围、取消和重约合同;协调原预约写者,统一共享文件、检查点及验证窗口 | `InboundFbaAppointmentService` 及核心预约/分批测试已明确交回总控;工作适配和 Dispatch/Fleet 仍由后端专项独占。后续移交须明确唯一写者,不按同文件不同方法并写。 |
| “工作事项后端” `01a13e1c-9101-7a43-8445-771685ff315e` | 完整待办、未定日期、准确影响集合、复核版本、下一步、真实车辆/预约同步;负责本批已移交的原域适配与直接测试 | 不另建数量分配账;先完成可独立部分,新增核心合同冻结后接入。共享 DDL、IAM、Firstleg 和公共门禁仍归总控。 |
| “预约页面前端” `01a13e1c-db36-73e3-a231-d6649c51664b` | 按 V13 完成范围选择、后送续办、当前去向、整组重约、结果与失败续办、未定日期入口和上下文;更新直接测试及操作矩阵 | 不猜后端字段、未交付接口不做假成功;先做现有合同可支持的部分,新增写入按冻结合同接入。保留已有页面和弹框改动。 |
精确文件路径、共享文件归属及串行构建窗口沿协作契约第五节。总控负责收集三个任务的差异、接口准备情况和直接验证证据,不能仅转述“已收到”。本轮用户授权文档同步和继续开发;部署、SQL、测试环境写入等不因本文新增授权,已有另行授权由对应开发总控按原范围核验。
## 11. 最小验收矩阵
HTTP 性能门槛(2026-10-16 用户确认):本预约链路涉及的每个接口、每次验收请求,从客户端发起到完整响应体读取结束均不得超过 1,000ms;同时独立校验 HTTP 状态、预期业务结果和数量/状态事实。不能以平均值或 P95 代替逐请求门槛,也不能把快速返回的同步中、非预期错误或缺少计时当作通过。预期拒绝场景须核对准确业务码,仍计入耗时。保留首次、超时、失败及重试记录,网络超时结果未知时先回查,不能盲目重放写操作;报告标明场景、方法/路径、耗时、requestId/traceId、运行版本及尚未覆盖项。HTTP 通过不代替页面验收,单轮全部达标也不构成任意负载下的性能保证。
| 编号 | 场景 | 必须结果 |
| --- | --- | --- |
| V13-01 | 乙 160 箱取消本次安排后重新约仓、配车、发车、签收、结束运输 | 原车甲丁 120 箱及其预约不变;乙来源和数量唯一;完成后待办退出、记录可查。 |
| V13-02 | 乙 100 先送、60 后送,后送独立执行完成 | 原车 220 箱;乙始终 160;后送未定日期可反复进入直到完成,不重复创建。 |
| V13-03 | 从后送入口选本批 60,加另一客户 40 共车 | 初始只选 60;新车 100,客户来源和预约结果分开;约仓、发车、各客户签收及运输完成可衔接,原车仍 220。 |
| V13-04 | 后送 60 仅选 40,另 20 待排 | 原车卡片各显示 20 待排和 40 新批一次,直接可操作;20 持续留在未定日期并可再次安排,乙各批始终合计 160;不显示失效 0 箱或遗漏已分配去向。 |
| V13-05 | 全部后送量再分配后从旧入口返回 | 直接找到当前新批次及车辆;重复点击/重试不重复占量,历史可追溯。 |
| V13-06 | 单客户未收到仓库回复;先记待确认再续办 | 原预约保留,输入可续办,相关未解决变化阻止误发车;确认后仅处理目标客户。 |
| V13-07 | 单客户从共约退出,填其他客户仍使用的旧约号 | 服务端拒绝孤立重约,不改其他成员;正确新约可继续;校验失败保留输入。 |
| V13-08 | 整份共约改期 | 当前全部覆盖客户一致更新,影响车辆清楚;核对一次,无变化保存不反复复核。 |
| V13-09 | 整份共约取消并重新共约 | 清失效目标/确认,保留原批次与原车;一次确认覆盖范围,形成新有效关联;再次整份变更按新范围。 |
| V13-10 | 整份取消后分别重约,或甲先单独另约再办理剩余组 | 独立约号/时段分别保存;已另约甲排除且不被覆盖;车辆核对所有当前时段后才能执行。 |
| V13-11 | 货没齐,保留量为 0;原车最终无有效货物 | 全部货量继续待办,不强留一箱;其他客户不被移动;无货原车按原业务取消/调整后正确关闭。 |
| V13-12 | 未定日期关闭后再进、换月、取消类型勾选、返回分页 | 需求和跟进不丢,送仓/用车各按稳定身份显示;下一步及返回上下文准确。 |
| V13-13 | 部分成功、关联失败、超时结果未知、重复提交、并发变化 | 复用原成功结果,只重试未完成步骤;不超分、不挂回已退出成员,过期版本不能清除新复核。 |
| V13-14 | 只读/跨客户权限、来源失败、缺时区、跨日与 DST | 权限及时间按正式合同校验;未知/失败不伪造零值、日期或成功;已有真实事实保留。 |
| V13-15 | 中转多批、整柜直送、还空转交及已发车异常 | 柜级工作不重复;中转还空不等尾程送完;直送无海外仓入库,实际卸货才可还空;转交新车队须重新明确接手,原车队结果不沿用,未落实继续跟进;发车后不走普通移车取消。 |
V13 本地原型已走过多客户变化、后送单送/共车、部分再分配、整份取消重约、约号冲突与返回续办,相关浏览器检查及原有 24 项原型回归通过。可追溯脚本位于原型同目录:`check-v11.cjs`、`check-v12.cjs`、`review-rebook-v13.cjs`、`review-partial-v13.cjs`、`review-v13-shared-rebooking.cjs`、`check-v13-usability.cjs`。这只是交互证据;尤其 V13-13/14 的真实权限、持久幂等、并发、外部接口和完整时区规则仍须生产代码和集成验证。
交付时分别列出业务代码、定向检查、部署清单和待真实验收项;Admin 人工视觉验收按 1920×1080、100% 缩放。不得把原型确认或本地检查通过写成环境已上线、全链已验收。
@@ -0,0 +1,221 @@
# 预约工作日历开发协作契约
建立日期:2026-10-15;V13 确认同步日期:2026-10-16。用户已确认 V13 原型,正式业务变更见[预约工作日历 V13 变更说明](预约工作日历V13变更说明.md)。本文继续维护接口、数据归属和文件边界,不重复维护产品规则或作为已实现说明;当前部署与验收事实只维护环境主契约。
本文承接[预约优化方案](美国预约管理统一总览与优化方案.md),日历首屏、多客户共车、分批后送、改期取消、重新预约与完整待办的确认行为以 V13 正式变更说明为准;不扩展为拼车、车队或海外仓的全面重构。任务身份与唯一写者见[协作登记](../独立任务协作登记.md)。
当前开发总控为用户明确指定的 `01a13df2-c639-7560-a3e2-30bc23a579b3`,负责开发设计、任务调度、接口对齐、共享集成、开发检查点及验证收口;原型对话 `01a13a8d-e968-7962-906b-1a514792d921` 只负责业务梳理、原型和变更文档。用户再次明确:设计确认后交开发总控安排,不由原型对话继续派工或跟踪开发。本文“总控”均指当前开发总控。两个专项保留原范围,精确触点以第五节为准。
## 1. 输入与共同目标
原型只读入口:`C:/Users/BY-OY/.codex/visualizations/2026/10/14/01a13a8d-e968-7962-906b-1a514792d921/appointment-calendar-guided.html`,当前确认交接为 V13,确认指纹见正式变更说明第一节。它承载交互示例,不作为真实 API、数据总量或权限来源。
- 实际开船后,所有必需工作进入统一事项范围,未预约、未定日期也有记录与负责人跟进;不能等创建预约后才出现。
- 默认进入“预约工作日历”。月格固定高度,提柜、接仓卸柜、送仓/FBA、用车、还空五类勾选显示数量,点击数量进入明细。到港参考单独开关,不计工作量。
- 全部待办、今日需跟进、超期、未定日期、需复核独立于月历月份、流程和类型勾选;全局统计由服务端计算。明细明确显示其范围,不能把月历条件偷偷带入全局待办。
- 目标日期、对方确认时间、实际完成时间分别保存。按作业地点时区落日;无日期进入未定日期区,不伪造日期或 00:00/09:00。
- 主按钮直接给下一步,返回时保留原柜、批次、日期和筛选;查看当前项与跳到前置事项是两个明确入口。
## 2. 数据归属与两条流程
| 业务 | 本轮约束 | 唯一生产者 |
| --- | --- | --- |
| 来源/核实资料/数量分配 | 保留客户、原来源、目的地及核实版本;补箱数和各票货件号只写预约核实资料,不覆盖原订单;并发按原来源加锁,总分配量守恒 | 预约核心任务 |
| FBA 预约申请、确认、取消、分批合并 | 沿原预约写服务执行;取消预约保留工作需求、历史和后续跟进;分批不能只移除原整票唯一约束 | 预约核心任务 |
| 工作事项/路线/跟进/复核 | 工作关系、未安排需求、责任和操作入口由工作事项模块维护;已有业务计划和实际事实只关联,不另建第二份可编辑数量或预约结果 | 工作事项后端 |
| 提柜计划和实际提柜/还空 | 以 Firstleg 原业务命令及事实为准 | 预约核心任务协调原域最小适配 |
| 实际接仓卸柜 | 以真实海外仓/PDA 收货为准,不能由事项勾选完成代替 | 原海外仓业务;本轮只读消费 |
| 车辆计划、出车、完成 | 以 Fleet/Dispatch 原业务命令及事实为准 | 工作事项后端维护本轮 Lastleg 原域适配及直接消费者 |
| 客户仓无需预约、还空责任交接 | 保存明确收货要求、责任及交接历史,不生成假确认号、不改提柜承运历史;实际还空仍走 Firstleg | 工作事项后端保存要求和责任,核心任务适配实际执行入口 |
中转:同柜共用提柜、接仓卸柜、还空;每个送货批次独立关联收货预约与用车,可以一柜多批、多车,也允许同一真实车次覆盖多个批次。批次变更不能重复生成柜级工作。实际卸柜后即可按真实条件还空,不必等待全部尾程送货完成。
直送:没有海外仓接仓卸柜事项;提柜、目的仓收货/卸货、运输、还空形成关联,可同车执行,也可转交独立还空。不得调用会建立海外仓库存的 PDA 入库命令来证明直送卸货。现有 Firstleg 还空若只认可海外仓卸柜,核心任务必须补真实目的仓卸货依据及守卫,未补齐前保持明确阻断,不能把事项状态写成完成。
路线未确认:显示一条“确认路线”需求,确认后事务内幂等生成对应清单,并立即可查询。已执行的路线不能通过切换选项抹掉事实;有安排时必须先评估关联影响。
稳定身份:柜级事项用柜次内部标识与类型去重,送货/用车需求用不可变 requirementKey/batchKey 关联。原来源键沿用 `ORDER:` / `BOOKING:`;不得用柜号文本、目的仓名称或可变预约号作为唯一键。未分批阶段先有送货/运输需求;真正分批后以明确的替代关系衔接,旧需求不和新批次重复计数,也不能消失但未生成后续。批次、预约、车次的内部键仅用于关联,界面展示业务号,缺失显示“—”。
事项完整来源不能直接复用目前仅 FBA 的 cargo 查询或排除完成订单的 containers 查询。新后端负责独立覆盖核对:已开船无海外仓绑定、非 FBA 目的仓、未知路线、货已送完但柜未还空均须保留。不得靠前端翻完所有页拼全局统计;GET 不隐式写库。生成/同步须有可验证的服务端幂等入口,不能依赖用户先打开某个柜。新增 Firstleg 提供端触点先交总控确认精确文件后由核心任务实施。
## 3. 工作事项 HTTP 接口 v1
平台路径前缀:`/api/platform/v1/last-leg/appointment-work`。沿用项目 ApiResponse/PageResult、鉴权与分页约定;平台列表权限包含详情只读。新后端同时维护 `appointment-work-v1.yaml` 与 Controller/DTO,不通过多路径或别名兼容旧草案。
| 方法与路径 | 输入 | 输出与口径 |
| --- | --- | --- |
| GET `/calendar` | `from`、`to`(当地日期,均包含);可选 `flow`、重复 `types` | `CalendarResult`,整个区间的日聚合,不能按明细分页结果算数量;最大 62 天 |
| GET `/summary` | 无月历筛选参数 | `Summary`,当前权限可见的全部活动事项;跨月份、类型和路线 |
| GET `/items` | `view=ALL/FOLLOW_TODAY/OVERDUE/UNDATED/REVIEW`,`page`、`size`;明细可显式传 `date/flow/types/containerBookingId/bucket/keyword` | 项目分页结构的 `WorkItem`;全局卡片调用不传月历条件;无 date 的 ALL 为全部未完成事项,有 date 的 ALL 包含当日已完成事项;bucket 对应日历互斥统计桶 |
| GET `/items/{workItemKey}` | 稳定事项键 | `WorkDetail`,当前项、前置/后续、原业务引用和历史 |
| POST `/items/{workItemKey}/commands` | `command`、`expectedVersion`、`idempotencyKey`、判别式 `payload` | `{item, affectedWorkItemKeys}`;成功后刷新摘要与当前日历;版本冲突 409,刷新后保留用户输入 |
`flow` 枚举 `TRANSFER/DIRECT/UNKNOWN`,省略为全部。`types` 为 `PICKUP/WAREHOUSE_RECEIPT/DELIVERY/TRANSPORT/EMPTY_RETURN`;未知路线需求为 `ROUTE`,独立保留在全局待办中,不因五类勾选被遗漏。日历无条件命中时返回空聚合,数据源不可用不能返回伪造零值。
DTO 冻结的共同字段:
```text
WorkItem
workItemKey: string, version: integer
type, flow: 上述枚举
title: string, businessNo: string|null
containers: ContainerReference[]
requirementKey: string|null, batchKey: string|null, batchNo: string|null
originName: string|null, destinationName: string|null
planStatus: UNPLANNED|TARGET_SET|AWAITING_REPLY|CONFIRMED|NOT_REQUIRED
executionStatus: PENDING|IN_PROGRESS|COMPLETED
reviewRequired: boolean
target: Slot|null, confirmed: Slot|null
actual: Actual|null
calendarDate: YYYY-MM-DD|null
dateBasis: ACTUAL|CONFIRMED|TARGET|NONE
timezone: IANA zone|null
owner: {id: string, name: string}|null
followupDate: YYYY-MM-DD|null, overdueReasons: string[]
allowedActions: Action[], nextAction: Action|null
blockReasons: string[], missingFields: string[]
Actual = {occurredAt: Instant|null, localOccurredAt: LocalDateTime|null, timezone: IANA zone|null}
Slot = {date: YYYY-MM-DD, startTime: HH:mm|null, endDate: YYYY-MM-DD|null, endTime: HH:mm|null, timezone: IANA zone|null}
ContainerReference = {containerBookingId: string, bookingNo: string|null, containerNo: string|null}
SourceReference = {customerId: string, sourceKey: string, destinationKey: string|null}
Action = {code: ActionCode, label: string, targetWorkItemKey: string|null, target: ActionTarget}
ActionCode = VIEW_DETAIL|SAVE_PLAN|REQUEST_BOOKING|RECORD_CONFIRMATION|CHANGE_BOOKING|CANCEL_BOOKING|
VERIFY_CARGO|EDIT_BATCH|ARRANGE_TRANSPORT|RECORD_EXECUTION|CONFIRM_ROUTE|SAVE_FOLLOWUP|
RESOLVE_REVIEW|SAVE_REQUIREMENT|HANDOFF_RETURN|ACCEPT_RETURN|VIEW_HISTORY
ActionTarget 是按 kind 判别的联合:
WORK_COMMAND {command: 工作命令枚举}
CARGO_VERIFICATION {source: SourceReference}
FBA_APPOINTMENT {appointmentId: string|null, batchKey: string|null, sources: SourceReference[]}
FIRSTLEG_CONTAINER {containerBookingId: string}
FLEET_TRIP {tripId: string|null, batchKeys: string[]}
WAREHOUSE_RECEIPT {inboundPlanId: string|null, containerBookingId: string}
READ_ONLY {references: BusinessReference[]}
WorkDetail = {item: WorkItem, relatedItems: WorkItem[], references: BusinessReference[], history: HistoryEntry[],
review: {version: integer, reasons: string[]}|null,
requirement: {bookingRequired: boolean, receivingRequirements: string, reason: string|null}|null,
returnHandoff: {version: integer, from: Responsibility, to: Responsibility,
status: PENDING_ACCEPTANCE|ACCEPTED, reason: string}|null}
Responsibility = {kind: USER|SUPPLIER|EXTERNAL, id: string|null, name: string}
BusinessReference = {kind: string, key: string, businessNo: string|null, label: string}
HistoryEntry = {occurredAt: ISO instant, operatorName: string|null, action: string, summary: string}
Summary = {all: integer, followToday: integer, overdue: integer, undated: integer, review: integer}
CalendarResult = {from: YYYY-MM-DD, to: YYYY-MM-DD, total: integer,
counts: BucketCounts, days: DayAggregate[]}
DayAggregate = {date: YYYY-MM-DD, total: integer, typeCounts: Map<type,integer>, counts: BucketCounts}
BucketCounts = {pending: integer, confirmed: integer, noBookingRequired: integer, review: integer, completed: integer}
```
Slot 的 `date` 为开始日期;`endDate` 与 `endTime` 必须同时有值或同时为空。结束不能没有开始时间:填写结束日期/时间时,`startTime` 必填。完整结束时间必须严格晚于开始时间,不允许相等;跨日必须显式填写结束日期,不能因为结束钟点小于开始钟点就自动推断次日。只有日期、没有开始时间时,结束日期和结束时间都为空;前后端按同一规则校验。例如开始 `2026-10-15 23:00`、结束 `2026-10-16 01:00` 可以明确表达跨日;仅填写结束 `01:00` 而未填结束日期应拒绝。
时间事实扩充合同已冻结:`Actual` 非空时,`occurredAt` 与 `localOccurredAt` 至少一种有值。`occurredAt` 表示绝对时间(Instant),`localOccurredAt` 表示原业务保存的无偏移当地时间(LocalDateTime)。原业务只有 local 实际事实且没有时区时,直接保留其当地日期用于日历,`timezone=null`,并在事项 `missingFields` 中标记 `SOURCE_TIMEZONE`;不得给 local 时间附加 `Z` 或伪装成 UTC,也不得从服务器、浏览器或计划时区推导实际时间。缺少时区不能抹去真实完成事实或让事项回退为待完成;有 local 实际时间时继续按实际日期展示,不能退回目标/确认日期。
跨地点实际先后比较必须基于可确定的绝对时间。原提柜/还空只有无时区 `LocalDateTime` 时,不能直接与有 IANA 时区的直送目的仓当地钟面值比较先后,也不能擅自套用目的仓或其他时区。真实提柜存在、全来源真实卸货完成仍是直送还空的硬门槛;缺少源时区时,跨地点实际先后尚无法证明,不能把时序校验记为已通过,也不能因此跳过真实业务前置条件。
多目的地直送的完成时间选择各目的地真实完成时间中最晚的 `Instant`,不按当地钟面值取最大。72 小时提醒按基准 `Instant` 之后的绝对 72 小时时长计算,跨夏令时(DST)也保持相同时长,不能以当地日期加三天或当地钟面差值替代。
来自原业务的 `Slot.timezone` 允许为 null,并同样标记 `SOURCE_TIMEZONE`;保留原日期与时间,不擅自转换。新 `SAVE_REQUIREMENT` 的用户输入仍要求有效 IANA 时区:只要提交非空 `target`,`target.timezone` 就必填,不能用原业务读取允许空值的规则放宽新录入校验。合同冻结不代表实现、部署或验收已完成。
内部 `ContainerSource` 的时间字段扩充如下(其余既有字段不变):
```text
departedAt: Instant|null
departedLocalAt: LocalDateTime|null
sailedEvidenceLocalAt: LocalDateTime|null
```
三种时间至少一种有值。`departedAt` 或 `departedLocalAt` 是确切开船时间;`sailedEvidenceLocalAt` 仅证明存在实际发生且节点序号大于等于开船节点的事实,可用于确认已开船来源资格,不能显示为确切开船时间,也不能复制成 `departedAt`/`departedLocalAt`。仅有后续实际节点证据时,保留证据及其语义,不能把该节点发生时间冒充开船时间。
所有统计按稳定事项键去重;全局五项统计是不同集合,允许重叠,不能相加作为工作量。日历五个 BucketCounts 互斥,依次按已完成、需复核、已确认、无需预约、其余待安排归类,相加等于 total;无需预约单独表达,不能冒充已确认。同一真实车次在一天按一项运输工作计数,关联批次在明细中展示;批次送货工作仍各计一项。containers 保存全部关联柜,按任一关联柜筛选均能命中,共享车次仍只计一个事项。keyword 仅过滤当前明细,匹配业务号、柜号、批次号和地点,不影响全局摘要。`calendarDate` 优先实际、确认、目标;日期已过而未完成进入超期,不能从全局消失。事项无日期但有跟进日期仍属于未定日期;“今日跟进”按该事项作业当地今日判断,无地点时使用明确的业务默认时区并展示口径,不能取服务器默认时区。
Action 的 code/target 是白名单业务动作,不下发任意 URL 或 HTTP 方法。前端映射既有入口或工作命令表单;不能只凭 code 发车/完成,原业务命令仍复核权限、版本及前置事实。缺权限可以看详情和明确原因,不能以禁用按钮替代完整下一步说明。首屏一个主要下一步,其余放详情;若需要先处理其他事项,targetWorkItemKey 指向前置项,关闭后回原上下文。
工作命令只覆盖工作模块自身拥有的数据:
| command | payload 必需语义 | 边界 |
| --- | --- | --- |
| `CONFIRM_ROUTE` | `flow=TRANSFER/DIRECT`,`reason` 可选 | 核对业务事实、版本与已有安排,事务幂等生成清单 |
| `SAVE_FOLLOWUP` | `ownerId`、`followupDate`(可空)、`note` | 只写跟进;不能清除未接手、未预约或未完成需求 |
| `RESOLVE_REVIEW` | `reviewVersion`、`note` | 对已展示的影响版本复核;若原安排本身需改,先走原业务命令,不能用复核代替改期 |
| `SAVE_REQUIREMENT` | `target: Slot|null`、`bookingRequired: boolean`、`receivingRequirements`、`reason` | 非空 target 必须填写有效 IANA timezone;仅用于原业务尚无计划实体的接仓需求、客户仓收货要求及还空目标;FBA、提柜、车次计划仍写原模块;无需预约必须有明确收货要求依据 |
| `HANDOFF_RETURN` | `recipient: Responsibility`、`reason` | 保留原预约、原责任与交接记录;新接手未确认仍待办;重复提交不重复交接 |
| `ACCEPT_RETURN` | `handoffVersion`、`note` | 服务端核验当前责任与有效转交版本;用户本人可接手,外部承运方由具备写权限的运营记录明确反馈依据,保留真实操作人;只确认责任,不等于实际还空 |
服务端拒绝不支持的 command/payload,不提供通用“改状态/标为完成”。跟进、复核使用 `platform:appointment:followup`;路线、缺失计划要求及责任转交使用新写权限 `platform:appointment:manage-work`,接手操作还需身份约束;读取使用 `platform:appointment:list` 并核验关联来源的读取资格。权限种子/菜单绑定由总控集成,不通过移除鉴权让前端联调。
首次设置目标、首次同日落实和首次配车建立基线,不触发无意义复核。真正改期/货量或执行关系变化仅标记已有相关目标或已落实的下游;未定日期、尚未安排的项继续待安排。复核动作本身不再传播一轮复核;旧影响版本不能覆盖新变化。取消预约不取消工作需求。普通回复、复核、取消不能清除还空转交待接手提醒。
## 4. 预约核心向消费者提供的边界
已落源码的货物核实接口可据此并行消费,但仍须测试通过才能作为完成交付:
- GET `/api/platform/v1/last-leg/appointment-planning/sources/{sourceKey}/cargo-verification`,query 为 `customerId`,可选 `destinationKey`。返回 `Context{source, verification, allocatedPackages, unknownAllocationCount, effectivePackages, availablePackages, sourceChanged, allowedActions, blockReasons}`;可分配数无法确定时为 null,不得显示为 0。
- POST 同路径,query 为 `customerId`;body:`destinationKey, expectedSourceVersion, expectedVersion, packageCount, shipmentReferences[], remark, idempotencyKey`。返回 `Verification{version, sourceVersion, destinationKey, sourcePackages, packageCount, shipmentReferences[], remark, operatorName, verifiedAt}`。未知原箱数可保存经核实箱数,已知原箱数不能超出,已分配量不能被覆盖到更小;不改原订单。
- source 字段以 `AppointmentSourceService.Source` 和 `appointment-cargo-verification-v1.yaml` 为准;现有 `VERIFY_CARGO` 只代表核实能力,不代表分批已开放。
分批能力以实际 Controller/DTO/OpenAPI 和直接验证为准,不得以旧整票 preview/create 假定 V13 已全部具备。核心任务核对并冻结本轮新增或调整的合同,必须包含稳定 batchKey/version、每个 customerId/sourceKey/destinationKey 的分配量、核实版本、来源版本、幂等键、取消/替代关系,以及所影响的批次/事项引用;对同仓合并保留逐票来源,不把客户归属抹平。新工作模块通过单向只读适配获得批次身份和覆盖,不能回调形成包循环;原业务命令成功后按相关键重新读取/协调工作项,不建立第二本数量台账。
本轮 V13 接口补充按正式变更说明第十节核对:全部/部分分配去向、当前共同预约范围及版本、待重约和排除成员、失效预约与仍有效数量分配的边界、逐步骤结果及受影响事项。沿既有真实合同补齐,不照搬原型字段名,也不另建同功能端点。具体新增字段、动作和错误码由生产者先冻结并同步消费者。
V13 生产者与消费者使用下列明确边界;这是接口合同,不表示已部署验收:
- 批次上下文沿 `GET /appointment-planning/batches/{batchKey}`,`currentBatches` 返回全部当前去向;`originalSourceRefs` 保留当前和已移出货物的客户、原来源、目的地,仅用于过滤当前去向。可写分配量仍取 `sources` 及服务端资格,不能将历史来源重新作为可用余量。
- 收货范围命令归 `inboundplan/receiving/`,HTTP 根为 `/api/platform/v1/last-leg/appointment-receiving`;具体七个读写入口、字段与权限以 `appointment-receiving-v1.yaml` 为准。稳定批次、独立收货预约及真实车次是不同身份。共同或独立重约产生新的有效预约关系,旧取消范围保留历史。
- 待确认变化提交 `ownerId`,平台人员目录校验身份并给出姓名;响应 `Pending.followup` 保存权威姓名及可空跟进日期。后送批次与再次分批由工作域继承负责人和跟进记录,不将自由文本当账号,不将跟进日代替作业日。合批遇到同客户不同跟进安排时须先明确统一,不能猜选覆盖。
- `FbaAppointmentTransportPort` 负责真实移货;`FbaAppointmentExecutionPort` 按客户、批次及原履约证据给出重约资格。`Book.executionVersion` 绑定涉及批次的执行事实,写入只核对所选客户;同批已完成客户不阻断未完客户重约。锁顺序为车次、排车/执行、批次,取得批次锁后再次读取执行版本防止间隙新增关联。
- 确认变化同事务核平原量、后送量及运输关系;失败整体回滚。撤回未生效变化不改货量、原确认或车辆,不因运输开始而失去撤回入口,仍校验变化版本及幂等。保存后的独立约仓、配车失败只续办该步骤,不重复创建已成功批次。
新增或调整部分采用阶段门禁:生产者先产出真实合同与直接测试,消费者再接写入;现有已冻结能力及不依赖新增接口的工作继续并行。生产链不得用 Mock、空数组或成功兜底假装未交付能力;缺依赖在开发交接中列明,不向用户呈现不可用的假成功按钮。
- 同批部分客户已正式确认时,其余客户通过 `POST /api/platform/v1/last-leg/appointment-receiving/plans` 保存本客户未确认计划。请求 `Plan` 使用 `member(batchKey,batchVersion,customerId)`、`details`、`executionVersion` 和幂等键;只允许 `PENDING`/`FAILED`,正式确认字段必须为空,目标日期可空,未约成须说明原因。`Context.plans` / `BatchReceiving.plans` 返回权威客户计划,存在但目标为空表示真实清空,不回退其他客户日期。计划不占用新的货量、不形成有效收货确认、不修改其他客户确认。当前计划归核心 `ll_fba_receiving_plan`,工作域仅作投影;批量读取为三条有界查询。
- 整组重约允许明确选择本次客户子集。跨批次组只选部分批次时,通过只读 `POST /api/platform/v1/last-leg/appointment-receiving/execution-scope` 以 `ExecutionQuery.members` 获取实际所选范围的执行资格及版本;该入口使用列表权限,不建立预约。前端重新核对选择,写入继续校验原批次和取消组版本,不能自行合成 token 或静默刷新用户未核对的批次事实。
- 独立核实资料更新后,当前未确认客户通过 `POST /api/platform/v1/last-leg/appointment-receiving/cargo-refresh` 明确采用最新资料。请求 `RefreshCargo` 包含原 `member`、完整逐来源期望版本、`executionVersion` 和幂等键;先展示最新核实量与货件资料供操作者核对。只更新本客户原批次资料快照,不改分配量、客户/来源/目的地身份或其他客户确认。有效确认、待确认变化、已执行、来源身份改变或数量不守恒均拒绝;不以放松Plan/Book版控恢复,不在独立核实保存后自动采用。
## 5. 唯一文件写者与阶段交付
以下代码路径相对工作区 `C:/Users/BY-OY/Desktop/code/chongchong-global`。修改前读适用最近指引,保留已经存在的未提交更改。包级范围只覆盖预约工作本轮直接相关文件,不授权重写整包无关业务。
| 写者 | 独占文件/触点 | 不得写入 |
| --- | --- | --- |
| 开发总控兼预约核心 `01a13df2-c639-7560-a3e2-30bc23a579b3` | `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/appointmentplanning/` 来源、核实、覆盖、批次与预约桥接,以及 `inboundplan/` 核心预约和直接消费者,排除下述本批交给后端专项的触点及直接测试;现有预约规划、核实、批次及 FBA OpenAPI;本轮全部 Firstleg 来源接口和直送卸货/还空守卫;既有检查点、共享 DDL/SQL、IAM/权限种子、根路由导航、Gateway/公共门禁集成及验证窗口 | 两个专项独占文件、原型及业务主文档;不能与专项并写 |
| 工作事项后端 `01a13e1c-9101-7a43-8445-771685ff315e` | 原 `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/appointmentwork/`、同包测试、`src/main/resources/openapi/appointment-work-v1.yaml`、独立 DDL 提案 `src/main/resources/db/appointment-work.sql` 保留;增加下述 Lastleg 原域适配及精确同步触点 | Firstleg;未列入本批适配的预约核心和 PDA 写类;共享 SQL/配置/IAM/权限种子/架构门禁 |
| 预约页面前端 `01a13e1c-db36-73e3-a231-d6649c51664b` | `apps/admin-web/src/modules/appointment-calendar/` 全部页面、组件、API、直接测试与操作矩阵;共享 `overseas-warehouse/components/FbaAppointmentFields.vue`、`appointmentForm.ts`/直接测试;`api/inboundOrders.ts`/测试仅预约消费段;`index.ts` 仅相关导出;`pages/InboundOrdersView.vue`/测试仅预约弹窗衔接;增加下述跨页面工作流触点 | 后端、根路由/导航、本轮工作流之外的业务功能、原型与业务文档 |
| 原型与文档支持 `01a13a8d-e968-7962-906b-1a514792d921` | 业务梳理、原型、本文及必要业务正式文档/入口;设计确认后向开发总控交接 | 代码、共享 SQL、构建、开发检查点写入、开发派工及持续进度跟踪;接口对齐和验证安排由开发总控负责 |
模块 `lastleg-service/src/main/resources/db/lastleg.sql`、`deploy/sql/海外区域统一增量-MySQL8.sql` 与 `reset-test-fba-appointments.sql` 统一由当前开发总控 `01a13df2-c639-7560-a3e2-30bc23a579b3` 集成,保留各专项已有改动,新后端仅维护独立 DDL 提案,不并写共享文件;本轮只编辑文件,不执行 SQL。
本批工作事项后端新增写权,以下 Java 路径相对 `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/`:
- 本轮 Lastleg 原业务域与工作事项间的真实读取/同步适配。
- `inboundplan/work/`:本轮原预约域的工作事项适配。`inboundplan/service/InboundFbaAppointmentService.java` 及核心预约/分批测试已由后端专项明确停止修改并交回开发总控,V13 核心调整由总控唯一写入;本条覆盖早期“专项增加最小同步钩子”的临时移交。
- `dispatch/service/DispatchService.java`、`dispatch/dto/DispatchRequests.java`、`fleet/trip/FleetTripExecutionService.java`,以及以上适配直接涉及的 Mapper、DTO 和对应测试;只为本轮工作流衔接修改,不扩展为原业务域整体重构。
上述保留给后端专项的触点及其直接测试由专项唯一写入;总控不同时编辑。已交回的预约核心服务及核心测试由总控唯一写入。再次调整写权时须明确移交后再写,不按同文件不同方法安排并写。后端专项仍不能改 Firstleg、共享 SQL/IAM/公共门禁。
本批预约页面前端新增以下最小工作流衔接写权,路径相对 `apps/admin-web/src/modules/`;可同步对应直接测试,不改页面中无关业务:
- `container-loading/pages/ContainerDetailView.vue`、`container-loading/api/terminalDrayages.ts`。
- `overseas-master-data/pages/TripsView.vue`、`overseas-master-data/pages/TripDetailView.vue`、`overseas-master-data/components/TripPlanDialog.vue`。
- `overseas-warehouse/pages/DispatchesView.vue`、`overseas-warehouse/components/SmartDispatchDialog.vue`、`overseas-warehouse/api/dispatches.ts`、`overseas-warehouse/pages/InboundOrderDetailView.vue`。
本轮全部 Firstleg 来源接口、直送实际卸货/还空守卫及相应原域事实适配由开发总控负责;工作事项后端消费和提出所需 DTO,不写 Firstleg。提柜后还空责任与原承运历史分离的业务约束不变。Firstleg 无时区 local 实际事实与开船证据按第三节已冻结时间合同衔接,不能把证据时间当作确切开船时间。共享 DDL、IAM、根公共权限常量及门禁仍归总控,不能借上述原域适配授权扩大写权。
1. 核心保持核实与数量分配开发;新后端按 v1 实现工作合同;前端接入已冻结的工作 v1 和核实接口。分批消费者等待真实分批合同,其他部分并行。
2. 每个任务在自己对话报告实际修改、接口偏差、缺口、测试证据与可集成基线。总控读取,不要求自动跨对话回信;不新增任务或递归派工。
3. Maven/共享构建输出按总控分配窗口串行;前端只运行本模块直接验证,完整测试/build 先核对其他专项的窗口。当前先开发和准备测试,由总控安排执行时段。
4. 原型由原型与文档支持对话统一维护;V13 已获用户确认并形成正式变更说明。实现偏差先报当前开发总控,必要时请求文档支持,不能各自改原型或偷偷改变 DTO。开发总控沿本节原分工推进,不新增任务或扩大文件写权。
## 6. 必须保留的验收场景
V13 本批新增及强化场景以[正式变更说明第十一节](预约工作日历V13变更说明.md#11-最小验收矩阵)为准;下列既有场景继续保留,不能用原型通过代替真实合同和实现验收。
- 已开船但未创建预约、未知路线、没有海外仓绑定的直送、非 FBA 客户仓、货已送完但未还空,全部能进入正确待办;跨月份、全关类型、只看单流程不能误清全局数量。
- 中转一柜分三批、两车运输,柜级不重复;部分取消/改期/合并后数量仍守恒、逐票客户和货件信息未丢失;并发或重复点击不超分、不中断剩余需求。
- 直送不生成海外仓入库,不伪造卸货事实;同车或转交还空均可追踪原预约、新责任、接手状态及真实完成前置条件。
- 未定日期仅补货物资料不自动预约;有跟进日仍未定作业日期;首次计划无多余复核,真实变更仅影响相关已安排项,复核不产生复核循环。
- 日期跨时区、实际发生时间晚于目标、改期/取消后的旧事实仍正确;同一车次多批不重复计车辆工作量;只读用户不能通过通用命令越权执行。
- 原业务无时区 local 实际事实保留当地日期与完成状态,并标记 `SOURCE_TIMEZONE`;原业务 Slot 可缺时区但新录入不可缺;仅有 `sailedEvidenceLocalAt` 时可证明已开船,不能展示为确切开船时间。
- 外部来源或权威事实读取失败有明确失败反馈,不能展示“0 项/全部完成”;生产接口不能返回原型 Fixture。
生产代码、离线检查、部署与真实验收分别交付。人工视觉验收仍按 1920×1080、100% 缩放,由用户截图确认;本轮不部署、不运行 SQL、不写测试环境数据、不启动本地后端、不自行提交或创建分支/worktree。
+301 -3
View File
@@ -1,7 +1,305 @@
# 测试环境独立任务协作登记 # 测试环境独立任务协作登记
已按用户要求清空全部任务登记与调度规则(2026-09-09)。当前无登记任务。 ## 2026-10-19 排车列表统一作业改造
任务由用户手动创建、处理和归档,不根据旧登记、历史消息或历史台账自动派工、恢复任务或回传进度。 用户明确当前对话 `01a15230-a9d6-7503-a8a9-d70691df49e5` 为本批总控并要求先定义规则再下发。旧三个排车对话已归档,本轮消息未送达,保持归档状态;用户随后明确新建三个独立任务。所属TEST项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host local、cwd `C:/Users/BY-OY/Desktop/code/chongchong-global` 已核对。用户已确认四个彩色图标详情页签、两种建单方式、允许临时填写外配车辆司机、PDA拣货核平后后台才能确认装车完成。新建任务如下,依后端工作量采用两个后端和一个Admin/PDA联合前端任务;首批仅做技术准备,共同接口冻结并由总控明确解锁前不修改生产代码。本批业务和文件边界唯一见[排车列表统一作业改造契约](海外仓业务/排车列表统一作业改造契约.md)。
本文件仅保留空登记说明,避免已有文档链接失效。历史需求与验收证据保留在《测试任务盘点与需求台账》,不作为当前调度或授权依据。 | task_id | 对话 | 本批稳定职责 |
| --- | --- | --- |
| `01a1524f-4f11-70c2-8a46-8e06e73a2d86` | 排车后端 | 排车主单与明细客户归属、建单/加货、五阶段、审核及装车/发车;`dispatch/`、`fleet/trip/`及对应测试唯一写者(`FleetBookingFreight.java`除外),后端Maven唯一执行者。 |
| `01a1524f-56a9-7320-a5fd-8ff76fa4356b` | 排车派送与费用后端 | `delivery/`、必要`financefee/`、`FleetBookingFreight.java`及对应测试;客户目的仓拆单、费用和正常签收汇总事实,不写排车主流程类/DTO/Mapper。 |
| `01a1524f-52c7-7cc3-9b08-d34ad24c172a` | 排车前端与PDA | Admin排车列表、四页签详情、弹框/API/类型,以及海外PDA任务/装车/发车/恢复与直接测试;不写Java,预约日历在途文件先只读。 |
当前总控负责业务与共同接口冻结、共享导航/根路由/权限/SQL/Gateway及共同OpenAPI集成、协调检查和交付。两个后端先对齐主单/明细、动作资格、派送完成事实、事务和锁顺序;前端并行准备原型矩阵和双端接口差异;接口冻结后再解锁实现。各任务自行报告,由总控读取,不自动获得向其他对话发消息或递归委派的授权。
用户随后明确“四项都按建议执行”,再澄清“新增预约”是预约日历功能,先与排车改造分开整理。此前两类预约先保存后关联的答复仅保留为日历需求输入,不派给本批三个任务。当前依主契约第八至十节进入分阶段实施:主流程先产出公共DTO/端口骨架;派送后端实施本域拆单/费用/提醒;前端接入真实骨架、四页签及双端,并取得Client旧派送创建直接消费的最小移除权。预约在途文件保持只读;确受整车改造影响的既有关联调用先核对唯一写者再逐文件解锁;`adminDensity.test.ts`等其他在途内容不得覆盖。共同SQL/OpenAPI/权限/根路由仍由总控集成,Maven仍由主流程唯一执行。此前仅准备的阶段门禁由本段及主契约第九节的精确解锁取代。
用户进一步指定日历新增预约由既有对话 `01a15231-2507-7802-8015-34b01f5eb2c4` 处理,并明确本总控不用管;此记录仅标注避免冲突,不授予本总控对该对话的读取、派工或接管职责。
本批本地实施检查点:三个任务已收到第九节实施派工且状态为执行中。总控已移除Client `order-management/routes.ts`的旧派送创建路由及`tenant-management/contracts.ts`对应权限展示/映射,前端任务负责同步直接测试并统一运行Client检查。实现前网关路由合同5项通过;Lastleg依赖合同9项通过、3项失败,现有`fleet/pickup`三个类直接依赖`transfer.entity.WarehouseTransferOrder`不符合基线,尚未由本批扩大修改或添加豁免。最终检查必须区分这项既存阻断与本批新增问题;以上不表示新流程已实现、已部署或已完成真实页面/PDA验收。
后续本地检查点:四页签结构和Client移除已有实际差异,总控已核对;前端专项报告四页签6项、Client全量601项及typecheck/build通过,真实页面仍待人工验收。`dispatch/port/`公共骨架已生成但尚未完整冻结:主后端负责补实载只读查询、候选来源版本、草稿转换和既有预约批次投影;同时处理缺失recordVersion不得默认为合法0、预约结果不得由请求伪造、命令结果持久化多态恢复。派送专项按实际端口接入信号/分组,前端先保持预约表单只读并交最小接线清单。总控下一步核对补齐后的生产者合同与消费者,再集成共享SQL/OpenAPI/权限,不以骨架或局部通过推定全链完成。
2026-10-19 14:05跟踪:主后端已在实际请求DTO中将版本改为Long并拒绝缺失/负值,0保持合法,车辆预约写请求收敛为引用和版本;其编译、恢复测试及完整接口仍待交付。派送域已新增签收持久信号Entity/Repository/Mapper及实际端口实现,签收资料保存同事务只入信号、不回调父流程;拆单、费用、完成汇总及结构尚未集成验证。四页签代码仍严格为车辆信息、排车信息、单据信息、关联订单明细。前端专项新报告Admin全量存在旧布局断言及另一页面超时,正在区分本批失败和独立失败;当前不能标记Admin全量通过。负责人分别保持主后端补齐公共合同、派送后端本域实现、前端给精确失败和既有预约消费者清单;日历新增预约不接管。
2026-10-19 14:36跟踪:总控已逐文件核对主设计第0节13个port文件SHA-256,全部匹配,公共骨架可供下游绑定;实载GET/候选版本/类型化草稿结果/既有批次投影已具备实际类型,Controller和来源适配仍未完成。主后端报告独立JDK17合同、全部Action跨实例JSON恢复、真实MyBatis/H2命令账本及身份冲突测试通过,Maven尚待派送稳定窗口;主单/审核/双端装发仍未交付。前端报告Client601项、Admin定向66项及两应用typecheck/build通过;旧布局断言已更新并定向通过,最终Admin全量3375项通过、11项5秒超时,不能标全量通过。五阶段列表及PDA仍未实现。派送后端仍执行中,正移除旧单客户生产转换链并补整车费用/回滚用例,尚无完整交付。已按既有写权衔接下一包:主后端接续主单/查询/建单和审核装发,前端按已核对骨架接续五阶段和PDA,派送继续原独占范围;不是重派已完成切片。受保护预约三表单与File证据仍是后续集成依赖,共享SQL/OpenAPI/权限由总控待最终提供者清单集成。未新增任务、文件写权或环境操作。
2026-10-19 14:56跟踪:派送后端本域代码已交付并冻结,39路径快照经总控按JS localeCompare排序独立重算,匹配`ab2a553af145d7a2c708f1b44d88eb2c349970d81295bbbe4504af5f55ed2f81`;最初ordinal排序差异已解释,没有代码漂移证据。总控已读实际整车安排/发车/签收事实链:按客户出库及客户目的地拆单、全体子单锁先于来源、签收只入持久信号;共享执行端口实现及并发组合仍未验证。本域Maven未执行,设计11.1—11.3已有两表/来源字段SQL及准确用例;已交主后端在当前切片稳定后统一test-compile和直接测试,并更新其独占手工fixture。主后端正在实现整车自动资源记录、主单持久化与查询,旧绑定尚未退出;前端实际代码已接五阶段、装车前三分区、带来源版本的整车草稿新建,四彩色页签保持,尚未给新输入测试结果/PDA交付。当前阶段为联合实现和编译前集成,不可部署;共享结构/API/权限及保护中的既有消费者仍待收口。未新增任务或扩大写权,未操作日历新增预约。
2026-10-19 15:16跟踪:主后端报告生产及测试源码均已编译通过,定向144项中143通过,唯一失败为Merchant OpenAPI旧创建POST。总控已核对实际Merchant测试报告失败位置并在共享`overseas-business-v1.yaml`删除对应7行POST描述,保留客户读取/详情/签收资料,diff检查通过;已交唯一Maven写者重跑该失败类,当前待复验,不把修文档当测试已绿。主单真实Mapper/H2三项测试报告3/3通过,总控已核对空单一对一Fleet、双客户一车及事务回滚断言;实际选货来源在该用例是受控输入,权威来源解析和完整审核/装发仍未验收。PDA专项报告全量278项通过,新增覆盖断网原命令恢复、同数量下一次实拣换新键、成功后GET失败及另一端已发车恢复;总控已核对实际API/store/页面差异,H5/App编译和Admin新输入检查仍在进行。派送冻结输入无变化;下一步主后端复验OpenAPI并继续真实来源/状态链,前端完成资源构建与Admin验证,总控继续共享结构/权限及受保护消费者集成,不部署或写环境。
本节作为三个对话在本批的职责依据,生产写权以主契约第九节的首批范围和停止点为准;上一批提交、发布、SQL和真实HTTP授权不延续。保留当前工作区和分支,不建worktree或项目副本,不提交推送、部署、执行环境SQL或真实业务写入。部署与真实验收事实仍只维护两份环境主契约。
2026-10-19用户要求检查“只有一个对话慢慢跑”:核实主后端active,另两项各自切片交付后idle。总控按主契约第九节“当前并行收口分工”重新衔接有限包:派送后端独占File的BusinessFileCategory、DispatchEvidenceFileTest及dispatch-evidence-v1.yaml三文件;前端独占WorkDispatchForm/WorkExistingDispatchForm/WorkSharedTripForm及同名测试六文件,仅处理原有排车消费者。上述文件已定向核对无在途未提交差异;WorkDetailPanel和新增预约文件继续保护。主后端保留主流程/公共端口/唯一Maven,总控承担共享SQL/OpenAPI/权限;不新建任务或业务范围,不接管用户指定日历对话。此有限移交覆盖此前三表单和File登记只读等待,其他边界保持。
2026-10-19 15:39跟踪:三个既有任务均active,File限定包及六表单接线均已确认接收,未出现新权限/业务决定阻塞。总控已实际同步模块及海外统一空库源SQL:公共命令账本、整车唯一派送安排、签收持久信号及出库不可变来源字段;并按当前DispatchAggregate完整收敛整车无客户头、五阶段、审核/版本/资源及loading_confirmation_json,新增追加历史和货物来源字段。静态比对两份整车列集合与实体全部字段一致,主单/历史定义一致,diff检查通过;Fleet/PDA/草稿与完整权限/API结构仍未收口,不能视为SQL整体验证通过或已执行。主后端继续主流程/附件公开端点,派送后端File提供者,前端既有排车消费者;无新建任务、无环境操作、无日历新增预约改动。
用户要求总控也直接参与实现后,总控独占完成权限集成8文件:OverseasPermissions、IAM phase5-delivery-permissions.sql及iam-v1.yaml、国内统一基线、四个直接IAM测试。新增dispatch:create/loading-complete/depart(5107065/66/67),移除客户创建5306001及默认关联,客户只读;来源目录20项、仓库操作岗19项、理货只读5项,PDA未获后台权限。主后端按唯一串行窗口运行后,总控核对四份实际Surefire报告合计24项全部通过,并核对target中执行的权限SQL/OpenAPI与当前源码哈希一致;这是本权限包验证,不代替Lastleg全链或环境验收。
File三文件实际哈希已逐项匹配交付,12个新增用例交主后端统一运行。前端六表单接线报告17文件142项及Admin typecheck/build通过,现按实际DispatchWorkModels/Controller接附件、移货和路线。派送专项继续只读审查集成,并收到一次精确编译反馈修正:MerchantDeliveryControllerTest第133行误将delivery之外的warehouse-transfer/cargo-discard合法POST纳入禁止范围;仅解除该测试文件冻结,按精确路径块修正并重记候选,生产文件及File三文件仍冻结,不为追绿删除其他业务接口。总控后续继续平台OpenAPI及其余Fleet/PDA/草稿结构收口。
2026-10-19 16:05跟踪:主后端报告生产源码编译通过,但全部测试源码被派送合同测试的旧取消调用阻断。总控核实`PlatformDispatchOutboundContractTest`仍引用旧`DispatchController.cancel`和旧更新DTO;实际取消已迁至`DispatchAggregateController`的版本化POST。已复用派送任务,仅解除该直接测试的冻结以修正调用、反射及实际受影响路由断言,保留客户拒绝和独立权限,不恢复旧接口、不自行运行Maven;主后端知悉并继续修正证据网关将HTTP200错误JSON当文件、业务拒绝误归上游故障的两项问题。派送任务已恢复执行。前端报告18个相关测试文件155项、Admin类型检查及构建通过,路线提示和资格禁用状态仍在最终收口;这是专项报告,尚非全量回归及真实页面/PDA验收。总控继续负责剩余共享OpenAPI和Fleet/PDA/草稿结构;无新增任务、无环境操作,日历新增预约仍不接管。
2026-10-19继续实施:前端已交付并冻结当前21生产文件候选,18文件155项及收口13项、typecheck/build通过;派送已修旧取消/更新消费者测试,待主后端运行。总控发现PDA Controller、草稿及Fleet关联仍为旧生产模型,主后端确认未完成;不得再以生产编译通过代表本批实现完成。主后端明确释放的草稿包已按主契约第九节移交派送任务唯一实施,PDA/发车/汇总/Fleet及公共端口仍由主后端负责。前端仅只读对账实际API/Controller,不重写已冻结生产。总控已同步两份SQL的Fleet草稿计划时间可空及活动物理托盘唯一锁,继续OpenAPI及共享结构。该分工复用既有三任务,没有新增对话、子代理或环境操作。
2026-10-19 16:25收口检查点:用户发现侧栏仍有车次管理,总控已将`fleet-trips`设为hidden并同步既有导航断言,实际16/16通过;出车记录按实际发车运营查询继续保留,旧车次详情和附加代码不删除。总控同步源及统一SQL的草稿拥有者/起运仓/版本/来源快照、容器来源键/序号唯一及草稿命令表,相关10表字段集合、重复字段、中文注释静态核对通过;同时纠正了上一轮明细中订单号列重复声明。平台29组路径与PDA7组原生路径已按实际Controller更新,两份OpenAPI共享实际DTO及Long字符串wire,537个引用及重复键检查通过;移除旧取消/移货DELETE、已退出fee-coverage、单客户standalone预排及PDA旧complete/车次版本发车协议。网关合同5/5通过,未运行环境SQL或HTTP。草稿主后端桥接已落地;旧DispatchService草稿方法仍须由其唯一写者清理。前端只读复现了批次货物数量严格比较、零扫码移货及附件大小校验三处真实字符串阻断,已仅在原独占范围解除冻结修正并补wire回归;此前155项不能代替新输入。当前仍待两个后端稳定编译及行为回归、既有预约批次/车辆预约权威提供者接通(现主流程仍显式拒绝其写入)、Fleet/PDA旧模型最终收敛、证据网关与全链事务验证。新增日历预约仍不接管。
2026-10-19 16:42跟踪:旧DispatchService草稿读写/占用/转换方法已由主后端删除,原草稿客户字段编译交集从源码中消失;主后端报告含桥接及原生PDA的当前生产快照编译通过,完整测试仍待稳定输入统一运行。草稿专项13文件稳定候选`db84f7527d8ee88a5b893ed291081041c5a1461d7dbdafc66716014c575d3ac0`经总控逐项及聚合复算全部匹配;3份16用例已写好未运行,已交唯一Maven写者。总控同步plan_ids_json为LONGTEXT以容纳500个Long引用,并补齐草稿公开业务必填;两份OpenAPI537引用及10表静态核对通过。总控同时收敛3份最近AGENTS中的旧排车流程指引,最终索引合同1161项通过。前端报告新候选Admin19文件209/209、PDA282/282及类型检查/H5/App/Admin构建通过,测试文件恢复后已复测;总控实际复算22生产文件摘要`63feb551c2325450ddd0bd7840c81191620372aa2cf64ea2dfb97027282c429f`匹配,源码响应边界保留ID/版本且安全归一化数量,之前3处字符串阻断已有真实wire回归。草稿和前端候选保持冻结,不代表后端全链或人工/真机通过。派送任务接续仅只读审查既有预约Provider的客户归属、分配保留、发车收货复核和锁序,不新增写权、不接管新增预约;主后端继续本域及统一编译/回归,总控收口共同契约。
2026-10-19 16:57跟踪:主后端已运行本批Lastleg定向轮次,总控此前读取28份实际Surefire报告合计178项、1失败和1错误;两项分别是草稿Controller权限测试错误遍历非HTTP方法,以及转换原结果的嵌套Payload恢复失败。已交草稿唯一写者修正,不恢复旧协议、不重做原转换。前端专项只读另发现并由总控核实首次选货在来源锁等待期间跨过草稿到期点,可能返回成功但没有有效占用;同一草稿写者补原租约锁后复核、完整续期校验和真实行锁/可控时钟回滚用例。上述有限草稿包仅为这三项解除冻结,修复后重记候选交主后端唯一Maven执行。File七类验证仍被原证据测试4处IOException编译错误阻断,已交该文件原写者最小修复;不能记作File运行通过。总控已同步两份SQL中单排车PDA任务唯一约束及Fleet关联去客户头部/旧审核镜像,12直接表静态核对通过;主后端继续Java模型及两客户单任务回归。后续PDA轮次13项被DispatchPdaTask非法字节码VerifyError阻断,主后端正处理本地target重编译,不能归类业务断言失败;总控实际报告核对证据网关5项通过、双端发车持久2项通过。前端22生产文件保持冻结,另接只读新建/草稿/候选权限调用链核对;预约Provider只读审查暂缓于草稿运行缺陷,尚未解除其写权。以上没有部署、SQL或真实页面/PDA验收,日历新增预约仍不接管。
2026-10-19 17:02跟踪:前端只读核对证实新建入口使用dispatch:create,但草稿接口仍依赖旧入仓智能排车权限,当前默认仓操作角色会被业务鉴权拒绝;总控按主契约9.7统一为候选/草稿GET使用dispatch:list、八个草稿写使用dispatch:create。Controller及直接测试由草稿唯一写者同批修正,前端仅在原模块内修正无重叠写者的InboundOrdersView/permissions及直接测试;原22生产文件保持冻结。总控已同步共享OpenAPI并实际重验537引用、重复键、路径及两份12表静态结构通过。草稿三项缺陷与File受检异常修正已有源码,最终指纹及唯一Maven重跑尚待交付。主后端报告隔离target异常后的定向JUnit36/36,含两客户单任务/发车竞争/回滚;总控已索要既有报告和源码指纹,尚不记完整Maven或全链通过。预约Provider客户头部消费者及锁序适配仍待处理,没有扩大其写权或接管新增预约。
2026-10-19 17:05交付复核:草稿唯一写者已停止该包写入,总控逐文件及聚合复算13文件新指纹`b0db1bb5191fa3578dacfa0f07c7c2a6a30346f0198047e34fc1fe3a99b0e554`匹配,当前17用例(持久10、Controller6、OpenAPI1)与File七类一并交主后端串行重跑。File测试新指纹`bba87946457fb1290960218127087552de95b59f443eb6d5dacf354084d04a19`及其余两文件已核对,运行通过仍待证据。入仓选货建排车入口4文件哈希均匹配交付,专项30/30及typecheck通过,原22文件候选聚合保持一致。派送任务接续此前暂停的预约Provider只读提案,不获得生产写权;前端停止待新反馈。总控另将原主后端独占的FleetCapacityOfferController arrange-dispatch旧智能排车权限消费交其随本域收敛,保留附加业务及其他独立权限;在全部直接消费者核清前不删除仍被引用的旧权限资源。没有新增任务或环境操作。
2026-10-19 17:12验证更新:总控已读取File本轮7份实际Surefire报告,合计49/49、0失败0错误,其中DispatchEvidenceFileTest12/12;测试源码指纹仍与交付`bba87946…84d04a19`一致,原File编译阻断关闭。总控另核对固定输出JUnit日志36/36、清单10份源码哈希、日志和编译jar指纹全部一致;该证据明确不覆盖随后Fleet重写。前端独立只读复核也匹配草稿新13文件指纹,确认此前跨期来源占用漏洞在源码上闭合,未发现本次修正明确回归;新17用例和完整生产提供者事务仍待运行。预约只读审查确认ExecutionAdapter及两份测试仍消费旧客户头,车辆预约带版本权威提供者尚未定位,不能拿FBA批次或Fleet预订代替;未扩写预约文件或接管新增预约。
2026-10-19 17:25授权及接续:总控已核对派送设计第13节的具体接线提案,用户明确答复“允许按清单接线,新增预约不动”。据此解除该节既有预约Provider/Execution/Transport/QueryMapper、原TransportPort/ReceivingService及直接测试只读限制,交派送后端唯一维护;主后端继续公共port/批次版本/主流程预锁和窄原预约变更命令,另最小适配ExceptionOrderService旧共享PDA调用与直接测试;前端按实际合同同步原排车模型和三个已授权Work表单。精确边界与批次→来源锁序已写主契约第九节新授权段,三个既有任务已收到接续派工,不新建对话。车辆预约独立权威仍未定位,此授权不允许新建权威表/API或接管日历新增预约。当前隔离编译显式排除3个未接线消费者,不能记整服务通过;新一轮62项中57通过、5个Fleet方法权限用例因缺测试Bean失败,其后单独5/5报告已出现,仍需主后端交完整输入和最终结果。此前File49/49和固定输出36/36证据保留原范围。
2026-10-19 17:32接线检查点:两侧薄合同已实际落地并由总控核对SHA,公共DispatchContracts为`73b5b83f…ca84f641`、窄DispatchAppointmentAmendmentPort为`45aca62f…7887b238`、原AppointmentWorkDispatchPort为`81107e69…717a784b`。两个公共批次DTO版本在末尾、Provider版本在中间,已向双方明确逐字段映射;版本必填、0合法,不增加HTTP入口。前端已据真实公共DTO接续,B开始从真实明细/分配读取客户并实现保留旧分配的增量。总控已将公共批次版本同步OpenAPI,4份相关OpenAPI的重复键/653引用/退役路径/版本规则及两份12表静态结构通过;Fleet已移除8个退役操作且保留附加能力入口,实际网关路由合同5/5通过。Fleet旧未用schemas及最新响应类型仍待最终提供者清单,不记完整契约收口。原22前端候选仅为此次版本消费解除相应冻结,包含DispatchWorkflowDialog ADD_CARGO直接调用;没有再次申请同一已授权范围。各本域实现和全服务编译/联合行为回归仍未完成。
## 2026-10-18 预约演示问题交接与原总控退出
用户明确指定既有对话 `01a14f36-9fae-7dc0-90e6-1d3c54d22de6`(Bug 处理-1)处理 D1674 演示中的三个问题:保存预约后页面 A0409、查看原排车单后事项弹窗未关闭、继续安排本批车辆提示操作资格已变化;并明确 `01a13df2-c639-7560-a3e2-30bc23a579b3`(预约)不再担任总控。原对话已将操作指南、四张用户截图路径、已有诊断和保护边界发送给指定对话,停止开发调度、修改与部署。下方历史预约总控身份不再代表当前授权;本次不指定新的全局总控、不新建长期专项。
接收对话 cwd 为 `C:/Users/BY-OY/Desktop/code/chongchong-global`、host local,属于本表 TEST 项目范围。本次交接仅覆盖这三个缺陷的定位、局部修复及离线验证;不自动授权提交发布、SQL、真实 HTTP 或测试环境写入。原两箱样本及用户已操作的领导演示数据保持,禁止重建或重置来绕过故障。涉及本表排车修复任务仍持有的文件时先核对当前写入状态,不覆盖其修改;原对话不再并行处理。接收对话直接向用户交付结果。
## 2026-10-18 排车修复分工
用户先创建三个待分工对话,随后明确由规划对话 `01a14cd6-4647-7b32-b719-f009dec87ae0` 只做文档规划并向以下三个对话分派修复。规划与精确文件边界见[排车流程修复规划](海外仓业务/排车流程修复规划.md);本轮为有限缺陷修复,不新建长期专项。三个对话均已核对归 TEST 项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host `local`、cwd `C:/Users/BY-OY/Desktop/code/chongchong-global`。
| task_id | 对话 | 当前职责与写权 |
| --- | --- | --- |
| `01a14d16-8631-7de2-acde-67050ce902b9` | 排车修复 | Lastleg后端修复与代码集成唯一写者;取消释放、派送状态、换标全托、合托来源及最小前端能力契约;直接测试与必要OpenAPI/结构定义,唯一后端Maven执行者。 |
| `01a14d17-02a2-7890-90bb-33067a1eb42f` | 排车修复-2 | Admin/PDA直接消费页面、组件、API/类型与相邻测试;修复动作提示、换标草稿和恢复错误,接入稳定后端契约;不改后端或预约核心页面。 |
| `01a14d17-17d8-7072-849b-37250083b676` | 排车修复-3 | 独立只读审查与连续场景回归设计;仅独占新增 `lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchRepairWorkflowTest.java`,不改生产实现、已有测试或共享fixture;Maven交后端负责人执行。 |
用户本轮已授权以上修复实施及必要离线验证;规划对话仅写规划、登记和最小路由,不改代码。执行者在自身对话报告,由规划对话读取并转达,不因派工自动获得向其他对话发送消息的授权。保持当前工作区和分支,不提交/推送,不新建对话、worktree或项目副本,不启动服务,不执行SQL、真实HTTP、部署或环境写入。
本批仅覆盖规划中精确缺陷,不接管预约核心或同步性能。既有预约批次分配和工作事项接线必须保留。派工时“预约”对话正在执行固定18文件提交发布;与其活动写入或共享构建重叠时先只读核对并报告,继续无冲突范围。前序任务环境授权不传递;不同任务不得并行写相同文件或运行共享后端Maven。部署与实际验收事实仍只维护两份环境主契约。
2026-10-18 用户在本规划对话追加明确授权“请提交代码,且帮我部署,然后验收”。本轮仅将已独立复审通过的排车修复候选提交、按发布需要推送,并部署到上述 TEST 项目的 Lastleg 与 Admin;覆盖前段针对本批提交、部署及真实 HTTP 的禁止,其他边界保持。后端“排车修复”唯一负责精确候选提交、Lastleg 发布及本批新建合成样本的接口验收;前端“排车修复-2”唯一负责 Admin 精确候选提交及配套发布,等待 Lastleg 就绪后串行发布;“排车修复-3”只读复核候选、部署版本和验收证据,测试文件继续冻结。规划对话维护分工与环境主契约,不接管代码或执行器。
发布前核对当前分支、冻结哈希、实际环境与 Schema,保留其他窗口未提交修改,不全目录暂存、不切分支、不创建 worktree。本轮真实接口的非破坏性业务写入仅用于可识别的新合成样本,不操作既有业务样本、不伪造外部真实凭证。执行 SQL、删除、重置及无关配置发布不包含在上述概括授权内;若实际结构不满足新版本,先交付具体差异、最小 SQL 与影响范围,再落实单独授权。未取得结构前置条件不得发布不匹配的服务。人工页面与 PDA 硬件验收仍按现行规则独立报告,不能由 HTTP 或 Job 成功代替。
用户随后通过本规划对话的确认项明确回答“授权执行这份两表 SQL 并继续”。授权仅限 TEST `baiyue_lastleg` 的 `lastleg-service/target/dispatch-repair-test-schema-20261018.sql`,SHA-256 `0d016752bac700d67de943e82a03db50853986c5dc3efa35f178ca8eb3ab0f6b`:调整 `ll_exception_return_item` 的原箱字段、索引及约束,并新建 `ll_return_carton_stock_receipt`。由后端“排车修复”唯一执行,执行前重新核对实际环境、文件哈希与当前结构,执行后只读核验;不包含其他 SQL、业务数据删除/重置/回填。结构核验通过后沿既有授权继续 Lastleg、Admin 发布与新样本验收,无需重复请求相同授权。
## 2026-10-15 库存历史还原并行只读验收
用户明确授权复用现有“库存分析-1”和“库存分析-2”,总控为“平台销量总控” / `01a13496-1713-7ac3-9981-1ae9ed551571`;TEST 项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host local、cwd `C:/Users/BY-OY/Desktop/code/chongchong-global` 已核对。仅本轮临时验收,不创建长期任务,不改变原业务代码写权。
| task_id | 对话 | 本轮只读职责与证据写权 |
| --- | --- | --- |
| `01a137dd-dc62-7000-88b9-fb1df4a2dd22` | 库存分析-1 | 真实流水归并、日末库存及独立样本对账、UNKNOWN原因;仅写后端 `target/history-review-collection-*`。 |
| `01a138f8-4b84-7d01-b47a-3caaf160e6f6` | 库存分析-2 | 周转率公式、排序、货主汇总和固定版本导出;仅写后端 `target/history-review-query-*`。 |
允许只读测试SQL和已授权账号的HTTP查询验证;禁止SQL写入、业务代码或配置修改、部署、停止采集、额外领星请求、Git提交及子代理。总控唯一负责运行、发布及主文档收口,主动读取专项结果。原采集与指标两个旧任务无法被当前工具访问,本轮未向其成功派工。
用户随后明确授权让“库存分析-2”直接修改新发现的同秒长唯一余额链误判,覆盖其只读限制。仅移交 `InventoryHistoryCalculator.java`、`InventoryHistoryBuilder.java` 的计算修订签名和对应history直接测试;使用已有流水本地重算,公开日末口径保持,禁止额外领星请求、环境写入、提交或部署。该任务获得一次定向Maven测试窗口,总控暂停并行Maven;总控负责审查、提交、发布及真实复核。
## 2026-10-15 预约工作日历开发分工
用户明确要求保留现有开发任务,并新建“工作事项后端”“预约页面前端”两个独立任务。用户随后在“预约”对话明确指定 `01a13df2-c639-7560-a3e2-30bc23a579b3` 接任开发总控,原总控 `01a13a8d-e968-7962-906b-1a514792d921` 仅保留原型及业务文档支持;本次交接覆盖此前原型对话的开发调度与共享文件写权。三个开发任务均使用 TEST 项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host `local`、cwd `C:/Users/BY-OY/Desktop/code/chongchong-global`;不切换到另一开发环境目录。以下是本轮预约工作日历的唯一分工,不改变其他业务专项的写权和环境授权。
| task_id | 对话 | 稳定职责及独占边界 |
| --- | --- | --- |
| `01a13df2-c639-7560-a3e2-30bc23a579b3` | 预约 | 当前开发总控兼预约核心后端:保留来源、核实、覆盖、批次和预约核心写权,但本批移交后端专项的原域适配触点及其直接测试除外。负责本轮全部 Firstleg 来源接口、直送卸货/还空守卫,开发调度、检查点、共享 DDL/SQL、IAM/公共门禁集成和 Maven/验证窗口;不得与两个专项并写。 |
| `01a13e1c-9101-7a43-8445-771685ff315e` | 工作事项后端 | 原 `appointmentwork/`、同包测试、独立 OpenAPI/DDL 提案写权保留;新增本轮 Lastleg 原域适配、`inboundplan/work/`、`DispatchService`、`DispatchRequests`、`FleetTripExecutionService` 及其直接 Mapper/DTO/测试写权。V13 首批已明确将 `InboundFbaAppointmentService` 及核心预约/分批测试交回开发总控,专项不再写入。精确路径见开发协作契约;不改 Firstleg、共享 SQL/IAM/公共门禁。 |
| `01a13e1c-db36-73e3-a231-d6649c51664b` | 预约页面前端 | 原预约页面范围保留;新增货柜详情/码头拖车 API、车次列表/详情/计划弹窗、排车列表/智能排车/API、入仓单详情的工作流衔接最小修改权,精确文件见开发协作契约。对齐真实工作与批次接口,不改后端。 |
当前开发总控 `01a13df2-c639-7560-a3e2-30bc23a579b3` 唯一维护开发检查点、调度两个专项,并负责本轮模块 `lastleg.sql`、统一增量 SQL、重置脚本、权限初始化、根路由/导航、Gateway 和架构门禁的最小集成及共享构建窗口。原型/文档支持对话 `01a13a8d-e968-7962-906b-1a514792d921` 停止代码、共享 SQL、构建和开发调度,仅维护原型及业务正式文档;检查点写权已交回,本次仅更新登记及开发契约。两个专项保留原范围,并按上表增补本批精确集成触点;发生原核心文件重叠时,以本批后端专项写权为准,总控不得同时写同一文件。接口生产者负责对应 OpenAPI/DTO,变更先同步消费者;具体文件和接口以[预约工作日历开发协作契约](海外仓业务/预约工作日历开发协作契约.md)为准。各任务在自己对话报告,由当前开发总控读取,不因收到消息自动跨对话回信或递归创建任务。
用户已授权本轮代码开发和必要离线验证;未授权部署、执行 SQL、环境写入、启动本地后端或真实 HTTP。保持当前工作区和分支,不创建分支、worktree 或项目副本,不提交。两个新任务已完成只读准备,按上述边界解锁实施;每个文件一个写者,Maven/共享构建串行协调,不能把原型通过当作真实业务验收。
2026-10-16 用户再次明确角色:`01a13df2-c639-7560-a3e2-30bc23a579b3` 是开发设计与总控对话,负责安排开发、接口对齐和验证收口;原型/文档对话完成设计与文档后交接,不继续派工、进度跟踪或开发审查。此前一次跟进产生的进度与问题交回开发总控,不改变三个开发任务现有写权,也不新增环境操作授权。
## 2026-10-14 列表优先采集紧急修改接管
用户在 `01a137b9-87ca-7db0-a400-7c48c301ae9b` 指定接续原总控 `01a13496-1713-7ac3-9981-1ae9ed551571` 的本批工作;原总控已明确释放本批代码、文档、共享 Maven 和发布调度权。本批唯一协调与实现写者为接管对话,继续使用 TEST 项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host local、cwd `C:/Users/BY-OY/Desktop/code/chongchong-global`,不创建新对话、分支、worktree 或内部子代理。
范围为 Integration 列表 SKU/数量 DTO、映射、内部 OpenAPI 与直接测试,以及 Lastleg 列表消费、Discovery/Validation、RoutingManifest、单次执行预算与直接测试。最终口径为列表完整时直接采用列表数量,仅具体订单缺商品行、SKU 或数量时补取既有详情;真实零值有效,正常空订单页不补详情。原开发对话 `01a135d0-f5c7-7422-892f-037b0c9ea00e` 已交回写权。`01a12f38-d28c-75c0-bc1a-dfb27e7a4961` 继续承担只读审查和唯一环境发布执行,接管协调者核对候选、验证与既有授权后安排,不自行并行执行 Maven 或发布。库存周转、发布查询范围修复及其他冻结修改不混入本批。此项交接不新增环境授权,运行及验收事实只维护正式部署契约。
## 2026-10-13 用户指定的数量对照临时验证
用户明确指定已自行创建的 `01a135d0-f5c7-7422-892f-037b0c9ea00e`(开启新对话)处理列表量/预报量/实际量验证,在不影响现有采集的前提下开发。保存项目 TEST `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host local、cwd `C:/Users/BY-OY/Desktop/code/chongchong-global`;本次只登记既有对话的一次性范围,不创建长期专项或新对话。采集整体协调仍归当前总控 `01a13496-1713-7ac3-9981-1ae9ed551571`。
该对话唯一维护本次 Integration 有界数量对照组件、列表/详情白名单观察触点及直接测试;先核对现有未提交内容,不改其他专项冻结的 Egress/Gate、持续采集、共享 SQL、发布和运行脚本。若触点涉及仍在写入的文件或扩大 DTO/OpenAPI 合同,先列出精确冲突和最小范围,由用户/总控协调后再写,不覆盖他人修改。当前明确授权的是本次开发及只读状态核对,不解除其他对话的暂停,不自动恢复采集、部署或发起新的历史扫描。方案维护对话继续维护文档,详细保护条件和验收见 `自营业务/领星WMS接口联调手册.md` 的“数量对照验证的采集保护与开发交接”。
## 2026-10-13 持续自动采集批次(当前精确写权)
用户指定复用四个既有独立对话,唯一总控为 `01a13496-1713-7ac3-9981-1ae9ed551571`,仅负责调度、协调、验收收口与发布安排;禁止新增内部子代理。保存项目为 TEST `c64729ff-6710-43c6-8ef2-d84e9666cc1e`,cwd 为 `C:/Users/BY-OY/Desktop/code/chongchong-global`,保持当前分支。以下范围覆盖旧内部代理和历史临时写权,所有内部代理已停止;已有修改由对应独立专项接管,不创建新对话、分支或 worktree。
| 执行对话 | 本批唯一写入范围与交付 |
| --- | --- |
| 采集专项 `01a12f3f-c971-7b62-a0bb-dbdddb091990` | Lastleg 自营 `sync/`、Planner/TaskService/Execution/Discovery、CollectionPolicy/AnalyticsProperties、BusinessBudget、CoordinationMapper 及直接测试;持久完整日任务池、每日计划、断点续跑与去重 |
| 接口专项 `01a12f3f-c57a-79e1-9efa-9401f594544c` | Lastleg Egress、Integration EgressProperties/Gate 及直接测试;配对持续 BUSINESS 开关、短 permit 与真实出口保护 |
| 指标专项 `01a12f3f-ce73-75d2-8fe3-23d709c755d5` | Collection 查询/OpenAPI、StageEstimate/ProgressProjection、Admin 采集展示及直接测试;前端测试由该专项独占执行 |
| 原总控 `01a12f38-d28c-75c0-bc1a-dfb27e7a4961` | 本批登记、一期方案自动化契约、两服务 application.yml 开关默认 false、target 下新 continuous 发布/配置/验收脚本与脱敏清单;三个专项差异只读审查,代码冻结且编译就绪经总控确认后串行执行共享 Maven |
### 已正式派工的下一批:库存周转
库存周转已派给指标专项 `01a12f3f-ce73-75d2-8fe3-23d709c755d5`,按 `docs/自营业务/库存周转视图设计.md` 在本批持续自动采集收口后实施,不再仅记录为收到方案。该专项唯一维护只读 `inventory-turnover` 接口及 Admin 库存分析默认 TURNOVER/SKU、OWNER 汇总、7/15/30 同屏和原 DETAIL 严格入口及直接测试。采集专项 c971 只读核对每日库存代表和 continuous 库存计划资格,不改写或补造历史样本;原总控维护独立验收清单并安排串行后端回归。库存周转未完成不阻断本批持续采集启用;两批文件输入和验证证据分别冻结,后续改动不覆盖已审持续采集输入。
当前精确阶段门禁:总控已确认本批 Admin 固定候选 `4c4a3db1ebc277b2462a2e93c3e597ea86df36ae`,ce73 获准接续库存周转仅前端实现;周转后端新源码/OpenAPI 暂不写入,待持续版后端集成收口后再解锁。本批 Admin 验证/发布必须绑定该固定提交,不能取已接续下一批的 workspace HEAD。c971 本批覆盖修复将通过 run.scope_snapshot_json 冻结完整区间集合并同步直接查询消费者;其扩大文件范围以总控下一次精确写权与冻结清单为准,原总控重审后再串行回归。
目标为北京时间最近两个月全部完整日(首次 2026-08-13 至 2026-10-12)进入服务端持久任务池,每日 00:05 补前一完整日并优先,历史近到远;跨夜运行不依赖本机队列。运行事实、已验证与未关闭项只维护正式部署契约。现有 cutover/queue/helper 只读,不修改运行脚本、不擅自停止进程;新 continuous 发布须先核对旧 cutover 状态和自然日完成边界。环境操作、SQL、Nacos、部署及提交等总控具体指令;真实只读核验先报范围。本批交付在各自对话回复,由总控读取,不自动跨对话回信。
2026-10-13 用户明确要求接管“平台销售总控”:当前唯一总控改为 `01a13496-1713-7ac3-9981-1ae9ed551571`,接替 `01a12feb-0474-77f1-afe0-a3b491733dca`。继续使用本 TEST 工作区、既有专项与原文件边界;本轮集成及发布由当前总控串行执行,既有专项已停止写入。独立完整日修复包暂不实施,待后续精确派工;不创建新长期对话。运行事实只记入正式部署契约。
2026-10-13 17:22 总控追加12日独立完整日修复包:采集专项c971独占 AnalyticsReadMapper/AnalyticsReadRows、AnalyticsQueryService/AnalyticsSqlRequest/AnalyticsReadSql、SalesBucketPolicy、DashboardSalesPolicy/DashboardQueryService及直接测试与最小共用覆盖值对象;此精确范围临时覆盖原指标查询长期归属。指标专项ce73仍独占本轮采集前端,不写上述后端文件。内部inventory_daily仅审查版本覆盖证明不可变性,owner_query仅维护target下既有发布helper与离线测试;环境、共享文档、Maven、集成提交和发布仍由总控执行。采集保持OFF,不续11日。
2026-10-13 16:43 用户在指标专项窗口补充“单领星账号运行看板”最新页面要求。发现该窗口与内部frontend在采集页面发生并行写入,内部frontend已停止全部写入/测试并交接;采集前端CollectionView、进度组件、相关types/tests和操作矩阵唯一写权转交指标专项ce73,取代下段内部frontend独占安排。总控停止基于混合输入发布,待唯一写者统一新需求、冻结后再测试构建。
2026-10-13 用户再次明确要求复用以下四个窗口推进采集页改版。本批精确写权覆盖旧临时包:指标专项唯一维护 CollectionResponses/CollectionReadRows/CollectionReadMapper/CollectionQueryService、自营 OpenAPI 与直接查询测试;采集专项接管内部代理已停止的 SelfopStageEstimate/SelfopProgressProjection/SelfopDiscoveryService、直接测试及 SelfopEgressMapper 终态摘要触点;接口专项只读核查官方仓库筛选和重复请求/额外等待;原总控只读准备发布及续采清单。内部 frontend 唯一维护采集页及其组件/API类型/测试/操作矩阵;内部 owner_query、inventory_daily 已停止写入并完成交接。共享合同由新总控协调,Maven、提交和发布仍由新总控串行收口,当前运行根不因页面开发被重启中断。
## 2026-10-12 平台销量统计长期开发分工
本轮用户授权复用四个既有对话并行收口 Lastleg 全服务依赖门禁,临时覆盖下文旧修复包:指标专项独占预约来源与入仓包循环涉及的 `appointmentplanning/`、`inboundplan/` 和根 `service/` 直接相关类(排除 `ReturnOrderReferenceResolver`);采集专项独占 `fleet/` 包循环及车队反向依赖修复、必要的 `delivery/` 适配器;接口专项负责 `export/` 导出组合依赖审查与直接测试;原总控负责 `ReturnRelabelPackingService`、`WarehouseTransferReceiptCoordinator`、`ReturnOrderReferenceResolver` 三处边界及必要本域适配器,并只读核对发布清单。每包包含直接调用测试,跨写权先交新总控协调。新总控唯一维护依赖分析器、架构 JSON 基线、共享文档并串行执行 Maven。不得以通配许可或循环豁免消除失败;不新增长期任务,不授权环境操作。
2026-10-12 用户明确授权总控接管:本节唯一当前总控改为 `01a12feb-0474-77f1-afe0-a3b491733dca`(当前接管对话),原“平台销售总控” `01a12f38-d28c-75c0-bc1a-dfb27e7a4961` 仅保留历史交接记录。以下三个长期专项和方案维护者继续复用,已有文件归属与环境操作限制不变;共享文件集成和 Maven 窗口由新总控协调,不新增用户可见任务。
用户随后明确授权上述三个专项及原总控作为当前总控的下级任务继续派工。本次原总控负责发布清单与配置的只读复核,不再承担调度;指标专项复核查询上下文和隔离,采集专项复核调度/恢复前置,接口专项复核预算与出口安全。当前新增经营查询、日库存代表和前端实现分别由新总控的独占内部工作包维护,四个既有对话在收到精确写入权移交前只读,不沿旧派工并行改写。所有 Maven 和共享文件仍由新总控统一收口。
上述复核后的定向修复写权:接口专项独占 `client/RestLingxingAnalyticsClient.java`、`request/SelfopEgressService.java` 及直接测试;采集专项独占 `sync/SelfopValidationRunner.java`、`SelfopExecutionService.java`、`SelfopTaskService.java`、`SelfopSchedulePlanner.java` 及直接测试。经营查询由内部工作包统一实现,指标专项只读复核,不重复写入;日代表 `inventory/`、`model/SelfopSyncRun.java`、`mapper/SelfopSyncRunMapper.java` 由内部工作包维护。新总控保留 `query/Collection*`、`retention/`、共享 SQL、配置集成和最终门禁。
用户此前明确确认新增以下三个开发对话;创建时所属总控为“平台销售-开发” / `01a12f38-d28c-75c0-bc1a-dfb27e7a4961`,当前归属以上述接管记录为准。保存项目为测试环境 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`,host `local`,cwd `C:/Users/BY-OY/Desktop/code/chongchong-global`;不得跨到开发环境项目。创建阶段仅准备并等待明确开发派工,不因创建自动开始编码、构建、API 调用或环境操作;后续开发授权见下段。
已有文档规划对话“平台销量统计” / `01a12ec3-b0a3-7e81-ab61-fbf9d9a183da` 保留方案及联调依据维护职责。业务输入以 `自营业务/README.md`、`自营业务/领星一件代发数据统计一期方案.md`、`自营业务/领星WMS接口联调手册.md` 和适用项目/模块指引为准;本轮用户经方案对话明确移交开发,一期包含后端任务、事实、统计、平台查询与受控重试 API,以及 Admin 销量分析、库存分析、数据采集三个入口。业务告警与补货另行确认。
用户后续明确授权按最新两份主文档继续开发、集成与离线验收,完成源码、SQL 基线文件、接口和权限合同;这覆盖创建时的等待开发要求。主设计文档继续由原规划对话维护,不并行覆盖。源及业务时区已确认 `Asia/Shanghai`,数量为每个 SKU 的件数 `PCS`,唯一账号、全部授权货主、按仓独立采集;已观测货主数量不成为硬编码上限。正式首采固定两个滚动月,生产独占账号;本轮只实现 `OFF/VALIDATION/BUSINESS`、持久会话预算和隔离,真实出口与发布默认关闭。不执行 SQL、不部署、不触发 Jenkins、不启动真实采集或发布、不读取凭据、不调用真实 HTTP、不自行 Git 提交或创建分支/worktree。总控唯一维护共享 SQL、IAM、Gateway、Admin 导航/根路由和公共门禁;前端模块可交独占内部子代理,不创建额外用户对话。真实启用和人工视觉验收另按现行主方案及工程门禁处理。
| task_id | 对话 | 唯一长期职责及文件边界 |
| --- | --- | --- |
| `01a12f3f-c57a-79e1-9efa-9401f594544c` | 平台销量|领星接口适配 | Integration 领星 WMS 单页/单单接口、DTO、签名和账号配额能力、内部鉴权、本服务 OpenAPI 及直接测试;补仓库目录、出库摘要/详情/按单定位、产品库存。多页采集与完成性判断归采集专项,Lastleg 调用方由采集专项维护。 |
| `01a12f3f-c971-7b62-a0bb-dbdddb091990` | 平台销量|采集与数据发布 | Lastleg 自营分析采集和发布写链,账号发现、分仓任务、共享持久化模型及写 Mapper、租约栅栏、暂存事实、修订、库存快照、覆盖证明、候选日事实/profile、版本发布、恢复、调度和人工任务命令及直接测试;SQL 结构需求交总控集成。 |
| `01a12f3f-ce73-75d2-8fe3-23d709c755d5` | 平台销量|指标与查询接口 | Lastleg 自营分析只读指标和查询,日销量、7/30 天、Top 100、可售天数、数据质量/时效、固定版本分页,查询 Controller/DTO/只读 Mapper、OpenAPI、权限校验及直接测试;只消费已发布版本,不修改共享持久化模型或写入/发布链。 |
开发前由总控明确包/文件归属和共享 DTO、版本及只读接口合同;两个 Lastleg 专项不得交叉修改共享模型和 Mapper。共享 SQL 基线、权限种子、Gateway、导航/根路由、主契约和集成提交由总控统一协调。文档规划对话的现有来源核验不因本次创建改变授权,开发专项不能自动复用其真实 API 授权。
本轮用户进一步明确要求拆分现有重包并发收口,复用上述三个对话,不新增用户可见任务。临时文件写入权覆盖下表原本轮边界:接口适配对话接管 Lastleg `selfoperated/analytics/request/` 及直接测试,完成出口许可、验证预算和冷却回调;指标查询对话接管 `outbound/OutboundCandidateBuilder.java`、`OutboundCandidateTransaction.java`、`OutboundAggregateMapper.java`、`retention/` 及对应直接测试,完成有界候选构建、覆盖聚合和版本引用保护;采集对话保留 `client/`、`sync/`、中立 `model/`、原持久模型/写 Mapper、`inventory/`,以及 `outbound/OutboundFactService.java`、`OutboundPolicy.java`、`OutboundLockMapper.java` 和直接测试。移交区域原写入者停止修改后才释放新写入者;跨包签名和模型变化交总控协调,Maven 由总控串行执行。该临时收口分工不放开环境操作或 Git 提交,不扩展长期职责和创建授权。
所有专项保持当前分支当前工作区,不创建分支/worktree、不覆盖他人改动、不使用共享 Git 索引自行提交;Maven/全量构建窗口由总控协调。此次创建不授权 SQL、数据库写入、部署、发布或真实 HTTP 验收;正式启用仍按一期方案逐仓核验。专项按精确派工交付,结果由总控只读收取,不自动跨对话回信或创建额外对话/持续目标。
## 2026-10-10 采购、拼车与预约的统一页面验收
2026-10-11用户新增并指定浏览器验收对话 `01a12ae6-c6d8-7331-8f26-4d4009f873bc` 加速本轮验收;已核对 cwd 为本测试工作区,归采购总控 `01a12033-95f3-7073-a74a-ef681e7ac470` 协调。新对话第一包仅采购 Client 页面与请求量,使用自己创建的 Client 标签,1920×1080;采购总控继续 Admin 预约/拼车。此次明确分工覆盖下面原“总控独占全部内置浏览器”的范围,仅放开新对话 Client 标签,不放开其 Admin 登录、共享标签、Cookie/storage 清理或全局视口变化。浏览器独立性须实际核对,未证明前按共享会话管理;PDA 390×848 待单独移交视口窗口。新对话只维护 `baiyue-firstleg/reports/client-parallel-acceptance-20261011/` 证据,不改共享进度、主契约、生产代码或触发发布。原拼车/预约开发对话仍不操作浏览器。
该新验收对话第二包获总控移交 PDA 390×848 视口操作窗口,限本轮关联的国内任务详情及海外转运收货/测量作业页;总控窗口期间不操作浏览器,完成后恢复1920×1080。复用根已确认连接TEST的两条本地H5服务,不接管原HBuilder服务、不新增发布;进入页面若必须推进任务,先交最小合成样本准备要求,不领取无关任务。证据仍写其专用目录下 `pda/`,业务代码和共享主契约保持总控协调。
用户明确授权复用以下三个既有对话,由“采购订单-开发”统一安排页面验收,并向另外两个对话发送协调指令。本节仅约束这三个业务的本轮协作,不创建新对话,不扩大环境授权,不改变其他专项的代码归属。
| task_id | 对话 | 本轮职责 |
| --- | --- | --- |
| `01a12033-95f3-7073-a74a-ef681e7ac470` | 采购订单-开发 | 统一页面验收协调;独占内置浏览器,负责三项业务的页面操作、身份切换、请求及截图取证,复核交付并协调发布窗口。 |
| `01a11999-5e90-75c3-9004-9bda35b92ced` | 拼车需求-开发 | 保留拼车业务实现、定向测试和独立会话HTTP验收;交付剩余页面检查清单、样本和证据,修复统一页面验收发现的本业务问题。 |
| `01a11b99-6f9e-7a72-9d91-bdbd5cea051f` | 预约列表-开发 | 保留预约业务实现、日历来源接入、定向测试和独立会话HTTP验收;交付页面检查清单、样本及就绪条件,修复本业务问题。 |
- 页面操作权移交时须确认无在途浏览器调用。拼车及预约对话不再开关标签页、登录、退出、切换账号或清理浏览器数据;交接时也不额外退出共享登录。
- 其他两项可继续不干扰验收样本和账号权限的开发、测试及独立会话HTTP操作。共享文件、构建产物及同一应用/服务的部署仍须协调;部署需求先交统一验收方确认窗口,避免中途改变验收版本。
- 凭据只引用私有环境变量键名,不在交接消息或证据中复制密码、Token。验收方默认使用新增管理员账号2的专用变量;其他对话不修改其权限或采购验收样本。
- 交接清单在原对话回复,由统一验收方只读收取;不因收到跨对话消息自行向其他对话回发消息。仅复用已有成果并补齐缺口,运行版本、已验证场景和未关闭项维护在两份正式主契约中。
## 2026-10-04 用户确认的三个独立执行对话(当前派工)
用户明确选择“按这 3 个独立对话创建”。所属唯一总控仍为 `退税报关` / `01a0d0da-130f-7d43-97b5-9c76abc1b5f1`;本次三个对话不各自建立持续目标。已核对保存项目 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`、host `local` 与 cwd `C:/Users/BY-OY/Desktop/code/chongchong-global` 一致。旧对话保持原状态,不恢复或唤醒。下表为本轮分阶段执行分工,不新增永久专项。
| task_id | 对话 | 职责与文件边界 |
| --- | --- | --- |
| `01a10686-c55c-75a3-9639-655b50cbce6c` | 全流程收口|头程装柜与报关 | Firstleg 装柜/报关实装口径、部分装柜结算、完成预检及直接测试。总控现有内部写入者释放之前,对完成预检/标签文件只读;之后由本对话接管。SQL 基线、受控 SQL、公共文档和发布归总控,不改 Lastleg/Order 或前端。 |
| `01a10686-cae9-7943-b976-27e78ad92723` | 全流程收口|FBA 接口与节点验收 | F01–F40 剩余接口/节点证据审计,优先 F23.2/F25/F27/F33;维护本轮专用 `scripts/fba-remaining-nodes-acceptance*` 和对应测试、`reports/fba-remaining-nodes-20261004/`。经总控复核后追加唯一维护 Lastleg 已有库存转运的本票关联换标:`transfer/service/WarehouseTransferService`、确需的直接 transfer Mapper/DTO/Controller/测试/OpenAPI,以及 `relabel/service/RelabelApplicationService` 和直接测试/调用链。正常库存选择、作业复核及客户确认需能继续至合法转运,实际出库守住换标前置;共享 SQL/权限/主契约和发布仍归总控,其他业务缺陷先交精确复现,不执行废弃批准或扣库存时点选择。 总控另授海外 PDA 主动退出修复:独占 `apps/pda-overseas-uniapp/src/api/auth.js`、`src/pages/profile/profile.vue`、必要会话辅助及对应测试,不改业务换标组件;业务前端仍由页面任务维护。 |
| `01a10686-cfdd-7f50-8500-7704e6fbc768` | 全流程收口|车辆与 PDA 页面验收 | 剩余车辆/司机/PDA 功能页面证据与直接前端修复,报告 `reports/fleet-pda-remaining-20261004/`;另经总控下发精确柜次承担海外 PDA 前置 F27 的正式页面失败恢复,报告 `reports/f27-conversion-recovery-ui-20261004-r1/`,仅指定预计到仓与转换命令,不改共享生产文件。可维护 Admin 车辆/司机与海外 PDA 直接涉及文件及测试;总控追加授权 F33 已有库存转运的本票关联换标前端接入,仅直接转运/尾程 API、组件/测试及确需的海外 PDA 换标显示,后端唯一归 FBA 任务。共享路由/导航/权限、auth/http、其他海外仓主页面及后端仍归总控协调。不得重做已关闭下载和成本场景。 |
总控于2026-10-05追加 F23.2 文件边界:头程装柜与报关对话负责客户实际进港展示缺口,只沿现有客户订单详情的实际 API 链维护 Firstleg 运输事实读取、必要 Order 客户详情投影及 Client 订单详情和直接测试;不改 Admin、PDA、Lastleg、共享认证、权限/SQL或导航。新接口或 DTO 变更须列出生产者/消费者与合同门禁,发布仍由总控串行处理。此项只实现正式交互矩阵要求的本客户已实装货物运输事实展示,不创建第二套客户状态。
三个对话先接受精确交接再工作;禁止覆盖他人改动或使用共享 Git 索引提交。数据库写入、SQL、Jenkins、部署、共享契约、集成提交由总控串行处理;真实 HTTP 每任务单请求流、独立会话,仅在交接明确样本范围操作,退出自己的会话。不得重置、删除数据或伪造业务事件。Maven/全量构建不得并发;总控发放窗口,其他任务可做不争用产物的轻量定向检查。环境文件沿既有授权读取,凭据不输出。
总控追加 F33 收货资源接入文件边界:FBA接口与节点对话可维护 `lastleg-service` 的 `transfer/` 直接收货服务、确需的局部DTO/Entity/Mapper及测试,并唯一接管 `inboundplan/pda/gateway/HttpWarehouseResourceGateway.java` 和对应测试,核对权威收货仓/托盘/库位、现有资源占用、原请求恢复及多来源收货。优先复用既有内部资源合同,不擅改PDA共享作业服务或Warehouse Overseas生产实现。SQL基线、统一SQL、实际数据库与发布仍由总控处理;必要结构先交精确字段/约束。本轮故障代理及F27资源恢复由总控维护,避免重叠。
沟通只保留初始派工、必要的文件释放/环境就绪、最终交付或明确阻塞;禁止“收到/等待/进度”跨对话互回。每个阶段交付一次后停止自主扩展,最终结果由总控只读收取;不自动发送消息、创建额外对话或子代理。部署与验收进度仅更新两份正式主契约,不在登记表复制。
用户于2026-10-05明确调整协作方式:大工作包由现有独立对话承担,具体项目出现阻塞时由总控接手未完成项,并继续推进不依赖该阻塞的工作。接手前明确原任务释放的文件、样本与浏览器操作权;复用其已验证成果,仅处理缺口,不重复整条流程。总控不以等待专项回复为停止其他可执行工作的理由;确属工具或外部条件限制时保留未验证边界,不虚报完成。
总控追加F27原操作恢复边界:头程装柜与报关对话唯一维护Lastleg `inboundplan/service` 的转换预览/恢复状态、直接Mapper/DTO/测试,以及 `mapper/LastlegOrderMapper.java` 的柜级待资源计数和直接测试;仅沿确切消费者核对入仓/PDA资源确认门禁,不接管转运/换标。车辆与PDA页面对话唯一维护Admin `LastMileOrdersView.vue` 及直接测试的原资源恢复入口和门禁。FBA接口对话继续独占原F33转运执行;三个样本范围互不混用。总控负责共同合同、编译、发布和现场故障运行窗口;工具或只读审计脚本的临时文件以精确派工为准,不由专项自行执行共享环境变更。
## 2026-10-04 全流程唯一持续目标与车辆交接(当前)
总控追加F33页面入口最小实现边界:FBA接口与节点对话独占 Admin `api/warehouseTransfers.ts`、`components/WarehouseTransferFulfillmentPanel.vue` 及直接局部组件/测试,承载既有库存转运正式出库与逐来源目标仓实收。车辆与PDA页面对话释放上述转运文件,仅继续F27恢复页面;`LastMileOrdersView.vue`不交叉写入。共享路由、权限、SQL、集成和部署仍由总控处理;实现任务先本地定向检查,不自行重跑已通过HTTP链或改变共享环境。
本包后端持久实收查询由头程装柜与报关对话唯一接管 `WarehouseTransferResponses`、`WarehouseTransferService.detail`、`WarehouseTransferReceiptCoordinator`、确需的 `WarehouseTransferReceiptCommandMapper` 及直接测试/OpenAPI;仅向既有详情提供本客户本票的原实收请求、状态和权威目标,保证跨浏览器续作及完成响应一致。FBA接口任务本包不写后端;不新增出库命令表、不改SQL或转运写入规则。编译、运行验证和发布仍归总控。
总控核对F33主/子状态后,本批后端边界进一步包含 `WarehouseTransferService.outbound/receiveReserved` 和 `RelabelApplicationService` 的既有库存转运完成回调及直接测试:保持本票已经成立的INBOUND_COMPLETED,仅推进转运子单与子状态。原来源订单、来货转运另一履约链及真实派送主链不得误改,不回填旧记录、不执行SQL;任务2仍只维护本批Admin入口。
总控追加F33预留所有者保护包:头程装柜与报关对话唯一维护必要的转运预留查询/守卫、`InventoryCommandService` 直接调用及测试、`DispatchCandidateMapper` 的候选/锁定归属校验、`PdaPalletOperationService` 拆合托入口及直接测试。禁止凭可由外部伪造的业务号/幂等前缀绕过预留,只允许服务端核对后的本转运消费者使用;保持独立逻辑预留模型,不改HOLD模型或泛化封禁保留身份的整托移库。该任务获得空闲本地Maven窗口,仅串行受限最小红/绿回归;总控此时不另起Maven或全量前端构建。真实环境样本及页面由总控和页面任务独占,专项不HTTP/SQL/部署。
总控追加废弃确认重放最小边界:FBA接口与节点对话唯一维护Lastleg `PdaCargoDiscardService.confirm`及直接测试,只修复已完成单/托的相同完整载荷恢复及异载荷/越权拒绝,不改变首次扣减时点、审批状态设计、SQL/API/权限。业务时点等待用户明确选择,专项不批准或实际废弃测试货物;独占本地串行受限Maven窗口。头程装柜与报关对话同期只在`reports/wallet-mid-transaction-20261005-r1/`准备单一合成资金指令中途故障工具,不修改生产或运行构建,不执行HTTP/SQL/部署。最终集成、共享主契约和环境操作仍归总控。
总控另授车辆与PDA页面对话仅在`reports/auth-validate-timeout-20261005-r1/`准备指定合成PDA账号/会话的Gateway→Auth权威会话校验超时工具及离线测试。只沿直接认证协议和已有依赖故障工具复用,不能写生产代码/共享脚本,不能关闭校验或影响其他账号。该任务不执行HTTP/SQL、运行配置切换或部署,不占Maven窗口;无法精确匹配或恢复时交源码依据,不扩大故障范围。实际故障窗口与恢复仍由总控独占执行。
用户在车辆对话明确要求:“当前的目标先停掉,只有总控一个目标”。已核对该对话的用户原文;当前唯一持续目标属于 `退税报关` / `01a0d0da-130f-7d43-97b5-9c76abc1b5f1`,保留F01–F40全范围,并统一收口下述车辆首版完整闭环。车辆对话 `01a0f19d-3f0b-7ae0-a860-c0d1d2e84475` 和三个既有专项停止自主全目标循环,仅保留原task_id、代码归属与交接证据;不得自行继续环境写入、发布或故障注入。没有创建新任务、恢复归档任务或标记车辆已完成。
唯一总控负责共享环境发布、串行Maven、数据库/故障窗口与最终验收。专项若获明确后续派工,只执行所分配阶段和文件边界;不各自建立持续总目标。当前对话仍遵循不自动回信的约束,交接与必要现场核对采用只读方式,不能凭另一任务来信自动授权消息回复。目标工具不支持修改一个活动目标的objective正文,不能把未完成原目标标complete来替换;车辆范围按本次确认纳入同一执行范围,原FBA目标保持active。
原车辆总控冻结的异常实收/重派关联10文件交给唯一总控集成,保留原冻结SHA和编译失败。总控只修复已交接的测试编译歧义、验证该冻结批次并按后端先于Admin安排发布;不将其他共享未提交修改一并暂存。两份正式主契约仍是部署、已验场景和未关闭项的唯一事实入口,本登记不复制进度。
### 原2026-10-03车辆四任务职责(保留文件边界,停止自主目标)
用户本轮明确确认:“确认创建三个任务,我们当前目标调整一下,加上自己,一共4个任务,一起处理,尽量把车辆的跑通”。本次车辆协作覆盖下方旧车辆专项归档状态,其他旧任务仍保持归档,不自动恢复。
- 原车辆总控:`01a0f19d-3f0b-7ae0-a860-c0d1d2e84475`,host `local`;当前转为交接入口,原车辆/司机、共享入口/权限/SQL、构建发布及最终验收职责由上述唯一总控接管。以下专项文件边界保留,未经新派工不自主继续。
- 项目固定为测试环境 `c64729ff-6710-43c6-8ef2-d84e9666cc1e`,工作目录 `C:/Users/BY-OY/Desktop/code/chongchong-global`。所有任务在当前分支当前工作区操作,不创建分支/worktree,不混入开发环境。
- 车辆原目标保持完整:以原型梳理与当前正式合同为准,完成车辆/司机、车次、自有及外接、成本财务、报价统计、异常、页面和PDA闭环;不能以单模块绿灯认定全部完成。
| task_id | 独立任务 | 稳定职责及写入边界 |
| --- | --- | --- |
| `01a0ffcf-7150-7db3-9d8c-108e568c12b1` | 车辆管理|成本与财务闭环 | 独占FleetTripCost系列后端、直接测试/OpenAPI、Admin tripCosts API和TripCostPanel及其测试;负责后续维修救援成本与Finance衔接。共有表结构、权限和车次页签由总控集成,Finance共享入口变更先列明路径。 |
| `01a0ffcf-eea3-7111-b30b-4be63547ac33` | 车辆管理|报价与运营统计 | 独占新增Lastleg fleet/quote、fleet/reporting及各自测试/OpenAPI、Admin独立报价/运营页面和API;不修改成本写入和车次执行。共享导航、路由、权限、表结构与导出注册交总控集成。 |
| `01a0ffd0-2a4d-7210-bad8-a790cd965e8a` | 车辆管理|在途异常与改派 | 独占新增fleet/exception及在途相关组件、API;按正式派工接管FleetTripService/Execution/Completion、资源及实际dispatch/PDA调用链。共享FleetTrip模型、接口和PDA入口先交总控协调;不改成本、报价统计及其草稿。 |
本轮已释放给在途专项的共享接入:`lastleg-service/src/main/java/com/baiyue/lastleg/fleet/trip/FleetDispatchGateway.java`、`lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/fleet/DispatchFleetAdapter.java`及对应专属测试。限定在途交接的目的地/实物托盘/派送终态只读依据,不改库存数量或重写原DEPART。已有`FleetTripPersistenceTest.java`、`FleetTripApiContractTest.java`、`FleetTripAuthorizationTest.java`归在途专项直接消费者维护;新`FleetTripCost*Test`仍由成本专项独占。
总控统一管理 `TripDetailView.vue`、模块路由/导航/权限、共享FleetTrip模型接入、IAM权限种子、模块与统一SQL、主契约和公共验收入口。独立任务不得部署或执行SQL,不同时启动Maven/全量前端构建;定向检查可自行执行,Git提交由总控统一选择,避免共享索引冲突。真实环境沿用户授权使用 `C:/Users/BY-OY/.codex/env/chongchong-global`,凭据不输出。共享未提交改动不得覆盖、暂存整库或回退。
2026-10-03 用户再次明确要求提高四任务并行效率,解除“所有验收均等总控亲自操作”的瓶颈。总控发出匹配版本就绪通知后,三个专项分别承担自身TEST真实HTTP、页面验收与修复;每任务仅一个串行请求流,独立登录会话及新建样本,不争用对方记录,不并发操作同一车次/库存或凭证。成本范围标记`FLEET-COST-20261003`、报告`reports/fleet-cost-live-20261003`;报价范围标记`FLEET-QUOTE-20261003`、报告`reports/fleet-quote-live-20261003`,不操作库存;在途范围`fleet-handover-20261003`、报告`reports/fleet-handover-live-20261003`,独占本轮客户、货物、车次和PDA作业员。各自保留失败与原请求,结束退出自身会话并恢复自己的测试资源,禁止删除或重置数据。运营统计只读消费在途任务已验证且冻结的当前轮DEPART事实;由总控转发,不复用历史样本冒充新链路。用户授权的测试环境范围不扩大到开发或生产。
在途专项追加独占`scripts/fleet-test-env-acceptance.mjs`及直接测试,负责将新交接验收挂在实际DEPART后、签收前;新`fleet-handover-acceptance`模块归在途专项,`fleet-company-cost-acceptance`归成本专项,`fleet-quotes-operations`归报价专项。总控保留公共Admin入口注册、权限、SQL及发布。
为消除发布串行瓶颈,在途专项另获海外PDA H5独立发布单元:仅测试`pda-overseas-h5-test`容器及既有Compose项目/网络,使用已固定源码与编译资产,核对健康和首页摘要;不得操作国内PDA、原生APK、后端或网关。三后端与Admin发布、共享SQL仍由总控收口。
混合履约后续接线继续复用三任务:成本专项唯一维护新增`SourceDeliveryCompletionPolicy/Query`、`DeliverySourceEvidenceMapper`及直接测试,并接管`DeliveryDocumentService`、`DeliveryCompletedOutboxService`和直接测试,按真实来源签收证明接既有完整签收事件;在途专项唯一维护退回入库来源及dispatch候选/预排/PDA拣货重派链和Admin海外仓对应直接调用文件;报价专项负责独立运营验收和只读交叉复核,不修改被复核者文件。共有SQL、权限/导航、发布仍由总控处理。新结构本地准备不等于已执行TEST,国内异常结案业务选择不由专项自行决定。
车辆总控进一步释放报价接线:报价专项唯一维护`FleetBookingService/Models/Entity/Reservations`及其直接测试/外接预订OpenAPI、Admin `bookingTypes.ts`、`api/tripBookings.ts`、`TripBookingPanel.vue`及直接测试,接入可选销售报价来源版本;保留`3440f9d`详情关闭后编辑修复。总控保留`FleetBookingQuoteContext`、`FleetWarehouseClient`及直接测试、全部SQL/权限及共有装配。异常专项继续独占车辆验收主入口,接入成本专项的`fleet-trip-cost-acceptance`助手和两类独立权限会话;异常退回缺陷仅沿实际调用链扩展局部实现,新增结构/权限由总控集成,不改其他任务的普通签收/F40流程。
本轮车辆总控追加释放:成本专项唯一维护Lastleg `fleet/maintenance/`及直接测试/`fleet-vehicle-records-v1.yaml`、Admin `VehicleCareTable.vue`、`VehicleCareEditor.vue`、`api/vehicleCare.ts`及直接测试,负责维修/救援公司成本命令和状态接入。保留#493空字段初始化与无变化不写入修复;公共事件配置、File类型、编号、SQL/权限仍由车辆总控集成。此为上方当前四任务的文件分工,不恢复下方历史任务。
## 2026-10-03 归档与重新规划
用户要求归档此前分配的对话并改为分阶段处理。下表四个独立任务及此前车辆专项 `01a0f19d-3f0b-7ae0-a860-c0d1d2e84475` 均已确认归档;下文职责与授权仅保留为交接历史,不再据此唤醒、派工或自动恢复。当前对话保留为汇总与规划入口,新对话数量及职责待用户确认后建立。
归档不删除工作区代码或报告。用户随后明确要求当前对话继续处理不依赖车辆的逻辑;本对话直接接续非车辆工作,不唤醒以上旧任务。F23原柜改船已接续提交、部署并完成既有船期编辑的双端验证,具体版本、证据与未覆盖项唯一见[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md)。车辆后续独立授权与职责以上方当前登记为准;归档本身不代表功能完成。
2026-09-09 的旧登记保持作废。下列任务根据用户 2026-09-30 的明确请求重新创建:用户要求“使用多个独立任务处理(不是子智能体)”,并确认“按4个创建,你直接负责汇总”。不根据旧台账恢复或派工。
## 所属总控与项目
- 总控:`退税报关`,`task_id=01a0d0da-130f-7d43-97b5-9c76abc1b5f1`,host `local`。
- 项目:测试环境,`projectId=c64729ff-6710-43c6-8ef2-d84e9666cc1e`。
- 唯一工作目录:`C:/Users/BY-OY/Desktop/code/chongchong-global`。不操作开发或生产环境,不创建分支、worktree、项目副本或内部子代理。
- 目标:按当前正式文档完成 F01–F40 逐节点验收。实现、服务测试、部署、真实 HTTP、页面验证分别记录,不能用局部绿灯代替全流程完成。
## 稳定职责与文件归属
| task_id | 独立任务 | 稳定职责及写入边界 |
|---|---|---|
| `01a0f14c-9262-7b43-990a-0e3beddcdd8a` | 全流程节点验收|头程与海运 F01–F24 | 头程与海运未闭环完成条件;只改对应头程/海运验收模块及其合同。国内 Firstleg 报关/船节点实现如需修改,先向总控列明精确文件,避开完成回写任务负责的消费者。Order 实现由完成回写任务维护。 |
| `01a0f14c-962f-73c3-b1aa-9df555b91586` | 全流程节点验收|海外收货库存与出库 F25–F37 | 接柜、收货、库存、出库及完整库存重放取证;维护 Phase4 收货脚本/合同、只读收货取证器,以及 Lastleg 后端实现与直接测试。跨到派送的 Lastleg 修改统一由本任务落地,避免后端多人写入。 |
| `01a0f14c-9a66-7f61-bc2b-6ad17a6c940a` | 全流程节点验收|签收余量与完成回写 F38–F40 | 双片真实签收、合法末票余量取消、根订单完成和反向回写;维护 F40/Phase5 专项脚本及合同、Order 完成聚合、Firstleg 完成消费者。涉及 Lastleg 实现的缺陷经总控转交海外库存任务。 |
| `01a0f14c-9e33-7a01-903d-a5febd50774b` | 全流程节点验收|平台客户页面与下载 | Admin/Client 真实页面操作、状态、文件上传下载和隔离;维护直接涉及的前端业务代码/合同。已有排车样式任务的文件不在本任务写入范围,遇重叠由总控协调。 |
## 调度与环境约束
- 用户已授权本轮测试数据库、真实 HTTP、页面及测试环境部署操作;具体环境文件只从用户指定的 `C:/Users/BY-OY/.codex/env/chongchong-global` 定向读取,凭据及 Token 不写入代码、文档或报告。
- 独立任务先由总控发送精确交接,再开展所属职责。当前文件尚有前序写入者时先只读,收到明确释放后才能写入。禁止覆盖、提交或回滚他人修改。
- 总控负责共享部署、Jenkins、SQL 执行、Maven 构建串行调度、共享入口/权限/初始化 SQL 和主流程文档汇总。独立任务不得自行部署、执行 SQL 写入、重置或删除数据/文件;需要这些操作时交付具体内容由总控处理。
- 独立任务可在正式派工指定范围内执行测试 HTTP;每个任务使用独立标记及新造测试客户/订单,只操作自己创建的数据。共享托盘、库位等资源变更须先协调,不能触碰其他任务的原验收样本。
- 必要派工及汇报仅围绕这四个任务与所属总控开展;独立任务把当前事实、文件、检查结果和阻断交给总控汇总,不扩大到其他聊天或新任务。
- 不改变统一架构专项及其他已在进行任务的范围。当前事实依据正式维护入口;历史报告仅证明对应版本和范围。
Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

+29
View File
@@ -83,6 +83,35 @@
## 七、验收主链 ## 七、验收主链
### 客户订单列表的分页与待办读取
- 客户订单首页使用 `GET /api/merchant/v1/orders/workbench`,客户范围只取认证上下文,权限为 `merchant:order:list`。接口一次返回当前页、筛选后总数、全部/待费用确认/装柜完成/已报关/已清关/已排车/派送中/派送完成/待上传报关资料/草稿十项数量及该客户完整渠道名称选项;不能先取前 200 条再在浏览器分页或统计。
- Order 在数据库内应用入仓码或 SKU、收货仓、渠道、目的仓类型、快递单号、创建时间、当前状态及待办筛选。草稿排在前面,同组按创建时间和订单 ID 倒序稳定分页;默认每页 10 条,上限 200 条。`DRAFT/CANCELLED` 是订单交易状态在客户读模型中的直接展示,不新增履约推进节点;默认列表排除已取消单。
- Firstleg 通过受内部服务令牌保护的 `/internal/firstleg/v1/inbounds/unified-orders/workbench-filters` 提供当前客户匹配的履约和待办订单范围。费用待确认只取最新费用版本的未确认 `SENT`;报关待上传取最新已完成装柜计划、有效货柜及尚未上传齐当前客户退税入仓码资料的范围,不受同柜其他客户未上传影响。查询不创建报关记录、不更改船或柜、不跨 Schema 读表。
- 切换分类和刷新期间保留上次已确认的分类数量,最新响应完整校验后统一替换,避免数量先归零再恢复;请求失败明确报错并清除失效数量。重复点击当前分类不重发请求或重置页码,错误态允许点击重试。翻页、换每页数量和筛选均重新请求服务端;快速切换时旧响应不得覆盖新页。筛选数量随当前条件计算,资料或费用确认后重新读取。分页响应不完整或依赖服务失败时明确报错,不能回退旧查询或显示成功的空列表。
### 客户头程订单履约分类
- 分类不是新增订单主状态。当前分类优先级为装柜完成、已报关、已清关、已排车、派送中、派送完成,采用已确认的最高当前进度;费用确认、报关资料上传是并行待办,可以与履约分类重叠。分类数量随当前查询条件计算,不从当前页推算。
- Firstleg仅按客户实际装载片段读取有效货柜:装柜计划和实际拣货完成才算装柜;报关聚合`COMPLETED`才算已报关;目的港标准节点`PICKUP_READY`存在实际时间才算已清关。上传、回执确认、正式申报、预计时间和较晚船节点不能补造缺失清关事实。
- Lastleg通过`POST /internal/lastleg/v1/customer-order-progress`只读返回认证客户来源订单的尾程进度。Order使用内部服务令牌调用,公网Gateway不公开该接口,不跨Schema联查。该查询依赖Lastleg可用,失败明确报错,不返回假的零数量。
- 已排车取正式排车单`PENDING_DEPARTURE/PICKING/READY_TO_DEPART`的有效货物;预排草稿、取消排车不计。未收货托盘按计划分配来源,实收托盘按实际库存与本次拣货还原所有来源,混托不能用代表订单号归属整托。
- 派送中必须有`DEPARTED + departAt`、关联出库`OUTBOUNDED`及对应目的地派送单`WAIT_DELIVERY/DELIVERING`;生成派送单不表示开始派送。取消、拒收、待退回及退回分支不伪装为正常派送中,原运输事实留在详情。
- 分批履约返回`partial`,列表显示“部分装柜完成/部分已报关/部分已清关/部分已排车/部分派送中”。根订单合并自身及全部有效子单进度,子单继续独立展示;未同步尾程片段不能算整单完成。派送完成只认Order既有可信完成门禁,不凭某张派送单签收推定根订单完成。
- 工作台响应`progress`与当前页订单一一对应,未到装柜阶段返回`none`并显示“—”;列表及导出保留当前订单状态并单独展示履约进度。历史节点仍由详情中的真实运输片段承载。
本次列表交互以用户提供的分类栏截图为依据:横向可滚动分类、计费待办角标、履约分类括号数量和右侧工具栏。截图未覆盖的“派送完成、上传资料、草稿”沿当前入口追加,履约进度列用于区分主状态与客户进度。详情、编辑、计费确认、资料弹框的承载方式沿现有实现,本次不改变。
列表交互核对范围:
| 页面/操作 | 原型依据与承载 | 实现口径 |
|---|---|---|
| 头程订单列表分类 | 用户提供分类栏截图:列表内横向滚动,计费角标、履约括号数量 | 按截图次序展示七个入口,随后保留完成、资料和草稿;筛选重新请求服务端 |
| 列表状态展示 | 截图保留当前订单状态列;已确认方案补充履约进度 | 主状态不改义,新增可选履约进度列,部分事实明确标注“部分” |
| 订单信息导出 | 原列表工具栏按钮与CSV下载承载 | 同步导出主状态及履约进度,不新增弹框 |
### 履约主链
```text ```text
客户提交订单 客户提交订单
→ 平台审核 → 平台审核
+231
View File
@@ -0,0 +1,231 @@
# 统一认证与服务通信契约
2026-10-15 23:58 用户确认本轮均为测试假数据,无需真实外部业务材料;此前对应阻塞撤销。现有自提样本经统一Gateway的25项只读复验通过,独立会话已退出;当前发布提交及健康一致。结合已完成的权限、稳定批次/消费者、四端页面请求和性能验收,本轮测试技术验收完成;不将合成预约PENDING或无真实POD作为认证/通信缺陷,也不宣称真实货物履约完成。完整结论及证据见测试环境主契约最新记录。
本轮最终版本Lastleg #339/Admin #624健康且实际提交匹配。目的仓冻结值修复经原样本25项GET-only检查和页面复核通过,单详情1个GET/51ms,浏览器logout200后关闭。#339最终保留首轮并补足两轮共36次搜索全部<1秒、最大973ms,完整语义同#334;两个性能验证会话及只读复验会话均注销。下述21:46记录的SKU目的仓缺口现已关闭,无新增Token、权限、路由或事件变更。
2026-10-15 21:46 同轮补验:Lastleg #338 新建退货换标直接出库复用现有受服务身份保护的 IAM 客户与 Warehouse 仓目录,各读取一次并校验主体后冻结名称;重放不重复目录查询,列表/详情读取快照,不新增跨服务逐行补全。新合成样本37项真实HTTP通过,三独立会话注销、无残余盘点会话;当前测试搜索36次全部小于1秒、最大808.4ms,完整语义同原基线。SKU目的仓页面缺口仍在补修,当前发布及最终验收以《测试环境单机部署与配置契约》的最新记录为准。本次未改Token、权限、Gateway路径或事件协议。
2026-10-15 预约工作日历 TEST 权限补验:IAM #177 已发布,两项新增权限 `platform:appointment:manage-work`、`platform:firstleg:terminal-drayage:direct-unload:confirm` 及平台管理员关联已按匹配 SQL 落库。独立新登录确认权限集合含两项权限,工作全局摘要、月日历、事项分页均经统一 Gateway 返回 HTTP 200/业务 200,验证会话退出成功。工作跟进 11 项 HTTP 检查已覆盖匿名/客户域拒绝、只读平台写入拒绝、正确 Auth 主体负责人、幂等与旧版本拒绝;首轮验收 fixture 把 IAM 档案 userId 当成 authUserId 的失败保留,确认未落库后修正复验。Admin #619 另修 JWT 数字长账号 ID 解码精度,真实解码→登录/恢复→负责人提交回归及最终 3,197 项前端测试通过,不改变 Token 签发和权限模型。18:48 独立托盘默认分组复验经 Lastleg #334 的 11 项检查通过,省略分组、重放及跨组拒绝均经统一 Gateway。19:14 Firstleg #497/Lastleg #335 批量事实读取修复后,九类查询各三轮及三路并发各三轮共 36 次统一 Gateway 请求全部 HTTP 200/业务 200、小于 1 秒,完整返回语义与旧版一致;后续 #336 的超标复测另保留。20:06 Firstleg #499 再缩小批次来源聚合范围后,同样 36 次请求全部小于 1 秒、最高 819.8ms,完整语义与原基线一致,当前性能边界以主契约最新补验为准。21:11 Lastleg #337/Admin #623 发布后,同样 36 次统一 Gateway 请求仍全部小于 1 秒、最高 928.9ms,完整语义不变。换标三种自提直接出库、未绑定确认拒绝、纯 SKU 数量守恒及成功后幂等重放已用独立合成样本经 Gateway 验证,首次脚本数量类型误断言保留并按原批续验通过,六个自有登录全部注销、盘点会话为空。客户详情精确进度联合发布后,12 项 HTTP 检查覆盖原票状态与列表一致、跨客户 A0404 无数据及自有会话退出。未改变 Token、权限或 Gateway 路由;Admin 首次浏览器退出取证被过早关页中断,不能判定产品缺陷,该会话已补充正式撤销,Client/PDA 浏览器退出均有 HTTP 200。发布版本、精确重建、实物消费证据、性能样本边界及未关闭项以[测试环境主契约](测试环境单机部署与配置契约.md)“预约工作日历 TEST 发布与定向联调”节为准。
2026-10-12 自营统计 TEST 身份验收进行中:六项权限及平台管理员关联已落库;独立最小只读平台身份可以查询、不能提交采集命令,无权限平台身份被 A0403 拒绝,客户身份不能进入平台统计域,匿名请求为 401/A0401。平台管理员在采集 OFF 时收到中文业务拒绝 B0001,未新增任务;内部调用无令牌被 A0401 拒绝,Lastleg 出口预算授权在 OFF 时被 `EGRESS_MODE_REJECTED` 拒绝。首轮业务查询验收脚本的六项错误已按正式合同修正,r2 完整 Gateway 矩阵 86/86 通过;这只证明合成查询和当前身份边界,不外推为真实来源、性能、发布恢复及人工页面验收。发布版本、合成数据边界及未关闭项统一见测试环境主契约“自营统计 TEST 发布与验收”节。
2026-10-08 TEST回归后灰度发布、10月9日恢复核对:灰度IAM #10更新至 `d4eb0ef0233c`,权限5107004与唯一关联主体授权版本按现行契约同事务同步,未改角色授权;新会话的废弃审批及八类导出所需权限均核对通过,正式HTTP验收后已退出。六部署目标与17容器健康、TEST故障恢复证据、灰度验收边界详见测试环境主契约“TEST 回归后灰度发布”节;不能将运行健康或接口冒烟外推为灰度全流程及真机均已验证。
2026-10-08 TEST 汇总发布补记:IAM #176部署 `6b6d217774be`。废弃审批权限5107004及精确两个关联主体授权版本已同事务按当前合同同步,未扩大角色授权;新登录权限集合已包含现行 `platform:overseas-warehouse:discard:approve`,验证会话正常退出,旧会话需重新登录。发布范围、版本和非全量验收边界以测试环境主契约“当前代码汇总 TEST 发布”节为准。
2026-10-08灰度拼车角色页面补验:专用两销售按本人意向隔离,报价库入口按权限显示;最小调度可确认承运,客户A可见自身商业订单、客户B列表为空。海外PDA浏览器初次登录暴露Gateway CORS漏配两个PDA Origin,已同步灰度持久环境与Jenkins环境文件并仅重建原镜像Gateway;四合法前端Origin通过、其他Origin仍403,海外PDA真实登录、收货与整车发车均通过。此前无Origin HTTP冒烟不代表此浏览器边界已验证。本轮证据、保留账号及硬件验收边界见测试环境主契约同日“灰度拼车角色页面与 PDA H5 补验”节及 `reports/gray-ui-20261008/`。
2026-10-08新增拼车灰度专项通过:独立GRAY入口735项HTTP断言通过,包含两销售同姓名不同身份隔离、无权确认/他人修改拒绝、客户不能读内部池及其他客户商业单;两类本土订单从实际收货至完成及唯一费用已核对,临时角色/账号停用与会话注销记录保留。取证绑定灰度production容器与数据库,不回落TEST;精确批次、creation_mode字段修复及终态回查见测试环境主契约同日拼车专项节。
2026-10-08内部拼车首版已发布临时灰度:IAM新增五项池权限及平台管理员授权,灰度新登录经统一Gateway和Admin公网代理均能读取池、本人/全部意向及仅id/code/name客户目录,退出成功。Lastleg/Admin/Client灰度版本、SQL精确范围及资源SHA验证见测试环境主契约同日发布节;其余认证服务、Gateway与PDA未重新发布。该冒烟不替代TEST的跨销售/客户隔离和完整业务链证据。
2026-10-07内部拼车需求池TEST身份验收:`reports/fleet-cross-pool-20261007-r5/report.json` 732项通过,独立r5审计核对原始响应与库存证据,其中两名同显示名、不同登录ID销售按本人意向隔离,最小调度manage权限可处理承运;销售不能确认占位,Client不能读取平台池,池来源商业单旧手工操作旁路被拒。凭据与会话均经统一Auth/ Gateway,执行后退出脚本会话;该HTTP证据不替代两端角色页面验收。Admin真实浏览器打开发布详情时自然遇到401,随后一次refresh200、权限快照200、原详情重放200,未形成多次刷新循环;网络与响应证据分别为 `reports/capacity-pool-20261007/admin-pool-detail-network.json`、`admin-pool-detail-status.json`。该场景首次详情有一次认证拒绝和一次成功请求,不能计作零认证重试的单次请求。本轮最小销售、调度及客户页面与请求预算已完成分层核对;48条最终合同映射必要未关闭项为0,部署版本和各证据层级以测试环境主契约及 supplemental-ui-audit.json 为准。报价正向补证为本地组件/API测试,不扩大为真实HTTP声明。
2026-10-07灰度退税 FBA 定向闭环补证:主单 `FL2107698725471256577` 及其余量单通过统一灰度 Gateway/Auth 完成国内装柜、报关、人工船节点、海外 PDA 收货、发车签收和完成回传,1325项断言通过。收货库存与原键重放使用灰度数据库只读快照核对;两来源完成 Outbox 各唯一一条 PUBLISHED,pending/failed均0,签收资料重复保存未新增完成事件。独立新会话回查主/余量订单均 COMPLETED、入仓均 DELIVERED;此证据仅证明本轮正常业务链和所执行的幂等边界,不代替灰度故障注入或 TEST 默认全量。准确版本、过程两次失败、脚本选仓修复、月度测试汇率及未覆盖范围见[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md)临时灰度节;原始证据 `reports/gray-release-20261007/gray-flow-tax-r3.json`、`gray-flow-tax-final-verification-r3.json`。
2026-10-07临时灰度统一认证已实际部署并验证:四端共用独立灰度Auth、签名密钥、Redis会话前缀和Nacos命名空间;两个API域名指向同一Gateway,不再运行独立海外Gateway或事件桥。四角色登录、权限、核心读取及Access/Refresh撤销48项通过,四个各自公网入口追加16项代理/登录/退出检查通过,JWT均为本次灰度签名身份;没有将内部服务接口暴露到公网。灰度旧Redis用户名错误已修正,临时管理员密码对齐用户安全配置,新建验收客户和国内PDA经正式接口创建。详细运行版本、账号交付位置、过程失败及验收边界以[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md)的临时灰度发布节为准。
2026-10-05本轮收口:用户明确跳过测试邮件/告警通知、外部船司自动查询以及V02凭证图片像素核对,均记录为“用户跳过”,不计为测试通过,也不关闭产品功能。结合下列最新补验证据,本轮约定范围已完成;最终范围、运行版本及保留边界统一见[测试环境单机部署与配置契约的最新验收状态](测试环境单机部署与配置契约.md#本轮最新验收状态2026-10-05test)。下方各日期记录保留当时证据范围,不将旧待补验描述作为新的阻塞。
2026-10-05 0A首次同/异hash并发补验:两组隔离合法换标业务先持本客户账户行锁,真实MySQL锁等待证明原自然消费者持有Inbox且两个手工请求在首次结果未成立时并发等待。门锁分别1.046秒/3.868秒;same原事件a92f9c14-548b-4119-b94e-7fc6c4e8d30c两手工DUPLICATE,different原事件8baa9074-d60a-4c33-90a9-aaab356a9697的不同载荷只改remark、实际运行库Java校验合法摘要,返回FIN-EVT-002身份冲突(不是坏摘要)。原自动消费者加两个手工请求分别留下完整时序与SQL锁链;每组唯一0.01冻结及唯一结果、源Outbox/结果Outbox PUBLISHED、Lastleg结果Inbox PROCESSED。只读终态复核、会话退出、账户锁连接/锁0、运行指纹/健康未变及远端临时文件清理见后端reports/wallet-first-execution-concurrency-root-20261005-r1/root-independent-review.json与root-final-runtime-cleanup.json;11份原文件已归档。关闭此首次并发要求,不宣称其他消费者或全局压力测试通过。
2026-10-05 结果提交失败原子性补验:合法RL-WH-20261005-264066原指令00c6799d-743c-4137-a499-c1a3a852e835在资金及成功结果Outbox均写入同一事务后,于最后UPDATE Inbox命中限定SQLSTATE45000/1644;资金余额/版本、hold/ledger/idempotency及本命令结果Outbox全部回滚,仅事件身份PROCESSING持久化。删除唯一触发器后同原事件/hash/envelope自然恢复,唯一0.01冻结及结果2e63d316-fbf3-4a5b-a74d-0e008c6d07bb的PUBLISHED/Lastleg PROCESSED均成立。触发器回查0、会话退出、服务容器/配置/网络指纹与健康未变;其他账户摘要未变,库存按合法重新预留与故障后恢复两个阶段核对。后端reports/wallet-result-commit-20261005-r1/root-independent-review.json复核18项原始条件及证据SHA,保留先前合法余额不足FAILED事件。本次关闭对应原子性与原事件恢复缺口;首次同/异hash并发由本文件开头另列的独立场景补证,不冒充已找回历史原0A报告。
2026-10-05 Client退出补验关闭:修复随Client384发布,当前385只追加报关统计文案。正常UI退出恰好一次带Bearer的logout200/200,返回登录页;原Access尚未过期即被受保护接口401/A0401拒绝,原Refresh为HTTP200/A0401。自然过期分支使用独立正式登录会话,原Access于11:02:51 UTC到期后实际确认退出,完整网络严格为logout401/A0401→refresh200/200→logout200/200,只有一次刷新;原与替换Access/Refresh全部被拒,替换Access在11:06:36 UTC验证时尚未到11:27:34 UTC自然到期。身份长整数以私有原JWT精确核对,原及替换Bearer与真实UI请求匹配;未改时钟、TTL或伪造响应。后端reports/f22-201-browser-20261005-root-r4/final-result.json、normal-logout-independent.json、expiry-independent.json及网络/DOM/截图为证据,客户端自建标签已关闭、临时视口恢复。仅关闭该客户端正常与自然过期退出分支,不外推未运行的并发或未知传输分支;部署及其他未关闭项见测试环境主契约。
2026-10-05 自然租约与旧持有者CAS补验:新合成换标RL-WH-20261005-915970的WalletCommandCompleted结果a109b5d8-2ff6-4d00-bfba-bf17594b6012由独立非Spring JVM使用当前Finance125生产Relay/Journal领取一次;真实内部ACK已收到后,本进程屏障等待原60秒租约自然过期。正式共享Finance在62020ms标LEASE_EXPIRED、按原退避另由新owner获得DUPLICATE/PUBLISHED;先保存独立SQL快照,再放行旧真实ACK,原deliver返回前后Outbox、两审计及本包Finance/Lastleg业务数据完全不变,唯一0.01冻结。没有改锁时间/重试时间/TTL、暂停共享服务或假ACK;生产类库/容器/配置/Nacos未变,临时JVM/worker退出且自有文件清理。后端reports/outbox-lease-live-20261005-r1/root-business-verification.json、root-ledger-verification.json、root-final-verification.json及其运行证据为依据。仅关闭指定生产Relay/Journal的晚到成功CAS;一次性客户端为JDK真实HTTP,不宣称Feign故障、全部消费者或压力测试通过。
2026-10-05 船节点限定消费补验:独立新柜D1442/TSTU1527735正常装柜事件APPLIED后,3条受内部服务身份保护的直接请求依次得到APPLIED、STALE、EVT_PROTOCOL摘要冲突。新事件ID的低版本/低节点不回退有效事实;原eventId配不同但规范合法的payloadHash拒绝且原Inbox/gate不变,捕获的客户订单/库存及原装柜Outbox/Inbox/投递审计不变。后端reports/shipping-event-canonical-20261005-r1/root-final-verification.json与root-original-source-unchanged.json为真实HTTP/MySQL证据,生产canonical原类计算字节/hash;不是篡改旧Outbox,也不宣称外部船司、其他消费者或自然租约故障通过。
2026-10-05 国内PDA退出修复已发布:e699e9d9bacb捕获原会话后立即清理敏感草稿,等待服务端撤销再跳转;明确HTTP401时最多刷新一次并撤销同主体的新凭据,不将该凭据写回本地。并发自动刷新共享原请求且旧响应不能恢复已退出或覆盖后续登录;未知网络失败不盲目重试,明确提示服务端退出未确认。总控176项本地测试、5项Gateway合同及HBuilderX5.26实际构建通过,TEST静态包逐66文件核对通过;本机390×848正常页面退出已捕获唯一logout200、无refresh,原Access在尚未过期时受保护接口401/A0401,原Refresh200/A0401且不签新凭据;reports/domestic-pda-logout-ui-20261005-r1/normal-final-evidence.json及root-normal-independent-verification.json为证据。自然过期退出已补验:原Access14:10:30自然到期,14:11:54在原tab确认,真实logout401→refresh200→logout200;原及替换两组Access/Refresh均A0401且不签新凭据,替换Access在14:13:30拒绝时尚未到14:35:53的自然到期时刻。root私有核对两组身份/原exp及替换iat、完整网络,查看原390×848截图并记录导出像素差异;原标签关闭、视口恢复。证据为同目录expiry-final-evidence.json与root-expiry-independent-verification.json,仅关闭国内本分支。部署证据见测试环境主契约及后端reports/domestic-pda-logout-release-20261005-r2/root-runtime-verification.json。
2026-10-05 Gateway Redis连接不可用补验:仅同镜像Gateway临时覆盖Redis客户端host/port,指向容器自身无监听端口19391;共享Redis、Auth/IAM保持运行。实际日志确认连接拒绝;两组原有效Admin/PDA Access在直达及公网入口均401/A0401,同时Auth权威接口对同会话仍200/true。聚合health503/DOWN未当作认证拒绝证据。恢复原镜像完整配置/Nacos后,同Access摘要的直达和公网请求均200、health200/UP,Auth/IAM原容器/配置未变,运行FINISHED且会话退出。后端 `reports/redis-gateway-failclosed-20261005-r1/root-final-verification.json`(26项)保存HTTP、运行状态及私有原故障日志摘要。第一次准备因namespace链接权限失败的原记录保留,确认无state且原服务未改后仅归档自有初始化;没有停共享Redis、清键或变更超时预算。本项只证明Gateway自身Redis连接故障的失败关闭和原凭据恢复,不覆盖全部Redis消费者及剩余消息可靠性场景。
2026-10-05 IAM→Auth撤销响应超时补验:仅新合成PDA账号auth2106926470848942081/member2106926470848942083的一次正式仓绑定PUT,Auth `/internal/auth/accounts/sessions/revoke` 已真实成功后,代理精确延迟该响应6秒;IAM在5277ms返回HTTP200/S0503。真实SQL核对完整IAM成员/用户/角色/主体权限版本均回滚,仍为洛杉矶原仓和权限版本1;Auth令牌版本1→2已提交,旧Access与Refresh均A0401且没有新凭据,对照账号200。恢复原IAM运行配置后新登录仍正常访问原仓,证明IAM回滚没有复活已撤销会话。原镜像/完整配置/Nacos摘要一致,Auth与Gateway原容器未变并健康;代理/端口/锁清理、有效会话退出,唯一新账号经正式接口停用并由SQL确认。证据为后端 `reports/auth-revocation-timeout-20261005-r1/root-final-verification.json`(26项核对)及所引HTTP、代理时间记录和三份真实SQL快照。只关闭此“远端成功、调用方响应超时”的撤销分支,不覆盖Redis故障及所有IAM/Auth变更;未采集原IAM异常栈,不推定具体异常类。
2026-10-05 Gateway权威会话校验超时补验:精确TEST PDA账号及jti的单次 `/internal/auth/accounts/sessions/validate` 调用延迟6秒,外部受保护请求在4142ms返回401/A0401;另一平台账号的用户列表请求168ms返回200。完整5条代理事实证明只延迟指定一次校验、对照直通及Auth稍后正常200。恢复原网关后,同两组尚未过期原Access再次通过,代理记录无增长;原Gateway镜像及完整配置、Auth原容器及配置、Nacos摘要均一致并健康。代理进程和两监听端口清理、锁消失、两会话退出均已核对。后端 `reports/auth-validate-timeout-20261005-r1/root-final-verification.json`(23项原证据核对)及 `root-final-runtime-proof.json` 为本次依据。只关闭Gateway→Auth权威校验超时,不覆盖Auth撤销调用超时、Redis不可用或所有业务服务的校验分支。首次旧PDA对照登录被A0403拒绝的记录保留,原目标会话正常退出后改用现有有效平台账号,未复活旧账号、创建替代账号或更改权限。
2026-10-05 资金执行中途故障补验:合法新换标RL-WH-20261005-560514的0.01CNY冻结指令200ebc4a-f078-4fc8-af7d-2e334c123b8c,在真实MySQL账户更新/hold插入后、流水插入前命中特定SQL异常;余额/版本、hold、资金流水和业务幂等写入均回滚,仅保留PROCESSING事件身份,无最终结果/结果Outbox。专属短时触发器移除后,同eventId/hash自然重试仅冻结一次,结果Outbox发布、Lastleg结果Inbox处理和FROZEN状态均完成,原库存/流水不变;触发器不存在、独立会话退出。证据为后端reports/wallet-mid-transaction-20261005-r1/root-fault-run.json、independent-final-review.json及所引原始SQL/日志。初次余额不足FAILED前置事件另存,不把重新发布业务指令当作原故障事件恢复。本次关闭这一资金中途回滚运行缺口,其余认证/消息故障和通知链路仍分别保留。
2026-10-05 自然过期退出补验:海外PDA r2原Access于北京时间07:30:33到期、07:30:58从原个人中心点击退出;Admin原Access于07:36:13到期、07:37:07从原详情页点击退出。两端各一次真实退出确认,完整网络均为logout401→refresh200→logout200。原及替换Access均401/A0401,两组Refresh均HTTP200/业务A0401且不签新凭据;总控分别私有核对替换Access被拒时尚未自然到期。原/替换凭据同一性、登录页和标签释放均有证据,见后端reports/pda-expired-logout-ui-20261005-r1/与admin-expired-logout-ui-20261005-r1/下的final-evidence.json、root-independent-verification.json。关闭R07两个指定自然过期退出分支,其他认证故障未据此关闭。下方2026-10-04记录中的“待补验”保留为当时状态,以本段较新证据为准。
2026-10-04 本轮权限与退出补验:既有转运执行权限 `lastleg:warehouse-transfer:manage` 已在 IAM 模块及统一基线注册,TEST 仅给默认平台管理员增加该授权,并推进受影响主体权限版本。新登录正式权限接口已确认执行/审核/库存列表权限,退出成功;证据 `baiyue-firstleg/reports/transfer-permission-login-verify-20261004-r1.json`。海外 PDA `b247b0c` 正常主动退出已用真实页面验证,一次 Auth logout 成功后原 Access 与 Refresh 均拒绝且不签发新凭据;证据 `reports/pda-local-h5-ui-20261004-r1/fixed-logout-credential-proof-r1.json`。自然过期令牌退出分支仍待真实 UI 补验,不以单元测试代替。装柜 B 柜唯一实际来源完成事件、APPLIED 回执及 Lastleg Inbox 摘要对应已验证,见 `reports/partial-B-completion-event-proof-20261004-r1.json`;只关闭该样本范围,不扩展为全部船节点/库存/车辆验收通过。
更新日期:2026-09-29。本文是已确认目标的唯一主契约;当前仅有测试环境,所有服务同机部署。部署与切换见[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md)。
状态:统一 Token/JWKS/Redis 会话、八类可靠直接投递和单 TEST 的 13 个服务已部署。真实 HTTP 主验收 7149 项断言通过,目标装柜事件 ACK 丢失、有限重试耗尽、人工原事件恢复及幂等结果已实测;代理已停止并恢复直连。旧海外 Gateway 与事件桥已停止且退出构建/部署,遗留源码尚未删除。完整页面作业、其余真实故障矩阵及告警通知链路不能据此视为通过,整体迁移验收尚未关闭。
2026-10-03 费用可靠投递补证:F40三顺序共10条费用事件以及车辆专项外接30CNY来源费用,均已按客户/来源/版本/事件ID核对唯一Outbox与已完成APPLIED投递审计。车辆专项组合证据为后端`reports/fleet-current-20261003-r2-terminal/final-evidence.json`,总控已核对源报告摘要;该结论仅证明这些样本正常投递确认,不覆盖费用ACK丢失、撤销重试或完整故障矩阵。具体部署及未关闭项仍维护在测试环境主契约。
2026-10-03 Order依赖故障边界补验通过:限定本轮客户与原请求ID,客户端/平台分别验证IAM资格和Finance钱包不可用(4次),提交正确失败且订单/履约事实不变;恢复同镜像/同配置/同Nacos源后,原请求成功提交且重放不重复,代理已停止、会话已退出。运行报告为后端`reports/order-dependency-fault-runtime-20261003-r1.json`。请求关联在实际熔断配置下命中,无关闭熔断或扩大故障客户范围;该证据不覆盖事件ACK丢失等另一类可靠投递测试。
下文路径、响应与时序为改造目标。实际业务服务、客户隔离、仓库类型、作业角色与状态机保持原职责;不能将“同机”解释为合并数据库表或绕过权限。
### A. 唯一路由与消费端映射
全部客户端共用 Gateway。下表写完整服务端路径;前端 HTTP Base 若已含 `/api`,业务调用不重复拼接该段。所有资源接口仍校验平台身份、客户范围及业务权限。
海外资源前缀记作 R=`/api/platform/v1/overseas-warehouse-resources`,权限前缀记作 P=`platform:overseas-warehouse:`。以下 R/P 仅用于文档缩写,不是配置变量。
| 方法与目标路径 | 目标服务 | 权限 | 主要调用方/改动 |
|---|---|---|---|
| GET `/api/platform/v1/warehouse-admin` 及现有主档 CRUD | Warehouse | 维持现有主档权限,GET 为 `platform:warehouse:list` | 主档页面与 IAM 的共享收货仓查询保留现有调用;写操作不改权限 |
| GET `/api/platform/v1/warehouse-admin/overseas-receiving-options` | Warehouse | P+`warehouse:list` | 新增限定用途查询;替代海外资源服务原根目录查询,返回平台公共、OVERSEAS、ACTIVE、RECEIVING 仓库,不因迁移给资源角色授予主档维护权限 |
| GET R+`/pallets`、R+`/pallets/summary` | Warehouse Overseas | P+`pallet:list` | Admin `overseas-warehouse/api/pallets.ts` 跨仓查询 |
| GET R+`/{warehouseId}/locations`、R+`/{warehouseId}/locations/{id}` | Warehouse Overseas | P+`location:list` | Admin `overseas-warehouse/api/locations.ts` |
| POST R+`/{warehouseId}/locations` | Warehouse Overseas | P+`location:create` | 同上 |
| PUT R+`/{warehouseId}/locations/{id}` | Warehouse Overseas | P+`location:edit` | 同上 |
| DELETE R+`/{warehouseId}/locations/{id}` | Warehouse Overseas | P+`location:delete` | 同上 |
| GET R+`/{warehouseId}/pallets`、`/pallets/summary`、`/pallets/{id}`、`/pallets/{id}/label`(后面三项同属 R+`/{warehouseId}`) | Warehouse Overseas | P+`pallet:list` | Admin `overseas-warehouse/api/pallets.ts`,标签二进制响应保持原格式 |
| POST R+`/{warehouseId}/pallets` | Warehouse Overseas | P+`pallet:create` | 同上 |
| PUT R+`/{warehouseId}/pallets/{id}` | Warehouse Overseas | P+`pallet:edit` | 同上 |
| DELETE R+`/{warehouseId}/pallets/{id}` | Warehouse Overseas | P+`pallet:delete` | 同上 |
| 现有方法 `/api/platform/v1/last-leg/**`、`/api/merchant/v1/last-leg/**`、`/api/pda/v1/last-leg/**` | Lastleg | 保留对应 Controller 权限与作业数据范围 | Admin、Client、海外 PDA 改用统一 HTTP/Token,业务路径保持 |
| 现有文件、打印、审计、集成公开接口 | 原对应服务 | 保留现有权限 | 从原双网关去重后接入唯一入口 |
| 任意 `/internal/**` | 仅服务间内部网络 | 内部服务身份 | Gateway 无公开路由;测试内部接口不能通过公网入口调用 |
新增收货仓选项查询沿用原海外目录的分页参数 `page/size`(size≤200)和 `WarehouseOption` 字段语义,由 Warehouse 直接查询权威主档,不能只通过客户端过滤实现范围限制。该用途查询需在 Warehouse Controller/OpenAPI/IAM 权限合同中明确登记。现有 IAM 查询与 Admin pallets 中 `listSharedReceivingOverseasWarehouseOptions` 已使用主档接口,保留其现有权限边界;仅原海外目录的直接调用者迁移到新用途接口,不批量改写无关主档消费者。
修改 `PlatformWarehouseResourceController` 和 `PlatformWarehouseDirectoryController` 的资源路径;移除海外服务中的重复目录代理和无独立必要性的公开健康路由。内部资源锁、托盘作业路径保持服务内使用。Gateway 对 `/warehouse-admin/**` 只指向 Warehouse,对 R 只指向 Warehouse Overseas,不按路由先后顺序或请求 warehouseId 猜测目标服务。
路由验收:逐条 method/path 唯一匹配;静态 `/overseas-receiving-options` 不误命中 `/{id}`;同名旧前缀下的国内接口仍有效;海外调用方全部迁移,不为其保留旧别名;客户端角色只能读取被授权目录,不能借新增用途查询修改主档。
### B. 逐事件直接投递与结果确认
以下内部路径复用当前消费者入口,统一为 POST,使用内部服务令牌、服务发现或容器服务名,不能经公开 Gateway。按 eventType 明确选择目标,不再根据 CN/OVERSEAS 选择目标;未知事件类型直接记录永久错误,不默认投某个业务服务。
| eventType | 当前生产与投递入口 | 直接目标 |
|---|---|---|
| `FirstLegLoadingPlanCompleted` | Firstleg `LoadingCompletedOutboxService` → `LoadingCompletedOutboxRelay` | Lastleg `/internal/lastleg/events` |
| `FirstLegContainerShippingNodeRecorded` | Firstleg `CarrierScheduleNodeOutboxService` → 同一 `LoadingCompletedOutboxRelay` | Lastleg `/internal/lastleg/events` |
| `OverseasContainerUnloaded` | Lastleg `InboundUnloadCompletedOutboxService` → `InboundUnloadCompletedOutboxRelay` | Firstleg `/internal/firstleg/v1/container-events` |
| `OverseasInboundOrderDetainedChanged` | Lastleg `InboundOrderDetainedOutboxService` → 同一卸柜 Relay | Firstleg `/internal/firstleg/v1/container-events` |
| `OverseasDeliveryCompleted` | Lastleg `DeliveryCompletedOutboxService` → 同一卸柜 Relay | Firstleg `/internal/firstleg/v1/container-events` |
| `BusinessFeeSourceChanged` | Lastleg `OverseasFeeOutboxService` → `OverseasFeeOutboxRelay` | Finance `/internal/finance/v1/business-fee-source-events` |
| `CompanyVehicleCostSubmitted` | Lastleg车辆运维费用来源 → `InboundUnloadCompletedOutboxRelay`;源码接入中,尚未部署验收 | Finance `/internal/finance/v1/vehicle-costs/events` |
| `WalletCommandRequested` | Lastleg `WalletCommandOutboxService` → `InboundUnloadCompletedOutboxRelay` | Finance `/internal/finance/v1/wallet-command-events` |
| `WalletCommandCompleted` | Finance 资金指令处理的结果 Outbox → `WalletResultOutboxRelay` | Lastleg `/internal/lastleg/events` |
| `IamUserStatusChanged`、`IamTenantStatusChanged`、`IamPermissionVersionChanged` | IAM 安全事件专用生产/Relay | 不迁移业务投递;完成 C 的撤销替代验证后移除专用投影链 |
车辆混合履约边界(2026-10-03):`OverseasDeliveryCompleted`仍只表示整来源实际签收,消费者据此把来源入仓单置为`DELIVERED`,不表示车次结束或异常工单关闭。工作区新增接线在首次实际签收的显式READ_COMMITTED事务中,沿历史出库/拣货分组取得全部受影响来源,按订单数值ID排序加锁,再核对实际签收、退回流水与重派凭据;不能使用可被改写的当前派送号或按比例猜来源数量。签前退回的货物重派后首次签收才新增贡献;签后退回再次签收不重复累计,可追溯多跳沿同一规则。逐来源独立发布,幂等键为事件类型+客户+来源入仓单;未齐来源保留未完成和中文审计,不影响同车另一已全签来源。事件格式与消费者语义未变,只有确实整来源全签才产生既有事件;国内异常结案不在本轮自行新增。签收完成与整单完成分别验收:来源入仓已签收不跳过仍未履约的有效余量子单。匹配版本部署、逐来源实签/退回重派、事件与接收端核对、失败记录及未关闭验收项统一见测试环境主契约。
已核对:Lastleg 卸柜 Relay 的 Repository 还选择了资金指令,不能把它整体改成 Firstleg URL;费用 Relay 只选择费用来源事件。实现时使用明确的事件白名单分派,并测试资金请求不误投 Firstleg。Firstleg 现有直达 Finance 的其他费用链、Order 的既有投递和 RocketMQ 导出/通知不并入本次新路由表,保持现有行为并做受影响回归。
统一目标返回结构为 `ApiResponse<DeliveryAck>`,其中 `DeliveryAck={eventId,payloadHash,outcome}`。`outcome` 只允许 `APPLIED`(已完成消费)、`DUPLICATE`(已成功处理的同一事件)、`STALE`(该类事件明确允许忽略的旧版本)。四个内部消费路径同步修改为这个返回结构,Relay 与全部直接调用者同步更新;当前 Integer/Object/feeSourceId 等响应不作为最终成功判定依据,不引入双响应兼容。
成功必须同时满足:HTTP 2xx、body code 为字符串 `200`、ACK 中 eventId/payloadHash 与发送一致、outcome 为该类事件允许的值。消费端只在可靠提交后返回成功;不能刚入内存或仅保留待处理记录就返回 APPLIED。重复确认必须来自持久化幂等记录;同 eventId 不同 hash 为冲突,不允许覆盖。
消费处理的原子性按业务实现验证:普通消费者将业务变更与成功幂等记录同事务提交;第0A批已将资金执行、成功Inbox和结果Outbox收敛到同一事务,保存结果失败时资金一同回滚;事件身份独立持久化防止重试换内容。保留既有钱包业务幂等键和状态机。历史记录曾报告MySQL结果提交失败回滚、原事件恢复及首次同/异hash并发已测,但本轮定向追溯未定位这些场景的原始证据,历史结论本身不能计作可复核关闭;见reports/wallet-0a-original-evidence-trace-20261005-r1.json。结果提交失败与原事件恢复现已由本轮新合法样本补证,见本文件开头wallet-result-commit证据;首次同/异hash并发也已由本文件开头的独立真实锁等待场景补证关闭。2026-10-05又完成账户更新/hold插入后、流水插入前的真实中途故障、完整回滚及原事件唯一冻结恢复,原始证明见本文件开头的限定钱包场景;不以此替代其他故障分支。
特别约定:资金指令的投递成功不等于冻结/扣款成功。Finance 必须可靠保存 SUCCEEDED 或 FAILED 业务结果及结果 Outbox 后确认该指令已消费,Lastleg 以 `WalletCommandCompleted` 更新业务状态。余额不足等已形成 FAILED 结果的指令不进行无意义的传输重试;成功扣款后结果发送失败,只重试原结果事件,不能再次生成扣款指令。
采购资金合同扩展:`SETTLE_ACTUAL` 携带最终正额 CNY 金额,在原冻结身份上原子补差或释放余款,原冻结金额保持不变;实际零元使用 `RELEASE`。`REFUND` 必须携带 `originalLedgerId`,以独立退款业务号关联原成功消费,累计退款不超过该消费金额。成功结果携带 `walletHoldId`(退款可空)和 `walletLedgerId`,以及该动作实际金额;失败结果不伪造资金引用。Lastleg 以 `commandEventId` 定位原费用版本和请求尝试,不能用当前订单状态覆盖旧结果。
采购应收只在实扣成功后发布 `BusinessFeeSourceChangedV1.walletSettlement`,包含原 `commandEventId`、`holdId`、`ledgerId`;Finance 核对命令结果、客户、业务身份、消费流水与实际 CNY 金额,同事务关联为 `SETTLED`。缺失或错误引用拒绝入池,禁止降级为待收费 `AVAILABLE`。原冻结金额与实际消费金额可不同;同一消费不能认领成多笔费用来源。已确认汇率快照随来源发布,传输重试不重新折算。
采购资金 TEST 定向证据(2026-10-10):`reports/procurement-purchase-replay-20261010-r2.json` 验证原购买请求重放只产生一笔1元实扣并完成来源关联;`reports/procurement-sample-20261010-r3/report.json` 验证2元预估只冻结、最终1.50元结算释放差额,货款及实际运费来源均关联成功,重复节点命令未新增消费。运行版本及已知缺口见单机部署主契约;此证据不替代原冻结不足、退款上限、并发或全部异常分支。
补充已寄客户财务证据:`reports/procurement-financial-corrections-20261010-r3.json` 验证只补扣0.50、按负差额退款1.00、超额退款拒绝、旧请求重放不重复扣退,以及独立0.25费用成功结算;原消费与汇率不覆盖。`reports/procurement-isolation-sources-20261010-r3b.json` 验证4笔正额来源在Finance均为SETTLED且禁止直接改写来源。余额不足及全部故障/权限分支仍待验收。
采购 SETTLE_ACTUAL 余额不足实证:`reports/procurement-insufficient-20261010-r2.json` 验证E=2、A=11、实际余额9时失败,原冻结和账户版本不变、交寄被阻断;充值5后原费用重试成功。`reports/procurement-insufficient-ledger-20261010-r2.json` 确认原hold.amount仍为2,只有一条-11的CONSUMPTION。`reports/procurement-usd-20261010-r3.json` 验证业务月USD换算、原币目标差额与原汇率快照保留,不修改共享汇率。不能据此推定所有权限及故障分支通过。
采购平台动作权限实证(2026-10-10):`reports/procurement-rbac-20261010-r2.json` 的240格矩阵通过。统一Auth新会话按专用角色分别验证list及15个写权限(13项新增、review/edit):list包含详情和只读明细,无仓绑定仍可处理平台范围;未授予相应权限时连原幂等请求重放也被A0403拒绝,授予后按原业务结果/状态门禁处理。订单完整投影和钱包前后不变;专用账号、角色已停用,所有专用会话退出。此结果只覆盖代表命令,费用用途/来源驱动的重试、文件分类上传及页面按钮边界继续单独验收。
采购零额与异常结束补证:`reports/procurement-physical-zero-ledger-20261010-r3.json` 确认免费样品、零预估及三项零实际费用共5笔ZERO核定、0资金请求,完整履约钱包不变;`reports/procurement-closure-ledger-20261010-r1.json` 确认新客户取消/异常关闭两单无资金请求和交寄,不以自动退款或虚构发运结束异常。HTTP原请求重放及只读补证、过程脚本失败原因和仍未覆盖的正额资金关闭边界见测试环境单机部署主契约。各成功登录的测试会话均已退出。
采购未实扣失败替代实证:`reports/procurement-budget-failure-20261010-r1.json` 及其resume报告验证货款FREEZE明确失败时不能绕过终止直接替代,失败费用仍阻断异常关闭;终止后替代按原汇率/业务日和预算校验,以FINANCIAL来源及新钱包身份只实扣1元,原版本无法再次重试,原键重放不重复消费。`reports/procurement-purchase-anomalies-20261010-r1.json` 验证缺汇率、错误购买即使提高预算仍不发资金请求。`reports/procurement-corrections-20261010-r1.json` 验证国内实收更正后重新引用已有零元费用不会新增资金动作。上述均为隔离TEST样本,成功登录会话全部退出;不外推为所有延迟回执或并发分支均已做真实故障注入。
预估资金及分类权限补证:`reports/procurement-reprice-zero-20261010-r1.json` 验证先释放0.40旧冻结再建立0.60新冻结、原键重放不重复占款、零实际只释放;`reports/procurement-estimate-cases-20261010-r1.json` 验证零预估后独立实际扣款、等额实际结清原冻结及四类正额费用分别关联来源。`reports/procurement-file-retry-rbac-20261010-r1.json` 验证文件按6种分类授权、错误订单文件拒绝,以及BUSINESS/FINANCIAL来源驱动的重试权限(财务替代货款不能用购买权限重试)。本地测试提交 `373f1b2c1` 补全来源故障恢复后原回执重放不重复资金命令的持久化断言,定向10项通过;与真实HTTP证据分层,不将其称为运行环境故障注入。
采购页面补验(2026-10-10):Admin #544修复详情文件操作列未绑定插槽的问题;平台账号真实点击本单面单后,订单及客户范围内下载接口返回200/image/png。该项仅证明页面请求接线和服务响应,下载落盘事件未取证成功;list-only授权仍以此前HTTP矩阵及本轮挂载测试为证。采购列表2次业务请求、详情及手动刷新各1次,均200;尚未关闭两端完整UI验收,详见单机部署主契约。
采购数值与真实审核补验:Admin #547采购适配器将接口数字字符串明确转为安全整数,长ID不转Number。原审核在本地校验失败、未提交业务变更,修复后同单ICSGS202610100001审核通过,客户详情同步待购买与审核时间。API路径、权限和服务端合同未变;139项模块及2761项全量通过。客户端独立创建请求一次、详情一次、列表一次,公共报关待办每60秒轮询;证据和剩余节点以单机部署主契约为准。
采购国内核费UI补证:真实页面核定国际0.01、关税/国内零、其他不适用,原冻结结清、实际扣款及费用来源关联完成,账户实际4.97→4.96、冻结0.03→0.02;不重复冻结或二次扣款。后续界面验收因同一浏览器platform_admin被切换成另一拼车测试账号而中断,已记录会话覆盖证据,未改跨标签页认证策略。国内面单已保存,最终交寄及Client终态仍待恢复隔离验收环境后验证,具体证据见单机部署主契约。
| 情况 | 生产端动作 | 消费端要求 |
|---|---|---|
| APPLIED / DUPLICATE | 标记完成 | 已提交、幂等记录可核验 |
| STALE | 仅显式允许旧版本忽略的事件标记完成 | 证明较新版本已覆盖且不丢独立业务事实;资金和独立费用动作不能泛用 STALE |
| 连接失败、超时、HTTP 5xx/429、临时数据库失败 | 原事件重试 | 超时后可能已提交,下次必须幂等 |
| 船节点等先于依赖单据到达 | 返回明确的可重试“依赖未就绪”业务错误,退避重试 | 不以不存在直接当成功,不靠查询顺序假设到达顺序 |
| 非法信封/版本、hash 冲突、未知类型、明确不可执行协议错误 | DEAD 并保留原因 | 不修改业务,不兜底成功 |
| 401/403 或内部令牌错误 | DEAD,标注配置/认证失败,修复后人工原样重试 | 失败关闭,不绕过鉴权 |
| 响应缺失、ACK 不匹配、未识别业务错误 | 不确认成功,有限重试后 DEAD | 保留诊断信息,不能仅按 HTTP 200 通过 |
统一逻辑状态为待投递、投递中、重试等待、完成、DEAD;可映射到现有表字段,不要求批量改名。初始测试参数:连接超时 3 秒、单次请求超时 15 秒、租约 60 秒、累计自动尝试 12 次、退避从 5 秒翻倍上限 30 分钟,加入小幅抖动;参数需可配置。租约失效后的恢复和最终状态更新必须校验持有者,避免旧任务覆盖新任务。消费超时不能被解释为事务一定回滚。
源码配置已统一为 `baiyue.event-delivery.connect-timeout-ms=3000`、`read-timeout-ms=15000`、`max-attempts=12`、`base-delay-seconds=5`、`max-delay-seconds=1800`、`jitter=0.1`、`lease-seconds=60`,供四个业务 Relay 使用。事件 Feign 客户端显式应用 EventDeliveryFeignConfiguration,禁止客户端内部自动重试及重定向,最终构建参数不被旧的全局 Feign 超时覆盖;连接与读取超时之和必须小于租约时长。`retry_count` 表示已失败或租约超时的投递次数;普通领取不递增,领取超时任务或恢复超时租约时计入一次,自动预算耗尽后保持 DEAD。实际投递失败从失败时刻计算下一次重试时间;每次领取使用独立租约 ID 和当前时间,最终写入必须匹配该 ID。DEAD 保留原始事件,不能通过定时扫描自行恢复。人工重试、逐次审计和指标已落地并通过本地事务回归,真实 MySQL 的目标装柜事件故障恢复已验证,旧桥已停止;其他故障矩阵场景仍须按实际证据分别确认。
每次尝试在本服务 event_delivery_attempt 表记录事件、目标、时间、耗时、结果、有限错误码和下一次重试;领取与STARTED审计同事务提交后才发HTTP,持有者CAS完成与审计完成同事务,失败一同回滚。过期租约审计为LEASE_EXPIRED并退避,本轮不立即重发。按服务/类型提供 pending/DEAD 数量及最老待处理时长;指标 baiyue.event.delivery.pending/dead/oldest.pending.seconds/sample.timestamp/sample.success 默认30秒采样,Prometheus只读缓存。采样失败保留旧值并标记失败,未知初值为NaN,不误报零积压。告警接入现有能力,不为本次新增独立监控平台。人工重试采用各生产服务的受保护内部操作与配套运维脚本,不新增公开后台页面:只允许 DEAD 原事件重试,记录操作人/原因,保留 eventId/hash/payload/业务幂等键,禁止修改载荷或伪造新 ID 后重发。
人工重试源码接口已冻结:GET `/internal/{firstleg|lastleg|finance}/event-operations/{entryId}` 查询状态,POST 同路径加 `/retry` 提交 `{requestId,operator,reason,expectedPayloadHash}`。使用独立 `X-Event-Operations-Token`,服务配置 `baiyue.event-delivery.operations-token` 对应 `EVENT_OPERATIONS_TOKEN`;缺失或不足32字节时仅关闭该运维能力,不影响业务启动。请求编号为稳定UUID,锁定本服务原Outbox行,DEAD→PENDING和 `event_delivery_retry_audit` 同事务提交;相同请求参数幂等,不同参数冲突,审计失败回滚状态。脚本 `baiyue-firstleg/scripts/event-outbox-operations.mjs` 只接受显式服务源地址与 `CHONGCHONG_ENV=test`,凭据仅从环境读取,不跟随重定向、不自动重试。不得通过公网Gateway或直接改表验收。
信封保留业务事件类型/版本、客户归属、聚合版本、因果/追踪标识及 payloadHash;删除 sourceRegion/targetRegion 及纯区域部署字段时同步 DTO、Validator、构造调用、SQL 基线和测试。语义事件版本及业务载荷不因去桥而随意改动。本轮不重写旧测试事件,不做旧信封兼容。
### C. 统一认证和会话撤销矩阵
2026-10-04 本机海外PDA真实登录与仓绑定通过,但个人中心主动退出未发起 `/auth/logout`,仅清本地会话;该项不满足服务端撤销要求。原始网络证据和独立账号停用清理保留。最小修复b247b0c已提交且TEST H5发布,正常撤销、明确401单次刷新、在飞刷新与新登录隔离的42项定向及192项全量Node通过;新版真实UI及旧Access/Refresh拒绝仍待验证,不能以返回登录页证明凭据失效。详细版本与证据见测试环境主契约。
2026-10-04 Admin 实际页面退出返回401、清本地后原Refresh仍可刷新,说明过期Access的退出路径未完成服务端撤销。Admin `d3a2671` 经 #509匹配发布:本地状态先清除,只有明确HTTP401或已移除过期Access时,才用捕获的原Refresh刷新一次并撤销新签发的同一会话凭据;该结果不写回登录存储、不加载权限,也不覆盖后续新登录;网络/503未知结果不自动重试。6项红灯后32项定向、299文件2392项全量及类型/build通过。已确认部署及实际auth分块;#509 普通页面退出已实际取得一次 POST200、登录页恢复及会话清理证据,自然过期401分支仍未取得新版真实运行证据。原失败和人工刷新撤销结果保留,具体证据见测试环境主契约。
2026-10-02 Admin r4 已取得密码重置多会话撤销、角色权限清空、账号停用、PDA 仓绑定变更与取消 PDA 身份后访问拒绝的真实 HTTP 证据,旧 Access 与旧 Refresh 均分别核对。目标装柜事件的 ACK 丢失、DEAD、原事件 retry、单次消费及配置恢复也在同轮重新验证;运行报告、版本和其余未覆盖边界统一见[测试环境单机部署与配置契约的 Admin 全量 HTTP 复核](测试环境单机部署与配置契约.md#admin-全量-http-复核2026-10-02尚未全绿),不据此关闭下表全部矩阵。
Auth 是唯一签发者;Gateway 负责入口令牌与访问域校验,业务服务通过 common-security 校验同一会话及业务权限。统一使用 Auth 现有国内会话协议,不只调整海外 Audience。Auth、Gateway、Lastleg、Warehouse Overseas 必须使用一致 Redis DB、会话键前缀、序列化结构与有效期规则;业务缓存用独立前缀,不能混同会话键。
JWT 不携带角色或权限集合,只保留必要身份、客户/应用/仓绑定与版本声明;授权快照取服务端会话,平台/客户/PDA 访问域仍独立校验。客户端不能从 JWT 或外部伪造头获得绕过服务器权限检查的能力。
并发撤销以持久版本和权威快照指纹为准,不能只依赖删除Redis:Auth账号变更与签发读取使用行锁,Access会话另存状态指纹,Refresh签发前复核旧指纹;Gateway及common-security在Redis会话检查后调用Auth `/internal/auth/accounts/sessions/validate`。Auth重新核对账号版本及IAM当前授权快照,缺失状态或下游不可用拒绝访问。IAM用单条SELECT读取身份、客户、角色权限、两类仓绑定及subject/tenant版本,避免跨查询混合快照。Gateway采用非阻塞HTTP,校验调用不转发Bearer Token,内部服务令牌保护该端点且不递归调用会话验证。此依赖增加每次请求的权威校验成本,测试环境仍须测可用性与延迟。
| 触发行为 | 撤销范围与负责链 | 必须验证 |
|---|---|---|
| 当前会话退出 | Auth 撤销当前会话的 Access/Refresh 能力 | 原 Access 被拒绝,原 Refresh 不能恢复 |
| 密码重置、账号停用 | Auth 或 IAM 调 Auth,撤销该账号全部相关会话 | 多端旧 Token 均失效,停用后不可重新登录 |
| 客户停用 | IAM 确定该客户成员范围,Auth 撤销该客户作用域会话 | 该客户业务不可访问/刷新;其他客户与平台账号不被误撤销 |
| 成员移除、成员角色改变 | IAM → Auth 撤销对应成员/客户作用域会话 | 旧权限不可继续使用,重新登录/刷新不能恢复被移除身份 |
| 角色权限、角色分配变化 | IAM RBAC 确定所有受影响账号与作用域 → Auth 撤销 | 已登录用户不能继续使用旧权限快照,遗漏批量关联用户算失败 |
| 平台人员角色改变 | IAM 平台人员维护 → Auth 撤销相应账号会话 | 新旧角色与平台访问域正确 |
| PDA 仓绑定修改/清空 | IAM → Auth 撤销绑定账号全部相关会话 | 原仓 Token 拒绝;新登录只获得新仓;无绑定拒绝受限作业 |
| Refresh Token 轮转与重放 | Auth 维持现有会话轮转规则,各端共用刷新编排 | 失效 Refresh 不重复换取;并发刷新行为与当前契约一致 |
撤销职责优先复用现有 MemberService、RbacService、PlatformInternalUserService/PlatformUserManagementService 与 Auth revokeSessions 链。逐入口确认,不能只凭其中一处已有调用就删除全体安全投影。
安全变更不得在撤销失败后仍返回完整成功。实施必须核对调用与提交顺序,证明“新安全状态已生效、旧会话却残留”的异常路径不会继续授权;同进程 try/catch 或口头要求重试不构成保证。若当前实现无法保证,应在该批次补齐可靠撤销及失败关闭机制,并先验证再删投影,不能降级为等待 Token 自然过期。这里冻结的是安全结果,具体撤销代码调整依据逐入口核查限定范围。
必须覆盖 Redis 不可用、Auth 撤销调用超时、账号/客户停用后的刷新、跨客户 Token 混用、伪造身份头。业务服务不能仅信任浏览器提供的权限头;统一服务端认证后清除对原海外可信头及 Lastleg 安全投影的专用依赖。权限继续由服务器决定,客户端快照只用于显示。
卸柜反向投递补证:`OverseasContainerUnloaded` 已通过本轮指定原事件的 ACK 丢失、重试耗尽、人工恢复及重复消费确认,Lastleg 原镜像/有效配置、健康与代理关闭已核对,库存及 Firstleg 柜回写事实不变。原始失败、工具修正、独立故障通过与整轮仍失败的范围统一见[卸柜反向事件故障验收](测试环境单机部署与配置契约.md#卸柜反向事件故障验收2026-10-02);不能据此关闭签收完成事件或其余故障矩阵。
2026-10-03 费用作废另有独立真实证据:BusinessFeeSourceChanged/VOIDED在未出账应收来源验证首次APPLIED后ACK丢失、12次失败DEAD及原事件人工retry后DUPLICATE/PUBLISHED;Finance只作废一次,Lastleg只在匹配ACK后确认。人工retry与逐次投递统一使用UTC,避免默认时区造成恢复排期延迟。共用修复d93185e7已发布Firstleg/Finance/Lastleg,真实范围、恢复指纹及首轮失败保留见[部署契约](测试环境单机部署与配置契约.md)。
2026-10-03 签收回写另有独立真实证据:`OverseasDeliveryCompleted` 在退税FBA根先签完整链中验证首次APPLIED后ACK丢失、12次失败到DEAD、同原eventId/hash/信封人工retry及DUPLICATE/PUBLISHED;Firstleg入仓、Order根/子状态及历史、完成事件和完整库存未重复变化。首片根单等待余量,第二片正常签收后根/子才均COMPLETED。Lastleg原镜像、完整配置/网络指纹、健康及代理关闭均已核对,运行报告与初次脚本失败保留规则见[部署契约当前验收证据](测试环境单机部署与配置契约.md)。这项证据不覆盖费用作废、全部摘要冲突或事务中途故障回滚。
## 业务归属与权限边界
平台和客户两级模型、服务端客户隔离、实际收货仓与 FBA 目的仓的区分继续有效。仓管绑定修改须撤销会话;无关平台角色不能通过客户端参数假冒仓绑定。统一认证后,不再用双区域安全投影作为权限来源。
资金指令当前实现补充:Finance 先单独提交 eventId/hash 身份记录,再在事务内锁定 Inbox 并复核 hash。资金变更、Inbox 最终结果及结果 Outbox 同事务提交;明确业务拒绝在原事务回滚后重新加锁记录,已有最终结果不得覆盖。可重试异常不产生最终 FAILED。内部消费响应已统一为 ApiResponse<DeliveryAck>,可靠提交后才确认成功。
最终业务拒绝白名单为 FIN-WALLET-INSUFFICIENT、FIN-WALLET-HOLD-409、FIN-IDEMPOTENCY-CONFLICT、FIN-REQ-400;处理中、乐观锁冲突、依赖冻结未到达及未分类异常继续向投递方抛出。基于 H2 的 JDBC 并发与回滚测试已经通过,不替代真实 MySQL 和测试环境全链路验证。
### 国内仓库目录同步读取
- 国内 `warehouse-service` 是 Warehouse ID、类型、状态、地址和能力的唯一权威。海外数据库不得复制仓库、地址或服务能力主表。
- `warehouse-overseas-service` 只保存库位、托盘、资源锁及其国内 `warehouseId` 引用;资源写入和 Lastleg PDA 仓绑定校验通过受内部服务令牌保护的国内只读目录完成。
- 只允许平台共享、`OVERSEAS`、`ACTIVE` 且启用 `RECEIVING` 的仓作为海外实际收货仓。低频正结果可缓存 30 分钟,空目录、不存在和停用结果不得长缓存。
- FBA 目的仓同样只以国内 `warehouse-service` 的平台公共主数据为权威,但语义与海外实际收货仓严格分离:Admin 候选使用 `warehouseType=FBA&status=ACTIVE` 的平台仓库分页;Lastleg 写入通过受内部服务令牌保护的 `/internal/warehouses/0/{warehouseId}/active` 读取当前事实,并继续校验 `warehouseType=FBA` 及 ID/编码/名称一致。`OVERSEAS`、`OVERSEAS_PARTNER` 或 `DOMESTIC` 均不得作为 FBA 目的仓。
- 按 FBA 仓拆分的海外派送单在签收完成时,由 Lastleg 在同一事务按关联来源入仓单分别写 `OverseasDeliveryCompleted` V1 Outbox;Lastleg Relay 直接投递 Firstleg 的 `/internal/firstleg/v1/container-events`。Firstleg 校验事件信封、客户、来源入仓单/订单、入仓码和 FBA 仓后,只将该来源入仓单从 `LOADED` 推进到 `DELIVERED`;同一 Order 的全部有效入仓单均为 `DELIVERED` 后,才以内部服务身份幂等推进该 Order 到 `COMPLETED`。同车其他 FBA 派送单必须各自签收,不得随整车一起完成。
- 签收本地时间使用服务执行时区转换为事件的 UTC `completedAt`,信封 `occurredAt` 与其为同一时刻;Firstleg 完成时间及状态历史按该事件 UTC 时刻保存。不得将本地 `LocalDateTime` 直接解释为 UTC。来源完成审计同时核对实际签收数量、事件标识与载荷摘要、目标投递 ACK、接收端 Inbox 和完成历史;Outbox 数量检查不能替代完整接收端核对。
三对话发布后只读冒烟(2026-10-10):Lastleg #254 与 Admin #555 的精确提交及健康证据见单机部署主契约。统一 Auth 的 admin1 独立会话经 Gateway 查询 `/platform/v1/last-leg/appointment-planning/impacts`、`/appointment-planning/external-candidates`(同属 Lastleg 前缀)及 `/platform/v1/last-leg/overseas-procurements` 均 HTTP 200、业务码200,随后退出自身会话成功。仅证明本轮读接口与新增表接线可用,不代替船期事项认领/记录/关闭的完整写入与权限验收;证据 `reports/three-threads-release-http-20261010.json`。
2026-10-19 本土卡车与散板字段发布后的真实 HTTP 已核对:客户查询/编辑仅使用认证客户范围,伪造其它客户参数不能读取或修改其订单;客户访问平台入口、平台身份访问客户入口及未登录请求均按现有合同拒绝。平台、客户独立测试会话均退出成功。本轮未发布 Gateway/Auth,未重跑全部撤销、事件或 PDA 仓绑定矩阵;精确版本及 111 项业务 HTTP、34 项端侧产物检查证据统一见[本土卡车与散板需求字段发布](测试环境单机部署与配置契约.md#本土卡车与散板需求字段发布2026-10-19)。
+12
View File
@@ -0,0 +1,12 @@
# 自营业务文档入口
本目录维护平台自营业务的设计与规则。自营外部系统数据与客户物流订单、仓储作业库存分开管理。
- [领星一件代发数据统计一期方案](领星一件代发数据统计一期方案.md):Java 服务归属、分仓同步、表结构、自营菜单、货主经营概览与 SKU 库存关注、每日库存观测、销量图表、采集进度、查询性能及验收;后续库龄、内部评级与成本分摊边界。
- [经营总览图表设计](经营总览图表设计.md):新增经营总览页面、指标带、出库趋势、消化天数分布、三类 SKU 图形榜单、统一版本聚合及下钻验收;保持 SKU 为中心。
- [库存周转视图设计](库存周转视图设计.md):库存分析默认视图、7/15/30 天同屏、SKU 与货主汇总、可售天数与期间件数周转、数据资格、查询结构及验收。
- [数据采集页面设计](数据采集页面设计.md):采集首页与任务详情、来源依赖、阶段进度图、数量摘要、预计剩余时间、结果可用性及逐操作验收。
- [领星统计查询性能优化方案](领星统计查询性能优化方案.md):查询耗时定位、总览共享结果与复杂筛选优化顺序、正确性对照及性能验收;业务口径仍以一期方案和总览设计为准。
- [领星 WMS 接口联调手册](领星WMS接口联调手册.md):自研系统(OMP)的签名、仓库发现、一件代发出库、产品库存请求参数及只读实测依据,后续批次库龄接口核验入口。
后端实现先读 [Integration 指引](../../baiyue-firstleg/integration-service/AGENTS.md)与 [Lastleg 指引](../../baiyue-firstleg/lastleg-service/AGENTS.md)。统一部署、认证和服务通信继续遵循现行主契约。
+361
View File
@@ -0,0 +1,361 @@
# 库存周转视图设计
在 Admin「自营业务 → 库存分析」增加默认打开的“库存周转”视图,让运营在同一处比较各 SKU 的 7/15/30 天出库、当前库存和消化速度,并按货主汇总,筛选需要复核库存安排及内部仓储成本的对象。
本设计整理自 2026-10-13 [优化数据采集页面状态提示中的业务讨论](codex://threads/01a134a1-0ccd-7b61-add0-945d47eec5de)。用户已要求整理方案并交开发总控安排。本文件是新增视图、指标扩展、查询合同与验收的维护入口;基础数据、采集及权限沿用[一期方案](领星一件代发数据统计一期方案.md),总览原有下钻沿用[经营总览图表设计](经营总览图表设计.md)。设计交付不表示功能已实现、部署或通过验收。
## 历史库存还原与周转率修正方案(2026-10-15,实施合同)
用户已确认按本方案实现,先完成本地验证,再统一更新测试环境。本节是该扩展的唯一实施合同;`FLOW_EOD_V1` 整体替换期间周转的分母来源,原始日观测继续留作对账证据,不能混用两套日库存口径。代码完成不表示已建表、补齐两仓历史或部署,运行与验收事实只维护在 TEST 主契约。
### 1. 目标与已知边界
- 先补 US01、US02 截至昨日的最近30个完整日,校验通过的 SKU 可以显示期间件数周转率;再扩展到60日。现有两个月销量复用,不重拉出库详情,也不要求等待30天自然积累。
- 数量周转率=**同期已发布出库件数 ÷ 同期平均每日实物库存 ×100%**。出库件数继续使用现行列表优先、缺项补详情口径,不能借本次库存流水核验宣称所有列表量已经证明等于最终实出量。期间次数与百分比来自同一个未舍入比值;不是金额/成本财务周转率。
- 分母采用北京时间每日结束前的全品质实物库存,规则名 `FLOW_EOD_V1`。日期 D 对应 `[D 00:00, D+1 00:00)`,D+1零点事件归次日。平均数为N个完整日末库存之和÷N;不把08:00快照直接当日末,不与旧日代表混合,不用当前库存替代缺失的日库存。该口径与查询合同一并冻结。
- 已验证一条 SKU 的两个月77条流水、5组库位/批次/品质结存链;三个真实库存观测点和最近30天逐日销量一致,支持此 SKU 的还原。后续本地扩展样本补齐DO/PA/IMO/IAT/RI、正次品转换、包含端点、空页及小范围多页对照;这不等于新增SKU都已完成独立库存锚点对账,也不证明两仓全量历史完整。真实执行与验收证据统一见[TEST主契约](../测试环境单机部署与配置契约.md),字段实测统一见[接口手册](领星WMS接口联调手册.md#库存流水有界诊断2026-10-15)。
### 2. 拉取什么、如何分页
| 数据 | 首次补齐 | 后续增量 | 用途 |
| --- | --- | --- | --- |
| 已发布 SKU 日销量 | 读取已有完整版本及日覆盖,不重新采集 | 继续现行销量增量 | 周转率分子、DO差异诊断 |
| 产品库存快照 | 复用合格的已保存快照;需要新锚点时通过既有库存任务采一轮 | 继续每日计划库存 | 当前库存展示、独立库存锚点 |
| `stock/stockCellBook/page` 流水 | 目标起日00:00到有效锚点之后的必要尾段;冻结上界后分页 | 采新增时间片,重查近期窗口捕获迟到变化 | 历史实物增减、批次链与日末库存 |
1. 开发阶段先在本地回放已保存响应,补样本时继续限定账号、仓库、货主/SKU,不通过反复发布试探类型。全量上线必须回到 Integration 的唯一受控出口,共用账号锁、permit、请求计数、冷却和至少1200ms间隔;本地直连只用于本轮明确授权的诊断,不能变成长驻的第二个采集器。
2. 生产采集计划按**仓库+固定时间片**,优先整仓分页覆盖全部货主/SKU,不按几千个 SKU 逐个请求。官方参数允许货主/SKU筛选;整仓不传这两个条件的实际范围及权限尚须小页验证。若整仓范围不能证明,明确改为已核验的“货主+时间片”计划,不能静默认为返回的是全仓。
3. 首补从最近日向前推进,一天一片、每页1000条,端点支持情况经本地小范围确认。片内 `startTime/endTime`、排序、账号/仓范围固定;单片过大时按小时确定性拆分,不改变已开始翻页的条件。请求次数按各片 `ceil(total/1000)` 估算,首片取得总数后再估算耗时,不承诺“几分钟全补完”。
4. 已核验来源时间参数在样本处两端包含;请求允许边界重叠取回,入库按流水ID去重,本地严格归属半开区间。小范围分页一致不替代每次完整性校验,同秒事件排序仍无永久合同;不能仅凭时间戳大于上次最大值跳过同秒或迟到记录。`createTime` 用已确认北京时间解析,原字符串同时保留。合法空首分页的size10特殊响应按接口手册严格归一化,不因空片误暂停整仓。
5. 页响应、暂存及下一页检查点同事务保存;HTTP不在数据库长事务里。累计返回数、唯一ID数、源total/pages、每页范围及摘要均校验。总数变化、同页/跨页异常重复、排序漂移导致可能漏页时,不用“去重后条数差不多”判完整;缩小到固定历史片重新形成一次完整尝试,保留失败证据。重叠时间片的边界重复与片内分页异常分别处理。
6. 只有全部页验证通过,时间片才获得“请求范围覆盖完整”的证据;这个结论不等于供应商永久保留、不可修改或历史绝无漏记。跨重启恢复若不能证明原分页集合稳定,重读当前小时间片,不从旧页码盲接新集合。
7. 流水HTTP每页完成后释放账号锁,让销量及当日库存优先执行。流水归并、历史重建和版本发布交给本地工作队列;当前 `SelfopSchedulePlanner.tick → SelfopExecutionService.execute` 同步执行路径必须调整,否则仅释放账号锁仍会被同一个调度线程的计算阻塞。采集与本地计算分开调度,本地同仓重建有持久化状态与互斥,发布只持有短锁。
### 3. 必须保存的字段与三张新表
数据归 `baiyue_lastleg`。复用 `ll_selfop_sync_task/run` 记录请求、尝试、失败和检查点,复用 `ll_selfop_sync_stage` 保存每次拉取的白名单原始字段,新增 `INVENTORY_FLOW` 对象类型;原始响应中姓名、备注、操作者、地址等与数量无关字段不入业务库。日志不保存原始响应、Key或签名。
| 新表 | 关键内容 | 唯一性与用途 |
| --- | --- | --- |
| `ll_selfop_inventory_flow` | source_account、warehouse_code、customer_code、sku_code、source_flow_id、cell_no、inner_batch_no、product_quality;bill_no、source_no、bill_type;book_qty、book_change_qty_raw、delta_quantity、close_quantity;source_create_time、event_at_utc、business_date、quantity_unit;content_hash、revision_no、first/last_run_id、last_observed_at、validation_status/reason | 来源账号+仓库+来源流水ID唯一,ID按字符串保存;同ID异身份拒绝,不按单号或时间去重。保存最新确认事实,旧载荷/版本证据留在不可变stage中。ID作用域核验后再冻结唯一键,不能假定其全球唯一。 |
| `ll_selfop_inventory_day_version` | account/warehouse/business_date/scope_hash/rule_version、版本号、build_run_id、publication_group_id、固定销量版引用、锚点库存run及观测区间、已完成流水片与事实修订号、输入摘要;READY/PUBLISHED/SUPERSEDED/FAILED、发布/替代时刻、有效/未知SKU数、差异摘要 | 每仓每日一个已发布头;历史版本不覆盖。唯一约束配合仓scope短锁切换;同一校正组涉及的全部日头在一个事务内切换。它不是原库存快照的发布指针。 |
| `ll_selfop_inventory_daily` | day_version_id、customer_code、sku_code、product_quality、physical_quantity、quality_status/reason、anchor_reference、evidence_hash、source=`FLOW_RECONSTRUCTED` | 每日版本+货主+SKU+品质唯一;数量用DECIMAL(20,6),未知NULL、有效零为0。日末实物分品质保存,查询再合计一次;不储存重复的冻结/可售/在途推算值。 |
原有 `ll_selfop_inventory_snapshot` 和已发布 `sync_run` 日标记原样保留。不能把人工快照改成历史定时日代表,不能把还原数据塞回原始快照,也不能更新旧库存时间。客户/商品名称继续关联已有主档,不在流水复制第二套主数据。
校正组清单与执行状态放入对应重建 `task/run` 的专用结构,禁止复用原库存日代表的发布标记;组清单冻结后不可改,输入再次变化则放弃候选并生成新清单。日版本另存 `invalidated_at/reason/rebuild_run_id` 以支持查询资格检查,失效标记不可因重建失败而清除;旧日行和证据仍保留。事实修订归并与所影响旧版的失效标记同事务提交,避免出现新事实已接受、查询仍把已知错误旧值判有效的间隙。失效范围尚不能精确确定时,保守覆盖该仓保留的历史日版本,不能漏标;已知细粒度范围记录在重建清单中。
流水至少按 `(account,warehouse,customer,sku,event_at,source_flow_id)`、`(account,warehouse,business_date)` 建查询索引;每日表按 `(day_version_id,customer,sku,quality)` 唯一及必要身份索引查询。日版本按仓/日期/发布有效区间查头;查询不得全表读取大JSON。删除策略需保护被日版本引用的流水证据、锚点和版本;本期不自动清理这批历史证据,也不直接套用销量计算副本7日淘汰规则。
字段实现时对齐现有长度:账号/仓库/货主64、SKU128、来源ID64、原始时间64;来源ID不转BIGINT,日期用DATE、UTC观测时刻用DATETIME(3),原始变动字符串与数值分开保留。基线在 `lastleg-service/src/main/resources/db/lastleg.sql` 与独立 `selfop-inventory-history.sql` 同步,部署SQL索引记录三表及已有stage/任务字段语义变更;本方案不执行DDL。
### 4. 历史每日库存如何还原
以 `账号+仓库+货主+SKU` 为统计身份,内部链进一步按 `库位+内部批次+品质` 区分。同名SKU不跨货主合并,跨仓独立。
1. **变动量**用有符号 `bookChangQty` 解析为DECIMAL;PA/DO样本中它与 `bookQty` 一致。两字段保留,不相加、不因业务类型再取负号。`bookQty` 不是期初量。其他类型是否同义由类型样本验证,未知语义不能用于正式日库存。
2. **链校验**:同一链前一笔结存+当前变动=当前结存;首笔前结存=首笔结存-首笔变动。`closeQty` 只对该库位/批次/品质有效,不能把多笔结存直接相加或取最新一笔当SKU总量。分组键缺失时保留未知;同秒流水按“前结存→后结存”构成有向余额图,只有使用全部独立流水边的完整路径唯一时才接受,不按条数阈值或字符串ID猜顺序。无前序余额的多边回路、重复边引起的多解及真正分支歧义仍未知,断链/断开图拒绝;用相反边优先级的两次迭代欧拉路径核对唯一性,避免阶乘枚举。
3. **SKU锚点**:使用已保存、身份与单位明确的SKU分品质实物快照作为独立锚点,按同品质完整流水反推,再合计全品质。某批次在窗口内无变动就可能完全不出现在流水中,因此不能要求“出现过的链结存之和=SKU快照”,也不能把两者的差额自动判为漏账。例如活动批次10件、无变动批次90件,SKU锚点仍是100件;90件保留在锚点余额内。链连续性检查只约束实际观察到的链;只有另有完整同刻批次清单,才做全链总额对账。缺品质快照不能把总量任意拆分;快照缺行只有在供应商已核验的完整返回/零库存省略规则下才能认定零,否则未知。
库存扫描不是原子历史快照,`observed_at` 也不保证就是供应商扣账时刻;保存真实页面/整次扫描观测区间。若该SKU在区间内发生变动而无法确定先后,标记 `ANCHOR_TIME_AMBIGUOUS`,补稳定锚点或缩小对账区间,不能把秒级流水与毫秒响应时间机械相减。用其他独立库存观测点检验还原结果;仅从同一个锚点正推、反推互相吻合不能充当独立正确性证明。
4. **反推公式与尾段**:在已确认稳定的锚点状态A下,日期D日末为 `I_D = I_A − ΣΔ`,求和范围从 `D+1 00:00`(含)到锚点状态已包含的最后事件,不能漏掉次日零点至早晨锚点之间的流水。来源端点未核验或无法确认事件是否已包含于锚点时,不发布该SKU。目标日期片与锚点尾段分别冻结边界并记录覆盖;尾段必须覆盖锚点整个观测区间以检查歧义,不以“昨日片已完成”替代。跨片重复按来源ID只计一次,恰好零点的事件属于新一天。也可从已核验期初正推逐笔核对;没有变动的日子只有在完整流水范围与有效锚点支撑下才继承余额,这属于结存推导,不是缺日补零。
5. **品质转换和移库**:同SKU同仓移库的出/入两端合计应为0,但不能仅按业务单号删掉两条。已实测IMO也承载正品转次品,必须分品质分别记增减后合计,全品质总量不重复;不能只取某一品质或把全部IMO直接丢弃。跨仓移出入分别影响两仓。冻结/解冻若不改变实物不计入实物增减。调整已有正负样本,退件已见正增量,拦截/出库差异尚无实际样本;未知类型影响到的SKU/日期保持未知。上述增减不自动加入销量分子。
6. **历史售空与新商品**:候选全集是当前库存、目标窗销量、窗口流水、已有历史日库存身份的并集,包含当前已售空SKU。无流水且有可靠库存锚点及完整范围,可证明恒定存量;缺锚点不能把缺行当0。新SKU首次入库前,必须有可靠零期初和完整流水才能确认历史零值;仅“第一次看见”不够。
7. **资格逐SKU逐日判断**:范围缺页、重复身份、链断裂、负库存、单位未知、未知业务语义、锚点不符均保留NULL和原因。数值为0也要证据。对账容差按来源数量精度固定,不用任意百分比误差将不符样本判通过。
### 5. “回写”写到哪里、什么时候可见
这里的回写仅指写入平台自己的历史事实和日表,**不调用领星库存调整接口、不改变领星库存或已有销量事实**。
流程为:`固定片拉取 → stage落地 → 覆盖校验 → 幂等归并flow事实 → 固定输入构建day_version/daily → 锚点及链校验 → 原子发布日版本 → 查询读取`。
- 相同流水ID、相同内容重复采集只更新本次已见证据,不重复增减库存;同ID内容变化生成本地修订号,保留旧stage、标记受影响日版本需重算。同ID异身份先隔离冲突并使可能受影响范围待核验,不能自动搬移事实;只有身份更正得到确认后,才按新旧依赖并集重建。不能用 `ON DUPLICATE KEY` 累加delta,也不因为某一页没返回就删除历史流水。
- 每日候选在独立版本下批量写入;写入中断只留下未发布候选,页面读不到半批数据。公开日末口径 `FLOW_EOD_V1` 与内部计算修订分开:计算修订号进入构建去重签名和版本证据;算法修复后用已存流水自动重算一次,相同输入和修订成功后不重复构建,无需重新请求来源。输入流水修订号、锚点、范围、候选身份全集、规则版本及校验摘要冻结,指向可重放的不可变stage修订,不能只存摘要后再读flow表最新值。归并事实修订与发布校验共用同仓版本互斥;发布短事务内核对输入代次未变并切换日头,变化则重建,不能在校验和切换之间放入新的修订。
- **首次补齐或新增日期,一天构建和校验通过即可发布一天**,不设30分钟等待,不等60天全跑完。版本包含全候选的有效/未知状态;个别SKU异常不阻塞其他SKU出结果,但未知不能被省略而使货主合计看似完整。若本次也修正已发布日期或改变既有候选全集,按下述校正组发布,不能借“逐日发布”跳过跨日一致性。
- 同一SKU历史变动修订会影响多个日余额,必须按实际计算依赖确定受影响日期,不能只重算发生当日或机械地重算“事件日至锚点”。以较晚锚点反推时,某笔delta修订影响求和范围包含它的更早日末;以较早锚点正推时则影响其后的日末。时间、身份、品质或锚点变化按新旧依赖范围并集失效重建;新发现的售空SKU也要重新核对候选全集。按依赖重建保留范围内的全部受影响日期,无需重拉其他未变化的历史销量。无修改时间或删除契约时,旧记录缺失只进入冲突核验,不自动抹账。
- **校正组原子发布**:一个重建任务保存不可变的组清单(publication_group_id、受影响日期、预期旧头、新候选ID、输入代次)。全部候选就绪后,在一个短事务内校验旧头和输入代次、切换全部日头及有效区间、标记整组完成;失败全部回滚。批量计算与daily写入在事务外提前完成,切换只涉及头记录;同仓重建互斥避免并发覆盖。查询可读完整旧组或完整新组,不能读到一半新、一半旧;重启用组清单确认整组是否已提交,不逐日猜测完成状态。
- 已确认旧值有问题而新候选尚未就绪时,当前查询返回对应范围“校正中”,期间周转率暂不展示;首次拉取失败但尚未证明旧值错误不自动撤销旧版本。新查询须在同一个数据库一致性读事务内取得组状态、各日头和销量版本并固化准确版本ID映射;不在多个普通读请求间拼装日头,也不能仅靠墙钟asOf重新推导版本。已打开的上下文及导出继续引用固定证据,同时检查其版本是否被标为需校正,命中则要求刷新/暂不输出该周转率,不能继续称为有效正式结果。已发布日行不可就地修改。
- 归并与重建按日期、货主/SKU分批,流式读取有序流水,不把两仓两个月的JSON一次载入内存。批量写入使用短事务;输入版本未变时复用本地结果,不为生成新日版本再次请求领星。数值计算用DECIMAL,不能在JavaScript浮点或前端做最终业务求和。
### 6. 周转查询、货主汇总与导出
- 改 `InventoryTurnoverContext` 固定新的日版本映射、校正组与 `FLOW_EOD_V1`,改 `InventoryTurnoverSql` 的日库存来源为每日表。上下文在一致性读中同时确定输入版本;后续查询按准确ID读取,并检查校正失效标记,避免迟提交事务被墙钟时间误归入旧上下文。当前 `inventoryRunId` 仍服务当前库存、可售天数和立方数;历史日库存版本独立。规则切换后旧上下文明确要求刷新,不保留隐式混算分支。
- 对每个SKU,分子日期完整且N个有效日末库存齐全、平均库存>0,才输出周转次数及百分比。平均库存>0且销量0,结果为0%;均库存为0则仍未知并说明原因,不给无限大。补到7日就可计算7日,30日不足仍不缩短分母。
- 货主周转率=该货主同期总出库÷该货主每日总实物库存的均值×100%,不是SKU百分比的算术平均。历史售空SKU继续参加分子和分母;“隐藏0库存”只控制当前列表展示,不偷偷改变货主历史统计总体。
- 货主范围内存在缺失SKU/日期,正式总周转率未知,同时返回可计算SKU数、未知数及已知库存小计;不能只挑完整SKU算出一个看似完整的货主值。其他已齐的货主可独立正常展示。
- 列表、排序、导出共用后端计算和同一固定销量版/日库存版。导出包含期间、期间出库、平均日末实物库存、周转率%、库存来源“流水还原”、可用日数及缺失原因;不在浏览器用当前库存重算百分比。主表不重新塞回每行0/30,说明和证据留在现有入口。
### 7. 以后如何自动保持正确
1. 首补30日优先,后续60日;时间片永久记录边界和完成证据,已完成片不在每次启动时重新全跑。现有销量、当日库存继续优先执行。
2. 每天北京时间00:05创建昨日流水片,完成后立即尝试使用已有合格锚点构建;若证据不足,则等待**当天08:00**计划库存,并追加覆盖“当天00:00至该锚点观测区间结束”的固定尾段任务。仅在昨日片、所有必要尾段、锚点稳定性共同校验通过后发布昨日;有可用证据即可提前发布,不固定等08:00。锚点在翻页后发生变化,不能移动在途请求上界,另建固定片补齐再选新锚点。00:05是启动时间,不承诺所有SKU此时都已具备证据;尾段未齐显示待核验,不把任务完成当库存已完整。
3. 固定冻结上界,日常重查最近3个完整日捕获迟到记录;每周分片复核近30日、保持低优先级且每页让出账号。因为该接口目前只见 `createTime`,不能宣称它支持更新时间增量或能发现任意旧记录变更。超过复核窗口的更正通过显式指定日期重算;若供应商确认有更新/删除通知或游标,再替换复核方案。
4. 每天与真实库存对账,差异影响对应SKU与日期资格;保持原数据、错误码和业务任务号,不能为“恢复”自动清库、重置采集或更改历史时间。
5. 429遵守账号冷却与暂停;HTTP结果未知先查审计,不重复发同次请求。固定历史片在明确收到响应且可重读时才有限重试。新增流水采集没有额外HTTP总额度上限,仍受现有安全出口和人工停止控制。
### 8. 实施批次与验收退出条件
| 批次 | 交付 | 通过条件 |
| --- | --- | --- |
| A 本地语义核验 | 保存白名单字段、时间/品质/变动/结存对照;冻结日末口径 | 已有77条实响应回放;另补移库/调整/退货/品质等出现的真实类型样本、同秒与端点证据。未出现类型列出未验证,不假造真实通过。 |
| B 持久化与受控拉取 | 三张新表基线、stage/任务类型、整仓分页合同、断点/去重/修订及调度分离 | 分页变化不假完整;重启不重算delta;本地构建不占供应商锁或阻塞销量线程;无重复任务头。 |
| C 单SKU→单货主还原 | 日末重建、原子校正组、独立锚点对账 | 样本三锚点一致;次日尾段、静止批次、连续日链、空日、售空、新品、负库存、未知字段与重复/修订场景通过;正推与反推的修订依赖分别验证;至少一个货主完整候选汇总对齐。 |
| D 两仓30日与查询 | 近30日分片补齐,页面/排序/导出改读新日版本 | 已覆盖完整且合格的SKU显示数值;未知有原因;货主算总量比值;当前库存/销量原数据不变;首次逐日发布、校正组事务回滚/重启、并发读、旧上下文失效均通过,不出现跨日新旧混合。 |
| E 增量与60日 | 昨日自动任务、近期复核、低优先级更早历史 | 无人操作仍生成任务并继续;停机恢复、迟到流水、冲突与日版本重建有证据;不以首轮成功替代持续能力验收。 |
代码入口为 Lastleg `selfoperated/analytics/history/`。`INVENTORY_FLOW_HISTORY` 请求任务和 `INVENTORY_HISTORY_BUILD` 本地构建任务使用独立类型及账号任务角色,不进入原始库存/销量任务执行器;构建结果使用独立日版本,原库存发布指针保持。两个独立调度执行器分别负责每页HTTP和有界本地归并/构建。Lastleg 配置 `inventoryHistoryEnabled` 默认 false;启用前必须完成三表与两服务发布,`inventoryHistoryDays` 默认60、首批30日。SQL、发布、开启两仓采集按仓库要求明确授权;单SKU本地诊断不扩大成全量本地直连。
### 9. 设计复核与必须保留的反例
以下是设计推演和已有样本证据,不代替待实现代码的测试或上线验收:
| 场景 | 必须得到的结果 |
| --- | --- |
| 已核验样本:次日早晨库存144、零点至锚点出库变动−1 | 前一日日末为145;漏采尾段时禁止把144发布为日末。 |
| 活动批次10、窗口内无流水批次90、完整SKU锚点100 | 无变动批次保留在锚点余额中;不能因已观察链只合计10而判缺90或把总库存算成10。 |
| 两个已发布日均为100,校正后均为110 | 新查询只能看到完整旧组、校正中或完整新组;不允许110/100混合得到105的均值。 |
| 较晚锚点固定为100、区间内仅一笔事件,其delta由−1修订为−2 | 该笔事件之前的日末应从101变102,事件之后的日末不因该笔修订改变;失效范围沿计算依赖确定。 |
| 校正组发布到一半异常、或计算后输入被再次修订 | 日头全事务回滚,或拒绝过期候选;重启不重复发布部分日期。 |
| 零点事件、尾段边界重叠、观测期间恰有库存变动 | 零点归新日,重叠ID只计一次,锚点先后不明则未知;禁止通过毫秒时间精度假装先后已确认。 |
第二轮复核除前三项外,已补齐反推修订向更早日期传播、输入冻结与发布竞争、旧查询/导出失效检查。随后有界本地核验结果已纳入接口手册;BO/OBIAT、全仓独立覆盖对照、缺行零库存语义、永久稳定排序及历史修改/删除规则仍未关闭。基础存储、已验证字段适配和资格校验可进入实现,正式日库存仍须逐SKU/日期满足证据门槛;不能把未验证类型当0跳过,也不能把有限样本当作所有历史数据完整的证明。
## 业务目标与本次边界
业务需要回答四个问题:哪些货现在存得多;哪些 SKU 近期不动或消化慢;哪些货主的库存需要优先复核;哪些商品持续流转,可以进一步评估仓储支持或成本优惠。
继续按仓库独立查看全部授权货主,当前仍是自营业务的内部评估与成本分摊准备。领星货主不是平台收费客户,不自动绑定财务账户。件数、出库速度与当前可售天数是经营依据,不直接给出“加价”“优惠”“优级客户”或费率结论。
| 本次交付 | 后续另行核验 |
| --- | --- |
| 默认进入即查;SKU 与货主两种视图;7/15/30 天出库同屏;按所选窗口的日均及可售天数;无出库、消化较慢/较快、冻结/次品及待评估筛选 | 真实批次库龄、占用体积、托盘/库位及占用时间、货主与内部成本中心映射 |
| 有完整日库存样本时计算期间件数周转次数;不足时展示样本数与缺口,不阻断其他指标 | 正式内部评级、仓租加价/优惠规则、生效期、例外、审批及财务联动 |
| 库存与销量时间分别展示;同版本分页、汇总、图表及趋势下钻 | 新外部接口、提高领星并发、补造历史库存、任意历史时点库存重建 |
本轮扩展了早前“期间周转留待后续”的范围:实现有资格才计算的查询与展示,但不放宽日样本标准。新品、战略备货、季节性、断货与促销尚未建模,所有关注标签都供人工复核。
## 菜单与首次进入
### 库存与出库立方数(2026-10-14 确认)
库存周转增加库存立方数、所选区间出库立方数及 SKU 单件体积,单位统一为 m³。沿现有 SKU/货主分组、客户筛选、时间范围及客户下钻查看;本仓/本客户概览增加两项体积汇总,汇总范围与原概览相同,不随分页、SKU 或关注筛选缩小。
- 尺寸使用查询时刻 `queryAsOf` 之前最近完整已发布的资料批次,按来源账号+货主编码+SKU 精确关联。后续翻页和下钻保持原时刻,整体刷新才取得新尺寸。
- 优先完整、正值且单位有效的仓库实测长宽高;否则使用完整商品申报尺寸,并标明估算。不混用两套长宽高。支持 mm、cm、m、in、ft,英寸严格按 0.0254 米换算;未知单位不猜测。
- 库存立方数=当前全品质实物件数×单件体积。不叠加冻结、次品或在途,不代表托盘/库位占用或含空隙的仓储空间。过期、缺失或异常库存保持未知。
- 出库立方数=对应完整出库窗口件数×当前商品单件体积。所有历史出库体积均明确标为估算,不冒充历史包裹实测体积;7/15/30 天及所选 N 天独立判断覆盖,不以部分销量冒充完整体积。
- 先按 SKU 计算再聚合货主与本仓,不平均尺寸、不按当前页求和、不把同名 SKU 跨客户合并。已知零件数可得零体积;正件数缺尺寸及数量未知分开统计。正式总量未知显示“—”,保留已知体积小计、缺尺寸件数/SKU 数、数量待确认 SKU 数及商品尺寸估算件数。
- 表格体积列的m³放在有效数值后,未知值只显示“—”,估算及缺尺寸说明保留;库存立方数、所选窗口出库立方数支持SKU/货主全量升降序,单件体积仅SKU支持排序。排序取正式未舍入值,未知末尾,不以已知小计代替;切换排序保持上下文并回第一页。
- 不增加领星请求、重新采集或改动采集节奏。当前扩展仅在库存周转视图展示体积,原库存明细及销量分析保持现有指标。
保持 `/self-operated/inventory` 和现有菜单,页内提供「库存周转」「库存明细」两个视图。普通菜单进入默认“库存周转”,其中默认“按 SKU”;“按货主”是可选切换,不要求先选择货主,不在经营总览和销量分析恢复货主面板。
四个统计页面统一最近3/7/15/30天及自定义(1~366天),均截至北京时间昨日,日期选择器禁止今日及未来。原库存明细继续承接所选时段查询与经营总览严格下钻,不得被新默认页签吞掉或转换成相似的新筛选。它是现有查询能力的明确入口,不增加旧协议别名。
仓库优先级为合法深链仓库、当前页面保留的有权限仓库、服务端返回的首个有权限仓库;不硬编码仓库编码。确定仓库后自动加载,默认截止日为北京时间昨天,计算基准为 30 天,按实物件数降序、未知末尾。无可用仓库不发经营请求。非法深链或无权仓库明确报错,不静默改查其他仓。
新视图路由参数使用 `view=TURNOVER,groupBy=SKU|OWNER,endDate,baseWindowDays=1..366`,以及其合法筛选/排序和查询上下文。显式 `view=DETAIL` 或原总览严格下钻走原合同;相互冲突的参数拒绝,不混合两套筛选。重置保留仓库,恢复新视图默认条件并重新查询;刷新、查询都只读本地已发布数据,不创建采集任务。
页签判定按以下顺序执行:总览严格下钻(`from=overview`/`drilldownFrom=DASHBOARD`)进入 DETAIL;其次采用合法显式 view;未指定 view 但有明细专属 `salesWindowDays,attention,coverageSelection,coverageBucket,bucketRuleVersion` 时进入 DETAIL;其余默认 TURNOVER。`warehouseCode,sku,customerCode,endDate` 和公共版本字段本身不决定页签。优先级不吞掉冲突:显式 TURNOVER 同时携带总览来源或明细专属条件必须报错,所有参数再按选定视图校验。
## 页面示意与交互
以下是布局与承载设计,不是实际数据或已验收截图。沿用模块 ECharts、蓝紫主色及浅色指标卡,数量、异常和数据状态同时有文字,不只靠颜色。
```text
库存分析 库存周转〔默认〕 库存明细 数据采集
仓库 [当前仓] 统计时间范围 [最近3 / 7 / 15 / 30天 / 自定义] 查询 刷新
按 SKU / 按货主 SKU 搜索〔仅 SKU 视图〕 关注条件 / 阈值 / 排序
销量:7日完整、15日缺2日、30日缺12日 当前库存采集:开始……完成……
────────────────────────────────────────────────────────────────────
实物件数 正品可售件数 所选时段无出库 SKU 待评估 SKU
────────────────────────────────────────────────────────────────────
货主实物件数 Top10(横条) 货主库存立方数 Top10/日均出库对比
────────────────────────────────────────────────────────────────────
全部 | 实物件数最多 | 所选时段无出库 | 消化较慢 | 消化较快 | 待评估
SKU/商品/货主 | 实物/可售 | 7日/15日/30日出库 | 日均 | 可售天数 | 状态
……服务端分页,20条/页…… 扩展列/统计说明
```
图表约 220~260px 高,可折叠且记住本页偏好,表格仍是比较明细的主区。四张指标卡和两图显示当前仓库及精确货主范围的整体情况,不随 SKU 关键字、关注筛选及翻页改变;区块标明“本仓概览”或“本货主概览”。列表上方单独显示筛选结果条数,不能让全仓卡片被误读为当前页合计。
指标卡主数值只展示正式总量,未知总量显示“—”;已知小计(含0)与待核验SKU数放辅助说明,不用已知小计冒充完整总量。库存过期须明确显示最近观测完成时间及受影响指标;同仓采集失败独立显示原因、真实任务号与状态观测时间,沿现有数据采集入口查看。整体刷新同时更新只读采集状态,状态请求失败须说明,不能继续把旧失败当最新状态或影响已成功返回的经营数据。样本证据明确区分出库历史、原始库存观测和流水还原的日末库存;截止日只允许已结束的北京时间日期。当天08:00库存仅作为独立锚点,尾段和对账齐全后可还原并发布昨日库存,不需要再等一天。
货主 Top10 按有效全品质实物件数排序,未知货主不按零参与排名,图旁显示未能完整计算的货主数;标题必须是“实物件数”,不写“占仓面积/占仓最多”。相同件数按货主编码稳定排序。点击条目切入本仓该货主的 SKU 视图,显示可清除的货主条件,保留上下文;不足十个按实际数展示。
右侧默认显示“货主库存立方数 Top10”,标题处切换“日均出库对比”,切换不发新请求、不改变筛选和查询上下文。体积榜复用当前全品质库存体积口径,按完整未舍入值降序、同值按货主编码稳定排序,最多十个;缺尺寸或数量未知的货主不按零或已知小计排名,展示未参与的货主数。条末显示最多两位小数及 m³,明细保留尺寸来源及估算说明,点击条目及明细货主沿用同版本 SKU 下钻。库存体积排名不受统计时段影响,不代表库位空间或占仓面积。
日均对比包含截至所选结束日的7/15/30天及所选N天(去重),每窗完整出库分别除以对应自然日数,各柱独立判覆盖,不比较不同天数的原始累计量;无完整口径的柱留空并显示原因,不画零柱。图表用于观察平均速度,不直接生成增长率或客户等级。
| 操作 | 承载与行为 |
| --- | --- |
| 切仓/截止日/计算基准/分组 | 同页 QueryToolbar;更新条件并回到第一页;切仓清旧数据,取消旧请求并校验请求世代 |
| 关注与阈值 | 同页紧凑控件;选择消化较慢/较快时展开整数天阈值,输入有效后查询;不新增确认弹框 |
| 按货主切换 | 同页服务端分页汇总;切换时清除 SKU 关键字及仅适用 SKU 的排序,提示条件已调整;保留仓库、截止日、基准及有效精确货主条件 |
| 点击货主 | 同页切回 SKU 列表并添加精确货主 chip;返回货主汇总恢复原页码、筛选和上下文 |
| 点击 SKU | 复用当前 1120px 居中 SKU 日趋势 AppDialog,带真实货主+SKU与所选基准区间;不加抽屉或独立详情页 |
| 历史库存记录与未知原因 | 主表隐藏“状态与样本”列,不逐行显示日样本进度;期间平均实物/期间件数周转未知时显示“—”,悬停说明原因。在现有“统计说明”中选择本页商品或货主,打开现有 1040px 居中证据 AppDialog 查看历史库存记录及销量覆盖,最多 366 日 |
列表快捷筛选右侧提供默认选中的带边框复选框“隐藏 0 库存”(`hideZeroInventory`,省略时为true)。按当前全品质实物件数筛选:SKU视图隐藏明确零实物SKU,货主视图隐藏汇总实物明确为零的货主;未知、过期库存不当作零,可售为零但仍有实物的记录保留。服务端在完整候选上筛选后计数、排序、分页;不改变概览、图表及货主内部销量的汇总范围。取消勾选显示全部,切换立即回第一页并保留查询快照,分组/货主下钻保持选择,重置恢复默认选中。
| 图表完整明细 | 沿用 1040px 居中图表明细框,支持键盘等价下钻;不默认重复展示第二张表 |
| 统计说明 | 同页折叠文字,集中说明三种指标、时间及未知规则;主表不重复长段说明 |
SKU 列表是只读分析表,无须新增“操作”列。第一组身份列为 SKU、商品名称、所属货主;长名称可换行,不以内部 ID 回退。首屏保留三窗出库及主要库存/速度指标;在正品可售后默认展示“在途”列,SKU及货主视图均支持全量升降序排序,未知末尾;冻结、次品、期间平均库存、周转次数、最近已观测出库日放扩展列。历史库存记录明细收进统计说明,不单设状态与样本列。允许表格内部横向滚动,不挤小全页字体。
本节是新视图的逐操作设计依据,总控实施时并入模块 `operation-matrix.md`;原明细和总览承载继续沿用既有矩阵。视觉验收为人工 1920×1080、100% 截图,缺证据记“待人工截图确认”。
## 统计时间与三种指标
所有窗口使用同一个北京时间截止日 D,默认昨天且不允许未来或未结束的今日。N 天范围为 `[D-N+1 00:00, D+1 00:00)`,N 为所选日期数(1~366);保留7、15、30天辅助对比,非这些天数的所选窗口另行返回;不是自然周/自然月。例:截止 2026-10-12,三个起始日分别为 10-06、09-28、09-13。
三列出库量始终同屏;`baseWindowDays` 决定日均、可售天数、无出库、快慢查询和期间周转的计算基准,默认 30,不会偷偷把未齐的 30 天换成 7 天。每窗独立返回完整量、已采集量、完整/部分/未知日数、实际日期及原因。部分窗口显示“已采集 X,覆盖不足”,所有日均与派生判断不采用该部分量。
SKU 窗口出库、日均、可售天数及无出库判断与库存明细使用相同资格:仓库固定销量版可信且日期覆盖完整、商品及实际出库数量单位有效时,缺销量行可确认为窗口内零出库,不再要求商品首次观察早于窗口起点。单日存在无效单位或异常出库数量时必须撤销该日资格,不能由缺行补零掩盖。首次观察时间保留为证据;历史周转以合格日末库存资格为准,不再要求观察起点早于整个窗口,历史库存缺口仍不得补零。卡片汇总与列表筛选使用同一结果,真正未知的库存或出库继续保留已知小计和待核验数。
| 指标 | 计算与命名 | 资格 |
| --- | --- | --- |
| N 日日均出库 | 同期完整实际出库件数 ÷ N,含真实零出库日 | 使用固定销量版日事实及完整日规则;不只除以有出库的天数 |
| 预计可售天数 | 当前正品可售量 ÷ N 日日均出库 | 沿用库存有效性、可信窗口完整性及数量单位资格,不以 SKU 首次观察时间阻断;描述正品可售库存,不代表全部实物消化时间 |
| N 日件数周转次数 | 同期完整实际出库件数 ÷ 同期每日全品质日末实物均值 | N 个合格同口径日代表、范围/单位/商品身份可靠、同期销量完整;显示“次/N日”,不叫财务周转率 |
期间平均库存为 `N 个合格日末实物量之和 ÷ N`,统一采用本节 `FLOW_EOD_V1` 流水还原规则,不使用日内首次快照、期初/期末二点平均或时间加权平均。每个日版本的商品库存先按品质聚合一次,冻结和次品是实物子集,在途不加入。出库分子为同商品同单位全部实际出库,不以某个库存品质过滤重复累加订单。
当前库存和历史期间独立:更改截止日只改变销量及平均库存的历史区间,预计可售天数仍使用查询时固定的当前库存,页面必须保留库存观测时间。历史周转有完整样本时,不因当前库存过期而抹去历史结果;当前可售天数仍须失效。不同 N 的周转次数不是同一期间,不能直接比较次数得出速度变快。
计算保留原六位小数精度;日均显示两位、天数一位、周转次数两位,筛选和排序使用未舍入值。很小的正数按显示精度显示“<0.01/<0.1”,不伪装为真实零;前端不重新推算业务指标。
仓库/货主的 7/15/30 日日均出库图按固定已发布销量版的实际覆盖与单位资格独立计算。后台补采或归并触发 `rebuildRequired` 时,不抹去该版已经完整覆盖的日期;图表显示销量发布时间和新版待重算提示,未发布的事实及其他版本均不混入。30 日未齐不能用已覆盖天数缩小分母。SKU当前库存评估继续受待重算保护,图表旧版可读不代表可作为最新补货或告警依据。
### 零值与数据不足
| 条件 | 结果 |
| --- | --- |
| 窗口完整,当前正可售,但出库为零 | 日均 0,可售天数为空,显示“所选窗口无出库”;不填无限大 |
| 当前库存有效且可售为 0 | 可售天数 0 并标“无可售库存”;不进入消化较快,不代表库存健康或货主优秀 |
| 当前库存未知/异常/过期 | 可售天数为空并说明;可靠历史出库及历史周转独立展示 |
| 7 天完整、15/30 天缺失 | 7 天可独立输出正式值,其他窗口显示已采集量/缺口;默认 30 日基准的日均及天数仍为空 |
| N 日日代表齐全且平均实物大于零、出库为零 | 件数周转次数为 0;仍要满足历史日末库存与销量完整性 |
| 平均实物为零 | 周转次数为空;有出库时说明“每日观测未捕获存量”,不输出无穷大或直接认定数据造假 |
| 有 30 天出库,但库存只有 2 个合格日样本 | 证据弹框显示 2/30、缺口和历史覆盖起点;周转次数为空,不缩小分母、不用当前库存直接替代历史 |
| 缺少独立锚点、流水不完整、日版本缺商品行或品质/单位异常 | 保留未知/缺口;不补零,不把原始快照事后改成历史日末记录 |
最近已观测出库日期取固定销量版的有效正出库最大日期,不以任意首采日充当。没有可靠日期显示“已采集历史内未见出库”;只有该日期至截止日连续覆盖且商品存在证据可靠时,才可显示“距最近出库 N 天”。不得将有限观察窗口内未见出库写成“从未售出”或真实库龄。
## 筛选与内部评估规则
新视图使用独立 `focus`,不改写原 `attention`、总览分桶或所选时段严格下钻含义。观察与异常证据沿用主方案。快慢阈值是本次查询输入,按仓库保存页面偏好但不是正式仓租政策;初始不预设未经确认的 90/180 天,不因未设阈值阻止默认列表。
| 快捷入口/focus | 规则与默认排序 |
| --- | --- |
| 全部 ALL | 固定版本候选全集,保留零值、售空及未知;默认实物件数降序 |
| 实物件数最多 | ALL+实物降序;不得称为占用空间最大 |
| 所选时段无出库 NO_OUTBOUND_IN_WINDOW | 有效正实物、所选可信完整时段出库为零及有效数量单位;包含全冻结/次品;按所选基准窗口判定 |
| 消化较慢 COVERAGE_GT | 有效正品可售量和 N 日日均均为正且正式可售天数 > 查询阈值;天数降序 |
| 消化较快 COVERAGE_LE | 有效正品可售量和 N 日日均均为正且正式可售天数 ≤ 查询阈值;天数升序;只是消化估算,不代表持续销售或正式高周转等级 |
| 冻结/次品 FROZEN/DEFECTIVE | 对应有效数量 >0,不依赖销量完整性;这些库存可能无法按日均正常售出 |
| 待评估 UNASSESSABLE | 当前库存、所选 N 日可信窗口或数量单位资格不足,无法完整评估流转表现;有效零可售仍按优先规则显示0天,窗口不足时可同时标“待评估:销量覆盖不足”;完整零出库不属于此类 |
可售天数判定固定为库存有效性 → 明确零可售 → 正可售的窗口/单位资格 → 分母是否为零;待评估标签不覆盖这一数值顺序,也不等同“可售天数必为空”。另提供“周转样本不足”状态/筛选 `turnoverStatus=INSUFFICIENT`,它与经营待评估独立:已有完整出库和可售天数的 SKU 可以仅缺历史库存样本。无出库与慢消化是不同集合,不将空天数伪装为超大数;冻结/次品与其他关注可重叠,不把标签命中数相加当总 SKU 数。
货主视图不把整个货主简单分为快/慢:使用“含此类 SKU 的货主”筛选,行内同时显示该类已确认 SKU 数、实物件数和待判断数;未输入阈值时快慢相关值为空并显示“未设查询阈值”。
## 货主汇总
货主汇总是一条服务端分页聚合查询,不先获取货主选项再逐个调用 `owner-overview`。身份键为来源账号+仓库+货主;SKU 继续以货主+SKU 去重,不跨货主合并同名商品。
每行展示货主名称/编码、有实物 SKU 数、实物/正品可售/在途/冻结/次品件数、7/15/30 日出库、所选 N 日日均、所选时段无出库 SKU 数及实物件数、慢消化命中和待评估数量;期间周转放扩展列。不平均 SKU 可售天数,也不输出“总库存÷总日均”作为货主整体可售天数。
货主历史出库和平均实物候选必须涵盖期间曾有库存或出库而当前已售空的商品;不能先筛当前正库存再算周转。货主平均实物先按每个合格日代表汇总该货主全部同口径商品,再取 N 日均值;完整时用货主同期总出库除以该平均量。它仍是混合商品的件数指标,不作为跨货主奖惩排名,不能用高销量小件掩盖积压大件。
每项总量分别提供正式总量、已知小计和未知数量。销售窗口完整即可展示货主真实出库总量;单个 SKU 库存观察不足不抹掉已可靠的出库事实。无出库等正式命中件数占比,只有整个候选范围及判断均可靠才输出;否则仅给已确认小计与待判断数。比例为实物件数比例,不是空间占比;分母零时比例为空。
## 服务端合同与数据结构
新增 Lastleg 只读 `GET /api/platform/v1/last-leg/self-operated-analytics/inventory-turnover`,供新视图使用;原 `/inventory-coverage`、`owner-overview`、经营总览及其严格下钻合同保留各自用途,不把原单窗口接口改成三次调用。复用平台 list 权限、仓库范围检查和既有异常响应。最终 Controller、DTO、OpenAPI、前端类型必须一起收口,以下是开发目标,不宣称接口已经存在。
| 入参 | 约束 |
| --- | --- |
| sourceAccount、warehouseCode | 沿现有受控配置及服务端范围检查;只查单仓 |
| endDate、baseWindowDays | 截止日含当天且必须为已结束日期;基准 7/15/30,默认昨天/30;三窗固定返回,不传任意窗口数组 |
| groupBy、customerCodes、sku | SKU/OWNER;customerCodes 为可选货主编码集合,重复query键传输,最多100个,省略或空集合查询全部,列表/概览/图表统一按集合筛选,不合并不同货主的同名SKU;下钻传单元素集合;sku 只适用 SKU 分组,OWNER 携带则拒绝 |
| focus、coverageDaysThreshold、turnoverStatus | 按上节枚举;GT/LE 必须有正整数阈值,其他关注可带阈值展示标签;拒绝原 attention/coverageBucket 等混入 |
| sortBy、current、size | 按分组白名单排序;默认 PHYSICAL_DESC,1/20,size≤100;同值以 SKU+货主或货主编码稳定排序,未知末尾 |
| 查询上下文 | 复用固定版本、queryAsOf 和有效期;新增历史日代表集合的固定证据,不能由客户端任填 run ID 绕过检查 |
SKU 数值表头支持实物件数、正品可售、7/15/30 日出库、所选基准日均出库、预计可售天数,以及扩展列冻结件数、次品实物、期间平均实物、期间件数周转的升降序。首次点击未选中的列使用降序,再次点击切换升序;箭头表示成功查询的顺序,与排序下拉框共用同一合同。切换排序回到第一页,保持有效的查询上下文;按全部筛选结果排序后分页,不在当前页重排。日均排序随 `baseWindowDays` 使用对应窗口。未知或覆盖不足的正式值始终排在末尾,不按已采集小计或零参与;同值按 SKU+货主稳定排序。OWNER 支持相同指标(预计可售天数除外)及已确认无出库实物小计排序,同值按货主编码稳定排序,未知状态随值返回。
一次响应返回 `context,summary,charts,rows,total`。首次/整体刷新返回概览与两图,普通列表翻页用同一上下文及 `includeOverview=false` 省去重复汇总;筛选 SKU 或关注不改变概览范围。切仓、截止日、基准、精确货主或分组变化时,重新请求对应概览;不得把新上下文的行与旧图拼屏。
`context` 固定账号、仓库、销量版、当前库存版、queryAsOf、有效期、三个真实窗口、当前库存观测起止、历史日末规则与最多366个日期到独立日版本的准确映射及摘要。历史样本只纳入首次上下文时已经发布且合格的代表;后续样本补齐不能悄悄改变旧查询。实际代表映射须可由服务端验证/重建,缺失日期也冻结,不只是返回一个不可校验的哈希。受引用版本按现有保留策略保护,到期或无法重建时明确要求整体刷新。
每窗指标至少返回 `days,startDate,endDateExclusive,outboundQuantity,observedQuantity,averageDailyOutboundQuantity,completeDayCount,partialDayCount,unknownDayCount,dataStatus,reasonCodes`;行另外返回 `inventoryCoverageDays,averagePhysicalQuantity,quantityTurnoverCount,qualifiedSampleDays,requiredSampleDays,attentionReasons` 及各自状态。不能用一个行级 COMPLETE 掩盖部分指标未知。内部版本标识用于程序,不作为用户可见业务编号。
### 复用表与最小结构要求
| 数据 | 复用与约束 |
| --- | --- |
| 三窗实际出库 | `ll_selfop_sku_daily_sales`,按固定销量版、仓库及最长max(30,N)日读取,一次条件聚合三窗;仓级概览优先复用 `ll_selfop_warehouse_daily_sales` 及原覆盖证据 |
| 当前实物/可售/在途库存 | `ll_selfop_inventory_snapshot`+其固定 profile,同 SKU 全品质先聚合,避免与日销量多行连接后乘倍 |
| 历史平均库存 | `ll_selfop_inventory_day_version`+`ll_selfop_inventory_daily`,固定最多366个不可变日版本,检查范围、规则和已知失效标记 |
| 商品观察与缺日 | 固定版本 profile+销量覆盖证明+各库存代表的资格;可信完整销量覆盖内缺销量行可计零,缺库存代表行仍不得补零,不读取可变最新档案污染旧上下文 |
| 查询上下文 | 压缩JSON+HMAC签名令牌固定准确日版本集合;服务进程重启后旧令牌要求整体刷新,当前单机单实例部署不依赖跨实例共享密钥 |
不新增 7/15/30 天销量表、不存一张会被实时覆盖的“SKU 周转结果表”;历史流水、独立日版本与还原日明细及专用调度按本文件首节实现。若实际执行计划证明需要索引或有界聚合缓存,由总控在唯一 SQL 基线中评审;不凭设计先引入缓存平台。没有历史代表时,周转值为空即可交付页面,不能为得到数值额外扫描领星或修改原样本标记。
## 查询性能与一致性
所有查询读取本地已发布数据,不查原始订单明细,不调用 Integration。禁止前端逐 SKU/逐货主请求、把第一页求和当全仓汇总、先取 Top100 后筛选、为三窗执行三套完整扫描。
候选身份是本次固定当前库存版 profile/snapshot、固定销量版所选最长max(30,N)日事实及相关 profile、同期合格历史日版本的 daily 中货主+SKU 的并集;不读取后续可变档案。仅历史存在而当前缺行的商品保留为当前库存未知,不能补零。rows、total、summary 和图表使用同一候选定义,再分别应用各自已声明的范围与列表筛选。
默认实物排序且无销量/天数/周转等依赖筛选时,可先对完整候选身份分页,再补该页三窗和历史样本,不能只从当前 snapshot 选页而丢失未知/售空商品。依赖销量、可售天数、周转次数的筛选/排序必须先在完整候选计算资格,再排序分页。货主聚合与图表独立按完整范围计算;复用现有性能方案中已验证的路径,不原样重复已无收益的优化实验。
验收采用单仓至少1万货主+SKU、最多30日代表、多历史销量版、10并发只读用户及后台构建场景。新增目标:首屏含概览 HTTP P95≤1.5s;默认列表翻页 P95≤1s。复杂筛选、货主汇总和完整30日周转排序分别报告,不用缺样本快速返回证明达标;未达目标记录瓶颈交总控安排,不能伪报通过。保留 P50/P95/P99、SQL 数、扫描行、响应大小及结果对照,压测不请求领星。
相同条件刷新失败可以保留旧结果并明确时间;切仓清旧结果。当前库存过期时只失效依赖当前库存的判断,历史销量/历史周转仍按各自证据展示。页面刷新不会改变采集状态,开发与发布不得为本视图重置采集任务。
## 开发顺序与职责
1. 总控冻结新增接口、窗口/零值规则、历史样本上下文和文件写权;明确 SKU 默认与货主可选视图是本轮新增例外,同步最近模块指引及操作矩阵,不恢复其他页面货主控件。
2. 指标查询工作包实现一次三窗聚合、库存资格、分页排序、全范围汇总与有资格的期间周转;样本不足作为正常业务状态,补定向公式/覆盖/版本测试。
3. 前端工作包实现默认打开、表格两视图、紧凑图表、筛选与既有趋势/证据弹框;先按冻结 DTO 并行,随后联调。共享类型与导航由总控协调唯一写者。
4. 采集实现按首节完成受控流水分页、本地重建、独立库存对账和原子日版本发布;保留现有销量优先级及统一出口约束。
5. 总控完成接口、SQL 基线、权限及受影响门禁,安排人工页面验收。实现、自动测试、部署、人工验收分别记录;运行状态仍只维护正式工程契约。
优先交付能立即使用的默认查询、三窗出库、日均/可售天数、关注筛选与货主汇总;期间周转的合成样本测试同期完成,真实数值由已验证流水还原历史日末库存后产生,无证据的日期继续保持缺口。不得以“已有可售天数”宣称正式周转已完成。
## 验收清单
| 场景 | 必须结果 |
| --- | --- |
| 普通菜单进入/有效深链/无仓库 | 自动选合法仓并查询;深链优先;无仓不查;不要求先选货主 |
| 截止2026-10-12 | 三窗起止分别为10-06/09-28/09-13至10-13不含,均不包含今日 |
| 示例 SKU:7/15/30日出库70/150/300,当前可售600;选30日 | 三列各自真实显示;日均10,可售60.0天;切7日仍日均10,不改三窗累计 |
| 同一SKU同期30个日代表实物均值500,30日出库300 | 30日件数周转0.60次;不能用当前可售600算成0.50次 |
| 7日齐、15/30日未齐 | 7日正式值可用;其他显示已采集量与不足;30日基准天数空,不自动缩短窗口 |
| 30日出库齐、仅2个日代表/只有人工TEST库存 | 显示真实样本缺口,正式周转空;销量和符合资格的可售天数继续展示 |
| 全冻结/次品正实物且完整30日零出库 | 可命中无出库和库存品质关注;可售为零不判消化较快,不重复累加实物 |
| 新品/首次观察晚于窗口起点 | 可信完整销量窗口按实际出库计算日均、天数及无出库判断,不因观察时间变成覆盖不足;期间件数周转仍核对历史库存样本与观察证据 |
| 来源库存缺行/负数/过期或销量未覆盖 | 对依赖指标逐项传播未知;不得把真正未知数量补零,负数不取绝对值 |
| 库存有效且可售0,但销量窗口不足 | 可售天数0并标无可售库存,同时保留销量覆盖不足及待评估;不因0天进入消化较快 |
| 平均库存正且零出库/平均库存零且有出库 | 前者周转0;后者为空并说明单日观测局限,不显示无限大 |
| 当前售空但期间有出库与历史库存 | 仍计入货主期间出库及平均库存;不因当前零库存丢失历史贡献 |
| 同仓同名SKU不同货主、两仓同货主SKU | 分行、分仓、独立窗口资格,不混合库存或借另一仓历史 |
| 货主有部分未知商品 | 出库、库存及关注分别传播;保留已知小计与未知数,不用合格样本比率冒充完整风险占比 |
| 切货主/筛选/分页/图表下钻 | 统计范围标签准确;列表 total 与全量谓词一致;图表不由当前页拼出;身份与上下文不丢 |
| 原经营总览无出库/最长天数/分桶跳入库存 | 进入原库存明细,保留原所选时段资格、严格版本及时效,不落入新近似筛选 |
| 新版发布、日样本新增、旧上下文读取 | 旧上下文结果不漂移;整体刷新才切新;过期明确要求刷新 |
| 页面与性能 | 1920×1080人工核对;三窗与主库存可读;未知有原因;性能按上述真实完整样本分别报告 |
本轮评审已明确:7/15/30是完整滚动窗口;四页日期统一最近3/7/15/30天及自定义,原明细继续有入口;货主汇总仅在新视图可选;件数不是空间;可售天数不是库龄或期间周转;历史样本不足不造数;新视图查询不增加领星请求。待后续业务确认的是正式仓租/优惠阈值、空间数据和成本主体,均不阻断本次只读功能开发。
自定义长区间的签名翻页上下文携带准确日版本ID集合及SHA-256摘要,服务端按固定ID读取并重建max(30,N)日历(含缺失日期),不再通过墙钟时刻推定某个版本当时可见。已知修订使所引用旧版本失效时明确要求刷新;普通新版本发布不改变旧查询。完整日历留在响应,日版本字段为dayVersionId。
### 货主多选、导出与期间周转率(2026-10-15确认)
货主筛选支持可搜索多选,清空恢复全部,变化回到第一页;概览及图表标注“所选货主”。期间周转率默认显示,沿用期间件数周转次数×100%,历史库存样本不足或分母不可计算时保留—,不以当前库存替代。
默认“期间周转率”表头支持全量升降序,与扩展周转次数列及筛选区的“期间周转率从高到低/从低到高”同步,未知值始终末尾。点击排序保留货主、日期、隐藏零库存及固定版本,回到第一页。表头独立信息按钮展示百分比公式、每日末均值、货主汇总与未知值口径;打开说明不触发排序或查询。
顶部“导出”接入统一下载中心,提交 SELFOP_INVENTORY_TURNOVER 后台任务生成 XLSX;浏览器不再分页拉明细或拼CSV。提交参数固定当前已查询的筛选、排序、版本、总条数及有序列键,扩展列打开时一并提交;列名、周转率、未知与估算说明由 Lastleg 生成,File 分批写文件并提供进度、下载和重试。离开页面不取消已提交任务。独立权限为 platform:self-operated-analytics:export,仅平台非代登录账号可创建/下载/重试。
沿用库存周转查询的30分钟固定上下文,不在排队或重试时重新取最新版本。上下文过期、后端重启或日版本失效须刷新列表重新提交;条数变化、缺页等异常整任务失败,不提供部分文件。每批100条,最多200000条,沿用下载中心文件大小与存储有效期限制。必带统计期间、期间出库、平均日末库存、周转率及历史证据列,其他列保留当前表格顺序;新增 File 类型配置及IAM导出权限,无业务建表或销量/库存回写。
+200
View File
@@ -0,0 +1,200 @@
# 数据采集页面设计
把采集首页和任务详情改成能直接看懂的进度界面:**正在做什么、总量多少、完成多少、还剩多少、预计还要多久、结果是否已经可用。** 历史尝试、配置和诊断按需展开,不再让用户从多段文字和两张宽表中寻找答案。
2026-10-13 用户已确认本文方案及配套交互示意,并明确交由开发总控 `01a12feb-0474-77f1-afe0-a3b491733dca` 安排开发。方案维护对话只维护文档,不修改业务代码;图形示意不是实时任务监控,方案确认也不等于正式页面视觉验收。采集范围、统计口径、发布条件和账号保护继续以[一期方案](领星一件代发数据统计一期方案.md)为准,查询性能按[优化方案](领星统计查询性能优化方案.md)验收。
## 从这条任务暴露的问题
用户关注任务为 `LXCOL-20261013-FC1699DFFB6E4EC7`,截图显示 US01、2026-10-12 的出库销量采集。本仓状态为“等待数据准备”,详情却显示来源任务 `LXCOL-20261013-0D70D251A9C5488F` 正在获取详情,已处理 339 / 2,787 单。两种状态可以同时成立:来源数据还在准备,本仓尚未开始归并。
上述数量只代表截图时刻的来源阶段,不能当成此刻实时进度、US01 单量、SKU 销量或整个同步的完成比例。按截图口径剩余 2,448 单,阶段百分比为 12.1%;展示沿用服务端统一舍入口径。
| 当前问题 | 用户需要看到的解释 | 设计处理 |
| --- | --- | --- |
| 首页只写等待,关键列被截断 | 后台到底有没有在干活 | 首屏聚焦当前关注任务,同时展示已确认关联的来源进度 |
| 本仓执行 0 次,来源却正在执行 | 两段状态是什么关系 | 用“来源准备 → 本仓归并 → 统计计算 → 结果发布”阶段流串起来,范围分别标注 |
| 详情重复任务号并铺满文字 | 总量、已完成、剩余在哪里 | 标题保留一次完整任务号;主体用数字摘要、阶段进度图和一句状态解释 |
| “完成时间暂无法预计”长期不变 | 大概要等多久 | 增加基于可靠检查点的速度与当前阶段剩余时间;不具备条件时解释具体原因 |
| 空执行历史占大块区域,仍展示恢复表单 | 是否有需要我处理的事 | 历史默认收起;无尝试显示一行摘要;不可恢复时不铺表单 |
| 页面更新时间看起来很新,但数量未动 | 是页面在刷新,还是任务在推进 | 区分状态读取时间、进度推进时间和执行心跳 |
### 源码核对结论与边界
当前前端已有阶段计数、尝试信息、共享来源和结果状态,不需要另起一个监控系统。但后端 `currentTasks` 按最新创建任务选取,不保证它正在执行;详情上游依据直接关联,概览另有时间窗口关联。调度占位任务还可能没有自己的执行尝试。因此,改版必须补齐“当前实际执行”和“本任务等待对象”的语义,不能只改变文字或给现有最新记录套进度条。
源码入口为 [CollectionView](../../apps/admin-web/src/modules/self-operated/pages/CollectionView.vue)、[CollectionQueryService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/CollectionQueryService.java)、[CollectionReadMapper](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/CollectionReadMapper.java) 和 [SelfopProgressProjection](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/model/SelfopProgressProjection.java)。这些是只读源码结论,不证明截图任务最新运行情况或部署状态。
## 首页:先看正在发生什么
### 2026-10-13 单账号首屏收敛(优先于下方原方案)
用户在最新截图中明确:只有一个领星账号,首页只关心账号正在做什么、完成/剩余多少、预计本阶段多久结束及后续处理。首屏改为账号运行看板,直接使用账号活动与各仓实际活动摘要,不受历史任务号或仓库筛选影响;不能把停止的历史记录作为主进度。布局按配套原型重构为运行看板,配色使用现有 Admin 白色卡片与蓝紫色强调,保留环形进度、三项数量、预计时间和阶段流程;待机时显示最近发布结果与各仓可用状态,不把待机画成100%完成。
按用户最新要求,采集页移除仓库筛选、任务定位、配置、历史详情、诊断与恢复表单,只读一个账号概览接口;旧链接中的仓库和任务号不改变账号首屏。后续阶段用流程说明展示,不宣称已确定执行顺序;待处理只列服务端已返回的活动摘要(每仓每类型有上限),不能将其数量冒充全账号剩余任务总数。没有完整队列与总任务ETA契约时如实说明,继续展示可靠的当前阶段剩余量和阶段ETA。
保留“自营业务 → 数据采集”和现有页面路由,按以下顺序组织。沿用 [Admin 高密度规范](../Admin高密度界面规范.md),使用连续白底区域、轻分隔和紧凑间距,不为每个字段单独放一张大卡片。
1. **查询栏:** 仓库、采集内容、任务号定位、查询/刷新;北京时间作为统一辅助说明。任务号支持完整粘贴。选择仓库后定位该仓任务,错误仓库返回明确提示,不自动跨权限搜索。
2. **当前关注任务:** 一行完整任务号、仓库、采集内容和数据日期;下面是阶段流、当前阶段数量、等待原因、预计剩余时间和最近推进时间。普通用户无需先打开详情就能理解进展。
3. **各仓数据可用情况:** 紧凑表展示仓库+采集内容、当前活动、最近可用数据、覆盖/新鲜度。出库与产品库存各自独立,库存已发布不代表销量已完成。
4. **任务记录:** 保留分页、筛选和历史详情。初始展示较少行,把视觉重点留给当前任务;历史列表不能代替实时运行概览。
首屏焦点默认采用服务端明确的实际活动/阻塞任务,不将“最新创建”冒充“正在执行”。同仓有多个关联任务时给出数量和可切换入口,切换后持续关注所选任务,不被刷新自动换掉。手动选择历史记录时标明“查看历史任务”,保留返回当前活动入口。
任务号定位同步到现有路由查询参数 `warehouseCode,taskNo`,读取已有受权限约束的任务详情;不要求用户先翻到该任务所在页。轮询不重置历史分页,不丢弃手动选择。任务不存在、无权访问、首次读取失败、暂无任务分别呈现。
### 历史记录压缩为六列
| 顺序 | 列 | 呈现方式 |
| --- | --- | --- |
| 1 | 操作 | “查看详情”;需要固定时固定左侧,不统一写“详情/恢复” |
| 2 | 任务/范围 | 完整任务号允许两行;辅助行放仓库、出库/库存、正式/验证用途 |
| 3 | 数据时间段 | 显示明确日期区间,精确起止时间进入详情;统一北京时间,结束边界不歧义 |
| 4 | 当前阶段与进度 | 阶段标签+简短计数;等待来源时标注来源范围,不塞完整解释段落 |
| 5 | 最近进展 | 推进时间及多久前;没有执行尝试时显示未开始本仓执行,不能用读取时间填充 |
| 6 | 执行/发布结果 | 如“等待来源 · 未发布”“已完成 · 已发布”“本次失败 · 旧数据可用” |
完整技术字段、重试资格、尝试历史和诊断从详情查看,不继续横向增加列。按 1920×1080、100% 缩放及展开侧栏验收:关键状态与进度不依赖横向滚动,任务号不只剩无法区分的前缀,长内容自然换行,不缩小字号硬塞。
## 详情:图形进度在上,诊断记录在下
继续使用已确认的 **1200px 居中 AppDialog**,保留全屏与关闭;不新增抽屉或独立详情页。弹框标题只出现一次完整业务任务号,内容分为三层。
### 第一层:数量、进度与时间
顶部显示“US01 · 出库销量 · 2026-10-12”和简短状态。当前正在等待来源时,主状态为“等待来源数据”,其下突出“关联来源正在获取出库详情”,避免一个大大的“未开始”盖过真实活动。
主体左侧为当前阶段的环形进度图,右侧为一组数字和时间摘要,共用一个区域:
| 位置 | 本次截图对应的呈现 | 规则 |
| --- | --- | --- |
| 图形标题 | 来源详情采集 · 账号共享 | 图形旁持续显示范围,不能只放在提示浮层中 |
| 中心数字 | 12.1% · 当前阶段 | 只有可靠分母才能画确定比例;不叫“同步总进度” |
| 数量摘要 | 总数 2,787 单/已完成 339 单/剩余 2,448 单 | 同一计数范围、阶段和基准;“单”不是 SKU 件数 |
| 时间摘要 | 任务累计耗时(含排队与重试);最近处理速度;预计本阶段还需多久 | 累计耗时使用 Task.elapsedSeconds,从 createdAt 起算,活动任务截止读取时间,终态截止任务最后更新时间;不受 attempt 或阶段切换影响,缺失显示 —;当前阶段 ETA 与任务累计耗时分别标注 |
| 提示 | 本仓尚未归并;来源完成后继续计算与发布 | 一句话解释下一步,不复述整段技术规则 |
未知总量显示“已完成 N 单/总量待确认”(库存按实际单位),使用不表达百分比的阶段状态图,不画 0% 或假转动的确定进度。零量仅表示数量,状态继续取服务端证据:如“0 单,正在核验”或“0 单,结果已发布”;库存显示对应页/行单位,不由 `total=0` 推断正在校验或已经完成。异常计数或总量变化时撤去比例,说明正在复核。
进度图只表达当前阶段。按 2026-10-13 用户确认,与自营业务其他图表统一使用 ECharts+vue-echarts 的 Canvas 配置,通过 `AnalyticsChart.vue` 复用;当前阶段环图使用无指针、无刻度的环形进度配置。未知、零分母及异常计数只显示空环,不填入虚假百分比。状态同时使用文字和图形,不只靠红绿颜色区分。
### 第二层:阶段流与结果可用性
出库流程画为五个节点:**来源目录 → 来源详情 → 更新本仓出库数据 → 统计计算 → 结果发布**。前两个节点标“账号共享”,后三个标“本仓”。完成节点用勾、当前节点用突出色、阻塞节点用原因、未开始节点用灰色;只有服务器确认适用时显示“复用完成/无需此步骤”。不能把完成两个节点直接换算为整体 40%。
节点完成必须有对应任务、尝试/轮次及切片的服务端完成证据,不能因当前进入后一个阶段就自动勾选之前全部节点。重复扫描、恢复或多切片时标明当前适用范围;缺少阶段历史证据显示“状态未确认”,不补造完成时间或完成结论。
产品库存采用自己的流程:**本仓库存分页 → 完整性校验 → 统计计算 → 结果发布**。展示页数、读取行数和去重业务键时分别标单位;库存行数不能冒充 SKU 数。
阶段流下方只保留两条业务说明:
- **本次结果:** 未发布/已发布/沿用已有结果/失败。来源完成或详情 100% 不等于本仓报表更新。
- **当前报表:** 正在使用哪次已发布数据、销量连续覆盖到哪天、库存观测时间。首次没有结果时显示尚无可用数据;已有旧版则继续展示其真实时效。
多日首采另显示目标日期范围和已发布覆盖/缺口摘要,目标从服务端读取。当前 TEST 最近 30 个完整日和生产首次最近 2 个月不得写成同一个固定标签;单个 12 日任务完成也不代表近 10/30 天可售天数观察窗口已经齐全。
### 第三层:按需查看与处理
“执行记录(N 次)”“校验与诊断”按需展开。配置只保留必要摘要,完整配置继续从原页面入口使用只读 AppDialog 查看,不在详情里另造配置区或叠开弹框。没有本仓尝试时只占一行:“本仓尚未开始执行;来源准备进度见上方”,不显示空表、空分页器。来源任务号与其尝试信息独立展示,不混进本仓尝试次数。
失败、长时间无推进或账号保护生效时,将简短原因提到上方;完整错误码、历史检查点和请求用量留在诊断区。质量尚未计算时摘要写“待校验”,不在多个区块重复长解释。可恢复任务且具备独立写权限时,才展示原有原因填写、核对与恢复操作;等待来源、正常运行或会话终止时不展示不可使用的表单。
恢复仍沿已有 `POST /sync-tasks` 的 `RETRY`、原任务号和幂等键,受服务端 `allowedActions/actionBlockReason` 控制。受理后只提示已排队,不能提示同步成功;页面不增加绕过账号暂停、会话截止或预算的“强制继续”。
## 预计时间:先给可靠的阶段估算
用户需要大概同步时间,因此把速度与预计剩余时间纳入本次设计,不无限期留一句“无法预计”。先交付**当前可计量阶段的剩余时间**;整个任务还需归并、计算、发布时明确说明。完整同步 ETA 只有所有剩余阶段均有可信工作量或校准过的历史耗时模型后才开放,不能把当前阶段 ETA 改个标题当总 ETA。
计算由服务端产生,页面只显示,不按页面轮询次数、请求次数或截图里的“339 单/78 秒”推算。78 秒可能是尝试耗时,且已完成数量可能包含检查点复用,两者并非同一个测速口径。
### 计算条件与公式
- 采样来自已提交的进度检查点。使用同一来源任务、尝试、阶段、扫描轮次、范围、单位和计数基准;分母已确认且在采样窗口内稳定,执行健康正常。
- 建议初始参数:最近不超过 3 分钟的有界样本,至少跨度 60 秒、至少 3 次真实推进。阈值集中配置,并用实际采集验证;这是实现建议,不是当前已测得的领星吞吐能力。
- `处理速度 = 窗口内新增实际处理完成量 / 窗口实际经过秒数`;正常运行期间没有推进的间隔也计入耗时,不能只统计快的请求。完成总数允许包含复用对象,但测速增量独立排除复用;窗口内新识别的历史复用也不能抬高速度。实现可保留可靠的实际处理增量,无法区分时遇到复用跳变重新建立基线,暂不估算。
- 同身份且完成数不变的保存不重置样本,也不计为有效推进;复用导致完成数增加仍重新采样。本次执行至少积累60秒、3次实际推进后估算,累计完成比例不能作为本次测速的样本量。有效期为最多30秒,为10秒轮询留出请求时间,仍受最近推进、执行健康及180秒采样窗口约束;选取在有效期内不会移出窗口的采样起点,避免窗口滚动造成短暂失效。
- 估算使用同一份进度身份、完成数、分母和时点。采样窗口截止到本次估算时刻,最后一次检查点后正常等待的时间也计入分母,补充的只读端点不伪造新推进。不能将旧估算与新 completed/total 混合返回;页面按身份和有效期整体接收或丢弃。
- `本阶段预计剩余秒数 = (可靠总量 - 已完成量) / 处理速度`。速度必须大于零、剩余量非负;以“约 N 分钟”向上取整展示,小于一分钟显示“约 1 分钟内”,不显示精确到秒的完成承诺。
- 阶段切换、尝试重开、轮次变化、分母变化或冷却后恢复均重建测速窗口。建议样本按 10 秒桶合并、最多保留 20 个端点,ETA 持久采样数据不超过 1 KiB,并与已有阶段记录合计遵守进度 JSON 8 KiB 上限。优先保留业务检查点及审计摘要;接近上限时压缩/丢弃 ETA 样本并返回暂不可估算,不能让估算附加数据导致采集提交失败。不为 ETA 扫描全部订单或引入独立时序平台。
| 情况 | 预计时间区域 |
| --- | --- |
| 正常推进且样本充分 | “当前阶段预计还需约 N 分钟”,同时显示最近处理速度与估算更新时间 |
| 刚启动/恢复后样本不足 | “正在测速”,照常显示已有完成量 |
| 总量未确定/正在变化 | “总量待确认,暂不估算” |
| 明确限流冷却 | “限流暂停;最早恢复时刻……;恢复后重新估算”,不把冷却结束当完成时刻 |
| 预算耗尽/人工暂停/失败/健康待确认 | “已暂停估算”+具体原因,不保留看似继续倒计时的旧 ETA |
| 超过配置的无推进期限 | 保留最后真实计数,显示“近期无新增进度,暂不估算”;心跳正常不等于有处理速度 |
| 页面读取失败/估算已过期 | 标记最后观测时间,撤去活动倒计时,显示更新失败或估算已过期 |
| 本阶段结束但后续阶段未知 | “本阶段已完成;正在归并/计算/发布”,不显示整个同步还剩 0 分钟 |
服务端返回 ETA 适用阶段、有效期及不可估算原因。全任务 ETA 留作后续校准能力,不阻塞本轮数量、阶段图、测速和阶段预计时间交付;不以提高领星请求并发来让预计时间变短。
## 任务关联、等待与活动状态合同
继续扩展现有运行查询 DTO,不新增平行的监控 API,不改采集任务身份。以下为需补齐的语义;已有等价字段优先复用,开发总控确认最终 DTO 命名并同步 OpenAPI、直接调用方和契约测试。
| 数据组 | 已有基础 | 必须补齐或明确的语义 |
| --- | --- | --- |
| 关注任务与实际执行 | `currentTask,latestAttempt,taskNo` | 显式区分最新逻辑任务与活动执行;无本仓 run 是合法状态。不能依赖创建时间推断活动任务 |
| 依赖与阻塞 | `sharedUpstream`、直接上游关联、概览窗口关联 | 建议返回 `dependencyState,blockingReason,progressSourceTaskNo`;服务端确认关联后才标“为本任务准备”。窗口相交只表示相关候选,不能证明直接依赖;多个实际依赖以有界摘要呈现 |
| 阶段计数 | `progressScope,countBasis,attemptNo,phase,scanRound,completed,total,totalKnown,unit,sliceFrom,sliceUntil` | 数量保留范围、来源和分母依据;本仓无投影不能借账号总数填充。本仓页可展示共享进度,但标题必须标账号共享 |
| 状态时钟 | `observedAt,progressUpdatedAt,heartbeatAt,executionHealth` | 读取时间、最后提交推进时间、执行心跳分别返回;终态尝试冻结可靠摘要时间。当前终态读取 `summaryAsOf` 而标准冻结路径未写此值,需补实际快照证据,不用查询时刻伪装 |
| 等待与保护 | `nextRetryAt,accountCooldownUntil,accountPauseReason` 和预算摘要 | 等待原因与不能重试原因分开;区分来源未齐、排队、冷却、会话截止、预算耗尽。前端不靠本地时钟自行判失败或宣布已恢复 |
| 速度与预计时间 | 现有可靠计数和阶段时间 | 建议有界 `stageEstimate`:状态、`progressIdentity`(来源任务、尝试、阶段、轮次、范围、单位、基准)、所依据的 completed/total,以及 `sampleFrom,sampleUntil,completedDelta,ratePerSecond,remainingSeconds,estimatedAt,validUntil,unavailableReason`;completedDelta 仅指实际处理增量。估算和进度依据一致才返回数值,有效期同时受状态观测及无推进期限约束 |
| 结果与覆盖 | `resultPublicationState,lastPublishedAt,initialCoverageStatus` 等 | 本次结果和目前报表可用结果独立;来源 `ROUTED`、预算 `YIELDED`、目录完整不能当成本仓发布 |
依赖不明确时,展示“本任务等待来源;关联进度尚未确认”。如服务端确有其他账号活动,可以另外显示“账号正在执行其他采集”,不能挂在这条任务下面冒充它的完成量。`actionBlockReason` 是操作资格,不能直接当成执行等待原因。
共享采集可能服务两个仓库,在全部仓库视图按来源任务号去重展示一次;本仓任务不重复累加共享数量或尝试次数。数据范围与权限由服务端核验,不暴露来源密钥、内部数据库 ID 或原始订单载荷。
## 状态刷新与查询成本
页面可见且有本仓活动、来源活动、等待来源或待执行任务时,沿用每 10 秒刷新运行元数据;没有活动时每 60 秒刷新。来源仍在推进时,不因本仓执行次数为零降为闲置。切页或浏览器隐藏停止,恢复可见立即读取。
只保留一个轮询调度器:概览和所关注任务读取有界摘要;任务详情展开时复用同一任务数据,历史尝试分页按需获取,不为每一行各开请求,也不每 10 秒反复拉不变的历史页。仓库切换、任务切换、旧尝试迟到响应均进行取消/身份校验,不覆盖新选择。
轮询失败保留最后成功读到的数量和时间,提示“状态更新失败”,不把运行状态改成失败。无新推进且心跳正常显示“执行中,最近一次推进在……”,是否超时或失联由服务端判定。页面刷新成功不更新任务推进时间;只有下一次服务端健康与保护状态确认后,才撤销冷却/暂停提示。
运行查询只读 scope、task、run 与有界投影,不扫描订单、商品明细、统计全表或完整 manifest,不调用领星。阶段 ETA 也不增加外部请求。已有运行元数据 P95 ≤500 ms 的目标继续适用;后续与候选构建混合负载验证按性能方案安排,本轮不新增真实采集或压测。
## 逐操作设计与验收
视觉依据是本轮首页与任务详情两张用户截图及用户已确认的配套交互示意;现有承载以 [模块操作矩阵](../../apps/admin-web/src/modules/self-operated/operation-matrix.md)为准。下表为已确认的改版设计,由开发者实施时更新该矩阵;本轮不把设计图写成已实现/已验收。
| 操作 | 承载与关键验收 |
| --- | --- |
| 打开采集页 | 现有独立页面;首屏读到活动/等待对象、当前计数、最近推进和结果可用性 |
| 输入任务号 | 现有查询栏;可直接定位,不依赖历史首屏;当前关注区保留完整任务号和仓库 |
| 切换仓库/关注任务 | 原页更新;旧响应不串仓、不替换手动选择;共享数量不重复合计 |
| 查看任务详情 | 原 1200px AppDialog;首屏为数量摘要、阶段图、阶段预计时间和结果提示;全屏/关闭保留 |
| 查看历史/诊断 | 当前详情内折叠;空历史无表格和分页;失败原因在首层有短摘要 |
| 查看配置 | 复用原只读 AppDialog,不把查看变成修改配置 |
| 恢复任务 | 原详情内受权限与资格控制的确认流程;无资格不铺表单,不能绕过账号保护 |
| 跳转销量/库存 | 复用已有页面与仓库上下文;目标展示已发布版本,不把运行计数当销量 |
### 必测状态
1. **本次截图场景:** 本仓未启动,已确认关联来源正处理 339 / 2,787 单。首页和详情均明确来源在工作,本仓等待;两个任务号、尝试次数和计数范围不混用。
2. **关联缺失:** 账号有活动但无法证明属于该任务。明确待确认,不把无关进度贴过来;详情与概览采用同一关联语义。
3. **计数边界:** 总量未知、零单、分母变化、分页轮次变化、对象复用、尝试重开。没有虚假百分比、剩余负数、重复完成数或从阶段序号算整体比例。
4. **预计时间:** 样本未齐不估算,稳定采样可估算;窗口内外复用都不抬高速度;最后推进后的正常停顿计入窗口;阶段/尝试变化重置,旧估算不得配新数量,冷却和陈旧数据暂停估算,阶段 100% 不等于任务剩余 0。高频推进且历史阶段摘要接近 8 KiB 时,样本仍有界、可降级,采集提交不受 ETA 影响。
5. **更新故障:** HTTP 失败、旧响应迟到、心跳过期、心跳正常但无推进。最后观测值保留,任务不被浏览器误判失败;来源活动下保持活动轮询。
6. **发布与覆盖:** 来源完成但本仓计算中、本次失败但旧版可用、首次无版本、单日已发布但 10/30 日窗口不足、库存独立发布。所有结论均与实际覆盖一致。
7. **权限与布局:** 只读账号可看详情但不可恢复;无资格任务无恢复表单;1920×1080/100% 截图核对首页、普通详情、全屏详情、长任务号和错误状态,关键内容不靠横向滚动或极小字号查看。
前端状态用受控样本和组件验证,后端关联、计数、ETA 和权限用合同测试;不为验收设计扩大真实领星采集。源码检查、接口验证和人工截图分别交付,缺少人工截图时保留“待人工视觉确认”。
## 交给开发总控的建议顺序
| 顺序 | 工作包 | 交付判断 |
| --- | --- | --- |
| 1 | 统一活动任务、等待依赖与计数范围 | 服务端能解释这条任务在等谁;概览和详情一致;未确认关联如实显示 |
| 2 | 首页与现有详情改版 | 先用已有可靠计数呈现阶段图、大数字和结果状态,收起历史及无效操作;不等待复杂总 ETA 才改善可读性 |
| 3 | 阶段速度与预计时间 | 补有界采样和服务端估算合同;所有不可估算状态有具体解释,页面显示约数 |
| 4 | 联合验收 | 跑上述状态矩阵、元数据查询检查和人工截图,核对两仓/出库/库存;已通过项目不无故重复 |
用户已授权开发总控将本设计纳入开发安排,由总控协调现有模块写入者、共享接口与执行顺序;方案维护对话不改业务代码,不另建监控服务、任务表、调度系统或用户可见对话。代码、部署和正式验收进度继续只维护在工程主契约;本次设计交接不扩大环境操作授权。
页面阶段名称 MERGE 显示“更新本仓出库数据”:将已校验的来源出库单按所属仓库写入或更新本地出库数据,再计算销量;不表示库存合并。库存流程独立为获取产品库存、完整性校验、统计计算、结果发布。
+184
View File
@@ -0,0 +1,184 @@
# 自营经营总览图表设计
新增 Admin「海外仓 → 经营总览」,用图表回答本仓近期出库是否变化、库存大约需要多久消化、哪些 SKU 出库多、哪些库存值得关注。页面以 SKU 为中心,所属货主只作识别;保持同仓同名 SKU 跨货主分开,不恢复已取消的货主独立筛选或经营面板。
本文件是经营总览页面、聚合接口、下钻和验收的维护入口;原始事实、同步、可售天数、观察资格、版本与权限沿用[一期方案](领星一件代发数据统计一期方案.md)。本次范围为设计与开发交接,不表示页面已经实现、上线或通过视觉验收。采集和环境操作继续按当前正式契约及用户授权执行,图表查询不调用领星。
## 菜单与页面布局
新增路由 `/self-operated/overview`,模块页建议为 `apps/admin-web/src/modules/self-operated/pages/OverviewView.vue`。菜单顺序为经营总览、销量分析、库存分析、数据采集;沿用 `platform:self-operated-analytics:list`,总控统一集成路由、导航及 IAM。保留原三个页面的查询与作业入口,不更改登录后的全局首页。
总览只选一个仓库,不合并两仓库存、规则或可售天数;不增加来源账号、货主或 SKU 输入框。仓库首次为空时提示选择,返回页面可恢复最近选择;无有效仓库不查询经营接口。来源账号由已有受控配置确定,不在业务页面显示技术键。
在 `1920×1080`、100% 缩放下采用以下设计布局,正常纵向滚动,不为挤进一屏压缩图形和字体:
```text
经营总览 查看销量 查看库存 数据采集
仓库 [选择] 统计时间范围 [最近3天/最近7天/最近15天/最近30天/自定义] 查询 刷新
销量覆盖截至…… 库存采集于…… 有新数据可刷新 / 部分资料提示
──────────────────────────────────────────────────────────────────────
区间出库量 | 所选时段日均出库 | 实物库存 | 正品可售 | 有库存SKU | 无出库SKU
──────────────────────────────────────────────────────────────────────
出库趋势(日折线,约 2/3 宽) 库存消化天数分布(横向条形,约 1/3 宽)
所选日期范围;真实每日点 所选日期范围;分类数量与待核验范围
──────────────────────────────────────────────────────────────────────
所选时段热销Top10 预计消化时间最长Top10 所选时段无出库库存Top10
按出库件数的横向条形 按可售天数的横向条形 按实物件数的横向条形
```
经营总览时间筛选默认近15天(截至昨日),提供最近3天、最近7天、最近15天、最近30天及最多366天的自定义范围,移除今日;快捷范围均截至北京时间昨日。最近N天为昨日往前完整N天;自定义最晚为昨日,起止日期均包含在统计内。前端将快捷范围转换为明确CUSTOM起止日期调用现有接口,复用查询上下文时以其anchorDate固定边界,整体刷新按当前北京时间重新计算;查看销量与其他下钻统一使用响应中的实际日期。该控件同时影响趋势、区间出库与日均 KPI、库存分布和三个榜单;热销按所选日期内已采集有效出库量排序,未采齐显示部分覆盖。日均与库存评估以同一所选区间的自然日数为分母,包含今日或缺失日期时不以部分销量推算。库存数量仍来自当前固定库存版本,不代表所选日期的历史库存。
KPI 采用紧凑的一行指标带;图表是主要内容,不再以整页描述表承载。复用 Admin 密度令牌,图表不套详情字段网格或普通表格行高。图表行建议趋势约 280~320px 高;榜单给 10 条保留可读高度,不强制全部首屏可见。长 SKU 可换行或省略并提供可聚焦的完整文字;名称与货主为辅助文本,不以内部 ID 回退。
## 指标带
数值来自服务端,保留版本、单位、覆盖和未知原因。这里的件数均为出库或库存数量,不是订单数、成交收入或净销售额。
| 指标 | 展示口径 |
| --- | --- |
| 区间出库量 | 与当前全仓趋势的日点合计守恒;全日均完整才显示正式总量,否则标为“区间已采集出库量”,全无可靠值为“—” |
| 所选时段日均出库 | 本仓所选区间实际出库总量÷区间自然日数;完整仓级覆盖即可计算,不因某个 SKU 库存观察不足抹去有效出库。缺日或含未完整今日则为空 |
| 实物库存 | 当前固定库存版各货主/SKU/品质的有效实物量;冻结、次品已经包含在实物中,不重复相加;在途不加入 |
| 正品可售 | 只汇总正品有效可用数量,不再减冻结、不加在途或次品 |
| 有库存 SKU | 全品质实物量已核验大于零的货主+SKU 去重数;品质行不是独立 SKU;存在库存未知时标记“已确认 N,另 M 待核验” |
| 所选时段无出库 SKU | 有实物且满足完整所选区间零出库的 SKU 数;观察不足仅提示,库存或销量未知另外说明,不认定卖不掉 |
库存或风险总量存在依赖未知时,正式值为空,允许显示“已知小计”及未知 SKU 数;不把未知过滤后仍显示成全仓总数。单项完整性独立:库存失败不阻止完整销量图;销量不足不掩盖已核验库存。全仓可售天数、平均 SKU 可售天数、评分和“优级客户”不在指标带中。
## 五张图表
### 出库趋势
使用日折线图,横轴为北京时间业务日期,纵轴为件数,零基线;日期轴包含完整选择区间。后台按仓库及固定销量版直接汇总有效日事实,包含现在已无库存的出库商品,不从库存列表或 Top 榜单反推总量。仓级全日覆盖完整且无出库时可为零,不要求每个 SKU 均满足所选区间库存观察资格。
每个日点返回正式量、已采集量、完整性和覆盖原因。缺日断线,部分日用明确的点形/虚线及“未完整”文字;不平滑跨越缺口。今日只有一个日累计点,不画小时趋势;自定义长区间减少坐标标签密度但保留全部日点和提示。整段已采集合计等于可靠日点已采集量之和;所有日点未知时合计为空。
仓级趋势按固定已发布版本的覆盖证据判定历史日,采集滞后或待重算不将该版完整历史日统一降为未完整;待重算时明确提示展示已发布历史结果,未发布事实不混入。来源时区、数量单位、日期缺口及今日未结束的限制保留。当前库存评估仍受待重算保护;所选区间包含今日时页面直接说明完整自然日条件不满足,并提示可选择截至昨日的自定义时段,其他库存与销量可信条件仍须满足。
仓级零值与部分值单独判断:全天覆盖完整时,正式量=已采集量=有效日行合计,无行可为 0;只有部分已证明覆盖且无日行时,正式量为空、已采集量为 0、状态 PARTIAL;没有覆盖证明但存在已确认日行时仍保留日行合计为已采集量、状态 PARTIAL;没有覆盖证明且没有日行时,两值均为空、状态 UNKNOWN。连续水位外的已确认日行不能被丢弃,整个仓级趋势不套单 SKU 存在时间或库存观察门槛。
点击已知日点进入销量分析当日自定义范围;未知日不可伪造零数据下钻,改显示该日覆盖不足原因。鼠标提示和键盘聚焦均显示日期、件数、状态;不能仅依赖颜色解释未知。
### 库存消化天数分布
使用横向条形图,单位为 SKU 个数,显示“有实物库存或库存待核验 SKU 的分布”。候选取固定两版 profile 的货主+SKU 并集:明确有效且实物为零的 SKU 排除;有效正实物以及实物未知/过期的候选保留。整个库存版尚不可用时显示无库存资料,不将全部销售候选画成一个伪造的库存总量。
`bucketRuleVersion=COVERAGE_DISTRIBUTION_V1` 按以下先后顺序将每个候选只归入一个桶;上一步命中后不再落入后续桶。销量资格沿用主方案;仅在完整可信窗口及数量单位确认后,没有出库行可记零,观察不足不单独归入 UNKNOWN:
| 桶 | 判定 |
| --- | --- |
| `UNKNOWN` 库存或销量待核验 | 先检查本 SKU 实物或用于可售天数的正品可售数据异常/未知/过期;命中即归此桶。后续因销量窗口或数量质量不足无法计算时也归此桶,分别统计原因 |
| `NO_AVAILABLE` 无可售库存 | 库存有效、实物大于零且正品可售量明确为零;可包含冻结或次品,不宣称周转良好,不依赖销量资格 |
| `NO_OUTBOUND_IN_WINDOW` 所选时段无出库 | 有效正可售量、完整可信所选区间且出库为零;天数为空,不转成无限大 |
| `DAYS_0_30`、`DAYS_30_60`、`DAYS_60_90`、`DAYS_GT_90` | 正可售量、正日均且资格完整,按未舍入天数分别落 `(0,30]`、`(30,60]`、`(60,90]`、`(90,+∞)` |
在无可售库存判断之后、零出库或数值分桶之前检查销量完整性、可信状态和数量单位;不足回到 UNKNOWN。展示顺序为四个数值桶、无出库、无可售、待核验,不等于执行判定顺序。可售天数=当前正品可售量×所选区间自然日数÷区间完整出库量;SKU 的最早有效观察证据单独保留为提示,不阻断上述统计。30/60/90 仅为本版图形分组边界,不是收费、补货或优劣政策。
各桶 `skuCount` 之和必须等于 `candidateSkuCount`,并同时返回已排除的确定零实物 SKU 数。图表不展示“风险率”百分比;待核验量无法被藏进已评估分母。可在提示中显示桶内已知实物小计及未知件数范围,不把件数与 SKU 个数混用。
此分布为互斥展示分组,主方案 attention 是可并存的关注条件,两者不等价。例:全冻结且所选区间零出库 SKU 归 NO_AVAILABLE,但仍可出现在无出库库存榜。冻结、次品、可售、在途不能作为可相加的饼图组成部分。
### 三个 SKU 榜单
均为横向条形图,最多 10 个候选;三个榜单统一使用页面所选日期;无合格候选显示原因,不造空条或补足 10 个。每条展示 SKU、可用名称、所属货主及主指标,提示补充库存/日均/日期依据。同名 SKU 不跨货主合并;坐标从零开始,条长按真实数值,不截成相同最大长度。数量过大可用统一刻度单位,提示保留原值。
| 图表 | 资格与排序 | 下钻 |
| --- | --- | --- |
| 所选时段热销 Top 10 | 按所选日期已采集有效正出库量降序、单数降序、SKU/货主编码升序;部分覆盖也展示,明确标记未完整,不将未采集当零。库存缺失或售罄不阻止进入 | 条目打开同窗口 SKU 趋势;“查看 Top 100”进入销量分析相同 CUSTOM 日期范围 |
| 预计消化时间最长 Top 10 | 有效正可售、正日均、完整可信窗口;按未舍入可售天数降序,SKU/货主编码升序。零销量单列,不冒充无限天数;不等同原 slow-skus 低销量榜 | 条目打开 SKU 趋势;“查看全部”进入库存分析相同有限天数候选及天数降序 |
| 所选时段无出库库存 Top 10 | 主方案 attention=NO_OUTBOUND_IN_WINDOW:全品质有效正实物、完整可信窗口、出库零;包含全冻结/次品有实物者。按实物量降序,SKU/货主编码升序 | 条目打开 SKU 趋势;“查看全部”进入库存分析无出库关注及实物量降序 |
排名从全仓所有已授权货主的候选先算资格/排序后截取,不先截 SKU 清单或逐货主各取十个再汇总。库存或销量数据实际不足时返回待评估数量,观察不足本身不增加待评估数;榜单明确是“符合条件的 SKU”,不以没有合格候选推断库存健康。可售天数很长仍是按历史速度的估算,不标成真实库龄或一定卖不掉。
## 图表交互与视觉依据
本文件作为新增页面的设计依据,布局由上面的页面示意和本矩阵约束;实现前总控将对应记录并入模块现有 `operation-matrix.md`。既有页面承载以该矩阵的用户截图纠正为准,不读取或恢复更早的货主面板。
| 页面操作 | 承载与行为 | 设计验收 |
| --- | --- | --- |
| 仓库/统计范围查询 | 同页紧凑 QueryToolbar;查询先校验再更新,切仓清旧数据并取消旧请求 | 不增加独立货主控件,不在主区堆账号键、时区技术值、长规则 |
| 刷新 | 明确按钮整体更新版本与 queryAsOf;新数据提示不自行替换某张图 | 过期上下文显示刷新提示,不混合版本 |
| 柱/条与日点提示 | 图内提示,键盘可聚焦查看同等内容;未知日只展示缺口原因 | 不是新业务弹框,不仅靠颜色或悬浮识别数值 |
| SKU 条目趋势 | 沿用当前 1120px 居中 AppDialog,支持已有全屏/关闭;传该行 customerCode+sku 和上下文,三个榜单均使用所选范围 | 不改为列表下方详情、抽屉或新详情页;关闭取消请求 |
| 分桶或查看全部 | 导航至既有销量/库存正式页面并带准确筛选、版本和返回来源 | 目标页显示可清除的“来自经营总览”条件摘要,不重新引入货主选择器 |
| 查看采集状态 | 导航至所选仓的数据采集页 | 只查看当前状态,不触发采集/重试 |
保留屏幕阅读名称、键盘入口、焦点和足够对比度;趋势每日数值、SKU覆盖证据、库存分组说明、分布与排行榜按2026-10-13用户截图反馈统一使用居中弹框;分布与排行榜使用“查看完整明细”1040px居中弹框,提供完整名称、数值、证据及同资格的键盘下钻入口,长字段换行,正文滚动;悬浮提示只展示名称和数量并限制宽度,Top100/查看全部仍进入对应列表,不将全页默认变回表格。主图使用折线与条形,不使用 3D、雷达、仪表盘、双轴、装饰动画或无依据的“健康分”。按 2026-10-13 用户确认,自营业务图表统一使用 ECharts+vue-echarts,通过模块内 `AnalyticsChart.vue` 按需注册并使用 Canvas 渲染;坐标轴、提示框、缩放、条形及环形进度用配置维护,删除手写 SVG/CSS 绘图。日趋势与 SKU 趋势共用有效数据连线配置,未完整日用虚线,未知或缺失日期仍断线。
功能/合同评审和人工视觉验收分别记录。本设计不代替真实页面的人工 `1920×1080`、100% 截图验收,未提供截图时保留待人工确认,不声称视觉通过。
## 服务端聚合接口
新增 `GET /api/platform/v1/last-leg/self-operated-analytics/dashboard`,前端使用独立 `analyticsApi.dashboard`。现有前端 `overview` 实际调用 `sync-overview`,是采集状态接口,不能用它冒充经营聚合或改掉原语义。
入参要求 `sourceAccount,warehouseCode`,趋势参数复用 `rangePreset` 和 CUSTOM 的 `startDate,endDate`;不接受 customerCode、SKU、跨仓合并或任意 Top N。首次查询固定主方案中的两版、范围摘要、queryAsOf 及到期时间;后续切换统计范围复用上下文,显式刷新/切仓重新建立。榜单数量服务端固定 10,消化天数分组固定 V1。
在一次短只读一致快照中校验范围/版本并读取所需数据;整个响应共同使用同一上下文,不由前端并发获取多个“最新版本”后拼屏。某一数据族不可用时仅返回该族不可用,不妨碍另一族可用图形;鉴权失败、参数错误、版本无效或 SQL 失败是请求错误,不吞掉后转零或正常空图。
| 响应块 | 主要字段与要求 |
| --- | --- |
| `context` | 主方案现有完整版本上下文、统一所选范围 rangeStartDate/rangeEndDateExclusive、salesCoveredFrom/Until、库存观测起止、inventoryFreshUntil、queryExpiresAt,另含 inventoryDrilldownExpiresAt(有效库存时取前两截止时间的较早值,否则不可用);技术字段用于程序,不放主页面占位 |
| `kpis` | 六项指标各有 value/knownSubtotal、单位、dataStatus、unknownSkuCount、reasonCodes;区间出库另有正式量/已采集量,日均 averageDailyOutboundQuantity 与无出库数 noOutboundSkuCount 使用同一所选区间 |
| `salesTrend` | 每日 points 及区间汇总;每点 businessDate、outboundQuantity、observedQuantity、dataStatus、reasonCodes,最多 366 点,日轴不省略缺日 |
| `coverageDistribution` | bucketRuleVersion、candidateSkuCount、excludedZeroPhysicalSkuCount、各 bucketCode/skuCount、可选已知实物小计/未知数、dataStatus/reasonCodes;分组未知原因有摘要 |
| `hotSkus`/`longCoverageSkus`/`noOutboundSkus` | 各自实际窗口(windowStartDate/windowEndDateExclusive/calculationWindowDays)、eligibleCount、unassessableCount、items(最多 10)、dataStatus/reasonCodes;每项包含实际 customerCode+sku、名称、主指标及其单位/必要辅助值,窗口出库字段为windowOutboundQuantity。热销部分覆盖返回PARTIAL与SALES_WINDOW_INCOMPLETE,不返回该部分量推算的日均和消化天数。单点弹框复用原 daily API,不因图形新增另一份销量公式 |
计数无法确定时用空值和原因,不能把未计算的 eligibleCount/unassessableCount 默认为零。冻结、次品、在途可作为必要辅助数量,不新增会被误加总的库存占比饼图。所有经营数量的已知小计/完整总量遵守主方案;日均销售和本页库存分类均不以 SKU 观察期作为阻断条件,观察状态单独提示。
### 精确下钻合同
现有销量/库存页仅解析并传递 warehouseCode、sku,不能只拼一个新 URL 就宣称下钻已完成。此次必须扩展目标页的参数解析、初始化、取消请求、校验与返回上下文;来源条件只作为查询条件,权限仍由服务端核验。
- 通用路由条件:`warehouseCode`、可选精确 `sku,customerCode`(仅行身份,不显示独立货主选择器)、原完整版本上下文、`from=overview`。使用固定本地路由,不接受任意 return URL;编码/日期/枚举非法显式提示,不能静默忽略成全仓查询。
- 趋势日点:销量页 `analysis=SKU`、`rangePreset=CUSTOM` 且 startDate=endDate=该日。热销 Top 100:`analysis=HOT,rangePreset=CUSTOM,startDate,endDate`,日期来自榜单窗口(endDate 为 exclusive 截止前一日),不再携带 windowDays。这两个路由枚举是新增初始化合同,开发映射到现有页面状态,不能原样当作新的外部 API 字段。dashboard 的 eligibleCount 是当前已采集有效正出库候选数,热销明细沿用原 Top 100 上限,故 total=min(eligibleCount,100),前 10 名及主值必须一致;不扩展成无限热销榜。
- 无出库全部:库存页 `attention=NO_OUTBOUND_IN_WINDOW,sortBy=PHYSICAL_DESC`。最长可售全部:`/inventory-coverage` 和路由均新增 `coverageSelection=FINITE_POSITIVE`,在服务端 SQL 分页前过滤为正式有限正可售天数候选,`sortBy=COVERAGE_DAYS_DESC`;不能仅在浏览器当前页过滤,也不能把零库存、未知天数放进候选冒充同一榜单。该字段属于本地报表接口,不传领星。
- 分布条形:库存页新增 `coverageBucket` 与 `bucketRuleVersion=COVERAGE_DISTRIBUTION_V1`。服务端 `/inventory-coverage` 同步接收并按上述唯一分组谓词过滤;不能把区间点击近似替换成 attention 或一个“大于”阈值。coverageBucket 与 coverageSelection、非 ALL attention 互斥,冲突拒绝;未带 bucket 时不接收单独 ruleVersion。FINITE_POSITIVE 与非 ALL attention 也互斥。
- 日点、整榜、分桶或具体 SKU 下钻均携带同一版本上下文;条件 chip 可清除,清除后恢复目标页常规范围,但不更换仍有效的上下文。返回总览恢复原仓库、趋势范围、上下文及滚动位置;到期或版本不可用时提示整体刷新,不能悄悄换新后声称与原图一致。
库存严格下钻从原图 context 提取起止日期,向 `/inventory-coverage` 携带 `drilldownFrom=DASHBOARD,rangePreset=CUSTOM,startDate,endDate`(endDate 含当日),不携带 salesWindowDays/salesWindowEndDate。普通库存明细仍使用独立的 10/30 日选择;同一无出库关注与区间出库排序按实际窗口计算。严格下钻标志用于声明与原图一致的读取要求,不授予额外权限;from=overview 的目标页必须映射此参数。服务端从原上下文及库存 run 的真实时效重新计算 inventoryDrilldownExpiresAt,不信任客户端传入的截止时间。库存已超过有效期或上下文到期时返回明确的“原图库存已过期,请刷新总览”错误,不能按过期后的 UNKNOWN 重新分桶再冒充原图结果;前端同时禁用原库存图的分桶/榜单列表下钻。此时趋势与热销的有效读取仍可继续,普通库存页的历史/过期展示保持原规则;重新加载的过期总览仅提供普通库存诊断入口,不提供严格分桶下钻。单条 SKU 的出库趋势不受库存过期阻断。
## 数据模型与查询性能
本页不新增采集任务、调度、周月汇总、缓存平台或库龄表。2026-10-13 用户确认允许新增仓库每日汇总表 `ll_selfop_warehouse_daily_sales`,按销量版本、来源账号、仓库、业务日保存有效已采集量、异常日行数与源日行数,数量沿用六位小数。每批 SKU 日行与对应仓日汇总在同一事务写入并推进构建检查点;发布前核对汇总覆盖的源行数,成功后同事务设置销量版本 `warehouse_daily_ready`。空销量版也必须完成该验证,不能以汇总表无记录推断为零。缺少就绪证据的版本明确拒绝总览读取,重新构建发布,不回退到旧查询或补写旧版本。
趋势和仓库销量合计读取已发布仓日汇总,日期完整性、部分采集与异常口径仍由原版本覆盖证据判定;仓日汇总不证明完整自然日。SKU 明细、库存与榜单继续复用已发布 daily、snapshot、profile、run;SQL 按版本、仓库、日期限缩,库存先按货主+SKU/品质聚合,再与销量连接,禁止原始订单 Join 或逐 SKU/逐货主 N+1。版本保留与受保护版本规则同时覆盖仓日汇总;不引入额外清理调度。
趋势在数据库按业务日期聚合;三个榜单分别在完整候选上计算并排序 LIMIT 10;分桶在 SQL 中 CASE 聚合,不能从第一页库存或 Top 100 拼出全仓分布。前端一次 dashboard 响应只接收最多 366 个日点、7 个桶和 30 条榜单记录及固定 KPI,不请求全部库存,不逐货主调用 owner-overview。下钻的库存计数及谓词必须与 dashboard 共享,避免边界漂移。
沿用主方案的代表性合成数据档位:单仓 1 万货主+SKU、多个历史统计版、有后台构建及 10 个并发只读用户。新增目标为 dashboard HTTP P95≤1.5s;报告 P50/P95/P99、SQL 数、扫描行及响应大小,查询数量须为固定少量、不得随 SKU/货主数线性增长。目标未实测,不以 SVG 绘图流畅代替后端验收。首次与预热分别记录,任何测试不对领星发起压力请求。
首次加载用结构占位;无仓、无业务版本、可靠全零、观察不足、过期和失败分别呈现。主动切仓立即清旧仓图并隔离迟到响应;相同条件刷新失败可以保留旧图,但明确“刷新失败,展示上次查询”,不伪装新成功。到达库存有效期或上下文到期后,相应指标标为历史/待刷新,不继续作为当前可信结论;不靠后台轮询替换单张图。点击刷新只读本地接口,不意味着立即同步领星。
## 离线验收与评审
下表均为合成数据设计,不作为真实经营结果;开发需同步 OpenAPI、权限、目标页路由解析和直接测试,API 门禁沿后端根指引执行。原模块已有功能与人工截图结论保留,不因新增总览回退 SKU 中心布局。
| 用例 | 必须得到的结果 |
| --- | --- |
| 近15天截至昨日,切换最近3/7/15/30天/CUSTOM | 无今日选项,自定义禁选今日及未来;趋势、KPI、分布和榜单使用同一实际区间,缺日保留待评估;下钻与返回日期一致 |
| 日量 2、未知、5,今日部分 1 | 可靠值合计 8 标已采集,正式总量为空;缺日断线,今日部分;全未知合计为空,不为 0 |
| 同仓 SKU X 属货主 A 出库 2、B 出库 5,均有效 | 全仓对应日为 7;榜单与点击身份保留两条,下钻分别为 2/5 |
| 库存缺失但所选区间完整销量数据存在 | 日均、趋势、热销可用,依赖库存的图形显示未就绪,不让库存失败清空销售 |
| A 正可售 3000、30 日出库 300;B 正可售 30、出库 30 | A 可售 300、B 30,分别归 >90 和 (0,30],最长榜 A 在前;不按低销量将 B 当更积压 |
| 候选 5 个:有效正可售零出库、全冻结且零出库、库存未知、有效天数 30、有效天数 30.04;再有明确零实物 1 个 | 分别落无出库/无可售/待核验/(0,30]/(30,60];桶合计 5、排除数 1;冻结 SKU 仍能进入独立无出库库存榜 |
| 正品实物 120 含冻结 20,可售 100;次品实物 8,在途 30 | 实物 128、可售 100,不相加为 278;图中不出现这几个重叠量的库存组成饼图 |
| 整体存在未知库存或销量缺口;热销和无出库候选不足 10 个 | 标已知小计和待评估,不补齐榜单、不宣称整体无风险;完全无可靠资料不显示健康零值 |
| 90、90.04 天显示均可能接近 90;零出库的天数为空 | 比较与分桶按未舍入值,分别≤90/>90;零出库不进最长有限天数榜、不放成无限值 |
| 每个分桶点击、榜单跳转、单条趋势,随后返回;另测 200 个热销候选 | 库存分桶/最长/无出库的 total 等于对应完整候选数;热销 total=min(eligibleCount,100),200 个候选时为 100,前 10 一致。身份/版本不变,复用 1120px 趋势弹框,返回保留范围及滚动位置 |
| 图表加载途中切仓、后台发布新版、跨午夜或上下文过期 | 旧仓响应不覆盖新仓;不单图切版或自动滚动今天;到期明确刷新,库存过期不继续显示当前有效 |
| 同一版本和 30 分钟上下文仍有效,但库存先到 freshUntil,再点击原分桶/库存榜单 | 前端阻止旧图严格下钻,服务端同样拒绝,不返回改变分类的结果冒充一致;要求刷新总览,出库趋势/热销仍按其独立资格读取 |
| dashboard 或路由参数缺仓、非法桶、互斥参数冲突、客户身份调用 | 明确拒绝,不能悄悄全仓查询;平台鉴权和来源范围校验不因汇总而弱化 |
设计评审收口项:SKU 中心与现有页面一致;总览及下钻统一所选区间;分布互斥且守恒;零出库与有限天数分开;全品质实物不重叠相加;未知不隐藏;下钻需要真实参数接线和共用谓词;新增聚合接口与运行概览分开。评审不覆盖生产吞吐、真实数据对账或人工视觉验收。
本轮已分别完成数据口径、页面/接口两项独立评审,并复核修正后的合同:补齐仓级部分日零值规则、库存时效先于查询上下文到期的严格下钻门禁,以及热销完整候选数与原 Top 100 上限的区别。设计范围内无剩余阻塞,可交开发总控安排;不把该结论作为代码、性能或视觉验收通过。
后续可在真实库龄、空间占用和内部经营规则核验后增加库龄分布及成本分析,不在本页放无数据的库龄饼图、平均周转率、货主评分或费用预测。开发总控按本设计安排前后端工作,计划和测试状态由其当前对话及正式工程契约维护。
图表明细与说明弹框通过 append-to-body 挂到页面根部,避免图表卡片动画/transform限制遮罩与弹框;更换数据关闭旧弹框,日期下钻先关闭明细,长表只滚动弹框正文。库存分组说明宽760px,每日数值/覆盖证据和排行明细宽1040px,可全屏。
热销Top10完整明细按用户最新截图去重:使用1280px居中弹框,按排名、SKU、商品名称、货主、所选时段出库量、实物库存、可售库存、窗口日均、预计可售天数分列;不再拼接重复说明段落,窗口与覆盖状态只在表格上方展示。商品名称与SKU完全相同时显示—,以“SKU+空格”起始时仅去掉该重复前缀;货主+SKU身份及点击下钻保持不变,未知指标不补零。
三张Top10卡片的日常展示只保留标题、图表与必要的一行异常提示(未采齐、待评估数量或待刷新);日期、资格数量、完整性详情和统计口径收进右上角“说明”,正常状态不重复显示“完整/待评估0”。图表顶部保持对齐,预计消化天数图上与悬浮数字最多两位小数,明细保留原始精度。
出库趋势与库存消化天数分布沿用Top10的简洁展示:日期、线型图例、候选/排除数量、完整性及分组口径均在右上角“说明”查看,独立“明细”入口保留每日数据或分桶数值。图表主体保留坐标轴、单位及必要空态。
+408
View File
@@ -0,0 +1,408 @@
# 领星 WMS 一件代发与产品库存接口联调手册
本手册是后续开发的外部 API 入口,说明请求方式、参数、字段映射、实测差异和验收方法。业务同步、表结构、统计口径和开发顺序以[一期方案](领星一件代发数据统计一期方案.md)为准。本期只使用 **WMS 一件代发出库单和 SKU 产品库存**,不接整箱中转出库单或整箱库存,不做箱数到件数的推算。
接口体系为领星 WMS 管理后台的“自研系统/服务商内部系统对接”,官方文档站为 OMP。不要换成 OMS 货主端或 WMS 智能设备的路径和签名。
**当前执行边界与数量来源**以[一期方案](领星一件代发数据统计一期方案.md)的持续 BUSINESS 自动采集及“出库件数”规则为准。2026-10-14 用户确认列表优先、仅缺商品行/SKU/数量的具体订单补详情;本手册下文数量对照是历史验证依据,不再是采用列表数量的前置门禁,也不表示已经证明列表量与实际量始终相等。历史 TEST 小样本次数及时间限制只对应当次 VALIDATION,不覆盖已授权持续 BUSINESS。实际部署、采集及验收状态只看[测试环境主契约](../测试环境单机部署与配置契约.md)。
**时间口径已确认:2026-10-12 用户说明领星返回时间已转换为北京时间。** 本期两个仓库均按 `Asia/Shanghai` 解析出库时间和统计日期,直接使用有效返回日期;查询 `startTime/endTime` 同样按北京时间传参。不要再按洛杉矶、纽约或仓库资料中的 `timeZone` 二次转换。08:00/20:00 出库同步、建议的每日 08:00 库存同步及五种图表自然周期均采用北京时间;分仓任务、覆盖与时效继续独立。
原始时间字符串保持不变,业务日期直接取其日期;内部 UTC 字段按既有存储规范标准化,不使用 UTC 日期替代业务日。认证包络的 Unix 秒级 `timestamp` 仍按当前时间点生成,不能因业务时间为北京时间而手动加减 8 小时。完整实现与验收见一期方案的[同步时间和统计日期](领星一件代发数据统计一期方案.md#同步时间和统计日期)。
## 接口和当前实现
| 用途 | 方法与路径 | 返回主体 | 本地 Java 当前能力 |
| --- | --- | --- | --- |
| 发现正常仓库 | `POST /openapi/v2/warehouse/page` | `data.records[]` | 已有内部仓库目录接口源码;外部接口已直接 HTTP 联调 |
| 一件代发已出库单目录 | `POST /openapi/v2/order/delivery/page` | `data.records[]` | 已有只读内部分页摘要接口 |
| 一件代发单的实际 SKU 明细 | `POST /openapi/v2/order/delivery/detail` | `data` | 已有内部详情接口及 SKU 数量 DTO 源码;外部接口已直接 HTTP 联调 |
| 产品库存 | `POST /openapi/v2/stock/stockSku/page` | `data.records[]` | 已有内部产品库存接口源码;外部接口已直接 HTTP 联调 |
当前 Java 已有五个内部 POST 入口,共用 `/internal/integrations/lingxing/wms` 前缀并要求内部服务令牌:`/warehouses/query`、`/outbound-orders/query`、`/outbound-orders/locate`、`/outbound-orders/detail`、`/product-inventory/query`。出库发现与按单定位接口同时传递 `productList[].productSku/productName/qty`;列表字段完整时直接用于统计,缺项时才补该单详情,数量为零不属于缺项。接口职责和字段见[一期方案的接口约定](领星一件代发数据统计一期方案.md#平台查询接口和权限建议)。外部直接 HTTP 联调或源码核对不代表 Java 入口已运行验收。[本地启动说明](../../baiyue-firstleg/integration-service/README.md)
## 库存流水有界诊断(2026-10-15)
官方 OMP [库存流水分页接口](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-stock-stockcellbook-page-1.md) 为 `POST /openapi/v2/stock/stockCellBook/page`,支持 `whCode`、`customerCode`、精确 SKU `barcodeAccurate`、`startTime/endTime`、`sortName=createTime`、`sortOrder=asc`。返回库位、批次、业务类型、`bookQty`、字符串 `bookChangQty`、`closeQty` 和时间。文档品质为1正品/2次品、ID为数字,但2026-10-15授权本地样本实际为字符串ID、品质0正品/1次品;其他品质仍未确认,不照搬文档枚举。另有批次流水接口 `/openapi/v2/stock/batch/flow/page`,本轮不混采两套流水。
实测字段合同:分页为 `records,total,size,current,pages`;流水ID保持字符串,禁止经JS Number再转回而丢精度。样本中 `bookQty` 是有符号增减量,与字符串 `bookChangQty` 一致,不是期初库存;`closeQty` 是同库位/内部批次/品质链的结存,不是SKU全仓总库存。三锚点及逐日销量可在原单SKU样本范围内对齐;本轮扩大字段核验并不表示新增SKU已完成独立锚点对账。原始响应仅存私有诊断目录,业务设计见[库存周转历史还原方案](库存周转视图设计.md#历史库存还原与周转率修正方案2026-10-15实施合同)。
### 本地扩展核验后的接口约束
| 核验项 | 已观察到的合同 | 实现边界 |
| --- | --- | --- |
| 时间端点 | 同一已知流水放在startTime、endTime均返回;严格前后相邻秒窗口均不返回 | 来源窗口两端含,平台按ID去重并按北京时间半开区间归属。午夜归属需离线测试,不宣称已取得恰在午夜的真实事件。 |
| 仓范围与分页 | 不传货主/SKU可返回多个货主;一个完整小时间片10条,size100/20/6两页的ID与载荷一致;原单SKU32条以size20两页重读也一致 | 支持按仓时间片计划,不等于已核验两仓全量或永久稳定排序。每次正式片仍做覆盖、数量、身份、重复和漂移校验。 |
| 合法空流水页 | 实测返回 `current=1,size=10,total=0,pages=0,records=[]`,请求页大小可能为20或100 | 只有首个空页且全部条件吻合才归一化,保留sourceSize;非空页、页码错误、pages非0和其他size不放宽。现有库存接口策略不随流水修复一起改变。 |
| 数量/品质 | 234条去重流水中,bookQty均与bookChangQty一致;出现DO/PA/IMO/IAT/RI,品质0正品/1次品 | 不再按业务类型二次取负;不把未见BO/OBIAT自动映射为其他类型。 |
| 调整与退件 | 完整窗口IAT35条:7正、28负;RI12条均为正 | 符号来自实际delta;退件和调整不自动成为销量分子。单独的链段仍需完整窗口及锚点校验。 |
| 移库与品质转换 | 10组同品质移出/移入净额0;另一个完整单12条、6个SKU,正品合计−17、次品+17,总量0,业务类型同为IMO | 不能按IMO忽略全部行,也不能按单号去重掉一端。分品质记账后合计总实物;一个品质过滤结果不能用于全品质历史还原。 |
| 同链同秒 | 观察到同一链同一秒两笔−1,结存分别38、37 | 此样本可由数量关系区分顺序,不证明ID或接口同秒排序有永久顺序合同;存在多种可行链序时保持未知。 |
| 零库存 | 一条定向产品库存,isHideInventory=0明确返回stkQty=0,改为1则空页 | 明确零行可作为零锚点;缺行仍不能推定0,不能由该样本证明所有历史售空SKU都会返回。 |
源数据保留期限、历史更正/删除通知、跨页一致性保证和不可见历史主体无法由有限只读请求证明;这些仍需供应商契约或独立业务对账。当前实现准入为“已观察字段可开发,逐SKU/日期证据合格才发布”,不是“整个仓库历史完整已证明”。请求次数、实际时段、账号状态及本地测试结果统一见[TEST主契约](../测试环境单机部署与配置契约.md#自营库存周转-test-发布与验收2026-10-15)。
最小诊断源码入口为平台 `POST /api/platform/v1/last-leg/self-operated-analytics/inventory-flow-probe` → Integration `/inventory-flow/query`。只允许 TEST BUSINESS、配置仓库、平台非代登录且有 sync 权限;一次限定一个货主/SKU、最多31日、第一页最多1000行、最多一次供应商请求。同键成功回读结果,异参拒绝,失败/未知不自动重试;完整分页只证明这次返回完整,不证明供应商历史无缺失。请求共用原账号 lease/fence、短 permit、间隔、冷却和计数,独立任务类型 `INVENTORY_FLOW_PROBE` 不进入自动调度,SAMPLE_DONE/DEAD 只作为诊断终态。源11008“无接口权限”仅终止这个可选接口,其他凭据错误、429及未知结果仍按原账号保护处理。
诊断记录保存在现有任务/尝试中,不新建业务表,不写库存日代表,不发布经营结果。实施顺序:验证受控入口及失败隔离 → 经授权部署诊断版本 → 单SKU真实流水与已保存观测时点对账 → 决定是否具备全量历史重建条件。当前 key 权限、历史完整性和重建可行性不能由离线测试或文档推定;部署事实仍只维护在测试环境主契约。
## 认证和请求格式
历史库存自动采集使用独立内部入口 `POST /internal/integrations/lingxing/wms/inventory-flow-page/query`,保持服务令牌及单次出口许可验证,不暴露为平台可任意调用的接口。冻结仓库、北京时间起止(最长一天)、排序和每页1000条;`current`必须匹配任务持久化下一页。Integration 的 Long 类型 `total` 按统一Jackson合同输出十进制字符串,Lastleg 严格解析整数并验证页数及累计条数。来源ID、货主、SKU和仓库按字符串保存;只持久化数量还原所需白名单。该内部路径与仅单SKU的诊断入口并存,各自有独立权限/任务边界;真实部署与覆盖状态见TEST主契约。
基础地址为 `https://api.xlwms.com`;所有请求使用 HTTPS POST,`Content-Type: application/json; charset=UTF-8`,响应按 JSON 解析。认证参数放在请求体中,不需要 OAuth 获取 Token 的前置调用。
| 包络字段 | 类型 | 约束 |
| --- | --- | --- |
| `appKey` | string | 自研系统的 App Key,官方长度 32 |
| `timestamp` | string | 当前 Unix 秒时间戳,官方为 10 位数字;不是毫秒 |
| `data` | object | 对应接口的业务参数 |
| `sign` | string | HMAC-SHA256 小写十六进制,64 位 |
领星凭据按用户在开发总控对话中的确认配置为 `LINGXING_OMS_APP_KEY` 和 `LINGXING_OMS_APP_SECRET`,应用、示例及 Compose 已采用这两个名称;产品仍为 WMS OMP,真实出口开关仍为 `LINGXING_WMS_ENABLED`。真实值仅通过私有环境配置/Jenkins 凭据注入,不复制到文档。本地私有配置由 Git 忽略;Spring 不会自动加载 `.env.local`,运行前按上述 README 核对变量名和加载方式,不输出凭据值。内部服务令牌是本平台自身的调用保护,与领星凭据分开。
```json
{
"appKey": "<运行时注入>",
"data": {"current": 1, "size": 2, "whCode": "WH-DEMO", "isHideInventory": 0},
"timestamp": "<当前秒时间戳>",
"sign": "<本次计算的签名>"
}
```
以上占位符不是可直接发送的凭据。先确定业务参数与路径,再为每次请求重新生成时间戳和签名,不能把分页接口的签名复用于详情或库存。[官方加签算法](https://apidoc-omp.xlwms.com/docs/%E5%BC%80%E5%8F%91%E9%AA%8C%E7%AD%BE%E5%B7%A5%E5%85%B7.md)的当前参数拼接为:
```text
待签名串 = appSecret + path
+ "appKey" + appKey
+ "data" + data的Map/List字符串表示
+ "timestamp" + timestamp
+ appSecret
sign = hexLower(HMAC_SHA256(key=appSecret, message=待签名串, UTF-8))
库存例子的 data 表示:{current=1, size=2, whCode=WH-DEMO, isHideInventory=0}
不是 JSON:{"current":1,"size":2,"whCode":"WH-DEMO","isHideInventory":0}
```
保留业务对象的插入顺序,使用同一数据对象参与签名和实际发送;对象以 `k=v`、逗号加空格连接,数组也按 Map/List 规则递归表示。`path` 包括 `/openapi/v2/...`,不包括域名和查询串。Java 已有 `LingxingWmsSigner`,后续优先复用它,避免新增第二份签名实现:
```java
Map<String, Object> data = new LinkedHashMap<>();
data.put("current", 1);
data.put("size", 2);
data.put("whCode", warehouseCode); // 来自已配置仓库,不能用文档占位值
data.put("isHideInventory", 0);
var signed = signer.sign(appKey, appSecret,
"/openapi/v2/stock/stockSku/page", data, Instant.now());
// POST signed.body();不可打印请求体、签名、密钥或原始响应。
```
客户端使用超时、HTTPS、禁止重定向及受控并发;认证错误不能盲目重试。现有本地适配器请求间隔为 1 秒,这只是保护配置,不表示领星承诺 1 QPS。正式初始化前确认账号配额和详情调用量,使用统一账号级限流。
## 一件代发出库分页
[官方 WMS 分页说明](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-page-1.md)明确对应管理端的一件代发出库单列表。
一期使用的 `data` 参数如下;首采固定起止时刻,后续翻页不能移动窗口:
| 参数 | 类型 | 本期值与说明 |
| --- | --- | --- |
| `current` | integer | 从 1 开始 |
| `size` | integer | 官方默认 10、最大 1000;联调先 1 |
| `timeType` | string | 固定 `outboundTime`;不用创建时间代替出库时间 |
| `startTime`、`endTime` | string | `yyyy-MM-dd HH:mm:ss`,按已确认的北京时间口径传入,与返回的出库时间保持一致。2026-10-12 已出库单样本观察到起点、终点均包含,见后文边界验证;不能外推为全部仓库/时间类型的保证 |
| `status` | integer | `100` 已出库;`99` 已取消。已知单的修订复查走详情,不只查状态 100 |
| `customerCodes` | string | 官方类型为字符串、描述为客户编码;不是已确认的数组,多货主拼接方式未验证。本期账号全集省略该参数;与库存单数 `customerCode` 名称不同 |
| `deliveryNo` | string | 官方描述“发货单单号”;已验证正常单和取消单省略时间/状态可定位,本期默认新单发现不传。仍须校验单号完全一致与货主身份,不能假定所有输入均精确匹配 |
公开分页入参没有 `whCode` 或 `whCodeList`。因此出库目录按账号共享发现,再用返回的 `whCode` 路由至每仓独立任务和统计范围;不得发送未声明字段并假定已经按仓过滤,也不为每个仓重复抓取全账号目录。详情可使用仓库标识,已知单的复查按所属仓执行;跨仓修订必须同时处理旧、新仓贡献。
```json
{
"current": 1,
"size": 1,
"timeType": "outboundTime",
"startTime": "2026-09-12 08:00:00",
"endTime": "2026-10-12 08:00:00",
"status": 100
}
```
正式任务按已确认账号全集读取,不传 `customerCodes`。用户已确认当前可见全部 70 个货主、2 个仓库均为自营统计范围,货主数量不作为硬编码上限。若后续加入货主子集筛选,应先实测该字符串参数,不能依据复数名称自行发送 JSON 数组。
目录保留 `deliveryNo`、`sourceNo`、`customerCode`、`whCode`、`status`、`createTime`、`outboundTime`,并保留商品列表的 SKU、名称与 `qty`;统计取值按一期方案“出库件数”的列表优先规则执行。
## 一件代发出库详情
[官方详情说明](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-detail-1.md)的业务参数仅有以下三个字符串。Schema 未声明 `required`,但本平台合同要求三个值齐全,全部来自同一条已验证分页记录:
```json
{
"whCode": "WH-DEMO",
"customerCode": "CUSTOMER-DEMO",
"deliveryNo": "DO-DEMO-001"
}
```
不要用来源单号 `sourceNo` 代替出库单号 `deliveryNo`,也不要从单号格式推断货主或仓库。
| 响应路径 | 含义与处理 |
| --- | --- |
| `data.deliveryNo/customerCode/whCode` | 必须与查询主体相符;同单仓库变更进入修订核对 |
| `data.status` | 当前状态;以当前事实决定是否计入 |
| `data.orderCreateTime` | 详情的创建时间字段名;分页中对应 `createTime`,不能照搬 DTO 名称 |
| `data.outboundTime` | 实际出库时间,已由领星转换为北京时间;保留源字符串,按 `Asia/Shanghai` 解析并直接使用其业务日期,不再转美国时间 |
| `data.skuVOList[].productSku` | SKU;货主和仓库从详情主体继承 |
| `data.skuVOList[].actualDeliveryQty` | 实际出库量;官方 integer,实测为 JSON number;Java 使用 BigDecimal 统一保留精度 |
| `data.skuVOList[].deliveryQty` | 预报出库量,只作对照,不用于销量替代 |
| `data.packageList[].skuList[]` | 包裹维度重复明细,不与 `skuVOList` 累加;其 `actualDeliveryQty` 官方类型是 string |
同单同 SKU 多行先归并。完整详情缺失、数量无法解析或身份不符时,不能把该单视为零销量后推进完整水位。原始响应可能含面单链接、物流信息等,日志和持久化只能保留本期白名单字段。
### 列表数量与实际数量对照的证据缺口
2026-10-13 按用户要求只读检查 TEST 已保存数据,目标是寻找预报量与实际量不同的一件代发出库单。检查在只读事务中执行,单条 SELECT 限时5秒;本次没有向领星发起请求,没有修改采集任务或统计数据。
- 当前查得12,823条有效出库暂存、12,740个不同订单业务键;预报量字段检查命中0。核对最新完整载荷及代码,商品行仅保留 `skuCode,productName,quantityUnit,actualQuantity`。Integration 的详情 DTO 虽有 `deliveryQty`,Lastleg 转为统计载荷时未保留它,订单事实也不保存预报量。
- 同时查询已出库状态100、商品实际量为0的候选,结果为空;不能据此推断所有订单预报量等于实际量。
- Integration 列表映射只保留订单头,不返回 `productList[].qty`。所以当前库不能直接筛选预报/实出差异,现有内部列表接口也不能完成三值对照。当前检索结果是“缺比较字段”,不是“已证明一致”。
下一步最小验证应优先附着正常采集已经收到的响应,采集少量白名单对照证据:同一账号、仓库、货主、出库单、SKU 的列表 `qty`、详情 `deliveryQty`、详情 `actualDeliveryQty`,订单状态/出库时间及列表、详情观测时间。按同 SKU 汇总后比较,同时核对 SKU 集合完整性。一次授权累计最多选择100个 LIST 候选,缺失配对不补选;首次三值任一已知差异、未知量或 SKU 集合不一致即停止诊断。不额外创建历史采集,不输出面单、收件信息、签名或凭据。当前有界诊断实现及发布边界见下节。
命中预报量不等于实际量时,优先使用同次配对的列表证据;若列表/详情时点相差或订单被修订,则仅针对该订单在现有账号预算和统一出口内最多补一次列表与一次详情核验,限流即停止。已保存匹配证据不重新请求。
验收判定:列表量等于预报且不等于实际量,可否定“列表直接替代实际量”;列表量等于实际量且不等于预报,只证明该差异样本支持替代方向,还需确认 SKU 完整性、修订与取消边界;三值相同不能区分语义。未取得差异样本时明确保留未验证,不停用详情链路。
### 下一自动 root 的一次性有界诊断
当前实现通过 Lastleg 内部 `quantity-diagnostics/arm、status、observe、stop` 管理单次授权,四个入口均校验内部服务令牌,不经 Gateway 公开。旧固定 root/30 分钟配置及 `/orders` 协议已替换,Integration、Lastleg 必须成对更新。默认两端诊断开关关闭;完成契约核验后才能显式 arm,不因重启、会话终止或 root 切换自动重新授权。
- `arm` 冻结诊断 ID、账号、允许仓库、货主及当时实际当前自动 root。客户端传入的排除 root 必须与服务端只读查询一致;当前没有已开始且未结束的自动 root 时传空,发现多个则拒绝。已结束的历史 root 不能冒充当前 root。
- 最多等待 6 小时,接收时刻及原始 LIST 观测时刻均须在绑定截止前。只绑定随后正常 `OUTBOUND_QUERY` 的自动历史出库 root,排除 LOCATE、DETAIL 首绑定、验证与手工任务。root 可以提前规划,不能用创建时间晚于授权作为条件。账号、root 自动属性和 `selfop-<root>` 会话由服务端核验,延迟回调不依赖已经清除的瞬时 permit。
- 采样开始取首次 LIST 原始 `observedAt`,最多再采 4 小时,同时绝不晚于授权后 10 小时;网络延迟、重试和排空均不顺延。会话终态不自动绑定下一个 root。
- 同一会话在诊断行锁内串行选择累计最多 100 个候选。唯一业务键为账号、仓库、货主、出库单;LIST 先存入独立 pending 表,DETAIL 再与首次 LIST 配对。未选中的 early DETAIL 忽略;两侧原始时间、attempt、SKU 数量保持不变。相同规范载荷重传幂等,包含终态重传;新 attempt 或改写载荷不能覆盖首次证据。
- 新授权的持久证据将数量编码为无指数、去除尾零的十进制字符串,读取时严格恢复 BigDecimal;哈希、字节额度与重复比较使用同一规范编码,避免数据库 JSON 数字归一化造成精度损失。未知仍为 null,负数拒绝。此编码只用于诊断存储,外部回调仍传数值并精确解析;JSON 列及历史证据不变,不增加旧数值证据读取分支。
- pending 与最终配对共同累计最多 2000 个保留 SKU 行、2 MiB 规范证据(含配对包装预留),提升为最终证据不返还额度,不通过删除或换候选重新获得预算。未知量或 SKU 不齐为 `INCONCLUSIVE`;三值任意已知差异为 `QUANTITY_DIFFERENCE`,与证据同事务关闭诊断。100 个完整配对且无观察丢失才为 `COMPLETED`,全相等也不证明列表与实际量语义一致。
- 接收线性化点为 Lastleg 会话锁下持久化成功;Integration 本地入队不算已接收。root 结束进入 `DRAINING`,禁止新 LIST 候选,只排空已选候选的在途 DETAIL。Integration 停止入队、依次发送已入队观察后,才提交 drained 确认。少于 100 个完整配对明确为 `ROOT_ENDED_INSUFFICIENT`;有未配对或观察可能丢失则为 `INCOMPLETE`;硬截止始终优先。
- Integration 重启可从持久候选恢复,但未持久化的内存尾部不可证明无损,因此替换 producer 会设置 `deliveryUncertain`,旧 producer 被隔离,最终不能报完整成功。回调不可用、队列满或诊断失败只关闭诊断,不影响正常采集返回,不补发领星请求。
- 正常出口线程只做有界白名单快照和 `tryLock` 入队,不解析/序列化整个原始响应,不等待诊断 HTTP。队列最多100项、2000行和2 MiB保守内存记账;独立单工作线程发送。Lastleg 在获取连接前非等待准入,诊断专用池最多1条连接、借用超时250ms,事务3秒及语句2秒限制;初始化失败只让诊断 API 不可用,不阻止业务服务启动,也不关闭主池。请求/响应均流式限制262144字节。
配置只保留 Integration 的 `quantity-capture.enabled/source-account`,以及 Lastleg 的 `quantity-diagnostics.enabled/source-account/warehouse-codes`。这些是启动时配置,不具备热启用能力;若以 enabled=false 启动,之后改配置不能直接 arm,需重新加载对应进程。本轮总控选择一次成对发布:旧版本窗口已过期且无在途诊断作为变更前停止证据;新版本以能力 enabled=true、无新授权启动,核验带内部令牌的 status 返回 null、active_slot 无活动且 pending 为空,再释放维护、显式 arm。未授权时观察器不接收或留存样本,只查询内部授权状态。不做 OFF→ON 二次重启,也不得把“未授权”与“配置关闭”混称。授权参数与时限留在诊断会话,不通过修改 Nacos、重启或每次 root 发布代码重新启用。源 DDL 为 `lastleg-service/src/main/resources/db/selfop-quantity-diagnostics.sql`:原会话表、配对表以及一张 pending 表,只写诊断证据,不改业务表。该文件是最终空库结构基线,不自动执行。已有表只需会话表增加 `active_slot/state_json` 两个可空字段及活动授权唯一索引,root/session标识允许授权未绑定时为空,另建 pending 表;原配对表结构和全部已有证据保留。原 `stop_reason/accepted_orders/accepted_sku_rows/accepted_bytes` 列仍为终态及计数的唯一事实来源,根标识、开始与截止也使用原列;`state_json` 只补授权范围、绑定截止、producer、候选数、root结束及丢失标记,不另存一份终态或计数。历史会话 `state_json` 为空,不参与新授权协议,不能复用旧 ID arm;不回填、不改写旧证据。发布前由负责发布者先只读导出并核对原证据哈希,再逐项审查已有表的必要 ALTER,不在同名表上运行整份 CREATE,也不执行 DROP。
本地合成测试只证明边界实现;没有执行环境 SQL、发布、arm 或真实取样,不能据此宣称已取得新样本、诊断无物理开销或列表量可替代详情实际量。1200ms 出口间隔、原采集任务、统计来源及业务表保持原逻辑。
### 数量对照验证的采集保护与开发交接
2026-10-13 用户指定已有对话 [开启新对话](codex://threads/01a135d0-f5c7-7422-892f-037b0c9ea00e) 实施本次有界验证,要求不影响采集。仅接管数量对照与所需只读状态判断,不恢复其他对话已暂停的开发、服务或采集。业务销量继续以详情实际量为准;验证通过前不切换统计来源。
开发先核对当前代码、运行版本及改动归属。只读状态使用实际生效配置、账号预算/冷却/暂停原因、未完成请求许可、任务/执行尝试/租约和真实进度观测时间联合判断,不凭聊天状态、“无活动任务”、页面等待文案或心跳正常推断可发请求。前后两次轻量只读观测可识别正常推进与证据变化,不轮询原始订单或 SKU 明细。
| 状态证据 | 对照行为 |
| --- | --- |
| 正常采集运行,有有效租约/在途请求或成功数量推进 | 只附着正在发生的正常响应保留白名单字段;不发独立扫描或插队详情,不调整并发 |
| 等待间隔/自动冷却/预算耗尽/授权失效 | 按实际原因展示等待或不可验证;不缩短间隔、清零预算、延长期限或自动重试探测 |
| 人工暂停、模式OFF、复核暂停、服务正在切换 | 保留暂停;允许准备代码和离线对照,运行取样等后续启用,不为验证开启采集或重启服务 |
| 证据缺失/前后冲突/许可结果未知/版本不一致 | 返回“状态待确认”和缺失证据,禁止主动核验;不把未知解释为安全空闲 |
| 已确认空闲且无在途/遗留未结许可,账号预算及授权均有效 | 如确需补验,只通过现有持久账号预算和统一出口领取一次性许可,最多一单的列表+详情共2次;空闲检查不能代替发请求时的原子许可校验 |
旁路取样必须默认关闭,使用一次有上限的验证会话。会话冻结范围、开始/截止时间、最多100个完整配对订单、接收记录及字节上限;建议最长30分钟,到期或首次预报/实出差异即结束本次捕获,没有差异也按“未命中”结束。不能每次轮询、翻页、重试或重启重置额度。字段来自同一次来源采集代次,配对键至少包含账号/仓库/货主/单号/SKU与观测证据;同单同SKU多行以十进制数量汇总,缺值保留未知,不能按总件数相等掩盖SKU替换或缺行。
诊断字段与业务事实分离,不改变业务内容摘要、修订号、任务就绪条件、归并、发布或现有返回状态。捕获失败、配对超时、存储满时停止诊断并记录脱敏原因,不能让正常采集失败,也不能无限缓存或同步写大量日志。不得保存原始全响应、面单、地址或凭据;三值与必要业务身份仅留在受控诊断存储,文档和报告使用样本别名。
最小代码范围是 Integration 列表/详情响应映射旁的白名单观察、独立有界配对组件及直接测试。优先在 Integration 层完成三值观察,避免为了找样本修改 Lastleg 业务事实表;如必须新增字段传递或内部诊断合同,先声明精确 DTO/调用方/OpenAPI 影响,再由唯一写者同步。不改 Egress 的预算、许可、限流逻辑或已经冻结的持续采集候选,不新增公开绕过出口的接口。开发可以在当前工作区完成,发布需另按当前授权协调;不能把“新增代码不影响运行”扩大成“重启后无损”。
交付须分别给出:采集状态证据和是否具备取样条件;三值对照的有界实现与离线测试;真实差异样本是否命中;额外供应商请求数;是否可以替代及尚未覆盖的边界。至少测试预报10/实际8且列表分别为10和8、SKU集合不一致、重复行、部分字段缺失、跨代次拒配、取消单、会话到期/上限、诊断失败不影响业务返回、暂停/429/许可未知不发请求。没有真实差异样本时只能交付验证能力,不能宣称字段语义已证实。
已实测当前取消单可查详情,且正常单、取消单均可按单号重新定位;实际改仓后的旧三标识行为尚无样本。若旧仓三标识无法取得详情,使用出库分页的按单重新定位方式,以下为合成业务参数:
```json
{"current": 1, "size": 10, "deliveryNo": "DO-DEMO-001"}
```
官方业务 Schema 没有将时间参数和 `status` 列为必填。2026-10-12 的正常、取消两个样本均省略这些字段,分别返回唯一同货主、同单号记录;样本未受到默认已出库过滤。必须读完返回页、逐条校验单号完全一致及货主身份,再取当前仓库查详情;不能只按模糊单号命中就迁移事实。无结果、权限失败、多个身份冲突均进入待核对,不认定取消、不清零。
当前 Java 已有独立的 `/outbound-orders/locate` 入口和按单定位请求 DTO,不传时间/状态条件;默认摘要发现接口仍用于状态 100 的新单发现,不能用它替代取消定位。新单发现和已知单修订复核使用不同查询意图,仍共用账号限流和签名器。该源码能力仍须完成内部 HTTP 和编排验收。当前取消样本的详情仍有实际数量 `1`,但 `outboundTime` 为空;必须先按状态和有效出库时间判定,不因数量大于零计入销量,也不能据此证明该单过去已经出库。
## 仓库发现和分仓配置
用户已确认按仓库分别采集和管理时效。先调用 [正常仓库列表](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-warehouse-page-1.md):
```json
{"current": 1, "size": 1000}
```
请求路径为 `/openapi/v2/warehouse/page`,业务入参 `current` 默认 1、`size` 默认 10、最大 1000。可按 `whCode`、`whNameCn`、`countryCode` 筛选,但一期发现当前全部正常仓库时不传过滤。接口没有 `status` 请求参数,也不要因为业务是“自营”就添加 `warehouseType=0`,自营商品可能存放在代理仓。
响应分页字段是 **`data.page/pageSize/pages/total`**,不是产品库存的 `current/size`;2026-10-12 已实测这一差异。每行保留 `whCode`、`whNameCn`、`warehouseType`、`status`、`timeZone`;不用仓库地址、联系人或联系方式。`warehouseType` 为 0 自营仓、1 代理仓;`status` 为 0 正常、1 停用、2 冻结,但该接口只返回正常仓库,缺失仓不能解释为“库存归零”。
仓库编号是任务、快照、时效与未来预警规则的必需维度。每仓保存来源时区、报表时区、出库计划、库存计划及过期阈值;本期两个时区字段均已确认填写 `Asia/Shanghai`,每天北京时间 08:00/20:00 出库、建议每天北京时间 08:00 库存。返回的 `timeZone` 只是仓库所在地资料,不覆盖领星已转换好的北京时间。某仓失败不阻止另一仓发布完整库存,不能用成功仓的采集时间刷新失败仓。
## 产品库存分页
[官方产品库存说明](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-stock-stocksku-page-1.md)与管理端「产品库存-库存信息」口径一致。库存接口没有日期筛选,也不使用出库的最近两个月窗口。
正式任务必须按仓发送 `whCode`,以下是单仓全量产品库存 `data` 模板:
```json
{
"current": 1,
"size": 1000,
"whCode": "WH-DEMO",
"isHideInventory": 0
}
```
对每个已确认仓库独立从第 1 页读完,每页只增加 `current`,同仓其他参数保持一致。**不传 `productQuality`,采集正品和次品;不设置 SKU、数量、预警或品类过滤。** 该仓全部货主均纳入,正常全量不传 `customerCode`;它只用于定向核验。每仓独立记录执行状态、覆盖范围、采集起止和发布版本,统计只使用正品 `productQuality=0` 的可用库存。
| 参数 | 类型 | 官方规则与使用方式 |
| --- | --- | --- |
| `current`、`size` | integer | 默认 1、10;每页最大 1000 |
| `customerCode`、`whCode` | string | 官方均未标必填,实测可省略;本平台分仓采集要求 `whCode` 必填,`customerCode` 可省略读取该仓全部货主 |
| `whCodeList` | string[] | 仓库列表,最多 500;不要同时混用单仓与多仓参数,优先关系未核验 |
| `productQuality` | integer | `0` 正品、`1` 次品;全量不传,专题查询可传 |
| `isHideInventory` | integer | `0` 保留零库存,`1` 隐藏;正式全量必须为 0 |
| `barcode`、`barcodeAccurate`、`barcodeList` | string、string、string[] | 模糊/精确检索;列表最多 500。官方名称 Barcode 与列表说明“SKU”不一致,未经单 SKU 实测不得用于生产过滤;全量不传 |
| `productName`、`categoryIdList` | string、string[] | 商品名、品类过滤;品类最多 500;全量不传 |
| `stockValueType`、`startValue`、`endValue` | string | 数量过滤;类型为 `stkQty/freezeQty/useStkQty`,边界开闭未说明;全量不传 |
| `sortName`、`sortOrder` | string | 数量排序,方向 `asc/desc`;无稳定快照或唯一排序保证,不能靠排序解决翻页期间变动 |
| `stockStatus` | integer | `0` 无预警、`1` 预警;全量不传 |
返回是 `data.records[]`,分页元数据是 `data.current/size/total/pages`。主体字段都在每条记录的第一层:
| 字段 | 类型与映射 |
| --- | --- |
| `customerCode`、`whCode`、`productSku` | string;与来源账号、品质一起构成候选业务键 |
| `productName` | string;展示信息,不作为唯一键 |
| `productQuality` | integer;分别保存正品、次品 |
| `stkQty` | number;实物库存 |
| `freezeQty` | number;冻结库存 |
| `useStkQty` | number;可用库存,正品该值用作可售量,不再次扣冻结 |
| `transitQty` | number;在途,单独保存,不计入当前可售量 |
| `innerBatchNo`、`outBatchNo` | string;批次线索,空字符串保留为空;不能未经核验据其拆分库存粒度 |
| `uniqueKey4tenant` | string;只作来源核对,不拆解它替代明确维度 |
| `stockCompare` | object;代理仓对比信息,不与本行数量相加;其中 `refreshTime` 不是主体库存采集时间 |
数量使用 BigDecimal/数据库 DECIMAL;不能强转 int、截断小数或将 `""`、null、缺字段自动转换为 0。官方统一空值规则可能把数值 null 输出成空串或 0,API 数值 0 仅能证明“接口报告零”,首次正式验收仍须与领星页面核对。接口缺行不证明库存为零。
## 后续库龄数据入口
[官方批次库存分页](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-stock-batch-page-1.md)公开 `POST /openapi/v2/stock/batch/page`,对应 SKU 批次库存,不是整箱库存。可作为后续真实库龄核验入口,已核对的公开字段如下:
| 字段 | 官方含义与类型 |
| --- | --- |
| `stockAge` | integer,库龄天数 |
| `putawayDate` | string,上架日期 |
| `stkQty` | number,在库数量 |
| `customerCode`、`whCode`、`productSku`、`productQuality` | 货主、仓库、SKU 与品质;前三者为 string,品质为 integer |
| `sysBatchNo`、`batchNo`、`innerBatchNo`、`outBatchNo`、`relateOrderNo` | string,系统批次、上架批次、内部/外部批次及关联入库单号 |
该接口尚未实测账号权限、字段非空覆盖和分页完整性;还需确认库龄起算、移仓/退货是否重置、不同视图及库位是否重复汇总,并按同一货主、仓库、SKU、品质与产品库存对账。现有产品库存样本的批次字段为空,不能代替此接口验证,也不能用首次同步日补造真实库龄。领星 `stockAgeStatus` 的规则尚未核准,不直接作为本平台的滞销判断或评级。
本节仅登记后续待核验能力,不是本轮一期必交代码,不默认接入生产;一期仍使用现有出库与产品库存链路,本次不新增真实请求。后续核验沿用账号独占、同一会话共享请求预算及遇限流即停规则,不另开预算或自动全量补采。用途仍为自营业务内部评估与仓储成本分摊,不用于对外客户收费。
## 成功、失败和契约差异
2026-10-12 出库分页、详情和产品库存已观察到成功包络为数值 `code=200`、`data` 和 `msg`,没有 `success`,与官方 BaseResponse 的 required 声明不同。解析规则为:
1. HTTP 200 只是传输成功;仍检查 JSON `code` 为数值 200。
2. `success` 缺失时继续校验数据结构;存在时必须是布尔 true,false、null 或字符串均拒绝。
3. 分页必须有有效 `records` 数组和可核验分页元数据;详情必须是对象并核验主体身份与 SKU 明细。当前 Java `mappedPage` 已要求 `total/current/size/pages` 并校验页数和本页行数;完整批次仍须由 Lastleg 跨页检查唯一业务键、页间总数变化及应有页数,不能由单页适配成功推定全量成功。
4. 官方认证错误可使用字符串错误码;保留数值错误码和固定错误分类,原始 `msg` 不直接输出日志或用户界面。认证失败不当作空页。
5. 测试验证遇 HTTP 429/明确限流码立即停止整轮会话,不自动重试;正式任务交回账号协调器统一冷却后有限退避,不由各接口独立重试。超时等失败也消耗原预算;权限与验签错误停止盲目重试。没有验证的配额与历史限制保留为待确认项。
**出库分页空结果的已验证例外**:请求 `current=1,size=100`、时间窗口明确不包含目标单时,成功响应为 `records=[]、total=0、pages=0、current=1、size=10`。它把空页条数恢复为默认 10。可仅在这组完整空结果条件同时成立、且本次请求为第一页时归一化内部 `size` 为请求值,保留源分页元数据作为诊断;不能因此判失败。非空页、总数缺失、后续页异常或其他结构错误仍严格拒绝;未经验证不能把例外推广到库存或仓库接口。首次探针因严格回显检查中止,针对空结果核验后完成后续测试,这不是供应商业务请求失败。
成功响应示例为合成数据,展示的不是实际业务记录:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"current": 1, "size": 1000, "total": 1, "pages": 1,
"records": [{
"customerCode": "CUSTOMER-DEMO", "whCode": "WH-DEMO",
"productSku": "SKU-DEMO", "productQuality": 0,
"stkQty": 120.0, "freezeQty": 20.0,
"useStkQty": 100.0, "transitQty": 30.0
}]
}
}
```
这里的 `total` 是供应商 JSON number;经过现有平台 Long 序列化后,本地内部 API 的 `total` 为字符串,这是平台响应格式,不能据此要求供应商返回字符串。
## 联调证据与复现验收
### 2026-10-14 客户名称与商品资料权限核验
用户明确要求核验当前 key 是否可读取客户列表、货主名称和商品。15:37(北京时间)使用 TEST Integration 当前容器中的同一组凭据,只读请求以下两个官方 OMP 接口各一次,间隔1.3秒,无自动重试;请求前后只读检查账号无活动任务、运行或占用租约。没有暂停采集、重启、配置发布、SQL数据写入或业务数据导入。本次是独立有界接口权限验证,不表示已有正式主数据同步能力。
| 接口 | 本次实际结果 | 后续接入边界 |
| --- | --- | --- |
| [客户列表](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-customer-list.md),`POST /openapi/v2/customer/list`,`current=1,size=1000` | HTTP200、业务码200;total=85、单页返回85条,85条均有 `customerCode/customerName`,用户截图中的编码与名称对应核验通过 | 85是该key当前可见客户目录数,不等于有库存或销量的货主数;正式保存账号+客户编码对应名称,保留编码作为关联键,不能用名称连接销量。无需重拉历史出库 |
| [商品分页](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-product-page-1.md),`POST /openapi/v2/product/page`,`current=1,size=5` | HTTP200、业务码200;total=8536,本次仅读取5条,均有 `customerCode/sku/productName` 和正数 `length/width/height`,`sizeUnit=cm`;5条 `wmsLength/wmsWidth/wmsHeight/wmsSizeUnit` 均为空字符串 | 官方每页最多100,8536条按当前总数预计86页,尚未执行全量。不得从5条推定全部尺寸有效;普通资料尺寸可用于标明来源的估算,不能冒充仓库实测体积或历史出库包裹体积 |
两个资料接口的请求分页参数均为 `current/size`,**响应分页字段均为 `data.page/pageSize/pages/total`**;不能套用产品库存接口的响应 `current/size`。2026-10-14 对照官方两个接口 Schema 再次确认这一差异;先前有界样本保存的 `current/size=null` 也不应被视为有效页码。Integration 按正式响应字段严格核对当前页、页大小、总页数及行数,向 Lastleg 统一输出内部 `current/size`,不增加两套响应字段兼容回退。客户响应 `status` 为字符串;商品实测尺寸空字符串继续表示未知。
客户名称映射和5条商品白名单样本只保存在本机受控私有证据文件,未保存联系人、电话、邮箱或完整原始响应;不将真实客户资料提交仓库。临时验证程序为后端忽略目录 `target/selfop-masterdata-key-probe.mjs`。此次只读核验时的业务采集 DTO 尚未接入客户名称和商品尺寸。后续接入契约见《领星一件代发数据统计一期方案》页首“客户名称与商品资料接入”;接口权限证据不代表实际部署、全量同步和体积口径已验收。
截至 2026-10-12,出库分页通过本地 Java 服务验证;详情、仓库发现和库存使用同一组凭据及 OMP 签名直接执行只读 HTTPS 请求。临时探针与脱敏报告放在被 Git 忽略的 `integration-service/target/lingxing-local/`,只保留字段类型、数量、分页计数和核验结论,不保存密钥、签名或完整原始响应。这些临时文件可被构建清理,开发依据以本手册记录为准。
| 项目 | 已验证内容 | 不能由此推定 |
| --- | --- | --- |
| 一件代发分页 | 本地 Java 已取得一条状态 100 的摘要;使用出库时间最近一个月窗口 | 整月已完成采集、时间区间完整 |
| 一件代发详情 | 对同一单传齐仓库、货主、出库单号,HTTP 200、业务码 200;`skuVOList` 返回一行,实出和预报数量均为数值 1 | 所有单都单 SKU、预报永远等于实出;北京时间口径来自后续用户确认,不由 HTTP 成功推定 |
| 产品库存样本 | 不传货主、仓库、品质,`current=1,size=2,isHideInventory=0` 返回两行;四种数量是 JSON number,零库存能返回 | 所有空值语义、同一时刻快照;自营范围由用户另外确认 |
| 产品库存两轮全集核验 | 北京时间 15:30:32—15:32:24,每轮 7 页、6,635 条;两轮业务键与四种数量一致 | 永久稳定排序、跨页原子快照、已持久化业务库存 |
| 正常仓库发现 | 返回 2 个仓库;分页元数据为 `page/pageSize`,仓库资料有 `timeZone` | 接口时间必定使用仓库时区、未来停用仓可直接清零 |
| 定向库存筛选 | 用样本货主+仓库查询,返回记录均属于所请求的货主与仓库 | 同仓全量只需该货主,或其他货主不属于自营 |
| 按仓全分页 | 分别带两个实际 `whCode` 查询,每页 1000,合计 7 页、6,635 条;每行都属于所请求仓库,分别通过总数与业务键核验 | 跨仓为同一原子时刻、时区已完成业务对账 |
全集核验的 6,635 是“货主+仓库+SKU+品质”库存记录数,不是商品件数,也不等于去重后的 SKU 数。两轮均为正品 6,293 行、次品 342 行;实物为零 3,278 行、实物大于零 3,357 行。未观察到重复业务键、缺失主体身份、四种数量类型异常或负数;样本全集的批次字段均为空,`stockCompare` 均为空对象,因此非空批次和代理仓对比仍待专项样本。用户随后确认全部 70 个货主、2 个仓库纳入自营,并要求正式采集按仓执行。
2026-10-12 北京时间 15:43:18—15:44:09 的按仓结果如下。仓库 A/B 是文档脱敏别名,不可作为请求中的 `whCode`;实际编码必须从仓库目录或受控配置读取。
| 仓库 | 仓库资料时区 | 页数 | 库存记录 | 正品/次品记录 | 零实物记录 | 涉及货主 |
| --- | --- | --- | --- | --- | --- | --- |
| A | `America/New_York` | 1 | 894 | 892/2 | 280 | 15 |
| B | `America/Los_Angeles` | 6 | 5,741 | 5,401/340 | 2,998 | 69 |
表中美国时区为接口实际返回的仓库资料,保留原值作为证据;两仓的出库返回时间和本期统计口径仍统一为用户确认的北京时间,不按这两个资料值分别转换。
两仓合计与先前账号全集相符;货主可跨仓出现,15+69 不能作为去重货主数。首次分仓尝试遇到临时网络错误,未视为成功;随后重跑完整分仓读取成功。正式同步必须同样区分失败尝试和已发布完整批次。以上核验只读入内存并保存脱敏统计,没有导入业务表,也没有新增 Java 库存 API。
### 2026-10-12 追加前置验证
用户要求继续验证后,本轮继续直接串行请求 OMP,最小请求起始间隔 1.1 秒,不制造业务变更、不做限流压测。以下 API 验证发生时尚未取得用户的时区确认,也未完成页面对账;用户随后确认领星返回值已是北京时间,当前按本手册开头的 `Asia/Shanghai` 口径执行。该用户确认与下列只读实测证据分别记录。
| 验证项 | 本次结果 | 保留的限制 |
| --- | --- | --- |
| 正常单按号定位 | 省略时间与状态,返回唯一同货主、同单号的状态 100 记录;三标识详情一致 | 不保证模糊输入或同号跨货主也唯一,仍须逐条核验 |
| 出库不同页大小 | 源字符串窗口 `2026-10-10 01:00:00` 至 `02:00:00`,size=124/125 均 3 页、372 个唯一单据;两轮单号集合及仓库/状态/出库时间摘要相同 | 不是 UTC 区间证明,也不是原子快照或永久稳定分页承诺;没有页面导出对账 |
| 秒级边界 | 一个已出库样本:宽窗前后复读均命中;以该时刻为起点、终点均命中;严格前一秒与后一秒窗口均不命中。六次结果均全量、唯一且单号准确 | 仅观察到该样本两端包含;尚未覆盖另一仓、其他时间类型或北京时间午夜边界 |
| 空结果分页 | 两个不相交窗口都返回 `records=[]、total=0、pages=0、current=1、size=10`,请求 size=100 | 仅按前述严格条件归一化;不能放宽非空页、库存页或后续页 |
| 多 SKU 详情 | 另取 5 条已出库单,分别有 4、4、3、3、2 个 SKU;身份、数量类型与列表出库时间一致,实际量均等于预报量 | 未观察到同 SKU 多行、实出少于预报或部分出库,不把缺少样本标为通过;单位仍需业务核对 |
| 当前取消单 | 近月创建时间查询的取消目录报告 163 条;抽查列表的 20 行均状态99,读取其中1条详情也为99,按号无时间/状态定位仍唯一命中 | 该样本实际数量1、出库时间为空,不能证明过去已出库;改仓及“出库后再撤销”仍无前后证据 |
| 详情耗时 | 7 次详情耗时约 1.09—2.63 秒,平均约 1.57 秒 | 只是小样本观测,不是配额、容量或首采完成时间承诺 |
| 实际限流与退避 | 串行、最小起始间隔1.1秒下,仍观察到1次出库分页 HTTP429;有限退避后的第二次请求为 HTTP200、业务码200 | 未刻意压测;不能由一次429反推准确阈值,也不能将1.1秒间隔视为已确认的安全持续速率 |
| A 仓库存分页 | size=298/299 各3页、各894个唯一业务键,集合和四种数量一致 | 仍为采集区间观测 |
| B 仓库存反例 | size=999 时6页、5,741个唯一键;随后 size=1000 返回5,741行,但只有5,740个唯一键,发现1个重复键,两轮集合不同 | **该次尝试完整性失败,不能发布。** 原因尚不能区分业务变化与非稳定排序,不删除异常证据 |
| B 仓完整重试 | 再从第一页以 size=1000 完整读取两轮,各6页、5,741个唯一键;无重复、集合和四种数量一致 | 证明本次可恢复,不证明供应商分页永久稳定;不是将前后数据拼起来凑齐 |
出库与详情验证于北京时间 16:25:37—16:26:31 完成;两仓不同页大小核验于 16:27:57—16:29:22 完成;B 仓完整重读于 16:32:40 完成。脱敏报告分别为忽略目录中的 `prerequisites-20261012T082631Z.json`、`prerequisites-20261012T082922Z.json`、`prerequisites-20261012T083240Z.json`;前一次空页严格校验中止记录另保留,不能混记为成功。
验收必须覆盖两个实际用例:出库合法空页不误报失败;库存总数与返回行数相同、但唯一键少 1 时仍整批拒绝并重试。当前 `LingxingWmsClient` 已包含限定的出库空页例外:请求首分页 `size=100`,来源 `current=1,size=10,total=0,pages=0,records=[]` 时允许通过,其余页大小不匹配仍拒绝。此处仅更新源码事实,未重新运行 Java 或批次验收;既有直接 HTTP 联调证据与当前适配器验证应分别记录。
公开官方资料专项核对未找到账号 QPS/每日配额、时间戳容许误差、源出库时区、历史保留或最大更正期限的明确值。官方 `requestDeliveryTime` 的北京时间说明不能单独外推给 `outboundTime`;本期出库北京时间口径采用用户的明确确认,不再列为待选时区。供应商仍需补充列表/详情保留期限、已出库后撤销与改仓是否允许及查询方式、账号请求配额,以及稳定分页能力。当前低频调用成功不能代替这些确认。
后续复验先检查账号独占和整轮预算;不直接开启当前会自动规划正式首采的执行开关:
1. 先完成离线签名、异常脱敏、预算耗尽及用途隔离测试,确认原采集环境已停止且在途请求排空。在独占验证窗口内只读读取配置、不回显值,用 `size=1` 的出库分页和 `size=2` 的产品库存开始,足够即停。保存业务参数模板、时间、HTTP/业务码、字段类型和已用预算。
2. 用分页同一行的三个业务标识查详情,核对实际 SKU 数量和创建/出库时间字段;与领星页面同单对账。禁止把包裹数量重复累加。
3. 以已确认的当前账号全部 70 个货主、2 个仓库建立范围版本;按仓库目录取得实际编码,核验带 `whCode` 返回的每行仓库一致。仓库目录或业务范围变化要重新验证覆盖,不将 70/2 固定在代码中。
4. 测试只在原会话预算内翻少量页、读取有限详情,并记录 `total/pages`、实际行数、唯一键与停止原因;达到预算或遇到限流即停止,不为凑齐某种样本继续搜索。不完整库存不得发布、补零或触发缺行占位。
5. 重复键、缺页、总量变化、断点恢复、事实归并和版本发布先用离线合成数据验证。2026-10-13 用户确认库存按每仓一轮完整分页观测,取消两轮数量完全一致的发布前提;正式受控任务保存每仓真实采集区间和完整性证据。所有页、唯一业务键、总量、范围及数量校验仍须通过,不拼接失败批次,不承诺跨页原子快照。历史两轮核验仅证明当次观测结果,出库目录规则不变。
6. 对本次预算内已有的正品、零库存、次品、冻结、在途样本进行相同筛选的页面核对;未取到的场景留待合成用例或正式生产验收,不追加无上限查询。结束验证后关闭该环境真实出口,再交还账号给正式采集。
来源与统计时区已确认采用北京时间;实现仍需验证北京时间午夜边界与内部 UTC 存储不改变业务日期,订单历史修正期限、稳定分页和实际账号限流仍需供应商或人工对账确认。库存 API 没有历史时点参数,不能用当前查询补造昨日库存。开发可以从适配、暂存及分仓任务开始;正式启用标准统一见[一期方案的开发准入与正式启用门槛](领星一件代发数据统计一期方案.md#开发准入与正式启用门槛),本手册的成功样本不替代这些门槛。
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,278 @@
# 领星统计查询性能优化方案
面向平台销售开发总控,当前先完成功能、真实数据正确性及人工页面确认,并发优化后置。本文维护后续性能专项规划,不触发代码修改、真实采集或压测,不把新增诊断任务变成功能联调的前置条件;页面不可用、请求超时或数据错误仍按功能问题处理。
性能专项恢复时,按“复用完整基线与诊断 → 验证有证据的新候选 → 全场景验收”推进。窄投影、profile 归并和延后商品名称均已试验,未显示稳定收益,移出默认实施顺序;只有新的执行计划证据表明问题或条件发生实质变化时才考虑重测。每次只验证一项主要改动,保留结果一致性与执行计划证据。
本文为 2026-10-13 的查询优化执行方案,只交付文档,不修改代码或操作环境。业务口径、版本保护及验收目标继续以[一期主方案](领星一件代发数据统计一期方案.md)和[经营总览图表设计](经营总览图表设计.md)为准;本文不另建部署状态或验收进度台账。开发安排由[平台销售总控](codex://threads/01a12feb-0474-77f1-afe0-a3b491733dca)统一收口。
用户本轮追加的领星获取速度、重复请求与等待开销只读梳理,统一维护在[采集速度优化顺序](#采集速度优化顺序)。它与前述经营查询 SQL 优化分开,不因本次梳理调整正在运行的采集任务或提高账号出口并发。
## 对照基线与问题判断
以[库存索引倒序优化后的完整压测](../../baiyue-firstleg/reports/selfop-test-20261013/selfop-perf-read-r5-inventory-seek-r2-result.json)为本次核对取得的较新基线。该轮于北京时间 2026-10-13 10:29 结束,合成数据共 11,968,200 条 SKU 日行,包含多个版本;不能把这个总量当作单仓单版本行数。10 个并发用户持续约 301 秒,总览和销量各完成 664 次、默认库存完成 663 次,共 1,991 次,无请求错误。
| 查询路径 | P50 | P95 | P99 | 现行 P95 目标 |
| --- | ---: | ---: | ---: | ---: |
| 经营总览近 15 天 | 2,732 ms | 3,107 ms | 3,275 ms | ≤1,500 ms,未达标 |
| SKU 销量近 15 天 | 1,150 ms | 1,382 ms | 1,489 ms | ≤1,000 ms,未达标 |
| 默认库存列表 | 613 ms | 774 ms | 849 ms | ≤1,000 ms,该场景达标 |
[此前仓库日汇总后的报告](../../baiyue-firstleg/reports/selfop-test-20261013/selfop-perf-read-r5-warehouse-daily-r1-result.json)中,三个路径的 P95 分别为 3,169、1,412、1,092 ms。保留它作为前后对照,不能继续将默认库存写成尚未达到 1 秒,也不能把默认列表通过扩大为所有关注筛选、排序和下钻均已通过。
常用路径稳定性通过不代表完整性能验收通过。该压测报告仍列有未验证项;后续[分段诊断摘要](../../baiyue-firstleg/reports/selfop-test-20261013/selfop-query-timing-r4-summary.json)补充了 SQL 次数与阶段耗时采样,不能再把这项写成完全未开始。后台候选构建并行、构建增长成本、复杂筛选及原单增长不影响查询等仍需专项证据。旧销量版本的 366 天 SKU 清单在较早报告中有约 7.30/7.39 秒的单次抽样,后续需复核;单次结果不能当作 P95。
已完成且输入条件一致的基线与诊断直接复用,中途停止的压测不算完整基线。恢复性能专项后,先核对期间功能修复是否改变查询 SQL、索引、数据集、版本和资源条件,再决定是否需要更新基线,不因本文更新原样重跑。以上为固定证据快照,后续实际部署和验收状态仍由现行主契约维护。
## 保留已有优化
当前代码已具备以下能力,不再作为待从零实现的任务:
| 已有能力 | 代码入口 | 本轮处理 |
| --- | --- | --- |
| 趋势读取已发布仓库日汇总,进入查询前验证就绪证据 | [DashboardReadMapper](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/DashboardReadMapper.java)、[DashboardQueryService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/DashboardQueryService.java) | 保留,不再让趋势扫描所有 SKU 日行 |
| 一次 report 返回统计和三个 Top 10,共享 SKU 计算结果 | [DashboardReadSql](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/DashboardReadSql.java) 的 `report` | 保留共享计算,不拆成每张图独立扫描;窄投影按下文已试验结论处理 |
| 默认库存按库存量先选页,再补该页销量;普通 ALL 计数只读候选身份 | [AnalyticsInventorySql](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/AnalyticsInventorySql.java) 的 `stockFirst`、`inventoryCount` | 保留轻量路径,不能被复杂筛选的通用方案拖慢 |
| 默认库存最后出库日按现有索引倒序取首条 | 同上 `inventoryPage` | 复用上文已完成的并发结果;仅默认 ALL+AVAILABLE_DESC 且无分桶/selection 的路径已采用,复杂筛选不能视作同时完成 |
| SKU 销量清单先选分页键,再计算本页完整/部分/未知日数 | [AnalyticsReadSql](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/query/AnalyticsReadSql.java) 的 SUMMARY 分支 | 保留,不重新引入所有 SKU × 所有日期的展开 |
| 库存过期或 30 日不完整时,总览跳过相应无用事实聚合 | `AnalyticsInventorySql.dashboardCte` | 保留,不能以资格不足场景的快速结果代替完整场景验收 |
查询已经有日表覆盖索引,不能仅凭慢就继续叠加相近索引。最多 366 个趋势点、30 条榜单记录的 Java 处理暂不列为优化重点。
## 复用分段诊断并限定剩余测量
分段诊断共 39 个请求,包含三个接口各 3 个单用户样本和各 10 个并发样本;它明确标为诊断用途、非 P95 验收。并发组的已观测结果如下,均为平均值:
| 路径 | 主要 SQL 阶段耗时 | 其他阶段与结论 |
| --- | ---: | --- |
| 总览 | report 约 3,028 ms | context 约 4 ms、daily 约 2 ms;优先研究全仓 SKU 聚合、分桶及榜单成本 |
| SKU 销量 | page 约 1,166 ms | count 约 54 ms、context 约 4 ms;优先研究区间聚合与分页排序 |
| 默认库存 | page 约 498 ms | count 约 48 ms、context 约 5 ms;保留已达标路径,后续做回归 |
三个接口在这组样本中均固定为 6 条统计读 SQL。诊断范围为 `ONLY_ANALYTICS_READ_MAPPERS`,不能将 6 条说成包含 IAM/鉴权等全部应用 SQL,也不能由小样本推断全部场景都不存在额外调用。采样已指出主要 SQL 成本;连接池等待、数据库资源竞争、写入重叠等仍按需要补证据,不再从头重复同一诊断。
固定同一数据集、代码版本、仓库、双统计版本、业务日期、覆盖证据和库存时效,分别记录以下阶段。跨午夜、库存过期、版本切换或测试数据重建后,需要重建可比基线。
| 请求 | 需要分开的耗时 |
| --- | --- |
| 总览 | 权限与 context 校验、仓库 daily、report、DTO 组装、序列化与 HTTP 总耗时 |
| SKU 销量 | context、候选 count、分页及日量聚合、DTO/HTTP |
| 库存 | context 与下钻资格、count、分页与最后出库日、DTO/HTTP |
每个代表 SQL 保存绑定参数范围、执行计划、实际行数/循环数/耗时、排序和临时表证据。对比 profile、snapshot、daily 各访问节点,确认共享 CTE 是否确实只构建一次。同一请求关联各阶段耗时,不能用两个阶段各自的 P95 相减估算成本。数据库总耗时还应与连接池等待、CPU、磁盘及同机负载对照,不能把 HTTP 与数据库耗时之差全部归给 Java 计算。
只采集当前测试需要的只读诊断;`EXPLAIN ANALYZE` 会真正执行查询,沿总控既有环境窗口安排,不和另一轮压测或构建竞争。诊断参数采用合成账号和业务编码,不在文档、日志或证据中写凭据及真实客户载荷。
候选方案先做相同输入的响应对照,再做单请求 SQL 对照;有一致且可解释的收益,才进入整轮 HTTP 压测。首次应用请求、预热和业务结果缓存命中分别标注,不把“首次应用请求”称为数据库磁盘冷启动;不为制造冷启动清理共享数据库缓存。
## 已试验方案与重试条件
依据[开发总控 2026-10-13 的后续性能反馈](codex://threads/01a12feb-0474-77f1-afe0-a3b491733dca),以下三项已经测试,均未显示稳定收益。此处记录试验结论与选题边界,不把“尚无稳定收益”扩大成所有数据规模下永久无收益,也不编造提升比例。
| 方案 | 已有结论 | 默认处理 | 重新验证的前提 |
| --- | --- | --- | --- |
| 总览共享结果窄投影 | 已试验,未显示稳定收益 | 不再列为首选任务,不重复原样 A/B | 新执行计划显示宽字段确实造成主要临时表/去重成本,且能说明新方案与已测方案的实质差异 |
| 两版 profile 归并以减少重复访问 | 已试验,未显示稳定收益 | 不再安排同一归并方案 | 新执行计划显示 profile 访问成为主要成本,并能指出访问路径、规模或归并方法相对既有试验发生的变化 |
| 榜单确定后延后读取商品名称 | 后续已试验,未显示稳定收益 | 从待试新候选中移除,不再单独派工 | 新证据表明名称访问或携带名称的中间结果成为主要成本,且处理方式与已测方案存在实质差异 |
重试前先复用总控保留的代码版本、输入及计划证据,写清旧结论、新证据和本次差异。重新发布文档、换一个试验名称或重新出现同一静态代码建议,都不构成重试理由;已有试验详细证据需要核对时先核对记录,不直接重跑。
若满足上述前提,正确性边界仍保留:窄投影不能删除身份、分类、资格或排序所需字段,观察证据即使不展示也须参与上游计算;profile 归并须保留来源存在标记,区分“无该版记录”和“该版字段无效”,不能因 MAX/MIN 忽略空值而将未知改成有效。单位资格、编码比较、名称优先级及有效观察依据均不变,库存过期也不意味着其 profile 身份可删除。
## 后续集中处理两条主要慢查询
### 总览聚合与销量分页
总览以 report、销量以 page 为下一阶段的主要优化对象。对照已有计划核实日行扫描、聚合、排序及物化的实际工作量,先说明新方案具体减少哪一部分,而不是继续围绕已无收益的字段/名称调整。默认库存保留回归覆盖,不继续作为主要提速目标。
总览固定 30 日的重复计算与销量清单任意日期区间是两种需求,不能用只覆盖固定 30 日的结果替代今日、近 3 天、本周、近 15 天、本月及历史自定义区间。若要评估把重复计算移到版本构建阶段,按后文条件分支测算读取收益和构建成本,另行形成具体设计,不直接追加统计表。
连接池或线程数只有在等待和资源证据支持时才评估,不以增加请求并行度代替减少数据库工作量。每项候选均保留固定版本、全候选资格、未知值及排序语义,不提前裁掉 SKU 获得表面速度。
### 按实际成本审视物化方式
`DashboardReadSql.report` 的 DISTINCT 有阻止四个消费者重复展开计算的用途,不能直接删除。如果新的分段与执行计划证据显示共享结果的去重仍是主要成本,再核对既有试验,决定是否有值得验证的物化替代方案;不把 `NO_MERGE` 等提示自动当作尚未尝试的新方向,也不要求先重做窄投影。
任何替代方案都要证明统计与三个榜单仍共用一次聚合,没有将 daily/snapshot/profile 展开四次。计划不稳定或未显示可重复收益时,保留当前实现;不能仅凭提示写进 SQL 就认定生效。已试验方案若无实质变化,直接沿用既有结论。
## 减少复杂库存筛选的重复聚合
`AnalyticsQueryService.inventoryCoverage` 先调用 `inventoryCount`,再读取 `inventoryPage`。当条件依赖销量资格,例如无销量、可售天数、分桶或无法评估时,两次查询都会执行相近的完整候选计算。
分段测量若证实这两次聚合是相关路径的主要成本,再尝试一次共享候选:先在全候选上计算、筛选和排序,再从同一结果取得计数与当前页。执行计划须证明公共聚合只执行一次,仅抽取相同 SQL 字符串再调用两次不算共享。统计行应独立产生,即使结果为空或 offset 超出末页也返回真实 total,并且不能把统计占位行映射成伪 SKU 记录;不能仅依赖附在页记录上的 `COUNT(*) OVER()`,否则空页会丢失总数。响应 DTO 继续使用现有分页合同,不对前端引入第二套格式。
必须保留普通 ALL 的身份计数、冻结/次品关注的库存专用计数,以及默认库存先分页方案。**本项主要优化图表下钻和复杂筛选,不承诺降低基线中的 inventory-ALL 耗时。**
复杂筛选最后出库日仍可单独评估同一 SQL 内的页内索引倒序探测;它只补充展示,不参与筛选资格。保持固定销量版本、账号/仓库/货主/SKU、`business_date<=anchor`、PCS 正出库量及无匹配返回空值。对无销量或大量无效日行的 SKU 仍可能扫描较多行,不能承诺每个 SKU 必定只读取一行。
热销/滞销计数与分页也有类似重复计算,但只有定向测量证实不达标时再扩展,避免把本轮收敛变成全查询重写。
## 实测后再启用的方案
### 不完整或过期状态的快速路径
总览已跳过部分无用事实扫描。若“30 日不完整且库存过期”的场景仍耗时,可进一步评估只从固定 profile 身份生成候选数和未知统计,跳过空榜单计算。四种 `complete30 × stockFresh` 组合分别对照,零候选、未发布版本、未知原因优先级和七桶计数均须一致。
该项改善诊断状态响应,不能代替“30 日完整且库存新鲜”的正常经营查询优化,也不优先于总览正常路径。
### 固定版本结果的有界缓存
如果前述查询调整后仍未达标,再依据测量结果评估进程内有界缓存及同键并发请求合并,不默认新增 Redis 或缓存平台。总览 report 固定计算 30 日,切换趋势范围时存在复用机会;首先评估该稳定数据块,不缓存整页响应。
缓存键必须覆盖账号、仓库、全部实际访问范围、销量与库存版本、范围/修订摘要、固定日期窗、完整性和时效资格、规则版本。容量受条目数及内存预算限制,失败结果不作为正常数据缓存;发布、跨午夜、库存过期、修订屏障及旧版本不可读均须使相关复用失效。
每次请求仍在受控只读快照中完成权限、范围、版本可读性、覆盖和时效校验,重算实时状态。携带固定上下文的请求保留原 `queryAsOf`、业务日期锚点和 `queryExpiresAt`;下钻截止时间依据实际库存时效重算,并受原上下文有效期上限约束,不因缓存命中或翻页续期。一个旧缓存命中不能绕过被删除版本、待重建状态或过期库存的处理;同键请求合并不能把一个请求的上下文直接发给另一请求。
主方案明确要求无业务结果缓存的性能验收,本方案不修改该标准。缓存关闭、首次未命中、同键首次并发和命中分别报告;缓存收益只能作为额外体验改善。若无缓存始终不能达标,总控应提交剩余成本与方案取舍,不能自行以命中数据宣布通过。
本轮不新增固定 30 日 SKU 表、周月表或搜索引擎。若执行计划证明正常请求的全仓 SKU 聚合已是主要且无法继续压缩的成本,再单独评估发布时预计算的读取收益、构建增量成本、跨日期重算和原子发布规则;不能仅为省一次查询把可变结果写回已发布版本。
## 分开规划采集速度与查询并发
| 链路 | 记录的时间与吞吐 | 与其他链路的边界 |
| --- | --- | --- |
| 领星目录与逐单详情采集 | 配置间隔、实际请求起始间隔、请求耗时、成功明细数/分钟、429/冷却、剩余目录与详情请求量 | 统一账号级限流及环境独占;不能因有两个仓库就给每仓单独一份额度 |
| 本地归并与统计候选构建 | 输入行量、批次量、构建阶段耗时、写入量、发布耗时及磁盘增长 | 使用已落库的事实;统计发布完成与详情下载完成分开记录 |
| 页面查询 | 请求并发数、请求组合、实际完成请求数/秒、P50/P95/P99、错误率及各 SQL 耗时 | 读取已发布本地版本,10 个并发用户不等于固定 10 QPS,也不对应领星请求并发 |
总控在 2026-10-13 报告的账号串行小样本中,3/2/1 秒配置档各完成 20 次成功请求,对应平均详情请求间隔约 3.77/2.79/1.86 秒;0.5 秒配置档在约 735 ms 的两次详情请求间隔处出现 429 并停止。这证明配置等待和实际吞吐要分开测量,不能据此推导领星固定配额,也不能由 20 次成功认定可长期稳定维持该速率。总控选择的 1 秒配置不作为本方案的永久安全速率或新默认配额。
这些实测仅用于容量推算与解释来源等待。后续仍遵循[主方案的生产首采与测试请求边界](领星一件代发数据统计一期方案.md#生产首采与测试请求边界)及[接口联调手册](领星WMS接口联调手册.md)的账号预算、冷却和终止规则;本方案不发起新的限流探测,不增加真实采集并发,也不放宽原有请求预算。页面性能验证使用本地合成事实与统计数据。
采集预计完成时间应分为“剩余目录/详情获取、归并、构建、发布”四段。获取阶段根据实际成功吞吐及剩余请求量滚动估算,冷却和失败另计;不能仅用配置间隔乘单数给出整轮完成承诺,也不能因目录页拉完就显示销量已可用。页面分别展示已获取详情、已归并数量、构建阶段、最近完整发布版本及停止原因,沿用既有采集进度合同。
### 采集速度优化顺序
依据[接口专项的只读反馈](codex://threads/01a12f3f-c57a-79e1-9efa-9401f594544c),本轮复核了当前工作区的获取、路由、等待和预算链路。结论是:**先减少每条详情之后重复执行的本地工作,再减少短间隔等待造成的恢复开销;扩大目录分页作为后续新任务的次要节省项。** 已定位的是源码中的工作量放大,还没有整轮分段耗时证据,不能宣称它已占总耗时的某个比例或承诺若干倍提速。
接口调用单位也要分清:一个出库单详情请求可以带回多个 SKU,当前不是每个 SKU 都发一次详情请求。出库目录由账号共享获取,再分仓处理;产品库存独立按仓全量分页,两条链路不混用过滤能力。
| 顺序 | 已核对的情况 | 候选改进与预期影响 |
| --- | --- | --- |
| 先保留基线 | 1 秒配置不等于 1 秒实际请求间隔;短样本约 1.86 秒还没有完整分段 | 用现有观测与本地合成回放拆分耗时,不增加领星限流探测;记录生效配置、代码快照及阶段规模 |
| 优先 1 | 每拿到一条新详情即执行全量 `route(false)`;按仓逐个检查整批目录 | 保留首次等待任务登记与最终完整路由,中间不再每单重建全量子任务;减少本地查询与子任务写回,不改变必要详情 HTTP 数量 |
| 优先 2 | 每次间隔不足可能退出任务、释放租约,随后恢复重新扫描 | 若分段证据确认短间隔让出频繁,评估事务外有界等待或准确的到点调度;减少额外恢复成本,不降低账号最小间隔 |
| 随后核对 | 父 manifest 每次整批序列化、重新统计完成量并写回;恢复检查也从开头进行 | 先测累计 JSON 字节、检查点和恢复扫描成本;用可靠的增量计数、变更集合/有界批量减少重复工作,保持可恢复证据。取消全量路由不代表这部分自动消失 |
| 后续新窗口 | 官方目录上限 1000,本地出库 Query DTO 与校验上限为 100 | 统一 DTO、适配校验、配置和冻结参数后再验证较大分页;只节省目录请求,不能中途改变已运行任务的分页参数 |
| 条件分支 | 批量实际出库明细、可靠修改游标或变更推送尚无已确认合同 | 向供应商核实能力及字段等价性后再设计;这是可能显著减少详情 HTTP 的方向,不能现在直接替换现有来源 |
#### 已确认的本地放大点
[SelfopDiscoveryService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/sync/SelfopDiscoveryService.java) 在详情处理前、每条新详情提交后和全部完成后调用 `route`。其中按配置仓库遍历完整 manifest,对每个对象点查旧订单;相关对象有有效详情时,再读取和解析 stage,并重建子任务 manifest。中途 `detailsResolved=false`,子任务仍等待来源,不会因为这些完整重算提前进入 READY。
设目录对象数为 N、仓库数为 W、本轮实际新增抓取详情数为 K,在不计恢复和修订的基础路径上,旧订单查询方法调用量约为 `W × N × (K + 2)`。代入 N=K=2,787、W=2,约 1,554.6 万次调用。**这是代码循环的条件推算,不是已测 SQL 次数或数据库全表扫描次数**;MyBatis 缓存、事务边界、恢复和分支都会影响实际 SQL 与耗时。首采 K 接近 N 时,这部分工作量近似平方增长。
`saveManifest` 还会序列化父任务整批对象、遍历完成数并更新 task/run;检查点读取包含 manifest 的 task 行,路由又为各仓写回完整 manifest。该成本需要单列。优化不能简单把持久检查点全部改成内存缓存,也不能不落库直到最后;可复用的 VALID stage、对应关联及提交边界必须可靠保留,进程中断不能丢失已取得的详情或错误复用旧版本。
首个最小改动可先减少路由频次,不急于换表或调度平台。最终路由再评估有界批量读取旧归属和有效 stage、每对象解析一次后按仓分组。保留旧仓+新仓联合归属、取消/跨日期修订、`belongsToSlice`、租约栅栏及半归并屏障;全部详情确认前不能让空仓提前发布零量,已经 APPLYING/APPLIED/BLOCKED 的子任务不能被覆盖。页面等待关联和进度继续使用轻量投影,不靠重复全量路由维持可见性。
#### 额外等待不等于供应商请求时间
[SelfopEgressService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/request/SelfopEgressService.java) 的 `ACCOUNT_INTERVAL_WAIT` 在发出领星 HTTP 前产生;[SelfopExecutionService](../../baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/selfoperated/analytics/sync/SelfopExecutionService.java) 将执行让出并释放租约。调度器 `fixedDelay=1000` 表示当前 tick 的同步任务处理结束后再等 1 秒,不是保证每秒准时启动。出库任务恢复还包含重新获取租约、建立尝试和读取/扫描 manifest。
[LingxingEgressGate](../../baiyue-firstleg/integration-service/src/main/java/com/baiyue/integration/provider/lingxing/LingxingEgressGate.java) 在实际 HTTP 开始前另有账号保护,只等待尚未满足的剩余间隔。HTTP、落库和路由也消耗时间,不能把两处配置间隔简单相加。Lastleg 的持久 `minIntervalMs` 采用旧值与配置值的较大者,配置改成 1000 也不能直接证明实际已按 1000 生效;应只读核对实际许可和 HTTP 时间,不为本次梳理清空保护状态。
短间隔优化仅针对可恢复的普通间隔等待:事务外有界等待后重新校验租约、截止时间、账号保护及预约资格。等待超界、限流冷却、会话预算耗尽和结果不确定仍走原有让出/暂停路径;不能持有数据库事务或行锁睡眠,不能无限占用唯一调度线程,不能为了减少尝试数跳过重新授权。是否使用短等待还是到点调度,由实测等待分布和调度公平性决定。
| 事件 | 领星真实 HTTP 与预算 |
| --- | --- |
| 预约前因最小间隔/冷却/在途被拒绝 | 不发领星 HTTP、不增加持久 HTTP 预留;此前本轮内存工作额度可能已消耗,需与请求预算分开统计 |
| 成功预留后、发送前失败 | 可能没有真实 HTTP,但预留与根会话额度不自动退还;不能据 reserved 数认定已调用领星 |
| 已开始的超时、429 或业务失败 | 消耗一次真实请求;有回执时按实际调用数确认,未知结果保持保守预留 |
| 重试/重新定位/再取详情 | 每次均重新授权计额;当前 Integration 没有隐藏的供应商 HTTP 重试循环 |
内部 reserve/authorize/complete 通信也有成本,但不是领星请求。下一轮性能证据分别记录内部调用数、真实 HTTP 数、预留额度和确认额度,不用 run 次数或重试次数代替外部调用次数。
#### 哪些请求可以减少,哪些还不能省
官方[出库分页](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-page-1.md)目前公开的请求字段没有仓库过滤,最大页大小为 1000;返回仓库编码不代表请求支持按仓筛选。按两个仓库重复扫同一账号目录不节省请求,当前账号共享采集设计应保留。
以 2,787 单、两个稳定目录扫描轮次、所有订单均需一次详情、无异常重试为例:每页 100 需要 56 次目录请求,每页 1000 需要 6 次;加上 2,787 次详情,总量约从 2,843 降到 2,793,少 50 次,约 1.8%。这里只是基础请求量推算,不含重新定位、修订、库存等;真实收益还受响应大小和分页稳定性影响。已经完成目录的当前任务,不会因扩大未来分页而加快剩余详情。
列表虽然有 `productList[].qty`,官方未明确它在部分出库、差异出库及后续修订中等同实际出库量;[详情](https://apidoc-omp.xlwms.com/reference/post_openapi-v2-order-delivery-detail-1.md)明确区分 `deliveryQty` 与 `actualDeliveryQty`。当前统计需要后者,不能仅因列表包含 SKU 和数量就删掉详情请求。列表的批量单号筛选也不等于批量实际明细。
已有有效详情且没有更新观测时,当前代码会跳过 HTTP;这项应保留,不再作为从零开发的优化。新的观测代次、身份失配或修订要求重新核实时,仍需读取或重新定位。当前公开时间筛选未确认可靠的修改时间游标,不能永久以“列表字段没变”判断详情无需复查,也不能删除第二轮目录稳定性核验来制造提速。
需要供应商确认的高价值问题是:已出库列表 qty 的完整语义、批量实际明细能力、带稳定游标的修改时间增量/变更推送、历史修订与取消范围,以及账号级/接口级速率、突发和在途限制。当前未找到已确认能力不等于供应商没有这些能力;取得契约与针对性对账证据后,才能评估替换详情链路的收益。本轮不联系供应商、不增加试探调用。
#### 最小测量与验收
先复用已有日志和只读统计。缺少的分段埋点留给后续开发工作包,不为测量新增真实采集、加大并发或反复重跑已完成日期。每轮证据关联同一任务、尝试和出站许可,保留代码版本、N/W/K、复用比例、生效间隔、已发布覆盖、同机负载及预算边界。
| 测量组 | 必须区分的指标 |
| --- | --- |
| 外部调用 | 各接口 HTTP 数、实际起始间隔、HTTP 耗时、成功新增详情/分钟、429/超时;复用完成量不算新增下载速度 |
| 调度与保护 | 最小间隔拒绝数、可再次尝试时刻、到点至实际恢复的延迟、租约获取/begin 耗时、内部授权/完成回执耗时 |
| 本地处理 | 详情检查点、route、最终路由、归并/构建/发布分别计时;订单/stage 方法调用与实际 SQL 次数分别记录 |
| 序列化与恢复 | manifest 大小、累计编码/解码字节、子任务写回次数、恢复重扫对象数、峰值内存和数据库连接等待 |
实际 HTTP 起始间隔、详情提交间隔和整阶段耗时分别报告;用同一请求链中不重叠的时间段解释墙钟耗时,不将互相覆盖的保护等待重复相加。先回答本地重复工作、外部等待各占多少,再决定线程数、连接池或并发调整;短样本不能证明长期限额。
离线对照建议固定 N=100/1,000/3,000、W=1/2,使用假领星 Client 和计数 Mapper,比较优化前后的必要 HTTP 数、route 次数、查询调用、JSON 字节、子任务写回和最终结果。覆盖部分恢复、全部复用、新观测强制复查、跨仓、取消、时间切片、零单、提交回滚、租约失效、等待超界及冷却。证明减少工作量且结果/恢复语义等价后,再按总控有效授权验证实际数据库耗时与整阶段吞吐;离线替身耗时不能冒充数据库提速。
本轮不承诺减少必需详情数量,不修改正在运行任务的分页、租约和会话预算,不为赶速度增加账号并发。采集页改版仍按已确认设计推进;这些采集性能候选由总控另行安排,不能把未经测量的优化变成当前页面交付的前置条件。
## 真实数据覆盖与容量样本用途
此前几分钟的真实销量样本只能验证局部链路。总控为功能验证补采的两仓单日 2,014 单,也必须完成目录核对、详情获取、归并与覆盖/发布校验后,才能用于判断对应日期的结果;目录数量相同或 HTTP 全部成功本身不证明业务日完整。
一个日期的数据完整不代表最近 30 日完整,也不自动补足每个 SKU 的观察期。相应平均销量、可售天数、无销量结论及榜单资格仍按主方案判定;不能为让页面出现数字把未覆盖日补零。真实功能样本与合成容量数据分别标注账号范围、仓库、统计版本、覆盖区间、观察依据及库存新鲜度。
功能核验可先使用真实单日结果,并用已有合成数据检查完整 30 日榜单、边界和下钻。容量验收必须包含“30 日完整且库存新鲜”的正常经营路径;观察不足或库存过期导致跳过聚合的快速响应仅代表该状态,不用于替代正常路径性能结果。
## 正确性与性能验收
所有 SQL 调整保留当前 API、权限、六位小数数量口径、统计版本、北京时间业务日及未知值规则。不会因为优化改变页面字段、图表范围、榜单资格或库存新鲜度。
| 对照组 | 必须验证的结果 |
| --- | --- |
| 两仓、同 SKU 不同货主、仅单版存在的 SKU | 身份不串仓/不串货主,候选并集不丢失;名称优先级不变 |
| 完整/部分/未知销量、真实零量、单位冲突 | 正式量、已采集量、未知数量及原因一致,未知不能变成零 |
| 新鲜/过期库存与完整/不足 30 日的四种组合 | KPI、榜单、七桶和下钻资格一致;正常完整场景单独计时 |
| 边界 30/60/90 天、零可售、次品/冻结、短观察期 | 分桶用原精度比较;有限天数、无销量和未知不混算,库存品质不放大销量 |
| 首末页、越界页、空结果及并列销量/天数 | total、顺序及业务键一致;不先取 Top 10 再算全仓分布 |
| 发布切换、旧版、修订屏障、跨午夜、库存到期 | 同请求读一致快照;严格下钻拒绝规则及独立销量读取不变 |
| 小数与最后出库日 | 小数汇总不提前取整;最近日期条件不放宽,无匹配仍为空 |
响应对照使用同一逻辑时钟与固定输入,逐字段比较;真实 HTTP 中必须变化的请求时间/诊断标识单独核对,不以整段忽略 context 的方式让对照通过。
每项候选先完成直接回归和 SQL 对照,再串行复测同档 HTTP,记录 P50/P95/P99、样本数、错误数、每请求 SQL 数、数据库耗时、扫描及临时结果、响应大小。相同资源下重复比较以排除波动;不能靠提高超时、减少候选、缩短统计范围或跳过资格校验获得收益。
最终验收沿用主方案:单仓 1 万货主+SKU、单销量版最多 366 万条稀疏日行、当前及至少两个旧版,并验证两仓隔离。无业务结果缓存,10 并发稳定至少 5 分钟;各类用例需要分别有足够样本,低于 100 个成功样本的路径只作抽测,不用其 P95 宣布通过。缺失阶段或失败请求不能从汇总中静默排除。
| 性能场景 | P95 目标及边界 |
| --- | --- |
| 经营总览 | ≤1.5 秒 |
| 五种常用范围的 SKU 清单、7/30 日榜单、库存各关注筛选/排序、货主概览 | ≤1 秒 |
| 366 天自定义 SKU 清单 | ≤2 秒,覆盖当前及仍可读旧版 |
| 单 SKU 日趋势、货主选项、采集运行元数据查询 | ≤500 ms |
| 全部正常合法请求 | 无超时/错误;首次与预热、单用户与并发、深分页分别报告 |
同档后台候选构建期间也要满足查询目标,并验证只读完整旧版;构建耗时、扫描、写入及磁盘增长单独报告。增加原单和旧统计版本后,当前固定版本查询不能扩大成原单/全部版本扫描。查询不访问 order/item/stage,不调用领星;合成容量验证不能通过开启真实采集获得数据。
### 并发与后台构建的对照矩阵
| 场景 | 固定条件与增加的负载 | 应取得的证据 |
| --- | --- | --- |
| 查询单独运行 | 单用户与 10 并发分别记录;请求组合、分页深度、日期范围、双版本、资格状态及资源不变 | 每条路径分别统计样本量和时延;默认库存作为已达标回归项,总览与销量作为主要改善对象 |
| 查询与候选构建重叠 | 相同查询读取原固定版本,同时启动规模明确的本地候选构建 | 记录真正重叠的起止时间、构建阶段、输入/输出行量、批次及进度,关联查询时延、连接等待、CPU/磁盘;不能仅以后台曾启动证明已覆盖竞争 |
| 查询与采集落库重叠 | 如需验证,采用受控合成输入,并单列写入速率与持续时间 | 与前两组分别比较,保留归并/写入的干扰证据;不调用领星制造压力 |
| 版本发布边界 | 新旧版切换前后的请求分别标记,固定上下文仍读取原版 | 版本一致、无半份数据、到期拒绝正确;不把发布后更换数据范围的请求混入同一 A/B 结果 |
请求组合先覆盖既有近 15 日总览、销量和默认库存,再增加常用范围、长窗口、复杂筛选及深分页;记录每类占比,不能改变组合后直接比较整体平均值。主读阶段仍要求稳定至少 5 分钟;短构建或短采样仅标明覆盖到的阶段,其余阶段保留未验证。是否单独追加容量档位由实际使用需求决定,不自行把 10 并发目标扩展为新的大规模压测要求。
## 交给开发总控的工作包
以下工作包在功能与人工页面验收安排后启动;当前仅更新规划和证据,不向总控追加立即执行的性能任务。
| 顺序 | 工作包 | 完成条件 |
| --- | --- | --- |
| 1 | 复用完整基线与诊断 | 复用 1,991 次请求的完整基线及 39 次分段诊断,核对功能修复后的可比性;仅补缺失或已变化的证据 |
| 2 | 对准总览 report 与销量 page | 现有采样已明确主要 SQL 成本;补查计划及资源竞争中的剩余问题,默认库存保持回归,不重做无收益实验 |
| 3 | 验证有证据的新候选 | 用具体减少的扫描/聚合/排序工作量说明收益来源;复杂筛选共享聚合按其自身瓶颈选题,窄投影、profile 归并和延后名称无新证据不重做 |
| 4 | 全场景验收 | 按主方案完成无缓存、长窗口/旧版、下钻及上述混合负载矩阵;无稳定收益候选不进入最终实现 |
| 条件分支 | 退化状态快路/固定版有界缓存/发布时预计算评估 | 仅在前述证据支持时展开,不自动增加本轮表结构或平台依赖 |
总控指定查询实现的唯一写入者;只读评审、回归设计可以内部并行,Maven、部署和共享环境压测窗口继续串行协调。现有查询、Mapper、SQL 基线由其当前写入者维护,本次文档交接不另行移交文件写权,不创建独立对话。
每个候选交付“修改点与版本、固定输入、响应对照、前后执行计划、同档性能结果、是否保留及理由”。已试验未显示稳定收益的方案保留结论,新派工先查重;有实质差异才重新验证。测量完整后再决定下一项,不以预计收益百分比代替结果。本文不授权部署、SQL 执行、环境写入或真实领星调用;这些操作继续沿总控已有有效授权和工程约束安排。
@@ -132,7 +132,7 @@
| `shipperSnapshot` | 我司提货时提交必填 | 仅取货方式为 `PICKUP` 时保存提货公司、联系人、电话和地址快照;自送快递、自送卡车不要求 | | `shipperSnapshot` | 我司提货时提交必填 | 仅取货方式为 `PICKUP` 时保存提货公司、联系人、电话和地址快照;自送快递、自送卡车不要求 |
| `consigneeCounterpartyId` | 可选 | 兼容后台往来单位引用;企业客户端下单不强制选择 | | `consigneeCounterpartyId` | 可选 | 兼容后台往来单位引用;企业客户端下单不强制选择 |
| `consigneeSnapshot` | 私人仓时提交必填 | 仅目的仓类型为 `PRIVATE` 时保存私人收件地址快照;FBA 仓、海外仓使用所选公共仓主数据,不重复填写收件资料 | | `consigneeSnapshot` | 私人仓时提交必填 | 仅目的仓类型为 `PRIVATE` 时保存私人收件地址快照;FBA 仓、海外仓使用所选公共仓主数据,不重复填写收件资料 |
| `deliveryInfo` | 平台维护 | 可选履约信息,包含快递公司 ID/快照和快递单号;企业客户端只读 | | `deliveryInfo` | 平台维护 | 包含快递公司 ID/快照和快递单号;客户仅在快递自提(SELF_EXPRESS)下单或编辑草稿时可选填 `expressTrackingNo`(最长 128 字符),复用现有快递单号字段与详情回读;其他状态只读 |
| `transportMode` | 提交必填 | FCL、LCL、AIR、ROAD | | `transportMode` | 提交必填 | FCL、LCL、AIR、ROAD |
| `businessType` | 提交必填 | 订单与客户支持 EXPORT、IMPORT | | `businessType` | 提交必填 | 订单与客户支持 EXPORT、IMPORT |
| `origin` | 提交必填 | 起运地或起运港 | | `origin` | 提交必填 | 起运地或起运港 |
@@ -309,6 +309,8 @@
订单列表包含订单号、参考号、运输方式、起运地、目的地、状态、负责人、预计时间和更新时间;支持关键词、状态、运输方式和创建日期筛选。 订单列表包含订单号、参考号、运输方式、起运地、目的地、状态、负责人、预计时间和更新时间;支持关键词、状态、运输方式和创建日期筛选。
头程下单取货方式按“卡车自送、我司提货、快递自提”排序。仅快递自提显示选填快递单号;服务端去除首尾空白,空值清空,其他取货方式不保存单号。复制订单时清空单号,避免复用上一票快递信息。
创建页按以下顺序组织: 创建页按以下顺序组织:
1. 运输信息和平台收货仓; 1. 运输信息和平台收货仓;
@@ -317,7 +319,7 @@
4. 客户备注; 4. 客户备注;
5. 保存草稿或提交审核;提交前校验企业资料已经平台人工审核通过。 5. 保存草稿或提交审核;提交前校验企业资料已经平台人工审核通过。
详情页展示订单摘要、发货方/收货方快照、货物明细、服务端时间线、履约快递公司、快递单号和当前可用操作。内部备注、成本和平台内部操作信息不得进入客户响应;企业客户端不能修改快递信息或往来单位档案。 详情页展示订单摘要、发货方/收货方快照、货物明细、服务端时间线、履约快递公司、快递单号和当前可用操作。内部备注、成本和平台内部操作信息不得进入客户响应;企业客户端仅能在快递自提下单或编辑草稿时选填快递单号,不能维护快递公司或往来单位档案。
### 管理后台 ### 管理后台
@@ -339,7 +341,7 @@
- 往来单位查询只返回当前企业可见且已启用的发货单位和收货单位;跨数据范围 ID 在保存草稿和提交时均被拒绝。 - 往来单位查询只返回当前企业可见且已启用的发货单位和收货单位;跨数据范围 ID 在保存草稿和提交时均被拒绝。
- 往来单位改名、改地址或停用后,历史订单继续展示下单时快照;停用单位不能用于新订单提交。 - 往来单位改名、改地址或停用后,历史订单继续展示下单时快照;停用单位不能用于新订单提交。
- 快递公司编码和名称满足唯一规则;停用公司不能新增到履约信息,历史订单继续展示已保存快照。 - 快递公司编码和名称满足唯一规则;停用公司不能新增到履约信息,历史订单继续展示已保存快照。
- 客户端订单详情只读展示快递公司和快递单号,接口不得接受客户修改履约快递信息。 - 客户端订单详情只读展示快递公司和快递单号;客户仅可在快递自提下单或编辑草稿时选填单号,不可修改快递公司或已提交订单的快递信息。
- 我的信息只能读取当前登录成员;修改所属公司或其他成员资料的伪造请求必须拒绝,修改密码必须校验当前密码并写入安全审计。 - 我的信息只能读取当前登录成员;修改所属公司或其他成员资料的伪造请求必须拒绝,修改密码必须校验当前密码并写入安全审计。
- 注册成功后无需审核即可登录;公司信息只返回当前企业数据,未通过企业资料审核时服务端拒绝提交订单,审核通过后允许提交。普通成员无写权限时仍可按授权查看,资质文件下载使用受控地址并覆盖过期、缺失、上传失败和无权限状态。 - 注册成功后无需审核即可登录;公司信息只返回当前企业数据,未通过企业资料审核时服务端拒绝提交订单,审核通过后允许提交。普通成员无写权限时仍可按授权查看,资质文件下载使用受控地址并覆盖过期、缺失、上传失败和无权限状态。
- 快递公司和往来单位批量导入仅允许具备对应导入权限的后台人员调用;企业客户端和普通写权限不能绕过独立导入权限。 - 快递公司和往来单位批量导入仅允许具备对应导入权限的后台人员调用;企业客户端和普通写权限不能绕过独立导入权限。
@@ -1,99 +1,229 @@
# 海外仓费用统一接入阶段 0 技术契约 # 海外仓费用统一接入阶段 0 技术契约
> 版本:V0.5-0A | 状态:开发前技术基线 | 来源:海外仓费用统一接入财务评审方案 V0.5 > 文档状态:开发基线配套契约 V0.1
> 编制日期:2026-09-21
> 适用范围:阶段 0A—0E;配套需求基线为 [海外仓费用统一接入财务评审方案](海外仓费用统一接入财务评审方案.md)
## 1. 目标与边界 本文把 V0.5 的阶段 0 规则转成可编码的跨服务边界、状态和唯一性约束。本文不是数据库字段逐项施工单;开发时可以调整表名和类名,但不得改变这里的业务语义、状态分离、幂等边界和跨区域结果规则。
阶段 0 只完成“费用事实可追踪、可幂等、可被 Finance 接受或拒绝”的底座,不新增业务收费规则,不部署测试环境,不启动 Java/Nacos/数据库。所有费用仍由业务服务产生事实,Finance 独立落库并负责应收/应付、钱包和结算。 ## 一、阶段 0 目标与顺序
实施顺序固定为: 阶段 0 不是新增仓租算法,先修复已有海外费用链路的一致性:
1. 0A:既有链路和收费身份; | 子阶段 | 目标 | 依赖 |
2. 0B:统一来源命令、结果和 Outbox/Inbox;
3. 0C:冻结/结算按收费身份和计划版本;
4. 0D:退货、仓租、按票及库存日事实;
5. 0E:商业调整、拒绝和财务待办。
## 2. 当前代码事实与必须修正点
| 范围 | 当前实现 | V0.5 要求 |
|---|---|---| |---|---|---|
| 来源事件 | `BusinessFeeSourceChangedV1` 单向完整快照 | 增加命令/结果闭环,Finance 明确 ACCEPTED/REJECTED | | 0A | 统一收费身份、人工/自动去重、换标漏发、拆柜费用身份、派送收付方向 | 先冻结本文模型和唯一键 |
| 费用版本 | Lastleg 调整、作废先改变当前状态再发事件 | Finance 接受新版本后,旧版本才可 SUPERSEDED/VOIDED | | 0B | 人工费用草稿/驳回修改、待审工作台、业务费用聚合、直付证据 | 0A 收费身份 |
| Wallet | 以 `businessType + businessNo + amount` 匹配冻结 | 绑定 `chargeIdentity + feeSourceVersion + walletPlanId` | | 0C | Finance 费用接受/拒绝结果回传、来源版本变更裁决 | 0A 的版本模型 |
| Relabel | 部分完成路径发布费用,SKU/客户确认路径漏发 | 所有完成路径统一产出一条收费身份 | | 0D | 资金计划 ID/版本、来源精确分配、冻结/结算/释放旧计划隔离 | 0C 的有效版本结果 |
| Destuff | 直接 insert 已审批客户应收,绕过服务和命令 | 进入统一来源命令;供应商应付按阶段配置 | | 0E | 商业减免、取消收费、待财务处理及自动重算门禁 | 0C、0D |
| Delivery | 转运时直接发布已审批费用 | 票级 AR/AP 分离,人工金额先待审 |
| 来源模型 | 无 `scenarioCode`、收费身份、Finance 同步状态 | 三者均为显式字段,不从业务单号推导 |
## 3. 收费身份与状态 0A—0E 可以在前序数据结构稳定后并行实现,但不能在未冻结本契约前各模块自行新增状态或幂等字段。
### 3.1 收费身份 ## 二、当前代码事实与必须修正的断点
`chargeIdentity` 是稳定的业务收费对象键,不等同于数据库 ID。格式由场景定义,至少包含 `scenarioCode`、业务主单号、客户和收费对象序号;同一身份可产生多个不可变 `sourceVersion`。Finance 唯一键为: | 现状入口 | 当前行为 | 阶段 0 修正 |
|---|---|---|
| `lastleg-service/financefee/OverseasFeeSourceService` | `adjust` 先把旧版本设为 `SUPERSEDED`,`voidSource` 先设为 `VOIDED` | Finance 接受前旧有效版本继续保留;新候选/作废命令等待 Finance 结果 |
| `OverseasFeeOutboxService` / `BusinessFeeSourceChangedV1` | 只有海外向 Finance 的完整快照事件,没有业务可消费的接受/拒绝结果 | 增加版本化费用变更命令和 Finance 结果事件,双向 Outbox/Inbox 幂等 |
| `BusinessFeeSourceEventService` | Finance 直接入池并返回本地方法结果,无结果事件;资金关联按业务类型、业务单号和金额匹配 | 同事务记录命令结果;接受、拒绝、冲突、超时可回传;资金按计划版本和来源分配关联 |
| `WalletCommandRequestedV1` | 只带业务类型、业务单号、金额和聚合版本 | 资金计划 ID/版本、收费身份、计划金额快照和来源分配进入新目标协议 |
| `DestuffingPalletCostService` | 手工构造 `APPROVED/PUBLISHED` 来源,绕过通用审核和统一收费身份 | 复用计费身份、来源版本、审核策略和调整门禁;分摊组保持守恒 |
| 换标完成分支 | 仅部分 `COMPLETED` 路径发布换标费并发起资金结算 | 所有合法完成分支汇合到唯一发布/结算入口,重复完成幂等 |
| 派送转单 | 转派送时人工费用自动审核,且同一费用项目的应收/应付身份不完整 | 人工费用进入待审核;应收与应付按收费身份独立,实际供应商和直付证据必填 |
| `listForBusiness` | 主要按单一 `businessType + businessId` 查询 | 业务详情按稳定关系聚合来源,当前有效版本与待确认变更分开返回 |
`sourceSystem + sourceType + sourceFeeId + sourceVersion` ## 三、收费身份模型
费用明细必须同时保存 `chargeIdentity`,用于 AR/AP、钱包、账单和追溯关联。 ### 3.1 收费身份与来源版本分离
### 3.2 状态轴 收费身份表示“同一业务应该收哪一笔钱”;来源版本表示“这一笔钱当前提交了哪个金额版本”。二者不得混用。
- 来源状态:`DRAFT`、`PENDING_REVIEW`、`APPROVED`、`REJECTED`、`SUPERSEDED`、`VOIDED`。 收费身份逻辑字段:
- 发布状态:`NOT_PUBLISHED`、`PUBLISHED`、`ACCEPTED`、`REJECTED`。
- Finance 同步状态:`PENDING`、`ACCEPTED`、`REJECTED`、`RETRYING`。
- 结算状态:`UNSETTLED`、`FROZEN`、`SETTLED`、`RELEASED`。
状态轴不可互相覆盖。费用调整必须生成新版本;同一版本不同 hash 必须拒绝。已进入有效账单、结算或钱包结算的来源不得替换或作废。 ```text
identityKey
customerId
sourceSystem
businessType
businessId / businessNo
scenarioCode
feeItemCode
direction
priceRole CUSTOMER_SALE / SUPPLIER_COST
supplierId 成本侧必填;销售侧为空
periodScope 离散事实或计费期间范围
```
## 4. 跨服务命令与结果 约束:
### 4.1 `BusinessFeeSourceCommandV2` - 客户应收和供应商应付是两条身份;不能用方向字段在一行中来回切换。
- 成本侧实际供应商进入身份。多个供应商责任必须拆成多个身份。
- 自动任务、人工补录、重放、报价恢复和资金计划都引用同一身份。
- 明确免收也占用身份,不能因为没有 Finance 来源而再次收费。
- 退货按票身份按 `RETURN_ORDER + RETURN_HANDLING + CUSTOMER_SALE` 去重;退货操作费按实收累计组;仓租按原始分量、角色、供应商和日期范围占用。
事件头:`eventId`、`eventType`、`eventVersion=2`、`eventKey`、`occurredAt`、`sourceSystem`、`traceId`。 ### 3.2 来源候选版本状态
业务体:`action`(UPSERT/VOID)、`sourceType`、`sourceFeeId`、`sourceVersion`、`chargeIdentity`、`scenarioCode`、客户/业务/仓库/供应商引用、方向、币种金额、数量单价、期间、付款证据、来源状态、`sourceHash`。 业务审核状态、Finance 同步状态、财务来源状态和结算状态分开保存:
发送方必须发送完整快照,不允许 Finance 回查海外库。`eventKey` 固定为 `sourceSystem:sourceFeeId:sourceVersion:action`。 | 状态轴 | 首版值 | 含义 |
|---|---|---|
| `reviewStatus` | `DRAFT`、`PENDING`、`APPROVED`、`REJECTED` | 业务是否允许向 Finance 提交 |
| `financeSyncStatus` | `NOT_SENT`、`PENDING_FINANCE`、`ACCEPTED`、`REJECTED` | 该候选命令的跨区结果 |
| `sourceStatus` | `ACTIVE`、`SUPERSEDED`、`VOIDED` | Finance 接受后的来源有效性;接受前不得覆盖旧有效版本 |
| `settlementStatus` | `AVAILABLE`、`PENDING_WALLET`、`SETTLED`、`BILLED`、`BLOCKED_FINANCE` | 出账或资金路径状态 |
### 4.2 `BusinessFeeSourceResultV2` 同一收费身份最多一个待 Finance 确认的候选或变更。Finance 拒绝后,旧有效版本继续有效;修订必须以最后 Finance 接受的版本为前序生成新候选。
Finance 处理后回传:`commandEventId`、`sourceFeeId`、`sourceVersion`、`result`(ACCEPTED/REJECTED)、`reasonCode`、`reasonMessage`、`financeFeeSourceId`、`processedAt`、`resultHash`。 ## 四、跨区域费用命令与结果
业务方以 `commandEventId` 幂等接收结果;REJECTED 必须形成可重试或人工待办,不得静默丢弃。结果事件不能改变原始费用快照。 ### 4.1 费用变更命令
## 5. 钱包与账单关联 现有 `BusinessFeeSourceChangedV1` 保留为被替换的旧目标,不新增双协议兼容。阶段 0 直接收敛到新版本事件,建议逻辑载荷名为 `BusinessFeeSourceCommandV2`,事件动作:
钱包命令新增 `chargeIdentity`、`sourceFeeId`、`sourceVersion`、`walletPlanId`、`walletPlanVersion`、`allocationId`。冻结、结算、释放均以 `allocationId` 幂等;禁止仅按业务类型、业务单号和金额猜测关联。 - `PUBLISH`:首次发布一个候选版本;
- `REPLACE`:申请替代当前有效版本;
- `VOID`:申请作废当前有效版本。
柜级费用先按真实客户/订单形成分摊明细,再分别产生收费身份和钱包分配;退货按票、仓租按期间/仓库、配送按票分别生成身份,不复用订单主单号充当费用键。 命令必须携带:
## 6. 场景接入约束 ```text
commandId
identityKey
sourceFeeId
targetVersion
expectedActiveVersion 首次发布显式为空
action
sourceSnapshot
sourceHash
requestedAt
```
- **Relabel**:所有完成入口调用同一应用服务;一次业务收费身份只允许一个当前版本。 `sourceSnapshot` 继续沿用现有完整客户、业务、方向、供应商、付款、币种、数量、期间和审核快照。Finance 不跨区回查 Lastleg。
- **Destuff**:按实际客户 CBM 分摊;客户应收与供应商应付分开建身份,禁止直接写 APPROVED/PUBLISHED 绕过命令。
- **Delivery**:每票每收费项独立身份;收款方与付款方分离,手工金额进入待审。
- **Return**:按票计费,退货收货完成才结束计费;迟到实收只能生成新版本/调整记录。
- **Warehouse rent**:按仓库、库位/货主、计费期间和计费规则生成期间身份,不能伪造入仓码。
## 7. 阶段 0 开发门禁 ### 4.2 Finance 结果事件
开始改代码前必须完成并评审: Finance 在同一事务完成校验、来源写入/变更裁决和结果 Outbox,向海外发送 `BusinessFeeSourceResultV2`:
1. V2 事件 DTO、事件类型、Gateway 路由、OpenAPI、权限码和跨区 Outbox/Inbox 位置; ```text
2. Lastleg 来源表与 Finance 来源表的字段/索引/状态迁移设计; commandId
3. 钱包计划及分摊表的唯一键与幂等键; identityKey
4. Relabel、Destuff、Delivery 的生产入口清单和漏发测试用例; result ACCEPTED / REJECTED
5. 拒绝、重试、迟到实收、旧版本已结算等异常验收用例。 acceptedSourceFeeId
acceptedSourceVersion
activeSourceVersion
errorCode
errorMessage
processedAt
```
实现后必须定向运行 DTO/事件/服务测试、`node scripts/gateway-route-contract.test.mjs`,若有 Mapper 变更再运行 `node scripts/mapper-scan-contract.mjs`。本阶段不执行部署和真实 HTTP 验收。 规则:
## 8. 代码入口 - 同 `commandId + payloadHash` 重放返回原结果;同命令异载荷拒绝。
- `expectedActiveVersion` 不等于 Finance 当前有效版本时拒绝,不回退当前有效版本。
- `ACCEPTED` 才能让海外候选变为有效版本;`REJECTED` 只关闭该候选命令,不删除事实。
- 超时和网络失败保持 `PENDING_FINANCE`,不能标记成功或拒绝。
- 结果回传失败不改变 Finance 已接受状态;海外重试同一结果事件。
- Event Bridge 只负责路由和投递,不把“已转发”当作 Finance 已接受。
- 事件模型:`baiyue-firstleg/common-event-contract/` ## 五、资金计划版本
- 海外来源服务:`baiyue-firstleg/lastleg-service/.../financefee/`
- Finance 消费:`baiyue-firstleg/finance/.../BusinessFeeSourceEventService.java` 费用来源与资金冻结不能再通过“业务类型 + 业务单号 + 金额”模糊关联。
- Relabel:`baiyue-firstleg/lastleg-service/.../relabel/`
- Delivery:`baiyue-firstleg/lastleg-service/.../delivery/` ### 5.1 计划模型
- Destuff:`baiyue-firstleg/lastleg-service/.../inboundplan/`
资金计划逻辑字段:
```text
planId
planVersion
identityKey
customerId
amountCny
status PENDING / FROZEN / SETTLE_PENDING / SETTLED / RELEASE_PENDING / RELEASED / FAILED
sourceAllocations[] sourceFeeId + sourceVersion + amountCny
```
一笔计划可以分配多笔来源,但所有分配金额之和必须等于计划金额;一份来源版本只能被该计划消费一次。计划金额、身份和版本一旦冻结,不允许先改费用再等待来源到达。
### 5.2 指令规则
资金命令至少携带 `planId + planVersion + operation + identityKey + amountSnapshot`。`SETTLE` 先到时,Finance 持久化等待;只有目标来源全部接受、分配完整且金额守恒后才扣款。`RELEASE` 结果未知时保持锁定,不允许同时建立新计划。
旧计划释放后收到迟到 `SETTLE`,只能访问旧计划并返回拒绝,不能按业务单号找到新计划执行扣款。计划 ID 不复用。
## 六、业务链路修复要求
### 6.1 换标
- 统一所有合法完成分支进入一个费用/资金编排入口。
- `RELABEL_SERVICE` 保持现有费用编码,不新增同义 `RELABEL_FEE`。
- 费用发布、资金结算和业务完成各自幂等;纯 SKU、需要出库和退货换标路径都必须覆盖。
- Finance 接受前允许业务保持原有效候选;资金结算必须绑定计划版本和已接受来源版本。
### 6.2 拆柜打托
- 保留全柜成本总额和客户分摊守恒;每客户分摊来源拥有稳定收费身份。
- 不再手工直接插入“已审核已发布”绕过通用服务;自动审核必须来自获批规则,调整和作废复用统一命令。
- 首版继续 `DESTUFF_PALLET` 与 `OVERSEAS_CONTAINER` 业务身份,但应在通用校验中明确允许该组合,避免项目编码与调整校验不一致。
- 当前仅自动客户应收;供应商成本属于后续阶段,不能伪造应付。
### 6.3 派送
- 同一派送业务允许一条客户应收和一条供应商应付,但两者身份、价格、供应商和结算方式独立。
- 人工金额默认进入 `PENDING`,不能在转派送动作中自动审核。
- 业务日期使用真实费用触发日期,不使用无关任务执行时刻作为历史补价日期。
- `DIRECT_PAID` 必须有付款时间、方式、流水号或凭证,并由 Finance 形成已确认成本;`ON_ACCOUNT` 进入应付。
### 6.4 业务费用查询
业务详情查询按稳定关系聚合订单、入仓、柜、派送、换标和退货来源;返回:
- 当前 Finance 接受的有效版本;
- 待 Finance 确认的候选/变更;
- 被拒绝、超时、待资金、已结算和已作废结果;
- 共享费用的分摊金额,不重复计入多个订单小计。
Finance 尚未接受的来源必须能从海外异常入口查询,不能以 Finance 费用池没有记录作为“未生成”的唯一判断。
## 七、ID、供应商和事件边界
- 跨端 DTO 和事件中的仓库、供应商、客户、业务 ID 使用十进制字符串;领域层严格解析,禁止使用名称或 FBA 目的仓代码替代主档 ID。
- Lastleg 报价仓、实际作业仓、库存仓引用同一国内 Warehouse 主档 ID;`providerName` 只能是快照,不能作为供应商身份。
- 供应商成本来源必须通过 Warehouse 校验启用状态和类别;Finance 再次失败关闭校验。
- 事件载荷不携带用户 JWT,不跨区域回查数据库;生产者、Event Bridge、Finance、结果消费者和测试必须同步升级。
## 八、开发与验证门禁
### 8.1 0A 开工前
开发先提交以下技术设计并在代码中一次性收敛:
1. 收费身份、候选版本、当前有效版本和唯一约束;
2. `BusinessFeeSourceCommandV2` / `BusinessFeeSourceResultV2` 事件 DTO、事件类型和双向路由;
3. 资金计划、分配表、计划版本和 V2 指令事件;
4. 仓库/供应商 ID 与业务场景枚举校验;
5. Lastleg、Finance、Event Bridge 的锁顺序、Outbox/Inbox 和拒绝重试分类。
### 8.2 阶段验证
- 0A:换标四类完成路径、拆柜分摊守恒、派送应收/应付和人工审核。
- 0B:草稿驳回修改、统一待审查询、业务聚合和直付证据。
- 0C:Finance 接受、拒绝、超时、乱序、重放、前序版本冲突和来源冻结。
- 0D:冻结/结算/释放乱序、计划版本隔离、来源分配守恒、旧指令拒绝。
- 0E:减免接受、减免拒绝、自动重算暂停、取消收费和待财务处理。
跨服务修改至少运行公共事件契约、Lastleg、Finance、Event Bridge 直接消费者测试,并执行 `node scripts/mapper-scan-contract.mjs`、`node --test scripts/gateway-route-contract.test.mjs`;未经明确环境授权不启动服务、不执行真实 HTTP、不部署。
## 九、代码入口
- 海外费用来源:`baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/financefee/`
- Finance 海外费用消费:`baiyue-firstleg/finance/src/main/java/com/baiyue/finance/service/BusinessFeeSourceEventService.java`
- 资金事件:`baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/WalletCommandRequestedV1.java`、`WalletCommandCompletedV1.java`
- 资金生产/消费:`baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/wallet/`、`baiyue-firstleg/finance/src/main/java/com/baiyue/finance/service/WalletCommandEventService.java`
- 换标:`baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/service/RelabelApplicationService.java`
- 派送:`baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java`
- 拆柜打托:`baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/DestuffingPalletCostService.java`
- 业务费用来源表:`lastleg-service/src/main/resources/db/lastleg.sql` 的 `ll_finance_fee_source`;Finance 表:`finance/src/main/resources/db/finance.sql` 的 `fin_fee_source`、`fin_wallet_hold`、`fin_wallet_command_inbox`
本文是 V0.5 的技术落地门禁;与 V0.5 方案冲突时,以当前对话确认和 V0.5 方案为准。
@@ -123,6 +123,16 @@ Finance 不以当前查询结果覆盖已保存快照。查询超时、5xx 或
## 7. 错误码与响应语义 ## 7. 错误码与响应语义
### 资金指令消费可靠性(2026-09-29)
`WalletCommandRequested` 先独立提交 eventId/hash 身份记录,再在处理事务使用 Inbox 行锁重新校验 hash;相同 ID 不同 hash 即使并发到达也不能执行钱包。资金变更、成功 Inbox 结果和结果 Outbox 同事务提交,任何结果写入失败均回滚资金变更,原事件保留身份并允许重试。
仅 `FIN-WALLET-INSUFFICIENT`、`FIN-WALLET-HOLD-409`、`FIN-IDEMPOTENCY-CONFLICT`、`FIN-REQ-400` 作为明确业务拒绝,在原事务回滚后重新锁定事件、确认无既有最终结果,再保存 FAILED 与结果 Outbox。临时数据库异常、处理中、乐观锁冲突、冻结依赖未到达及其他未分类异常继续抛出,不确认消费成功,不固化为最终业务失败。传输确认仍不等于资金业务成功,Lastleg 继续消费资金结果事件。
本条是当前消费者实现规则;单机去桥目标及统一 ACK 见[统一认证与服务通信契约](../统一认证与服务通信契约.md),后者尚未整体落地。
### 通用响应
错误码是跨服务稳定字符串,message 可本地化且不能作为程序判断依据: 错误码是跨服务稳定字符串,message 可本地化且不能作为程序判断依据:
| 错误码 | 语义 | 是否重试 | | 错误码 | 语义 | 是否重试 |
+3 -53
View File
@@ -1,55 +1,5 @@
# 跨区域认证与服务通信契约 # 跨区域认证与服务通信契约(已替代)
## 适用范围 自 2026-09-29 起,当前目标仅有一个测试环境,服务同机部署。旧双区域认证、独立海外网关及事件桥约束已由[统一认证与服务通信契约](统一认证与服务通信契约.md)替代;部署与切换见[测试环境单机部署与配置契约](测试环境单机部署与配置契约.md)。
- 本契约适用于 Admin、Client、国内头程服务、海外网关、尾程服务、海外仓资源服务及跨区域事件桥接。 此文件仅保留旧链接入口,不再定义有效规则。目标已确认不代表当前代码和环境已经迁移完成。
- 业务范围仍按对应阶段和模块文档确定;本文件只冻结跨区域账号、请求路由、服务鉴权和事件通信边界。
- 开发/测试同机共置及生产国内/海外双控制面的实际部署拓扑、Nacos、数据库和 Event Bridge 规划见[双区域部署与 Nacos 规划](双区域部署与Nacos规划.md)。
## 统一账号与 Token
- Admin、Client 只维护一套前端和一套用户账号体系;用户登录和 Token 签发统一归国内头程 Auth,不得为海外仓再创建独立登录、账号或权限体系。
- 统一使用 RS256/JWKS 信任链,但区分 Token 用途:国内登录/刷新时由同一 Auth 同时签发国内 Token 和短时海外 Token;海外 Token 限定海外 Audience,只携带稳定身份、客户范围与版本声明,不携带角色或权限集。
- 平台 `WAREHOUSE_PICKER` 必须在 IAM 成员关系中绑定一个启用的实际海外收货仓;Auth 将该绑定以可空 `overseas_warehouse_id` Claim 同步写入国内与海外 Token,海外 Token 同时携带账号 `token_version`。该 Claim 只用于已绑定的平台仓管员,页面和 PDA 请求不得传入或覆盖仓库身份;修改或清空仓绑定时 IAM 必须调用 Auth 撤销该账号全部会话并递增 `token_version`,随后重新签发 Token。
- 用户只登录一次,由前端统一认证模块按目标 API 自动选择 Token,不在页面或业务模块中分叉登录逻辑。
- JWKS 只暴露公钥验证能力,不暴露私钥;国内服务验证登录 Token 并结合 Redis 会话实现即时退出和权限变更,海外业务服务不访问国内 Redis。`gateway-overseas` 对普通 Admin/Client 海外接口验证海外 Token 的签名、Issuer、Audience、有效期、应用域和客户范围,再按 `userId/tenantId/permissionVersion` 从 Lastleg 安全投影取得当前海外授权快照;仅 `/api/pda/**` 在本地验签后,以内部服务身份向 Auth 发送 `userId/tokenVersion/overseasWarehouseId` 做无缓存实时核对。该调用不得传递 raw Token 或用户凭据,Auth 超时、不可用、账号停用、版本或仓绑定不一致均 fail-closed。
- 本期普通 Admin/Client 海外 Token 的即时失效范围固定为 IAM 投影的账号停用、客户停用和权限版本推进;Gateway 向 Lastleg 安全投影仅发送 `userId/tenantId/permissionVersion`,旧 Token 被拒绝后客户端必须退出并重新登录。`token_version` 仍是海外 JWT 必填 Claim,但其权威实时比对只用于上述 PDA→Auth 链;普通 Admin/Client 的退出、密码重置或普通会话撤销依赖短时 Token 自然过期,不得宣称已由 Lastleg 即时撤销。
## 区域 API 路由
- 一套前端使用国内、海外两个区域 API Base:国内业务直连 `gateway/`,海外仓业务直连 `gateway-overseas/`,再由海外网关路由到 `lastleg-service/`、`warehouse-overseas-service/` 和海外部署的公共服务。
- 日常海外请求不得经国内 Gateway 中转。区域地址、Token 选择和刷新由环境配置与统一 API/认证层处理,业务页面不得感知部署区域差异。
- 海外浏览器请求的具体 Audience、Claim 和路由以前端项目、`auth/`、`gateway-overseas/` 最近的 `AGENTS.md` 与实际配置为准;修改其中任一项时必须联查全部生产者和消费者。
## 跨区域事件与服务身份
- 头程与海外仓的数据流转使用 MQ 的 Outbox → Inbox、事件幂等、重试和死信机制。
- 事件使用版本化信封、事件 ID、业务键、来源/目标区域和 Payload 哈希,不携带用户 Access Token。
- 费用由海外仓发布事件,头程 Finance 消费并按来源快照入账;财务状态机和结算口径仍由财务契约冻结,海外服务不得自行定义。
- MQ 使用独立的服务身份、TLS 和 ACL;服务间事件鉴权与用户 JWT 鉴权分开。只有明确的同步 HTTP 内部接口才使用内部服务令牌。
- 修改事件时联查 `common-event-contract/`、`event-bridge-service/`、生产服务、消费服务、幂等记录、重试/死信和契约测试。
- 按 FBA 仓拆分的海外派送单在签收完成时,由 Lastleg 在同一事务按关联来源入仓单分别写 `OverseasDeliveryCompleted` V1 Outbox;Event Bridge 定向投递 Firstleg。Firstleg 校验事件信封、客户、来源入仓单/订单、入仓码和 FBA 仓后,只将该来源入仓单从 `LOADED` 推进到 `DELIVERED`;同一 Order 的全部有效入仓单均为 `DELIVERED` 后,才以内部服务身份幂等推进该 Order 到 `COMPLETED`。同车其他 FBA 派送单必须各自签收,不得随整车一起完成。
### 国内仓库目录同步读取
- 国内 `warehouse-service` 是 Warehouse ID、类型、状态、地址和能力的唯一权威。海外数据库不得复制仓库、地址或服务能力主表。
- `warehouse-overseas-service` 只保存库位、托盘、资源锁及其国内 `warehouseId` 引用;资源写入和 Lastleg PDA 仓绑定校验通过受内部服务令牌保护的国内只读目录完成。
- 只允许平台共享、`OVERSEAS`、`ACTIVE` 且启用 `RECEIVING` 的仓作为海外实际收货仓。低频正结果可缓存 30 分钟,空目录、不存在和停用结果不得长缓存。
- FBA 目的仓同样只以国内 `warehouse-service` 的平台公共主数据为权威,但语义与海外实际收货仓严格分离:Admin 候选使用 `warehouseType=FBA&status=ACTIVE` 的平台仓库分页;Lastleg 写入通过受内部服务令牌保护的 `/internal/warehouses/0/{warehouseId}/active` 读取当前事实,并继续校验 `warehouseType=FBA` 及 ID/编码/名称一致。`OVERSEAS`、`OVERSEAS_PARTNER` 或 `DOMESTIC` 均不得作为 FBA 目的仓。
### IAM 安全事件海外投影冻结
- `IamUserStatusChanged`、`IamTenantStatusChanged`、`IamPermissionVersionChanged` V1 固定由 Lastleg 独立安全入口 `/internal/lastleg/security/v1/events` 消费;不得投递到 Lastleg 的 LoadingCompletedConsumer。
- 安全状态只使用 `ACTIVE`/`DISABLED`:`IamTenantStatusChanged` 仅在 IAM 客户业务状态为 `ACTIVE` 时发布 `ACTIVE`,`PROFILE_REQUIRED`、`PENDING`、`REJECTED`、`DISABLED`、`ARCHIVED` 及其他不可用状态统一折叠为 `DISABLED`。Lastleg 只校验该两态安全快照,不解释国内建档/审核工作流。
- Event Bridge 只按冻结的 eventType→consumer URL 选择下游,不解析状态、权限版本或 payload 业务字段。海外业务事件仍投 Lastleg,国内回流事件仍投 Firstleg。
- Lastleg 以 MySQL `ll_security_event_inbox` 和 `ll_security_projection` 为可靠来源:eventId 相同 hash 相同幂等,异 hash 冲突;聚合版本只单调推进,旧版本标记 STALE,同版本异 hash 冲突。Redis 仅为提交后写入的可重建镜像,授权校验不依赖 Redis 默认放行。
- 海外 Gateway 对全部 `/api/**` 在本地 JWT 验签后,传递 `userId/tenantId/permissionVersion` 到 Lastleg 安全入口。Lastleg 校验通过时返回该版本的角色与海外权限快照,Gateway 清除外部伪造的授权头后,以内部服务令牌保护的可信头传给海外业务服务。业务服务必须同时验证 JWT 和内部服务令牌,不得从 JWT 回退读取完整权限集。用户停用返回 A0401;客户停用或 Token 权限版本不一致返回 A0403;安全投影、SQL 或调用链不可用均 fail-closed。PDA 在此基础上继续执行 Auth 仓绑定实时核验。
- Auth 的登录、刷新和海外 Token 兑换响应在响应体中返回当前 `roles/authorities` 授权快照;国内与海外 JWT 都只保留主体、客户、成员、应用、版本和海外仓绑定等最小身份 Claim,不携带角色或权限集合。客户端可用响应快照做入口展示或本地前置提示,但每次业务请求的最终授权仍由 Gateway/Lastleg 的实时投影决定;客户端不得再从 JWT 解析角色或权限,也不得把响应快照作为绕过服务端校验的依据。
- 新客户创建、审核激活以及新用户授权均由 IAM 在业务事务内写初始安全事件。开发阶段不提供历史账号长期 Bootstrap 或兼容入口;固定 `platform_admin` 由 Lastleg 数据库基线初始化 version=0 的 USER/AUTHORIZATION 投影,其中 AUTHORIZATION 冻结当前 `PLATFORM_ADMIN` 角色及 IAM 跨区前缀下的完整权限集合,空库重建后无需人工补投即可访问海外接口,后续 version>=1 的真实 IAM 事件单调覆盖。其他既有开发账号仍须由总控按 IAM 当前事实一次性重建授权快照;任何缺失投影继续 fail-closed,不能在 Lastleg 运行时代填或默认放行。
## 修改与验收
- Token、Audience、Claim、JWKS、API Base 或刷新策略变化时,至少联查 Auth、IAM、Admin/Client 统一认证层、国内/海外 Gateway、`common-security/` 和目标海外服务。
- `overseas_warehouse_id` 变化时还需联查 IAM 平台用户维护、海外 PDA、Lastleg 收货会话及 Warehouse Overseas 共享仓校验;验收必须同时覆盖未绑定拒绝、非仓管角色禁止绑定和换仓后旧 Token 失效。
- 跨区域事件变化时同步检查事件版本、Payload 哈希、Outbox、Inbox、重复投递、失败重试、死信和全部实际消费者。
- 本文件是跨区域通信的公共事实来源;项目和模块 `AGENTS.md` 只保留执行所需摘要及本文件入口,不复制完整协议。
-123
View File
@@ -1,123 +0,0 @@
# 领星新品测量接口联调说明
## 范围
墨家上传的 `boxCode` 不包含 `#` 时,Firstleg 将它作为 SKU 测量收件记录保存;带 `#` 的箱唛继续使用原箱唛测量流程。SKU 记录默认只保存,不自动修改领星,是否自动推送由 Nacos 配置控制。
领星账号使用独立浏览器容器和独立 profile,不复用其他 Node.js 账号或浏览器会话。
## 领星查询
请求:
```http
POST https://wms.xlwms.com/gateway/wms/newProduct/page
Content-Type: application/json
```
请求体:
```json
{
"barcode": "A120133-A-TK",
"current": 1,
"customerCode": "",
"keyword": "A120133-A-TK",
"multiKeyword": "",
"searchType": "barcode",
"size": 20,
"whCode": "US01"
}
```
系统按 `US01`、`US02` 分别查询,并只接受 `productSku` 或 `barcode` 精确等于请求 SKU 的记录。查询结果中的 `maintained=1` 表示该仓库已经维护过,不能再次提交。
## 领星测量
请求:
```http
POST https://wms.xlwms.com/gateway/wms/newProduct/measure
Content-Type: application/json
```
Java 会以查询返回的整条商品记录为基础,仅替换墨家测量值。请求中的单位字段必须区分:
| 字段 | 值 | 含义 |
| --- | --- | --- |
| `sizeUnit` | `in` | 领星原商品尺寸展示单位 |
| `length`/`width`/`height` | 查询原值 | 原商品申报尺寸 |
| `lengthBs`/`widthBs`/`heightBs` | 查询原值 | 原商品英寸换算值 |
| `wmsSizeUnit` | `cm` | 本次维护尺寸单位 |
| `wmsLength`/`wmsWidth`/`wmsHeight` | 墨家厘米值 | 本次维护尺寸 |
| `wmsLengthBs`/`wmsWidthBs`/`wmsHeightBs` | 厘米 ÷ 2.54 | 本次维护英寸换算值 |
| `weightUnit` | `lb` | 领星原商品重量展示单位 |
| `wmsWeightUnit` | `kg` | 本次维护重量单位 |
| `wmsWeight` | 墨家千克值 | 本次维护重量 |
| `wmsWeightBs` | 千克 × 2.2046226218 | 本次维护磅换算值 |
示例中的维护字段如下:
```json
{
"wmsLength": "24.5",
"wmsLengthBs": "9.646",
"wmsWidth": "18.5",
"wmsWidthBs": "7.283",
"wmsHeight": "5",
"wmsHeightBs": "1.969",
"wmsSizeUnit": "cm",
"wmsWeight": "0.15",
"wmsWeightBs": "0.331",
"wmsWeightUnit": "kg"
}
```
接口返回 `code=200` 才视为提交成功。HTTP 401 或领星业务码表示登录失效时,Java 清理缓存并自动重新登录后重试一次;其他失败记录为同步失败,不自动无限重试。
## 登录和二次验证
浏览器页地址为 `https://wms.xlwms.com/login`。Java 通过 CDP 操作独立浏览器页面:
- 账号:`input[name="username"]`
- 密码:`input[name="password"]`
- 登录:`.login-btn`
- 腾讯安全验证容器:`#captchaId`(仅在可见挑战出现时转人工处理)
- 短信/邮箱验证码:`input[placeholder="输入验证码"]`
- TOTP 验证码:`input.verification-code-native`
- 短信/邮箱获取验证码:`.verify-code-login .code-btn`
- 验证登录:`.verify-code-login .login-btn`
检测到二次验证页面后,Java 立即为短信/邮箱渠道点击获取验证码;用户在后台输入收到的验证码后,Java 只提交验证码,不会再次发送。TOTP 由领星页面自动初始化。腾讯安全滑块属于人工安全验证,必须通过 noVNC 完成,Java 不绕过该验证。
账号、密码和主登录按钮选择器已根据 `https://wms.xlwms.com/login` 页面源码及登录脚本核对;短信/邮箱和 TOTP 二次验证输入选择器也已确认。验证码错误或过期等业务结果仍需以真实运行时返回为准。
## Nacos 配置
开发环境默认关闭自动推送:
```yaml
firstleg:
lingxing:
auto-sync-enabled: false
base-url: https://wms.xlwms.com
login-origin: https://wms.xlwms.com
browser-cdp-endpoint: http://lingxing-browser:9222
username: ${LINGXING_USERNAME}
password: ${LINGXING_PASSWORD}
track-key-v2-secret-base64: ${LINGXING_TRACK_KEY_V2_SECRET_BASE64}
warehouses: [US01, US02]
```
`lingxing-browser` 和 Java Firstleg 必须加入同一个 Docker 网络(开发部署脚本默认是 `firstleg-development-network`)。noVNC 只绑定服务器回环地址,远程人工处理安全滑块时使用 SSH 本地端口转发。账号、密码、Cookie、Token 和 Track-Key 密钥不得写入仓库或提交到 Git。
Track-Key 密钥按参考实现只做一次 Base64 解码,Java 不限制解码后的固定字节长度;只要密钥非空且与 Node 实际使用的 keyBytes 相同即可。
## 验收步骤
1. 启动独立浏览器容器并确认 `http://lingxing-browser:9222/json/version` 可从 Java 容器访问。
2. 保持 `auto-sync-enabled=false`,进入后台“SKU同步”页面,输入 SKU,点击“测试连接”。
3. 首次触发二次验证时,在后台输入验证码,确认原查询自动继续,并返回 `US01`、`US02` 结果。
4. 对 `maintained=0` 的记录点击“人工推送”,确认领星返回 `code=200`。
5. 再次查询同一 SKU,确认已维护记录不会重复提交。
6. 将 `auto-sync-enabled` 改为 `true` 后重新上传不带 `#` 的 SKU,确认入库后自动推送;失败记录可在页面人工重新推送。