#!/usr/bin/env python3 """ Quick diagnostic: Check Migration 024 state Run this inside the backend container: docker exec bodytrack-dev-backend-1 python check_migration_024.py """ import psycopg2 import os from psycopg2.extras import RealDictCursor # Database connection DB_HOST = os.getenv('DB_HOST', 'db') 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("=" * 70) print("Migration 024 Diagnostic") print("=" * 70) # Connect to database conn = psycopg2.connect( host=DB_HOST, port=DB_PORT, dbname=DB_NAME, user=DB_USER, password=DB_PASS ) cur = conn.cursor(cursor_factory=RealDictCursor) # 1. Check if table exists print("\n1. Checking if goal_type_definitions table exists...") cur.execute(""" SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_name = 'goal_type_definitions' ) """) exists = cur.fetchone()['exists'] print(f" ✓ Table exists: {exists}") if not exists: print("\n❌ TABLE DOES NOT EXIST - Migration 024 did not run!") print("\nRECOMMENDED ACTION:") print(" 1. Restart backend container: docker restart bodytrack-dev-backend-1") print(" 2. Check logs: docker logs bodytrack-dev-backend-1 | grep 'Migration'") cur.close() conn.close() return # 2. Check row count print("\n2. Checking row count...") cur.execute("SELECT COUNT(*) as count FROM goal_type_definitions") count = cur.fetchone()['count'] print(f" Row count: {count}") if count == 0: print("\n❌ TABLE IS EMPTY - Seed data was not inserted!") print("\nPOSSIBLE CAUSES:") print(" - INSERT statements failed (constraint violation?)") print(" - Migration ran partially") print("\nRECOMMENDED ACTION:") print(" Run the seed statements manually (see below)") else: print(f" ✓ Table has {count} entries") # 3. Show all entries print("\n3. Current goal type definitions:") cur.execute(""" SELECT type_key, label_de, unit, is_system, is_active, created_at FROM goal_type_definitions ORDER BY is_system DESC, type_key """) entries = cur.fetchall() if entries: print(f"\n {'Type Key':<20} {'Label':<20} {'Unit':<10} {'System':<8} {'Active':<8}") print(" " + "-" * 70) for row in entries: status = "SYSTEM" if row['is_system'] else "CUSTOM" active = "YES" if row['is_active'] else "NO" print(f" {row['type_key']:<20} {row['label_de']:<20} {row['unit']:<10} {status:<8} {active:<8}") else: print(" (empty)") # 4. Check schema_migrations print("\n4. Checking schema_migrations tracking...") cur.execute(""" SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_name = 'schema_migrations' ) """) sm_exists = cur.fetchone()['exists'] if sm_exists: cur.execute(""" SELECT filename, executed_at FROM schema_migrations WHERE filename = '024_goal_type_registry.sql' """) tracked = cur.fetchone() if tracked: print(f" ✓ Migration 024 is tracked (executed: {tracked['executed_at']})") else: print(" ❌ Migration 024 is NOT tracked in schema_migrations") else: print(" ⚠️ schema_migrations table does not exist") # 5. Check for errors print("\n5. Potential issues:") issues = [] if count == 0: issues.append("No seed data - INSERTs failed") if count > 0 and count < 6: issues.append(f"Only {count} types (expected 8) - partial seed") cur.execute(""" SELECT COUNT(*) as inactive_count FROM goal_type_definitions WHERE is_active = false """) inactive = cur.fetchone()['inactive_count'] if inactive > 2: issues.append(f"{inactive} inactive types (expected 2)") if not issues: print(" ✓ No issues detected") else: for issue in issues: print(f" ❌ {issue}") # 6. Test query that frontend uses print("\n6. Testing frontend query (WHERE is_active = true)...") cur.execute(""" SELECT COUNT(*) as active_count FROM goal_type_definitions WHERE is_active = true """) active_count = cur.fetchone()['active_count'] print(f" Active types returned: {active_count}") if active_count == 0: print(" ❌ This is why frontend shows empty list!") print("\n" + "=" * 70) print("SUMMARY") print("=" * 70) if count == 0: print("\n🔴 PROBLEM: Table exists but has no data") print("\nQUICK FIX: Run these SQL commands manually:") print("\n```sql") print("-- Connect to database:") print("docker exec -it bodytrack-dev-db-1 psql -U bodytrack -d bodytrack") print("\n-- Then paste migration content:") print("-- (copy from backend/migrations/024_goal_type_registry.sql)") print("-- Skip CREATE TABLE (already exists), run INSERT statements only") print("```") elif active_count >= 6: print("\n🟢 EVERYTHING LOOKS GOOD") print(f" {active_count} active goal types available") print("\nIf frontend still shows error, check:") print(" 1. Backend logs: docker logs bodytrack-dev-backend-1 -f") print(" 2. Network tab in browser DevTools") print(" 3. API endpoint: curl -H 'X-Auth-Token: YOUR_TOKEN' http://localhost:8099/api/goals/goal-types") else: print(f"\n🟡 PARTIAL DATA: {active_count} active types (expected 6)") print(" Some INSERTs might have failed") cur.close() conn.close() if __name__ == '__main__': main()