修复:统一用户Draw信息流eCPM统计口径 #190

Merged
guke merged 2 commits from codex/user-draw-ecpm-scope into main 2026-07-28 17:58:24 +08:00
Member

问题

业务收益详情的平均 Draw eCPM 仅平均成功发奖记录,会排除未发奖的真实展示,导致数值系统性偏高,且与广告收益页口径不一致。

修复

  • feed_avg_ecpm 改为从 ad_ecpm_record 的全部 draw/feed 实际展示计算
  • 成功发奖、未发奖展示均纳入,每次展示等权
  • 日期、正式/测试环境、业务代码位、领券/比价场景支持与广告收益页对齐
  • 奖励份数仍基于成功发奖表,不混用展示数据源
  • 复用广告收益报表的业务代码位集合

线上数据复算

2026-07-25、正式业务、用户 #33:

  • 旧口径(只看成功发奖):29.9117 元/千次
  • 新口径(333 次真实展示):19.9926 元/千次
  • 新值与广告收益报表一致

验证

  • 新增成功/未发奖、场景、环境、业务代码位回归用例
  • tests/test_admin_read.py + tests/test_admin_ad_revenue_scope.py:29 项全通过
  • Ruff 改动文件检查通过

上线顺序

本 PR 需先于管理后台配套 PR 上线。

## 问题 业务收益详情的平均 Draw eCPM 仅平均成功发奖记录,会排除未发奖的真实展示,导致数值系统性偏高,且与广告收益页口径不一致。 ## 修复 - `feed_avg_ecpm` 改为从 `ad_ecpm_record` 的全部 `draw/feed` 实际展示计算 - 成功发奖、未发奖展示均纳入,每次展示等权 - 日期、正式/测试环境、业务代码位、领券/比价场景支持与广告收益页对齐 - 奖励份数仍基于成功发奖表,不混用展示数据源 - 复用广告收益报表的业务代码位集合 ## 线上数据复算 2026-07-25、正式业务、用户 #33: - 旧口径(只看成功发奖):`29.9117 元/千次` - 新口径(333 次真实展示):`19.9926 元/千次` - 新值与广告收益报表一致 ## 验证 - 新增成功/未发奖、场景、环境、业务代码位回归用例 - `tests/test_admin_read.py` + `tests/test_admin_ad_revenue_scope.py`:29 项全通过 - Ruff 改动文件检查通过 ## 上线顺序 本 PR 需先于管理后台配套 PR 上线。
linkeyu added 1 commit 2026-07-28 13:57:23 +08:00
Member

🤖 review-pr 深审结论

🟡 可合并,一处跨消费方影响待作者确认 — 逻辑正确、测试实跑通过;但改的是共享端点,withdraws 抽屉的 feed eCPM 也会随之变。置信度 0.85(隔离 worktree 实跑 PG 24 passed + 列校验 + 与 category_stats 静态核对)。

