"""激励域:referrals / asset_wallets / asset_transactions / withdrawals / video_earnings""" from datetime import datetime from decimal import Decimal from sqlalchemy import DateTime, Index, Numeric, SmallInteger, String, func from sqlalchemy.dialects.mysql import BIGINT from sqlalchemy.orm import Mapped, mapped_column from app.models.base import Base class Referral(Base): __tablename__ = "referrals" id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True) inviter_id: Mapped[int] = mapped_column(BIGINT(unsigned=True), comment="推荐人") invitee_id: Mapped[int] = mapped_column(BIGINT(unsigned=True), comment="被推荐人") invite_code: Mapped[str] = mapped_column(String(10)) status: Mapped[int] = mapped_column(SmallInteger, default=0, comment="0待激活 1有效 2无效 3风控冻结") risk_flag: Mapped[str] = mapped_column(String(50), default="") register_ip: Mapped[str] = mapped_column(String(45), default="") activated_at: Mapped[datetime | None] = mapped_column(DateTime) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) __table_args__ = ( Index("uk_invitee", "invitee_id", unique=True), Index("idx_inviter", "inviter_id", "created_at"), Index("idx_status", "status", "created_at"), ) class AssetWallet(Base): __tablename__ = "asset_wallets" user_id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True) assets: Mapped[Decimal] = mapped_column(Numeric(12, 1), default=0, comment="当前资产(允许为负)") total_earned: Mapped[Decimal] = mapped_column(Numeric(14, 1), default=0) total_withdrawn: Mapped[Decimal] = mapped_column(Numeric(14, 1), default=0) version: Mapped[int] = mapped_column(default=0) updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now()) class AssetTransaction(Base): __tablename__ = "asset_transactions" id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True) user_id: Mapped[int] = mapped_column(BIGINT(unsigned=True)) change_amount: Mapped[Decimal] = mapped_column(Numeric(12, 1)) balance_after: Mapped[Decimal] = mapped_column(Numeric(12, 1)) biz_type: Mapped[int] = mapped_column( SmallInteger, comment="1充值返利 2完整观看 3点赞 4提现 5提现退回 6返利扣回 7后台调整" ) biz_id: Mapped[str] = mapped_column(String(64), default="") remark: Mapped[str] = mapped_column(String(200), default="") created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) __table_args__ = ( Index("idx_user_created", "user_id", "created_at"), Index("idx_biz", "biz_type", "biz_id"), ) class Withdrawal(Base): __tablename__ = "withdrawals" id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True) withdraw_no: Mapped[str] = mapped_column(String(32), unique=True) user_id: Mapped[int] = mapped_column(BIGINT(unsigned=True)) assets: Mapped[Decimal] = mapped_column(Numeric(12, 1)) amount_fen: Mapped[int] = mapped_column(comment="折合人民币(分)") channel: Mapped[int] = mapped_column(SmallInteger, comment="1支付宝 2微信 3USDT") account: Mapped[str] = mapped_column(String(200)) status: Mapped[int] = mapped_column(SmallInteger, default=0, comment="0待审核 1已打款 2已拒绝") reason: Mapped[str] = mapped_column(String(200), default="") admin_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True)) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) processed_at: Mapped[datetime | None] = mapped_column(DateTime) __table_args__ = ( Index("idx_user", "user_id", "created_at"), Index("idx_status", "status", "created_at"), ) class VideoEarning(Base): """视频收益结算刻度(完整观看/点赞按增量结算,余数保留)""" __tablename__ = "video_earnings" video_id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True) author_id: Mapped[int] = mapped_column(BIGINT(unsigned=True)) complete_views: Mapped[int] = mapped_column(default=0, comment="累计完整观看次数") views_settled: Mapped[int] = mapped_column(default=0, comment="已结算的完整观看刻度") likes_accrued: Mapped[int] = mapped_column(default=0, comment="累计点赞(取消会回退)") likes_settled: Mapped[int] = mapped_column(default=0, comment="已结算的点赞刻度") updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now()) __table_args__ = (Index("idx_author", "author_id"),)