Files
docs/财务管理/财务领域模型与数据字典.md
T
2026-08-10 18:12:20 +08:00

204 lines
16 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.
# 财务领域模型与数据字典(F0/F1 首版)
> 版本:V0.1(开发前设计稿)
> 日期:2026-08-10
> 范围:F0 财务底座、F1 客户应收与对账;F2-F4 预留
> 关联:[财务服务边界设计](财务服务边界设计.md)、[财务管理产品确认表](财务管理产品确认表.md)、[二期费用项目数据归属决策记录](../二期/二期费用项目数据归属决策记录.md)
## 1. 阅读和决策标记
| 标记 | 含义 |
|---|---|
| 技术已确认 | 已由当前架构或总控决策冻结,开发必须遵守;不再要求产品选择技术方案。 |
| 建议默认值 | 为保证模型可实施而提出的默认值,产品未确认前可调整。 |
| 产品待确认 | 会改变业务口径、页面或验收结果,不能当作已确定需求。 |
本稿只冻结逻辑归属、关系和不可逆数据保护规则。账期天数、账套/主体、收入确认日、汇率及分摊算法等业务口径仍以产品确认表为准。
## 2. 已确认的公共约束
### 2.1 服务与数据库
- **技术已确认**:Finance 为独立 `finance-service`,数据库为 `baiyue_finance`;Finance 不跨库 Join,不引用其他服务 Entity,不接受 Firstleg 直接写库。
- **技术已确认**:Firstleg 只提供已发布的业务费用版本;Finance 入池后保存来源快照,历史账单不依赖 Firstleg 当前行回算。
- **技术已确认**:跨服务只使用 DTO、受保护内部查询和 Outbox/Inbox 事件;事件消费必须幂等、可重试、可查结果。
### 2.2 主体、客户和 ID
- **技术已确认**:产品层级为“平台—客户”,`tenant_id=0` 仅为平台技术作用域,客户业务数据使用 `tenant_id>0`。Finance 表按客户隔离;平台公共主数据不因客户筛选改变候选范围。
- **建议默认值**:所有主键使用 `BIGINT UNSIGNED`(雪花/号段 ID);API、JSON 和前端 TypeScript 均按字符串传输。
- **技术已确认**:往来单位只保存 `party_id` 引用、`party_type` 和当时的名称/编码快照,不复制客户或供应商实体。
### 2.3 平台、客户与子用户
- **当前对话已确认**:产品只有平台、客户两种身份;平台维护平台角色/用户,客户维护本客户角色/用户。
- **技术已确认**:客户用户的财务操作上下文必须来自服务端当前客户成员关系和权限快照;不能信任前端传入的 `customerId/tenantId`,也不能让客户用户切换到其他客户范围。
- **技术已确认**:财务单据保存操作人的 `userId/memberId`、角色/权限快照标识和操作时姓名快照;成员停用只撤销后续访问,不改历史单据。
- **产品待确认**:客户用户默认查看本客户全部财务数据,还是继续按部门/业务线细分;客户管理员可分配哪些客户侧财务权限;付款、退款、反核销和关账是否强制职责分离。
- **术语约束**:客户企业是客户数据归属/结算对象;平台收付款、开票和核算的法律主体仍以 Finance 的 `FinancialEntity`/账套表达。客户子用户永远不是新的财务主体。
### 2.4 金额、币种和精度
- **技术已确认**:币种保存 ISO 4217 三位码;原币金额不可覆盖;不同币种不能直接合并或核销。
- **建议默认值**:金额 `DECIMAL(20,6)` 保存原始计算值,展示/结算精度和舍入模式另设字段;数量/重量/体积 `DECIMAL(20,6)`。具体精度需与产品确认的计费规则复核。
- 所有金额字段成对保存 `*_amount` 与 `currency_code`(或由单据头统一币种且明细校验一致),不得用浮点数。
### 2.5 通用字段与审计
所有业务表建议具备:`id`、`tenant_id`、`version`(乐观锁)、`created_at`、`created_by`、`updated_at`、`updated_by`、`deleted`(仅允许非财务事实草稿使用)。已出账、收款、核销、冲销、开票和期间记录禁止物理删除;更正使用反向/调整记录。
## 3. 聚合边界与关系
```text
Firstleg FeeVersion --(Outbox)--> FinanceFeeSource
FinanceFeeSource --(可选多条)--> ARStatementLine --(一条有效来源只入一张有效账单)
ARStatement --(确认后生成)--> ARReceivable
ARReceipt <--> ARAllocation <--> ARReceivable
ARAllocation --(反核销)--> ARAllocationReversal
所有写操作 --> FinanceAuditLog / FinanceOutbox
```
聚合根建议:`FinanceFeeSource`(来源池)、`ARStatement`(客户对账单)、`ARReceivable`(应收单)、`ARReceipt`(收款单)。核销是独立不可变事实,不把余额直接写成“收款成功”。
## 4. F0 财务底座数据字典
以下为建议物理表名;字段类型是实现建议,不代表已经执行建表。
### 4.1 `fin_subject`:财务主体(产品待确认)
| 字段 | 类型/约束 | 说明 | 状态 |
|---|---|---|---|
| `id` | BIGINT PK | 主体 ID | 技术已确认(ID 规则) |
| `subject_code` | VARCHAR(64) UNIQUE | 收款/付款法律或业务主体编码 | 产品待确认:主体数量和编码 |
| `subject_name` | VARCHAR(200) | 主体名称快照 | 产品待确认 |
| `subject_type` | VARCHAR(32) | `RECEIVING`/`PAYING`/`BOTH` 建议 | 建议默认值 |
| `status` | VARCHAR(20) | `ACTIVE`/`INACTIVE` | 建议默认值 |
### 4.2 `fin_ledger`:账套与期间归属(账套待确认)
`ledger` 关联 `subject_id`,不把客户 ID 当作账套。建议字段:`ledger_code`(唯一)、`ledger_name`、`subject_id`、`base_currency_code`、`status`、审计字段。期间表 `fin_period` 使用 `period_code`(如 `2026-08`)和 `status=OPEN|CLOSING|CLOSED`;关闭期间禁止原地改账。主体、账套数量、本位币和是否月结均为**产品待确认**。
### 4.3 `fin_counterparty_ref`:往来单位引用快照
| 字段 | 类型/约束 | 说明 |
|---|---|---|
| `id` | BIGINT PK | Finance 内部引用 ID |
| `tenant_id` | BIGINT UNSIGNED NOT NULL | 客户隔离键;供应商为平台公共或其所属业务范围需按确认结果定 |
| `party_type` | VARCHAR(20) | `CUSTOMER`/`SUPPLIER` |
| `party_id` | BIGINT UNSIGNED NOT NULL | IAM/Warehouse 的外部 ID,仅引用 |
| `party_code`,`party_name` | VARCHAR | 获取时快照,保障历史可读 |
| 唯一约束 | `(tenant_id, party_type, party_id)` | 禁止同一客户重复引用 |
往来单位来源服务和供应商归属规则为**产品待确认**;Finance 不跨库外键。
### 4.4 `fin_currency` / `fin_exchange_rate`(F0 预留)
`fin_currency`:`currency_code CHAR(3) PK`、名称、精度、启用状态。
`fin_exchange_rate`:`id`、`from_currency`、`to_currency`、`rate DECIMAL(20,10)`、`rate_source`、`effective_at`、`version_no`、`snapshot_hash`、审计字段;唯一建议为 `(from_currency,to_currency,effective_at,version_no)`。汇率来源、交易日/账单日/月末取值和本位币折算为**产品待确认**,F0 仅建扩展位,未确认前不自动折算。
### 4.5 `fin_number_sequence`:单据编号
按 `sequence_type`(`AR`、`AP`、`STATEMENT`、`RECEIPT`、`PAYMENT`、`ALLOCATION`、`INVOICE`、`ACCOUNT`)和日期/主体分段发号。建议唯一 `(tenant_id, sequence_type, period_key)`,数据库锁或原子更新保证并发安全;重试使用幂等键返回原单号。编号格式和是否按主体分段为**产品待确认**。
### 4.6 `fin_fee_source`:财务费用来源池
| 字段 | 类型/约束 | 说明 |
|---|---|---|
| `id` | BIGINT PK | Finance 来源记录 ID |
| `tenant_id` | BIGINT UNSIGNED NOT NULL, CHECK >0 | 客户隔离键 |
| `source_type` | VARCHAR(32) | `FIRSTLEG_FEE` 等 |
| `source_id`,`source_version` | BIGINT/INT NOT NULL | Firstleg 费用 ID 与不可变版本 |
| `source_no` | VARCHAR(64) | 业务费用单号快照 |
| `inbound_id`,`order_id` | BIGINT NULL | 业务关联 ID 快照,不建跨库 FK |
| `fee_item_id`,`fee_item_code`,`fee_item_name` | ID + 快照 | 引用平台公共费用项目;名称保留快照 |
| `direction` | VARCHAR(16) | `RECEIVABLE`/`PAYABLE`,供应商方向待 F2 确认 |
| `amount`,`currency_code` | DECIMAL + CHAR(3) | 原币金额 |
| `tax_amount`,`tax_rate` | DECIMAL | 税务字段,税口径待确认 |
| `business_date` | DATE | 来源业务日期 |
| `eligibility_status` | VARCHAR(20) | `PENDING/ELIGIBLE/EXCLUDED/BILLED/VOIDED` |
| `source_hash` | CHAR(64) | 来源内容哈希 |
| `event_id` | VARCHAR(100) | Outbox 事件 ID |
| 唯一约束 | `(source_type, source_id, source_version)`;`(event_id)` | 防重复入池 |
**建议默认值**:仅 `APPROVED + PUBLISHED + settlementIncluded=true`、未作废版本进入 `ELIGIBLE`。该门槛、是否自动入池及历史迁移是**产品待确认(F0-08/F1 相关)**。
### 4.7 `fin_inbox_event` / `fin_audit_log`
`fin_inbox_event` 保存 `event_id`、事件类型、来源服务、幂等键、payload_hash、处理状态、重试次数、最后错误和处理时间;唯一 `(source_service,event_id)`,同键不同哈希必须拒绝并报警。
`fin_audit_log` 保存聚合类型/ID、动作、前后状态、变更摘要、操作者、请求/幂等键、trace_id、时间和原因。审计留存期、是否需要不可篡改存储为**产品待确认**,但财务事实不得删除是技术底线。
## 5. F1 客户应收与对账数据字典
### 5.1 `ar_statement`:客户对账单聚合根
核心字段:`id`、`tenant_id`、`statement_no`、`ledger_id`、`subject_id`、`counterparty_ref_id`、`currency_code`、`period_start/end`、`due_date`、`status`、`subtotal_amount`、`tax_amount`、`total_amount`、`confirmed_at/by`、`dispute_reason`、`version`。
建议唯一 `(tenant_id, statement_no)`;防重复出账的业务唯一键建议 `(tenant_id,counterparty_ref_id,currency_code,period_start,period_end,generation_key)`。账期边界、到期日和是否允许同一期间多张账单为**产品待确认**。
状态建议:`DRAFT → INTERNAL_REVIEW → SENT → CUSTOMER_CONFIRMED → CLOSED`;`SENT → DISPUTED → DRAFT`(重开)或 `VOIDED`。状态值来自产品确认表建议,最终流转和客户确认是否必需仍待确认。
### 5.2 `ar_statement_line`:对账单明细快照
字段:`id`、`statement_id`、`tenant_id`、`fee_source_id`、`source_version`、费用项目/来源单号快照、`quantity`、`unit_price`、`amount`、`currency_code`、税额、争议标记、排除原因、审计字段。
唯一建议 `(statement_id, fee_source_id)`;另以唯一条件约束同一有效 `fee_source_id` 只能关联一张未作废账单。明细不直接回写 Firstleg。
### 5.3 `ar_receivable`:应收单
字段:`id`、`tenant_id`、`receivable_no`、`statement_id`、`counterparty_ref_id`、`subject_id`、`currency_code`、`original_amount`、`allocated_amount`、`outstanding_amount`、`due_date`、`status`、`overdue_flag`、`recognized_at`、版本与审计字段。
唯一建议 `(tenant_id, statement_id)`(若产品允许一张账单拆多应收,改为 `(statement_id, receivable_no)`)。余额由核销事实汇总并在事务内更新,禁止前端传余额。
状态建议:`OPEN → PARTIALLY_SETTLED → SETTLED`;到期只置 `overdue_flag`。是否账单确认即生成应收、是否允许账单拆分,为**产品待确认**。
### 5.4 `ar_receipt`:收款单
字段:`id`、`tenant_id`、`receipt_no`、`subject_id`、`counterparty_ref_id`、`currency_code`、`received_amount`、`allocated_amount`、`available_amount`、`received_at`、`method`、`voucher_no`、`file_id`、`status`、登记/复核人、版本与审计字段。
建议状态 `DRAFT → CONFIRMED → PARTIALLY_ALLOCATED → FULLY_ALLOCATED → VOIDED`。到账方式、是否需复核和银行流水接入均为**产品待确认**;首版默认人工登记。
### 5.5 `ar_allocation` 与 `ar_allocation_reversal`
核销记录字段:`id`、`tenant_id`、`allocation_no`、`receipt_id`、`receivable_id`、`currency_code`、`allocated_amount`、`allocated_at`、`status=ACTIVE|REVERSED`、幂等键、操作者、原因和版本。
反核销字段:`id`、`allocation_id`、`reversal_no`、`reversed_amount`、`reason`、审批/操作人、时间、幂等键。唯一建议 `(tenant_id, idempotency_key)`;服务端校验同币种、不可超出收款可用额和应收未结额,反核销不删除原核销。
### 5.6 `ar_dispute`(建议预留)
保存 `statement_id`、提出方、争议明细/原因、状态 `OPEN|PROCESSING|RESOLVED|REJECTED`、处理结论和审计字段。客户是否在线提出争议、是否超期自动确认是**产品待确认**;若 F1 暂不做,可先在对账单保留原因字段而不开放独立菜单。
## 6. F2-F4 预留模型(不代表本期开发)
| 阶段 | 建议聚合/表 | 预留关系 | 产品待确认 |
|---|---|---|---|
| F2 应付 | `ap_statement`、`ap_statement_line`、`ap_payable`、`ap_payment`、`ap_allocation`、`ap_allocation_reversal` | 成本来源池 → 供应商账单 → 应付 → 付款核销 | 供应商主数据、成本确认节点、付款主体、审批分级 |
| F3 账户 | `fin_customer_account`、`fin_account_entry`、`fin_account_hold`、`fin_account_refund` | 充值/冻结/扣款/退款与应收核销分开,任何抵扣关联 `ar_allocation` | 账户是预付款还是授信、冻结/退款规则 |
| F3 发票 | `fin_invoice_application`、`fin_invoice`、`fin_invoice_action` | 应收可选关联发票;红冲/作废新增动作,不覆盖原票 | 开票主体、税率、含税口径、外部平台 |
| F4 分析 | `fin_cost_entry`、`fin_allocation_rule`、`fin_profit_snapshot`、`fin_report_snapshot` | 收入/成本来源、分摊、汇率快照 → 可钻取利润 | 收入成本确认日、汇率日、分摊维度、本位币和月结 |
F2 的来源必须具备供应商、付款主体、成本凭证、币种金额和成本归属;当前人工 `PAYABLE` 明细不自动视为应付闭环。
## 7. 跨服务来源契约(逻辑字段)
Firstleg Outbox 事件建议包含:`eventId`、`eventType`、`occurredAt`、`customerId`、`inboundId`、`orderId`、`sourceFeeId`、`sourceFeeVersion`、`sourceFeeNo`、`feeDetailId`、`direction`、`businessDate`、`currency`、`amount`、`sourceHash`、`settlementIncluded`、`isVoided`。Finance 收到后通过内部 DTO 查询完整费用快照并写入 `fin_fee_source`。
事件顺序可乱序:以 `(source_id, source_version)` 和版本状态机处理,旧版本不得覆盖新版本。相同幂等键不同 `source_hash` 必须进入冲突状态并告警。费用调整/作废不改写已出账明细,而是形成新的补差或冲销来源(具体业务单据待 F1/F2 确认)。
## 8. 数据访问、索引和隔离验收
- 业务表查询索引必须以 `tenant_id` 开头,并覆盖状态、日期、客户和单号等常用筛选;单据号在客户内唯一。
- Finance 不建立跨库外键;所有外部 ID 仅作引用和快照,失联时显示“来源不可用”而不删除财务事实。
- 平台员工按授权客户范围查询;客户端从登录态取 `tenant_id`,禁止信任请求体客户 ID。供应商成本、内部备注、审计详情和内部附件不向客户返回。
- 金额变更必须通过服务方法在同一财务期间事务内完成,使用幂等键和乐观锁;期间 `CLOSING/CLOSED` 禁止直接编辑。
- 关键唯一约束:来源 `(source_type,source_id,source_version)`;有效账单来源占用;单据号;核销幂等键;主体/账套/币种编码。
## 9. 产品待确认清单(本稿不替代确认表)
1. F0:财务主体与账套数量、往来单位/供应商归属、账期与关账、单据编号格式、来源入池和历史迁移。
2. F1:账单生成维度和周期、客户确认/争议、应收生成节点、收款登记/复核、到期日、预收/多收/手续费/退款处理。
3. F2:供应商成本确认节点、付款主体、应付审批和付款方式。
4. F3:账户资金性质、冻结/解冻/退款、发票税务主体和外部平台。
5. F4:收入/成本确认日、汇率来源和日期、公共成本分摊、期间快照及报表权限。
## 10. 实施前检查
- 产品确认表中 S1-S8、F0、F1 形成结论或“暂缓+临时口径”后,冻结本稿对应字段和状态。
- 冻结后补充 API/权限/错误码/事件契约,并将表名建议转为迁移脚本;不得先从页面或跨库查询反推模型。
- 迁移前只读核对历史已发布费用和线下结算事实,避免重复入账;任何冲突先停在预检,不直接改写历史。
- 本文件是设计文档,不代表已创建 `finance-service`、`baiyue_finance` 或任何数据库表。