Files
docs/财务管理/财务一期P0操作契约与验收用例.md
T
2026-08-20 09:43:35 +08:00

122 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 财务一期 P0 操作契约与验收用例
> 日期:2026-08-11
> 适用范围:一期财务闭环及后续确认的费用编辑审核、客户确认操作
> 状态口径:以下 11 项全部是一期 P0,目标契约已冻结;实现和 Admin 接入证据只维护在 `财务一期P0实现证据矩阵.md`
> 机器契约:`openapi/finance-phase1-five-pages-v1.yaml`
## 1. 统一冻结规则
- 金额只允许 CNY;请求出现其他币种或金额 `<= 0` 返回 `FIN_400`。
- 财务操作全部由平台财务人员人工提交表单。客户只能读取自己的已出账结果,不能审核、生成、调整、作废或登记收付款。
- 客户账户是账单、费用来源和收付款派生视图,不建设余额表,不提供钱包、预收、充值或余额调整接口。
- 平台接口使用权限码控制。实体必须按其真实客户归属校验;同一写请求中的来源、对账单、结算单和收付款对象必须属于同一客户。跨客户对象按不存在处理,返回 `FIN_404`,不得泄露对象是否存在。
- 所有写操作必须带 `Idempotency-Key`。请求哈希至少覆盖 method、规范化 path、目标客户、全部 query/body 字段;同键同参重放原结果,同键异参或仍在 `PROCESSING` 返回 `FIN_409`,FAILED/超时 PROCESSING 按现有 Finance 恢复规则执行。
- 带 `expectedVersion` 的操作使用乐观锁;版本不一致返回 `FIN_409`。出账后不原地覆盖,调整、作废和重开必须新增 revision 并保留操作人、原因、时间和前后值。
- 稳定错误码固定为:`FIN_400` 参数/CNY/金额错误,`FIN_404` 不存在或跨客户隐藏,`FIN_409` 状态/版本/重复占用/幂等冲突,`FIN_503` File 或内部依赖不可用,`FIN_001` 未分类服务端错误。认证和权限拒绝使用 HTTP `401/403`。
- 所有成功和业务错误响应固定包含 `requestId`、`traceId`、`timestamp`;成功 body 使用 `code="200"`,不得返回 Entity、Map 或临时字段。
## 2. P0 operation 冻结矩阵
| P0 | operationId | 请求 DTO | 响应 DTO | 权限 | 状态/隔离与核心验收 |
|---|---|---|---|---|---|
| P0-01 | `listDerivedCustomerAccounts` | `AccountListQuery`(page/pageSize/keyword/status) | `AccountPageEnvelope<AccountSummary>` | `platform:finance:account:view` | 聚合未收、待出账、本期已收、应付;停用客户仍保留历史金额;无钱包字段。验收 AC-01、AC-02 |
| P0-02 | `listDerivedCustomerAccountLedger` | `AccountLedgerQuery`(customerId path、业务类型、日期、分页) | `LedgerPageEnvelope<LedgerEntry>` | `platform:finance:account:view` | 只返回指定客户来源/单据/收付款派生流水;日期闭区间;跨客户对象不可混入。验收 AC-03、AC-04 |
| P0-03 | `getFinanceFeeSource` | `FeeSourceIdPath` | `FeeSourceDetailEnvelope<FeeSourceDetail>` | `platform:finance:customer-arap:list` | 返回业务关联、版本、审核、占用和操作日志;不接受前端覆盖客户或来源标识。验收 AC-05 |
| P0-04 | `reviewFinanceFeeSource` | `ReviewRequest` | `FeeSourceDetailEnvelope<FeeSourceDetail>` | `platform:finance:fee-source:review` | `PENDING -> APPROVED/REJECTED`;非 PENDING、旧版本、已占用均拒绝。审核通过自动发布并成为结算候选。验收 AC-06、AC-07 |
| P0-05 | `editFinanceFeeSource` / `submitFinanceFeeSource` / `adjustFinanceFeeSource` / `voidFinanceFeeSource` | `FeeSourceEditRequest` / `FeeSourceActionRequest` | `FeeSourceDetailEnvelope<FeeSourceDetail>` | `platform:finance:fee-source:edit` | `DRAFT/REJECTED` 可编辑并提交;`APPROVED` 调整回新草稿;作废保留审计。没有“是否结算”开关。验收 AC-08、AC-09 |
| P0-06 | `createReconciliationStatement` | `CreateReconciliationRequest` | `ReconciliationDetailEnvelope<ReconciliationDetail>` | `platform:finance:reconciliation:create` | 按截止日或勾选来源生成 DRAFT;来源须同客户、合格且未被有效单据占用,金额由服务端快照读取。验收 AC-10 至 AC-12 |
| P0-07 | `actionReconciliationStatement` | `ReconciliationActionRequest` | `ReconciliationDetailEnvelope<ReconciliationDetail>` | 按 action 使用 review/issue/adjust/void 权限 | 提交、审核、出账、调整、作废、重开均走 revision;ISSUED 冻结来源,调整后总额不得低于已收。验收 AC-13 至 AC-17 |
| P0-08 | `createReceivableSettlement` | `CreateReceivableSettlementRequest` | `SettlementDetailEnvelope<SettlementDetail>` | `platform:finance:settlement-ar:create` | 只从同客户 ISSUED 对账单生成,一张有效对账单只能有一个有效应收结算单;直接进入 ISSUED。验收 AC-18、AC-19 |
| P0-09 | `createPayableSettlement` | `CreatePayableSettlementRequest` | `SettlementDetailEnvelope<SettlementDetail>` | `platform:finance:settlement-ap:create` | 同客户、同供应商的 APPROVED/PUBLISHED/AVAILABLE/CNY PAYABLE 来源生成;供应商必须 ACTIVE,非空 supplierCategory 必须匹配。直接进入 ISSUED。验收 AC-20、AC-21 |
| P0-10 | `getSettlement` | `SettlementIdPath` | `SettlementDetailEnvelope<SettlementDetail>` | AR/AP view 二选一并与单据方向匹配 | 返回结算单、来源快照、revision 和收付款记录;没有对应方向权限时 HTTP 403。验收 AC-22、AC-23 |
| P0-11 | `createSettlementPayment` | `CreateSettlementPaymentRequest` | `SettlementDetailEnvelope<SettlementDetail>` | `platform:finance:payment:create` | 只允许 PAYABLE 的 ISSUED/PARTIALLY_PAID;金额不得超过余额,凭证 File fail-closed;更新为 PARTIALLY_PAID/PAID。验收 AC-24 至 AC-26 |
`createReceiptWithAllocations` 已实现,不计入上述 11 项,但仍属于一期 P0 回归门禁:一笔 300 元收款可人工分配到同一客户 3 张各 100 元应收结算单并共用凭证;跨客户、草稿、超额、非 CNY、无有效凭证必须拒绝。
### 2.1 契约与证据分离
本文件不记录 Controller、编译和测试中间态,也不使用 `NOT_IMPLEMENTED/IN_PROGRESS/IMPLEMENTED` 标记。G1-G4 后端行为测试和 Admin 真实接入证据统一见 `财务一期P0实现证据矩阵.md`;开发过程不得反向修改本文件冻结的路径、DTO、状态机和验收标准。
## 3. 状态机
### 3.1 费用来源
```text
DRAFT/REJECTED --EDIT/SUBMIT--> PENDING
PENDING --APPROVE--> APPROVED + PUBLISHED(自动成为结算候选)
PENDING --REJECT---> REJECTED
APPROVED --ADJUST--> DRAFT(新版本)
AVAILABLE --对账单占用--> LOCKED --对账单出账--> BILLED
任意未出账有效版本 --VOID--> VOIDED
AVAILABLE --上游调整新版本--> SUPERSEDED
```
### 3.2 客户对账单
```text
DRAFT --SUBMIT--> PENDING_REVIEW
PENDING_REVIEW --APPROVE--> APPROVED
PENDING_REVIEW --REJECT--> REJECTED
REJECTED/VOIDED --REOPEN--> DRAFT(新 revision)
APPROVED --ISSUE--> ISSUED(冻结来源)
ISSUED --ADJUST--> ISSUED(新 revision,不覆盖旧版)
DRAFT/PENDING_REVIEW/APPROVED/ISSUED --VOID--> VOIDED(已收金额=0 且无有效结算单)
```
`ADJUST` 必须提交至少一条调整行和原因;新总额不得小于已收金额。`VOID/REOPEN` 必须填写原因。ISSUED 后普通编辑接口不存在。
客户确认状态独立于上述主状态:`NOT_REQUIRED --ISSUE--> PENDING_CONFIRMATION --客户确认--> CONFIRMED`;调整后重置为 `PENDING_CONFIRMATION` 并保留历史确认审计。
Client 列表和详情中的“确认账单”均只在待确认且当前成员拥有独立写权限 `merchant:finance:statement:confirm` 时展示;`list/view` 只读权限不能替代确认权限。真实客户管理员通过全局 `MERCHANT_OWNER` 权限模板获得该权限,其他客户角色按授权配置决定是否可确认。
### 3.3 应收/应付结算单和收付款
```text
生成成功 -> ISSUED
ISSUED --部分收/付款--> PARTIALLY_PAID
ISSUED/PARTIALLY_PAID --收/付清--> PAID
ISSUED --VOID--> VOIDED(已收付金额=0)
VOIDED --REOPEN--> ISSUED(新 revision)
```
一期不处理预收、多收、退款、手续费、自动银行对账或汇率折算。人工收付款只能分配到同客户、同方向、CNY 且已出账的结算单。
## 4. 请求字段条件
- `CreateReconciliationRequest`:`customerId/currency/generationMode/periodStart/periodEnd` 必填;`currency=CNY`。`SELECTED` 时 `feeSourceIds` 至少 1 个,`BY_CUTOFF` 时服务端按 `periodEnd` 选择合格来源。
- `ReconciliationActionRequest`:`action/expectedVersion` 必填;`REJECT/ADJUST/VOID/REOPEN` 时 `reason` 必填;`ADJUST` 时 `adjustmentLines` 至少 1 个,每行包含 `statementLineId/adjustedAmount/reason`。
- `CreateReceivableSettlementRequest`:只提交 `reconciliationStatementId/currency`;客户、期间、金额和默认 30 天到期日由对账单与客户账期派生,不信任前端重复提交。
- `CreatePayableSettlementRequest`:`customerId/supplierId/feeSourceIds/dueDate/currency` 必填;来源必须同客户、同供应商。
- `CreateSettlementPaymentRequest`:`transactionDate/amount/currency/method/voucherFileIds/expectedVersion` 必填;`currency=CNY`、金额 `>0`、至少一张有效付款凭证。
## 5. 行为验收用例
| 用例 | 期望 |
|---|---|
| AC-01/02 | 账户列表金额可由来源、已出账结算单和收付款重算;响应不存在 balance/recharge/prepayment 字段 |
| AC-03/04 | 客户 A 流水不出现客户 B 单据;起止日期非法返回 `FIN_400` |
| AC-05 | 详情返回来源版本、业务对象和操作日志;不存在返回 `FIN_404` |
| AC-06/07 | PENDING 审核成功;重复审核、旧 expectedVersion 返回 `FIN_409` |
| AC-08/09 | 草稿/驳回项可编辑提交,已审核项可调整,非法状态或旧版本返回 `FIN_409`;审核通过后自动进入结算候选 |
| AC-10/11/12 | 两种生成模式成功;跨客户、非 CNY、重复占用或不合格来源分别返回 `FIN_404/FIN_400/FIN_409`,且不产生半成品 |
| AC-13/14 | 合法提交、审核和出账按状态迁移;非法 action/state 或并发版本返回 `FIN_409` |
| AC-15/16/17 | ISSUED 调整产生 revision;低于已收拒绝;有收款或有效结算单时作废拒绝;重开保留历史 |
| AC-18/19 | ISSUED 对账单生成唯一 AR;重复生成同参重放,异参或已有有效 AR 返回 `FIN_409` |
| AC-20/21 | 同客户同供应商 PAYABLE 来源生成 AP;混客户/供应商、已占用或非合格来源拒绝 |
| AC-22/23 | AR/AP 详情 DTO 完整;缺方向权限返回 403,不存在返回 `FIN_404` |
| AC-24/25/26 | 部分付款、付清状态正确;超额/重复/非 CNY/无凭证拒绝;File 不可用返回 `FIN_503` 且不落付款或更新余额 |
| AC-27 | 已实现收款回归:300 元分配 3 张 100 元同客户应收单成功并共用凭证 |
| AC-28 | 客户接口只能看到本人 `ISSUED/PARTIALLY_PAID/PAID` 单据和 `CONFIRMED` 收款,不返回凭证、内部备注、供应商成本或其他客户数据 |
| AC-29 | 每个写 operation 覆盖同键同参、同键异参、PROCESSING、FAILED/超时恢复;请求哈希改变任一业务字段即视为异参 |
## 6. 验收证据更新规则
目标契约保持冻结,不跟随实现状态修改。证据矩阵中的单项或分组只有同时满足以下全部证据才允许从 `FAIL` 改为 `PASS`:
1. Controller 存在与 OpenAPI 一致的 method/path、权限和固定 DTO。
2. Service/Repository 实现上述状态、客户归属、CNY、幂等、版本和审计规则。
3. 正向、非法状态、跨客户、无权限、同参重放、异参冲突和并发版本行为测试通过。
4. 涉及凭证的操作补 File fail-closed 测试;涉及客户可见数据的操作补脱敏与状态过滤测试。
5. 证据矩阵记录具体测试类、用例数、Admin 真实用例和最近通过结果。只有代码存在、只有编译通过或只有间接测试均不得提前标完成。