Files
docs/财务管理/财务服务边界设计.md

220 lines
12 KiB
Markdown
Raw Permalink 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.
# 财务服务边界设计
> **范围说明**:本文只作为 Finance 独立服务/独立数据库的技术边界依据。文中的钱包、充值、发票、费用分析和利润属于长期模型,不属于订单与客户;订单与客户唯一产品范围以《财务核心五页产品与接口验收契约》为准。
> 决策日期:2026-08-10
> 决策状态:技术已确认
> 决策结论:Finance 采用独立服务和独立数据库
> 适用范围:财务 F0-F4 全量建设
## 一、正式结论
财务域新增独立 `finance-service`,拥有独立财务数据库。不得把应收、应付、对账单、收付款、核销、客户账户、发票、费用分析或利润继续放入 `firstleg-service`。
身份与主体边界补充确认:产品层只有“平台、客户”两种身份。平台可以管理平台角色和平台用户;客户可以在本客户范围内管理客户角色和客户用户。客户用户是财务操作人,不因创建或操作财务单据而成为新的财务主体。
Finance 中必须分开建模:
- **客户企业/客户范围**:业务数据归属和客户侧结算对象,服务端从登录授权上下文确定,不能由前端任意切换;
- **平台财务主体/账套**:平台收款、付款、开票和核算的法律/账务主体;即使当前只有一个,也保留独立对象;
- **客户用户/成员**:仅作为客户范围内的操作人,保存 `userId/memberId` 和当时的姓名快照;账单、应收、余额和核销归属客户企业,不归属成员。成员停用只撤销访问和权限,不触发财务单据转交。
- **角色与权限**:平台角色由平台维护,客户角色由客户在允许的权限目录内维护,任何角色都不能越过客户范围。
已确认首期采用“一客户企业=一个对客结算对象”。这里的客户是业务数据归属和应收结算对象,不等同于平台收付款、开票和核算的法律主体;平台财务主体/账套仍单独建模。首期不支持一个客户配置多个对客结算对象或独立账套。
`firstleg-service` 保持现有业务边界,只负责:
- 入库单、测量、称重和审核;
- FBA/头程计费规则匹配与费用计算;
- 业务费用快照、费用版本、发布、调整和作废;
- 向 Finance 发布不可变费用来源事件;
- 提供 Finance 核验完整费用来源的内部查询接口。
`finance-service` 负责:
- 财务主体、往来单位引用、币种、汇率、财务期间和单据编号;
- 财务费用来源池;
- 客户对账单、应收单、收款单、核销和反核销;
- 供应商对账单、应付单、付款单、付款核销和反核销;
- 客户账户、充值、冻结、解冻、扣款、退款和账户流水;
- 发票申请、开票登记、红冲、作废和附件关联;
- 成本台账、费用分析、利润分析和期间快照;
- 财务权限、幂等、Outbox、版本和审计记录。
## 二、为什么拆服务
拆库本身不强制拆服务,但当前财务范围已经形成独立业务域,具备独立服务的必要条件:
1. 财务拥有独立状态机。计费状态不能代替账单、应收、收款和核销状态。
2. 财务拥有独立事务边界。入库完成不能与收款、核销或开票放在同一个事务中。
3. 财务需要更严格的权限和审计。反核销、付款、关账和红冲不应复用入库费用编辑权限。
4. 财务数据生命周期更长。已出账、已核销和已开票记录不能随着业务订单调整被覆盖。
5. 财务同时消费 Firstleg、Order、Warehouse、IAM、File 等业务信息,不属于 Firstleg 的单一履约职责。
6. 后续应付、客户账户、发票和利润会持续扩展,放入 Firstleg 会形成不可控耦合。
## 三、目标拓扑
```text
Admin / Client
|
v
Gateway
|
+-----------------------+
| |
v v
firstleg-service finance-service
firstleg 数据库 finance 数据库
| |
| 费用事件 / 内部查询 | 财务单据与台账
+---------------------->|
|
+--> file-service(凭证/发票附件)
+--> iam-service(身份、客户与权限核验)
+--> warehouse-service(供应商/往来单位核验)
```
禁止:
- Finance 跨库 Join Firstleg、Warehouse、IAM 或 Order 数据库;
- Finance 直接引用其他服务 Entity;
- Firstleg 直接写 Finance 数据库;
- 前端传入客户 ID 后绕过服务端客户范围校验;
- 通过修改 Firstleg 费用状态代替财务调整、冲销或反核销。
### 3.1 实现标识预留
经现有 Maven 聚合工程、服务端口表、Nacos 配置和部署清单核对,Finance 实施时统一使用以下标识:
| 项目 | 规划值 | 当前状态 |
|---|---|---|
| 后端模块目录 | `baiyue-firstleg/finance/` | 规划,尚未创建 |
| Maven artifactId | `finance-service` | 规划,尚未创建 |
| Nacos 注册服务名 | `finance-service` | 规划,尚未注册 |
| 服务端口 | `9203` | 规划预留;现有 11 个服务未占用 |
| 独立数据库 | `baiyue_finance` | 规划,尚未创建 |
`9203` 仅作为当前架构下的默认预留端口;若部署环境端口占用情况变化,可由配置调整,但仓库内默认值、部署映射和文档必须保持一致。
## 四、数据归属
| 数据 | 归属服务 | 说明 |
|---|---|---|
| 入库单、测量、重量、体积 | Firstleg | 业务履约事实 |
| 计费规则、价格版本、计费快照 | Firstleg | 业务费用计算依据 |
| 已发布费用来源版本 | Firstleg | Finance 的不可变上游来源 |
| 财务来源池 | Finance | 保存来源引用、版本、哈希和财务入池状态 |
| 客户/供应商对账单 | Finance | 不回写业务费用表 |
| 应收、应付、收款、付款 | Finance | 财务余额和状态唯一来源 |
| 核销、反核销 | Finance | 不允许物理删除 |
| 客户账户和流水 | Finance | 与应收台账分开,抵扣必须产生核销记录 |
| 发票台账 | Finance | 文件内容仍由 File 保存 |
| 成本、分摊、利润和期间快照 | Finance | 只能基于财务台账计算 |
| 客户身份和权限资源 | IAM | Finance 只引用和核验 |
| 公共往来单位/供应商资料 | Warehouse | Finance 保存引用和历史名称快照 |
## 五、Firstleg 到 Finance 的契约
### 5.1 事件
Firstleg 通过本地 Outbox 发布:
- `FIRSTLEG_FEE_PUBLISHED`
- `FIRSTLEG_FEE_ADJUSTED`
- `FIRSTLEG_FEE_VOIDED`
以上是目标事件名。当前 Firstleg 已存在 `FIRSTLEG_FEE_SENT` 和 `FIRSTLEG_FEE_ADJUSTED`;实施时将 `FIRSTLEG_FEE_SENT` 兼容映射为 `FIRSTLEG_FEE_PUBLISHED`,并补充明确的作废事件,不能把规划事件误写成当前已上线能力。
事件采用“统一信封 + 轻量来源引用”,不直接承载完整金额和计费明细。至少包含:
```text
eventId
eventType
eventVersion
occurredAt
producer
tenantId
inboundId
sourceFeeId
sourceFeeVersion
sequence
idempotencyKey
payloadHash
traceId
```
Finance 以 `eventId` 做投递幂等,并以 `sourceType + sourceFeeId + sourceFeeVersion` 做业务唯一约束。重复相同事件返回第一次处理结果;同一业务键对应不同哈希时拒绝处理并记录冲突。金额、币种、方向、业务日期、费用明细和业务快照必须通过内部快照接口核验后保存,不能只信任事件载荷。
### 5.2 内部查询
Finance 接收事件后,通过服务令牌调用 Firstleg 内部接口核验完整来源快照。内部接口返回 DTO,不返回或共享 Entity。接口路径、信封字段、重试和兼容规则以《Firstleg-Finance 跨服务契约》为准。
Finance 保存来源快照后,不依赖 Firstleg 当前表数据实时计算历史账单。已出账来源发生调整时,Finance 生成补差或冲销来源,不覆盖原账单明细。
## 六、Finance 服务内部模块
建议 `finance-service` 内部先按业务域分包,不在首期继续拆成多个微服务:
```text
finance-service/
foundation/ 财务主体、币种、汇率、期间、编号
source/ 费用来源接入与校验
receivable/ 对账单、应收、收款、核销
payable/ 供应商对账、应付、付款、核销
account/ 客户账户和流水
invoice/ 发票生命周期
costing/ 成本和分摊
reporting/ 费用分析和利润
audit/ 财务操作日志
```
当前只拆一个 Finance 服务,不把应收、应付、钱包、发票和报表各自拆成独立微服务。只有将来出现独立团队、独立扩缩容或明显不同的可用性需求时,才重新评估二次拆分。
## 七、开发顺序
```text
F0:finance-service 骨架、独立数据库、主体/币种/期间/编号、来源接入、幂等和审计
-> F1:客户对账、应收、收款和核销
-> F2:供应商对账、应付、付款和核销
-> F3:客户账户和发票
-> F4:成本、费用分析和利润
```
F1 与 F2 可以在 F0 契约冻结后并行开发;F3/F4 可以并行做页面和契约设计,但生产数据链路必须依赖前序财务台账。
## 八、技术验收标准
- `finance-service` 可以独立构建、部署和回滚;
- Finance 数据库不存在对其他服务数据库的跨库外键或 Join;
- Firstleg 发布费用后,Finance 能幂等生成一条财务来源;
- 重复事件、乱序事件和失败重试不会重复入账;
- 已出账费用调整不会覆盖历史账单;
- 所有财务写操作有幂等键、乐观锁、权限和审计;
- 长整型 ID 以前端字符串传输,金额使用定点小数和 ISO 三位币种;
- 跨客户、跨主体、跨币种和关闭期间操作由服务端拒绝;
- Admin/Client 使用正式 Finance API,不依赖 `/prototype/finance/*` 页面或模拟数据。
## 九、进入实现时的仓库改造清单
以下是 Finance 开发阶段必须完成的技术工作,不属于产品待确认项。本轮只形成规划,不创建服务、不建库、不修改部署环境。
| 范围 | 实施时需要新增或修改 | 验证重点 |
|---|---|---|
| Maven 聚合 | 根 `pom.xml` 增加 `finance` module;新增 `finance/pom.xml` | `mvn -pl finance -am test` 可独立构建 |
| 服务配置 | 新增 `config/nacos/local/finance-service.yml`、`config/nacos/cn/finance-service.yml` | 服务名、端口、数据源、内部令牌与环境变量约定一致 |
| 数据库 | 新增 Finance 自有迁移目录,并同步统一增量 SQL 入口 | 只创建/访问 `baiyue_finance`,无跨库外键或 Join |
| 部署映射 | 更新 `deploy/service-map.yml`、`deploy/docker-compose.yml` 和部署脚本 | 生成独立 JAR、镜像、容器,可单独部署/回滚 |
| Gateway | 增加 Finance 平台端/客户端路由和 Swagger/OpenAPI 聚合 | 前端仍只通过 `/api` 访问;平台端与客户端访问域隔离 |
| CI/CD | 更新 Jenkins 增量构建、受影响服务识别和部署映射 | 修改 Finance 只构建相关单元;公共模块变更包含 Finance |
| 服务契约 | Firstleg 增加费用 Outbox 事件及受保护内部快照查询;Finance 增加 Inbox/消费结果 | 重复、乱序、重试、冲突事件均可验证 |
| 权限与审计 | IAM 增加 Finance 权限资源;Finance 接入公共鉴权与审计能力 | 服务端校验客户范围、高风险权限和操作留痕 |
| 架构文档 | 更新服务总览、端口/数据库表和调用拓扑 | 可运行服务口径由 11 个变为 12 个 |
实施时必须先冻结 Finance 与 Firstleg 的事件/查询契约,再并行建设 Finance 内部 F1/F2 模块;不得先由前端或数据库表反推跨服务契约。
## 十、复核结论
当前仓库采用 Maven 多模块单仓、服务独立 JAR/镜像/容器、服务独立数据库、DTO/事件协作的架构。Finance 独立服务与这一模式一致,不需要因为代码处于同一 Git 仓库而并回 `firstleg-service`。
因此本技术决策保持不变:**新增一个 `finance-service` 和一个 `baiyue_finance` 数据库,服务内部按财务子域分包,当前不继续拆成多个财务微服务。**