From f5d3d487af218f5964166a855d8c70053e4a31a4 Mon Sep 17 00:00:00 2001 From: "Troll (Hermes Agent)" Date: Wed, 5 Aug 2026 13:51:53 +0000 Subject: [PATCH] Fix 500 on /play//revise for missing revision_count column Deployed DBs persisted without the revision_count column / revision_history table, causing customer revision requests to 500. - init_db() now migrates existing tables by adding missing columns. - log_revision() falls back to init_db() on missing table for full repair. - Bump version 0.4.1 -> 0.4.2. --- README.md | 2 +- VERSION | 2 +- models.py | 37 ++++++++++++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 7 deletions(-) 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)