Files
new-api-key-usage/docs/design/payments表字段设计.md
T
skycurtain db20dcb611 docs: 交互设计定稿——八篇按功能分篇,经作者逐篇审阅定稿
- 八篇:总览与共性 / 登录与会话 / 全员总览 / key 管理 / 支付记录 / 成员管理 / 审计日志 / 成员视图
- 关键定案:R12 携带形态(来源徽章 + 展开行,两种空值场景区分)、纯用量模式(部门实例——无支付记录的完整子集,共性 §3.8)、响应式只做布局响应、组件能力需求清单(选型验收标准)、审计日志保留操作者列(前向兼容多管理员)、Key 与成员管理分页 + 「+ 新建成员」缝合流程
- 审阅期修订全记录见需求清单 §9「交互设计八篇定稿」
2026-10-01 23:58:28 +08:00

99 lines
7.6 KiB
Markdown
Raw 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.
# payments 表字段设计
> 数据模型第三张表:支付记录——每笔支付事件(订阅购买 / 充值)一行。平台只存**事实**(支付金额、换得额度、来源参数),「支付金额与额度之间的比率」是查询时的派生视图,不存储、不做任何分摊计算。本文记录字段清单、语义与决策理由。
| 项目 | 内容 |
|------|------|
| 状态 | 定稿(2026-10-01) |
| 关联 | `docs/design/usage_logs表字段设计.md` 3.6(`subscription_id` 直连与本表)· `docs/design/qpu_history表字段设计.md`(quota → 额度美元的换算时间线)· `docs/references/NewAPI-接口范围.md` §2.⑨(`other.subscription_*` 字段依据) |
| 范围 | 列结构 + 语义 + 写入时机;方言映射归数据访问层设计 |
| 字段数 | 9 = 1 主键 + 8 人工录入(支付 4 · 期间 2 · 订阅 2) |
---
## 1. 表定位
- **一行 = 一笔支付事件**(订阅购买 / 充值)——同一模型兼容两种形态(`kind` 列区分)
- **本表是「只有作者知道」的信息的唯一落点**:支付金额、额度、订阅 ID——上游没有免 auth 接口可查,全靠作者手工抄录
- **币种无关**:`paid_amount` 是支付金额数值,**系统不预设币种**——币种是使用者之间的约定;「金额 ↔ 额度」的比率同样是派生视图(查询时相除即得)
- **不做分摊计算**:平台不把支付金额按用量比例分摊到日志或成员——分账是社交层问题;本表与日志的交汇只发生在**事实关联**(`subscription_id` 直连)与**参数展示**(订阅信息对使用者完全公开透明)
- 数据规模:年个位数到十位数行——无需索引设计
## 2. 字段清单
### 2.1 主键与支付字段(5 个)
| 列 | 类型 | 值来源 | 说明 |
|----|------|--------|------|
| `id` | bigserial PK | 自增 | |
| `kind` | text | 人工选择 | `subscription`(订阅)/ `topup`(充值) |
| `paid_at` | timestamptz | 人工填写 | 支付时间 |
| `paid_amount` | numeric | **人工必填** | **支付金额**(币种无关——数值本身,币种由使用者约定) |
| `remark` | text | 人工填写 | 备注 |
### 2.2 期间与订阅字段(4 个)
| 列 | 类型 | 值来源 | 说明 |
|----|------|--------|------|
| `period_start` | timestamptz? | **人工录入**(钱包页面) | 仅订阅:该笔覆盖的用量期间起点;左闭 |
| `period_end` | timestamptz? | **人工录入**(钱包页面) | 期间终点;左开;未结束可空 |
| `subscription_id` | bigint? | **人工录入**(钱包页面「订阅 #N」) | 上游订阅实例 ID;与日志 `subscription_id` 直连(事实关联,不推算) |
| `quota_granted` | bigint? | **人工录入**(钱包页面「总额度」/ 充值记录) | 本笔换得的额度——**单位钉死为原始 quota 整数**(如 $25 额度 = 12,500,000;见 3.6) |
## 3. 决策记录(含理由)
### 3.1 登记 = 手工抄录(来源只有两处)
支付记录全部由作者手工录入,来源仅两处:**支付凭证**(`kind` / `paid_at` / `paid_amount`)与**钱包页面**(订阅 ID / 期间 / 总额度)。订阅关键信息只有作者可见(没有免 auth 接口可查)——系统不做回填与推断,日志观测仅用于核对提示(见 §4);必填 / 可空的校验细节归技术稿。
### 3.2 只存事实,不存派生数
- `paid_amount` 与 `quota_granted` 是不可替代的事实;「金额 ↔ 额度」的比率是派生数——查询时相除即得,事后核对永远可用;只存比率会丢失核对依据
- **日志同样不加任何金额 / 比率列**(`usage_logs` 零分摊字段):把支付金额按用量分摊到日志行的任何计算都不做——分摊口径是社交层问题,账本上只有客观事实
- 关联维度(`billing_source` / `subscription_id`)已在日志侧提为独立列(见 `usage_logs表字段设计.md` 3.6),统计按事实关联
### 3.3 为什么额度也手工录入(不采用日志感知)
日志逐条自带 `subscription_total`(实测),但回填它需要「订阅 ID → 该 ID 日志 total」的关联逻辑;钱包页面已直接给出总额度——手工抄录一步到位。**系统对支付记录零回填、零推断**,观测仅用于核对(见 §4)。
### 3.4 币种无关(不预设人民币)
`paid_amount` 是纯数值。作者记账用什么货币是他的事,展示层的货币符号是界面约定——数据层与币种彻底解耦,更换支付渠道 / 币种时零 schema 变化。
### 3.5 命名与类型
- 表名 `payments`(支付记录):订阅与充值同构,`purchases`(购买)只覆盖前者,`payments` 是两者的上位词
- 金额列 `numeric`(金额不用浮点);时间列统一 `timestamptz`
- 期间左闭右开(`[period_start, period_end)`)——与全项目期间惯例一致
- 订阅实例 ID 与日志同名 `subscription_id`——同一体系、同一含义(直连即用此列)
### 3.6 `quota_granted` 的单位:原始 quota,不是美元
- **存真值,不存换算快照**:上游订阅套餐的额度本体是 quota 整数,「$25」只是界面显示形态(quota ÷ `quota_per_unit`,随 `quota_display_type` 而变)——本列存本体
- **域一致性**:日志的 `quota` 同为原始整数——`SUM(usage_logs.quota)` 与 `quota_granted` 同域直接可比,零换算;若存美元则每次比较都要过 ÷QPU,而 QPU 是时间线变量(`qpu_history`),凭空引入取值时刻问题
- **类型精确**:quota 恒为整数;美元额度可能有小数,`bigint` 装不下
- **录入体验归交互层**:钱包页面显示美元形态——管理面表单支持输入美元、按当时 QPU 换算落库(或展示两态),换算逻辑不进数据模型
- 美元形态随时可派生:`quota_granted ÷ QPU`(展示层)
- **与 qpu_history 无概念重复**:quota 是**量**,QPU 是**换算率**——记录量不等于记录单位定义(记「¥170」不涵盖「1 美元 = 6.8 人民币」)。真值域(quota)不携带任何换算,换算率只在一处(`qpu_history` 时间线),美元永远现算现用;反过来若直接存美元,每个值都是某次换算的快照、各自隐含一个换算时刻——那才是真正的冗余,且上游改 QPU 后与日志统计失去同域可比性
## 4. 写入时机与维护
| 时机 | 动作 |
|------|------|
| 人工登记(管理通道) | INSERT:录入支付信息(时间 / 金额)与订阅信息(ID / 期间 / 总额度,抄自钱包页面)→ 确认 |
| 系统观测(仅核对) | 日志观测到的订阅 ID / `subscription_total` 仅作核对提示(如「观测到 #N 未对应任何支付记录」——即「未关联」分组的健康信号),不参与回填 |
| 编辑 / 删除 | 数据为人工登记,改错即修 |
## 5. 展示层边界(界面设计的输入)
- **订阅与支付参数对使用者完全公开透明**(访问主体模型裁决):期间、额度、支付金额、订阅 ID——成员视图与管理面同源可见;不存在「管理面独占的金额信息」
- 「按订阅维度统计」(某笔订阅的消耗占比等)数据天然支持——按 `subscription_id` 直连聚合即可
- 成员视角的日志行携带所属订阅/充值信息的具体形态,交互设计期定(见 `docs/design/需求清单.md` R12)
## 6. 待定事项(关联后续环节)
| 事项 | 归属 |
|------|------|
| 核对提示(观测到的订阅 ID ↔ 已录入记录比对)的交互 | 交互设计(待立) |
| 充值(`topup`)的 `quota_granted` 抄录来源(充值记录页)核实 | 实现期真实数据核查 |