#!/usr/bin/env python3
"""
One-time migration to copy royal_assent to royal_assent_date for existing bills.
This fixes a field name mismatch where:
- Ingestion was writing to: royal_assent
- Frontend was reading from: royal_assent_date
Run this once against production to sync the data.
"""
import os
import sys
from pathlib import Path
# Add packages to path
SCRIPT_DIR = Path(__file__).parent
PIPELINE_DIR = SCRIPT_DIR.parent
sys.path.insert(0, str(PIPELINE_DIR))
from fedmcp_pipeline.utils.neo4j_client import Neo4jClient
from fedmcp_pipeline.utils.config import Config
from fedmcp_pipeline.utils.progress import logger
def migrate_royal_assent_field(neo4j_client: Neo4jClient) -> dict:
"""
Copy royal_assent to royal_assent_date for bills where:
- royal_assent is set
- royal_assent_date is not set
Returns dict with migration stats.
"""
logger.info("Checking for bills that need migration...")
# First, count how many need migration
count_query = """
MATCH (b:Bill)
WHERE b.royal_assent IS NOT NULL AND b.royal_assent_date IS NULL
RETURN count(b) as count
"""
result = neo4j_client.run_query(count_query)
needs_migration = result[0]["count"] if result else 0
logger.info(f"Found {needs_migration} bills that need migration")
if needs_migration == 0:
logger.info("No migration needed - all bills already have royal_assent_date set")
return {"migrated": 0, "already_set": 0}
# Perform the migration
migrate_query = """
MATCH (b:Bill)
WHERE b.royal_assent IS NOT NULL AND b.royal_assent_date IS NULL
SET b.royal_assent_date = b.royal_assent
RETURN count(b) as migrated
"""
result = neo4j_client.run_query(migrate_query)
migrated = result[0]["migrated"] if result else 0
logger.success(f"✅ Migrated {migrated} bills: copied royal_assent → royal_assent_date")
# Also count how many already had royal_assent_date set
already_set_query = """
MATCH (b:Bill)
WHERE b.royal_assent_date IS NOT NULL
RETURN count(b) as count
"""
result = neo4j_client.run_query(already_set_query)
total_with_date = result[0]["count"] if result else 0
logger.info(f"Total bills with royal_assent_date: {total_with_date}")
return {
"migrated": migrated,
"total_with_royal_assent_date": total_with_date
}
def main():
"""Main entry point."""
logger.info("=" * 60)
logger.info("MIGRATION: royal_assent → royal_assent_date")
logger.info("=" * 60)
# Load config from environment or .env file
config = Config()
# Connect to Neo4j
neo4j_client = Neo4jClient(
uri=config.neo4j_uri,
user=config.neo4j_user,
password=config.neo4j_password
)
try:
stats = migrate_royal_assent_field(neo4j_client)
logger.info("=" * 60)
logger.success("Migration complete!")
logger.info(f"Bills migrated: {stats['migrated']}")
logger.info(f"Total with royal_assent_date: {stats['total_with_royal_assent_date']}")
logger.info("=" * 60)
return 0
except Exception as e:
logger.error(f"Migration failed: {e}")
import traceback
traceback.print_exc()
return 1
finally:
neo4j_client.close()
if __name__ == "__main__":
exit(main())