mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-05 19:20:21 -06:00
- Remove redundant documentation files (DATABASE_INIT_FIX_*.md, TIMEZONE_FIX_README.md) - Delete unused Docker files (Dockerfile.test, Dockerfile.combined, docker-compose.yml) - Remove obsolete deployment scripts (deploy.sh) and unused files (index.html, _config.yml) - Clean up logs directory (remove 2MB timetracker.log, keep .gitkeep) - Remove .pytest_cache directory - Consolidate Docker setup to two main container types: * Simple container (recommended for production) * Public container (for development/testing) - Enhance timezone support in admin settings: * Add 100+ timezone options organized by region * Implement real-time timezone preview with current time display * Add timezone offset calculation and display * Remove search functionality for cleaner interface * Update timezone utility functions for database-driven configuration - Update documentation: * Revise README.md to reflect current project state * Add comprehensive timezone features documentation * Update Docker deployment instructions * Create PROJECT_STRUCTURE.md for project overview * Remove references to deleted files - Improve project structure: * Streamlined file organization * Better maintainability and focus * Preserved all essential functionality * Cleaner deployment options
166 lines
5.7 KiB
Python
166 lines
5.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Migration script to rename database fields from start_utc/end_utc to start_time/end_time
|
|
This script should be run after updating the application code but before starting the new version.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
from sqlalchemy import create_engine, text, inspect
|
|
|
|
def wait_for_database(url, max_attempts=30, delay=2):
|
|
"""Wait for database to be ready"""
|
|
print(f"Waiting for database to be ready...")
|
|
|
|
for attempt in range(max_attempts):
|
|
try:
|
|
engine = create_engine(url, pool_pre_ping=True)
|
|
with engine.connect() as conn:
|
|
conn.execute(text("SELECT 1"))
|
|
print("Database connection established successfully")
|
|
return engine
|
|
except Exception as e:
|
|
print(f"Waiting for database... (attempt {attempt+1}/{max_attempts}): {e}")
|
|
if attempt < max_attempts - 1:
|
|
time.sleep(delay)
|
|
else:
|
|
print("Database not ready after waiting, exiting...")
|
|
sys.exit(1)
|
|
|
|
return None
|
|
|
|
def check_migration_needed(engine):
|
|
"""Check if migration is needed"""
|
|
print("Checking if migration is needed...")
|
|
|
|
try:
|
|
inspector = inspect(engine)
|
|
columns = inspector.get_columns('time_entries')
|
|
column_names = [col['name'] for col in columns]
|
|
|
|
has_old_fields = 'start_utc' in column_names or 'end_utc' in column_names
|
|
has_new_fields = 'start_time' in column_names or 'end_time' in column_names
|
|
|
|
if has_old_fields and not has_new_fields:
|
|
print("✓ Migration needed: old field names detected")
|
|
return True
|
|
elif has_new_fields and not has_old_fields:
|
|
print("✓ Migration not needed: new field names already exist")
|
|
return False
|
|
elif has_old_fields and has_new_fields:
|
|
print("⚠ Migration partially done: both old and new field names exist")
|
|
return True
|
|
else:
|
|
print("⚠ Unknown state: neither old nor new field names found")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ Error checking migration status: {e}")
|
|
return True
|
|
|
|
def migrate_database(engine):
|
|
"""Perform the migration"""
|
|
print("Starting database migration...")
|
|
|
|
try:
|
|
with engine.connect() as conn:
|
|
# Start transaction
|
|
trans = conn.begin()
|
|
|
|
try:
|
|
# Check if old columns exist
|
|
inspector = inspect(engine)
|
|
columns = inspector.get_columns('time_entries')
|
|
column_names = [col['name'] for col in columns]
|
|
|
|
if 'start_utc' in column_names:
|
|
print("Renaming start_utc to start_time...")
|
|
conn.execute(text("ALTER TABLE time_entries RENAME COLUMN start_utc TO start_time"))
|
|
|
|
if 'end_utc' in column_names:
|
|
print("Renaming end_utc to end_time...")
|
|
conn.execute(text("ALTER TABLE time_entries RENAME COLUMN end_utc TO end_time"))
|
|
|
|
# Update indexes
|
|
print("Updating indexes...")
|
|
|
|
# Drop old index if it exists
|
|
try:
|
|
conn.execute(text("DROP INDEX IF EXISTS idx_time_entries_start_utc"))
|
|
except:
|
|
pass
|
|
|
|
# Create new index
|
|
conn.execute(text("CREATE INDEX IF NOT EXISTS idx_time_entries_start_time ON time_entries(start_time)"))
|
|
|
|
# Commit transaction
|
|
trans.commit()
|
|
print("✓ Migration completed successfully")
|
|
return True
|
|
|
|
except Exception as e:
|
|
trans.rollback()
|
|
print(f"✗ Migration failed: {e}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ Error during migration: {e}")
|
|
return False
|
|
|
|
def verify_migration(engine):
|
|
"""Verify the migration was successful"""
|
|
print("Verifying migration...")
|
|
|
|
try:
|
|
inspector = inspect(engine)
|
|
columns = inspector.get_columns('time_entries')
|
|
column_names = [col['name'] for col in columns]
|
|
|
|
has_new_fields = 'start_time' in column_names and 'end_time' in column_names
|
|
has_old_fields = 'start_utc' in column_names or 'end_utc' in column_names
|
|
|
|
if has_new_fields and not has_old_fields:
|
|
print("✓ Migration verified: new field names are present, old ones are gone")
|
|
return True
|
|
else:
|
|
print(f"✗ Migration verification failed: new fields: {has_new_fields}, old fields: {has_old_fields}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ Error verifying migration: {e}")
|
|
return False
|
|
|
|
def main():
|
|
"""Main function"""
|
|
url = os.getenv("DATABASE_URL", "")
|
|
|
|
if not url.startswith("postgresql"):
|
|
print("No PostgreSQL database configured, skipping migration")
|
|
return
|
|
|
|
print(f"Database URL: {url}")
|
|
|
|
# Wait for database to be ready
|
|
engine = wait_for_database(url)
|
|
|
|
# Check if migration is needed
|
|
if not check_migration_needed(engine):
|
|
print("No migration needed, exiting...")
|
|
return
|
|
|
|
# Perform migration
|
|
if not migrate_database(engine):
|
|
print("Migration failed, exiting...")
|
|
sys.exit(1)
|
|
|
|
# Verify migration
|
|
if not verify_migration(engine):
|
|
print("Migration verification failed, exiting...")
|
|
sys.exit(1)
|
|
|
|
print("✓ Database migration completed successfully!")
|
|
|
|
if __name__ == "__main__":
|
|
import time
|
|
main()
|