This commit is contained in:
2026-08-11 18:06:30 +08:00
parent 863f9ca395
commit 767ffe8544
16 changed files with 1765 additions and 184 deletions
+2 -1
View File
@@ -7,11 +7,12 @@
- [一期文档](一期/README.md):一期范围、开发进度和头程订单最小闭环。 - [一期文档](一期/README.md):一期范围、开发进度和头程订单最小闭环。
- [二期文档](二期/README.md):预约取货、到仓收货、实测差异和指定库位闭环。 - [二期文档](二期/README.md):预约取货、到仓收货、实测差异和指定库位闭环。
- [三期文档](三期/README.md):智能排柜、订舱、拖车、PDA 拣货、报关协同和国内出仓闭环。 - [三期文档](三期/README.md):智能排柜、订舱、拖车、PDA 拣货、报关协同和国内出仓闭环。
- [独立任务协作登记](独立任务协作登记.md):登记独立 Codex 任务 ID,并作为总控下发、通信和汇总的唯一寻址索引。 - [独立任务协作登记](独立任务协作登记.md):以稳定 `routing_key + task_id` 维护长期复用通道,并保留一次性任务执行历史。
## 跨阶段参考 ## 跨阶段参考
- [财务管理闭环盘点与范围建议](财务管理/README.md):基于当前入库计费、财务原型和现有代码盘点财务闭环、缺口及建议的首期应收边界。 - [财务管理闭环盘点与范围建议](财务管理/README.md):基于当前入库计费、财务原型和现有代码盘点财务闭环、缺口及建议的首期应收边界。
- [数据库中文注释维护规范](数据库注释维护规范.md):数据库注释口径、职责、迁移流程、自动门禁与实值验收要求。
- [测试环境 Jenkins 部署指南](测试环境Jenkins部署指南.md):测试环境持续部署授权、Job 参数、执行边界、健康检查与失败处理。 - [测试环境 Jenkins 部署指南](测试环境Jenkins部署指南.md):测试环境持续部署授权、Job 参数、执行边界、健康检查与失败处理。
- `悦/`:产品原型、流程图、历史架构资料和调研数据,仅作为需求参考,不直接等同于已确认范围。 - `悦/`:产品原型、流程图、历史架构资料和调研数据,仅作为需求参考,不直接等同于已确认范围。
- `superpowers/`:具体功能的设计与实施记录,按日期和主题维护。 - `superpowers/`:具体功能的设计与实施记录,按日期和主题维护。
+96
View File
@@ -0,0 +1,96 @@
# 数据库中文注释维护规范
## 目标与适用范围
本规范适用于 `baiyue-firstleg/` 各服务拥有的 MySQL 业务表。目标是让表和字段语义可以直接从数据库元数据理解,并通过自动检查防止新增无注释结构。
SQL 是数据库结构和注释的事实来源。数据字典应从 `information_schema` 生成,不维护 Excel、Markdown 字段清单等并行事实来源。
## 职责
- 数据库注释总控:维护本规范、统一术语、审计整体覆盖率、协调统一部署 SQL,并完成最终验收。
- 模块负责人:依据 Controller、DTO、Service、状态机和已确认需求解释本模块字段,维护模块 SQL。
- 业务审核人:确认状态、金额、时间、快照、审计和数据隔离字段的业务口径。
- 发布执行人:按发布规范执行已审核的幂等迁移;未经当前对话授权不得直接修改测试、预发布或生产数据库。
## 必须遵守的规则
1. 每张业务表和每个业务字段都必须有非空中文注释。
2. 英文缩写和枚举值可以保留,但注释必须包含中文业务含义。
3. 模块 `src/main/resources/db/`、统一部署 SQL 和实际数据库的注释必须一致。
4. 同一张表在基线与迁移脚本中重复定义时,每个可执行定义都必须有完整注释。
5. 注释变更不得改变字段类型、长度、精度、字符集、默认值、可空性、索引或约束。
6. `CREATE TABLE IF NOT EXISTS` 不会更新存量表注释;存量环境必须使用可重复执行的兼容迁移。
7. 注释不得写密钥、令牌、客户真实数据、环境地址或其他敏感值。
## 中文口径
| 字段类型 | 注释要求 | 示例 |
|---|---|---|
| `tenant_id` | 客户数据统一说明客户与隔离语义;公共数据明确平台作用域 | `客户ID和数据隔离键`;`平台公共数据作用域,固定为0` |
| 状态 | 列出允许值及每个值的中文含义 | `状态:DRAFT草稿、ISSUED已出账、PAID已收清` |
| 金额 | 说明金额口径、币种来源,必要时说明含税口径 | `账单含税总金额;币种由currency_code指定` |
| 时间 | 说明事件语义,不只写“时间” | `财务确认实际收款时间` |
| JSON | 说明结构、元素类型、来源及敏感性 | `File服务文件ID字符串数组` |
| 快照 | 说明来源和是否随源数据回写 | `创建账单时的客户名称快照;客户档案变化不回写` |
| 布尔值 | 明确 `0` 和 `1` 的含义 | `尾差归集标记:0否、1是` |
| ID | 说明关联对象和逻辑属性 | `Firstleg入库单逻辑ID,不建立跨库外键` |
| 版本 | 说明版本用途 | `乐观锁版本号,每次更新递增` |
| 审计 | 区分业务操作人、系统创建人和链路标识 | `执行本次业务操作的平台用户ID` |
不要把 `tenant_id` 用户可见地解释为“租户”。当前产品只有“平台、客户”两级,后端兼容字段不能扩展产品层级。
## 变更流程
1. 盘点模块 SQL 中缺失、空白或纯英文注释。
2. 根据需求确认文档和真实代码确认字段语义;不凭字段名猜测高风险业务口径。
3. 先更新模块 SQL,再由总控同步统一部署 SQL。
4. 为存量环境编写幂等注释迁移。MySQL `MODIFY COLUMN` 必须完整复述原类型、默认值、可空性及其他属性。
5. 对比迁移前后 `information_schema.columns`,除 `column_comment` 外的结构签名必须完全一致。
6. 运行静态审计、模块测试、统一 SQL 空库与重复执行验证。
7. 从实际数据库元数据生成数据字典和覆盖率报告。
## 自动审计
在 `baiyue-firstleg` 根目录执行:
```powershell
.\scripts\database-comment-audit.ps1
.\scripts\database-comment-audit.ps1 -Modules finance,order
.\scripts\database-comment-audit.ps1 -Modules finance -SummaryOnly
.\scripts\database-comment-audit.ps1 -Format Json
.\scripts\database-comment-audit.ps1 -FailOnIssues
.\scripts\database-comment-audit.ps1 -SelfTest
```
脚本只读取模块 `src/main/resources/db/*.sql`,不连接数据库、不启动服务、不执行 SQL。默认输出报告且退出码为 `0`;CI 使用 `-FailOnIssues`,发现缺失或纯英文注释时退出码为 `1`;配置或路径错误退出码为 `2`。
当前存量缺口允许通过不带 `-FailOnIssues` 的报告模式逐模块治理。模块达到 100% 后,应在其 CI 中启用强制门禁,禁止覆盖率回退。
## 数据库实值验收
部署后使用只读元数据查询验收:
```sql
SELECT table_schema, table_name, table_comment
FROM information_schema.tables
WHERE table_schema LIKE 'baiyue_%'
AND table_type = 'BASE TABLE'
ORDER BY table_schema, table_name;
SELECT table_schema, table_name, column_name, column_type, is_nullable,
column_default, extra, column_comment
FROM information_schema.columns
WHERE table_schema LIKE 'baiyue_%'
ORDER BY table_schema, table_name, ordinal_position;
```
数据字典以第二个查询为基础,可追加索引元数据;不得把生成文件改造成另一份手工契约。
## 验收门槛
- 目标模块表注释和字段中文注释覆盖率均为 100%。
- 模块 SQL、统一部署 SQL和数据库实值一致。
- 空库执行、存量升级和重复执行均通过。
- 注释迁移前后,除注释外的表结构零变化。
- 新增 SQL 在 CI 强制模式下通过。
+56 -15
View File
@@ -1,25 +1,42 @@
# 独立任务协作登记 # 独立任务协作登记
> 本表只登记用户可独立打开和查看的 Codex 任务/对话,不登记子代理。任务 ID 是唯一寻址键,名称只是展示标签。 > 本文件登记用户可独立打开和查看的 Codex 任务/对话,不登记子代理。长期复用通道负责创建前路由,执行历史只负责追溯;任务名称始终只是展示标签。
## 长期复用通道
总控下发独立工作前必须先查本表。`idle`、`active`、`blocked` 都表示通道可复用;只有 `archived` 表示不可继续下发。同一 `routing_key` 只能保留一个未归档任务。
| routing_key | task_id | display_name | durable_scope | owner | status | last_update | notes |
|---|---|---|---|---|---|---|---|
| `phase3.control.release-acceptance` | `019fdf57-2f16-7cf1-88f0-a75854ed7629` | 三期总控|发布与验收 | 三期发布、测试环境验收、阻断分类与最终汇总 | 三期总控 | idle | 2026-08-11 | 后续三期发布与验收优先向此 ID 续发;一次性复验或部署默认使用子代理 |
| `finance.control` | `019feaa3-9f10-7ab0-8023-4b121ff9662c` | 财务模块-总控 | 财务范围、跨端契约、后端/Admin/Client 协调与汇总 | 财务总控 | active | 2026-08-11 | Finance一期最终验收FAIL;正在协调11个一期P0 operation返工与独立复验 |
| `database-comments.control` | `019fef70-b644-7071-8b76-975b8940985c` | 数据库注释治理 | 数据库中文注释规范、模块分派、统一 SQL 集成与总体验收 | 数据库注释总控 | idle | 2026-08-11 | 后续数据库注释工作优先向此 ID 续发;模块盘点和修改默认使用子代理 |
### 通道路由规则
- `routing_key` 按长期职责确定,格式为 `<domain>.<unit>.<responsibility>`;不包含序号、日期、批次、提交号或本轮动作。
- 命中未归档通道后直接使用其 `task_id` 通信;标题相同或不同均不影响寻址。通道开始新一轮工作时改为 `active`,一轮工作结束后回到 `idle`。
- `completed` 只用于下方一次性执行历史,不是长期通道状态。长期通道不得因为一轮工作完成而失去复用资格。
- 用户未明确要求新增独立对话时,未命中通道也不自动创建;使用当前任务或子代理完成工作。
- 永久停用才标记 `archived`。创建替代通道时,在新旧记录备注中互相写明 ID,不覆盖或复用旧 ID。
## 登记规则 ## 登记规则
- 独立任务创建成功并获得平台返回的稳定 ID 后,立即登记;没有稳定 ID 不得写入临时名称或自行生成替代 ID。 - 下表只保存既有一次性任务和已结束轮次,不作为新任务的复用路由;可长期复用的任务必须同时登记到上方“长期复用通道”。
- 总控下发、追问、催办、读取、汇总和关闭任务时,一律使用 `task_id`/平台返回的任务 ID;不得根据任务名称、主题相似度或创建顺序寻址。 - 独立任务创建成功并获得平台返回的稳定 ID 后立即登记;没有稳定 ID 不得写入临时名称或自行生成替代 ID。
- 下发前先按范围、模块和状态检索本表;已有可复用任务时继续向该 ID 通信,不重复创建独立任务。 - 任务名称可以修改,`task_id` 不得复用、改写或转给另一项工作。历史任务完成后保留记录,不删除历史 ID。
- 任务名称可以修改,`task_id` 不得复用、改写或转给另一项工作。任务完成后保留记录并标记 `completed`,不要删除历史 ID。 - 跨任务共享契约由总控记录在备注中;独立任务回复必须带回自身 `task_id`、状态、变更文件、验证结果和阻断项。
- 跨任务共享契约由总控记录在登记表备注中;独立任务回复必须带回自身 `task_id`、状态、变更文件、验证结果和阻断项,便于按 ID 汇总。
## 状态值 ## 执行历史状态值
`planned`、`active`、`blocked`、`completed`、`archived`。 `planned`、`active`、`blocked`、`completed`、`archived`。
## 当前登记 ## 执行历史
| task_id | display_name | scope | owner | status | worktree/branch | last_update | notes | | task_id | display_name | scope | owner | status | worktree/branch | last_update | notes |
|---|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|---|
| 019feb17-b5de-7d63-a0e4-5a8c2181e323 | PDA 后端作业链收口 | `baiyue-firstleg/firstleg` PDA 拣货事务、原子批量提交和相关测试 | 三期总控 | completed | 后端 `test` | 2026-08-11 | `40171b7` 已推送;根因是 operation CHECK 未允许 BATCH,统一SQL与模块SQL已补幂等迁移;定向17/17、Firstleg 524项无失败 | | 019feb17-b5de-7d63-a0e4-5a8c2181e323 | PDA 后端作业链收口 | `baiyue-firstleg/firstleg` PDA 拣货事务、原子批量提交和相关测试 | 三期总控 | completed | 后端 `test` | 2026-08-11 | `40171b7` 已推送;根因是 operation CHECK 未允许 BATCH,统一SQL与模块SQL已补幂等迁移;定向17/17、Firstleg 524项无失败 |
| 019feb17-c56c-7e02-8f9c-0b74f960df34 | 三期验收 fixture 审计 | `baiyue-firstleg/scripts/admin-test-env-modules` | 三期总控 | active | 后端 `test` | 2026-08-11 | `fe0f166` 已完成状态映射;继续在同一职责内收口 customs 对新单余量“来源分片承载”模型的断言 | | 019feb17-c56c-7e02-8f9c-0b74f960df34 | 三期验收 fixture 审计 | `baiyue-firstleg/scripts/admin-test-env-modules` | 三期总控 | completed | 后端 `test` | 2026-08-11 | `df0f05c`已推送:修正customs同一来源fixture配对及loading-finalize失败后误标LOADED;4/4契约测试通过,仅脚本无需部署 |
| 019feb17-d3c2-7480-802a-498db11c7d3c | Admin 装柜工作流页面 | `apps/admin-web` 统一订单、智能装柜、预装清单、装柜清单、证据与完成入口 | 三期总控 | completed | Admin `release/test` | 2026-08-11 | 装柜`9b99404`、服务中心接线`17d483b`、出仓空态`af30c0c`均已部署;103 files/535 tests、typecheck/build、浏览器真实页面通过 | | 019feb17-d3c2-7480-802a-498db11c7d3c | Admin 装柜工作流页面 | `apps/admin-web` 统一订单、智能装柜、预装清单、装柜清单、证据与完成入口 | 三期总控 | completed | Admin `release/test` | 2026-08-11 | 装柜`9b99404`、服务中心接线`17d483b`、出仓空态`af30c0c`均已部署;103 files/535 tests、typecheck/build、浏览器真实页面通过 |
| 019feb2a-419b-7161-8174-5aed7e84a047 | PDA 原子批量提交契约 | PDA 后端 Controller/DTO/OpenAPI/调用方只读契约梳理 | 三期总控 | completed | 后端 `test` | 2026-08-10 | 只读阶段完成;等待 S0500 修复后进入实现 | | 019feb2a-419b-7161-8174-5aed7e84a047 | PDA 原子批量提交契约 | PDA 后端 Controller/DTO/OpenAPI/调用方只读契约梳理 | 三期总控 | completed | 后端 `test` | 2026-08-10 | 只读阶段完成;等待 S0500 修复后进入实现 |
| 019feb29-ef52-7f83-96d7-42d963d2ae34 | PDA uni-app 前端验收 | `apps/pda-uniapp` 登录、领取、广播扫码、设备草稿、批量提交、证据和真实 API 映射 | 三期总控 | completed | PDA `release/test` | 2026-08-11 | 功能提交`be776c8`已推送,远端`f83a0c4`;43/43 PASS,A0409刷新和失败回滚已验证;HBuilderX/Android真机仍为最终gap | | 019feb29-ef52-7f83-96d7-42d963d2ae34 | PDA uni-app 前端验收 | `apps/pda-uniapp` 登录、领取、广播扫码、设备草稿、批量提交、证据和真实 API 映射 | 三期总控 | completed | PDA `release/test` | 2026-08-11 | 功能提交`be776c8`已推送,远端`f83a0c4`;43/43 PASS,A0409刷新和失败回滚已验证;HBuilderX/Android真机仍为最终gap |
@@ -29,18 +46,42 @@
| 019feed6-edeb-7da3-aa75-8c40aa5fb305 | Firstleg P0 测试环境发布 | Jenkins `backend-java` 的 `firstleg` 定向发布与健康检查 | 三期总控 | completed | 后端 `test` | 2026-08-11 | backend-java #101、firstleg #71 成功;部署 `9f455b6`,包含 `7aa2b50` 与 PDA 原子 `/batch`;无 SQL,已通知全量复跑 | | 019feed6-edeb-7da3-aa75-8c40aa5fb305 | Firstleg P0 测试环境发布 | Jenkins `backend-java` 的 `firstleg` 定向发布与健康检查 | 三期总控 | completed | 后端 `test` | 2026-08-11 | backend-java #101、firstleg #71 成功;部署 `9f455b6`,包含 `7aa2b50` 与 PDA 原子 `/batch`;无 SQL,已通知全量复跑 |
| 019feeee-e042-73b0-ba84-c6b8e21fa6c9 | Loading-finalize 测试环境发布 | Jenkins `backend-java` 的 `firstleg` 定向发布与健康检查 | 三期总控 | completed | 后端 `test` | 2026-08-11 | backend-java #102、firstleg #72成功,部署`3f301e3`;消费者单跑缺同轮fixture,需随生产者链最终复验 | | 019feeee-e042-73b0-ba84-c6b8e21fa6c9 | Loading-finalize 测试环境发布 | Jenkins `backend-java` 的 `firstleg` 定向发布与健康检查 | 三期总控 | completed | 后端 `test` | 2026-08-11 | backend-java #102、firstleg #72成功,部署`3f301e3`;消费者单跑缺同轮fixture,需随生产者链最终复验 |
| 019feef5-59e3-7110-b87f-4aea14bb67c6 | PDA BATCH SQL 与 Firstleg 发布 | 测试库统一SQL、Jenkins `firstleg` 定向发布和健康检查 | 三期总控 | archived | 后端 `test` | 2026-08-11 | 执行前卡在工具审批,未开始备份或写库;已由新任务`019fef02-863b-7413-84f7-36593aac0c4e`替代 | | 019feef5-59e3-7110-b87f-4aea14bb67c6 | PDA BATCH SQL 与 Firstleg 发布 | 测试库统一SQL、Jenkins `firstleg` 定向发布和健康检查 | 三期总控 | archived | 后端 `test` | 2026-08-11 | 执行前卡在工具审批,未开始备份或写库;已由新任务`019fef02-863b-7413-84f7-36593aac0c4e`替代 |
| 019fef02-863b-7413-84f7-36593aac0c4e | PDA BATCH SQL 与 Firstleg 发布(替代) | 测试库统一SQL、Jenkins `firstleg` 定向发布和健康检查 | 三期总控 | active | 后端 `test` | 2026-08-11 | 使用默认权限和已有授权继续:备份、统一SQL两次、CHECK含BATCH核验、部署Firstleg并通知最终全量 | | 019fef02-863b-7413-84f7-36593aac0c4e | PDA BATCH SQL 与 Firstleg 发布(替代) | 测试库统一SQL、Jenkins `firstleg` 定向发布和健康检查 | 三期总控 | completed | 后端 `test` | 2026-08-11 | 统一SQL连续两次唯一PASS,CHECK含BATCH;backend-java #103、firstleg #73成功,部署`40171b7`,健康/OpenAPI通过,已通知最终全量 |
| 019fef67-b9b5-7f20-a19f-0f2bb9e91a68 | Loading complete 最终阻断修复 | `baiyue-firstleg/firstleg` 装柜完成首次提交、幂等重放与事务状态收口 | 三期总控 | completed | 后端 `test` | 2026-08-11 | `bf7c214`已推送:修复普通注解SQL误用XML实体导致MySQL语法异常;定向13/13、Firstleg 527项无失败,无SQL,仅需部署Firstleg |
| 019fef75-68c8-7d63-9f28-d2f5ac068c8b | Loading complete 修复发布 | Jenkins `firstleg` 定向发布、健康与OpenAPI核验 | 三期总控 | completed | 后端 `test` | 2026-08-11 | backend-java #104、firstleg #74成功,部署`cb308399`(包含`bf7c214`与`df0f05c`);无SQL,Gateway健康与Firstleg OpenAPI通过,已通知最终全量复跑 |
| 019fef90-4707-7c62-af0d-8b3395ef1e80 | 柜次与计划状态机复验分类 | 三期柜次push、计划推进、预装门禁及验收fixture顺序 | 三期总控 | completed | 后端 `test` | 2026-08-11 | 已确认双缺口:`cb308399`正确引入WAIT_LOADING/推送后EDITING,但错误地在首笔写库而非claim时推进LOADING;脚本仍按旧push即LOADING顺序,需后端claim推进与fixture重排后再部署复验 |
| 019fef9a-e00d-7ea2-8450-5a5930e5279d | PDA claim 推进装柜中 | `baiyue-firstleg/firstleg` 任务领取、计划LOADING推进、历史与幂等 | 三期总控 | completed | 后端 `test` | 2026-08-11 | `16a2f83`已推送:claim首次及同作业员重入幂等推进LOADING,保留pick/batch兜底且START_LOADING历史不重复;定向10/10、Firstleg 531项无失败,无SQL,仅需部署Firstleg |
| 019fef9b-046a-7062-bcfd-8069f02a4822 | 三期装柜状态验收脚本重排 | `phase3-container-loading`、`phase3-loading`及级联fixture | 三期总控 | completed | 后端 `test` | 2026-08-11 | 远端`386eae6`已收口:WAIT_LOADING→EDITING→claim后LOADING→真实pick/batch→COMPLETED,customs/finalize同轮fixture;脚本契约6/6、node check、diff check通过,仅脚本无需部署 |
| 019fefb4-ef2e-7db2-a698-a65f185df8f8 | PDA claim 状态修复发布 | Jenkins `firstleg` 定向发布、健康与OpenAPI核验 | 三期总控 | completed | 后端 `test` | 2026-08-11 | backend-java #105、firstleg #75成功,部署`a59f4634`(包含`16a2f83`与`386eae6`);无SQL,健康/OpenAPI通过,已放行完整生产者链与默认全量 |
| 019fef9f-0a38-7523-bb40-33256352505b | Firstleg claim 推进装柜状态 | `LoadingPickService.claim` 原子推进计划至LOADING并保持幂等 | 三期总控 | completed | 后端 `test` | 2026-08-11 | `16a2f83`已推送origin/test;claim成功/同作业员重入调用`startPicking`,仅首次写START_LOADING历史;LoadingPickService定向10/10、Firstleg 531项0失败2跳过、diff check通过;无SQL,仅需部署Firstleg |
| 019fef8f-8134-7380-b112-33ba490fa911 | 柜次推送状态机阻断排查 | `baiyue-firstleg/firstleg` 柜次推送、计划状态与预装确认门禁 | 三期总控 | completed | 后端 `test` | 2026-08-11 | 后端契约完整无需改动:push-preload保持EDITING,PDA task claim后才推进LOADING;失败为脚本旧顺序,已交fixture任务修正 |
| 019fef8f-994b-75c0-a3a2-0c76574567b4 | 三期最终fixture稳定性审计 | `baiyue-firstleg/scripts/admin-test-env-modules` 生产者链marker与跨模块fixture | 三期总控 | completed | 后端 `test` | 2026-08-11 | `386eae6`已推送:按push EDITING、claim EDITING、首笔PICK/BATCH启动装柜的真实顺序修正3个脚本;静态3/3、契约6/6通过 |
| 019fefae-09e8-7993-906e-95b073ffc0b7 | 预装确认与装柜启动门禁矛盾修复 | `baiyue-firstleg/firstleg` 入库预装确认、柜次启动与主状态同步 | 三期总控 | completed | 后端 `test` | 2026-08-11 | `a59f463`已推送:confirming允许INBOUNDED或LOADING,LOADING仍强制关联柜次已启动;定向4/4、Firstleg 532项无失败,无SQL |
| 019fefb7-d33d-7521-ae9d-1ef268755b9c | 预装门禁修复发布 | Jenkins `firstleg` 定向发布、健康与OpenAPI核验 | 三期总控 | completed | 后端 `test` | 2026-08-11 | backend-java #105、firstleg #75成功,部署`a59f463`;Firstleg 533项0失败2跳过,Gateway health与Firstleg OpenAPI HTTP200,未执行SQL,已通知最终全量复跑 |
| 019ff02d-924c-7290-a34e-b2c3704601b8 | 三期最终验收状态与finalize fixture修正 | `baiyue-firstleg/scripts/admin-test-env-modules` claim/CONFIRMING真实状态与订舱拖车报关到finalize柜次关联 | 三期总控 | archived | 后端 `test` | 2026-08-11 | 发布任务越权创建但未下发业务工作;已归档,范围交回现有全量任务`019fdf0a-4933-7903-8a0c-10018c379f6f`处理 |
| 019ff034-87cb-7d32-8c93-3e8aa992b082 | 三期最终脚本与全量收口 | `baiyue-firstleg/scripts/admin-test-env-*` 状态断言、finalize实际柜次关联、定向与默认全量 | 三期总控 | active | 后端 `test` | 2026-08-11 | 因原全量任务被Finance独占而建立的唯一替代任务;修复后直接跑定向和默认全量,完成即归档,不再拆分 |
| 019fdf0a-4933-7903-8a0c-10018c379f6f | 后台真实全量测试 | `baiyue-firstleg/scripts/admin-test-env-*` 与测试环境真实 HTTP 验收 | 三期总控 | active | 后端 `test` | 2026-08-11 | 当前基线复跑与下一批 PDA batch/Admin 终验分两轮执行;禁止 mock、放宽断言或 gap 伪装 PASS | | 019fdf0a-4933-7903-8a0c-10018c379f6f | 后台真实全量测试 | `baiyue-firstleg/scripts/admin-test-env-*` 与测试环境真实 HTTP 验收 | 三期总控 | active | 后端 `test` | 2026-08-11 | 当前基线复跑与下一批 PDA batch/Admin 终验分两轮执行;禁止 mock、放宽断言或 gap 伪装 PASS |
| 019febc3-704f-7c72-8e82-dc317f69dc9b | Finance 后端与数据库 | `baiyue-firstleg/finance`、Finance 依赖的 `file/firstleg/gateway/iam` 契约、模块 SQL 与统一 SQL | 财务总控 | active | 共享工作区 | 2026-08-11 | 第三轮修复因会话中断待恢复;P0 为成本入口体积快照、凭证校验、订单/柜次客户归属、完整幂等 hash 和行为测试 | | 019febc3-704f-7c72-8e82-dc317f69dc9b | Finance 后端与数据库 | `baiyue-firstleg/finance`、Finance 依赖的 `file/firstleg/gateway/iam` 契约、模块 SQL 与统一 SQL | 财务总控 | active | 共享工作区 | 2026-08-11 | 最终专项判定11个一期operation缺失;已返工账户/流水、来源审核与纳入结算、对账单和应收应付结算单正式闭环 |
| 019febc3-7c39-7ec2-8051-a4cce8d5f104 | Finance F1 接口契约 | `docs/财务管理/` 的 OpenAPI、接口契约、门禁和状态文档 | 财务总控 | active | 共享工作区 | 2026-08-11 | 第三轮修订因会话中断待恢复;只改文档,按真实实现更新 D1/D4/D6/D8/D9/D11 | | 019febc3-7c39-7ec2-8051-a4cce8d5f104 | Finance F1 接口契约 | `docs/财务管理/` 的 OpenAPI、接口契约、门禁和状态文档 | 财务总控 | active | 共享工作区 | 2026-08-11 | 11个NOT_IMPLEMENTED已判定一期P0;正在冻结DTO、状态、权限、幂等、错误码和验收用例并跟踪实现 |
| 019febc3-89f3-7991-b7eb-6c697fd9f032 | Admin 人工财务模块 | `apps/admin-web/src/modules/finance/` 及其路由、权限和测试 | 财务总控 | active | Admin 当前工作区 | 2026-08-11 | 第三轮修复因会话中断待恢复;接入真实凭证上传、成本体积快照和 revision 查询,禁止模拟成功 | | 019febc3-89f3-7991-b7eb-6c697fd9f032 | Admin 人工财务模块 | `apps/admin-web/src/modules/finance/` 及其路由、权限和测试 | 财务总控 | active | Admin 当前工作区 | 2026-08-11 | 五路由已存在但后三页仍为旧能力映射;返工正式生成、详情、状态动作和来源审核/结算纳入交互 |
| 019febc3-9519-7982-81dd-bc048819bf48 | Client 财务只读模块 | `apps/client-web/src/modules/finance/` 及财务权限映射和测试 | 财务总控 | completed | Client 当前工作区 | 2026-08-11 | 184/184、typecheck/build 通过;过滤 DRAFT/VOIDED,财务 list+view 权限按 AND 判断,不传 customerId/tenantId | | 019febc3-9519-7982-81dd-bc048819bf48 | Client 财务只读模块 | `apps/client-web/src/modules/finance/` 及财务权限映射和测试 | 财务总控 | active | Client 当前工作区 | 2026-08-11 | Client交付已完成;因原全量ID被三期持续占用,复用本独立ID执行Finance一期五页最终只读专项,禁止修改文件 |
| 019fef83-0763-7930-8c00-c42d5398b0f1 | 数据库注释全库盘点 | `baiyue-firstleg/*/src/main/resources/db/` 与统一 SQL 的只读盘点 | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 155个建表定义、约2339字段;字段注释覆盖约69%,缺失724;Finance缺164、Firstleg缺461;未修改文件 |
| 019fef83-2697-7062-a902-a0e9791d75ea | 数据库注释规范与门禁 | 数据库中文注释规范、静态审计脚本和 CI/验收门禁 | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 规范与离线门禁完成;多行CHECK假阳性已按MySQL数据类型白名单修复并补SelfTest;Order/Finance Issues=0 |
| 019fef8b-9f95-7102-a57b-dc4960ff5ffa | Firstleg 二期数据库注释 | `firstleg` 基线、入库、测量、计费、价格及托盘相关模块 SQL | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 7文件新增47个注释、修正1个英文状态;范围内Issues=0、结构不变、聚合构建成功;完整测试被并行Finance测试编译错误阻断 |
| 019fef8b-a844-75c1-9ed3-85dfca8a89f1 | Firstleg 三期船期数据库注释 | `firstleg` 船司查询与港口船期模块 SQL | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 两文件补齐/中文化113字段;覆盖100%;SQL契约测试6/6、BUILD SUCCESS;仅COMMENT变更 |
| 019fef8b-afb6-7342-a707-f014f7baa785 | Order Auth IAM 数据库注释 | `order`、`auth`、`iam` 模块 SQL | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 26表389字段覆盖100%;Auth/IAM测试通过;Order 125/126,唯一失败为统一SQL旧注释镜像待集成同步 |
| 019fef8b-b84f-70e2-b312-bebdce157ad0 | Warehouse File Audit Event 数据库注释 | `warehouse`、`file`、`audit-service`、`event-bridge-service` 模块 SQL | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 28个表定义、433字段注释100%;四模块Maven测试BUILD SUCCESS;未改统一SQL |
| 019fef9d-ddf6-7963-b683-46bab7685bee | Firstleg 三期报关数据库注释 | `phase3-customs-schema.sql` | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 8表107字段中文注释完成;CustomsSqlContractTest通过;仅COMMENT变更,未改统一SQL |
| 019fef9d-e7df-7bd2-9d07-ef22bbac1e6a | Firstleg 三期订舱拖车数据库注释 | `phase3-ocean-booking-schema.sql`、`phase3-truck-appointment-schema.sql` | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 两文件Issues=0且结构不变;订舱/拖车定向测试20/20、BUILD SUCCESS;未改统一SQL |
| 019fef9d-f2f1-7e12-8f70-63e54a855851 | Firstleg 三期装柜PDA数据库注释 | 三期装柜、出仓、PDA、分柜、排柜及桥接脚本 | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 七文件完成;Firstleg 89表1443字段覆盖100%、Issues=0;相关SQL测试33项通过、1跳过;统一SQL待同步 |
| 019fefb9-fce8-78e3-8270-dd569546ae9d | 数据库注释统一SQL集成 | `deploy/sql/头程数据库统一增量-MySQL8.sql` 与相关SQL契约测试 | 数据库注释总控 | completed | 共享工作区 | 2026-08-11 | 150唯一表2456字段;每表最多一次DDL并验签;九库断言/唯一PASS;DryRun PASS;Firstleg549、Finance35通过;未执行真实MySQL |
## 通信与汇总格式 ## 通信与汇总格式
总控下发消息至少包含: 总控下发消息至少包含:
```text ```text
routing_key: <长期职责键>
task_id: <已登记 ID> task_id: <已登记 ID>
目标: <单一交付目标> 目标: <单一交付目标>
范围: <目录/模块> 范围: <目录/模块>
@@ -48,4 +89,4 @@ task_id: <已登记 ID>
回传: <状态、变更文件、验证命令/结果、阻断项> 回传: <状态、变更文件、验证命令/结果、阻断项>
``` ```
汇总时按 `task_id` 聚合,不按 display_name 聚合;同一 ID 的最新状态覆盖旧状态,但保留重要阻断和验证记录。 汇总时按 `routing_key + task_id` 聚合,不按 display_name 聚合;同一 ID 的最新状态覆盖旧状态,但保留重要阻断和验证记录。
@@ -4,6 +4,8 @@
> 审查范围:Finance Java、Finance 建库 SQL、统一增量 SQL、Admin/Client Finance API、File Java/测试、`openapi/finance-f1-manual-v1.yaml` > 审查范围:Finance Java、Finance 建库 SQL、统一增量 SQL、Admin/Client Finance API、File Java/测试、`openapi/finance-f1-manual-v1.yaml`
> 结论:F0/F1 基础代码已经实现,当前处于专项修复与契约收敛阶段;不是整体未开发。修复项完成前尚未达到完整联调验收/测试放行。 > 结论:F0/F1 基础代码已经实现,当前处于专项修复与契约收敛阶段;不是整体未开发。修复项完成前尚未达到完整联调验收/测试放行。
> 范围重定:领导验收改为《财务一期五页产品与接口验收契约》中的 5 页。本文 D1-D11 继续作为既有人工接口专项门禁,并新增来源链路和五页门禁。
## 1. 已确认且已对齐 ## 1. 已确认且已对齐
| 范围 | 目标 | 当前结论 | | 范围 | 目标 | 当前结论 |
@@ -21,51 +23,76 @@
当前实现包括 Finance Controller/Service、独立财务表、统一 SQL 权限种子、Admin 人工财务页面和 Client 只读账单页面。本文中的 D1-D11 是对现有实现的修复门禁,不是从零建设清单。 当前实现包括 Finance Controller/Service、独立财务表、统一 SQL 权限种子、Admin 人工财务页面和 Client 只读账单页面。本文中的 D1-D11 是对现有实现的修复门禁,不是从零建设清单。
### 1.1 第三轮复验记录(2026-08-11) ### 1.1 后端最终实现复验记录(2026-08-11,基线 `7c2274b`)
| 验证对象 | 命令/范围 | 结果 | 结论 | | 验证对象 | 命令/范围 | 结果 | 结论 |
|---|---|---|---| |---|---|---|---|
| Finance | `mvn -pl finance -am test` | 通过;Finance 7 个测试通过(1 个源码契约检查、6 个校验单测) | 可证明现有校验和 1:2:3 体积分摊单测通过;不能证明固定 DTO、完整幂等或跨服务闭环 | | Finance | 后端历史基线复验 | 12 个测试通过 | 历史基线记录;固定 DTO、来源消费和完整幂等已由下方最新 35/35 结果覆盖 |
| Firstleg | 后端全量复验 | 527 个测试通过 | 真实柜次体积快照、客户过滤和无有效体积拒绝有直接证据 |
| File | 后端全量复验 | 114 个测试通过 | 原 JUnit 测试发现故障已解决,不再作为阻断 |
| Gateway | 后端全量复验 | 26 个测试通过 | 本次相关网关回归通过 |
| IAM | 后端全量复验 | 163 个测试通过 | 本次相关权限回归通过 |
| Admin Finance API | `pnpm test -- src/modules/finance/api/finance.test.ts` | 通过;1 个测试文件、7 个测试通过 | D8 字段适配与账单动作封装有直接证据 | | Admin Finance API | `pnpm test -- src/modules/finance/api/finance.test.ts` | 通过;1 个测试文件、7 个测试通过 | D8 字段适配与账单动作封装有直接证据 |
| File | `mvn -pl file -am test` | 失败;`file-service` 运行 0 个测试,JUnit Jupiter 发现阶段失败 | `ProductImageControllerContractTest` 缺少 `AuthenticatedUser`;File 凭证链路无绿色全量测试证据 |
File 失败转储:`baiyue-firstleg/file/target/surefire-reports/2026-08-11T12-07-49_956-jvmRun1.dump`。由于 File 测试未进入执行阶段,Admin 创建收款/成本的真实凭证端到端闭环继续阻断。 以上计数来自总控最终后端复验。尚未提供测试环境中 Finance → Firstleg/File 的真实 HTTP 联调报告,因此跨服务部署连通性仍需在联调阶段验证,但不再视为代码实现阻断。
### 1.2 五页与费用来源主链增量复验(2026-08-11)
| 验证对象 | 当前 Surefire 证据 | 结果 |
|---|---|---|
| Finance 全模块 | 10 个测试类:费用来源消费、内部 Controller、五页 DTO、Client 脱敏、异常码、File fail-closed、SQL 契约等 | **35/35,BUILD SUCCESS** |
| Finance 来源消费 | `FinanceFeeSourceEventServiceTest`、`InternalFinanceFeeSourceControllerTest` | **10/10 + 2/2 通过**;覆盖入库/柜子来源写入、调整替代、作废保留、同参重放、异参冲突、跨客户、未发布、零金额和负金额拒绝 |
| Firstleg | 全量复验 549 项(2 skip);其中事件客户端、Outbox relay、快照、柜子费用、迁移契约等 7 个测试类 17 项 | **549/549 通过,2 skip;来源定向 17/17 通过** |
| 其他直接消费者与 SQL 契约 | File、Gateway、IAM、Phase3/PDA SQL、Order SQL | **114/114、26/26、163/163、12/12、3/3,均 BUILD SUCCESS** |
| 五页固定 DTO 与脱敏 | `FinanceReadApiBehaviorTest`、`FinanceFeePoolDirectionBehaviorTest`、`FinanceExceptionHandlerTest` | **3/3 + 2/2 + 2/2 通过** |
本轮文档任务未重新执行 Maven;以上结果直接读取当前工作树已有 Surefire 报告,不把“测试源码存在”替代为“测试通过”。
## 2. 接口与权限基线 ## 2. 接口与权限基线
| 接口 | 权限 | 当前状态 | | 接口 | 权限 | 当前状态 |
|---|---|---| |---|---|---|
| `GET /api/platform/finance/v1/bills?customerId=` | `platform:finance:bill:view` | 已实现;返回非分页数组 | | `GET /api/platform/finance/v1/bills?customerId=` | `platform:finance:bill:view` | 已实现;返回非分页数组 |
| `POST /internal/finance/v1/fee-source-events` | `X-Internal-Service-Token` | 已实现并验证;Inbox 幂等消费后写入/替代/作废 `fin_fee_source`,Finance 消费/Controller 12 项定向测试通过 |
| `GET /api/platform/finance/v1/customer-accounts/{customerId}` | `platform:finance:bill:view` | 已实现固定 `CustomerAccount` DTO;Finance DTO 行为测试通过 |
| `GET /api/platform/finance/v1/fee-pool?customerId=&direction=` | `platform:finance:bill:view` | 已实现固定 `FeePoolItem` DTO;方向和客户范围测试通过 |
| `GET /api/platform/finance/v1/statements?customerId=` | `platform:finance:bill:view` | 已实现固定 `Statement` DTO;生成/审核操作未实现 |
| `GET /api/platform/finance/v1/receivable-settlements?customerId=` | `platform:finance:bill:view` | 已实现固定 `ReceivableSettlement` DTO;生成操作未实现 |
| `GET /api/platform/finance/v1/payable-settlements?customerId=` | `platform:finance:cost:view` | 已实现固定 `PayableSettlement` DTO;审核/付款操作未实现 |
| `POST /api/platform/finance/v1/bills` | `platform:finance:bill:create` | 已实现 | | `POST /api/platform/finance/v1/bills` | `platform:finance:bill:create` | 已实现 |
| `GET/PUT /api/platform/finance/v1/bills/{billId}` | `bill:view/update` | Java 和 Admin 均已接入;缺修订历史查询 | | `GET/PUT /api/platform/finance/v1/bills/{billId}` | `bill:view/update` | Java 和 Admin 均已接入;缺修订历史查询 |
| `POST .../{billId}/issue|adjust|void` | `bill:issue/adjust/void` | Java 和 Admin 均已接入;端到端闭环未放行 | | `POST .../{billId}/issue|adjust|void` | `bill:issue/adjust/void` | Java 和 Admin 均已接入;端到端闭环未放行 |
| `GET/POST /api/platform/finance/v1/receipts` | `receipt:view/create` | 已实现 | | `GET/POST /api/platform/finance/v1/receipts` | `receipt:view/create` | 已实现平台 `PlatformReceipt` 查询 DTO、多账单分配和凭证 fail-closed;Finance 测试通过 |
| `GET/POST /api/platform/finance/v1/cost-entries` | `cost:view/create` | 登记及分摊落库已实现;真实体积快照、归属和成本凭证校验未完成 | | `GET/POST /api/platform/finance/v1/cost-entries` | `cost:view/create` | 已实现;整柜由 Finance 调 Firstleg 真实快照,成本凭证和归属均校验 |
| `GET/PUT /api/platform/finance/v1/customers/{tenantId}/terms` | `customer-terms:view/update` | Java 已实现;Admin 尚未接入 | | `GET/PUT /api/platform/finance/v1/customers/{tenantId}/terms` | `customer-terms:view/update` | Java 已实现;Admin 尚未接入 |
| `POST /api/platform/finance/v1/vouchers?customerId=` | `receipt:create` | 已实现图片上传;用途区分、成本上传权限和关联状态未实现 | | `GET /api/platform/finance/v1/bills/{billId}/revisions?customerId=` | `bill:view` | 已实现,并校验账单客户归属;Admin 尚未接入 |
| `POST /api/platform/finance/v1/vouchers?customerId=` | `receipt:create` 或 `cost:create` | 已实现图片上传,双权限兼容 |
| `GET /api/client/finance/v1/bills` | `merchant:finance:statement:list` | 已实现 | | `GET /api/client/finance/v1/bills` | `merchant:finance:statement:list` | 已实现 |
| `GET /api/client/finance/v1/bills/{billId}` | `merchant:finance:statement:view` | 已实现 | | `GET /api/client/finance/v1/bills/{billId}` | `merchant:finance:statement:view` | 已实现 |
| `GET /api/client/finance/v1/receipts` | `merchant:finance:statement:view` | 已实现 | | `GET /api/client/finance/v1/receipts` | `merchant:finance:statement:view` | 已实现 |
`tenantId` 只保留为后端兼容路径字段,产品语义统一为客户 ID,不增加用户可见的“租户”层级。 `tenantId` 只保留为后端兼容路径字段,产品语义统一为客户 ID,不增加用户可见的“租户”层级。
## 3. 开发门禁阻断项 ## 3. 门禁状态(已解决与剩余)
以下项目未完成前,可以继续编码,但不能宣称 F1 已具备完整业务闭环。 本表保留 D1-D11 的稳定编号用于总控追踪。标为“后端完成/定向验证通过”的项目不再作为代码实现阻断;其余项目完成前不能宣称 F1 已具备完整业务闭环。
| 编号 | 阻断项 | 当前事实 | 完成标准 | | 编号 | 阻断项 | 当前事实 | 完成标准 |
|---|---|---|---| |---|---|---|---|
| D1 | 稳定响应 DTO | **未完成。** Finance 仍返回 JDBC `Map`/`List<Map>` 和 snake_case;`ApiResponse` 已有 `requestId/traceId/timestamp`,但 Controller 调用 `success(data)` 时成功响应的 `requestId/traceId` 仍为空 | 按 OpenAPI 1.2.0 输出固定 camelCase DTO;所有成功/失败响应的三个追踪字段均为非空有效值,并有序列化契约测试 | | D1 | 稳定响应 DTO | **后端完成。** 五页查询使用 `FinanceReadModels`、`FinanceQueryService` 和 `FinanceResponses`;平台/客户收款使用专用 DTO,成功/失败均带追踪字段;Finance 35/35 通过 | 后端门禁关闭;Admin 继续按固定 camelCase DTO 接入 |
| D2 | 列表形态统一 | Java 为非分页数组;Admin/Client 已做本地分页适配,但仍发送分页/筛选参数 | 首期明确维持非分页并清理无效参数,或后端真正实现统一分页;两端测试与 OpenAPI 同步 | | D2 | 列表形态统一 | **契约已冻结。** 首期维持非分页数组,Admin/Client 在适配层本地分页,OpenAPI 与 Java 一致 | 清理前端无效分页参数属于非阻断整理,不再要求后端改为分页对象 |
| D3 | 调整记录可查询 | Java 调整前写 `fin_bill_revision`,再更新当前账单及替换明细,具备数据库快照;但无修订查询接口,产品无法查看调整前后 | 明确“同账单版本修订”即首期方案,并提供调整记录查询/展示;不得无痕覆盖 | | D3 | 调整记录可查询 | **后端完成。** 调整前写 `fin_bill_revision`;`GET /bills/{billId}/revisions?customerId=` 已落地并校验客户归属,Finance 测试覆盖同客户和跨客户场景 | Admin 接入展示后完成产品闭环;后端门禁已通过 |
| D4 | 幂等语义 | **部分实现。** 已使用 SHA-256(JSON(request)),支持成功同参返回原资源、异参冲突和 PROCESSING 冲突;但哈希未统一覆盖 `method + path + customer + normalized body`,`updateBill` 的 `String.valueOf(lines)` 不稳定,且缺 `Retry-After`、超时恢复、FAILED 处理和真实回归测试 | 全部写操作使用完整规范化请求哈希;固定冲突码;补同参、异参、PROCESSING、恢复和并发测试 | | D4 | 幂等语义 | **后端完成。** 幂等记录按客户、操作人、operation 和 key 隔离,请求哈希覆盖 method、path 和序列化 body;支持成功同参重放、异参 `FIN_409`、PROCESSING 冲突、超时 PROCESSING 抢占恢复和 FAILED 恢复 | 后端门禁关闭;保持写操作回归测试 |
| D5 | 财务凭证链路 | **未完成。** 现有上传为 `POST /api/platform/finance/v1/vouchers`,仅图片且权限为 `receipt:create`;收款调用校验但 `fileClient == null` 时 fail-open,成本未调用校验;无关联接口/状态;File 全量测试发现失败 | 收款和成本均 fail-closed 校验文件存在、客户、业务类型、MIME 和状态;成本角色可上传;建立幂等关联或明确等价持久化关系;File 全量测试通过 | | D5 | 财务凭证链路 | **后端完成。** 上传路径和双权限已对齐;File 客户端缺失返回 `FIN_503`,凭证归属/MIME/业务类型校验保持 fail-closed;Finance 35/35 通过 | 后端门禁关闭;测试环境保留一次真实 File HTTP 冒烟 |
| D6 | 整柜体积分摊 | **部分实现。** 已有 `ContainerOrderVolume`、`fin_cost_allocation` 落库及 6 位 `HALF_UP` 测试;但公开请求和 Admin 允许人工填 `volumeCbm`,没有 Firstleg 真实快照;归属由请求自证;最后一票无实际尾差也标记 `roundingAdjustment=true`,且未保存真实 `roundingDelta` | 服务端从 Firstleg 取得不可篡改体积快照并验证柜次/订单/客户关系;只有 `tailAmount != round(costAmount × tailRatio, 6, HALF_UP)` 时标记尾差并保存 delta;总和严格等于成本 | | D6 | 整柜体积分摊 | **后端完成。** 公共请求只提交 `containerId`;Finance 调 Firstleg 真实柜次快照,按 6 位 `HALF_UP` 分摊并落 `fin_cost_allocation`;只有最后一票实际偏离常规舍入结果时才标记尾差 | Finance 12、Firstleg 527 测试通过;测试环境补一次真实跨服务冒烟即可进入联调验收 |
| D7 | 成本归属校验 | **未完成。** 单票只检查 `orderId` 非空;整柜请求的 `customerId` 被直接复制到各分摊行,未验证订单、柜次及入柜关系 | 单票订单存在且属于客户;整柜存在且订单实际在柜内,并全部属于该客户;任何不一致整单拒绝 | | D7 | 成本归属校验 | **后端完成。** Firstleg 只返回柜内属于客户且体积有效的订单;Finance 再以 `fin_fee_source` 校验单票/整柜订单属于客户 | 单票、整柜客户归属及无效快照测试通过 |
| D8 | Admin 成本字段映射 | **定向验证通过。** Admin 已兼容 `fee_item_name/expense_name` 与 `cost_amount/amount`;Finance API 测试 7/7 通过 | 保持回归测试;不得据此宣称成本创建端到端闭环通过 | | D8 | Admin 成本字段映射 | **定向验证通过。** Admin 已兼容 `fee_item_name/expense_name` 与 `cost_amount/amount`;Finance API 测试 7/7 通过 | 保持回归测试;不得据此宣称成本创建端到端闭环通过 |
| D9 | Admin 完整操作 | **部分实现。** 已有详情、草稿修改、调整、作废、出账、凭证选择/上传和收款/成本创建;未接客户账期和修订历史,整柜体积仍人工填写,成本凭证后端不校验,File 全量测试失败 | 接客户账期和修订历史;改为服务端真实体积快照;File/Finance 凭证校验通过并完成真实环境创建闭环 | | D9 | Admin 完整操作 | **部分实现。** 已有详情、草稿修改、调整、作废、出账、凭证选择/上传和收款/成本创建;未接客户账期和 revision;整柜表单仍强制人工填写 `containerOrders/volumeCbm`,与最终后端只接 `containerId` 的契约不一致 | 删除人工体积录入,只提交 `containerId`;接客户账期和 revision;完成真实环境创建闭环 |
| D10 | 业务错误码 | 文档定义 `FIN-AR-*`/`FIN-COST-*`;Java 当前主要返回通用 BAD_REQUEST/CONFLICT + 中文消息 | 后端建立稳定业务码并由 Admin/Client 按码处理,不依赖消息文本 | | D10 | 业务错误码 | **后端完成。** 通用财务异常固定为 `FIN_400/404/409/503/001`,来源事件固定为 `FIN-EVT-001` 至 `015`、`FIN-EVT-401`;未发布稳定返回 `FIN-EVT-015`,金额/币种错误返回 `FIN-EVT-010` | 后端门禁关闭;Admin/Client 按码处理,不依赖中文消息 |
| D11 | 客户状态可见性 | **部分实现。** 账单列表/详情 SQL 已过滤 `ISSUED/PARTIALLY_PAID/PAID`;收款列表只按客户过滤,仍可返回 `voucher_file_ids`、`voucher_no`、内部状态等平台字段;DRAFT/VOIDED 详情异常尚未固定映射 `FIN-AR-001` | 客户账单及其收款只来源于三种可见状态;使用专用只读 DTO,去除凭证和内部字段;不可见/跨客户/不存在统一 `FIN-AR-001` | | D11 | 客户状态可见性 | **后端完成。** 客户账单只见 `ISSUED/PARTIALLY_PAID/PAID`;客户收款只见 `CONFIRMED`,使用 `ClientReceipt` 专用 DTO 并去除凭证、操作人和内部字段;脱敏测试通过 | 后端门禁关闭;保留跨客户与序列化回归 |
| D12 | Finance 费用来源写入 | **后端完成。** 内部事件入口、令牌鉴权、Inbox 幂等、Firstleg 快照回查、来源写入/替代/作废均已实现;非作废事件必须 `PUBLISHED`,未发布返回 `FIN-EVT-015`;金额必须 `>0`,零/负返回 `FIN-EVT-010`;专项 10/10、Finance 全量 35/35 通过 | 后端门禁关闭;保留真实跨服务 HTTP 冒烟 |
| D13 | 柜子费用来源 | **后端完成并验证。** Firstleg 已有柜子费用模型、审核/参与结算/作废、事件、Relay 和内部快照;Firstleg 相关 17/17、Finance 柜子来源消费测试通过 | 后端门禁关闭;测试环境补真实跨服务事件冒烟 |
| D14 | 一期 5 页 | **后端查询契约完成,页面开发中。** 五页固定 DTO 路径、Client 脱敏和错误码已经验证;11 个目标写/明细 operation 仍真实标记 `NOT_IMPLEMENTED`,Admin 正在接入 | 完成 Admin 五页矩阵和剩余 11 个 operation;删除费用分析、利润表、充值及假入口并完成端到端验收 |
## 4. 非阻断但需锁定的契约说明 ## 4. 非阻断但需锁定的契约说明
@@ -80,11 +107,11 @@ File 失败转储:`baiyue-firstleg/file/target/surefire-reports/2026-08-11T12-
进入前后端联调前至少满足: 进入前后端联调前至少满足:
1. D1、D3、D5、D6、D7、D8、D9、D10、D11 已完成并有直接测试。 1. D1-D8、D10-D13 已具备后端直接证据;剩余以 D9 和 D14 的 11 个 operation/Admin 验收为准。
2. D2 选定“首期非分页”或“服务端分页”之一,OpenAPI、Admin、Client 三方一致。 2. D2 已固定为首期非分页数组;后续若改服务端分页须另行升级契约。
3. D4 至少完成账单创建、出账和收款登记的同键重放测试。 3. 幂等门禁已关闭;后续写 operation 继续复用同参重放、异参冲突和恢复语义。
4. Finance 集成测试覆盖:默认 30 天、CNY 拒绝、出账冻结、300 分 3 单、超额/跨客户/草稿拒绝、部分收款到收清、调整修订、已收不可作废。 4. Finance 集成测试覆盖:默认 30 天、CNY 拒绝、出账冻结、300 分 3 单、超额/跨客户/草稿拒绝、部分收款到收清、调整修订、已收不可作废。
5. 成本测试覆盖:单票归属、整柜按体积分摊、零体积人工处理、舍入尾差、跨客户对象拒绝。 5. 成本测试覆盖:单票归属、真实柜次快照、整柜按体积分摊、无有效体积拒绝、实际舍入尾差、跨客户对象拒绝。
6. 权限测试覆盖平台 12 个权限码和客户 2 个权限码,并验证客户无法写入及无法跨客户查询。 6. 权限测试覆盖平台 12 个权限码和客户 2 个权限码,并验证客户无法写入及无法跨客户查询。
7. 客户查询测试证明列表、详情和收款均不会暴露 `DRAFT/VOIDED`、平台凭证 fileId 或内部备注。 7. 客户查询测试证明列表、详情和收款均不会暴露 `DRAFT/VOIDED`、平台凭证 fileId 或内部备注。
@@ -93,6 +120,6 @@ File 失败转储:`baiyue-firstleg/file/target/surefire-reports/2026-08-11T12-
- **当前阶段:专项修复中。** Finance、SQL、Admin 和 Client 均已有实现,不再按“未开发”管理。 - **当前阶段:专项修复中。** Finance、SQL、Admin 和 Client 均已有实现,不再按“未开发”管理。
- **可继续开发:是。** 路径、权限、固定 DTO、凭证、分摊、幂等和客户可见性已经冻结,不再需要新增产品决策。 - **可继续开发:是。** 路径、权限、固定 DTO、凭证、分摊、幂等和客户可见性已经冻结,不再需要新增产品决策。
- **可进行接口冒烟:有条件。** 可验证现有路径、鉴权和基础创建/查询,但结果不代表业务验收通过。 - **可进行接口冒烟:有条件。** 可验证现有路径、鉴权和基础创建/查询,但结果不代表业务验收通过。
- **可进入完整联调验收:否。** 主要阻断为真实体积快照与归属校验、收款/成本凭证 fail-closed 校验、File 全量测试故障、Admin 创建闭环、稳定 DTO/错误码、完整幂等和客户收款 DTO。 - **可进入完整联调验收:否。** Finance 来源写入及 `PUBLISHED + amount>0`、五页 DTO、完整幂等、File fail-closed、客户脱敏、稳定错误码和柜子来源已经通过后端测试,不再是阻断;剩余阻断是 11 个目标 operation、Admin 五页接入和真实跨服务冒烟。
本次审查只修订文档与 OpenAPI,未修改 Java、前端或 SQL。 本次审查只修订文档与 OpenAPI,未修改 Java、前端或 SQL。
@@ -5,8 +5,13 @@
> 状态:目标契约;以《F1人工财务契约审查与门禁》为开发/联调准入依据 > 状态:目标契约;以《F1人工财务契约审查与门禁》为开发/联调准入依据
> OpenAPI:`openapi/finance-f1-manual-v1.yaml` > OpenAPI:`openapi/finance-f1-manual-v1.yaml`
> 一期 5 页产品与新增接口以《财务一期五页产品与接口验收契约》和 `openapi/finance-phase1-five-pages-v1.yaml` 为准;本文保留现有人工账单、收款和成本能力的细化契约。
## 1. 首期边界 ## 1. 首期边界
- 领导验收页面固定为客户账户、客户应收应付、客户对账单、结算单应收、结算单应付。
- 费用分析、利润表、发票、钱包、预收和充值不做,不保留按钮、菜单或路由。
- 客户账户只读聚合账单、收款和应收应付来源,不存在可直接修改的账户余额。
- 只支持 RMB/CNY,不做汇率、月结、钱包、发票、银行流水和自动认款。 - 只支持 RMB/CNY,不做汇率、月结、钱包、发票、银行流水和自动认款。
- 平台财务人工填写账单、收款、成本表单并上传凭证。 - 平台财务人工填写账单、收款、成本表单并上传凭证。
- 客户只读查看本客户账单、收款记录和未收余额。 - 客户只读查看本客户账单、收款记录和未收余额。
@@ -14,6 +19,7 @@
- 客户账期按客户配置,默认 30 个自然日;账单日期和到期日由服务端按 `billDate + creditDays` 计算。 - 客户账期按客户配置,默认 30 个自然日;账单日期和到期日由服务端按 `billDate + creditDays` 计算。
- 一笔收款可分配到多张账单;财务逐张填写分配金额。首期不处理预收、多收、手续费、退款。 - 一笔收款可分配到多张账单;财务逐张填写分配金额。首期不处理预收、多收、手续费、退款。
- 单票成本归属单票;整柜清关、拖车等公共成本按柜内有效票体积分摊。 - 单票成本归属单票;整柜清关、拖车等公共成本按柜内有效票体积分摊。
- 账单/对账单不得接收 Admin 自造来源:只有已审核、已发布、参与结算、有效且为 CNY 的入库单/柜子费用版本进入 `fin_fee_source` 后才能选入。
## 2. 统一接口约定 ## 2. 统一接口约定
@@ -61,9 +67,9 @@
整柜分摊固定规则: 整柜分摊固定规则:
1. 放行后的 Finance 公开入口仅接收 `containerId`,并由服务端向 Firstleg 读取成本创建时的真实柜次/订单有效体积快照;当前公开请求中的 `containerOrders[].volumeCbm` 是过渡实现,不可信且不得作为放行后的权威输入。快照单位 CBM、精度 6 位;有效票按 `orderId` 升序形成确定顺序。 1. Finance 公开入口仅接收 `containerId`,由服务端调用 `GET /internal/firstleg/v1/finance-cost-snapshots/customers/{customerId}/containers/{containerId}` 读取真实柜次/订单有效体积快照。浏览器不得提交 `containerOrders` 或 `volumeCbm`。快照单位 CBM、精度 6 位;有效票按 Firstleg 柜次明细形成确定输入。
2. `ratio = orderVolume / totalVolume`;除最后一票外,`allocatedAmount = costAmount × ratio`,按 6 位小数 `HALF_UP`。 2. `ratio = orderVolume / totalVolume`;除最后一票外,`allocatedAmount = costAmount × ratio`,按 6 位小数 `HALF_UP`。
3. 最后一票金额为 `costAmount - 前序分摊金额合计`。仅当该金额不等于 `costAmount × tailRatio` 按 6 位 `HALF_UP` 的常规舍入结果时,`roundingAdjustment=true`,并保存非零 `roundingDelta=tailAmount-roundedTailAmount`;没有实际尾差时必须为 `false/0`。 3. 最后一票金额为 `costAmount - 前序分摊金额合计`。仅当该金额不等于 `costAmount × tailRatio` 按 6 位 `HALF_UP` 的常规舍入结果时,`roundingAdjustment=true`;没有实际尾差时必须为 `false`。分摊金额合计严格等于成本金额。
4. 单票体积为零时该票自动分摊为 0;柜内有效票总体积为零时返回 `FIN-COST-VOLUME-SNAPSHOT-INVALID`。首期不支持请求端 `MANUAL_ZERO_VOLUME` 人工分摊。 4. 单票体积为零时该票自动分摊为 0;柜内有效票总体积为零时返回 `FIN-COST-VOLUME-SNAPSHOT-INVALID`。首期不支持请求端 `MANUAL_ZERO_VOLUME` 人工分摊。
5. 已落库的体积、比例、分摊金额和尾差均为不可变快照;来源体积后续变化不追改历史成本。 5. 已落库的体积、比例、分摊金额和尾差均为不可变快照;来源体积后续变化不追改历史成本。
@@ -71,9 +77,9 @@
1. 当前公开上传入口为 Finance 的 `POST /api/platform/finance/v1/vouchers?customerId={customerId}`,multipart 字段为 `file`;当前只接受图片。OpenAPI 描述该真实入口,不再声明不存在的 `/platform/v1/files/finance-vouchers`。 1. 当前公开上传入口为 Finance 的 `POST /api/platform/finance/v1/vouchers?customerId={customerId}`,multipart 字段为 `file`;当前只接受图片。OpenAPI 描述该真实入口,不再声明不存在的 `/platform/v1/files/finance-vouchers`。
2. Finance 当前通过 File 的既有 `POST /internal/file/v1/business-files/{tenantId}/FINANCE_VOUCHER/{customerId}` 上传,并以 `GET /internal/file/v1/business-files/{tenantId}/FINANCE_VOUCHER/{customerId}/{fileId}` 查询校验。仓库当前没有财务专用 `validate/associate` Controller,OpenAPI 不得将其写成已实现路径。 2. Finance 当前通过 File 的既有 `POST /internal/file/v1/business-files/{tenantId}/FINANCE_VOUCHER/{customerId}` 上传,并以 `GET /internal/file/v1/business-files/{tenantId}/FINANCE_VOUCHER/{customerId}/{fileId}` 查询校验。仓库当前没有财务专用 `validate/associate` Controller,OpenAPI 不得将其写成已实现路径。
3. 放行目标要求收款和成本在落库前均 fail-closed 校验:File 客户与表单客户一致、业务类型为 `FINANCE_VOUCHER`、文件存在且有效、未删除、MIME 为允许的图片类型。File 客户端不可用或超时时返回 `FIN-FILE-VALIDATION-UNAVAILABLE`,不得跳过校验。 3. 收款和成本现已在落库前调用 File 元数据校验:File 客户与表单客户一致、业务类型为 `FINANCE_VOUCHER`、文件存在且 MIME 为允许的图片类型。当前遗留是 `fileClient == null` 时仍跳过校验;放行前必须改为 fail-closed,并返回 `FIN-FILE-VALIDATION-UNAVAILABLE`。
4. 当前 File 模型没有用途区分和关联状态;首期可由 Finance 的 `voucherFileIds` 与财务资源事务性绑定作为关联事实,但必须防止跨客户引用。若后续增加 File 关联接口,需另行更新契约,不能在本版预先承诺 Outbox 行为。 4. 当前 File 模型没有用途区分和关联状态;首期可由 Finance 的 `voucherFileIds` 与财务资源事务性绑定作为关联事实,但必须防止跨客户引用。若后续增加 File 关联接口,需另行更新契约,不能在本版预先承诺 Outbox 行为。
5. 上传权限必须同时覆盖收款和成本创建人员;当前入口只有 `platform:finance:receipt:create`,因此成本凭证上传仍是门禁阻断。 5. 上传入口使用 `hasAnyAuthority('platform:finance:receipt:create','platform:finance:cost:create')`,收款和成本创建人员均可上传。
6. 客户侧收款 DTO 不返回 `voucherFileIds`、`voucherNo`、内部状态、内部备注或下载地址;首期客户不能查看平台收款/成本凭证。 6. 客户侧收款 DTO 不返回 `voucherFileIds`、`voucherNo`、内部状态、内部备注或下载地址;首期客户不能查看平台收款/成本凭证。
## 4. 接口清单 ## 4. 接口清单
@@ -89,6 +95,7 @@
| POST | `/api/platform/finance/v1/bills/{billId}/issue` | 出账并冻结 | | POST | `/api/platform/finance/v1/bills/{billId}/issue` | 出账并冻结 |
| POST | `/api/platform/finance/v1/bills/{billId}/adjust` | 出账后调整/生成新版本 | | POST | `/api/platform/finance/v1/bills/{billId}/adjust` | 出账后调整/生成新版本 |
| POST | `/api/platform/finance/v1/bills/{billId}/void` | 作废账单 | | POST | `/api/platform/finance/v1/bills/{billId}/void` | 作废账单 |
| GET | `/api/platform/finance/v1/bills/{billId}/revisions?customerId=` | 查询账单修订历史并校验客户归属 |
| POST | `/api/platform/finance/v1/receipts` | 人工登记收款并分配账单 | | POST | `/api/platform/finance/v1/receipts` | 人工登记收款并分配账单 |
| GET | `/api/platform/finance/v1/receipts` | 查询收款记录 | | GET | `/api/platform/finance/v1/receipts` | 查询收款记录 |
| POST | `/api/platform/finance/v1/cost-entries` | 人工登记单票/整柜成本 | | POST | `/api/platform/finance/v1/cost-entries` | 人工登记单票/整柜成本 |
@@ -139,7 +146,7 @@
## 6. 验收用例 ## 6. 验收用例
1. 平台财务创建 CNY 草稿账单,保存后可继续编辑。 1. 平台财务创建 CNY 草稿账单,保存后可继续编辑。
2. 账单出账生成账单号和到期日(出账日+客户账期,默认 30 天)。 2. 账单创建时按账单日期生成到期日(`billDate + creditDays`,默认 30 天),出账后冻结。
3. 出账后修改金额被拒绝;通过调整或作废重开保留原版本。 3. 出账后修改金额被拒绝;通过调整或作废重开保留原版本。
4. 登记 300 元收款,上传一张凭证并分配到 3 张 100 元账单,三张账单均更新余额。 4. 登记 300 元收款,上传一张凭证并分配到 3 张 100 元账单,三张账单均更新余额。
5. 一张账单分两次收款后显示 `PARTIALLY_PAID`,余额归零后显示 `PAID`。 5. 一张账单分两次收款后显示 `PARTIALLY_PAID`,余额归零后显示 `PAID`。
@@ -149,9 +156,10 @@
9. 登记单票成本前校验订单存在且属于客户;整柜公共成本仅使用服务端真实快照分摊,零总体积直接拒绝。 9. 登记单票成本前校验订单存在且属于客户;整柜公共成本仅使用服务端真实快照分摊,零总体积直接拒绝。
10. 重复 `Idempotency-Key` 且同参返回原结果;同键不同请求返回 `FIN-IDEMPOTENCY-CONFLICT`。 10. 重复 `Idempotency-Key` 且同参返回原结果;同键不同请求返回 `FIN-IDEMPOTENCY-CONFLICT`。
11. 同键同参处于 `PROCESSING` 时返回 409、`FIN-IDEMPOTENCY-PROCESSING` 和 `Retry-After`,不会生成第二张单。 11. 同键同参处于 `PROCESSING` 时返回 409、`FIN-IDEMPOTENCY-PROCESSING` 和 `Retry-After`,不会生成第二张单。
12. File 凭证客户、业务类型、状态或 MIME 任一不匹配,或 File 校验不可用时,收款/成本和分配均不落库。 12. File 凭证客户、业务类型或 MIME 任一不匹配时,收款/成本和分配均不落库;File 客户端缺失或不可用场景仍需补 fail-closed 验收。
13. 整柜自动分摊按 6 位 `HALF_UP` 计算,合计严格等于成本金额;只有实际发生尾差时最后一票才标记 `roundingAdjustment=true` 并保存非零 `roundingDelta`。 13. 整柜自动分摊按 Firstleg 真实体积快照和 6 位 `HALF_UP` 计算,合计严格等于成本金额;只有实际发生尾差时最后一票才标记 `roundingAdjustment=true`。
14. 客户列表、详情和收款记录均看不到 `DRAFT/VOIDED` 账单,也看不到平台凭证 fileId 和内部备注。 14. 平台按 `customerId + billId` 查询 revision 成功;跨客户账单拒绝且不返回修订快照。
15. 客户列表、详情和收款记录均看不到 `DRAFT/VOIDED` 账单,也看不到平台凭证 fileId 和内部备注。
## 7. 权限矩阵 ## 7. 权限矩阵
@@ -164,4 +172,4 @@
- Admin:平台财务路由和三个写表单。 - Admin:平台财务路由和三个写表单。
- Client:账单/收款只读查询。 - Client:账单/收款只读查询。
本契约记录开发目标与当前过渡接口;是否可测试以门禁审查结论为准。当前 Java 返回的 JDBC `snake_case Map`、公开请求体积和非分页数组均属于过渡实现,不能据此放行。 本契约记录开发目标与当前实现;是否可测试以门禁审查结论为准。当前 Java 返回的 JDBC `snake_case Map` 和非分页数组仍属于过渡实现。整柜成本的浏览器体积输入已从后端契约移除,但 Admin 消费端尚需同步。
+25 -25
View File
@@ -1,24 +1,24 @@
# Firstleg-Finance 跨服务契约(技术草案) # Firstleg-Finance 跨服务契约(技术草案)
> 版本:V0.1(开发前冻结草案) > 版本:V0.3(一期五页来源链路实现对齐)
> 日期:2026-08-10 > 日期:2026-08-11
> 状态:技术边界已确认;业务口径以《财务管理产品确认表》为准,未将产品待确认项擅自固化。 > 状态:技术边界和一期产品口径已确认;Firstleg 事件/Relay/快照与 Finance Inbox/来源写入已实现并通过定向测试。
本文是 `firstleg-service` 与规划中的 `finance-service` 之间的技术契约草案。它只规定服务边界、传输可靠性和来源快照,不替代财务账单、收款、核销、汇率或收入确认规则。 本文是 `firstleg-service` 与已落地 `finance-service` 之间的费用来源技术契约。产品范围以《财务一期五页产品与接口验收契约》为准。
## 1. 事实依据与当前实现差异 ## 1. 事实依据与当前实现差异
当前 Firstleg 已有 `fl_inbound_outbox`(与入库事务同库写入)和发布状态/重试字段;`FbaPricingService` 已发布 `FIRSTLEG_FEE_SENT`,调整已发布费用时发布 `FIRSTLEG_FEE_ADJUSTED`。现有 payload 主要只有 `inboundId`、`feeId`、`feeVersion`,Finance 不得把它当作完整财务凭证,必须再调用受保护的来源快照接口。 当前 Firstleg 使用 `fl_inbound_outbox` 与业务事务同库记录统一事件信封,Outbox Relay 至少一次投递到 `POST /internal/finance/v1/fee-source-events`;事件只携带入库/柜子 ID、费用 ID 和版本,Finance 必须再调用受保护的来源快照接口,不能把短 payload 当作财务凭证。
当前代码没有独立 Finance 消费者、`FIRSTLEG_FEE_VOIDED` 事件或 Finance 数据库;下列事件版本、信封、消费表和接口均为实施时新增/补齐的契约,不代表已上线。 Finance 已实现内部事件 Controller、令牌鉴权、Inbox 同事件哈希幂等、Firstleg 快照回查,以及 `fin_fee_source` 新版本写入、旧版本替代和作废保留。非作废事件显式要求 `publicationStatus=PUBLISHED`,否则返回 `FIN-EVT-015`;金额必须 `>0`,零/负值返回 `FIN-EVT-010`。Finance 来源专项 10/10、全量 35/35 BUILD SUCCESS,Firstleg 事件/Relay/快照/柜子费用相关测试 17/17 通过。
## 2. 事件目录 ## 2. 事件目录
| 事件名 | 生产时机 | Finance 处理 | 备注 | | 事件名 | 生产时机 | Finance 处理 | 备注 |
|---|---|---|---| |---|---|---|---|
| `FIRSTLEG_FEE_PUBLISHED` | 费用确认并发送、来源明细发布成功 | 建立/更新来源池候选,待规则校验 | 首版可由现有 `FIRSTLEG_FEE_SENT` 兼容映射;新契约统一使用 PUBLISHED | | `FIRSTLEG_FEE_PUBLISHED` | 入库或柜子费用审核通过、参与结算并发布;由 `aggregateType/payload` 区分来源 | 写入不可变来源版本 | 已实现并验证 |
| `FIRSTLEG_FEE_ADJUSTED` | 已发布费用被调整,新版本替代旧版本 | 原来源保留,新增调整来源;不得覆盖已出账明细 | 只有来源版本递增且哈希改变才接受 | | `FIRSTLEG_FEE_ADJUSTED` | 入库或柜子费用调整产生新版本 | 追加新版本并将旧 `AVAILABLE` 标为 `SUPERSEDED` | 已实现并验证 |
| `FIRSTLEG_FEE_VOIDED` | 费用来源作废 | 标记来源作废;若已入账,生成冲销/补差任务,不自动删除应收 | 需要 Firstleg 补充明确作废动作及原因 | | `FIRSTLEG_FEE_VOIDED` | 入库或柜子费用作废 | 将同版本来源标为 `VOIDED`,不物理删除 | 已实现并验证 |
事件不是“已生成应收”通知;Finance 仍按产品确认的入池条件(例如 `settlementIncluded`、审核状态和作废状态)决定是否进入可出账池。 事件不是“已生成应收”通知;Finance 仍按产品确认的入池条件(例如 `settlementIncluded`、审核状态和作废状态)决定是否进入可出账池。
@@ -26,11 +26,11 @@
```json ```json
{ {
"eventId": "fl-01J...", "eventType": "FIRSTLEG_FEE_PUBLISHED", "eventId": "FIRSTLEG_FEE:INBOUND:456:789:2:FIRSTLEG_FEE_PUBLISHED", "eventType": "FIRSTLEG_FEE_PUBLISHED",
"eventVersion": 1, "producer": "firstleg-service", "occurredAt": "2026-08-10T10:20:30.123+08:00", "eventVersion": 1, "producer": "firstleg-service", "occurredAt": "2026-08-10T10:20:30.123+08:00",
"tenantId": "123", "aggregateType": "INBOUND", "aggregateId": "456", "tenantId": "123", "aggregateType": "INBOUND", "aggregateId": "456",
"sequence": 3, "idempotencyKey": "FIRSTLEG_FEE:456:789:2", "sequence": 2, "idempotencyKey": "FIRSTLEG_FEE:INBOUND:456:789:2:FIRSTLEG_FEE_PUBLISHED",
"payloadHash": "sha256...", "traceId": "...", "payload": { "inboundId": "456", "feeId": "789", "feeVersion": 2 } "payloadHash": "sha256...", "payload": { "inboundId": "456", "containerId": null, "feeId": "789", "feeVersion": 2 }
} }
``` ```
@@ -40,24 +40,25 @@
Finance 使用服务间令牌调用 Firstleg(不经过客户端权限,不共享 Entity): Finance 使用服务间令牌调用 Firstleg(不经过客户端权限,不共享 Entity):
`GET /internal/firstleg/v1/inbounds/{inboundId}/fees/{feeId}/source-snapshot` 目标:`GET /internal/firstleg/v1/inbounds/{inboundId}/fees/{feeId}/source-snapshot`
请求头:`X-Service-Name: finance-service`、`X-Service-Token`、`X-Request-Id`。令牌由环境密钥管理,按服务名、路径和方法授予最小权限;拒绝客户端 JWT 伪造内部调用。 入库和柜子来源快照接口均已实现并通过 Firstleg 定向测试;Finance Feign Client 使用相同路径和内部令牌。既有 `/internal/firstleg/v1/finance-cost-snapshots/customers/{customerId}/containers/{containerId}` 仍只是体积分摊接口,不能作为费用来源快照使用。
请求头:`X-Internal-Service-Token`。令牌由环境密钥管理;Firstleg Controller 使用恒定时间比较校验,拒绝客户端 JWT 伪造内部调用。
响应 DTO 至少包含: 响应 DTO 至少包含:
```text ```text
tenantId, inboundId, inboundCode, customerId, customerName, tenantId, sourceType, feeId, feeVersion,
feeId, feeNo, feeVersion, sourceType, direction, businessDate, inboundId, inboundCode, orderId, containerId, containerBookingId, containerNo,
currency, subtotalAmount, additionalAmount, totalAmount, customerId, customerName, feeItemId, feeItemCode, feeItemName,
feeStatus, publicationStatus, settlementIncluded, publishedAt, direction, businessDate, currency, totalAmount,
chargeUnit, chargeableQuantity, actualGrossWeightKg, actualVolumeCbm, reviewStatus, publicationStatus, settlementIncluded, publishedAt,
originWarehouseId/name, channelCode/name, destinationCode/name, chargeableQuantity, chargeUnit, actualGrossWeightKg, actualVolumeCbm,
items[{feeItemId, feeCode, name, quantity, unit, unitPrice, amount}],
sourceHash, snapshotVersion sourceHash, snapshotVersion
``` ```
响应必须是当前 Firstleg 已发布版本的不可变业务快照;Finance 将完整 DTO 和 `sourceHash` 存入自有来源池。若上游只返回 `SUPERSEDED`/`VOID` 版本,Finance 不得将其作为新应收来源。 Finance 将完整 DTO 和 `sourceHash` 存入自有来源池。非 `FIRSTLEG_FEE_VOIDED` 事件只接受 `publicationStatus=PUBLISHED`;未发布返回 `FIN-EVT-015`。作废事件允许读取对应作废版本,但只能把既有来源标为 `VOIDED`,不得创建新来源。
建议附加只读校验接口:`GET /internal/firstleg/v1/inbounds/{inboundId}/fees/{feeId}/publication`,用于消费重试时快速判断发布状态;该接口不能返回跨客户数据。 建议附加只读校验接口:`GET /internal/firstleg/v1/inbounds/{inboundId}/fees/{feeId}/publication`,用于消费重试时快速判断发布状态;该接口不能返回跨客户数据。
@@ -116,7 +117,6 @@ Firstleg Outbox 发布采用至少一次投递:指数退避(建议 10s、30s
技术已确认:独立服务/数据库、DTO/事件通信、Outbox 至少一次、Finance Inbox 幂等、不可变来源快照、无跨库 Join、服务令牌、错误隔离和审计要求。 技术已确认:独立服务/数据库、DTO/事件通信、Outbox 至少一次、Finance Inbox 幂等、不可变来源快照、无跨库 Join、服务令牌、错误隔离和审计要求。
仍依赖产品确认:何时 `settlementIncluded`、何种来源进入应收;客户/供应商账单聚合和确认节点;调整/作废对已出账单的补差或冲销策略;汇率、财务期间和收入/成本确认口径;客户账户是否抵扣应收。上述未确认项不得由事件消费者自行推断。 产品口径已冻结:只有 `APPROVED + PUBLISHED + settlementIncluded=true + ACTIVE + CNY` 来源可入池;一期按客户/供应商形成五页单据,出账后冻结,调整/作废重开保留版本和原因;不做汇率、月结、钱包抵扣、费用分析和利润表。事件消费者不得从历史原型推断这些已排除能力。剩余问题是来源模型、接口、事件和消费者实现,不是产品冲突。
主要风险:现有 `FIRSTLEG_FEE_SENT` payload 过小且 Outbox 未带 `eventVersion/payloadHash/sequence`;当前没有明确的作废 API;`fl_consumed_event` 属 Firstleg 内部消费表,不能直接复用为 Finance Inbox。实施时需新增兼容字段/映射和回放工具,并在切换前验证历史费用版本的唯一性与哈希完整性。
主要剩余风险:测试环境尚未完成 Firstleg Relay → Finance Inbox → `fin_fee_source` 的真实 HTTP 冒烟。产品已确认无历史财务数据,不需要历史事件回放方案。
+41 -24
View File
@@ -1,7 +1,7 @@
# 财务管理闭环盘点与范围建议 # 财务管理闭环盘点与范围建议
> 盘点日期:2026-08-10 > 盘点日期:2026-08-10
> 当前状态:F0/F1 已有 Finance 服务、数据库、权限、Admin/Client 页面和基础接口实现;专项契约与闭环缺口修复中 > 当前状态:F0/F1 已有 Finance 服务、数据库、权限、Admin/Client 页面和基础接口;费用来源主链、固定 DTO、脱敏、凭证 fail-closed 和稳定错误码已通过后端验证,剩余为五页页面与未实现 operation 收口
> 盘点范围:二期入库计费现状、平台后台财务原型、Admin/Client/Firstleg 当前实现 > 盘点范围:二期入库计费现状、平台后台财务原型、Admin/Client/Firstleg 当前实现
> 结论口径:本文区分“代码已实现”“原型展示”和“建议范围”;原型功能不自动成为开发范围。 > 结论口径:本文区分“代码已实现”“原型展示”和“建议范围”;原型功能不自动成为开发范围。
@@ -13,6 +13,19 @@
开发前总控门禁与 F0/F1 任务清单:[财务开工门禁与F0-F1任务清单](财务开工门禁与F0-F1任务清单.md)。 开发前总控门禁与 F0/F1 任务清单:[财务开工门禁与F0-F1任务清单](财务开工门禁与F0-F1任务清单.md)。
一期领导验收唯一范围入口:[财务一期五页产品与接口验收契约](财务一期五页产品与接口验收契约.md)。
文档优先级:五页验收契约和本轮产品确认 > 五页目标 OpenAPI > 既有人工 F1 契约/门禁 > 领域模型、历史全量规划和迁移文档。旧文档用于追溯,不得据此把钱包、充值、发票、费用分析或利润表重新纳入一期。
旧文档降级规则:
| 文档/章节 | 当前用途 | 一期实施约束 |
|---|---|---|
| 本文第六节起的“历史全量规划” | 保存早期盘点和演进背景 | 与五页契约冲突时全部失效,不作为菜单、路由、字段或接口依据 |
| `财务领域模型与跨服务契约.md` | 历史合并稿 | 已被数据字典和跨服务契约替代 |
| `财务服务边界设计.md`、`财务领域模型与数据字典.md` | 服务边界和长期模型参考 | 其中钱包、充值、发票、费用分析、利润模型不属于一期 |
| `财务历史迁移与上线验收方案.md`、`财务F0实施任务拆分.md` | 历史迁移、底座任务追溯 | 不得覆盖五页范围和当前实现状态 |
详细设计材料: 详细设计材料:
- [财务来源接入现状](财务来源接入现状.md) - [财务来源接入现状](财务来源接入现状.md)
@@ -20,6 +33,8 @@
- [Firstleg-Finance跨服务契约](Firstleg-Finance跨服务契约.md) - [Firstleg-Finance跨服务契约](Firstleg-Finance跨服务契约.md)
- [F1 人工账单、收款、成本接口契约](F1人工账单收款成本接口契约.md) - [F1 人工账单、收款、成本接口契约](F1人工账单收款成本接口契约.md)
- [F1 人工财务契约审查与门禁](F1人工财务契约审查与门禁.md) - [F1 人工财务契约审查与门禁](F1人工财务契约审查与门禁.md)
- [财务一期五页产品与接口验收契约](财务一期五页产品与接口验收契约.md)
- [财务一期五页 OpenAPI](openapi/finance-phase1-five-pages-v1.yaml)
- [财务历史迁移与上线验收方案](财务历史迁移与上线验收方案.md) - [财务历史迁移与上线验收方案](财务历史迁移与上线验收方案.md)
- [财务F0实施任务拆分](财务F0实施任务拆分.md) - [财务F0实施任务拆分](财务F0实施任务拆分.md)
@@ -54,9 +69,9 @@
-> 客户只读查询 -> 客户只读查询
``` ```
当前仍需修复:固定响应 DTO、收款/成本凭证 fail-closed 校验、Firstleg 真实体积快照与客户归属校验、完整幂等请求哈希与恢复、客户收款专用 DTO,以及 Admin 客户账期和修订历史查询。完成《F1人工财务契约审查与门禁》中的测试门禁后,才能宣称 F1 人工财务闭环通过验收。 后端当前已完成 Firstleg 真实柜次体积快照、客户归属、成本凭证校验、revision、双权限上传、费用来源事件/Relay/快照、Finance `fin_fee_source` 消费写入和完整幂等;Finance 35/35、Firstleg 549/549(2 skip)、File 114/114、Gateway 26/26、IAM 163/163、Phase3/PDA SQL 12/12、Order SQL 3/3,均 BUILD SUCCESS。当前剩余是 Admin 客户账期/revision 与五页页面动作,以及 11 个目标 operation;完成《F1人工财务契约审查与门禁》剩余门禁后才能宣称一期页面闭环通过验收。
本轮确认“全部都需要做”后,目标范围升级为覆盖原型财务菜单的完整财务域:客户账户、客户应收应付、客户对账单、结算单应收、结算单应付、收付款与核销、费用分析、发票和利润报表。仍建议按依赖关系分阶段交付,避免在应收、应付、钱包和利润各自造一套金额口径。 一期范围已重新冻结为原型 5 页:客户账户、客户应收应付、客户对账单、结算单应收、结算单应付。费用分析、利润表、发票和钱包不做,也不保留菜单、路由或假按钮。客户账户改为账单、收款和应收应付来源派生的财务往来总览,不做充值/预收。
## 二、事实来源与边界 ## 二、事实来源与边界
@@ -118,38 +133,40 @@ Firstleg 已有 `fl_inbound_fee_detail`,包含:
| 原型模块 | 原型展示的主要能力 | 当前代码状态 | 是否能直接纳入首期 | | 原型模块 | 原型展示的主要能力 | 当前代码状态 | 是否能直接纳入首期 |
|---|---|---|---| |---|---|---|---|
| 客户账户 | 余额、冻结金额、可用余额、充值、扣款流水 | 未实现 | 否,这是预存款/钱包模型,需单独确认资金合规和扣款规则 | | 客户账户 | 原型为余额、冻结、可用余额和充值流水 | 未实现 | 一期保留汇总/详情/流水结构,但改为未收、待出账、本期已收等派生指标;删除充值/钱包能力 |
| 客户应收应付 | 费用明细、审核、参与结算、按截止时间或勾选生成账单 | 仅有入库费用明细后端基础;无正式财务页面 | 可裁剪为应收费用池 | | 客户应收应付 | 费用明细、审核、参与结算、按截止时间或勾选生成账单 | 仅有入库费用明细后端基础;无正式财务页面 | 可裁剪为应收费用池 |
| 客户对账单 | 账期、汇率、应收、已收、结清、明细和支付历史 | 未实现 | 可作为应收闭环核心,但汇率和开票先暂缓 | | 客户对账单 | 账期、汇率、应收、已收、结清、明细和支付历史 | 未实现 | 可作为应收闭环核心,但汇率和开票先暂缓 |
| 结算单应收 | 应收、已收、余额、到期日、审批、部分收款 | 未实现 | 可合并进账单/应收单,避免首期重复建模 | | 结算单应收 | 应收、已收、余额、到期日、审批、部分收款 | 未实现 | 可合并进账单/应收单,避免首期重复建模 |
| 结算单应付 | 供应商应付、已付、余额、审批、部分付款、利润 | 未实现;上游成本来源不完整 | 否,建议后续独立阶段 | | 结算单应付 | 供应商应付、已付、余额、审批、部分付款、利润 | 未实现;上游成本来源不完整 | 一期纳入,但删除利润字段/按钮;必须先补真实供应商应付来源和付款凭证链路 |
| 费用分析 | 内外部费用对比、趋势和明细 | 未实现 | 否,依赖稳定应收/应付口径 | | 费用分析 | 内外部费用对比、趋势和明细 | 未实现 | 一期明确不做,不进菜单/路由 |
| 利润表 | 按客户、货柜、单票、月份统计收入、成本、利润率 | 未实现 | 否,依赖应收、成本、汇率及分摊规则 | | 利润表 | 按客户、货柜、单票、月份统计收入、成本、利润率 | 未实现 | 一期明确不做,不进菜单/路由 |
原型还出现了发票抬头、开票日期、汇率、支付方式、收付款凭证号等字段。它们只说明未来可能需要,不代表当前产品已经确认税务、外币折算、资金或发票边界。 原型还出现了发票抬头、开票日期、汇率、支付方式、收付款凭证号等字段。它们只说明未来可能需要,不代表当前产品已经确认税务、外币折算、资金或发票边界。
当前 Admin 已有正式财务路由、账单详情/草稿修改/出账/调整/作废、人工收款和成本页面及真实凭证上传调用,Client 已有正式只读账单页面;但 Admin 未接客户账期和修订历史,成本仍允许人工填写柜内体积,File 全量测试在发现阶段失败,后端成本凭证校验也未接通,因此只能视为修复中的实现,不能视为已验收交付。 当前 Admin 已有正式财务路由、账单详情/草稿修改/出账/调整/作废、人工收款和成本页面及真实凭证上传调用,Client 已有正式只读账单页面。后端已改为根据 `containerId` 调 Firstleg 体积快照并完成成本凭证校验,但 Admin 仍强制人工填写并提交柜内订单体积,且未接客户账期和 revision,因此前端创建闭环尚未与最终契约对齐。
## 五、当前修复中缺口 ## 五、当前修复中缺口
| 序号 | 断点 | 直接影响 | | 序号 | 断点 | 直接影响 |
|---|---|---| |---|---|---|
| 1 | Finance 仍直接返回 JDBC `Map/List<Map>` | 字段和响应结构未形成稳定 DTO,前端依赖临时适配 | | 1 | 五页读接口、平台/客户固定 DTO 和追踪响应已实现 | Finance 35/35 BUILD SUCCESS;本轮使用现有 Surefire 报告核对,不重新执行 Maven |
| 2 | 凭证已可上传,但成本未校验,收款校验存在 fail-open,且 File 全量测试故障 | Admin 收款/成本真实创建闭环不能放行 | | 2 | 收款和成本均已校验凭证,但 `fileClient == null` 时仍 fail-open | File 客户端缺失时可能绕过凭证校验 |
| 3 | 整柜分摊已落库,但体积由请求人工填写且归属未向 Firstleg 校验 | 分摊结果不可证明来自真实柜次快照 | | 3 | 后端已使用 Firstleg 真实体积快照,Admin 仍要求人工填写并提交体积 | 页面与最终请求契约不一致,产生无效输入和误导 |
| 4 | 幂等已有 SHA-256 与同参重放,但未覆盖完整规范化请求,缺 PROCESSING 恢复测试 | 仍可能误判同参或无法恢复中间态 | | 4 | 幂等已有 SHA-256 与同参重放,但未覆盖完整规范化请求,缺 PROCESSING 恢复测试 | 仍可能误判同参或无法恢复中间态 |
| 5 | 客户账单已过滤可见状态,收款列表仍暴露平台字段且未按可见账单过滤 | 客户只读边界仍不完整 | | 5 | 客户账单已过滤可见状态,收款列表仍暴露平台字段且未按可见账单过滤 | 客户只读边界仍不完整 |
| 6 | Admin 已接账单动作,但未接客户账期、修订历史,整柜仍人工填体积 | 平台财务页面仍非完整闭环 | | 6 | Admin 已接账单动作,但未接客户账期、revision,整柜仍人工填体积 | 平台财务页面仍非完整闭环 |
| 7 | 业务错误码仍以通用错误和中文消息为主 | 前端无法稳定区分版本、幂等、凭证和归属错误 | | 7 | 业务错误码仍以通用错误和中文消息为主 | 前端无法稳定区分版本、幂等、凭证和归属错误 |
| 8 | 修订快照已有表和写入逻辑,但缺少查询展示 | 调整历史尚不能由产品和测试人员核对 | | 8 | revision 后端查询已落地,Admin 尚未接展示 | 调整历史仍不能在产品页面核对 |
## 六、全量财务规划与交付顺序 ## 六、全量财务规划与交付顺序
### 6.1 全量目标域 ### 6.1 历史全量规划(不作为一期范围)
以下内容只保留为历史分析。若与《财务一期五页产品与接口验收契约》冲突,以五页契约为准。
| 目标域 | 业务结果 | 主要来源 | 不能提前假定的口径 | | 目标域 | 业务结果 | 主要来源 | 不能提前假定的口径 |
|---|---|---|---| |---|---|---|---|
| 客户账户 | 预存、冻结、扣款、退款、账户流水 | 客户充值、业务扣款 | 是否采用钱包作为应收结算方式、资金归属和退款规则 | | 客户账户 | 客户财务往来派生汇总、详情和流水 | 账单、收款和应收应付来源 | 一期不建设钱包、充值、预收或自动扣款 |
| 客户应收 | 客户欠款、到期、逾期、结清 | 已发布对客费用、补差/冲销 | 收入确认节点和账期规则 | | 客户应收 | 客户欠款、到期、逾期、结清 | 已发布对客费用、补差/冲销 | 收入确认节点和账期规则 |
| 客户应付 | 客户代垫或返还类应付款(如确有业务) | 业务费用或人工单据 | 产品是否真的存在“平台向客户付款”的场景 | | 客户应付 | 客户代垫或返还类应付款(如确有业务) | 业务费用或人工单据 | 产品是否真的存在“平台向客户付款”的场景 |
| 客户对账单 | 期间内费用汇总、明细、平台出账和客户只读查看 | 应收/应付费用池 | 一张账单是否允许混合方向、混合币种 | | 客户对账单 | 期间内费用汇总、明细、平台出账和客户只读查看 | 应收/应付费用池 | 一张账单是否允许混合方向、混合币种 |
@@ -157,7 +174,7 @@ Firstleg 已有 `fl_inbound_fee_detail`,包含:
| 结算单应付 | 供应商成本、付款、余额和结清 | 供应商费用、运力/仓储/报关成本 | 成本确认、供应商账期、审批和付款方式 | | 结算单应付 | 供应商成本、付款、余额和结清 | 供应商费用、运力/仓储/报关成本 | 成本确认、供应商账期、审批和付款方式 |
| 收付款与核销 | 到账/付款凭证,部分结算、反核销 | 银行流水或人工登记 | 是否首期接银行流水,是否允许一笔多单核销 | | 收付款与核销 | 到账/付款凭证,部分结算、反核销 | 银行流水或人工登记 | 是否首期接银行流水,是否允许一笔多单核销 |
| 发票 | 开票申请、开具、红冲、作废和关联 | 已确认应收/收款 | 税率、含税/未税、开票主体、外部平台 | | 发票 | 开票申请、开具、红冲、作废和关联 | 已确认应收/收款 | 税率、含税/未税、开票主体、外部平台 |
| 费用分析 | 按费用项目、客户、供应商、期间分析 | 应收应付台账 | 统计按发生制还是结算制 | | 费用分析 | 历史规划,一期不做 | 应收应付台账 | 不进入一期菜单、路由和验收 |
| 利润 | 客户/单票/柜次/月度收入、成本、利润率 | 应收收入 + 应付成本 + 分摊 | 汇率、成本分摊、收入成本确认时间 | | 利润 | 客户/单票/柜次/月度收入、成本、利润率 | 应收收入 + 应付成本 + 分摊 | 汇率、成本分摊、收入成本确认时间 |
### 6.2 分阶段交付顺序 ### 6.2 分阶段交付顺序
@@ -169,8 +186,8 @@ Firstleg 已有 `fl_inbound_fee_detail`,包含:
| F0 财务底座 | 独立 Finance 服务/数据库、财务主体、客户/供应商往来单位、币种、费用科目、期间、权限、审计、幂等、金额精度 | 所有后续对象使用同一基础口径 | 服务边界已技术确认;产品确认主体、币种、权限和编码 | | F0 财务底座 | 独立 Finance 服务/数据库、财务主体、客户/供应商往来单位、币种、费用科目、期间、权限、审计、幂等、金额精度 | 所有后续对象使用同一基础口径 | 服务边界已技术确认;产品确认主体、币种、权限和编码 |
| F1 应收与客户对账 | 应收费用池、平台出账、客户只读查看、结算单应收、收款登记、核销、反核销 | 费用 → 账单 → 应收 → 收款 → 结清 | 当前已发布对客费用来源 | | F1 应收与客户对账 | 应收费用池、平台出账、客户只读查看、结算单应收、收款登记、核销、反核销 | 费用 → 账单 → 应收 → 收款 → 结清 | 当前已发布对客费用来源 |
| F2 应付与供应商结算 | 成本费用池、供应商账单、结算单应付、付款登记、付款核销、应付调整 | 成本 → 供应商账单 → 应付 → 付款 → 结清 | 供应商主数据和真实成本来源 | | F2 应付与供应商结算 | 成本费用池、供应商账单、结算单应付、付款登记、付款核销、应付调整 | 成本 → 供应商账单 → 应付 → 付款 → 结清 | 供应商主数据和真实成本来源 |
| F3 客户账户与发票 | 充值、冻结、扣款、退款、账户流水;开票申请、开票登记、红冲/作废 | 账户余额与应收核销可选联动;应收与发票可追溯 | 资金/税务主体、开票平台和合规口径 | | F3 客户账户与发票 | 一期只做派生客户账户总览;发票暂缓 | 账户只读聚合,不维护资金余额 | 发票不属于一期 |
| F4 分析与利润 | 费用分析、收入成本汇总、客户/单票/柜次/月度利润、利润率、导出 | 应收与应付同源统计,结果可追溯 | F1/F2 结算数据、汇率和分摊规则 | | F4 分析与利润 | 一期不做 | 不建设菜单、路由或假入口 | 后续重新立项 |
阶段之间可以并行做页面原型和契约设计,但生产数据链路必须按 F0 → F1/F2 → F3 → F4 验收。F4 不能用原型静态数字先行替代真实台账。 阶段之间可以并行做页面原型和契约设计,但生产数据链路必须按 F0 → F1/F2 → F3 → F4 验收。F4 不能用原型静态数字先行替代真实台账。
@@ -199,9 +216,9 @@ F1 建议页面:
4. 核销记录:每笔收款对应哪些应收、核销金额、剩余余额、反核销历史。 4. 核销记录:每笔收款对应哪些应收、核销金额、剩余余额、反核销历史。
5. 客户侧账单:只读明细、查看收款与未结余额;异议通过线下渠道反馈。 5. 客户侧账单:只读明细、查看收款与未结余额;异议通过线下渠道反馈。
F1 暂不包含(在 F2-F4 交付): 以下历史排除清单已被 2026-08-11 的五页范围取代。结算单应付现在属于一期;其余未确认能力继续排除:
- 供应商应付与付款; - 供应商在线确认和自动付款(应付结算单与人工付款属于一期);
- 客户预充值、余额冻结和自动扣款; - 客户预充值、余额冻结和自动扣款;
- 发票申请、开票和税务接口; - 发票申请、开票和税务接口;
- 多币种折算与汇兑损益; - 多币种折算与汇兑损益;
@@ -213,20 +230,20 @@ F1 暂不包含(在 F2-F4 交付):
| 范围 | 开工门禁 | | 范围 | 开工门禁 |
|---|---| |---|---|
| 客户账户 | 明确充值是否真实入账、冻结/解冻、退款、自动扣款和资金对账责任;不得直接拿账户余额抵消应收而不留核销记录 | | 客户账户 | 已确认只做派生财务往来总览;禁止充值、冻结/解冻、退款、自动扣款和可写余额 |
| 客户应收应付 | 明确客户作为付款方还是收款方;没有真实业务场景的方向不建菜单和数据 | | 客户应收应付 | 明确客户作为付款方还是收款方;没有真实业务场景的方向不建菜单和数据 |
| 供应商应付 | 必须有供应商主数据、成本来源凭证、审批人、付款方式和付款责任主体 | | 供应商应付 | 必须有供应商主数据、成本来源凭证、审批人、付款方式和付款责任主体 |
| 收付款核销 | 明确人工登记与银行流水的边界;收款、付款、核销、反核销分开授权 | | 收付款核销 | 明确人工登记与银行流水的边界;收款、付款、核销、反核销分开授权 |
| 发票 | 明确开票主体、税率、含税/未税、红冲/作废和外部开票平台;未确认前只保留接口扩展位 | | 发票 | 明确开票主体、税率、含税/未税、红冲/作废和外部开票平台;未确认前只保留接口扩展位 |
| 费用分析/利润 | 先冻结汇率、收入成本确认日、成本分摊和跨币种折算;报表必须能钻取到原始费用和结算单 | | 费用分析/利润 | 先冻结汇率、收入成本确认日、成本分摊和跨币种折算;报表必须能钻取到原始费用和结算单 |
## 七、必须先确认的产品问题 ## 七、已确认的产品结论(历史问题关闭结果)
以下结论没有确认前,只能做可逆的模型和页面设计,不能进入完整开发: 下表原为产品问题清单,现按本轮确认结果保留。不得再把这些条目解释为待产品确认;实现仍受真实费用来源链路和专项技术门禁约束。
| 编号 | 待确认问题 | 建议默认值 | | 编号 | 待确认问题 | 建议默认值 |
|---|---|---| |---|---|---|
| F1 | 全量范围是否按 F0 → F1 → F2 → F3 → F4 分阶段交付 | 是,目标范围全部保留;先完成 F0,再按依赖验收,不因先做应收而删除应付、账户、发票和利润 | | F1 | 一期领导验收范围 | 固定为客户账户、客户应收应付、客户对账单、结算单应收、结算单应付;费用分析和利润表不做 |
| F2 | 账单生成维度 | 客户 + 币种 + 账期;不同币种不合并 | | F2 | 账单生成维度 | 客户 + 币种 + 账期;不同币种不合并 |
| F3 | 哪些费用可以进入账单 | `APPROVED + PUBLISHED + settlementIncluded=true` 且未作废、未出账 | | F3 | 哪些费用可以进入账单 | `APPROVED + PUBLISHED + settlementIncluded=true` 且未作废、未出账 |
| F4 | 当前已发布头程费用是否自动进入待对账池 | 是,但仍由财务选择并生成账单 | | F4 | 当前已发布头程费用是否自动进入待对账池 | 是,但仍由财务选择并生成账单 |
+73 -39
View File
@@ -4,8 +4,9 @@ info:
version: 1.2.0 version: 1.2.0
description: >- description: >-
F1 人工账单、收款和成本目标契约。仅 CNY;平台财务可写;客户只读且仅可见 F1 人工账单、收款和成本目标契约。仅 CNY;平台财务可写;客户只读且仅可见
ISSUED、PARTIALLY_PAID、PAID 账单。固定 DTO、完整追踪字段、真实体积快照和 ISSUED、PARTIALLY_PAID、PAID 账单。整柜成本由 Finance 根据 containerId 调用
File fail-closed 校验属于放行目标;当前实现差异见契约门禁文档。 Firstleg 真实快照,浏览器不提交订单体积。固定 DTO、完整追踪字段和 File fail-closed
校验仍属于放行目标;当前实现差异见契约门禁文档。
servers: servers:
- url: /api - url: /api
paths: paths:
@@ -120,6 +121,21 @@ paths:
$ref: '#/components/responses/BillDetailResponse' $ref: '#/components/responses/BillDetailResponse'
'409': '409':
$ref: '#/components/responses/IdempotencyConflict' $ref: '#/components/responses/IdempotencyConflict'
/platform/finance/v1/bills/{billId}/revisions:
get:
summary: 查询账单修订历史
description: 只返回指定客户所属账单的调整前快照,跨客户或不存在账单统一拒绝。
x-permission: platform:finance:bill:view
security:
- platformFinance: []
parameters:
- $ref: '#/components/parameters/BillId'
- $ref: '#/components/parameters/RequiredCustomerId'
responses:
'200':
$ref: '#/components/responses/BillRevisionListResponse'
'404':
$ref: '#/components/responses/BusinessError'
/platform/finance/v1/bills/{billId}/adjust: /platform/finance/v1/bills/{billId}/adjust:
post: post:
summary: 调整已出账账单并保留修订历史 summary: 调整已出账账单并保留修订历史
@@ -204,9 +220,9 @@ paths:
post: post:
summary: 人工登记单票或整柜成本 summary: 人工登记单票或整柜成本
description: >- description: >-
SINGLE_ORDER 直接归属经服务端验证的同客户订单;CONTAINER_SHARED 当前请求包含 SINGLE_ORDER 直接归属经服务端验证的同客户订单;CONTAINER_SHARED 只提交 containerId,
containerOrders 过渡字段,但放行前必须改由服务端从 Firstleg 取得不可篡改体积快照。 Finance 从 Firstleg 取得属于该客户的柜内有效订单体积快照。快照为空或总体积无效时拒绝,
总体积为零时拒绝,首期不支持人工分摊。 首期不支持浏览器提交体积或人工分摊。
x-permission: platform:finance:cost:create x-permission: platform:finance:cost:create
security: security:
- platformFinance: [] - platformFinance: []
@@ -228,8 +244,8 @@ paths:
summary: 上传财务凭证图片 summary: 上传财务凭证图片
description: >- description: >-
当前 Finance Controller 的真实入口,query 参数为 customerId,multipart 字段为 file。 当前 Finance Controller 的真实入口,query 参数为 customerId,multipart 字段为 file。
当前 File 仅校验图片 MIME,尚无用途区分和关联状态;收款/成本落库前的 fail-closed 收款与成本创建均按客户、FINANCE_VOUCHER 业务类型和图片 MIME 校验元数据;
校验仍是门禁阻断。 File 客户端缺失时仍须改为 fail-closed,详见门禁文档。
x-permission-any-of: x-permission-any-of:
- platform:finance:receipt:create - platform:finance:receipt:create
- platform:finance:cost:create - platform:finance:cost:create
@@ -337,10 +353,6 @@ components:
type: string type: string
pattern: '^(0|[1-9][0-9]*)(\.[0-9]{1,6})?$' pattern: '^(0|[1-9][0-9]*)(\.[0-9]{1,6})?$'
example: '300.000000' example: '300.000000'
SignedMoney:
type: string
pattern: '^-?(0|[1-9][0-9]*)(\.[0-9]{1,6})?$'
example: '-0.000001'
ResponseMeta: ResponseMeta:
type: object type: object
required: required:
@@ -592,7 +604,6 @@ components:
required: required:
- costType - costType
- containerId - containerId
- containerOrders
properties: properties:
costType: costType:
type: string type: string
@@ -600,30 +611,6 @@ components:
- CONTAINER_SHARED - CONTAINER_SHARED
containerId: containerId:
$ref: '#/components/schemas/Id' $ref: '#/components/schemas/Id'
containerOrders:
type: array
minItems: 1
items:
$ref: '#/components/schemas/ContainerOrderVolumeInput'
description: >-
当前 Java 过渡请求字段。调用方不得把人工填写体积视为可信快照;放行前应由
Finance 根据 containerId 从 Firstleg 获取并校验,届时公开请求应移除此字段。
ContainerOrderVolumeInput:
type: object
required:
- orderId
- inboundId
- containerId
- volumeCbm
properties:
orderId:
$ref: '#/components/schemas/Id'
inboundId:
$ref: '#/components/schemas/Id'
containerId:
$ref: '#/components/schemas/Id'
volumeCbm:
$ref: '#/components/schemas/Money'
FinanceVoucherUploadRequest: FinanceVoucherUploadRequest:
type: object type: object
required: required:
@@ -733,6 +720,40 @@ components:
type: array type: array
items: items:
$ref: '#/components/schemas/BillLine' $ref: '#/components/schemas/BillLine'
BillRevision:
type: object
required:
- revisionId
- billId
- version
- reason
- billSnapshot
- lineSnapshot
- createdBy
- createdAt
properties:
revisionId:
$ref: '#/components/schemas/Id'
billId:
$ref: '#/components/schemas/Id'
version:
type: integer
minimum: 0
reason:
type: string
billSnapshot:
type: object
additionalProperties: true
lineSnapshot:
type: array
items:
type: object
additionalProperties: true
createdBy:
$ref: '#/components/schemas/Id'
createdAt:
type: string
format: date-time
ClientBillDetail: ClientBillDetail:
allOf: allOf:
- $ref: '#/components/schemas/ClientBill' - $ref: '#/components/schemas/ClientBill'
@@ -841,7 +862,6 @@ components:
- ratio - ratio
- allocatedAmount - allocatedAmount
- roundingAdjustment - roundingAdjustment
- roundingDelta
properties: properties:
orderId: orderId:
$ref: '#/components/schemas/Id' $ref: '#/components/schemas/Id'
@@ -857,8 +877,6 @@ components:
roundingAdjustment: roundingAdjustment:
type: boolean type: boolean
description: 仅实际尾差非零时为 true。 description: 仅实际尾差非零时为 true。
roundingDelta:
$ref: '#/components/schemas/SignedMoney'
Cost: Cost:
type: object type: object
required: required:
@@ -1033,6 +1051,17 @@ components:
code: {type: string, example: '200'} code: {type: string, example: '200'}
message: {type: string} message: {type: string}
data: {$ref: '#/components/schemas/BillDetail'} data: {$ref: '#/components/schemas/BillDetail'}
BillRevisionListEnvelope:
allOf:
- $ref: '#/components/schemas/ResponseMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data:
type: array
items: {$ref: '#/components/schemas/BillRevision'}
ClientBillDetailEnvelope: ClientBillDetailEnvelope:
allOf: allOf:
- $ref: '#/components/schemas/ResponseMeta' - $ref: '#/components/schemas/ResponseMeta'
@@ -1127,6 +1156,11 @@ components:
content: content:
application/json: application/json:
schema: {$ref: '#/components/schemas/BillDetailEnvelope'} schema: {$ref: '#/components/schemas/BillDetailEnvelope'}
BillRevisionListResponse:
description: 账单修订历史列表。
content:
application/json:
schema: {$ref: '#/components/schemas/BillRevisionListEnvelope'}
ClientBillDetailResponse: ClientBillDetailResponse:
description: 客户可见账单详情。 description: 客户可见账单详情。
content: content:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,174 @@
# 财务一期五页产品与接口验收契约
> 日期:2026-08-11
> 状态:产品范围已确认;Finance 来源链与五页查询契约已实现并验证,剩余 11 个目标 operation、Admin 五页接入及跨服务 HTTP 冒烟待完成
> 领导验收范围:客户账户、客户应收应付、客户对账单、结算单应收、结算单应付
> 原型依据:`docs/悦/货代SAAS平台后台/货代SaaS平台原型.html`
> 目标 OpenAPI:`openapi/finance-phase1-five-pages-v1.yaml`;当前人工接口继续参考 `openapi/finance-f1-manual-v1.yaml`。
## 1. 一期范围结论
一期只交付原型中的以下 5 页,并实现页面结构、字段、筛选、详情和状态:
1. 客户账户。
2. 客户应收应付。
3. 客户对账单。
4. 结算单应收。
5. 结算单应付。
明确不做:费用分析、利润表、钱包、预收、手动充值、自动扣款余额、汇率、外币、发票、月结、银行自动对账。未实现能力不得保留按钮、菜单、路由或模拟成功入口。
所有金额只使用 CNY。原型中的 USD、汇率、开票日期、利润审批、利润金额仅为历史原型字段,一期删除。
## 2. 客户账户冲突处理(已确认)
原型客户账户是“预充值余额 + 冻结 + 可用余额 + 手动充值”的钱包模型,与此前确认的“不做钱包/预收”冲突。产品已确认按以下方案处理,不再等待额外产品结论:
- 页面保留“客户账户”名称和客户汇总/详情/流水结构,但定位为客户财务往来总览,不是资金账户。
- 删除“手动充值”按钮、充值弹窗、充值方式和充值凭证号;不设计充值 API。
- 不显示可消费额度,不允许业务系统按余额自动扣款。
- 原型钱包指标改为财务派生指标:`未收余额`、`待出账金额`、`本期已收金额`;列表和详情使用相同口径。
- 流水只来自费用来源纳入/排除、对账单生成/调整/作废、结算单生效和人工收付款登记,不允许直接修改余额。
派生公式:
| 指标 | 公式 |
|---|---|
| 未收余额 | 生效应收结算单应收金额合计 - 已收金额合计 |
| 待出账金额 | `AVAILABLE + APPROVED + settlementIncluded=true` 且未进入有效对账单的应收费用来源金额合计 |
| 本期已收金额 | 查询期间内有效收款分配金额合计 |
| 应付余额 | 生效应付结算单应付金额合计 - 已付金额合计 |
## 3. 五页验收矩阵
| 页面 | 原型结构和筛选 | 一期字段 | 一期操作 | 状态与验收 |
|---|---|---|---|---|
| 客户账户 | 汇总卡、客户列表、账户详情、流水详情;客户名称/编号、账户状态、余额条件、流水类型和日期 | 客户基本信息、客户编号、联系人、电话、未收余额、待出账金额、本期已收金额、应付余额、账户状态、最后变动时间;流水号、时间、业务类型、关联单据、应收/应付变动、变动后未收余额、操作人、备注 | 详情、查询、重置、导出;**无充值、扣款或余额调整** | 客户主体正常/停用只影响访问和新业务;所有金额可由来源、单据和收付款逐笔追溯,禁止直接写余额 |
| 客户应收应付 | 工具栏、组合查询、选中汇总、费用列表、费用详情、审核进度、关联业务、操作记录 | 客户、费用单号、是否已生成对账单、参与结算、审核状态、应收/应付、入仓码/柜次号、业务状态、费用类型、金额、业务发生日、来源类型、来源版本 | 详情、审核通过、审核拒绝、编辑未审核人工项、参与结算/禁止结算、按截止时间或勾选生成;已发布来源不可删除,只能作废/调整 | `PENDING -> APPROVED/REJECTED`;只有 `APPROVED + INCLUDED + AVAILABLE + CNY` 可生成;同一来源版本不能重复进入有效单据 |
| 客户对账单 | 查询区、主表、账单明细、支付历史;审核状态、账单编号、客户、柜次、结算起止日、是否结清、创建日期、最后收款时间 | 对账单号、客户、期间、账期、CNY、总应收、已收、未收、最后收款时间、是否结清、备注、创建/更新人时间;明细保留入仓单/柜次、业务日、计费量、费用项、金额、来源版本 | 生成草稿、详情、导出、审核通过、审核拒绝、作废;不提供发票和汇率操作 | `DRAFT -> PENDING_REVIEW -> APPROVED/REJECTED/VOIDED`;审核通过后来源冻结,调整必须留 revision;支付历史只读展示有效收款 |
| 结算单应收 | 汇总卡、筛选、列表、详情、费用明细、收款记录;收款状态、客户、结算单号 | 结算单号、客户、CNY、应收、已收、余额、关联对账单、业务期间、生成日、到期日、收款状态、制单人、状态 | 从审核通过对账单生成、详情、部分收款、导出、作废/重开;不保留高级查询假入口 | `DRAFT -> ISSUED -> PARTIALLY_PAID -> PAID`,未收款可作废;出账后冻结,调整保留 revision;收款人工表单和图片沿用 F1 契约 |
| 结算单应付 | 汇总卡、供应商筛选、列表、详情、费用明细、付款记录 | 结算单号、供应商、费用类型、CNY、应付、已付、余额、来源期间、生成日、到期日、付款状态、制单人、审核人、状态 | 从审核通过且参与结算的应付来源生成、详情、审核、部分付款、导出、作废/重开;删除利润分析和利润审批按钮 | `DRAFT -> PENDING_REVIEW -> ISSUED -> PARTIALLY_PAID -> PAID`,拒绝/作废保留记录;付款为人工登记和凭证图片 |
表格“操作”列必须位于第一列。原型中未形成真实闭环的“新增、生成账单、高级查询、快捷导出”等按钮,只有在对应接口和权限完成后才显示。
### 3.1 五页现状/目标差异
| 页面 | 当前仓库事实 | 一期目标 | 差异等级 |
|---|---|---|---|
| 客户账户 | 后端已新增 `/customer-accounts/{customerId}` 和固定读 DTO;无列表接口 | 派生财务往来汇总、详情和流水,无任何充值/余额写入口 | IMPLEMENTED(单客户查询);列表/筛选仍缺,Finance DTO 测试通过 |
| 客户应收应付 | `/fee-pool` 固定 DTO、Firstleg 事件/快照和 `fin_fee_source` 写入均已实现并验证 | 真实入库/柜子费用来源池,支持审核、参与结算、详情和生成对账单 | 查询与来源入池已实现;详情/页面操作仍是 P0/P1 |
| 客户对账单 | 后端已新增 `/statements` 和 `/bills/{billId}` 固定读 DTO 路径;独立生成/审核模型仍缺失 | 按截止时间或勾选合格来源生成,支持审核、明细、支付历史和 revision | IN_PROGRESS/P0 |
| 结算单应收 | 后端已新增 `/receivable-settlements` 固定读 DTO 路径;`fin_bill + fin_receipt` 已有人工状态能力 | 关联审核通过的客户对账单,按原型结构形成应收结算页 | IN_PROGRESS/P0 适配 |
| 结算单应付 | 后端已新增 `/payable-settlements` 固定读 DTO 路径并读取人工成本;付款单和完整供应商来源池仍缺失 | 从真实 PAYABLE 来源生成,审核后人工登记付款与凭证 | IN_PROGRESS/P0 |
Finance 来源写入不再是阻断:内部事件入口、Inbox 幂等、Firstleg 入库/柜子快照、`fin_fee_source` 新版本写入/替代/作废、`PUBLISHED + amount>0` 入池校验、五页固定 DTO、完整幂等、File fail-closed、Client 脱敏和稳定错误码均已实现并通过测试。剩余主要阻断转为 11 个目标 operation、Admin 五页接入和测试环境跨服务冒烟。
## 4. 费用来源到结算全链路
```mermaid
flowchart LR
I["入库单费用项"] --> R["审核"]
C["柜子费用项"] --> R
R --> S["参与结算/禁止结算"]
S --> P["发布不可变来源版本"]
P --> X["Finance Inbox"]
X --> F["fin_fee_source"]
F --> A["客户应收应付费用池"]
A --> B["客户对账单"]
B --> AR["结算单应收"]
A --> AP["结算单应付"]
AR --> CR["人工收款与分配"]
AP --> CP["人工付款与凭证"]
CR --> CA["客户账户派生汇总/流水"]
CP --> CA
```
### 4.1 入库单费用项
现有 `fl_inbound_fee_detail` 已具备客户、入库单、方向、业务日、费用项快照、计费量、单价、金额、审核、发布和 `settlement_included` 字段;已有列表、新增、编辑、删除、审核通过和驳回接口。
仍缺:
- 通用费用的“参与结算/禁止结算”接口和原因、操作人、版本控制。
- 非 FBA 头程运费的统一发布动作;当前发布主要由 FBA 费用发送流程触发。
- 费用调整/作废事件及旧版本替代规则的完整实现。
- Finance 消费者和来源快照写入。
### 4.2 柜子费用项
当前工作树已新增柜子费用来源表/实体、Controller、审核/参与结算/作废服务、发布事件和内部快照代码;这些文件尚未形成通过测试的稳定基线。既有 Firstleg 柜次体积快照仍只服务 Finance 人工整柜成本分摊,不能替代新来源模型的审核和不可变发布链路。
一期至少需要业务侧模型:
- `containerFeeId/version`、`containerId/containerNo`、费用方向、费用项目、业务日、CNY 金额。
- 应付来源必须有供应商;应收来源必须有客户分摊结果。
- 审核状态、参与结算状态、发布状态、作废/调整原因和操作审计。
- 柜内跨客户时,业务侧按真实体积形成不可变客户分摊行;Finance 只接收客户级来源,不自行猜测客户归属。
建议新增 `fl_container_fee_detail + fl_container_fee_allocation`,或建立统一 `fl_business_fee_source`;这是技术选型,不改变上述产品字段和验收结果。
### 4.3 Finance 来源池
当前 `FinanceFeeSourceEventService` 已通过 `POST /internal/finance/v1/fee-source-events` 消费 Firstleg 事件,回查不可变快照,并在本地事务中写 `fin_inbox_event` 与 `fin_fee_source`。相同事件和内容返回原来源;同事件异内容冲突;调整写新版本并把旧 `AVAILABLE` 版本标为 `SUPERSEDED`;作废只标 `VOIDED`,不删除历史。现有人工账单入口仍允许 Admin 提交来源 ID/版本/金额,因此生成对账单/结算单时还必须改为只选择本地合格来源并由服务端取金额。
目标写入条件:
```text
reviewStatus = APPROVED
publicationStatus = PUBLISHED
settlementIncluded = true
sourceStatus = ACTIVE
currency = CNY
amount > 0
customer/supplier/business reference complete
```
Finance 必须通过 Inbox 幂等消费来源版本,或通过受保护的快照接口拉取后落库;禁止 Admin 直接构造来源金额。来源调整新增版本,已进入有效单据的旧版本不覆盖。
## 5. 目标接口矩阵
| 页面/链路 | 目标接口 | 当前状态 |
|---|---|---|
| 入库费用审核 | `POST /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}/approve|reject` | 已有 |
| 入库费用参与结算 | `PUT /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}/settlement-inclusion` | 缺失 |
| 入库费用发布 | `POST /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}/publish` | 通用入口缺失 |
| 柜子费用 | `/api/platform/v1/loading-plans/{loadingPlanId}/fee-details/**` | 模型、审核/调整/作废、事件、Relay 和快照已实现;Firstleg 相关 17/17 定向测试通过 |
| Finance 来源接入 | `POST /internal/finance/v1/fee-source-events` | 已实现并验证;来源专项 10/10、Finance 全量 35/35、Firstleg 相关 17/17 通过 |
| 客户账户 | `GET /api/platform/finance/v1/customer-accounts/{customerId}` | 已实现固定 DTO 单客户查询并通过测试;列表接口仍缺失 |
| 客户应收应付 | `GET /api/platform/finance/v1/fee-pool?customerId=&direction=` | 已实现固定 DTO 查询并通过测试;详情、审核和参与结算操作仍缺失 |
| 客户对账单 | `GET /api/platform/finance/v1/statements?customerId=`、`GET /api/platform/finance/v1/bills/{billId}` | 已实现固定 DTO 查询并通过测试;生成/审核操作仍缺失 |
| 结算单应收 | `GET /api/platform/finance/v1/receivable-settlements?customerId=` | 已实现固定 DTO 查询并通过测试;生成与页面动作仍缺失 |
| 应收人工收款 | `GET/POST /api/platform/finance/v1/receipts` | 已实现平台固定 DTO、多账单分配、合计校验、共用凭证和 File fail-closed;测试通过 |
| 结算单应付 | `GET /api/platform/finance/v1/payable-settlements?customerId=` | 已实现固定 DTO 查询并通过测试;应付生成、审核和付款仍缺失 |
## 6. 最小数据模型
| 模型 | 必要字段 | 当前缺口 |
|---|---|---|
| `fin_fee_source` | 来源系统/类型/ID/版本/hash、方向、客户、供应商、订单/入库/柜次、业务日、费用项、数量/单价/金额、审核/参与结算快照、状态、占用单据 | 已有写入、类型、方向、柜次、费用编码、hash、完整 JSON 快照和版本状态;供应商顶层字段及对账单占用关系仍待后续模型落地 |
| `fin_reconciliation_statement` | 对账单号、客户、期间、账期、CNY 总额、状态、审核、版本、备注 | 缺失 |
| `fin_reconciliation_line` | 对账单、feeSourceId/version/hash、业务与计费快照、金额 | 缺失 |
| `fin_settlement` | AR/AP、客户/供应商、来源对账单、期间、到期日、总额、已收付、余额、状态、版本 | 当前 `fin_bill` 仅覆盖部分 AR |
| `fin_settlement_line` | 结算单、对账单/来源行、费用项和金额快照 | 当前账单行只覆盖部分 AR |
| `fin_payment`/分配 | 收/付款、对象、日期、方式、凭证、金额、分配、操作人 | 收款已有;付款缺失 |
| 账户视图 | 客户、未收、待出账、本期已收、应付、最后变动 | 应由上述表聚合,不新增可写余额表 |
## 7. 专项优先级
### P0:不开工或不联调就无法闭环
1. 入库费用独立的参与结算/禁止结算和通用发布动作;柜子费用来源模型已完成,不再列为阻断。
2. 客户对账单、应收结算单、应付结算单的数据模型、状态机和剩余 11 个 operation。
### P1:领导验收前必须完成
1. 5 页 Admin 菜单、路由、字段、筛选、详情、状态和权限。
2. 删除费用分析、利润表、手动充值、利润审批、汇率/外币/发票及所有假入口。
3. 来源金额与对账单/结算单金额逐层勾稽报告。
4. 跨客户、跨供应商、重复来源、已占用来源、调整/作废和并发版本测试。
5. Finance → Firstleg/File 真实 HTTP 冒烟和 5 页端到端验收。
## 8. 当前确认项
客户账户冲突已由产品确认:采用派生财务往来总览,不做钱包/预收/充值。当前没有遗留的核心产品冲突;剩余均为接口、数据模型和实现门禁。
@@ -7,9 +7,9 @@
## 一、总控结论 ## 一、总控结论
Finance 的服务拆分、独立数据库、基础表、权限、人工账单/收款/成本接口及 Admin/Client 基础页面已经落地。当前不是等待开工,而是按专项测试退回项修复固定 DTO、凭证/File 链路、体积分摊、幂等和客户可见状态。 Finance 的服务拆分、独立数据库、基础表、权限、人工账单/收款/成本接口及 Admin/Client 基础页面已经落地。后端真实体积快照、归属、成本凭证、revision、双权限上传、费用来源事件/Relay/快照、固定 DTO、完整幂等、File fail-closed、客户收款 DTO 和稳定错误码已经完成并通过专项测试;当前继续收口 Admin 最终契约适配和五页剩余 operation。
F0 的平台主体、首期仅 RMB/CNY、自定义账期、编号、费用冻结、无历史迁移、客户角色和首期简化审批已经确认。当前采用人工简化方案:账单、收款、成本均由平台财务填写表单并上传凭证;客户账户、发票、供应商在线应付、银行接口、复杂审批和月结首期不做。原表状态已归一为 25 项已确认、7 项暂缓。详见[产品确认版差异与剩余待确认](财务管理产品确认版差异与剩余待确认.md)。 F0 的平台主体、首期仅 RMB/CNY、自定义账期、编号、费用冻结、无历史迁移、客户角色和首期简化审批已经确认。一期领导验收固定为 5 页;客户账户为派生财务往来总览,不做钱包/充值,费用分析和利润表不做。详见[财务一期五页产品与接口验收契约](财务一期五页产品与接口验收契约.md)。
## 二、文档交付状态 ## 二、文档交付状态
@@ -54,9 +54,9 @@ G0 允许:完善 API/OpenAPI、数据库迁移草案、契约测试样例、
- 预收、多收、手续费、退款、反核销的处理方式冻结; - 预收、多收、手续费、退款、反核销的处理方式冻结;
- 至少准备一组真实或脱敏费用来源样本,能够完成费用→账单→应收→收款→核销回归。 - 至少准备一组真实或脱敏费用来源样本,能够完成费用→账单→应收→收款→核销回归。
### G3/G4:F2-F4 门禁 ### G3/G4:一期应付与排除项门禁
供应商应付、客户账户、发票、费用分析和利润必须分别满足产品确认表中的阶段门禁。没有供应商成本凭证、资金性质、税务主体、汇率和分摊口径时,只能保留预留模型和页面草案。 结算单应付纳入一期,但必须有供应商和真实 PAYABLE 来源。客户账户只做派生查询。发票、费用分析、利润、汇率和月结不属于一期,禁止保留假入口。
## 四、F0/F1 任务清单 ## 四、F0/F1 任务清单
@@ -82,12 +82,12 @@ G0 允许:完善 API/OpenAPI、数据库迁移草案、契约测试样例、
- 完善 F0/F1 数据字典、状态转移表和权限矩阵; - 完善 F0/F1 数据字典、状态转移表和权限矩阵;
- 设计 Finance Admin/Client 页面和空态、错误态、线下异议录入态; - 设计 Finance Admin/Client 页面和空态、错误态、线下异议录入态;
- 准备脱敏历史费用样本与迁移校验脚本设计; - 准备脱敏历史费用样本与迁移校验脚本设计;
- 按 OpenAPI 1.2.0 修复服务端 DTO、凭证链路、真实体积快照与归属、幂等和客户可见状态,并补齐契约测试。 - 按 OpenAPI 1.2.0 完成剩余服务端 DTO、File fail-closed、幂等和客户可见 DTO,并让 Admin 移除人工体积、接入账期与 revision。
### 本轮不再等待产品确认 ### 本轮不再等待产品确认
- F1 首期只做 CNY 人工账单、人工收款、人工成本和客户只读,产品口径已经冻结。 - 一期只支持 CNY,验收 5 页及其真实费用来源、对账、应收/应付和人工收付款链路。
- 客户账户、发票、供应商在线应付、汇率、月结和利润不属于本轮,不阻塞 F1 修复。 - 客户账户是派生总览;发票、费用分析、利润、汇率、月结不属于本轮。
- 首发不迁移历史,不阻塞 F1 修复。 - 首发不迁移历史,不阻塞 F1 修复。
## 六、总控放行结论 ## 六、总控放行结论
+2
View File
@@ -1,5 +1,7 @@
# 财务服务边界设计 # 财务服务边界设计
> **范围说明**:本文只作为 Finance 独立服务/独立数据库的技术边界依据。文中的钱包、充值、发票、费用分析和利润属于长期模型,不属于一期;一期唯一产品范围以《财务一期五页产品与接口验收契约》为准。
> 决策日期:2026-08-10 > 决策日期:2026-08-10
> 决策状态:技术已确认 > 决策状态:技术已确认
> 决策结论:Finance 采用独立服务和独立数据库 > 决策结论:Finance 采用独立服务和独立数据库
@@ -4,17 +4,19 @@
> 复核日期:2026-08-10 > 复核日期:2026-08-10
> 用途:把产品回填内容转成可开发口径;不替代产品原始回传表。 > 用途:把产品回填内容转成可开发口径;不替代产品原始回传表。
> **降级说明(2026-08-11)**:本文保留首次回填复核过程,不再作为一期范围入口。当前范围和冲突处理以《财务一期五页产品与接口验收契约》为准;原文中的“仍待确认”“F3 整体暂缓”“成本/利润统计”均不得覆盖已确认的五页范围。
## 一、回传表复核结论 ## 一、回传表复核结论
回传表共 32 个事项。当前状态列实际为:16 项“已确认”、2 项“待确认”、14 项状态为空但填写了最终结论。因此,表内“填写说明”显示的 16 已确认 / 16 待确认不能直接作为放行依据;状态为空的 14 项需要产品补填“已确认”或“暂缓”。 回传表共 32 个事项。当前状态列实际为:16 项“已确认”、2 项“待确认”、14 项状态为空但填写了最终结论。因此,表内“填写说明”显示的 16 已确认 / 16 待确认不能直接作为放行依据;状态为空的 14 项需要产品补填“已确认”或“暂缓”。
其中,以下内容可直接纳入正式文档: 其中,以下内容可直接纳入正式文档:
- 客户应付、客户账户、发票和外部接口在头程首期不做,线下处理;不得因此创建半成品财务流程。 - 一期页面固定为客户账户、客户应收应付、客户对账单、结算单应收、结算单应付;客户账户只是派生财务往来总览,不做钱包/预收;发票和外部接口不做。
- 供应商付款为线下付款并上传凭证;单票成本直接归属单票,整柜清关、拖车等公共成本按柜内体积分摊。 - 供应商付款为线下付款并上传凭证;单票成本直接归属单票,整柜清关、拖车等公共成本按柜内体积分摊。
- 首期账单只支持 RMB/CNY;每个客户维护自己的账期配置,默认 30 天。 - 首期账单只支持 RMB/CNY;每个客户维护自己的账期配置,默认 30 天。
- 收款全部由财务人工填写表单并上传收款图片;一笔 300 元可由财务分别填入 3 张 100 元账单,关联同一张凭证。 - 收款全部由财务人工填写表单并上传收款图片;一笔 300 元可由财务分别填入 3 张 100 元账单,关联同一张凭证。
- 首期只统计 CNY 账单,不做汇率、不做月结,只按账单统计。 - 首期所有页面和单据只统计 CNY,不做汇率、不做月结;费用分析和利润表不建设。
- 客户财务权限按菜单分权限;与“客户子用户只读、平台财务执行写操作”的既有结论一致。 - 客户财务权限按菜单分权限;与“客户子用户只读、平台财务执行写操作”的既有结论一致。
## 二、已确认但需要写入契约的细节 ## 二、已确认但需要写入契约的细节
@@ -26,7 +28,7 @@
| F1-04 | “人工填写表单,上传收款图” | 已足够支撑首期人工收款;仍需把表单字段写入接口契约 | 收款金额、到账日、方式、凭证号、凭证图片、登记人由平台财务人工填写 | | F1-04 | “人工填写表单,上传收款图” | 已足够支撑首期人工收款;仍需把表单字段写入接口契约 | 收款金额、到账日、方式、凭证号、凭证图片、登记人由平台财务人工填写 |
| F1-05 | “客户给 300,3 个账单都是 100,直接 3 个单” | 已明确首期按账单逐笔分配;不再扩展预收、多收、手续费、退款 | 财务分别在 3 张账单填写 100 元,并关联同一张 300 元收款凭证 | | F1-05 | “客户给 300,3 个账单都是 100,直接 3 个单” | 已明确首期按账单逐笔分配;不再扩展预收、多收、手续费、退款 | 财务分别在 3 张账单填写 100 元,并关联同一张 300 元收款凭证 |
| F2-02/F4-01 | “单票成本;整柜清关、拖车按体积分摊” | 已明确业务归属;只需在接口中固定人工录入和凭证字段 | 单票成本归属单票;整柜公共成本按柜内体积分摊;平台财务人工登记并上传凭证;收入按 CNY 账单统计 | | F2-02/F4-01 | “单票成本;整柜清关、拖车按体积分摊” | 已明确业务归属;只需在接口中固定人工录入和凭证字段 | 单票成本归属单票;整柜公共成本按柜内体积分摊;平台财务人工登记并上传凭证;收入按 CNY 账单统计 |
| F4-03 | “不做汇率和月结,只做账单,只统计 CNY” | 已解决首期范围;仅需在权限和报表验收中冻结为 CNY | 首期利润/分析只统计 CNY 账单,不做汇率、汇兑损益和月结快照 | | F4-03 | “不做汇率和月结,只做账单,只统计 CNY” | 已解决首期范围;在五页接口和验收中冻结为 CNY | 五页单据和汇总只统计 CNY,不做汇率、汇兑损益、月结快照、费用分析或利润表 |
## 三、可以按“首期不做/暂缓”处理的事项 ## 三、可以按“首期不做/暂缓”处理的事项
@@ -34,17 +36,17 @@
| 事项 | 暂缓口径 | | 事项 | 暂缓口径 |
|---|---| |---|---|
| F2-01、F2-03、F2-04 | 当前不存在客户应付或供应商应付在线闭环,线下处理;不开放对应菜单和状态流转 | | F2-01、F2-03、F2-04 | 供应商在线确认、自动付款等能力暂缓;一期仍须交付结算单应付页、真实 PAYABLE 来源和人工付款凭证链路 |
| F3-01 至 F3-04 | 头程首期没有客户账户/钱包,线下处理;不建设余额、冻结、扣款、退款对象 | | F3-01 至 F3-04 | 一期建设客户账户派生总览页,但不建设钱包余额、充值、冻结、自动扣款或退款对象 |
| F3-05 至 F3-07 | 发票和外部开票/银行接口首期线下处理;只保留未来扩展位 | | F3-05 至 F3-07 | 发票和外部开票/银行接口首期线下处理;只保留未来扩展位 |
| F4-04 | 按菜单分权限;平台财务可见完整利润和成本,客户侧不开放供应商成本和内部利润 | | F4-04 | 费用分析和利润表一期不进菜单/路由;后续重新立项时再定义权限 |
## 四、当前放行判断 ## 四、当前放行判断
- F0 技术方案和客户主体/成员边界已经冻结,可以继续做 Finance 服务骨架、数据库迁移草案、事件契约和权限矩阵设计。 - F0 技术方案和客户主体/成员边界已经冻结,可以继续做 Finance 服务骨架、数据库迁移草案、事件契约和权限矩阵设计。
- F1 客户应收的核心产品口径已补齐;账期日期算法、账单单据粒度和收款字段可按本文默认值直接写入契约。 - F1 客户应收的核心产品口径已补齐;账期日期算法、账单单据粒度和收款字段可按本文默认值直接写入契约。
- F2/F4 的产品口径已补齐;开发前只需把人工成本/收款表单字段、凭证关联和体积分摊公式写入接口与验收契约。 - F2/F4 的产品口径已补齐;开发前只需把人工成本/收款表单字段、凭证关联和体积分摊公式写入接口与验收契约。
- F3 可整体标记暂缓,不阻断 F0/F1。 - F3 钱包/充值/发票能力可暂缓;客户账户派生总览属于一期五页,不得整体暂缓。
因此,本轮已没有新的核心产品问题;剩余工作是把确认版 XLSX 的状态归一化,并在接口/验收契约中补充账期日期算法、收款表单字段、收款凭证与账单分配关系、成本来源字段和体积分摊公式。 因此,本轮已没有新的核心产品问题;剩余工作是把确认版 XLSX 的状态归一化,并在接口/验收契约中补充账期日期算法、收款表单字段、收款凭证与账单分配关系、成本来源字段和体积分摊公式。
@@ -59,4 +61,4 @@
5. **客户侧**:客户只读查看账单、收款记录和余额;金额有误时线下反馈,由平台财务修改或作废重开。 5. **客户侧**:客户只读查看账单、收款记录和余额;金额有误时线下反馈,由平台财务修改或作废重开。
6. **凭证与审计**:所有人工表单保留填写人、填写时间、修改原因、凭证图片和原始版本;已出账记录不覆盖,修改使用调整或作废重开。 6. **凭证与审计**:所有人工表单保留填写人、填写时间、修改原因、凭证图片和原始版本;已出账记录不覆盖,修改使用调整或作废重开。
按此方案,开发重点是三个简单表单(账单、收款、成本)和三类查询(客户账单、收款记录、成本/利润统计),不是建设完整总账、钱包或自动结算系统。 按此方案,开发重点是五页查询与详情、账单/收付款人工表单及真实费用来源链路,不建设成本/利润分析、完整总账、钱包或自动结算系统。
+37 -32
View File
@@ -1,14 +1,16 @@
# 财务管理产品确认表 # 财务管理产品确认表
> 版本:V1.0 > 版本:V1.1
> 创建日期:2026-08-10 > 创建日期:2026-08-10
> 状态:首期人工简化财务口径已确认;后续 F2-F4 待确认项不阻塞本轮 F1 修复 > 状态:一期 5 页范围已确认
> 适用范围:客户账户、客户应收应付、客户对账单、结算单应收/应付、收付款核销、发票、费用分析和利润 > 适用范围:客户账户、客户应收应付、客户对账单、结算单应收、结算单应付
> 技术方案说明:服务边界、跨服务访问、事件幂等、金额存储、状态留痕和正式模块发布方式已按当前仓库架构直接确认,不再要求产品确认;以 XLSX 的“技术结论”工作表为准。 > 技术方案说明:服务边界、跨服务访问、事件幂等、金额存储、状态留痕和正式模块发布方式已按当前仓库架构直接确认,不再要求产品确认;以 XLSX 的“技术结论”工作表为准。
正式技术决策见:[财务服务边界设计](财务服务边界设计.md)。 正式技术决策见:[财务服务边界设计](财务服务边界设计.md)。
一期领导验收及接口事实以[财务一期五页产品与接口验收契约](财务一期五页产品与接口验收契约.md)为准;本文后续 F2-F4 历史问题不自动进入一期。
产品回传版 XLSX 的逐项复核和剩余确认门禁见:[财务管理产品确认版差异与剩余待确认](财务管理产品确认版差异与剩余待确认.md)。 产品回传版 XLSX 的逐项复核和剩余确认门禁见:[财务管理产品确认版差异与剩余待确认](财务管理产品确认版差异与剩余待确认.md)。
## 一、确认说明 ## 一、确认说明
@@ -42,19 +44,22 @@
| 实施复杂度 | 首期全部由平台财务人工填写账单、收款和成本表单并上传凭证;不建设自动银行对账、自动核销、复杂审批、钱包、发票或总账 | | 实施复杂度 | 首期全部由平台财务人工填写账单、收款和成本表单并上传凭证;不建设自动银行对账、自动核销、复杂审批、钱包、发票或总账 |
| 审批复杂度 | 首期不做强制双人复核和金额分级审批;保留独立权限、操作原因和完整审计 | | 审批复杂度 | 首期不做强制双人复核和金额分级审批;保留独立权限、操作原因和完整审计 |
| 成员停用 | 客户子用户停用只撤销访问权限;客户账单、应收、余额等仍归客户企业,不触发财务单据转交;历史保留操作人快照 | | 成员停用 | 客户子用户停用只撤销访问权限;客户账单、应收、余额等仍归客户企业,不触发财务单据转交;历史保留操作人快照 |
| 一期页面 | 只做客户账户、客户应收应付、客户对账单、结算单应收、结算单应付;费用分析和利润表不进菜单/路由 |
| 客户账户性质 | 财务往来派生总览,不是钱包;删除手动充值、预收、可消费余额和自动扣款入口 |
| 费用来源链路 | 入库单费用和柜子费用必须审核、标记参与结算并发布到 Finance 来源池后,才能生成对账单/结算单 |
## 二、全量范围确认 ## 二、全量范围确认
| 编号 | 范围 | 建议结论 | 最终结论 | 状态 | | 编号 | 范围 | 建议结论 | 最终结论 | 状态 |
|---|---|---|---|---| |---|---|---|---|---|
| S1 | 客户账户 | 做预充值、冻结、解冻、扣款、退款和账户流水;账户余额与应收核销分开,任何抵扣都产生核销记录 | 待填写 | 待确认 | | S1 | 客户账户 | 做预充值、冻结、解冻、扣款、退款和账户流水;账户余额与应收核销分开,任何抵扣都产生核销记录 | 只做账单、收款和应收应付来源派生的财务往来总览;不做钱包、预收、充值和自动扣款 | 已确认 |
| S2 | 客户应收 | 做客户费用池、对账单、应收单、到期/逾期、收款、部分核销、结清、反核销 | 待填写 | 待确认 | | S2 | 客户应收 | 做客户费用池、对账单、应收单、到期/逾期、收款、部分核销、结清、反核销 | 纳入一期 5 页;平台财务操作,客户只读 | 已确认 |
| S3 | 客户应付 | 仅在确有平台向客户付款的业务场景时启用;否则不开放菜单和数据方向 | 待填写 | 待确认 | | S3 | 客户应付 | 仅在确有平台向客户付款的业务场景时启用;否则不开放菜单和数据方向 | 客户应收应付页按来源方向展示;没有真实 PAYABLE 来源时为空,不造模拟数据 | 已确认 |
| S4 | 客户对账单 | 按客户 + 币种 + 账期生成,支持平台内部复核、发送、关闭和财务重开;客户只读查看 | 平台财务出账,客户只读,异议线下反馈 | 已确认 | | S4 | 客户对账单 | 按客户 + 币种 + 账期生成,支持平台内部复核、发送、关闭和财务重开;客户只读查看 | 平台财务出账,客户只读,异议线下反馈 | 已确认 |
| S5 | 供应商应付 | 做供应商成本池、供应商对账、应付单、付款、付款核销和反核销 | 待填写 | 待确认 | | S5 | 供应商应付 | 做供应商成本池、供应商对账、应付单、付款、付款核销和反核销 | 结算单应付纳入一期;只使用具有供应商和真实来源的 CNY 应付费用,付款人工登记 | 已确认 |
| S6 | 发票 | 做发票申请、开票登记、票号/文件关联、红冲和作废;不直接假定外部开票平台 | 待填写 | 待确认 | | S6 | 发票 | 做发票申请、开票登记、票号/文件关联、红冲和作废;不直接假定外部开票平台 | 一期不做,不设计菜单、路由或按钮 | 已确认 |
| S7 | 费用分析 | 按费用项目、客户、供应商、期间统计发生额、已结算额和余额,支持钻取来源单据 | 待填写 | 待确认 | | S7 | 费用分析 | 按费用项目、客户、供应商、期间统计发生额、已结算额和余额,支持钻取来源单据 | 一期不做,不进菜单/路由 | 已确认 |
| S8 | 利润 | 支持客户、货柜、单票、月份维度;收入、成本、分摊、汇率和利润率必须可追溯 | 待填写 | 待确认 | | S8 | 利润 | 支持客户、货柜、单票、月份维度;收入、成本、分摊、汇率和利润率必须可追溯 | 一期不做,不进菜单/路由;应付页删除利润字段和利润审批 | 已确认 |
## 三、F0 财务底座确认 ## 三、F0 财务底座确认
@@ -91,37 +96,37 @@
| 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 | | 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 |
|---|---|---|---|---| |---|---|---|---|---|
| F1-01 | 账单聚合维度 | 客户 + 币种 + 账期;不同币种不合并 | 首期只支持 RMB/CNY;支持多种费用项;多笔订单分别出账 | 已确认 | | F1-01 | 账单聚合维度 | 客户 + 币种 + 账期;不同币种不合并 | 首期只支持 RMB/CNY;支持多种费用项;多笔订单分别出账 | 已确认 |
| F1-02 | 生成方式 | 支持按筛选结果人工生成;后续可增加定时生成,但不得重复出账 | 待填写 | 待确认 | | F1-02 | 生成方式 | 支持按筛选结果人工生成;后续可增加定时生成,但不得重复出账 | 按截止时间或财务勾选合格来源生成;同一来源版本不得重复进入有效对账单 | 已确认 |
| F1-03 | 账单状态 | DRAFT → ISSUED → CLOSED;客户只读,异议线下反馈后由平台财务调整或作废重开 | 客户不在线确认/争议,平台财务手工处理 | 已确认 | | F1-03 | 账单状态 | DRAFT → ISSUED → CLOSED;客户只读,异议线下反馈后由平台财务调整或作废重开 | 客户不在线确认/争议,平台财务手工处理 | 已确认 |
| F1-04 | 应收状态 | OPEN → PARTIALLY_SETTLED → SETTLED;到期后增加 OVERDUE 标记,不改变余额 | 客户账期由客户配置,默认 30 天;到期日按账单日期+客户账期计算 | 已确认 | | F1-04 | 应收状态 | OPEN → PARTIALLY_SETTLED → SETTLED;到期后增加 OVERDUE 标记,不改变余额 | 客户账期由客户配置,默认 30 天;到期日按账单日期+客户账期计算 | 已确认 |
| F1-05 | 客户确认 | 首期不做客户在线确认/争议;客户只读查看,异议线下反馈 | 客户不能操作,由平台财务处理 | 已确认 | | F1-05 | 客户确认 | 首期不做客户在线确认/争议;客户只读查看,异议线下反馈 | 客户不能操作,由平台财务处理 | 已确认 |
| F1-06 | 收款登记 | 首版人工登记到账日、金额、币种、方式、凭证号、附件和登记人 | 平台财务人工填写收款表单并上传收款凭证图片 | 已确认 | | F1-06 | 收款登记 | 首版人工登记到账日、金额、币种、方式、凭证号、附件和登记人 | 平台财务人工填写收款表单并上传收款凭证图片 | 已确认 |
| F1-07 | 核销关系 | 支持一笔收款核销多张应收、一张应收被多笔收款核销;禁止跨币种和超额 | 一笔客户付款可分配到多张账单;财务分别填写各账单对应金额并关联同一收款凭证;首期不处理预收、多收、手续费、退款 | 已确认 | | F1-07 | 核销关系 | 支持一笔收款核销多张应收、一张应收被多笔收款核销;禁止跨币种和超额 | 一笔客户付款可分配到多张账单;财务分别填写各账单对应金额并关联同一收款凭证;首期不处理预收、多收、手续费、退款 | 已确认 |
| F1-08 | 反核销/作废 | 独立高风险权限,填写原因并保留原记录;不物理删除 | 待填写 | 待确认 | | F1-08 | 反核销/作废 | 独立高风险权限,填写原因并保留原记录;不物理删除 | 首期不做复杂反核销;未收单据可作废,已出账调整/作废重开必须留原因、版本和原记录 | 已确认 |
| F1-09 | 出账后调整 | 已出账冻结;平台财务通过调整/作废重开形成新版本,保留原金额和原因 | 仅平台财务手工调整,不允许客户修改 | 已确认 | | F1-09 | 出账后调整 | 已出账冻结;平台财务通过调整/作废重开形成新版本,保留原金额和原因 | 仅平台财务手工调整,不允许客户修改 | 已确认 |
| F1-10 | 预收/多收/手续费/退款 | 单独建模为预收、其他应付款或退款,不直接冲减应收金额 | 待填写 | 待确认 | | F1-10 | 预收/多收/手续费/退款 | 单独建模为预收、其他应付款或退款,不直接冲减应收金额 | 一期全部不做;不设计钱包或预收入口 | 已确认 |
## 五、F2 供应商应付与结算确认 ## 五、F2 供应商应付与结算确认
| 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 | | 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 |
|---|---|---|---|---| |---|---|---|---|---|
| F2-01 | 成本来源 | 只有具备供应商、付款主体、成本凭证、币种金额和成本归属的来源才能进入应付池 | 待填写 | 待确认 | | F2-01 | 成本来源 | 只有具备供应商、付款主体、成本凭证、币种金额和成本归属的来源才能进入应付池 | 一期只接具备供应商、真实业务来源、审核、参与结算和 CNY 金额的 PAYABLE 来源 | 已确认 |
| F2-02 | 成本确认节点 | 以供应商账单/业务完成/内部审核中确定一个正式节点;确认后冻结成本快照 | 待填写 | 待确认 | | F2-02 | 成本确认节点 | 以供应商账单/业务完成/内部审核中确定一个正式节点;确认后冻结成本快照 | 费用审核通过、参与结算并发布后进入 Finance;来源版本冻结 | 已确认 |
| F2-03 | 供应商账单 | DRAFT → INTERNAL_REVIEW → SENT → CONFIRMED → CLOSED;差异走争议/补差/冲销 | 待填写 | 待确认 | | F2-03 | 供应商账单 | DRAFT → INTERNAL_REVIEW → SENT → CONFIRMED → CLOSED;差异走争议/补差/冲销 | 一期不单独做供应商对账页,直接在结算单应付中生成、审核和付款 | 已确认 |
| F2-04 | 应付状态 | OPEN → PARTIALLY_PAID → PAID;到期增加 OVERDUE 标记 | 待填写 | 待确认 | | F2-04 | 应付状态 | OPEN → PARTIALLY_PAID → PAID;到期增加 OVERDUE 标记 | DRAFT → PENDING_REVIEW → ISSUED → PARTIALLY_PAID → PAID;可拒绝/作废并留痕 | 已确认 |
| F2-05 | 付款与核销 | 付款单独登记,支持多对多付款核销;禁止跨币种和超额 | 待填写 | 待确认 | | F2-05 | 付款与核销 | 付款单独登记,支持多对多付款核销;禁止跨币种和超额 | 平台财务人工登记付款表单和凭证;不得跨供应商或超额 | 已确认 |
| F2-06 | 审批 | 应付确认和付款前复核使用独立权限;是否需要金额分级审批待确认 | 待填写 | 待确认 | | F2-06 | 审批 | 应付确认和付款前复核使用独立权限;是否需要金额分级审批待确认 | 使用独立审核权限;一期不做金额分级或强制双人 | 已确认 |
| F2-07 | 预付/押金/代付/退款 | 不混入普通应付余额,单独建模并保留关联单据 | 待填写 | 待确认 | | F2-07 | 预付/押金/代付/退款 | 不混入普通应付余额,单独建模并保留关联单据 | 一期不做 | 已确认 |
| F2-08 | 当前人工 PAYABLE 明细 | 仅作为待补充来源,不得直接视为供应商应付闭环 | 待填写 | 待确认 | | F2-08 | 当前人工 PAYABLE 明细 | 仅作为待补充来源,不得直接视为供应商应付闭环 | 没有供应商、审核和发布事实的明细不得进入结算单应付 | 已确认 |
## 六、F3 客户账户与发票确认 ## 六、F3 客户账户与发票确认
| 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 | | 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 |
|---|---|---|---|---| |---|---|---|---|---|
| F3-01 | 账户余额性质 | 明确是客户预付款余额还是平台内部授信;充值必须有到账凭证,余额变更原子落流水 | 待填写 | 待确认 | | F3-01 | 账户余额性质 | 明确是客户预付款余额还是平台内部授信;充值必须有到账凭证,余额变更原子落流水 | 不是资金余额;客户账户页只展示账单、收款和费用来源派生指标 | 已确认 |
| F3-02 | 账户与应收关系 | 账户扣款可以核销应收,但不得直接修改应收原金额;余额、扣款、核销三条记录均保留 | 待填写 | 待确认 | | F3-02 | 账户与应收关系 | 账户扣款可以核销应收,但不得直接修改应收原金额;余额、扣款、核销三条记录均保留 | 不做账户扣款;收款只通过结算单分配更新未收余额 | 已确认 |
| F3-03 | 冻结与解冻 | 明确冻结触发、解冻人、原因、部分冻结和失败补偿 | 待填写 | 待确认 | | F3-03 | 冻结与解冻 | 明确冻结触发、解冻人、原因、部分冻结和失败补偿 | 不做钱包冻结/解冻;待出账金额由合格未出账来源派生 | 已确认 |
| F3-04 | 退款 | 退款必须关联原充值/收款,记录审批、到账方式、退款凭证和余额恢复规则 | 待填写 | 待确认 | | F3-04 | 退款 | 退款必须关联原充值/收款,记录审批、到账方式、退款凭证和余额恢复规则 | 一期不做充值和退款 | 已确认 |
| F3-05 | 发票主体 | 明确开票主体、税率、含税/未税、发票类型和客户抬头校验 | 待填写 | 待确认 | | F3-05 | 发票主体 | 明确开票主体、税率、含税/未税、发票类型和客户抬头校验 | 待填写 | 待确认 |
| F3-06 | 开票流程 | 申请 → 审核 → 开票登记 → 票据/文件关联;红冲、作废不可删除原票 | 待填写 | 待确认 | | F3-06 | 开票流程 | 申请 → 审核 → 开票登记 → 票据/文件关联;红冲、作废不可删除原票 | 待填写 | 待确认 |
| F3-07 | 外部平台 | 首版可人工登记,外部开票平台和银行流水接口另定接入契约 | 待填写 | 待确认 | | F3-07 | 外部平台 | 首版可人工登记,外部开票平台和银行流水接口另定接入契约 | 待填写 | 待确认 |
@@ -130,13 +135,13 @@
| 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 | | 编号 | 需要确认的事项 | 建议结论 | 最终结论 | 状态 |
|---|---|---|---|---| |---|---|---|---|---|
| F4-01 | 收入口径 | 按已确认/已发布应收还是已收款确认收入,二者报表分开显示 | 首期只统计 CNY 账单,不做汇率和月结,只按账单统计 | 已确认 | | F4-01 | 收入口径 | 按已确认/已发布应收还是已收款确认收入,二者报表分开显示 | 费用分析/利润表一期不做 | 已确认 |
| F4-02 | 成本口径 | 按已确认应付还是已付款确认成本,二者报表分开显示 | 单票成本直接归属单票;整柜公共成本进入柜次池 | 已确认 | | F4-02 | 成本口径 | 按已确认应付还是已付款确认成本,二者报表分开显示 | 费用分析/利润表一期不做;来源成本仍用于应付结算 | 已确认 |
| F4-03 | 分摊维度 | 支持客户、订单、单票、柜次、费用项目;明确公共成本分摊算法 | 单票按单票真实成本;整柜清关、拖车等公共成本按体积分摊 | 已确认 | | F4-03 | 分摊维度 | 支持客户、订单、单票、柜次、费用项目;明确公共成本分摊算法 | 一期只为来源和结算保留真实分摊,不开发利润分析页面 | 已确认 |
| F4-04 | 汇率 | 明确交易日、账单日或月末汇率,以及本位币和汇兑损益 | 待填写 | 待确认 | | F4-04 | 汇率 | 明确交易日、账单日或月末汇率,以及本位币和汇兑损益 | 一期只支持 CNY,不做汇率 | 已确认 |
| F4-05 | 期间锁定 | 月结后报表冻结;调整通过新期间补差/冲销反映 | 首期不做月结;只按账单统计,暂不生成月结快照 | 已确认 | | F4-05 | 期间锁定 | 月结后报表冻结;调整通过新期间补差/冲销反映 | 一期不做月结 | 已确认 |
| F4-06 | 利润维度 | 客户、货柜、单票、月份均支持;每个结果可钻取到收入、成本、分摊和原始单据 | 待填写 | 待确认 | | F4-06 | 利润维度 | 客户、货柜、单票、月份均支持;每个结果可钻取到收入、成本、分摊和原始单据 | 一期不做利润表 | 已确认 |
| F4-07 | 导出与权限 | 导出按财务数据权限控制,客户不可见供应商成本和内部利润 | 待填写 | 待确认 | | F4-07 | 导出与权限 | 导出按财务数据权限控制,客户不可见供应商成本和内部利润 | 一期无利润菜单、路由或权限 | 已确认 |
## 八、全量验收主链路 ## 八、全量验收主链路
@@ -1,5 +1,7 @@
# 财务领域模型与数据字典(F0/F1 首版) # 财务领域模型与数据字典(F0/F1 首版)
> **范围说明**:本文包含长期数据模型候选。钱包、充值、发票、费用分析和利润表不属于一期,不得据此建菜单、路由或接口;一期数据模型以《财务一期五页产品与接口验收契约》为准。
> 版本:V0.1(开发前设计稿) > 版本:V0.1(开发前设计稿)
> 日期:2026-08-10 > 日期:2026-08-10
> 范围:F0 财务底座、F1 客户应收与对账;F2-F4 预留 > 范围:F0 财务底座、F1 客户应收与对账;F2-F4 预留
@@ -1,5 +1,7 @@
# 财务领域模型与跨服务契约(历史合并稿) # 财务领域模型与跨服务契约(历史合并稿)
> **历史文档,非一期实施依据**:本合并稿已被《财务领域模型与数据字典》《Firstleg-Finance 跨服务契约》和《财务一期五页产品与接口验收契约》替代。钱包、充值、发票、费用分析和利润模型不属于一期。
> 文档状态:已被拆分替代,仅保留历史设计过程,不作为后续实施依据 > 文档状态:已被拆分替代,仅保留历史设计过程,不作为后续实施依据
> 替代文档:[财务领域模型与数据字典](财务领域模型与数据字典.md)、[Firstleg-Finance 跨服务契约](Firstleg-Finance跨服务契约.md) > 替代文档:[财务领域模型与数据字典](财务领域模型与数据字典.md)、[Firstleg-Finance 跨服务契约](Firstleg-Finance跨服务契约.md)
> 原版本:F0-V1.0(历史稿) > 原版本:F0-V1.0(历史稿)