2026-08-10 17:48:45 +08:00
|
|
|
|
# 财务服务边界设计
|
|
|
|
|
|
|
|
|
|
|
|
> 决策日期:2026-08-10
|
|
|
|
|
|
> 决策状态:技术已确认
|
|
|
|
|
|
> 决策结论:Finance 采用独立服务和独立数据库
|
|
|
|
|
|
> 适用范围:财务 F0-F4 全量建设
|
|
|
|
|
|
|
|
|
|
|
|
## 一、正式结论
|
|
|
|
|
|
|
|
|
|
|
|
财务域新增独立 `finance-service`,拥有独立财务数据库。不得把应收、应付、对账单、收付款、核销、客户账户、发票、费用分析或利润继续放入 `firstleg-service`。
|
|
|
|
|
|
|
2026-08-10 18:12:20 +08:00
|
|
|
|
身份与主体边界补充确认:产品层只有“平台、客户”两种身份。平台可以管理平台角色和平台用户;客户可以在本客户范围内管理客户角色和客户用户。客户用户是财务操作人,不因创建或操作财务单据而成为新的财务主体。
|
|
|
|
|
|
|
|
|
|
|
|
Finance 中必须分开建模:
|
|
|
|
|
|
|
|
|
|
|
|
- **客户企业/客户范围**:业务数据归属和客户侧结算对象,服务端从登录授权上下文确定,不能由前端任意切换;
|
|
|
|
|
|
- **平台财务主体/账套**:平台收款、付款、开票和核算的法律/账务主体;即使当前只有一个,也保留独立对象;
|
2026-08-11 09:25:45 +08:00
|
|
|
|
- **客户用户/成员**:仅作为客户范围内的操作人,保存 `userId/memberId` 和当时的姓名快照;账单、应收、余额和核销归属客户企业,不归属成员。成员停用只撤销访问和权限,不触发财务单据转交。
|
2026-08-10 18:12:20 +08:00
|
|
|
|
- **角色与权限**:平台角色由平台维护,客户角色由客户在允许的权限目录内维护,任何角色都不能越过客户范围。
|
|
|
|
|
|
|
2026-08-10 18:29:04 +08:00
|
|
|
|
已确认首期采用“一客户企业=一个对客结算对象”。这里的客户是业务数据归属和应收结算对象,不等同于平台收付款、开票和核算的法律主体;平台财务主体/账套仍单独建模。首期不支持一个客户配置多个对客结算对象或独立账套。
|
2026-08-10 18:12:20 +08:00
|
|
|
|
|
2026-08-10 17:48:45 +08:00
|
|
|
|
`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`
|
|
|
|
|
|
|
2026-08-10 18:12:20 +08:00
|
|
|
|
以上是目标事件名。当前 Firstleg 已存在 `FIRSTLEG_FEE_SENT` 和 `FIRSTLEG_FEE_ADJUSTED`;实施时将 `FIRSTLEG_FEE_SENT` 兼容映射为 `FIRSTLEG_FEE_PUBLISHED`,并补充明确的作废事件,不能把规划事件误写成当前已上线能力。
|
|
|
|
|
|
|
|
|
|
|
|
事件采用“统一信封 + 轻量来源引用”,不直接承载完整金额和计费明细。至少包含:
|
2026-08-10 17:48:45 +08:00
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
eventId
|
|
|
|
|
|
eventType
|
2026-08-10 18:12:20 +08:00
|
|
|
|
eventVersion
|
2026-08-10 17:48:45 +08:00
|
|
|
|
occurredAt
|
2026-08-10 18:12:20 +08:00
|
|
|
|
producer
|
|
|
|
|
|
tenantId
|
2026-08-10 17:48:45 +08:00
|
|
|
|
inboundId
|
|
|
|
|
|
sourceFeeId
|
|
|
|
|
|
sourceFeeVersion
|
2026-08-10 18:12:20 +08:00
|
|
|
|
sequence
|
|
|
|
|
|
idempotencyKey
|
|
|
|
|
|
payloadHash
|
|
|
|
|
|
traceId
|
2026-08-10 17:48:45 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-08-10 18:12:20 +08:00
|
|
|
|
Finance 以 `eventId` 做投递幂等,并以 `sourceType + sourceFeeId + sourceFeeVersion` 做业务唯一约束。重复相同事件返回第一次处理结果;同一业务键对应不同哈希时拒绝处理并记录冲突。金额、币种、方向、业务日期、费用明细和业务快照必须通过内部快照接口核验后保存,不能只信任事件载荷。
|
2026-08-10 17:48:45 +08:00
|
|
|
|
|
|
|
|
|
|
### 5.2 内部查询
|
|
|
|
|
|
|
2026-08-10 18:12:20 +08:00
|
|
|
|
Finance 接收事件后,通过服务令牌调用 Firstleg 内部接口核验完整来源快照。内部接口返回 DTO,不返回或共享 Entity。接口路径、信封字段、重试和兼容规则以《Firstleg-Finance 跨服务契约》为准。
|
2026-08-10 17:48:45 +08:00
|
|
|
|
|
|
|
|
|
|
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` 数据库,服务内部按财务子域分包,当前不继续拆成多个财务微服务。**
|