Files
docs/财务管理/财务来源接入现状.md
2026-08-14 10:09:48 +08:00

409 lines
25 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.
# 财务来源接入现状
> 盘点日期:2026-08-10
> 盘点范围:`baiyue-firstleg/`、`apps/admin-web/`
> 盘点方式:只读核对 Controller、DTO、Service、Entity、SQL、OpenAPI、前端 API/类型/页面和测试
> 用途:为 Firstleg → Finance F0 的来源接入设计提供代码现状基线,不代表 Finance 已实现
## 一、结论摘要
当前仓库已经具备可作为 Finance 上游的入库费用事实,但尚未形成可直接接入 Finance 的完整生产链路。
已经具备:
- 入库费用从试算、确认、发布到发布后调价的版本化快照;
- 自动发布的对客应收入库运费明细,以及人工应收/应付费用明细的录入与审核基础;
- 平台公共费用项目主数据;
- 费用写操作幂等、业务审计和 Firstleg 本地 Outbox 落库;
- Admin 的费用项目、入库费用快照、已发布费用调整和统一订单费用明细查询;
- Order 的可运行 Outbox 调度、重试模式,以及 Event Bridge 的事件信封和 Inbox 幂等模式,可作为实现参考。
尚未具备:
- `finance-service`、Finance 数据库、Finance Inbox 和财务来源池;
- Firstleg 面向 Finance 的冻结事件契约和内部来源快照查询接口;
- Firstleg Outbox 的实际扫描、投递、重试、失败/死信处理;
- 费用作废事件,以及已出账后补差/冲销语义;
- 跨入库单的待结算费用池、账单占用/冻结和财务状态回执;
- Finance 独立权限、财务单据、收付款及核销能力。
因此,F0 可以复用当前费用快照、费用明细和本地事务 Outbox 的写入位置,但不能直接把 `fl_inbound_fee_detail` 当作 Finance 台账,也不能把现有 Event Bridge 当作 Firstleg → Finance 的现成消息通道。
## 二、现有费用来源模型
### 2.1 入库计费快照
`fl_inbound_fee` 保存版本化费用头,`fl_inbound_fee_item` 保存费用组成。核心能力如下:
| 能力 | 当前实现 | 可复用价值 | 现有限制 |
|---|---|---|---|
| 试算 | `POST /api/platform/v1/inbounds/{inboundId}/fees/calculate` | 保存计费输入、规则/价格版本、计费量和金额快照 | 只面向单个入库单,不是财务来源查询接口 |
| 确认 | `POST .../fees/confirm` | `CALCULATED -> CONFIRMED`,写操作带 `Idempotency-Key` | 确认是业务计费状态,不等于财务审核 |
| 发布 | `POST .../fees/send` | `CONFIRMED -> SENT`,生成对客费用明细并写 Outbox | 方法和事件仍使用 `send/SENT` 旧命名;事件负载过少 |
| 查询最新快照 | `GET .../fees/latest` | Admin 可读取最新业务快照 | 只返回最新版本,不适合 Finance 核验指定历史版本 |
| 发布后调价 | `PUT .../fees/published` | 旧 `SENT` 版本转 `SUPERSEDED`,生成新 `SENT` 版本,保留调整原因并写 Outbox | 没有已出账判断;Finance 上线后不能继续无条件覆盖来源有效版本 |
`FeeSnapshotResponse` 已包含可复用的主要快照字段:
- 标识:`feeId`、`feeNo`、`feeVersion`、`inboundId`、`inboundCode`;
- 状态:`feeStatus`、`nextProcessStatus`;
- 客户与业务:`customerId`、`customerName`、`businessType`;
- 规则与价格:规则/价格 ID、编码、版本、价格表版本及有效期;
- 路由与目的地:起运仓、渠道、承运商、目的地类型/ID/名称/编码;
- 计费依据:实际重量、实际体积、换算量、计费量、单位、换算/舍入/税模式;
- 金额:单价、小计、附加费、总额、币种;
- 时间:试算、确认、发布时间。
费用快照的数据库约束已经提供 `(tenant_id, inbound_id, fee_version)` 唯一键,金额使用定点小数,币种为三位码。这些可继续作为 Firstleg 来源版本的事实基础。
### 2.2 已发布费用明细
`fl_inbound_fee_detail` 是当前最接近财务来源的业务表。自动发布链路会把 `SENT` 费用快照转换为一条入库应收运费明细:
| 字段组 | 已有字段/状态 |
|---|---|
| 来源定位 | `sourceType=FBA_PRICING`、`sourceFeeId`、`sourceFeeVersion`、`sourceFeeNo` |
| 业务定位 | `tenantId`、`inboundId`、`inboundCode`、`businessDate` |
| 客户快照 | `customerId`、`customerName`、`invoiceTitle` |
| 费用快照 | 费用分类、贸易范围、费用名称、方向、币种、单价、金额 |
| 计费依据 | 箱数、重量、体积、体积重、计费量、计费单位 |
| 审核 | `PENDING / APPROVED / REJECTED`,审核人、时间、原因 |
| 发布 | `DRAFT / PUBLISHED / SUPERSEDED`,发布人、时间 |
| 结算候选标识 | `settlementIncluded` |
自动发布的 FBA 头程运费固定为:
- `direction=RECEIVABLE`;
- `reviewStatus=APPROVED`;
- `publicationStatus=PUBLISHED`;
- `settlementIncluded=true`;
- 来源费用项目编码 `FBA_HEAD_FREIGHT`,作为独立于 Excel 110 条受控项目的系统公共费用项目,由完整初始化 SQL 固定创建;服务端不在业务请求中补建主数据。
发布新费用版本时,旧的已发布运费明细会被标记为 `SUPERSEDED`,而不是物理删除。`(tenant_id, source_type, source_fee_id)` 的来源唯一性和并发重复键兜底,已经能支撑来源版本幂等的第一层防护。
人工费用明细支持 `RECEIVABLE | PAYABLE`,但创建后为 `PENDING + DRAFT + settlementIncluded=false`。现有审核通过只改变审核状态,没有发布/纳入结算动作,因此人工明细尚不能按统一规则自动进入 Finance。
### 2.3 费用项目
平台费用项目接口已完整实现:
| 操作 | 接口 | 权限 |
|---|---|---|
| 分页查询 | `GET /api/platform/v1/fee-items` | `firstleg:fee-item:view` |
| 详情 | `GET /api/platform/v1/fee-items/{id}` | `firstleg:fee-item:view` |
| 新增 | `POST /api/platform/v1/fee-items` | `firstleg:fee-item:create` |
| 编辑 | `PUT /api/platform/v1/fee-items/{id}` | `firstleg:fee-item:edit` |
| 启停 | `PATCH /api/platform/v1/fee-items/{id}/status` | `firstleg:fee-item:edit` |
| 删除 | `DELETE /api/platform/v1/fee-items/{id}` | `firstleg:fee-item:delete` |
现有 DTO/实体字段包括 `feeCode`、分类、`DOMESTIC | INTERNATIONAL`、提货/仓库应收应付适用性、是否分摊费、说明和 `ACTIVE | DISABLED`。
F0 可引用稳定 `feeCode` 并保存名称/分类快照,但不应直接把 Firstleg 费用项目表作为 Finance 自有会计科目表。Finance 费用科目与业务费用项目需要显式映射和独立版本管理。
## 三、现有接口、DTO、权限与状态
### 3.1 可复用平台接口
| 范围 | 接口 | DTO/返回 | 权限 | F0 复用判断 |
|---|---|---|---|---|
| 费用快照 | `GET .../inbounds/{inboundId}/fees/latest` | `FeeSnapshotResponse` | `firstleg:fba-pricing:view` | 可供 Admin 查看,不满足 Finance 按来源版本核验 |
| 费用调整 | `PUT .../inbounds/{inboundId}/fees/published` | `AdjustFeeRequest` → `FeeSnapshotResponse` | `firstleg:fba-pricing:adjust` | 保留业务入口,但需增加已出账约束或改走补差/冲销 |
| 费用明细查询 | `GET .../inbounds/{inboundId}/fee-details?accountId=` | `List<InboundFeeDetailEntity>` | `firstleg:inbound:fee-detail:view` | 仅单入库单平台查询,不作为跨服务契约 |
| 人工费用新增/编辑 | `POST/PUT .../fee-details` | `SaveRequest` → `InboundFeeDetailEntity` | `firstleg:inbound:fee-detail:edit` | 可继续维护业务费用,不能代替财务制单 |
| 人工费用删除 | `DELETE .../fee-details/{detailId}` | 空 | `firstleg:inbound:fee-detail:delete` | 仅未审核明细可删;Finance 入池后必须禁止物理语义 |
| 人工费用审核 | `POST .../{detailId}/approve|reject` | `RejectRequest` | `firstleg:inbound:fee-detail:review` | 可作为业务来源前置条件 |
| 客户已发布费用 | `GET /api/merchant/v1/first-leg/orders/{orderId}/inbound-billing` | `MerchantInboundBillingResponse` | `merchant:order:view` | 客户只读展示,不是 Finance 内部来源接口 |
费用试算、确认、发布还分别使用:
- `firstleg:fba-pricing:calculate`;
- `firstleg:fba-pricing:confirm`;
- `firstleg:inbound:send-fee`。
上述权限都是 Firstleg 业务权限。F0 需要新增 Finance 独立权限资源,不能复用它们授权财务入池、冲突处理、来源重放或来源作废。
### 3.2 建议冻结的来源状态映射
| Firstleg 状态组合 | 当前含义 | F0 建议 |
|---|---|---|
| `feeStatus=CALCULATED` | 已试算 | 不入池 |
| `feeStatus=CONFIRMED` | 业务已确认 | 不入池 |
| `feeStatus=SENT` + 明细 `APPROVED/PUBLISHED/settlementIncluded=true` | 当前有效对客费用 | 允许生成 Finance 来源 |
| 旧费用 `SUPERSEDED` + 旧明细 `SUPERSEDED` | 已有更新版本 | Finance 已消费时保留原来源,新增调整来源,不覆盖历史 |
| 人工明细 `PENDING/DRAFT/false` | 待业务审核 | 不入池 |
| 人工明细 `APPROVED/DRAFT/false` | 已审核但未发布 | 当前仍不入池;先补发布动作与事件 |
| `REJECTED` | 业务驳回 | 不入池 |
`SENT` 是当前代码中的“已发布给客户”状态,F0 契约宜对外统一为业务语义清晰的 `PUBLISHED`,同时保留内部兼容映射,避免直接修改存量状态造成迁移风险。
## 四、Outbox 与事件能力现状
### 4.1 Firstleg 本地 Outbox
`fl_inbound_outbox` 已包含:事件 ID、客户隔离键、聚合类型/ID、事件类型、JSON 负载、发布状态、重试次数、下次重试时间、发布时间和创建时间。费用发布/调整与业务表在同一本地事务内写入 Outbox,写入位置可复用。
当前实际费用事件只有:
| 事件 | 触发点 | 当前负载 |
|---|---|---|
| `FIRSTLEG_FEE_SENT` | 已确认费用发布 | `inboundId`、`feeId` |
| `FIRSTLEG_FEE_ADJUSTED` | 已发布费用生成新版本 | `inboundId`、`feeId`、`feeVersion` |
当前 Firstleg 模块没有 `@Scheduled` Outbox 扫描器、消息生产者、发布成功/重试更新逻辑,也没有费用作废事件。因此 `PENDING` 记录目前只落库,不会自动送达 Finance。
### 4.2 可参考的 Order Outbox
Order 已有可运行的 `OrderInboundOutboxPublisher`:
- 定时分页扫描待发布事件;
- 校验聚合类型、事件类型、所有权和负载完整性;
- 通过受保护内部客户端投递 Firstleg;
- 成功标记已发布,失败设置下次重试,不支持的事件永久失败;
- 对应测试覆盖成功、无效事件、负载错误、所有权冲突和重试。
F0 可以复用这一可靠投递结构和测试思路,但费用事件应使用专门发布器/消费者和冻结的事件信封,不应扩展 `OrderInboundOutboxPublisher` 承载 Finance 逻辑。
### 4.3 Event Bridge 与公共事件契约
`common-event-contract` 已提供版本化 `EventEnvelope`、区域、事件 ID、负载规范化、SHA-256 哈希和基础校验;ID 使用字符串,适合跨语言和长整型安全传输。
`event-bridge-service` 已提供:
- `POST /internal/event-bridge/events`,使用 `X-Internal-Service-Token`;
- 目标区域和 `payloadHash` 校验;
- 以 `eventId` 幂等入库;
- 相同事件 ID 但负载哈希、客户或信封身份不同则拒绝覆盖;
- Inbox 状态初始为 `RECEIVED`。
但它明确是跨区域接收骨架:状态接口返回发送能力未就绪,尚无真实跨区发送、重试调度、死信补投和领域消费分发。公共 `EventTypes` 也没有费用事件常量。Firstleg → Finance 是同国内业务域内的服务协作,F0 应优先建立独立的服务内事件投递/Inbox 契约;只有架构明确要求统一事件总线时,才将公共信封的通用字段复用进该链路。
### 4.4 审计 Outbox 不是领域 Outbox
Firstleg 还包含通用 `sys_audit_outbox`,用于 `@BusinessAudit` 业务操作审计。它与 `fl_inbound_outbox` 的领域事件用途不同,不能把审计事件当作 Finance 来源事件。F0 需要同时保留“来源领域事件”和“财务操作审计”两条记录。
## 五、Admin 已有能力
### 5.1 正式页面与接口
| 页面/能力 | 当前状态 | 使用契约 |
|---|---|---|
| 费用项目 | 正式路由 `/master-data/fee-items`,支持查询、新增、编辑、启停、删除和权限态 | `/platform/v1/fee-items` |
| 船期价格表 | 正式路由 `/first-leg-pricing/carrier-rates`,支持价格表上传、查询和发布 | FBA pricing price-book API |
| 入库费用快照 | 入库详情工作区已嵌入 `InboundFeePanel`,展示计算依据、金额、规则/价格版本和时间线 | `GET .../fees/latest` |
| 已发布费用调整 | 入库费用面板支持填写小计、附加费和原因,带客户端幂等键 | `PUT .../fees/published` |
| 统一订单费用明细 | 订单详情费用页签按入库单加载应收/应付明细并展示审核、计费、结算标识 | `GET .../fee-details?accountId=` |
Admin 当前没有:
- 财务来源池页面;
- 跨客户/跨入库单费用筛选、入池状态、冲突和重放操作;
- 账单占用、冻结、补差/冲销、作废展示;
- Finance 权限和正式 Finance API 适配。
财务管理导航仍整体 `hidden: true`,指向 `/prototype/finance/*`。这些原型页不属于正式生产能力,不应作为 F0 接入基础。
### 5.2 前后端契约注意点
- Admin 对费用快照和入库 ID 使用字符串类型,符合长整型传输要求;
- 费用项目资源兼容 `number | string`,但新增/编辑请求没有暴露后端可选 `feeCode`,F0 不应从页面名称反推稳定来源科目;
- 统一订单费用明细前端预留了 `billNo`、结算起止日等字段,后端当前实体并未提供这些财务字段;这些 UI 预留不能视为已实现账单能力;
- `InboundFeePanel` 只接入查询和发布后调整,没有接入试算、确认、发布按钮,相关动作仍由后端流程/其他编排承担。
## 六、F0 缺口清单
| 优先级 | 缺口 | 风险/影响 |
|---|---|---|
| P0 | 缺少 Finance 服务、数据库、Inbox 和来源表 | 无法建立财务所有权和独立事务边界 |
| P0 | Firstleg 无费用 Outbox 发布器 | 事件只停留在 `PENDING`,Finance 无法接收 |
| P0 | 费用事件名称、版本和负载未冻结 | 当前 `FIRSTLEG_FEE_SENT` 与目标 `PUBLISHED` 语义不一致,负载无法独立幂等核验 |
| P0 | 缺少按 `sourceFeeId + sourceFeeVersion` 查询的内部快照 API | Finance 只能依赖事件少量字段或平台 API,均不合适 |
| P0 | 缺少来源哈希 | 无法检测同一来源版本内容被覆盖或事件冲突 |
| P0 | 缺少作废事件和原因 | 错误费用无法以不可变方式退出财务来源池 |
| P0 | 发布后调价未校验财务占用 | 已出账后仍可能直接把旧来源标记为 `SUPERSEDED` |
| P1 | 人工费用审核后无发布动作 | 人工应收/应付无法可靠进入统一来源链路 |
| P1 | 无跨单费用池查询和游标/时间增量接口 | 补偿扫描、历史迁移和运营核对困难 |
| P1 | 无 Outbox 失败查询、人工重放、退避和死信策略 | 故障不可运营化处理 |
| P1 | 无 Finance 独立权限与审计事件 | 来源冲突、重放、作废等高风险操作无法分权 |
| P1 | 应付来源字段不足 | 人工 `PAYABLE` 缺供应商、付款主体、凭证和成本归属,不能直接进入 F2 |
| P2 | OpenAPI 未提供完整 `FeeSnapshotResponse` schema | 跨服务调用方难以通过契约测试防止字段漂移 |
| P2 | Admin 无来源接入状态和错误可观测性 | 上游已发布但 Finance 未入池时无法定位 |
## 七、Firstleg → Finance F0 接入建议
### 7.1 接入主链路
```text
Firstleg 费用发布/调整/作废事务
-> 更新 Firstleg 业务费用与不可变版本
-> 同事务写 fl_inbound_outbox
-> Firstleg Outbox Publisher 投递版本化事件
-> Finance Inbox 以 eventId 去重并校验来源身份
-> Finance 用内部令牌查询指定来源版本完整快照
-> 校验 sourceHash
-> Finance 保存不可变来源快照和处理结果
-> 后续 F1/F2 从 Finance 来源池制单
```
Finance 不跨库读取 Firstleg,不共享 Entity,不以 Admin 平台接口作为服务间接口。
### 7.2 建议冻结的事件
建议对外统一:
- `FIRSTLEG_FEE_PUBLISHED`;
- `FIRSTLEG_FEE_ADJUSTED`;
- `FIRSTLEG_FEE_VOIDED`。
兼容策略:存量 `FIRSTLEG_FEE_SENT` 可由发布器映射为 `FIRSTLEG_FEE_PUBLISHED` V1,或通过一次受控迁移重建待发布事件;不要让 Finance 同时长期理解两套同义事件。
事件信封至少包含:
- `eventId`、`eventType`、`eventVersion`、`occurredAt`;
- `customerId`(技术字段仍可映射现有 `tenantId`);
- `aggregateType=FIRSTLEG_FEE`、`aggregateId=sourceFeeId`、`aggregateVersion=sourceFeeVersion`;
- `inboundId`、`sourceFeeId`、`sourceFeeVersion`、`sourceFeeNo`;
- `feeDetailId`、`direction`、`businessDate`、`currency`、`amount`;
- `reviewStatus`、`publicationStatus`、`settlementIncluded`;
- `sourceHash`、`traceId`、`correlationId`、`causationId`;
- 调整/作废事件的 `previousSourceFeeId`、`reason`。
事件只用于通知和快速路由,Finance 仍应通过内部接口读取完整快照。
### 7.3 建议新增的 Firstleg 内部接口
建议提供受内部服务令牌保护的版本查询,而不是复用 `latest`:
```text
GET /internal/firstleg/v1/finance/fee-sources/{sourceFeeId}?version={sourceFeeVersion}
```
返回专用 `FirstlegFeeSourceSnapshot`,至少覆盖:来源身份、客户、入库业务键、费用项目快照、方向、业务日、币种金额、计费依据、审核/发布/结算候选状态、发布时间、调整链和 `sourceHash`。不存在、版本不符、未达到入池状态时返回明确业务错误码。
可补充一个只用于补偿和迁移的分页接口,按 `publishedAt + sourceFeeId` 稳定游标扫描;它不能替代实时事件。
### 7.4 幂等与乱序
- Outbox 事件 ID 全局唯一;
- Finance Inbox 先按 `eventId` 去重;
- 财务来源再以 `sourceType + sourceId + sourceVersion` 唯一;
- 同一唯一键但 `sourceHash` 不同必须进入冲突状态,禁止覆盖;
- 调整 V2 早于发布 V1 到达时,先保存待依赖状态并重试核验,不能用 V2 覆盖 V1;
- Finance 已出账的 V1 永久保留,V2 形成补差/冲销候选,不修改原账单明细;
- 发布器成功、重试、永久失败和人工重放均记录时间、次数、错误摘要和审计人。
### 7.5 Firstleg 调整门禁
F0 上线前应冻结以下规则:
1. 未进入 Finance 或仍在待对账池的来源,可由新版本替代,但 Finance 保留版本历史;
2. 已被账单占用的来源不能直接调整原金额,必须发布补差或冲销来源;
3. 作废不物理删除原费用和事件;
4. Firstleg 不保存财务余额或账单状态,只保存必要的只读占用/处理回执或通过 Finance 内部校验门禁;
5. Finance 不回写 `fl_inbound_fee_detail` 伪造 `billNo`,账单关系归 Finance 自有表。
### 7.6 权限建议
保留现有 Firstleg 业务权限,并在 IAM 中为 Finance 新建独立权限,例如:
- `finance:source:view`;
- `finance:source:retry`;
- `finance:source:resolve-conflict`;
- `finance:source:void`;
- `finance:source:export`。
内部事件投递和快照查询使用服务身份,不使用平台员工权限。人工重放、冲突处理和作废属于高风险操作,必须填写原因并记录业务审计。
## 八、建议实施顺序与验收
### 8.1 实施顺序
1. 冻结 V1 事件、内部快照 DTO、来源哈希算法和状态映射;
2. 在 Firstleg 增加指定版本内部查询及契约测试;
3. 增加 Firstleg Outbox 发布器、重试/失败状态和运维查询;
4. 建立 Finance Inbox、来源表、唯一约束和冲突状态;
5. 联通发布、重复、乱序、失败重试、调整和作废链路;
6. 增加 Admin 来源池和接入状态页面;
7. 最后迁移满足条件的历史已发布费用。
### 8.2 F0 最小验收案例
- 一条 `APPROVED + PUBLISHED + settlementIncluded=true` 的应收费用只生成一个 Finance 来源;
- 同一事件重复投递不重复入池;
- 同一来源版本不同哈希被拒绝并可运营处理;
- Finance 暂停后恢复,Firstleg Outbox 能重试并最终成功;
- V2 调整不会覆盖 Finance 中 V1 来源;
- V2 先于 V1 到达不会破坏版本顺序;
- 已出账 V1 的后续调整形成补差/冲销候选;
- 作废保留原来源和审计链;
- 跨客户查询、事件或快照调用被服务端拒绝;
- 长整型 ID 按字符串传输,金额/币种精度不丢失;
- Admin 能看到待处理、成功、重试、冲突状态以及 `requestId/traceId`。
## 九、证据路径
### 9.1 Firstleg 费用与计费
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformFbaPricingController.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/dto/FbaPricingDtos.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/FbaPricingService.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/entity/InboundFeeEntity.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/entity/InboundFeeItemEntity.java`
- `baiyue-firstleg/firstleg/src/main/resources/openapi/fba-pricing-v1.yaml`
- `baiyue-firstleg/firstleg/src/main/resources/db/phase2-inbound-schema.sql`
- `baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/service/FbaPricingServiceTest.java`
- `baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/controller/FbaPricingContractTest.java`
### 9.2 费用明细与费用项目
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformInboundFeeDetailController.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/InboundFeeDetailService.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/dto/InboundFeeDetailDtos.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/entity/InboundFeeDetailEntity.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformFeeItemController.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/dto/FeeItemDtos.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/entity/FeeItemEntity.java`
- `baiyue-firstleg/firstleg/src/main/resources/openapi/fee-item-v1.yaml`
- `baiyue-firstleg/firstleg/src/main/resources/db/phase2-fee-item-and-inbound-detail.sql`
- `baiyue-firstleg/firstleg/src/main/resources/db/phase2-published-freight-detail-migration.sql`
- `baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/service/FeeManagementServiceTest.java`
- `baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/controller/FeeManagementContractTest.java`
### 9.3 客户费用查询
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/controller/MerchantInboundBillingController.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/MerchantInboundBillingService.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/dto/MerchantInboundBillingResponse.java`
- `baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/controller/MerchantInboundBillingControllerContractTest.java`
### 9.4 Outbox、事件与权限
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/entity/InboundOutboxEntity.java`
- `baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/mapper/InboundOutboxMapper.java`
- `baiyue-firstleg/order/src/main/java/com/baiyue/order/entity/OutboxEventEntity.java`
- `baiyue-firstleg/order/src/main/java/com/baiyue/order/service/OrderInboundOutboxPublisher.java`
- `baiyue-firstleg/order/src/test/java/com/baiyue/order/service/OrderInboundOutboxPublisherTest.java`
- `baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/EventEnvelope.java`
- `baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/EventTypes.java`
- `baiyue-firstleg/event-bridge-service/src/main/java/com/baiyue/eventbridge/controller/EventBridgeController.java`
- `baiyue-firstleg/event-bridge-service/src/main/java/com/baiyue/eventbridge/service/EventInboxService.java`
- `baiyue-firstleg/event-bridge-service/src/test/java/com/baiyue/eventbridge/service/EventInboxServiceTest.java`
- `baiyue-firstleg/iam/src/main/resources/db/phase2-fba-pricing-permissions.sql`
- `baiyue-firstleg/iam/src/main/resources/db/phase2-fee-item-permissions.sql`
- `baiyue-firstleg/deploy/sql/头程数据库统一增量-MySQL8.sql`
### 9.5 Admin
- `apps/admin-web/src/modules/inbounds/fee/api.ts`
- `apps/admin-web/src/modules/inbounds/fee/types.ts`
- `apps/admin-web/src/modules/inbounds/fee/InboundFeePanel.vue`
- `apps/admin-web/src/modules/inbounds/components/InboundWorkflowWorkspace.vue`
- `apps/admin-web/src/modules/fee-items/api/platformFeeItems.ts`
- `apps/admin-web/src/modules/fee-items/pages/FeeItemsView.vue`
- `apps/admin-web/src/modules/unified-orders/api/unifiedOrders.ts`
- `apps/admin-web/src/modules/unified-orders/pages/UnifiedOrdersView.vue`
- `apps/admin-web/src/core/navigation/adminNavigation.ts`
## 十、盘点边界
本文只证明当前代码已经存在的能力和 F0 接入缺口。没有修改业务代码、数据库脚本或既有文档,也没有验证测试环境消息中间件、数据库实值或实际事件投递。Finance 的财务主体、期间、账套、币种、权限和编号等产品口径仍以财务管理产品确认结果为准。