mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-02 18:29:26 -05:00
d9dab3a49c
- Add organized screenshot sections for better visual presentation - Include all 12 available screenshots from assets/screenshots/ - Group screenshots into logical categories: * Core Application Views (Dashboard, Projects, Tasks, Clients) * Management & Analytics (Reports, Visual Analytics, Task Management, Admin) * Data Entry & Creation (Log Time, New Task, New Client, New Project) - Improve visual layout with proper spacing and responsive design - Enhance user experience by showcasing full application capabilities
162 lines
5.4 KiB
Python
162 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Migration Management Script for TimeTracker
|
|
This script helps manage the transition from custom migrations to Flask-Migrate
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
def run_command(command, description):
|
|
"""Run a command and handle errors"""
|
|
print(f"\n--- {description} ---")
|
|
print(f"Running: {command}")
|
|
|
|
try:
|
|
result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
|
|
print(f"✓ {description} completed successfully")
|
|
if result.stdout:
|
|
print(result.stdout)
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"✗ {description} failed:")
|
|
print(f"Error code: {e.returncode}")
|
|
if e.stdout:
|
|
print(f"STDOUT: {e.stdout}")
|
|
if e.stderr:
|
|
print(f"STDERR: {e.stderr}")
|
|
return False
|
|
|
|
def check_flask_migrate_installed():
|
|
"""Check if Flask-Migrate is properly installed"""
|
|
try:
|
|
import flask_migrate
|
|
print("✓ Flask-Migrate is installed")
|
|
return True
|
|
except ImportError:
|
|
print("✗ Flask-Migrate is not installed")
|
|
print("Please install it with: pip install Flask-Migrate")
|
|
return False
|
|
|
|
def initialize_migrations():
|
|
"""Initialize Flask-Migrate if not already initialized"""
|
|
migrations_dir = Path("migrations")
|
|
|
|
if not migrations_dir.exists():
|
|
print("Initializing Flask-Migrate...")
|
|
return run_command("flask db init", "Initialize Flask-Migrate")
|
|
else:
|
|
print("✓ Migrations directory already exists")
|
|
return True
|
|
|
|
def create_initial_migration():
|
|
"""Create the initial migration if it doesn't exist"""
|
|
versions_dir = Path("migrations/versions")
|
|
|
|
if not versions_dir.exists() or not list(versions_dir.glob("*.py")):
|
|
print("Creating initial migration...")
|
|
return run_command("flask db migrate -m 'Initial database schema'", "Create initial migration")
|
|
else:
|
|
print("✓ Initial migration already exists")
|
|
return True
|
|
|
|
def apply_migrations():
|
|
"""Apply all pending migrations"""
|
|
return run_command("flask db upgrade", "Apply database migrations")
|
|
|
|
def show_migration_status():
|
|
"""Show current migration status"""
|
|
return run_command("flask db current", "Show current migration")
|
|
|
|
def show_migration_history():
|
|
"""Show migration history"""
|
|
return run_command("flask db history", "Show migration history")
|
|
|
|
def backup_database():
|
|
"""Create a backup of the current database"""
|
|
print("\n--- Creating Database Backup ---")
|
|
|
|
# Check if we're using PostgreSQL or SQLite
|
|
db_url = os.getenv('DATABASE_URL', '')
|
|
|
|
if db_url.startswith('postgresql'):
|
|
print("PostgreSQL database detected")
|
|
backup_cmd = "pg_dump --format=custom --dbname=\"$DATABASE_URL\" --file=backup_$(date +%Y%m%d_%H%M%S).dump"
|
|
print(f"Please run: {backup_cmd}")
|
|
return True
|
|
else:
|
|
print("SQLite database detected")
|
|
# For SQLite, we'll just copy the file
|
|
if os.path.exists('instance/timetracker.db'):
|
|
import shutil
|
|
from datetime import datetime
|
|
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
|
backup_file = f"backup_timetracker_{timestamp}.db"
|
|
shutil.copy2('instance/timetracker.db', backup_file)
|
|
print(f"✓ Database backed up to: {backup_file}")
|
|
return True
|
|
else:
|
|
print("SQLite database file not found")
|
|
return False
|
|
|
|
def main():
|
|
"""Main migration management function"""
|
|
print("=== TimeTracker Migration Management ===")
|
|
print("This script will help you transition to Flask-Migrate")
|
|
|
|
# Check prerequisites
|
|
if not check_flask_migrate_installed():
|
|
sys.exit(1)
|
|
|
|
# Create backup
|
|
print("\n⚠️ IMPORTANT: Creating database backup before proceeding...")
|
|
if not backup_database():
|
|
print("Failed to create backup. Please create one manually before proceeding.")
|
|
response = input("Continue anyway? (y/N): ")
|
|
if response.lower() != 'y':
|
|
print("Migration cancelled.")
|
|
sys.exit(1)
|
|
|
|
# Initialize migrations
|
|
if not initialize_migrations():
|
|
print("Failed to initialize migrations")
|
|
sys.exit(1)
|
|
|
|
# Create initial migration
|
|
if not create_initial_migration():
|
|
print("Failed to create initial migration")
|
|
sys.exit(1)
|
|
|
|
# Show current status
|
|
show_migration_status()
|
|
|
|
# Apply migrations
|
|
print("\n⚠️ About to apply migrations to your database...")
|
|
response = input("Continue? (y/N): ")
|
|
if response.lower() != 'y':
|
|
print("Migration cancelled. You can run 'flask db upgrade' manually later.")
|
|
return
|
|
|
|
if not apply_migrations():
|
|
print("Failed to apply migrations")
|
|
sys.exit(1)
|
|
|
|
# Show final status
|
|
print("\n=== Migration Complete ===")
|
|
show_migration_status()
|
|
show_migration_history()
|
|
|
|
print("\n🎉 Migration to Flask-Migrate completed successfully!")
|
|
print("\nNext steps:")
|
|
print("1. Test your application to ensure everything works")
|
|
print("2. For future schema changes, use:")
|
|
print(" - flask db migrate -m 'Description of changes'")
|
|
print(" - flask db upgrade")
|
|
print("3. To rollback: flask db downgrade")
|
|
print("4. To check status: flask db current")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|