cipher-attacks's picture
inline fuzzy + courses
d896946
Raw History Blame Contribute Delete
1.96 kB
from datetime import datetime
from typing import Optional
from sqlalchemy import BigInteger, DateTime, Integer, String, UniqueConstraint, func
from sqlalchemy.orm import Mapped, mapped_column
from app.db.base import Base
class XpEvent(Base):
"""Immutable XP ledger. users.points / week_xp are only a fast cache of this table.
UNIQUE(user_id, kind, ref) makes every rewarded action idempotent (no double pay)."""
__tablename__ = "xp_events"
__table_args__ = (UniqueConstraint("user_id", "kind", "ref", name="uq_xp_idem"),)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BigInteger, index=True)
kind: Mapped[str] = mapped_column(String(24))
amount: Mapped[int] = mapped_column(Integer)
ref: Mapped[Optional[str]] = mapped_column(String(64))
week: Mapped[str] = mapped_column(String(8), index=True)
day: Mapped[str] = mapped_column(String(10))
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
class SeasonResult(Base):
"""One row per winner per weekly season, plus a 'closed' marker (rank 0) per week."""
__tablename__ = "season_results"
__table_args__ = (UniqueConstraint("week", "kind", "rank", name="uq_season_slot"),)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
week: Mapped[str] = mapped_column(String(8), index=True)
kind: Mapped[str] = mapped_column(String(8)) # top | raffle | closed
rank: Mapped[int] = mapped_column(Integer, default=0)
user_id: Mapped[int] = mapped_column(BigInteger, default=0)
xp: Mapped[int] = mapped_column(Integer, default=0)
prize_birr: Mapped[int] = mapped_column(Integer, default=0)
status: Mapped[str] = mapped_column(String(12), default="info") # info | pending | paid
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())