Add multi-league foundation
This commit is contained in:
@@ -104,6 +104,9 @@ def run_migrations(engine):
|
||||
print("Running migrations...")
|
||||
|
||||
# Check if the columns already exist before adding them
|
||||
# Create league structures and attach existing records to a default league
|
||||
add_league_support(connection)
|
||||
|
||||
# Add additional_oauth_providers column if it doesn't exist
|
||||
add_oauth_providers_column(connection)
|
||||
|
||||
@@ -151,6 +154,156 @@ def add_oauth_providers_column(connection):
|
||||
except Exception as e:
|
||||
print(f"Error adding additional_oauth_providers column: {str(e)}")
|
||||
|
||||
def add_league_support(connection):
|
||||
"""Add leagues and backfill existing single-league data."""
|
||||
try:
|
||||
inspector = inspect(engine)
|
||||
tables = inspector.get_table_names()
|
||||
|
||||
if 'leagues' not in tables:
|
||||
print("Creating leagues table")
|
||||
if engine.name == 'sqlite':
|
||||
connection.execute(text("""
|
||||
CREATE TABLE leagues (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
slug VARCHAR(120) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
publisher_name VARCHAR(100),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
"""))
|
||||
else:
|
||||
connection.execute(text("""
|
||||
CREATE TABLE leagues (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
slug VARCHAR(120) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
publisher_name VARCHAR(100),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
)
|
||||
"""))
|
||||
connection.commit()
|
||||
|
||||
league_id = ensure_default_league(connection)
|
||||
|
||||
for table_name in ('teams', 'qr_sets', 'qr_codes', 'events'):
|
||||
add_nullable_league_id(connection, table_name)
|
||||
|
||||
backfill_league_ids(connection, league_id)
|
||||
drop_global_team_name_unique(connection)
|
||||
except Exception as e:
|
||||
print(f"Error adding league support: {str(e)}")
|
||||
|
||||
def ensure_default_league(connection):
|
||||
"""Return the default league id, creating it if needed."""
|
||||
row = connection.execute(
|
||||
text("SELECT id FROM leagues WHERE slug = :slug"),
|
||||
{"slug": "default"}
|
||||
).first()
|
||||
if row:
|
||||
return row[0]
|
||||
|
||||
connection.execute(
|
||||
text("""
|
||||
INSERT INTO leagues (name, slug, description, publisher_name, is_active)
|
||||
VALUES (:name, :slug, :description, :publisher_name, :is_active)
|
||||
"""),
|
||||
{
|
||||
"name": "Default League",
|
||||
"slug": "default",
|
||||
"description": "Default league for existing LeagueLedger data.",
|
||||
"publisher_name": "LeagueLedger",
|
||||
"is_active": True,
|
||||
}
|
||||
)
|
||||
connection.commit()
|
||||
return connection.execute(
|
||||
text("SELECT id FROM leagues WHERE slug = :slug"),
|
||||
{"slug": "default"}
|
||||
).scalar()
|
||||
|
||||
def add_nullable_league_id(connection, table_name):
|
||||
"""Add a nullable league_id column to an existing table."""
|
||||
inspector = inspect(engine)
|
||||
if table_name not in inspector.get_table_names():
|
||||
return
|
||||
|
||||
columns = [col['name'] for col in inspector.get_columns(table_name)]
|
||||
if 'league_id' in columns:
|
||||
print(f"Column league_id already exists in {table_name}")
|
||||
return
|
||||
|
||||
print(f"Adding league_id column to {table_name}")
|
||||
if engine.name == 'sqlite':
|
||||
connection.execute(text(f"ALTER TABLE {table_name} ADD COLUMN league_id INTEGER NULL"))
|
||||
else:
|
||||
connection.execute(text(f"ALTER TABLE {table_name} ADD COLUMN league_id INT NULL"))
|
||||
connection.commit()
|
||||
|
||||
def backfill_league_ids(connection, default_league_id):
|
||||
"""Attach legacy data to the default league."""
|
||||
inspector = inspect(engine)
|
||||
tables = inspector.get_table_names()
|
||||
|
||||
for table_name in ('teams', 'qr_sets', 'events'):
|
||||
if table_name in tables and 'league_id' in [col['name'] for col in inspector.get_columns(table_name)]:
|
||||
connection.execute(
|
||||
text(f"UPDATE {table_name} SET league_id = :league_id WHERE league_id IS NULL"),
|
||||
{"league_id": default_league_id}
|
||||
)
|
||||
|
||||
if 'qr_codes' in tables and 'league_id' in [col['name'] for col in inspector.get_columns('qr_codes')]:
|
||||
connection.execute(text("""
|
||||
UPDATE qr_codes
|
||||
SET league_id = (
|
||||
SELECT qr_sets.league_id
|
||||
FROM qr_sets
|
||||
WHERE qr_sets.id = qr_codes.qr_set_id
|
||||
)
|
||||
WHERE league_id IS NULL
|
||||
AND qr_set_id IS NOT NULL
|
||||
"""))
|
||||
connection.execute(text("""
|
||||
UPDATE qr_codes
|
||||
SET league_id = (
|
||||
SELECT events.league_id
|
||||
FROM events
|
||||
WHERE events.id = qr_codes.event_id
|
||||
)
|
||||
WHERE league_id IS NULL
|
||||
AND event_id IS NOT NULL
|
||||
"""))
|
||||
connection.execute(
|
||||
text("UPDATE qr_codes SET league_id = :league_id WHERE league_id IS NULL"),
|
||||
{"league_id": default_league_id}
|
||||
)
|
||||
|
||||
connection.commit()
|
||||
|
||||
def drop_global_team_name_unique(connection):
|
||||
"""Best-effort removal of the legacy global team-name uniqueness constraint."""
|
||||
if engine.name == 'sqlite':
|
||||
return
|
||||
|
||||
inspector = inspect(engine)
|
||||
if 'teams' not in inspector.get_table_names():
|
||||
return
|
||||
|
||||
for constraint in inspector.get_unique_constraints('teams'):
|
||||
if constraint.get('column_names') == ['name']:
|
||||
constraint_name = constraint.get('name')
|
||||
if constraint_name:
|
||||
print(f"Dropping global teams.name unique constraint {constraint_name}")
|
||||
connection.execute(text(f"ALTER TABLE teams DROP INDEX {constraint_name}"))
|
||||
connection.commit()
|
||||
break
|
||||
|
||||
def add_name_columns(connection):
|
||||
"""Add first_name and last_name columns to users table"""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user