# ARR 数据库最终架构冻结

更新时间：2026-07-28  
状态：已按 `database/008_arr_mvp_v1_rebuild.sql` 实施，不再是候选方案。

## 最终数据链

```text
用户上传 XML
  → ARR 后端存入私有 OSS
  → SuperAgent 获取 XML
  → Agent 调用确定性日报 Skill
  → 生成 structured-result.json 和正式工件
  → ARR 后端重新校验 Schema、哈希、公式和处理语义
  → 单事务写入 PostgreSQL
  → 普通程序查询数据库
      ├─ 生成月报 XLSX
      ├─ 查询渠道明细/渠道 BI
      └─ 生成每 10 日公司用房表

预订 Excel/当前 MD fixture
  → 私有 OSS/受控 fixture
  → 行级 Agent 解析
  → ARR 验收
  → PostgreSQL booking 来源行 + room items
  → 按 RES_COMMENT/Group Code 为报表补充 Booking Room
```

Agent、Skill 和 SuperAgent 永远不持有数据库凭据，也不直接写 PostgreSQL。ARR 后端是唯一写入方。

## 已实施的 schema 归属

| schema | 职责 |
|---|---|
| `ingestion` | 工件身份、处理运行/尝试/交付、幂等和 outbox |
| `booking` | 预订来源行、不可变解析版本、当前解析和房型明细 |
| `finance` | 日报不可变版本、全部 source outcome、渠道指标和 current 指针 |

## 关键冻结决策

1. 只使用独立 `booking_test`，不把 ARR 表放进共享维护库 `postgres`。
2. 预订来源行按原 worksheet/row 逐行保存；同一 Group Code 可以重复。
3. 预订原文和完整 Agent 行级 JSON 保留，同时把 room items 结构化供查询。
4. 日报 structured-result 的全部 outcome 都落库；业务视图只读 current + retained。
5. 同日重跑形成不可变新版本，全部验收通过后才切 current；失败不影响旧 current。
6. `TOTAL PRICE = REAL PRICE × NO_OF_ROOMS × NIGHTS` 由 ARR 重算并由数据库约束再次保护。
7. 精确关联键为 `upper(trim(XML.RES_COMMENT)) = booking.group_code_key`；不用 `BLOCK_CODE`，不用模糊匹配。
8. Booking 数据只补充 Booking Room；Finance 提供日期、晚数、实际房数和价格。
9. 月报、渠道明细、BI 和公司 10 日报表是程序投影，不复制一套 report rows/version facts。
10. 文件字节保存在私有 OSS；PostgreSQL 只保存不可变对象身份、哈希、大小和血缘。

## 为什么保留 `artifacts`、批次和解析版本

- `ingestion.artifacts` 让 ARR 能验证 Agent 所称的 XML、日报和 JSON 是否确实是同一批交付，并实现幂等和追溯。
- `booking.source_batches/source_rows` 记录“哪一份附件、哪个 worksheet、哪一行”产生了预订信息，不能只留最终 Group Code 汇总。
- `booking.parse_versions.result_json` 保存 Agent 已验收的结构化输出；`room_items` 是供普通 SQL 查询的可计算拆分。
- 这些字段是数据血缘，不是任务卡状态。

## 报表处理口径

| 输出 | 数据来源 | 是否重复落库 |
|---|---|---|
| 日报 | Agent structured-result，经 ARR 验收 | 是，作为 Finance 权威日事实 |
| 月报 | current + retained 日事实，加 Booking Room | 否，程序生成 |
| 渠道明细/BI | current + retained 日事实 | 否，视图/程序查询 |
| 每 10 日公司用房表 | Finance 日期/价格 + booking 房型 | 否，程序生成 |

渠道明细的 `Total Booking Price` 直接等于对应日报行的 `total_price`，不是同 Group Code 合计，也不使用预订附件价格重算。

## 本轮明确不做

- 多酒店/多租户；
- 用户、角色和最小权限 DDL；
- RSVN 任务卡；
- 邮件发件人、主题、Message-ID 等元数据；
- 报表数据库版本表；
- 日报追溯前端。

## 生产前门禁

当前使用远程测试地址和数据库 owner 用户，只用于测试；它不是面向应用的最小权限角色。生产前仍需：

- 创建 ARR writer、业务 reader 等最小权限角色；
- 接入正式私有 OSS provider/bucket 与 Secret 管理；
- 完成 SuperAgent 文件句柄、回调验签和共享幂等协议；
- 清理合成测试数据并导入真实但合规的数据；
- 做备份恢复、并发、失败注入、权限和隐私回归。

生产是否继续使用同一物理地址不是数据库模型能自动决定的事项；上线时必须显式核对环境、库名、账号和备份，不能只“清空测试数据”后默认当生产。
