修复:签到膨胀金币归入看视频分类 (#169)

## 修改内容

- 将历史 `signin_boost` 金币从“常规任务金币”分类移出。
- 将 `signin_boost` 与 `reward_video/ad_reward` 一起计入“看视频金币”。
- 保留独立的 `signin_boost_coin_total` 历史审计字段。
- 增加不重不漏回归测试,确认分类调整前后本期发放总额保持不变。

## 本地验证

- `tests/test_admin_read.py`:16 项通过。
- Ruff 与 `git diff --check`:通过。
- 全量后端测试:505 项通过;8 项为 `main` 现有无关失败。

---------

Co-authored-by: unknown <798648091@qq.com>
Reviewed-on: #169
Co-authored-by: linkeyu <linkeyu@wonderable.ai>
Co-committed-by: linkeyu <linkeyu@wonderable.ai>
This commit was merged in pull request #169.
This commit is contained in:
2026-07-24 11:16:38 +08:00
committed by guke
parent 66527f6cdc
commit 71aef455f4
2 changed files with 52 additions and 5 deletions
+3 -4
View File
@@ -30,18 +30,17 @@ from app.models.user import User
from app.models.wallet import CoinTransaction, WithdrawOrder
_BEIJING = timezone(timedelta(hours=8))
REWARD_VIDEO_BIZ_TYPES = ("reward_video", "ad_reward")
REWARD_VIDEO_BIZ_TYPES = ("reward_video", "ad_reward", "signin_boost")
# 领券/比价奖励金币的真实来源是信息流广告发奖(ad_feed_reward_record,按 feed_scene 分场景);
# coin_transaction 里只有扁平的 feed_ad_reward、biz_type 不分 coupon/comparison,故这俩桶历史从未
# 被写入,仅留作未来兜底,实际金额在下方按 feed_scene 汇总 ad_feed_reward_record 得出。reward_video/
# ad_reward 是激励视频,单独成桶、不再混进领券奖励(历史误并会把激励视频金币双计进领券)
# 被写入,仅留作未来兜底,实际金额在下方按 feed_scene 汇总 ad_feed_reward_record 得出。
# reward_video/ad_reward 及历史 signin_boost 均归看视频桶,不再混进领券奖励或常规任务
COUPON_REWARD_BIZ_TYPES = ("coupon", "coupon_reward")
COMPARISON_REWARD_BIZ_TYPES = ("comparison", "compare_reward", "comparison_reward")
# 常规任务必须按明确来源相加;不能从全部正向流水反减排除项,否则新增广告/运营
# biz_type 时会在排除清单更新前自动混入该桶。task_ 前缀在查询处单独覆盖现有及未来任务。
REGULAR_TASK_EXACT_BIZ_TYPES = (
"signin",
"signin_boost",
"price_report_reward",
"feedback_reward",
)
+49 -1
View File
@@ -468,13 +468,13 @@ def test_period_regular_task_coin_uses_explicit_allowlist(
d = "2021-06-18"
included = {
"signin": 100,
"signin_boost": 200,
"task_enable_notification": 300,
"task_other": 400,
"price_report_reward": 500,
"feedback_reward": 600,
}
excluded = {
"signin_boost": 200,
"feed_ad_reward_coupon": 700,
"feed_ad_reward_comparison": 800,
"feed_ad_reward": 900,
@@ -514,3 +514,51 @@ def test_period_regular_task_coin_uses_explicit_allowlist(
coins = response.json()["period"]["coins"]
assert coins["regular_task_coin_total"] == sum(included.values())
assert coins["task_coin_total"] == 700
assert coins["reward_video_coin_total"] == 1200
def test_period_signin_boost_moves_to_reward_video_without_double_count(
admin_client: TestClient, admin_token: str
) -> None:
"""历史签到膨胀归看视频桶,不再进常规任务;本期发放总额不变且不重复计算。"""
from datetime import datetime
from app.models.wallet import CoinTransaction
d = "2021-06-19"
rows = [
("signin_boost", 200),
("reward_video", 100),
("signin", 50),
]
db = SessionLocal()
try:
uid = user_repo.upsert_user_for_login(
db, phone="13800008805", register_channel="sms"
).id
balance = 0
for index, (biz_type, amount) in enumerate(rows, start=1):
balance += amount
db.add(CoinTransaction(
user_id=uid,
amount=amount,
balance_after=balance,
biz_type=biz_type,
ref_id=f"signin-boost-route-{index}",
created_at=datetime(2021, 6, 19, 12, 0, index),
))
db.commit()
finally:
db.close()
response = admin_client.get(
"/admin/api/stats/overview",
params={"date_from": d, "date_to": d},
headers=_auth(admin_token),
)
assert response.status_code == 200, response.text
coins = response.json()["period"]["coins"]
assert coins["granted_total"] == 350
assert coins["reward_video_coin_total"] == 300
assert coins["regular_task_coin_total"] == 50
assert coins["signin_boost_coin_total"] == 200