fix(welfare): review 修复 — 里程碑"暂不发金币"文档同步 + 消息提醒奖励降为 1000
- comparison_milestone: 删 record_milestone_reward 死导入(ruff F401), 模块 docstring 同步"暂不发金币" - 里程碑文档群对齐实现: compare-milestones / comparison_milestone_claim / MilestoneStateOut.coin 描述都标注暂不真发金币 - models/comparison: comparison_results JSONB 形状注释补 coupon_saved - enable_notification 奖励 10000→1000(产品定, =¥0.1); test_exchange_flow 改 grant_coins 直接供款(不再靠该任务=兑换下限) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+3
-1
@@ -53,8 +53,10 @@ WITHDRAW_MAX_CENTS: int = 5_000_000 # 5 万元
|
||||
TASK_ENABLE_NOTIFICATION = "enable_notification"
|
||||
|
||||
# task_key -> 奖励金币
|
||||
# 打开消息提醒: 1000 金币(=¥0.1, 客户端原型展示口径; 量级与签到/里程碑相称)。
|
||||
# 注意: 已不再 = 兑换下限(MIN_EXCHANGE_COIN=10000), test_exchange_flow 改走 grant_coins 直接供款。
|
||||
TASK_REWARDS: dict[str, int] = {
|
||||
TASK_ENABLE_NOTIFICATION: 10000,
|
||||
TASK_ENABLE_NOTIFICATION: 1000,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ class ComparisonRecord(Base):
|
||||
# ===== 明细(JSON,越详细越好)=====
|
||||
# 下单菜品 [{name, qty, specs?}]
|
||||
items: Mapped[list] = mapped_column(_JSON, nullable=False, default=list)
|
||||
# 逐平台对比 [{platform_id, platform_name, package, price, is_source, rank}](price 单位:元,原样存)
|
||||
# 逐平台对比 [{platform_id, platform_name, package, price, is_source, rank, coupon_saved}](price/coupon_saved 单位:元,原样存)
|
||||
comparison_results: Mapped[list] = mapped_column(_JSON, nullable=False, default=list)
|
||||
# 目标平台未找到、跳过的菜名
|
||||
skipped_dish_names: Mapped[list] = mapped_column(_JSON, nullable=False, default=list)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"""比价战绩里程碑 CRUD:进度查询 + 逐档领奖。
|
||||
|
||||
进度 = comparison_record 里 status='success' 的条数(crud_compare.count_success)。
|
||||
第 N 档在"成功次数 >= N"时解锁;每档领一次,写 comparison_milestone_claim 去重 +
|
||||
grant_coins,同一事务 commit(领奖记录与加金币原子化)。仿一次性任务 (task.py)。
|
||||
第 N 档在"成功次数 >= N"时解锁;每档领一次,写 comparison_milestone_claim 去重(标记已领)。
|
||||
⚠️ 当前产品定暂不真发金币(后续整体删除该功能):claim 只写领取记录,不调 grant_coins、
|
||||
不写 coin_transaction,coin_awarded 恒为 0,余额不变。仿一次性任务 (task.py)。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -14,7 +15,6 @@ from sqlalchemy.orm import Session
|
||||
from app.core.rewards import (
|
||||
RECORD_MILESTONE_COUNT,
|
||||
RECORD_MILESTONES,
|
||||
record_milestone_reward,
|
||||
)
|
||||
from app.models.comparison_milestone import ComparisonMilestoneClaim
|
||||
from app.repositories import comparison as crud_compare
|
||||
|
||||
@@ -113,7 +113,7 @@ class ComparisonRecordCreatedOut(BaseModel):
|
||||
|
||||
class MilestoneStateOut(BaseModel):
|
||||
milestone: int = Field(..., description="档位序号 1-based(= 解锁所需的成功比价次数)")
|
||||
coin: int = Field(..., description="该档奖励金币")
|
||||
coin: int = Field(..., description="该档应发金币额(产品规则值);当前领取暂不真发, 见 compare-milestone-claim 文档")
|
||||
state: str = Field(..., description="claimed(已领) / active(可领) / locked(未解锁)")
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
档位金额是**产品规则**,定义在后端 `app/core/rewards.py` 的 `RECORD_MILESTONES`(当前 `120/180/300/500/800/1200`),客户端**不要写死**,以本接口返回为准。
|
||||
|
||||
> ⚠️ **当前领取暂不真发金币**(产品定,后续整体删除该功能):`coin` 仍返回产品规则值仅供展示,但 [claim 接口](./compare-milestone-claim.md) 实际 `coin_awarded` 恒为 0、余额不变。前端展示须与之对齐,勿让用户误以为领取可到账。
|
||||
|
||||
## 入参
|
||||
无(用户身份取自 Bearer token)。
|
||||
|
||||
@@ -25,7 +27,7 @@
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `milestone` | int | 档位序号(1-based),= 解锁所需的成功比价次数 |
|
||||
| `coin` | int | 该档奖励金币 |
|
||||
| `coin` | int | 该档**应发**金币额(产品规则值);⚠️ 当前领取不真发,见上方说明 |
|
||||
| `state` | string | `claimed`(已领) / `active`(已解锁可领) / `locked`(未解锁) |
|
||||
|
||||
```json
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
| `id` | Integer | PK, autoincrement | |
|
||||
| `user_id` | Integer | FK→user.id, index, NOT NULL | 归属用户 |
|
||||
| `milestone` | Integer | NOT NULL | 档位序号(1-based),见 `rewards.RECORD_MILESTONES` |
|
||||
| `coin_awarded` | Integer | NOT NULL, default 0 | 该档发放金币 |
|
||||
| `coin_awarded` | Integer | NOT NULL, default 0 | 该档应发金币额;⚠️ 当前产品定暂不真发,实际恒为 0 |
|
||||
| `claimed_at` | DateTime(tz) | server_default now() | 领取时间 |
|
||||
|
||||
## 索引与约束
|
||||
@@ -22,5 +22,5 @@
|
||||
- 解锁进度依赖 `comparison_record`(`status='success'` 计数),本表不存进度本身。
|
||||
|
||||
## 说明
|
||||
- 发金币走 `wallet.grant_coins(biz_type='compare_milestone', ref_id=str(milestone))`,与本表写入同事务。
|
||||
- ⚠️ 当前 claim 仅写本表标记已领(去重),**不调 `grant_coins`、不写 `coin_transaction`,`coin_awarded` 恒为 0、余额不变**(产品定暂不真发金币,后续整体删除该功能)。
|
||||
- 领取校验:档位越界 404、未解锁(成功数 < milestone)409、已领 409。
|
||||
|
||||
+16
-4
@@ -12,6 +12,9 @@ from app.core.rewards import (
|
||||
TASK_ENABLE_NOTIFICATION,
|
||||
TASK_REWARDS,
|
||||
)
|
||||
from app.db.session import SessionLocal
|
||||
from app.repositories import wallet as crud_wallet
|
||||
from app.repositories.user import get_user_by_phone
|
||||
|
||||
|
||||
def _login(client, phone: str) -> str:
|
||||
@@ -130,10 +133,19 @@ def test_exchange_info(client) -> None:
|
||||
|
||||
|
||||
def test_exchange_flow(client) -> None:
|
||||
"""先用任务领够金币 → 兑换 1 元 → 金币扣、现金加 → 现金流水有记录。"""
|
||||
token = _login(client, "13800001005")
|
||||
# 领"打开消息提醒"得 10000 金币(= 1 元额度)
|
||||
client.post(f"/api/v1/tasks/{TASK_ENABLE_NOTIFICATION}/claim", headers=_auth(token))
|
||||
"""先供款够兑换下限的金币 → 兑换 1 元 → 金币扣、现金加 → 现金流水有记录。
|
||||
|
||||
打开消息提醒任务已降到 1000 金币(不再 = 兑换下限), 不能再靠领任务供款;
|
||||
直接 grant_coins 注入 MIN_EXCHANGE_COIN(= COIN_PER_YUAN = 10000)当种子。
|
||||
"""
|
||||
phone = "13800001005"
|
||||
token = _login(client, phone)
|
||||
# 供款: 直接注入 1 元额度金币(替代原先靠 notification=10000 领任务供款)
|
||||
with SessionLocal() as db:
|
||||
user = get_user_by_phone(db, phone)
|
||||
assert user is not None
|
||||
crud_wallet.grant_coins(db, user.id, MIN_EXCHANGE_COIN, biz_type="test_seed", remark="测试供款")
|
||||
db.commit()
|
||||
|
||||
# 兑换 10000 金币 → 100 分
|
||||
r = client.post(
|
||||
|
||||
Reference in New Issue
Block a user