diff --git a/app/db_engine.py b/app/db_engine.py index 06492f9..30e7d7c 100644 --- a/app/db_engine.py +++ b/app/db_engine.py @@ -498,51 +498,34 @@ class Roster(BaseModel): team = ForeignKeyField(Team) name = CharField() roster_num = IntegerField() - card_1 = ForeignKeyField(Card) - card_2 = ForeignKeyField(Card) - card_3 = ForeignKeyField(Card) - card_4 = ForeignKeyField(Card) - card_5 = ForeignKeyField(Card) - card_6 = ForeignKeyField(Card) - card_7 = ForeignKeyField(Card) - card_8 = ForeignKeyField(Card) - card_9 = ForeignKeyField(Card) - card_10 = ForeignKeyField(Card) - card_11 = ForeignKeyField(Card) - card_12 = ForeignKeyField(Card) - card_13 = ForeignKeyField(Card) - card_14 = ForeignKeyField(Card) - card_15 = ForeignKeyField(Card) - card_16 = ForeignKeyField(Card) - card_17 = ForeignKeyField(Card) - card_18 = ForeignKeyField(Card) - card_19 = ForeignKeyField(Card) - card_20 = ForeignKeyField(Card) - card_21 = ForeignKeyField(Card) - card_22 = ForeignKeyField(Card) - card_23 = ForeignKeyField(Card) - card_24 = ForeignKeyField(Card) - card_25 = ForeignKeyField(Card) - card_26 = ForeignKeyField(Card) def __str__(self): return f"{self.team} Roster" - # def get_cards(self, team): - # all_cards = Card.select().where(Card.roster == self) - # this_roster = [] - # return [this_roster.card1, this_roster.card2, this_roster.card3, this_roster.card4, this_roster.card5, - # this_roster.card6, this_roster.card7, this_roster.card8, this_roster.card9, this_roster.card10, - # this_roster.card11, this_roster.card12, this_roster.card13, this_roster.card14, this_roster.card15, - # this_roster.card16, this_roster.card17, this_roster.card18, this_roster.card19, this_roster.card20, - # this_roster.card21, this_roster.card22, this_roster.card23, this_roster.card24, this_roster.card25, - # this_roster.card26] + def get_cards(self): + return ( + Card.select() + .join(RosterSlot) + .where(RosterSlot.roster == self) + .order_by(RosterSlot.slot) + ) class Meta: database = db table_name = "roster" +class RosterSlot(BaseModel): + roster = ForeignKeyField(Roster, backref="slots") + slot = IntegerField() + card = ForeignKeyField(Card, backref="roster_slots") + + class Meta: + database = db + table_name = "rosterslot" + indexes = ((("roster", "slot"), True),) + + class Result(BaseModel): away_team = ForeignKeyField(Team) home_team = ForeignKeyField(Team) @@ -744,6 +727,7 @@ if not SKIP_TABLE_CREATION: db.create_tables( [ Roster, + RosterSlot, BattingStat, PitchingStat, Result, diff --git a/migrations/migrate_roster_junction_table.py b/migrations/migrate_roster_junction_table.py new file mode 100644 index 0000000..419c606 --- /dev/null +++ b/migrations/migrate_roster_junction_table.py @@ -0,0 +1,65 @@ +""" +Migration: Replace 26 FK columns on Roster with RosterSlot junction table. + +Creates the `rosterslot` table and migrates existing lineup data from the +card_1..card_26 columns. Safe to re-run (skips rosters already migrated). + +Usage: + python migrations/migrate_roster_junction_table.py +""" + +import os +import sys + +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) + +from app.db_engine import db, Roster, RosterSlot + +SLOTS = 26 + + +def migrate(): + db.connect(reuse_if_open=True) + + # Create the table if it doesn't exist yet + db.create_tables([RosterSlot], safe=True) + + # Read raw rows from the old schema via plain SQL so we don't depend on + # the ORM model knowing about the legacy card_N columns. + cursor = db.execute_sql("SELECT * FROM roster") + columns = [desc[0] for desc in cursor.description] + + migrated = 0 + skipped = 0 + + with db.atomic(): + for row in cursor.fetchall(): + row_dict = dict(zip(columns, row)) + roster_id = row_dict["id"] + + already_migrated = ( + RosterSlot.select().where(RosterSlot.roster == roster_id).exists() + ) + if already_migrated: + skipped += 1 + continue + + slots_to_insert = [] + for slot_num in range(1, SLOTS + 1): + col = f"card_{slot_num}_id" + card_id = row_dict.get(col) + if card_id is not None: + slots_to_insert.append( + {"roster": roster_id, "slot": slot_num, "card": card_id} + ) + + if slots_to_insert: + RosterSlot.insert_many(slots_to_insert).execute() + migrated += 1 + + print(f"Migration complete: {migrated} rosters migrated, {skipped} already done.") + db.close() + + +if __name__ == "__main__": + migrate()