diff --git a/app/admin/repositories/stats.py b/app/admin/repositories/stats.py index e82f5b6..26e13df 100644 --- a/app/admin/repositories/stats.py +++ b/app/admin/repositories/stats.py @@ -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", ) diff --git a/tests/test_admin_read.py b/tests/test_admin_read.py index d2b6526..a01ca96 100644 --- a/tests/test_admin_read.py +++ b/tests/test_admin_read.py @@ -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