feat(wallet): 流水 remark 语义化 + 比价里程碑暂不发金币

- 签到发奖 remark='每日签到 第N天';看视频发奖 remark='看视频奖励金币'(原'看广告奖励')

- 比价战绩里程碑领取暂不真发金币(产品定,后续删该功能):仍记领取/标记已领,但不调 grant_coins、余额不变、coin_awarded 恒 0

- 同步 test_compare_milestone(领取后余额不变/coin_awarded==0) + docs/api/compare-milestone-claim

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
OuYingJun1024
2026-06-02 14:23:48 +08:00
parent 9521cd96ce
commit 78cd4c2696
5 changed files with 21 additions and 20 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ def grant_ad_reward(
# 发金币 + 记一笔,同事务
crud_wallet.grant_coins(
db, user_id, coin,
biz_type="ad_reward", ref_id=trans_id, remark="广告奖励",
biz_type="ad_reward", ref_id=trans_id, remark="视频奖励金币",
)
rec = AdRewardRecord(
trans_id=trans_id, user_id=user_id, coin=coin, status="granted",
+5 -6
View File
@@ -103,14 +103,13 @@ def claim(db: Session, user_id: int, milestone: int) -> tuple[int, int]:
if crud_compare.count_success(db, user_id) < milestone:
raise MilestoneLockedError
coin = record_milestone_reward(milestone)
# ⚠️ 比价战绩里程碑暂不真发金币(产品定,后续整体删除该功能):仍记一条领取(去重/标记已领),
# 但不调 grant_coins、不写 coin_transaction,余额不变,返回发放 0 金币 + 当前余额。
db.add(
ComparisonMilestoneClaim(
user_id=user_id, milestone=milestone, coin_awarded=coin
user_id=user_id, milestone=milestone, coin_awarded=0
)
)
acc, _ = crud_wallet.grant_coins(
db, user_id, coin, biz_type="compare_milestone", ref_id=str(milestone)
)
acc = crud_wallet.get_or_create_account(db, user_id, commit=False)
db.commit()
return coin, acc.coin_balance
return 0, acc.coin_balance
+2 -1
View File
@@ -119,7 +119,8 @@ def do_signin(db: Session, user_id: int) -> tuple[SigninRecord, int]:
)
db.add(record)
acc, _ = crud_wallet.grant_coins(
db, user_id, coin, biz_type="signin", ref_id=today.isoformat()
db, user_id, coin, biz_type="signin", ref_id=today.isoformat(),
remark=f"每日签到 第{cycle_day}",
)
db.commit()
db.refresh(record)
+9 -8
View File
@@ -2,9 +2,10 @@
> 所属:比价记录组(前缀 `/api/v1/compare` | 鉴权:Bearer | [← 返回 API 索引](./README.md)
领取某一档(第 `milestone` 次)的金币奖励,真实入账金币钱包。领取记录
`comparison_milestone_claim`((user_id, milestone) 唯一)+ `grant_coins` 同一事务原子提交,
**每档只能领一次**。进度口径见 [milestones 进度接口](./compare-milestones.md)。
领取某一档(第 `milestone` 次)。⚠️ **当前不真发金币**(产品定,后续整体删除该功能):仍
`comparison_milestone_claim`((user_id, milestone) 唯一)标记该档已领、**每档只能领一次**,但不调
`grant_coins`、不写 `coin_transaction`,余额不变,`coin_awarded` 恒为 0。进度口径见
[milestones 进度接口](./compare-milestones.md)。
## 入参
- 路径参数 `milestone`(int):档位序号,1..6(= `RECORD_MILESTONES` 长度)。
@@ -15,11 +16,11 @@
| 字段 | 类型 | 说明 |
|---|---|---|
| `milestone` | int | 本次领取的档位序号 |
| `coin_awarded` | int | 本次发放金币 |
| `coin_balance` | int | 领奖后金币余额 |
| `coin_awarded` | int | 本次发放金币(当前恒为 `0`,暂不真发) |
| `coin_balance` | int | 领奖后金币余额(当前不变) |
```json
{ "milestone": 1, "coin_awarded": 120, "coin_balance": 29087 }
{ "milestone": 1, "coin_awarded": 0, "coin_balance": 29087 }
```
## 错误
@@ -29,5 +30,5 @@
- `409` 该档已领过(`milestone already claimed`)
## 说明
- 领取金币,客户端刷新钱包余额([`GET /api/v1/wallet/account`](./wallet-account.md))与本档状态
- 幂等:重复领同一档返回 409 且**不会重复发金币**(唯一约束 + 领取前查重)。
- 当前不发金币,客户端领取后只需把本档状态刷成 claimed 即可;若后续恢复发奖,再按 `coin_awarded` 刷新钱包余额([`GET /api/v1/wallet/account`](./wallet-account.md))。
- 幂等:重复领同一档返回 409(唯一约束 + 领取前查重)。
+4 -4
View File
@@ -82,8 +82,8 @@ def test_unlock_progresses_with_success(client) -> None:
assert states[2] == "locked"
def test_claim_grants_coin_and_becomes_claimed(client) -> None:
"""领第 1 档:发对应金币,进金币余额,该档变 claimed。"""
def test_claim_marks_claimed_without_coin(client) -> None:
"""领第 1 档:暂不真发金币(产品定,后续删该功能),余额不变,但该档变 claimed。"""
token = _login(client, "13800003003")
_report_success(client, token, "s-1")
@@ -93,8 +93,8 @@ def test_claim_grants_coin_and_becomes_claimed(client) -> None:
assert r.status_code == 200, r.text
res = r.json()
assert res["milestone"] == 1
assert res["coin_awarded"] == RECORD_MILESTONES[0]
assert res["coin_balance"] == bal_before + RECORD_MILESTONES[0]
assert res["coin_awarded"] == 0 # 不再发金币
assert res["coin_balance"] == bal_before # 余额不变
d = client.get("/api/v1/compare/milestones", headers=_auth(token)).json()
assert d["milestones"][0]["state"] == "claimed"