church-api/fix_migration_v2.py
Benjamin Slingo 0c06e159bb Initial commit: Church API Rust implementation
Complete church management system with bulletin management, media processing, live streaming integration, and web interface. Includes authentication, email notifications, database migrations, and comprehensive test suite.
2025-08-19 20:56:41 -04:00

139 lines
4.5 KiB
Python

import json
import psycopg2
import os
from datetime import datetime
import uuid
# Connect to database
conn = psycopg2.connect(os.environ['DATABASE_URL'])
cur = conn.cursor()
def load_json(filename):
try:
with open(f'/tmp/pb_migration/{filename}', 'r') as f:
data = json.load(f)
return data.get('items', [])
except Exception as e:
print(f"Error loading {filename}: {e}")
return []
def convert_pb_date(pb_date):
"""Convert PocketBase date to PostgreSQL timestamp"""
if not pb_date:
return None
try:
dt_str = pb_date.replace('Z', '+00:00')
return datetime.fromisoformat(dt_str)
except:
return None
def clean_recurring_type(value):
"""Clean recurring type field"""
if not value or value == '':
return None
return value
# Rollback any pending transaction
conn.rollback()
# Clear existing data
print("🧹 Clearing existing data...")
cur.execute("DELETE FROM bulletins")
cur.execute("DELETE FROM events")
# Import bulletins
print("📄 Importing bulletins...")
bulletins = load_json('bulletins.json')
print(f"Found {len(bulletins)} bulletins to import")
for i, bulletin in enumerate(bulletins):
try:
cur.execute("""
INSERT INTO bulletins (id, title, date, url, pdf_url, is_active, pdf_file,
sabbath_school, divine_worship, scripture_reading, sunset,
cover_image, created_at, updated_at)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""", (
str(uuid.uuid4()),
bulletin.get('title', ''),
bulletin.get('date'),
bulletin.get('url'),
bulletin.get('pdf_url'),
bulletin.get('is_active', True),
bulletin.get('pdf'),
bulletin.get('sabbath_school', ''),
bulletin.get('divine_worship', ''),
bulletin.get('scripture_reading'),
bulletin.get('sunset', ''),
bulletin.get('cover_image'),
convert_pb_date(bulletin.get('created')),
convert_pb_date(bulletin.get('updated'))
))
print(f" ✅ Imported bulletin {i+1}: {bulletin.get('title')}")
except Exception as e:
print(f" ❌ Failed to import bulletin {i+1}: {e}")
continue
# Import events
print("📅 Importing events...")
events = load_json('events.json')
print(f"Found {len(events)} events to import")
for i, event in enumerate(events):
try:
cur.execute("""
INSERT INTO events (id, title, description, start_time, end_time, location,
location_url, image, thumbnail, category, is_featured,
recurring_type, approved_from, created_at, updated_at)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""", (
str(uuid.uuid4()),
event.get('title', ''),
event.get('description', ''),
event.get('start_time'),
event.get('end_time'),
event.get('location', ''),
event.get('location_url'),
event.get('image'),
event.get('thumbnail'),
event.get('category', 'Other'),
event.get('is_featured', False),
clean_recurring_type(event.get('reoccuring')), # Fix this field
event.get('approved_from') if event.get('approved_from') else None,
convert_pb_date(event.get('created')),
convert_pb_date(event.get('updated'))
))
print(f" ✅ Imported event {i+1}: {event.get('title')}")
except Exception as e:
print(f" ❌ Failed to import event {i+1}: {e}")
print(f" Title: {event.get('title')}")
continue
# Commit all changes
conn.commit()
print("✅ Migration completed!")
# Show final results
cur.execute("SELECT COUNT(*) FROM bulletins")
bulletin_count = cur.fetchone()[0]
cur.execute("SELECT COUNT(*) FROM events")
event_count = cur.fetchone()[0]
print(f"📊 Final Results:")
print(f" Bulletins: {bulletin_count}")
print(f" Events: {event_count}")
# Show sample data
print(f"\n📄 Sample bulletins:")
cur.execute("SELECT title, date FROM bulletins ORDER BY date DESC LIMIT 3")
for row in cur.fetchall():
print(f" - {row[0]} ({row[1]})")
print(f"\n📅 Sample events:")
cur.execute("SELECT title, start_time FROM events ORDER BY start_time LIMIT 3")
for row in cur.fetchall():
print(f" - {row[0]} ({row[1]})")
cur.close()
conn.close()