Files
mtgonline/backend/app/models/__backup__/mirror_models.py
T
akadmin 900f51af3a Complete architecture simplification: 54+ files → 37 files
- Removed 11 duplicate router files (auth.py, users.py, decks.py, card_router.py, interactions.py, user_data.py, rooms.py, games/router.py, refresh.py, card_import.py, ws.py)
- Removed duplicate core files (logging_config.py, settings.py)
- Removed unused services (card_mirror_service.py, mtgjson_loader.py, mtgjson_uploader.py)
- Removed unused schemas (proto_messages.py, protocol_constants.py)
- Created run.py startup script for simple execution
- Created app/core/config.py for unified configuration management
- Created app/core/logging.py for logging configuration
- Consolidated routers into 6 focused files (auth_router.py, users_router.py, decks_router.py, cards_router.py, user_data_router.py, games_router.py)
- Updated all imports to use consolidated model paths
- Added backward compatibility aliases in database.py
- Created SIMPLIFICATION_SUMMARY.md documentation

Architecture improvements:
- Single unified database engine with auto-detection (SQLite/PostgreSQL)
- Consolidated models into 2 files (models.py, mtg_models.py)
- Clean router structure with one file per domain
- Simplified configuration with sensible defaults
- SQLite by default for development, PostgreSQL for production

Testing:
- All imports verified working
- App loads successfully
- Ready for development and testing
2026-08-26 15:15:36 +00:00

98 lines
3.7 KiB
Python

"""
SQLAlchemy ORM models for card mirrors and deck-card links.
Mirrored card data lives in mtgo_platform for fast deckbuilding queries.
The MTGJSON database remains the canonical source of truth.
"""
from sqlalchemy import (
Column, Integer, String, Text, DateTime, ForeignKey, Index,
UniqueConstraint, Boolean
)
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.core.database import Base
class MtgCardMirror(Base):
"""
Mirrored card data for user decks.
Contains all relevant card fields copied from mtg_cards (mtg_data)
to avoid cross-DB joins during deckbuilding. Back-references source_id
to the canonical mtg_cards.id for sync tracking.
"""
__tablename__ = "mtg_cards_mirror"
id = Column(Integer, primary_key=True, index=True)
source_id = Column(
Integer,
nullable=True,
index=True,
comment="Logical reference to mtg_cards.id in mtg_data database (cross-DB reference, no FK constraint)"
)
name = Column(String(255), nullable=False, index=True)
mana_cost = Column(String(255), nullable=True)
type_line = Column(String(255), nullable=True)
oracle_text = Column(Text, nullable=True)
power = Column(String(50), nullable=True)
toughness = Column(String(50), nullable=True)
rarity = Column(String(50), nullable=True)
layout = Column(String(50), nullable=True)
artist = Column(String(255), nullable=True)
flavor_text = Column(Text, nullable=True)
numbers = Column(String(100), nullable=True)
identifiers = Column(Text, nullable=True) # JSON string of all identifiers
images = Column(Text, nullable=True) # JSON string of image URLs
image = Column(Text, nullable=True) # Card image URL from MTGJSON
card_parts = Column(Text, nullable=True) # Comma-separated list of face names
keywords = Column(Text, nullable=True) # Comma-separated keywords
legalities = Column(Text, nullable=True) # JSON of format legality
set_code = Column(String(10), nullable=True, index=True)
set_name = Column(String(255), nullable=True)
# Sync tracking
synced_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
created_at = Column(DateTime, server_default=func.now())
# Relationships
deck_links = relationship(
"DeckCardLink",
back_populates="card",
cascade="all, delete-orphan"
)
def __repr__(self) -> str:
return f"<MtgCardMirror {self.name} (ID: {self.id}, source: {self.source_id})>"
class DeckCardLink(Base):
"""
Junction table linking user decks to mirrored cards.
Represents a specific quantity of a mirrored card in a specific zone
(main deck or sideboard) of a user's deck.
"""
__tablename__ = "deck_card_links"
id = Column(Integer, primary_key=True, index=True)
deck_id = Column(Integer, ForeignKey("mtgonline_decklist_files.id", ondelete="CASCADE"), nullable=False)
card_id = Column(Integer, ForeignKey("mtg_cards_mirror.id"), nullable=False)
quantity = Column(Integer, nullable=False, default=1)
zone = Column(String(20), nullable=False, default="main") # 'main' or 'sideboard'
# Composite unique: a card can only appear once per zone in a deck
__table_args__ = (
UniqueConstraint('deck_id', 'card_id', 'zone', name='uq_deck_card_link'),
Index('idx_deck_card_deck', 'deck_id'),
Index('idx_deck_card_card', 'card_id'),
)
# Relationships
deck = relationship("DecklistFile", back_populates="card_links")
card = relationship("MtgCardMirror", back_populates="deck_links")
def __repr__(self) -> str:
return (
f"<DeckCardLink deck={self.deck_id} card={self.card_id} "
f"qty={self.quantity} zone={self.zone}>"
)