修复广告收益用户详情加载失败 #180

Merged
guke merged 1 commits from codex/ad-revenue-user-drawer-fix into main 2026-07-27 10:15:56 +08:00
Member

问题原因

  • 奖励统计接口用完整 User ORM 判断用户存在,滚动发布或表结构未同步时会因无关字段导致 500
  • 金币记录合并广告与签到数据后直接排序,PostgreSQL 中 aware/naive datetime 混排会抛异常

修复内容

  • 新增只投影 user.id 的用户存在性检查,保持不存在用户返回 404
  • 金币记录排序前统一转换为 aware UTC 排序键
  • 增加旧表结构投影与混合时区回归测试

验证结果

  • tests/test_admin_read.py:18 项全部通过
  • 线上只读数据库回归:近期 7 个活跃用户统计与金币明细全部正常返回;用户 #33 返回 1514 条记录
  • 语法/未定义引用检查通过
  • 全量测试 532 通过、9 失败;失败均在未修改的 origin/main 基线上复现,和本 PR 无关
## 问题原因 - 奖励统计接口用完整 User ORM 判断用户存在,滚动发布或表结构未同步时会因无关字段导致 500 - 金币记录合并广告与签到数据后直接排序,PostgreSQL 中 aware/naive datetime 混排会抛异常 ## 修复内容 - 新增只投影 user.id 的用户存在性检查,保持不存在用户返回 404 - 金币记录排序前统一转换为 aware UTC 排序键 - 增加旧表结构投影与混合时区回归测试 ## 验证结果 - tests/test_admin_read.py:18 项全部通过 - 线上只读数据库回归:近期 7 个活跃用户统计与金币明细全部正常返回;用户 #33 返回 1514 条记录 - 语法/未定义引用检查通过 - 全量测试 532 通过、9 失败;失败均在未修改的 origin/main 基线上复现,和本 PR 无关
linkeyu added 1 commit 2026-07-26 21:02:09 +08:00
用户奖励统计改为仅查询用户主键,避免完整用户模型依赖未同步字段;统一金币记录跨数据源的 UTC 排序键,修复 PostgreSQL 下 naive 与 aware 时间混排异常;补充旧表结构与混合时区回归测试。
Member

🤖 review-pr 深审结论

🟢 通过 — 两个独立修复,均正确、对症、有测试覆盖,风险低。

① 金币明细混合时区排序崩溃app/admin/repositories/queries.py
根因准确:线上 PostgreSQL 广告记录 created_at 为 aware UTC,签到记录经 _cn_wall_to_utc 转成 naive UTC,混排触发 can't compare offset-naive and offset-aware。修复用 _coin_record_sort_key_as_utc 统一成 aware UTC 再排序;因各来源入 rows 时都已是 UTC,_as_utc 把 naive 当 UTC → 绝对时刻正确 → 排序正确。

② 用户存在性检查避免展开完整 user 表routers/users.py + repositories/user.py
get_user_by_iddb.get(User) 加载完整行)在旧库缺 ORM 新列时查询失败;改为 user_existsselect(User.id) 只查主键),语义等价(存在→继续 / 不存在→404),不再依赖完整表结构。

测试:混排排序用例 + 「存在性检查不展开完整 user 表」断言,覆盖到位。

小提醒(非阻断)_as_utc(created_at) 假设 created_at 非空;若某来源返回 null 会 AttributeError。实际这些表应为 NOT NULL、非本 PR 引入,留意即可。

review-pr 自动深审 · 完整仓 worktree 上下文

## 🤖 review-pr 深审结论 🟢 **通过** — 两个独立修复,均正确、对症、有测试覆盖,风险低。 **① 金币明细混合时区排序崩溃**(`app/admin/repositories/queries.py`) 根因准确:线上 PostgreSQL 广告记录 `created_at` 为 aware UTC,签到记录经 `_cn_wall_to_utc` 转成 naive UTC,混排触发 `can't compare offset-naive and offset-aware`。修复用 `_coin_record_sort_key` → `_as_utc` 统一成 aware UTC 再排序;因各来源入 rows 时都已是 UTC,`_as_utc` 把 naive 当 UTC → 绝对时刻正确 → 排序正确。 **② 用户存在性检查避免展开完整 user 表**(`routers/users.py` + `repositories/user.py`) 原 `get_user_by_id`(`db.get(User)` 加载完整行)在旧库缺 ORM 新列时查询失败;改为 `user_exists`(`select(User.id)` 只查主键),语义等价(存在→继续 / 不存在→404),不再依赖完整表结构。 **测试**:混排排序用例 + 「存在性检查不展开完整 user 表」断言,覆盖到位。 **小提醒(非阻断)**:`_as_utc(created_at)` 假设 `created_at` 非空;若某来源返回 null 会 `AttributeError`。实际这些表应为 NOT NULL、非本 PR 引入,留意即可。 *review-pr 自动深审 · 完整仓 worktree 上下文*
guke merged commit 775a503d6f into main 2026-07-27 10:15:56 +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#180