feat(invite): 邀请奖励金账户(与金币隔离) + 比价发奖 + 奖励金提现
- 新增邀请奖励金独立账本: coin_account 加余额列 + invite_cash_transaction 流水表, 与金币现金物理隔离 - bind 改 v2: 绑定只发被邀请人新人金币; 邀请人改在好友首次成功比价时发 2 元奖励金(幂等只发一次) - 提现链路按 source 分流: 扣款/退款/对账/分页各认账户, 两本账不串 - /invite/me 返回奖励金余额/累计提现/7天倒计时 - 新增 migration(建表加列) + 比价发奖与提现隔离测试
This commit is contained in:
+10
-10
@@ -11,7 +11,6 @@ from sqlalchemy import select
|
||||
from app.core.rewards import (
|
||||
INVITE_FP_WINDOW_DAYS,
|
||||
INVITE_INVITEE_COINS,
|
||||
INVITE_INVITER_COINS,
|
||||
INVITE_NEW_USER_WINDOW_HOURS,
|
||||
)
|
||||
from app.db.session import SessionLocal
|
||||
@@ -56,8 +55,8 @@ def test_invite_me_returns_stable_code(client) -> None:
|
||||
assert _my_code(client, token) == body["invite_code"]
|
||||
|
||||
|
||||
def test_bind_flow_both_get_coins(client) -> None:
|
||||
"""B 用 A 的码绑定 → 双方各得 1 万金币;A 战绩 +1。"""
|
||||
def test_bind_flow_invitee_gets_coins(client) -> None:
|
||||
"""v2:B 用 A 的码绑定 → 只有被邀请人 B 得新人金币;邀请人 A 绑定时不发(改比价发现金)。"""
|
||||
a = _login(client, "13800002002")
|
||||
b = _login(client, "13800002003")
|
||||
a_code = _my_code(client, a)
|
||||
@@ -71,14 +70,14 @@ def test_bind_flow_both_get_coins(client) -> None:
|
||||
assert res["status"] == "success"
|
||||
assert res["coins_awarded"] == INVITE_INVITEE_COINS
|
||||
|
||||
# 双方金币到账
|
||||
# 被邀请人金币到账;邀请人绑定时不发金币(v2 改"好友比价发 2 元邀请奖励金")
|
||||
assert _coin_balance(client, b) == INVITE_INVITEE_COINS
|
||||
assert _coin_balance(client, a) == INVITE_INVITER_COINS
|
||||
assert _coin_balance(client, a) == 0
|
||||
|
||||
# A 的战绩:已邀 1 人,累计获得 = 邀请人那份
|
||||
# A 的战绩:已邀 1 人;金币口径收益为 0(邀请人收益改走邀请奖励金,见 try_reward_on_compare)
|
||||
r = client.get("/api/v1/invite/me", headers=_auth(a))
|
||||
assert r.json()["invited_count"] == 1
|
||||
assert r.json()["coins_earned"] == INVITE_INVITER_COINS
|
||||
assert r.json()["coins_earned"] == 0
|
||||
|
||||
|
||||
def test_bind_idempotent_no_double_reward(client) -> None:
|
||||
@@ -217,8 +216,8 @@ def test_bind_by_fingerprint_success(client) -> None:
|
||||
)
|
||||
assert r2.status_code == 200, r2.text
|
||||
assert r2.json()["status"] == "success"
|
||||
# 双方各发金币
|
||||
assert _coin_balance(client, a) == INVITE_INVITER_COINS
|
||||
# v2:只被邀请人发新人金币;邀请人绑定不发(改比价发现金)
|
||||
assert _coin_balance(client, a) == 0
|
||||
assert _coin_balance(client, b) == INVITE_INVITEE_COINS
|
||||
|
||||
|
||||
@@ -322,7 +321,8 @@ def test_invitees_basic(client) -> None:
|
||||
names = {it["display_name"] for it in body["items"]}
|
||||
assert names == expected_names
|
||||
assert all(it["avatar_url"] is None for it in body["items"])
|
||||
assert all(it["coins"] == INVITE_INVITER_COINS for it in body["items"])
|
||||
# v2:绑定时邀请人那份为 0(收益改"好友比价才发奖"),故每条 coins 字段=0
|
||||
assert all(it["coins"] == 0 for it in body["items"])
|
||||
|
||||
|
||||
def test_invitees_order_desc(client) -> None:
|
||||
|
||||
Reference in New Issue
Block a user