diff --git a/app/core/rewards.py b/app/core/rewards.py index 80998a4..b2312d9 100644 --- a/app/core/rewards.py +++ b/app/core/rewards.py @@ -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, } diff --git a/app/models/comparison.py b/app/models/comparison.py index 22dab56..c351e94 100644 --- a/app/models/comparison.py +++ b/app/models/comparison.py @@ -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) diff --git a/app/repositories/comparison_milestone.py b/app/repositories/comparison_milestone.py index 4b43c05..730c3ba 100644 --- a/app/repositories/comparison_milestone.py +++ b/app/repositories/comparison_milestone.py @@ -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 diff --git a/app/schemas/compare_record.py b/app/schemas/compare_record.py index 7ecd94d..d431d46 100644 --- a/app/schemas/compare_record.py +++ b/app/schemas/compare_record.py @@ -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(未解锁)") diff --git a/docs/api/compare-milestones.md b/docs/api/compare-milestones.md index 075a444..7933913 100644 --- a/docs/api/compare-milestones.md +++ b/docs/api/compare-milestones.md @@ -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 diff --git a/docs/database/comparison_milestone_claim.md b/docs/database/comparison_milestone_claim.md index 7d626c3..303dede 100644 --- a/docs/database/comparison_milestone_claim.md +++ b/docs/database/comparison_milestone_claim.md @@ -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。 diff --git a/tests/test_welfare.py b/tests/test_welfare.py index 7bf69fe..d669ce6 100644 --- a/tests/test_welfare.py +++ b/tests/test_welfare.py @@ -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(