Files
new-api-key-usage/docs/design/subscriptions表字段设计.md
skycurtain b0e9ea750b feat: 账本域 billing_domain 与成员支付可见性收紧
三表增加账本域标签,成员支付参数改为同域透明、跨域隔离、未标域默认藏;管理面登记/筛选/行内编辑与文档中心同步对齐。
2026-10-13 20:42:26 +08:00

66 lines
4.2 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.
# subscriptions 表字段设计
> 数据模型:**订阅权益登记**——一行 = 一笔上游订阅实例(覆盖期 + 额度预算 + 可选的套餐付款事实)。与 `topups`(充值入账事件)分表,对齐 NewAPI「权益 vs 入账」两分(见 `payments建模评估.md`,方案 B 已采纳)。平台只存**事实**,不做分摊计算。
| 项目 | 内容 |
|------|------|
| 状态 | 定稿(2026-10-12,作者认可实现) |
| 关联 | `topups表字段设计.md`(充值事件)· `payments建模评估.md`(拆表裁决)· `usage_logs表字段设计.md` 3.6(`subscription_id` 直连)· `qpu_history表字段设计.md` · `docs/references/NewAPI-接口范围.md` §4.3 |
| 范围 | 列结构 + 语义 + 写入时机;方言映射归数据访问层 |
| 字段数 | 9 = 1 主键 + 1 上游编号 + 2 期间 + 1 额度 + 2 付款(可空) + 1 备注 + 1 登记时刻 |
---
## 1. 表定位
- **一行 = 一笔上游订阅实例**(权益),不是「一张付款单」
- 权益事实(`subscription_id` / 期间 / 总额度)抄自钱包页(`GET /api/subscription/self`);金钱事实(付了多少、何时付)来自支付凭证,**可空**——分期、赠送、未掌握凭证时允许不填
- `subscription_id` 与日志 `other.subscription_id` **同体系直连**(事实关联,不推算)
- 数据规模:年个位数行——无需独立索引设计(`subscription_id` UNIQUE 足够)
## 2. 字段清单
| 列 | 类型 | 值来源 | 说明 |
|----|------|--------|------|
| `id` | bigserial PK | 自增 | 本地主键 |
| `subscription_id` | bigint UNIQUE | 人工录入(钱包页「订阅 #N」) | 上游订阅实例 ID;日志直连键 |
| `period_start` | timestamptz | 人工录入 | 用量覆盖期起点;左闭 |
| `period_end` | timestamptz? | 人工录入 | 期间终点;左开;未结束可空 = 进行中 |
| `quota_granted` | bigint | 人工录入(钱包页 `amount_total`) | 套餐总额度——**原始 quota 整数**(与日志 `quota` 同域;充值侧无此列,额度由 `amount × qpu` 派生) |
| `paid_amount` | numeric? | 人工录入(支付凭证) | 该套餐实付金额;币种无关纯数值;未知可空 |
| `paid_at` | timestamptz? | 人工录入(支付凭证) | **钱出手时刻**(非登记时刻);未知可空 |
| `billing_domain` | text NULL | 人工标注(登记 / 编辑) | **账本域标签**(如 `carpool` / `office`);空 = 未标域,成员不可见(涉及该订阅 `subscription_id` 的日志事实直连除外) |
| `remark` | text | 人工填写 | 备注 |
| `created_at` | timestamptz | 系统 | **登记入库时刻**(补录审计) |
## 3. 时刻语义(三时刻钉死)
| 时刻 | 含义 | 谁写 |
|------|------|------|
| `created_at` | 作者按下「登记」 | 系统 |
| `paid_at` | 钱真实出手(凭证时间) | 人工;不知则空 |
| `period_start` / `period_end` | 用量覆盖期 | 人工(抄钱包页) |
筛选约定:**用量窗口看期间重叠**;**补录审计看 `created_at`**;**付款账看 `paid_at`(有则)**。
## 4. 决策摘要
- **不与充值同表**:时间轴不同(期间 vs 事件);见 `payments建模评估.md` 方案 B
- **只存事实、不存比率**:`paid_amount` 与 `quota_granted` 相除得比率;不落分摊
- **额度存原始 quota**(原 payments 3.6):与日志同域可比;美元展示现算
- **`paid_amount` / `paid_at` 可空**:社交层付款信息允许缺失;不阻塞权益登记
- **多订阅期间可重叠**(R8):不设互斥约束
## 5. 写入与维护
| 时机 | 动作 |
|------|------|
| 人工登记 | INSERT(管理通道);来源:钱包页 JSON 预填 + **辅助登录选用**(按 `subscription_id` 去重,已登记灰显)+ 支付凭证 |
| 编辑 / 删除 | 改错即修(人工数据) |
| 日志观测 | 仅核对提示(观测到 #N 无登记),不回填 |
## 6. 对外边界
- 参数对成员**同账本域内可见**(含 `remark` / 金额)——同域透明、跨域隔离;未标域默认对成员隐藏,例外:该订阅 `subscription_id` 出现在本人名下 key 的 `type = 2` 日志中(事实直连)
- 无「应付」、无分摊字段