d7c29c0883
- rewards: 激励视频实发改按 calculate_ad_reward_coin(eCPM, 当日第N次) 公式;AD_REWARD_COIN/MAX_AD_REWARD_COIN 降为历史兼容口径;新增 SIGNIN_BOOST_COIN=2000 - 签到膨胀: Day1-13 看完激励视频额外发固定金币、Day14 不允许 (signin.py / signin-boost) - ad_session_id 幂等: ad_ecpm/ad_reward/ad_feed_reward 记录加 ad_session_id 列 + 唯一索引(新迁移 coin_reward_phase2 / ad_feed_reward_session) - ad.py + schemas + repositories: ecpm-report / feed-reward / reward-status / test-grant 改造;config_schema 增 signin_boost_coin;admin stats overview 补充 - 同步 docs/api + docs/database + docs/integrations/pangle 及 tests(test_ad_reward / test_welfare) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: OuYingJun1024 <1034284404@qq.com> Reviewed-on: #28 Co-authored-by: ouzhou <ouzhou@wonderable.ai> Co-committed-by: ouzhou <ouzhou@wonderable.ai>
45 lines
1.9 KiB
Python
45 lines
1.9 KiB
Python
"""信息流广告奖励记录。
|
|
|
|
点位 2:比价等待 / 领券信息流广告。每展示满 10 秒累计一份奖励,视频完成后一次性入账。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import DateTime, ForeignKey, Integer, String, UniqueConstraint, func
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.db.base import Base
|
|
|
|
|
|
class AdFeedRewardRecord(Base):
|
|
__tablename__ = "ad_feed_reward_record"
|
|
__table_args__ = (
|
|
UniqueConstraint("client_event_id", name="uq_ad_feed_reward_client_event"),
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
client_event_id: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
ad_session_id: Mapped[str | None] = mapped_column(String(64), index=True, nullable=True)
|
|
user_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("user.id"), index=True, nullable=False
|
|
)
|
|
reward_date: Mapped[str] = mapped_column(String(10), index=True, nullable=False)
|
|
duration_seconds: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
unit_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
ecpm_raw: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
adn: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
slot_id: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
coin: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
status: Mapped[str] = mapped_column(String(16), nullable=False, default="granted")
|
|
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), index=True, nullable=False
|
|
)
|
|
|
|
def __repr__(self) -> str: # pragma: no cover
|
|
return (
|
|
f"<AdFeedRewardRecord user_id={self.user_id} event={self.client_event_id} "
|
|
f"{self.status} coin={self.coin}>"
|
|
)
|