67a9a15775
- 新增 app_config 表 + model/repository/config_schema + admin config 路由与 schema + 测试 - rewards.py 及 ad_reward/signin/task/wallet/comparison_milestone repositories 接入可配置项;ad.py / admin/main.py 配套 - alembic merge(ebb6af5c0b56)合并本地 app_config(cfg1a2b3c4d5)与 incoming price_report/best_deeplink(b7e2c1a9f4d3)两 head Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Reviewed-on: #14
75 lines
2.1 KiB
Python
75 lines
2.1 KiB
Python
"""一次性任务 CRUD:列表状态 + 领奖。
|
|
|
|
领奖原子化:写 user_task(唯一约束防重复)+ 发金币,同一事务 commit。
|
|
任务列表 + 奖励来自 rewards.get_task_rewards(运营后台可改)。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core import rewards
|
|
from app.models.task import UserTask
|
|
from app.repositories import wallet as crud_wallet
|
|
|
|
|
|
class UnknownTaskError(Exception):
|
|
"""task_key 不在已知任务表里。"""
|
|
|
|
|
|
class AlreadyClaimedError(Exception):
|
|
"""该任务已经领过奖了。"""
|
|
|
|
|
|
@dataclass
|
|
class TaskState:
|
|
task_key: str
|
|
coin: int
|
|
claimed: bool
|
|
|
|
|
|
def list_tasks(db: Session, user_id: int) -> list[TaskState]:
|
|
"""返回所有已知一次性任务及其领取状态。"""
|
|
task_rewards = rewards.get_task_rewards(db)
|
|
stmt = select(UserTask.task_key).where(UserTask.user_id == user_id)
|
|
claimed_keys = set(db.execute(stmt).scalars().all())
|
|
return [
|
|
TaskState(task_key=key, coin=coin, claimed=key in claimed_keys)
|
|
for key, coin in task_rewards.items()
|
|
]
|
|
|
|
|
|
def claim_task(db: Session, user_id: int, task_key: str) -> tuple[int, int]:
|
|
"""领取一次性任务奖励。返回 (发放金币, 领奖后余额)。
|
|
|
|
未知任务抛 UnknownTaskError;重复领取抛 AlreadyClaimedError。
|
|
"""
|
|
task_rewards = rewards.get_task_rewards(db)
|
|
if task_key not in task_rewards:
|
|
raise UnknownTaskError
|
|
|
|
existing = db.execute(
|
|
select(UserTask).where(
|
|
UserTask.user_id == user_id, UserTask.task_key == task_key
|
|
)
|
|
).scalar_one_or_none()
|
|
if existing is not None:
|
|
raise AlreadyClaimedError
|
|
|
|
coin = task_rewards[task_key]
|
|
db.add(
|
|
UserTask(
|
|
user_id=user_id,
|
|
task_key=task_key,
|
|
status="completed",
|
|
coin_awarded=coin,
|
|
)
|
|
)
|
|
acc, _ = crud_wallet.grant_coins(
|
|
db, user_id, coin, biz_type=f"task_{task_key}", ref_id=task_key
|
|
)
|
|
db.commit()
|
|
return coin, acc.coin_balance
|