"""看激励视频观看时长记录(旧版每日总时长字段)。 每条 = 客户端 onAdClose 上报的一次激励视频实际观看秒数。按 (user_id, watch_date) 聚合 SUM(watch_seconds) 得当日总观看时长。当前产品只保留每日 500 次上限, core.rewards.DAILY_AD_WATCH_SECONDS_LIMIT=0 表示不启用时长闸;本表保留用于旧客户端兼容和排查。 这是看广告的第三条数据流,与另两条并列、互不关联: - ad_reward(AdRewardRecord):穿山甲 S2S 回调发金币(后端,有 trans_id); - ad_ecpm(AdEcpmRecord):客户端上报展示收益(前端,有 ecpm); - ad_watch_log(本表):客户端上报观看时长(前端,有 watch_seconds)。 前端上报的时长不可信,不能作为唯一发奖依据;当前发奖闸口以 ad_reward 的每日次数上限为准。 """ from __future__ import annotations from datetime import datetime from sqlalchemy import DateTime, ForeignKey, Integer, String, func from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base class AdWatchLog(Base): __tablename__ = "ad_watch_log" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) user_id: Mapped[int] = mapped_column( Integer, ForeignKey("user.id"), index=True, nullable=False ) # 本次激励视频实际观看秒数(前端 onAdShow→onAdClose);服务端已夹 [0, MAX_SINGLE_WATCH_SECONDS] watch_seconds: Mapped[int] = mapped_column(Integer, nullable=False, default=0) # 北京时间日期串 'YYYY-MM-DD',按它等值做"当日总时长"聚合(不在 SQL 里跨时区比较) watch_date: Mapped[str] = mapped_column(String(10), index=True, nullable=False) 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""