Files
TimeTrack/migrate_freelancers.py
2025-07-02 23:11:27 +02:00

172 lines
5.8 KiB
Python

#!/usr/bin/env python3
"""
Migration script for freelancer support in TimeTrack.
This migration adds:
1. AccountType enum support (handled by SQLAlchemy)
2. account_type column to user table
3. business_name column to user table
4. is_personal column to company table
Usage:
python migrate_freelancers.py # Run migration
python migrate_freelancers.py rollback # Rollback migration
"""
from app import app, db
import sqlite3
import os
import sys
from models import User, Company, AccountType
from datetime import datetime
def migrate_freelancer_support():
"""Add freelancer support to existing database"""
db_path = 'timetrack.db'
# Check if database exists
if not os.path.exists(db_path):
print("Database doesn't exist. Please run main migration first.")
return False
print("Migrating database for freelancer support...")
# Connect to the database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
try:
# Check company table structure
cursor.execute("PRAGMA table_info(company)")
company_columns = [column[1] for column in cursor.fetchall()]
# Add is_personal column to company table if it doesn't exist
if 'is_personal' not in company_columns:
print("Adding is_personal column to company table...")
cursor.execute("ALTER TABLE company ADD COLUMN is_personal BOOLEAN DEFAULT 0")
# Check user table structure
cursor.execute("PRAGMA table_info(user)")
user_columns = [column[1] for column in cursor.fetchall()]
# Add account_type column to user table if it doesn't exist
if 'account_type' not in user_columns:
print("Adding account_type column to user table...")
# Default to 'COMPANY_USER' for existing users
cursor.execute("ALTER TABLE user ADD COLUMN account_type VARCHAR(20) DEFAULT 'COMPANY_USER'")
# Add business_name column to user table if it doesn't exist
if 'business_name' not in user_columns:
print("Adding business_name column to user table...")
cursor.execute("ALTER TABLE user ADD COLUMN business_name VARCHAR(100)")
# Commit changes
conn.commit()
print("✓ Freelancer migration completed successfully!")
# Update existing users to have explicit account_type
print("Updating existing users to COMPANY_USER account type...")
cursor.execute("UPDATE user SET account_type = 'COMPANY_USER' WHERE account_type IS NULL OR account_type = ''")
conn.commit()
return True
except Exception as e:
print(f"✗ Migration failed: {str(e)}")
conn.rollback()
return False
finally:
conn.close()
def rollback_freelancer_support():
"""Rollback freelancer support migration"""
db_path = 'timetrack.db'
if not os.path.exists(db_path):
print("Database doesn't exist.")
return False
print("Rolling back freelancer support migration...")
# Connect to the database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
try:
print("WARNING: SQLite doesn't support dropping columns directly.")
print("To fully rollback, you would need to:")
print("1. Create new tables without the freelancer columns")
print("2. Copy data from old tables to new tables")
print("3. Drop old tables and rename new ones")
print("\nFor safety, leaving columns in place but marking rollback as complete.")
print("The application will work without issues with the extra columns present.")
return True
except Exception as e:
print(f"✗ Rollback failed: {str(e)}")
return False
finally:
conn.close()
def verify_migration():
"""Verify that the migration was applied correctly"""
db_path = 'timetrack.db'
if not os.path.exists(db_path):
print("Database doesn't exist.")
return False
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
try:
# Check company table
cursor.execute("PRAGMA table_info(company)")
company_columns = [column[1] for column in cursor.fetchall()]
# Check user table
cursor.execute("PRAGMA table_info(user)")
user_columns = [column[1] for column in cursor.fetchall()]
print("\n=== Migration Verification ===")
print("Company table columns:", company_columns)
print("User table columns:", user_columns)
# Verify required columns exist
missing_columns = []
if 'is_personal' not in company_columns:
missing_columns.append('company.is_personal')
if 'account_type' not in user_columns:
missing_columns.append('user.account_type')
if 'business_name' not in user_columns:
missing_columns.append('user.business_name')
if missing_columns:
print(f"✗ Missing columns: {', '.join(missing_columns)}")
return False
else:
print("✓ All required columns present")
return True
except Exception as e:
print(f"✗ Verification failed: {str(e)}")
return False
finally:
conn.close()
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == 'rollback':
success = rollback_freelancer_support()
elif len(sys.argv) > 1 and sys.argv[1] == 'verify':
success = verify_migration()
else:
success = migrate_freelancer_support()
if success:
verify_migration()
if success:
print("\n✓ Operation completed successfully!")
else:
print("\n✗ Operation failed!")
sys.exit(1)