Files
docs/财务管理/F1人工账单收款成本接口契约.md
T
2026-08-11 09:25:45 +08:00

116 lines
6.1 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.
# F1 人工账单、收款、成本接口契约
> 版本:V1.0
> 日期:2026-08-11
> 状态:可进入 Finance 后端实现
> OpenAPI:`openapi/finance-f1-manual-v1.yaml`
## 1. 首期边界
- 只支持 RMB/CNY,不做汇率、月结、钱包、发票、银行流水和自动认款。
- 平台财务人工填写账单、收款、成本表单并上传凭证。
- 客户只读查看本客户账单、收款记录和未收余额。
- 出账前账单可改;出账后冻结,只能由平台财务调整或作废重开。
- 客户账期按客户配置,默认 30 个自然日;到期日为出账日加账期天数。
- 一笔收款可分配到多张账单;财务逐张填写分配金额。首期不处理预收、多收、手续费、退款。
- 单票成本归属单票;整柜清关、拖车等公共成本按柜内有效票体积分摊。
## 2. 统一接口约定
- 路径分为平台财务 `/api/platform/finance/v1` 和客户只读 `/api/client/finance/v1`。
- 普通业务返回 HTTP 200,业务结果在 `code` 字段;成功 `code="200"`。认证/网关拒绝可返回 401/403。
- 所有 ID 以字符串传输;金额为十进制定点数,首期 `currency=CNY`。
- 写请求必须带 `Idempotency-Key`;更新/动作请求必须带 `expectedVersion`。
- 客户范围从登录授权上下文取得,服务端忽略请求体中的客户切换字段。
- 文件先由 File 服务上传,Finance 接收 `fileId` 引用,不直接接收二进制。
## 3. 对象与状态
### 3.1 账单
字段:`billId`、`billNo`、`customerId`、`billDate`、`dueDate`、`currency`、`lines[]`、`totalAmount`、`receivedAmount`、`outstandingAmount`、`status`、`version`。
账单明细至少保存 `sourceFeeId`、`sourceFeeVersion`、`orderId`/`inboundId`、费用项目快照、数量、单价和金额。多笔订单分别出账;同一账单可包含多个费用项。
状态:`DRAFT → ISSUED → PARTIALLY_PAID → PAID`;`ISSUED/PARTIALLY_PAID/PAID → VOIDED`。`DRAFT` 可编辑,其他状态金额不可覆盖。
### 3.2 收款
字段:`receiptId`、`receiptNo`、`customerId`、`receivedDate`、`amount`、`currency`、`paymentMethod`、`voucherFileIds[]`、`remark`、`allocations[]`、`operatorSnapshot`。
`allocations[]` 每项为 `billId + allocatedAmount`。首期要求分配金额之和等于收款金额;每项不得超过对应账单未收余额。收款凭证可被同一笔收款的多张账单共享。
### 3.3 成本
字段:`costEntryId`、`costNo`、`costType`(`SINGLE_ORDER`/`CONTAINER_SHARED`)、`orderId`/`containerId`、费用项目、供应商/成本对象快照、金额、币种、凭证文件、备注、操作人。
单票成本直接归属单票;整柜公共成本按 `票体积 / 柜内有效票总体积` 分摊。体积为零或总量为零时拒绝自动分摊,改为人工指定;舍入尾差归最后一票并记录调整原因。
## 4. 接口清单
### 平台财务
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | `/api/platform/finance/v1/bills` | 查询账单 |
| POST | `/api/platform/finance/v1/bills` | 保存账单草稿 |
| GET | `/api/platform/finance/v1/bills/{billId}` | 查询平台账单详情 |
| PUT | `/api/platform/finance/v1/bills/{billId}` | 更新账单草稿 |
| POST | `/api/platform/finance/v1/bills/{billId}/issue` | 出账并冻结 |
| POST | `/api/platform/finance/v1/bills/{billId}/adjust` | 出账后调整/生成新版本 |
| POST | `/api/platform/finance/v1/bills/{billId}/void` | 作废账单 |
| POST | `/api/platform/finance/v1/receipts` | 人工登记收款并分配账单 |
| GET | `/api/platform/finance/v1/receipts` | 查询收款记录 |
| POST | `/api/platform/finance/v1/cost-entries` | 人工登记单票/整柜成本 |
| GET | `/api/platform/finance/v1/cost-entries` | 查询成本记录 |
### 客户只读
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | `/api/client/finance/v1/bills` | 查询本客户账单 |
| GET | `/api/client/finance/v1/bills/{billId}` | 查看账单详情 |
| GET | `/api/client/finance/v1/receipts` | 查看本客户收款记录 |
客户端禁止 POST、PUT、PATCH、DELETE 财务写操作。
## 5. 最小错误码
| 错误码 | 场景 |
|---|---|
| `FIN-AR-001` | 账单不存在或不属于当前客户 |
| `FIN-AR-002` | 账单状态不允许当前操作 |
| `FIN-AR-003` | 出账后尝试直接修改金额 |
| `FIN-AR-004` | 账期配置无效 |
| `FIN-AR-005` | 首期仅允许 CNY |
| `FIN-AR-006` | 收款分配金额合计不等于收款金额 |
| `FIN-AR-007` | 分配金额超过账单未收余额 |
| `FIN-AR-008` | 凭证文件不存在、无权引用或类型不允许 |
| `FIN-AR-009` | 版本冲突,请刷新后重试 |
| `FIN-AR-010` | 幂等键重复但请求内容不同 |
| `FIN-COST-001` | 成本归属对象缺失 |
| `FIN-COST-002` | 体积为零,无法按体积分摊 |
| `FIN-AUTH-001` | 当前角色无平台财务写权限 |
## 6. 验收用例
1. 平台财务创建 CNY 草稿账单,保存后可继续编辑。
2. 账单出账生成账单号和到期日(出账日+客户账期,默认 30 天)。
3. 出账后修改金额被拒绝;通过调整或作废重开保留原版本。
4. 登记 300 元收款,上传一张凭证并分配到 3 张 100 元账单,三张账单均更新余额。
5. 一张账单分两次收款后显示 `PARTIALLY_PAID`,余额归零后显示 `PAID`。
6. 收款分配超过任一账单未收余额或合计不等于收款金额时拒绝且不落部分数据。
7. 客户只读可见本客户账单和收款记录,不可写入、不跨客户查询。
8. 客户子用户停用后不能访问财务页面,但历史操作人和客户财务归属不变。
9. 登记单票成本成功;整柜公共成本按体积分摊,零体积场景要求人工指定。
10. 重复 `Idempotency-Key` 返回原结果;同键不同请求返回 `FIN-AR-010`。
## 7. 实现依赖
- F0:Finance 服务、客户范围、权限码、编号器、审计、文件引用和幂等表。
- Firstleg:已发布费用来源快照和来源版本查询;Finance 不跨库读取。
- Admin:平台财务路由和三个写表单。
- Client:账单/收款只读查询。
本契约不要求修改 Firstleg 或 Finance Java;后端实现时以此文档和 OpenAPI 为准。