diff --git a/README.md b/README.md index 35e38cb..4d2a160 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Theme Song Booth -**Version:** `v0.4.1` +**Version:** `v0.4.2` A Flask web app for a convention booth where visitors request a custom AI-generated theme song, the operator manages the queue, and the final MP3(s) are delivered by email after payment. diff --git a/VERSION b/VERSION index 267577d..2b7c5ae 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.1 +0.4.2 diff --git a/models.py b/models.py index 63b6a17..abad0b5 100644 --- a/models.py +++ b/models.py @@ -20,6 +20,7 @@ Schema overview (see SCHEMA constant): import sqlite3 import secrets from datetime import datetime, timezone +from pathlib import Path from flask import current_app, g # SQL executed by init_db() to create the requests table and indexes. @@ -89,9 +90,35 @@ def close_db(e=None): def init_db(): - """Create the database file and tables. Safe to run multiple times.""" - db = sqlite3.connect(current_app.config['DATABASE']) + """Create the database file and tables, adding any missing columns to existing tables.""" + db_path = current_app.config['DATABASE'] + Path(db_path).parent.mkdir(parents=True, exist_ok=True) + db = sqlite3.connect(db_path) + db.row_factory = sqlite3.Row db.executescript(SCHEMA) + + # SQLite ALTER TABLE is limited; add newer columns if they are missing. + expected_columns = { + 'requests': [ + 'id', 'created_at', 'name', 'email', 'hobbies', 'notable_facts', + 'style_genre', 'extra_requests', 'status', 'suno_title', 'suno_style', + 'suno_lyrics', 'song_a_path', 'song_b_path', 'vocal_gender', + 'customer_approved', 'approval_notified_at', 'preview_sent_at', + 'delivery_sent_at', 'square_payment_ref', 'admin_alert_email', + 'player_token', 'revision_count', 'revision_note', 'operator_notes', + 'stems_link' + ], + 'revision_history': [ + 'id', 'created_at', 'request_id', 'revision_count', 'note', + 'old_song_a_path', 'old_song_b_path', 'new_song_a_path', 'new_song_b_path' + ] + } + for table, columns in expected_columns.items(): + existing = {r['name'] for r in db.execute(f"PRAGMA table_info({table})")} + for col in columns: + if col not in existing: + # Use a safe default type; NULLable for all current optional columns. + db.execute(f'ALTER TABLE {table} ADD COLUMN {col} TEXT') db.commit() db.close() @@ -184,7 +211,7 @@ def delete_request(request_id): def log_revision(request_id, revision_count, note, old_a=None, old_b=None, new_a=None, new_b=None): - """Record a revision event in the revision_history table, creating the table if it is missing.""" + """Record a revision event in the revision_history table, creating it if it is missing.""" db = get_db() try: db.execute( @@ -196,8 +223,8 @@ def log_revision(request_id, revision_count, note, old_a=None, old_b=None, new_a db.commit() except sqlite3.OperationalError as e: if 'no such table' in str(e): - # Schema drift: table missing. Recreate and retry once. - db.executescript(SCHEMA) + # Schema drift: table missing. Run init_db to add tables/columns, then retry once. + init_db() db.execute( """INSERT INTO revision_history (request_id, revision_count, note, old_song_a_path, old_song_b_path, new_song_a_path, new_song_b_path)