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

79 lines
4.6 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.
# topups 表字段设计
> 数据模型:**充值入账事件**——一行 = 一次「钱 → 账号额度」的入账。与 `subscriptions`(订阅权益)分表(见 `payments建模评估.md`,方案 B)。字段对齐上游实测 `GET /api/user/topup/self`(2026-10-09 样本);**无 `quota_granted` 列**(派生),**事件时刻只存一条**(上游 `complete_time`,即平台列表展示的时间)。
| 项目 | 内容 |
|------|------|
| 状态 | 定稿(2026-10-12,作者认可实现) |
| 关联 | `subscriptions表字段设计.md` · `payments建模评估.md` · `NewAPI-接口范围.md` §4.5 · `qpu_history表字段设计.md` |
| 范围 | 列结构 + 语义 + 写入时机 |
| 字段数 | 10 = 1 主键 + 8 上游/业务事实 + 1 登记时刻 |
---
## 1. 表定位
- **一行 = 一次充值入账**(事件);时间主轴 = **`paid_at`**(上游 `complete_time`,平台展示时刻)
- 与消耗的关系:钱包/账号余额池,**无法**逐笔对应模型日志(`billing_source=wallet` 无 `subscription_id` 是正常态)
- 不存 `quota_granted` 真值列(上游没有;见 §3)
## 2. 字段清单
| 列 | 类型 | 上游字段 | 说明 |
|----|------|----------|------|
| `id` | bigserial PK | — | 本地主键 |
| `upstream_id` | bigint? | `id` | 上游充值单 ID(对账;手工补录可空) |
| `amount` | numeric | `amount` | **平台计费金额**(充值记账额,样本 `1`)——与实付 `money` 之间由**管理员约定汇率**换算;**不标币种/单位** |
| `money` | numeric | `money` | **实付金额**(样本 `2.04`);同样不预设币种 |
| `trade_no` | text? | `trade_no` | 交易号 |
| `payment_method` | text? | `payment_method` | 如 `alipay` |
| `payment_provider` | text? | `payment_provider` | 如 `epay` |
| `status` | text? | `status` | 如 `success`;失败单一般不入账本 |
| `paid_at` | timestamptz | **`complete_time`** | **入账时刻(唯一事件时间)**——平台列表展示的就是它;上游 `create_time` 不入库 |
| `billing_domain` | text NULL | 人工标注(登记 / 编辑) | **账本域标签**(如 `carpool` / `office`);空 = 未标域,成员不可见(充值无逐笔日志连线,无法用日志证明「与我相关」) |
| `remark` | text | — | 人工备注 |
| `created_at` | timestamptz | — | 本系统登记时刻(补录审计) |
> 样本(2026-10-09):`amount: 1` · `money: 2.04` · `trade_no: "USR6NOLqTPGa1791534153"` · `alipay`/`epay` · `create_time`/`complete_time` Unix 秒 · `status: "success"`。展示与筛选一律用 `complete_time` 落入的 `paid_at`。
## 3. 「换得额度」是派生
上游无 `quota_granted`:派生 `amount × quota_per_unit`(默认 QPU 500000)——`amount` 是平台计费侧充值额,与 quota 同域量纲。
- **只存事实**:`amount`(平台计费)与 `money`(实付)两真值;**汇率不入库**(管理员社交约定,查询/展示可现算 `money/amount`)
- 不在库中固化派生额度
## 4. 时刻语义
| 时刻 | 含义 |
|------|------|
| `paid_at` | 入账(= 上游 `complete_time`)——筛选、排序、QPU 锚点 |
| `created_at` | 登记进本表(补录审计) |
## 5. 写入与维护
| 时机 | 动作 |
|------|------|
| **辅助登录选用**(与订阅选择器同模式) | 控制台登录(密码不落库)→ 分页拉 `/api/user/topup/self` → 选用预填表单 → 确认入库 |
| 纯手工登记 | 抄充值页 / 账单;或粘贴 JSON 预填 |
| 编辑 / 删除 | 改错即修 |
| 后台定时同步 | **不做**(辅助登录仅代拉一次、token 会话内用) |
**分页请求策略**(接口仅 `p` / `page_size`,**无时间过滤**):
1. **传统分页 UI**:弹层底部「共 N 条 · 页码 / 上一页 / 下一页」;每次请求只取当前页(`page_size=10`)
2. **不设硬上限**——用户可一直翻到 `total` 尽头(找旧账必须靠翻页)
3. **不提供时间范围筛选**(上游收窄不了结果集;本地筛只会误导读不出的更早页)
4. **已登记去重**:按 `upstream_id` 灰显,不可重复选用
5. **401**:清会话 token → 重新登录;token 仅 sessionStorage
## 6. 对外边界
- 成员可见:`amount`、`money`、渠道、`paid_at`、备注、`billing_domain`;**仅本人名下 key 所属账本域内**;无逐笔与模型日志的连线;未标域默认不可见
- 纯用量模式可不登记
## 7. 迁移说明
- 原 `payments.kind=topup`:`paid_at` 语义本就落在入账日 → 直接迁入本表 `paid_at`
- 若曾手填 `quota_granted`:可反推 `amount = quota_granted / qpu` 填 `amount`,否则按实付与约定补记