Files
foodplanner/migrate_to_dates.py
2025-09-19 15:36:38 -07:00

128 lines
4.1 KiB
Python

#!/usr/bin/env python3
"""
Migration script to convert Plan.date from String to Date type
and convert existing "DayX" values to actual calendar dates.
"""
import sqlite3
from datetime import datetime, timedelta
def migrate_plans_to_dates():
"""Convert existing DayX plans to actual dates"""
# Connect to database
conn = sqlite3.connect('meal_planner.db')
cursor = conn.cursor()
try:
# Check if migration is needed
cursor.execute("PRAGMA table_info(plans)")
columns = cursor.fetchall()
date_column_type = None
for col in columns:
if col[1] == 'date': # column name
date_column_type = col[2] # column type
break
if date_column_type and 'DATE' in date_column_type.upper():
print("Migration already completed - date column is already DATE type")
return
print("Starting migration from String to Date...")
# Create backup
print("Creating backup of plans table...")
cursor.execute("""
CREATE TABLE plans_backup AS
SELECT * FROM plans
""")
# Add new date column
print("Adding new date column...")
cursor.execute("""
ALTER TABLE plans ADD COLUMN date_new DATE
""")
# Convert DayX to actual dates (starting from today as Day1)
print("Converting DayX values to dates...")
today = datetime.now().date()
# Get all unique day values
cursor.execute("SELECT DISTINCT date FROM plans WHERE date LIKE 'Day%'")
day_values = cursor.fetchall()
for (day_str,) in day_values:
if day_str.startswith('Day'):
try:
day_num = int(day_str[3:]) # Extract number from "Day1", "Day2", etc.
# Convert to date (Day1 = today, Day2 = tomorrow, etc.)
actual_date = today + timedelta(days=day_num - 1)
cursor.execute("""
UPDATE plans
SET date_new = ?
WHERE date = ?
""", (actual_date.isoformat(), day_str))
print(f"Converted {day_str} to {actual_date.isoformat()}")
except (ValueError, IndexError) as e:
print(f"Error converting {day_str}: {e}")
# Handle any non-DayX dates (if they exist)
cursor.execute("""
UPDATE plans
SET date_new = date
WHERE date NOT LIKE 'Day%' AND date_new IS NULL
""")
# Recreate table with new structure (SQLite doesn't support DROP COLUMN with indexes)
print("Recreating table with new structure...")
cursor.execute("""
CREATE TABLE plans_new (
id INTEGER PRIMARY KEY,
person VARCHAR NOT NULL,
date DATE NOT NULL,
meal_id INTEGER NOT NULL REFERENCES meals(id)
)
""")
# Copy data to new table
cursor.execute("""
INSERT INTO plans_new (id, person, date, meal_id)
SELECT id, person, date_new, meal_id FROM plans
""")
# Drop old table and rename new one
cursor.execute("DROP TABLE plans")
cursor.execute("ALTER TABLE plans_new RENAME TO plans")
# Create index on new date column
cursor.execute("CREATE INDEX ix_plans_date ON plans(date)")
conn.commit()
print("Migration completed successfully!")
# Show summary
cursor.execute("SELECT COUNT(*) FROM plans")
total_plans = cursor.fetchone()[0]
print(f"Total plans migrated: {total_plans}")
except Exception as e:
print(f"Migration failed: {e}")
conn.rollback()
# Restore backup if something went wrong
try:
cursor.execute("DROP TABLE IF EXISTS plans")
cursor.execute("ALTER TABLE plans_backup RENAME TO plans")
print("Restored from backup")
except Exception as backup_error:
print(f"Failed to restore backup: {backup_error}")
finally:
conn.close()
if __name__ == "__main__":
migrate_plans_to_dates()