feat(admin): app_config 运营配置后台(rewards 等常量可后台配置) (#14)
- 新增 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
This commit was merged in pull request #14.
This commit is contained in:
+59
-5
@@ -92,17 +92,71 @@ VIDEO_ROUND_REQUIRED_COUNT: int = 3
|
||||
VIDEO_ROUND_COOLDOWN_SECONDS: int = 600
|
||||
|
||||
|
||||
def resolve_ad_reward_coin(reward_amount: str | int | None) -> int:
|
||||
def resolve_ad_reward_coin(db, reward_amount: str | int | None) -> int: # noqa: ANN001
|
||||
"""把穿山甲回调的 reward_amount(后台代码位配的"奖励数量")解析成本次发放金币。
|
||||
|
||||
缺失 / 非数字 / ≤0 → 回退 AD_REWARD_COIN;超过 MAX_AD_REWARD_COIN → 夹紧。
|
||||
缺失 / 非数字 / ≤0 → 回退配置单次金币;超过配置单次上限 → 夹紧(均从 app_config 读)。
|
||||
注:reward_amount 不参与穿山甲 sign(只签 trans_id),但伪造回调需先伪造合法 sign
|
||||
(要 SecurityKey),故能过验签的 reward_amount 即视为可信,这里只防后台配错。
|
||||
"""
|
||||
default_coin = get_ad_reward_coin(db)
|
||||
try:
|
||||
coin = int(reward_amount) # type: ignore[arg-type]
|
||||
except (TypeError, ValueError):
|
||||
return AD_REWARD_COIN
|
||||
return default_coin
|
||||
if coin <= 0:
|
||||
return AD_REWARD_COIN
|
||||
return min(coin, MAX_AD_REWARD_COIN)
|
||||
return default_coin
|
||||
return min(coin, get_ad_max_coin(db))
|
||||
|
||||
|
||||
# ===== 配置读取(运营后台可覆盖;app_config 表空时返回上面的常量默认 = 现状不变)=====
|
||||
# 业务处用这些 getter(传 db)取值,而非直接用常量,这样 admin 改 app_config 即生效。
|
||||
# 函数内延迟 import,避免 rewards ← app_config ← config_schema ← rewards 的模块级循环。
|
||||
|
||||
def _cfg(db, key: str): # noqa: ANN001
|
||||
from app.repositories import app_config
|
||||
return app_config.get_value(db, key)
|
||||
|
||||
|
||||
def get_signin_rewards(db) -> list[int]: # noqa: ANN001
|
||||
return list(_cfg(db, "signin_rewards"))
|
||||
|
||||
|
||||
def get_min_exchange_coin(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "min_exchange_coin"))
|
||||
|
||||
|
||||
def get_withdraw_min_cents(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "withdraw_min_cents"))
|
||||
|
||||
|
||||
def get_withdraw_max_cents(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "withdraw_max_cents"))
|
||||
|
||||
|
||||
def get_task_rewards(db) -> dict[str, int]: # noqa: ANN001
|
||||
return dict(_cfg(db, "task_rewards"))
|
||||
|
||||
|
||||
def get_record_milestones(db) -> list[int]: # noqa: ANN001
|
||||
return list(_cfg(db, "record_milestones"))
|
||||
|
||||
|
||||
def get_ad_reward_coin(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "ad_reward_coin"))
|
||||
|
||||
|
||||
def get_ad_daily_limit(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "ad_daily_limit"))
|
||||
|
||||
|
||||
def get_ad_max_coin(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "ad_max_coin"))
|
||||
|
||||
|
||||
def get_ad_round_count(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "ad_round_count"))
|
||||
|
||||
|
||||
def get_ad_cooldown_sec(db) -> int: # noqa: ANN001
|
||||
return int(_cfg(db, "ad_cooldown_sec"))
|
||||
|
||||
Reference in New Issue
Block a user