""" Management command to populate existing staff with random emails and phone numbers """ import random from django.core.management.base import BaseCommand, CommandError from django.db import transaction from django.db.models import Q from apps.organizations.models import Staff class Command(BaseCommand): help = 'Populate existing staff records with random emails and phone numbers' def add_arguments(self, parser): parser.add_argument( '--hospital-code', type=str, help='Target hospital code (default: all hospitals)' ) parser.add_argument( '--email-only', action='store_true', help='Only populate email addresses' ) parser.add_argument( '--phone-only', action='store_true', help='Only populate phone numbers' ) parser.add_argument( '--overwrite', action='store_true', help='Overwrite existing email/phone (default: fill missing only)' ) parser.add_argument( '--dry-run', action='store_true', help='Preview changes without updating database' ) def handle(self, *args, **options): hospital_code = options['hospital_code'] email_only = options['email_only'] phone_only = options['phone_only'] overwrite = options['overwrite'] dry_run = options['dry_run'] self.stdout.write(f"\n{'='*60}") self.stdout.write("Staff Contact Information Populator") self.stdout.write(f"{'='*60}\n") # Base queryset queryset = Staff.objects.all() # Filter by hospital if specified if hospital_code: queryset = queryset.filter(hospital__code__iexact=hospital_code) self.stdout.write(f"Target hospital: {hospital_code}") else: self.stdout.write("Target: All hospitals") # Filter staff needing updates if not overwrite: if email_only: queryset = queryset.filter(Q(email__isnull=True) | Q(email='')) elif phone_only: queryset = queryset.filter(Q(phone__isnull=True) | Q(phone='')) else: # Both email and phone queryset = queryset.filter( Q(email__isnull=True) | Q(email='') | Q(phone__isnull=True) | Q(phone='') ) total_staff = queryset.count() if total_staff == 0: self.stdout.write( self.style.SUCCESS("✓ All staff already have contact information.") ) return self.stdout.write(f"\nFound {total_staff} staff to update") self.stdout.write(f" Email only: {email_only}") self.stdout.write(f" Phone only: {phone_only}") self.stdout.write(f" Overwrite existing: {overwrite}") self.stdout.write(f" Dry run: {dry_run}\n") # Track statistics updated_emails = 0 updated_phones = 0 skipped = 0 with transaction.atomic(): for staff in queryset: update_email = False update_phone = False # Determine which fields to update should_update_email = email_only or (not email_only and not phone_only) should_update_phone = phone_only or (not email_only and not phone_only) # Determine if we should update email if should_update_email: if overwrite or not staff.email or not staff.email.strip(): if not staff.first_name or not staff.last_name: self.stdout.write( self.style.WARNING(f" ⚠ Skipping staff {staff.id}: Missing first/last name") ) skipped += 1 continue update_email = True # Determine if we should update phone if should_update_phone: if overwrite or not staff.phone or not staff.phone.strip(): update_phone = True if not update_email and not update_phone: skipped += 1 continue # Generate new values new_email = None new_phone = None if update_email: new_email = self.generate_email(staff) updated_emails += 1 if update_phone: new_phone = self.generate_phone_number() updated_phones += 1 # Display what will be updated if dry_run: updates = [] if new_email: old_email = staff.email if staff.email else 'None' updates.append(f"email: {old_email} → {new_email}") if new_phone: old_phone = staff.phone if staff.phone else 'None' updates.append(f"phone: {old_phone} → {new_phone}") name = staff.name if staff.name else f"{staff.first_name} {staff.last_name}" self.stdout.write(f" Would update: {name}") for update in updates: self.stdout.write(f" - {update}") else: # Apply updates if new_email: staff.email = new_email if new_phone: staff.phone = new_phone staff.save() name = staff.name if staff.name else f"{staff.first_name} {staff.last_name}" self.stdout.write(f" ✓ Updated: {name}") if new_email: self.stdout.write(f" Email: {new_email}") if new_phone: self.stdout.write(f" Phone: {new_phone}") # Summary self.stdout.write("\n" + "="*60) self.stdout.write("Summary:") self.stdout.write(f" Total staff processed: {total_staff}") self.stdout.write(f" Emails populated: {updated_emails}") self.stdout.write(f" Phone numbers populated: {updated_phones}") self.stdout.write(f" Skipped: {skipped}") self.stdout.write("="*60 + "\n") if dry_run: self.stdout.write(self.style.WARNING("DRY RUN: No changes were made\n")) else: self.stdout.write(self.style.SUCCESS("Contact information populated successfully!\n")) def generate_email(self, staff): """Generate unique email for staff""" # Use staff.name if available, otherwise use first_name + last_name if staff.name and staff.name.strip(): # Try to split name into first and last name_parts = staff.name.strip().split() if len(name_parts) >= 2: first_name = name_parts[0] last_name = name_parts[-1] else: first_name = staff.name.strip() last_name = staff.last_name if staff.last_name else '' else: first_name = staff.first_name if staff.first_name else 'user' last_name = staff.last_name if staff.last_name else 'unknown' # Clean up names for email (remove spaces and special characters) clean_first = ''.join(c.lower() for c in first_name if c.isalnum() or c == ' ') clean_last = ''.join(c.lower() for c in last_name if c.isalnum() or c == ' ') # Get hospital code for domain hospital_code = staff.hospital.code if staff.hospital else 'hospital' hospital_code = hospital_code.lower().replace(' ', '') base = f"{clean_first.replace(' ', '.')}.{clean_last.replace(' ', '.')}" email = f"{base}@{hospital_code}.sa" # Add random suffix if email already exists counter = 1 while Staff.objects.filter(email=email).exists(): random_num = random.randint(1, 999) email = f"{base}{random_num}@{hospital_code}.sa" counter += 1 if counter > 100: # Safety limit break return email def generate_phone_number(self): """Generate random Saudi phone number (+966 5X XXX XXXX)""" # Saudi mobile format: +966 5X XXX XXXX # X is random digit second_digit = random.randint(0, 9) group1 = random.randint(100, 999) group2 = random.randint(100, 999) phone = f"+966 5{second_digit} {group1} {group2}" return phone