feat(ad): 记录不发金币的原因(closed_early / too_short)

让广告收益报表能呈现「有展示、没发金币」的原因:
- grant_feed_reward 改整场结算:aborted→closed_early、整场总时长<10s→too_short(均 coin=0)
- 新增 record_reward_noshow + POST /api/v1/ad/reward-noshow(激励视频提前关留痕;
  同 ad_session_id 已 granted 则跳过,防与 S2S 发奖重复)
- feed-reward 加 aborted 入参
- 文档:feed-reward / 两张表 status 取值、新增 ad-reward-noshow、README 索引
- alembic: 合并 ad_revenue_report_cols 与 store_mapping_tb_dl_invalid 双 head(空迁移)

报表复算无需改(非 granted 状态走 else 分支 expected=0 自动归类)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
OuYingJun1024
2026-06-15 22:41:41 +08:00
parent bebd694fb5
commit 3ac58c1670
10 changed files with 245 additions and 23 deletions
+3 -3
View File
@@ -11,15 +11,15 @@
| `ad_session_id` | String(64) | index, nullable | 客户端生成的一次信息流广告会话 id |
| `user_id` | Integer | FK → `user.id`, index, NOT NULL | 用户 |
| `reward_date` | String(10) | index, NOT NULL | 北京时间日期 `YYYY-MM-DD` |
| `duration_seconds` | Integer | NOT NULL | 实际展示/播放秒数 |
| `duration_seconds` | Integer | NOT NULL | 整场比价累计观看秒数(轮播各条相加) |
| `unit_count` | Integer | NOT NULL | `duration_seconds // 10` 得到的奖励份数 |
| `ecpm_raw` | String(32) | NOT NULL | 客户端上报 eCPM 原始值 |
| `adn` | String(32) | nullable | 实际投放 ADN(聚合后实际填充子渠道) |
| `slot_id` | String(64) | nullable | 实际展示代码位(底层 mediation rit) |
| `app_env` | String(16) | nullable | 来源应用 `prod`(傻瓜比价)/`test`(测试),客户端 feed-reward 上报;旧数据 NULL。广告收益报表金币侧按它聚合 |
| `our_code_id` | String(64) | nullable | 我们配置的代码位 104xxx,客户端上报;旧数据 NULL |
| `coin` | Integer | NOT NULL | 实发金币,`capped` 时为 0 |
| `status` | String(16) | NOT NULL | `granted` / `capped` |
| `coin` | Integer | NOT NULL | 实发金币,`granted` 时为 0 |
| `status` | String(16) | NOT NULL | `granted`(已发) / `capped`(当日次数超限) / `too_short`(整场总时长<10s 凑不满一份) / `closed_early`(用户中途 ✕ 关闭,全程未看完) |
| `created_at` | DateTime | index, NOT NULL | 创建时间 |
## 约束