"""Collection model for Mantimon TCG. This module defines the Collection model for tracking player card ownership. Each entry represents a card the player owns, with quantity and source tracking. Example: collection_entry = Collection( user_id=user.id, card_definition_id="pikachu_base_001", quantity=3, source=CardSource.BOOSTER ) """ from datetime import UTC, datetime from enum import Enum from typing import TYPE_CHECKING from uuid import UUID from sqlalchemy import ( DateTime, ForeignKey, Index, Integer, String, UniqueConstraint, ) from sqlalchemy import ( Enum as SQLEnum, ) from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base if TYPE_CHECKING: from app.db.models.user import User class CardSource(str, Enum): """Source of how a card was obtained. Attributes: STARTER: From a starter deck selection. BOOSTER: From opening a booster pack. REWARD: From winning matches or achievements. PURCHASE: From direct purchase with Mantibucks. TRADE: From trading with another player. GIFT: From promotional events or gifts. """ STARTER = "starter" BOOSTER = "booster" REWARD = "reward" PURCHASE = "purchase" TRADE = "trade" GIFT = "gift" class Collection(Base): """Player card collection entry. Tracks ownership of cards with quantity and source information. Each (user_id, card_definition_id) pair is unique - quantities are aggregated. Attributes: id: Unique identifier (UUID). user_id: Foreign key to the owning user. card_definition_id: ID of the card definition (e.g., "pikachu_base_001"). quantity: Number of copies owned (1+). source: How the first copy was obtained. obtained_at: When the card was first added to collection. created_at: Record creation timestamp. updated_at: Record update timestamp. Relationships: user: The user who owns this card. """ __tablename__ = "collections" # Ownership user_id: Mapped[UUID] = mapped_column( ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True, doc="Foreign key to owning user", ) # Card reference (string ID matching card JSON data) card_definition_id: Mapped[str] = mapped_column( String(100), nullable=False, doc="Card definition ID (e.g., 'pikachu_base_001')", ) # Quantity tracking quantity: Mapped[int] = mapped_column( Integer, default=1, nullable=False, doc="Number of copies owned", ) # Source tracking source: Mapped[CardSource] = mapped_column( SQLEnum(CardSource, name="card_source", create_constraint=True), nullable=False, doc="How the card was obtained", ) # When first obtained obtained_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), nullable=False, doc="When card was first added to collection", ) # Relationship user: Mapped["User"] = relationship( "User", back_populates="collection", ) # Constraints and indexes __table_args__ = ( UniqueConstraint("user_id", "card_definition_id", name="uq_collection_user_card"), Index("ix_collection_card", "card_definition_id"), ) def __repr__(self) -> str: return ( f"" )