feat(invite): 好友列表已比价状态(is_compared) + DEV 造虚拟好友接口; fix(deploy): 每日兑换定时器锁北京时区

邀请:
- get_invitees 返回增加 is_compared 字段(= compare_reward_granted),
  客户端据此区分好友列表"去提醒/邀请成功"、在途列表只取未比价、算在途好友数与收益。
- 新增 POST/DELETE /invite/seed-fake 开发接口(仅非生产, is_prod 挡):造未比价+已比价虚拟好友,
  已比价的走真实入账发 2 元邀请奖励金, 便于真机联调在途/好友列表 UI; 清理原路退回不留脏账。

兑换时区:
- daily-exchange.service/.timer 锁定 Asia/Shanghai, 避免按服务器本地时区在错误时刻触发每日兑换。
- 新增 test_daily_exchange_timezone 覆盖同一北京日内幂等。

测试: 邀请 + 兑换时区相关用例全过(28 passed)。
(仓库预存的 3 个 proxy 转发测试失败与本改动无关, 已在干净 HEAD 上复现确认。)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
no_gen_mu
2026-07-01 22:24:40 +08:00
parent 357b2312af
commit 5cdde8f6c6
9 changed files with 239 additions and 4 deletions
+25
View File
@@ -122,6 +122,31 @@ def my_invitees(
)
@router.post("/seed-fake", summary="[DEV] 给自己塞虚拟好友(测在途/好友列表 UI,仅非生产)")
def seed_fake_invitees(
user: CurrentUser, db: DbSession, pending: int = 3, compared: int = 2
) -> dict:
"""造 pending 个未比价 + compared 个已比价的虚拟好友。生产环境(is_prod)直接 404。
未比价 → 上"在途列表 / 好友列表去提醒";已比价 → 好友列表"邀请成功"、并发真实邀请奖励金
(可提现余额/累计提现也有数)。清理见 DELETE /seed-fake。
"""
if settings.is_prod:
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="Not Found")
n = invite_repo.seed_fake_invitees(db, user.id, pending=max(0, pending), compared=max(0, compared))
return {"status": "ok", "created": n, "pending": pending, "compared": compared}
@router.delete("/seed-fake", summary="[DEV] 清掉自己的虚拟好友(仅非生产)")
def clear_fake_invitees(user: CurrentUser, db: DbSession) -> dict:
if settings.is_prod:
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="Not Found")
n = invite_repo.clear_fake_invitees(db, user.id)
return {"status": "ok", "removed": n}
@router.post(
"/landing-track",
response_model=LandingTrackOut,