docs(database): 补全 19 表文档 + 新增 OVERVIEW 总览
- 重写 15 张已有表文档:每张补「用在 App 哪/增删改查时机/字段取值/join key 指向」 - 新建 4 张缺失表文档:wechat_transfer_authorization / ad_watch_log / price_report / app_config - 新增 OVERVIEW.md:功能↔表映射 + 写入路径 + 表间关系(含语义 join key)+ ER + 资金模型 - README 索引补齐到 19 表 + 置顶 OVERVIEW + 通用约定补全 - 纠正过时:withdraw_order(reviewing/rejected/user_name)、savings_record(/order/report 真实写入)、coin_transaction(biz_type) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,28 +1,35 @@
|
||||
# ad_reward_record — 看激励视频发奖记录(S2S 回调)
|
||||
|
||||
> 模型 `app/models/ad_reward.py` | 关联接口 [ad-pangle-callback](../api/ad-pangle-callback.md) / [ad-reward-status](../api/ad-reward-status.md) | [← 表索引](./README.md)
|
||||
> 模型 `app/models/ad_reward.py` · 仓库 `app/repositories/ad_reward.py` · 接口 [ad-pangle-callback](../api/ad-pangle-callback.md) / [ad-reward-status](../api/ad-reward-status.md) / [ad-test-grant](../api/ad-test-grant.md) · [← 索引](./README.md) · [总览](./OVERVIEW.md)
|
||||
|
||||
每条 = 穿山甲一次发奖回调。`trans_id` 唯一做幂等键(穿山甲会重试,同号只发一次)。`reward_date`(北京时间日期串)给"每日上限"计数用,按日期串等值查。
|
||||
每条 = 穿山甲一次**服务端发奖回调**(用户看完激励视频)。是看广告三条数据流之一(**发奖**;另两条:`ad_watch_log` 时长、`ad_ecpm_record` 收益,三者无公共键)。`trans_id` 唯一做幂等键(穿山甲会重试,同号只发一次)。`reward_date`(北京时间日期串)给"每日上限"计数用。
|
||||
|
||||
## 用在哪 / 增删改查
|
||||
- **C(插入)**:`POST /ad/pangle-callback`(穿山甲 S2S,经 SHA256 验签;`grant_ad_reward`)或 `POST /ad/test-grant`(本地联调)。三道闸:① 验签不过 → API 层 403,不进库;② `trans_id` 已存在 → 原样返回不重复发;③ **当日发奖次数(`DAILY_AD_REWARD_LIMIT`)或观看总时长(`DAILY_AD_WATCH_SECONDS_LIMIT`=50min,查 `ad_watch_log`)任一到顶** → 记一行 `status='capped'`、`coin=0`、不发币。否则 `granted` + `grant_coins(biz_type='ad_reward', ref_id=trans_id)` 加币,同事务。
|
||||
- **U / D**:无。
|
||||
- **R**:`GET /ad/reward-status`(看广告页:今日已发次数/上限、单次金币、本轮已看/冷却结束、今日已看时长/上限);审计/对账整表回溯。
|
||||
|
||||
## 字段
|
||||
| 列 | 类型 | 约束 / 默认 | 说明 |
|
||||
| 列 | 类型 | 约束 / 默认 | 说明(取值 / join) |
|
||||
|---|---|---|---|
|
||||
| `id` | Integer | PK, autoincrement | |
|
||||
| `trans_id` | String(64) | UNIQUE, index, NOT NULL | 穿山甲交易号(幂等键) |
|
||||
| `user_id` | Integer | FK→user.id, index, NOT NULL | 归属用户(回调 media_extra 带回) |
|
||||
| `coin` | Integer | NOT NULL, default 0 | 实发金币(capped 时为 0) |
|
||||
| `status` | String(16) | NOT NULL, default `granted` | `granted`(已发)/ `capped`(当日超限未发) |
|
||||
| `reward_date` | String(10) | index, NOT NULL | 北京时间日期串 `YYYY-MM-DD`,按它统计当日次数 |
|
||||
| `trans_id` | String(64) | UNIQUE, index, NOT NULL | 穿山甲交易号(幂等键)。**被 `coin_transaction.ref_id` 引用**(biz_type=ad_reward) |
|
||||
| `user_id` | Integer | FK→user.id, index, NOT NULL | 归属用户(回调 media_extra 带回;不存在抛 UnknownUserError) |
|
||||
| `coin` | Integer | NOT NULL, default 0 | 实发金币;`capped` 时为 0 |
|
||||
| `status` | String(16) | NOT NULL, default `granted` | 取值:`granted`(已发)/ `capped`(当日次数或时长超限,记录但不发) |
|
||||
| `reward_date` | String(10) | index, NOT NULL | 北京时间日期串 `YYYY-MM-DD`,按它等值统计当日发奖次数 |
|
||||
| `reward_name` | String(64) | nullable | 穿山甲上报奖励名(参考,不作发奖依据) |
|
||||
| `raw` | String(1024) | nullable | 回调原始参数(审计排查) |
|
||||
| `created_at` | DateTime(tz) | server_default now(), index | 时间 |
|
||||
|
||||
## 关系 / Join Key
|
||||
- `user_id` → `user.id`(多对一)。
|
||||
- `trans_id` ← 被 `coin_transaction.ref_id` 引用(`granted` 那条发币流水);`capped` 行不发币、无对应流水。
|
||||
- 与 `ad_watch_log` / `ad_ecpm_record` **无公共键**,仅在发奖时读 `ad_watch_log` 当日时长做闸。
|
||||
|
||||
## 索引与约束
|
||||
- PK: `id`;UNIQUE + index: `trans_id`;index: `user_id`、`reward_date`、`created_at`
|
||||
- PK `id`;UNIQUE+index `trans_id`;index `user_id`、`reward_date`、`created_at`。
|
||||
|
||||
## 关系
|
||||
- `user_id` → `user.id`(多对一)
|
||||
|
||||
## 说明
|
||||
- 三道闸:验签不过 403 → `trans_id` 唯一幂等(并发 catch IntegrityError)→ 当日次数 ≥ `DAILY_AD_REWARD_LIMIT` 记 `capped` 不发币。
|
||||
- 发币复用 `grant_coins(biz_type='ad_reward', ref_id=trans_id)`。
|
||||
## 注意
|
||||
- 实发金币以穿山甲回调 `reward_amount` 为准(`resolve_ad_reward_coin` 解析,缺/坏回退默认、超上限夹紧),单次金币/每日上限/单次上限均从 `app_config` 读(运营后台可改)。
|
||||
- 并发同 `trans_id` 撞唯一约束 → catch IntegrityError 回滚返回已存在那条(幂等兜底)。
|
||||
|
||||
Reference in New Issue
Block a user