#!/usr/bin/env python3 """ Script to identify and fix orphaned users (users without accounts). This script will: 1. Find all users with account = NULL 2. For each user, either: - Assign them to an existing account if possible - Create a new account for them - Delete them if they're test/invalid users 3. Report the results Run this from backend directory: python3 fix_orphaned_users.py """ import os import sys import django # Setup Django os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings') django.setup() from igny8_core.auth.models import User, Account, Plan from django.db import transaction def main(): print("=" * 80) print("ORPHANED USERS FIX SCRIPT") print("=" * 80) # Find users without accounts orphaned_users = User.objects.filter(account__isnull=True) count = orphaned_users.count() print(f"\nFound {count} user(s) without accounts:\n") if count == 0: print("✅ No orphaned users found. System is healthy!") return # List them for i, user in enumerate(orphaned_users, 1): print(f"{i}. ID: {user.id}") print(f" Email: {user.email}") print(f" Username: {user.username}") print(f" Role: {user.role}") print(f" Active: {user.is_active}") print(f" Superuser: {user.is_superuser}") print(f" Created: {user.created_at}") print() # Ask what to do print("\nOptions:") print("1. Auto-fix: Create accounts for all orphaned users") print("2. Delete all orphaned users") print("3. Exit without changes") choice = input("\nEnter choice (1-3): ").strip() if choice == '1': auto_fix_users(orphaned_users) elif choice == '2': delete_users(orphaned_users) else: print("\n❌ No changes made. Exiting.") def auto_fix_users(users): """Create accounts for orphaned users""" print("\n" + "=" * 80) print("AUTO-FIXING ORPHANED USERS") print("=" * 80 + "\n") # Get or create free plan try: free_plan = Plan.objects.get(slug='free', is_active=True) except Plan.DoesNotExist: print("❌ ERROR: Free plan not found. Cannot create accounts.") print(" Please create a 'free' plan first or assign users manually.") return fixed_count = 0 with transaction.atomic(): for user in users: try: # Generate account name if user.first_name or user.last_name: account_name = f"{user.first_name} {user.last_name}".strip() else: account_name = user.email.split('@')[0] # Generate unique slug base_slug = account_name.lower().replace(' ', '-').replace('_', '-')[:50] or 'account' slug = base_slug counter = 1 while Account.objects.filter(slug=slug).exists(): slug = f"{base_slug}-{counter}" counter += 1 # Create account account = Account.objects.create( name=account_name, slug=slug, owner=user, plan=free_plan, credits=free_plan.get_effective_credits_per_month(), status='trial', billing_email=user.email, ) # Assign account to user user.account = account user.save() print(f"✅ Fixed user: {user.email}") print(f" Created account: {account.name} (ID: {account.id})") print(f" Credits: {account.credits}") print() fixed_count += 1 except Exception as e: print(f"❌ ERROR fixing user {user.email}: {e}") print() print("=" * 80) print(f"✅ Successfully fixed {fixed_count} user(s)") print("=" * 80) def delete_users(users): """Delete orphaned users""" print("\n⚠️ WARNING: This will permanently delete the selected users!") confirm = input("Type 'DELETE' to confirm: ").strip() if confirm != 'DELETE': print("\n❌ Deletion cancelled.") return count = users.count() users.delete() print(f"\n✅ Deleted {count} user(s)") if __name__ == '__main__': main()