diff --git a/backend/run_migration_024.py b/backend/run_migration_024.py new file mode 100644 index 0000000..b3cc132 --- /dev/null +++ b/backend/run_migration_024.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +""" +Manual Migration 024 Runner + +Run this to manually execute Migration 024 if it didn't run automatically. +""" + +import psycopg2 +import os +from psycopg2.extras import RealDictCursor + +# Database connection +DB_HOST = os.getenv('DB_HOST', 'localhost') +DB_PORT = os.getenv('DB_PORT', '5432') +DB_NAME = os.getenv('DB_NAME', 'bodytrack') +DB_USER = os.getenv('DB_USER', 'bodytrack') +DB_PASS = os.getenv('DB_PASSWORD', '') + +def main(): + print("šŸ”§ Manual Migration 024 Runner") + print("=" * 60) + + # Connect to database + conn = psycopg2.connect( + host=DB_HOST, + port=DB_PORT, + dbname=DB_NAME, + user=DB_USER, + password=DB_PASS + ) + conn.autocommit = False + cur = conn.cursor(cursor_factory=RealDictCursor) + + try: + # Check if table exists + cur.execute(""" + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_name = 'goal_type_definitions' + ) + """) + exists = cur.fetchone()['exists'] + + if exists: + print("āœ“ goal_type_definitions table already exists") + + # Check if it has data + cur.execute("SELECT COUNT(*) as count FROM goal_type_definitions") + count = cur.fetchone()['count'] + print(f"āœ“ Table has {count} entries") + + if count > 0: + print("\nšŸ“Š Existing Goal Types:") + cur.execute(""" + SELECT type_key, label_de, unit, is_system, is_active + FROM goal_type_definitions + ORDER BY is_system DESC, label_de + """) + for row in cur.fetchall(): + status = "SYSTEM" if row['is_system'] else "CUSTOM" + active = "ACTIVE" if row['is_active'] else "INACTIVE" + print(f" - {row['type_key']}: {row['label_de']} ({row['unit']}) [{status}] [{active}]") + + print("\nāœ… Migration 024 is already complete!") + return + + # Run migration + print("\nšŸš€ Running Migration 024...") + + with open('migrations/024_goal_type_registry.sql', 'r', encoding='utf-8') as f: + migration_sql = f.read() + + cur.execute(migration_sql) + conn.commit() + + print("āœ… Migration 024 executed successfully!") + + # Verify + cur.execute("SELECT COUNT(*) as count FROM goal_type_definitions") + count = cur.fetchone()['count'] + print(f"āœ“ {count} goal types seeded") + + # Show created types + cur.execute(""" + SELECT type_key, label_de, unit, is_system + FROM goal_type_definitions + WHERE is_active = true + ORDER BY is_system DESC, label_de + """) + + print("\nšŸ“Š Created Goal Types:") + for row in cur.fetchall(): + status = "SYSTEM" if row['is_system'] else "CUSTOM" + print(f" - {row['type_key']}: {row['label_de']} ({row['unit']}) [{status}]") + + # Update schema_migrations + cur.execute(""" + INSERT INTO schema_migrations (filename, executed_at) + VALUES ('024_goal_type_registry.sql', NOW()) + ON CONFLICT (filename) DO NOTHING + """) + conn.commit() + + print("\nāœ… Migration 024 complete!") + + except Exception as e: + conn.rollback() + print(f"\nāŒ Error: {e}") + import traceback + traceback.print_exc() + finally: + cur.close() + conn.close() + +if __name__ == '__main__': + main()