验证(隔离 worktree 实跑)

  • pytest tests/test_admin_read.py24 passed,跑在 PostgreSQL;新增 test_..._draw_ecpm_uses_all_filtered_impressions 断言 feed_avg_ecpm==2000(全展示均值)而非 9000(发奖记录),并覆盖 scene / env / 非业务代码位的排除。
  • ORM 列均存在:AdRewardRecord.app_env/our_code_idAdFeedRewardRecord.app_env/feed_scene/our_code_idAdEcpmRecord.* → 无 AttributeError 风险。
  • _business_code_ids → business_code_ids 重命名全仓无残留旧引用。
  • parity 核对category_stats(ad_revenue.py:445-464)按展示加权、非法原值 parse_ecpm_fen 记 0、过滤空值;本 PR feed_impressions 简单均值同口径(每条 ad_ecpm = 1 展示)→ 一致。(此前担心的 line 276 是逐组明细行、非分类汇总,不影响。)
  • main 试合并:干净(合入了刚落地的 #189 fail_reason,文件不相交)。

med — 待确认(不阻塞)

  • user_reward_stats共享端点:withdraws 页抽屉(UserRewardPanel statsVariant='withdraw',UserRewardPanel.tsx:245)同样展示 feed_avg_ecpm,且不传 scope 参数 → 其口径也从「granted 均值」变成「全展示均值(未 scope)」。请确认这个附带变更是有意的。

low

  • ad-抽屉下 reward_video 也被 business+env 限定(符合「继承筛选口径」意图);但历史 our_code_id=NULL 的记录在 business scope 下会被排除(与报表口径一致)。
  • feed_impressions 用简单均值 vs category_stats 展示加权——每条 ad_ecpm=1 展示时等价;若将来单条带多展示会漂移。

正面:测试口径扎实、重命名干净、与报表 parity 明确。
配套:与 admin-web #94 配对,建议同发或 server 先(新参数可选有默认,双向不崩)。

## 🤖 review-pr 深审结论 🟡 **可合并,一处跨消费方影响待作者确认** — 逻辑正确、测试实跑通过;但改的是共享端点,withdraws 抽屉的 feed eCPM 也会随之变。置信度 **0.85**(隔离 worktree 实跑 PG 24 passed + 列校验 + 与 category_stats 静态核对)。 **验证(隔离 worktree 实跑)** - `pytest tests/test_admin_read.py` → **24 passed**,跑在 PostgreSQL;新增 `test_..._draw_ecpm_uses_all_filtered_impressions` 断言 `feed_avg_ecpm==2000`(全展示均值)而非 9000(发奖记录),并覆盖 scene / env / 非业务代码位的排除。 - ORM 列均存在:`AdRewardRecord.app_env/our_code_id`、`AdFeedRewardRecord.app_env/feed_scene/our_code_id`、`AdEcpmRecord.*` → 无 AttributeError 风险。 - `_business_code_ids → business_code_ids` 重命名全仓无残留旧引用。 - **parity 核对**:`category_stats`(ad_revenue.py:445-464)按展示加权、非法原值 `parse_ecpm_fen` 记 0、**不**过滤空值;本 PR `feed_impressions` 简单均值同口径(每条 ad_ecpm = 1 展示)→ 一致。(此前担心的 line 276 是逐组明细行、非分类汇总,不影响。) - 与 `main` 试合并:干净(合入了刚落地的 #189 fail_reason,文件不相交)。 **med — 待确认(不阻塞)** - `user_reward_stats` 是**共享端点**:withdraws 页抽屉(`UserRewardPanel` statsVariant='withdraw',UserRewardPanel.tsx:245)同样展示 `feed_avg_ecpm`,且不传 scope 参数 → 其口径也从「granted 均值」变成「全展示均值(未 scope)」。请确认这个附带变更是有意的。 **low** - ad-抽屉下 reward_video 也被 business+env 限定(符合「继承筛选口径」意图);但历史 `our_code_id=NULL` 的记录在 business scope 下会被排除(与报表口径一致)。 - `feed_impressions` 用简单均值 vs `category_stats` 展示加权——每条 ad_ecpm=1 展示时等价;若将来单条带多展示会漂移。 **正面**:测试口径扎实、重命名干净、与报表 parity 明确。 **配套**:与 admin-web #94 配对,建议同发或 server 先(新参数可选有默认,双向不崩)。
Member

🤖 review-pr 深审结论

🟢 逻辑正确,已实跑验证(后端 pytest 2 项通过 + 前端 #94 tsc 通过)。#94 为同一需求前后端,eCPM 口径向报表对齐的方向正确。置信度 0.9。

需确认(med)

  • 🟡 app/admin/repositories/queries.pyuser_reward_stats提现详情广告收益详情两页共用的后端。本 PR 把 feed_avg_ecpm 从「granted 发奖记录均值」改成「全部 draw/feed 展示记录均值」后,提现详情页也被动改口径:该页(WithdrawReviewPageUserRewardPanel 默认 withdraw 变体,渲染 feed_avg_ecpm)调用同一接口但不传 revenue_scope/app_env/feed_scene,默认 revenue_scope=all,于是它显示的信息流 eCPM 静默变成「全量展示均值」,而 withdraw 变体的说明文案没同步更新。请确认是否有意;若是,建议同步 withdraw 变体的 eCPM 文案。

说明(low)

  • 🟢 feed_count(granted 份数)与 feed_avg_ecpm(全部展示)现在来自不同记录集——广告详情页有新文案解释,提现页没有。

正面

  • AdEcpmRecord 各列齐全;ad_type IN (draw,feed)ad_revenue.category_stats(报表 draw 口径)完全一致,对齐扎实;business_code_ids 提为公有函数复用,避免两页随配置再次漂移。
## 🤖 review-pr 深审结论 **🟢 逻辑正确,已实跑验证(后端 pytest 2 项通过 + 前端 #94 `tsc` 通过)。** 与 #94 为同一需求前后端,eCPM 口径向报表对齐的方向正确。置信度 0.9。 ### 需确认(med) - 🟡 `app/admin/repositories/queries.py` 的 `user_reward_stats` 是**提现详情**与**广告收益详情**两页共用的后端。本 PR 把 `feed_avg_ecpm` 从「granted 发奖记录均值」改成「全部 draw/feed 展示记录均值」后,**提现详情页也被动改口径**:该页(`WithdrawReviewPage` → `UserRewardPanel` 默认 withdraw 变体,渲染 `feed_avg_ecpm`)调用同一接口但**不传** `revenue_scope/app_env/feed_scene`,默认 `revenue_scope=all`,于是它显示的信息流 eCPM 静默变成「全量展示均值」,而 withdraw 变体的说明文案没同步更新。请确认是否有意;若是,建议同步 withdraw 变体的 eCPM 文案。 ### 说明(low) - 🟢 `feed_count`(granted 份数)与 `feed_avg_ecpm`(全部展示)现在来自不同记录集——广告详情页有新文案解释,提现页没有。 ### 正面 - `AdEcpmRecord` 各列齐全;`ad_type IN (draw,feed)` 与 `ad_revenue.category_stats`(报表 draw 口径)完全一致,对齐扎实;`business_code_ids` 提为公有函数复用,避免两页随配置再次漂移。
guke added 1 commit 2026-07-28 17:58:17 +08:00
guke merged commit 90c6fe599a into main 2026-07-28 17:58:24 +08:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: WonderableAI/shaguabijia-app-server#190