#!/usr/bin/env python3 """ First-run initialization script. Creates the admin user and seeds default categories. Run once after `flask db upgrade`. Usage: cd /home/pfm/app source venv/bin/activate python scripts/init_db.py """ import sys import os # Add project root to path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from app import create_app from app.extensions import db from app.models.user import User from app.models.category import Category import getpass app = create_app() DEFAULT_EXPENSE_CATEGORIES = [ ('Housing', 'bi-house', '#6366f1'), ('Food & Dining', 'bi-cup-hot', '#f59e0b'), ('Transport', 'bi-car-front', '#3b82f6'), ('Utilities', 'bi-lightning-charge', '#8b5cf6'), ('Health', 'bi-heart-pulse', '#ef4444'), ('Entertainment', 'bi-controller', '#ec4899'), ('Shopping', 'bi-bag', '#f97316'), ('Education', 'bi-book', '#14b8a6'), ('Insurance', 'bi-shield-check', '#64748b'), ('Personal Care', 'bi-person-heart', '#a78bfa'), ('Travel', 'bi-airplane', '#0ea5e9'), ('Subscriptions', 'bi-repeat', '#84cc16'), ('Gifts', 'bi-gift', '#f43f5e'), ('Other', 'bi-three-dots', '#94a3b8'), ] DEFAULT_INCOME_CATEGORIES = [ ('Salary', 'bi-briefcase', '#10b981'), ('Freelance', 'bi-laptop', '#06b6d4'), ('Business', 'bi-building', '#8b5cf6'), ('Investment', 'bi-graph-up-arrow', '#3b82f6'), ('Rental', 'bi-house-door', '#f59e0b'), ('Gift Received', 'bi-gift', '#ec4899'), ('Other Income', 'bi-three-dots', '#94a3b8'), ] def seed_categories(): print("Seeding categories...") count = 0 for name, icon, color in DEFAULT_EXPENSE_CATEGORIES: if not Category.query.filter_by(name=name, category_type='expense').first(): db.session.add(Category( name=name, icon=icon, color=color, category_type='expense', is_system=True )) count += 1 for name, icon, color in DEFAULT_INCOME_CATEGORIES: if not Category.query.filter_by(name=name, category_type='income').first(): db.session.add(Category( name=name, icon=icon, color=color, category_type='income', is_system=True )) count += 1 db.session.commit() print(f" → {count} categories added.") def create_admin(): print("\nCreate admin user") print("-" * 30) existing = User.query.first() if existing: print(f" User '{existing.username}' already exists. Skipping.") return username = input("Username [admin]: ").strip() or 'admin' display_name = input("Display name (optional): ").strip() or None email = input("Email (optional): ").strip() or None while True: password = getpass.getpass("Password: ") confirm = getpass.getpass("Confirm password: ") if password == confirm and len(password) >= 6: break if password != confirm: print(" Passwords do not match. Try again.") else: print(" Password must be at least 6 characters.") from flask import current_app user = User( username=username, display_name=display_name, email=email, currency=current_app.config.get('APP_CURRENCY', 'USD'), currency_symbol=current_app.config.get('APP_CURRENCY_SYMBOL', '$'), timezone=current_app.config.get('APP_TIMEZONE', 'Asia/Ho_Chi_Minh'), ) user.set_password(password) db.session.add(user) db.session.commit() print(f" → User '{username}' created successfully.") if __name__ == '__main__': with app.app_context(): seed_categories() create_admin() print("\nInit complete. Run the app with: gunicorn wsgi:app")