Spaces:
Sleeping
Sleeping
| import os | |
| import bcrypt | |
| from datetime import datetime | |
| from sqlalchemy import text, inspect | |
| from database import engine | |
| def run_migrations(): | |
| print("Running database migrations...") | |
| run_engine_migrations(engine) | |
| def run_db_migrations(engine_param): | |
| print("Running SQLAlchemy engine migrations...") | |
| run_engine_migrations(engine_param) | |
| def run_engine_migrations(engine): | |
| # Get database inspector | |
| inspector = inspect(engine) | |
| # 0. Seed default user if not exists (in users table) | |
| if "users" in inspector.get_table_names(): | |
| try: | |
| with engine.connect() as conn: | |
| result = conn.execute(text("SELECT id FROM users WHERE id = 1")).fetchone() | |
| if not result: | |
| hashed_pass = bcrypt.hashpw(b"admin123", bcrypt.gensalt()).decode('utf-8') | |
| conn.execute( | |
| text("INSERT INTO users (id, email, hashed_password, company_name, created_at) VALUES (1, :email, :password, :company, :created)"), | |
| { | |
| "email": "admin@founder.os", | |
| "password": hashed_pass, | |
| "company": "Erha Technologies", | |
| "created": datetime.utcnow() | |
| } | |
| ) | |
| conn.commit() | |
| print("Migration: Inserted default admin user.") | |
| except Exception as e: | |
| print(f"Error seeding default user: {e}") | |
| # 1. Migrate clients table | |
| if "clients" in inspector.get_table_names(): | |
| columns_clients = [c['name'] for c in inspector.get_columns('clients')] | |
| migrations_clients = [ | |
| ("description", "TEXT"), | |
| ("is_active", "BOOLEAN DEFAULT TRUE"), | |
| ("advance_payment", "FLOAT DEFAULT 0.0"), | |
| ("remaining_payment", "FLOAT DEFAULT 0.0"), | |
| ("joining_date", "TIMESTAMP"), | |
| ("company", "VARCHAR(255)"), | |
| ("address", "TEXT") | |
| ] | |
| for col_name, col_type in migrations_clients: | |
| if col_name not in columns_clients: | |
| try: | |
| with engine.begin() as conn: | |
| conn.execute(text(f"ALTER TABLE clients ADD COLUMN {col_name} {col_type}")) | |
| print(f"Migration: Added column '{col_name}' ({col_type}) to 'clients' table.") | |
| except Exception as e: | |
| print(f"Error adding '{col_name}' to 'clients': {e}") | |
| # 2. Migrate employees table | |
| if "employees" in inspector.get_table_names(): | |
| columns_employees = [c['name'] for c in inspector.get_columns('employees')] | |
| migrations_employees = [ | |
| ("bank_account_number", "VARCHAR(255)"), | |
| ("bank_name", "VARCHAR(255)"), | |
| ("account_title", "VARCHAR(255)"), | |
| ("starting_salary", "FLOAT DEFAULT 0.0") | |
| ] | |
| for col_name, col_type in migrations_employees: | |
| if col_name not in columns_employees: | |
| try: | |
| with engine.begin() as conn: | |
| conn.execute(text(f"ALTER TABLE employees ADD COLUMN {col_name} {col_type}")) | |
| print(f"Migration: Added column '{col_name}' ({col_type}) to 'employees' table.") | |
| if col_name == "starting_salary": | |
| with engine.begin() as conn: | |
| conn.execute(text("UPDATE employees SET starting_salary = base_salary WHERE starting_salary IS NULL OR starting_salary = 0.0")) | |
| except Exception as e: | |
| print(f"Error adding '{col_name}' to 'employees': {e}") | |
| # 3. Add user_id column to all entity tables for multi-tenancy | |
| tables_to_migrate = ["clients", "employees", "bank_accounts", "invoices", "payroll", "revenues", "expenses", "security_config", "personal_expenses"] | |
| for table in tables_to_migrate: | |
| if table in inspector.get_table_names(): | |
| columns = [c['name'] for c in inspector.get_columns(table)] | |
| if "user_id" not in columns: | |
| try: | |
| with engine.begin() as conn: | |
| conn.execute(text(f"ALTER TABLE {table} ADD COLUMN user_id INTEGER DEFAULT 1")) | |
| print(f"Migration: Added 'user_id' column to '{table}' table.") | |
| except Exception as e: | |
| print(f"Error adding 'user_id' to '{table}': {e}") | |
| # 4. Add employee_id, payroll_id and created_at columns to expenses table | |
| if "expenses" in inspector.get_table_names(): | |
| columns_expenses = [c['name'] for c in inspector.get_columns('expenses')] | |
| migrations_expenses = [ | |
| ("employee_id", "INTEGER"), | |
| ("payroll_id", "INTEGER"), | |
| ("created_at", "TIMESTAMP"), | |
| ("target_month", "VARCHAR(50)"), | |
| ("target_year", "INTEGER") | |
| ] | |
| for col_name, col_type in migrations_expenses: | |
| if col_name not in columns_expenses: | |
| try: | |
| with engine.begin() as conn: | |
| conn.execute(text(f"ALTER TABLE expenses ADD COLUMN {col_name} {col_type}")) | |
| print(f"Migration: Added column '{col_name}' ({col_type}) to 'expenses' table.") | |
| except Exception as e: | |
| print(f"Error adding '{col_name}' to 'expenses': {e}") | |
| # 5. Add invoice_id, payroll_id, expense_id, revenue_id columns to transactions table | |
| if "transactions" in inspector.get_table_names(): | |
| columns_txn = [c['name'] for c in inspector.get_columns('transactions')] | |
| migrations_tx = [ | |
| ("invoice_id", "INTEGER"), | |
| ("payroll_id", "INTEGER"), | |
| ("expense_id", "INTEGER"), | |
| ("revenue_id", "INTEGER") | |
| ] | |
| for col_name, col_type in migrations_tx: | |
| if col_name not in columns_txn: | |
| try: | |
| with engine.begin() as conn: | |
| conn.execute(text(f"ALTER TABLE transactions ADD COLUMN {col_name} {col_type}")) | |
| print(f"Migration: Added column '{col_name}' ({col_type}) to 'transactions' table.") | |
| except Exception as e: | |
| print(f"Error adding '{col_name}' to 'transactions': {e}") | |
| # 6. Migrate salary_increments table | |
| if "salary_increments" in inspector.get_table_names(): | |
| columns_inc = [c['name'] for c in inspector.get_columns('salary_increments')] | |
| migrations_inc = [ | |
| ("old_salary", "FLOAT DEFAULT 0.0"), | |
| ("new_salary", "FLOAT DEFAULT 0.0"), | |
| ("increment_amount", "FLOAT DEFAULT 0.0"), | |
| ("date", "TIMESTAMP") | |
| ] | |
| for col_name, col_type in migrations_inc: | |
| if col_name not in columns_inc: | |
| try: | |
| with engine.begin() as conn: | |
| conn.execute(text(f"ALTER TABLE salary_increments ADD COLUMN {col_name} {col_type}")) | |
| print(f"Migration: Added column '{col_name}' ({col_type}) to 'salary_increments' table.") | |
| except Exception as e: | |
| print(f"Error adding '{col_name}' to 'salary_increments': {e}") | |
| print("Migrations completed successfully.") | |
| if __name__ == "__main__": | |
| run_migrations() |