hospital-management/patients/management/commands/populate_saudi_insurance.py
Marwan Alwali 610e165e17 update
2025-09-04 19:19:52 +03:00

229 lines
9.4 KiB
Python

"""
Django management command to populate Saudi insurance providers and create sample patients.
Usage:
python manage.py populate_saudi_insurance --tenant-id 1
python manage.py populate_saudi_insurance --create-patients 50
"""
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth import get_user_model
from django.db import transaction
from django.utils import timezone
from patients.models import PatientProfile, InsuranceInfo
from patients.data_generators.saudi_claims_generator import SaudiClaimsDataGenerator
from core.models import Tenant
import random
from datetime import datetime, timedelta
User = get_user_model()
class Command(BaseCommand):
help = 'Populate Saudi insurance providers and create sample patients with insurance'
def add_arguments(self, parser):
parser.add_argument(
'--tenant-id',
type=int,
required=True,
help='Tenant ID to create data for'
)
parser.add_argument(
'--create-patients',
type=int,
default=20,
help='Number of patients to create (default: 20)'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='Show what would be created without creating records'
)
def handle(self, *args, **options):
"""Main command handler."""
try:
# Get tenant
tenant = Tenant.objects.get(id=options['tenant_id'])
if options['dry_run']:
self._dry_run(tenant, options)
else:
self._create_data(tenant, options)
except Tenant.DoesNotExist:
raise CommandError(f"Tenant with ID {options['tenant_id']} not found")
except Exception as e:
raise CommandError(f"Error: {str(e)}")
def _dry_run(self, tenant, options):
"""Show what would be created."""
self.stdout.write(
self.style.WARNING("DRY RUN - No records will be created")
)
generator = SaudiClaimsDataGenerator()
self.stdout.write(f"\nWould create for tenant: {tenant.name}")
self.stdout.write(f"Number of patients: {options['create_patients']}")
self.stdout.write(f"Insurance companies available: {len(generator.SAUDI_INSURANCE_COMPANIES)}")
# Show sample data
self.stdout.write(f"\nSample insurance companies:")
for company in generator.SAUDI_INSURANCE_COMPANIES[:5]:
self.stdout.write(f" - {company}")
self.stdout.write(f"\nSample patient names:")
for i in range(3):
male_name = f"{random.choice(generator.SAUDI_FIRST_NAMES_MALE)} {random.choice(generator.SAUDI_FAMILY_NAMES)}"
female_name = f"{random.choice(generator.SAUDI_FIRST_NAMES_FEMALE)} {random.choice(generator.SAUDI_FAMILY_NAMES)}"
self.stdout.write(f" - {male_name}")
self.stdout.write(f" - {female_name}")
def _create_data(self, tenant, options):
"""Create the actual data."""
generator = SaudiClaimsDataGenerator()
created_by = self._get_system_user()
self.stdout.write(f"Creating data for tenant: {tenant.name}")
patients_created = 0
insurance_created = 0
with transaction.atomic():
# Create patients with insurance
for i in range(options['create_patients']):
try:
# Generate patient data
is_male = random.choice([True, False])
if is_male:
first_name = random.choice(generator.SAUDI_FIRST_NAMES_MALE)
gender = 'M'
else:
first_name = random.choice(generator.SAUDI_FIRST_NAMES_FEMALE)
gender = 'F'
last_name = random.choice(generator.SAUDI_FAMILY_NAMES)
# Generate birth date (18-80 years old)
birth_date = datetime.now().date() - timedelta(
days=random.randint(18*365, 80*365)
)
# Create patient
patient = PatientProfile.objects.create(
tenant=tenant,
mrn=f"MRN{random.randint(100000, 999999)}",
first_name=first_name,
last_name=last_name,
date_of_birth=birth_date,
gender=gender,
phone_number=f"+966{random.randint(500000000, 599999999)}",
email=f"{first_name.lower()}.{last_name.lower().replace(' ', '')}@example.com",
address=f"الرياض، المملكة العربية السعودية",
city="الرياض",
country="SA",
created_by=created_by
)
patients_created += 1
# Create 1-2 insurance policies per patient
num_insurances = random.choices([1, 2], weights=[0.7, 0.3])[0]
for j in range(num_insurances):
insurance_company = random.choice(generator.SAUDI_INSURANCE_COMPANIES)
# Generate policy dates
effective_date = datetime.now().date() - timedelta(
days=random.randint(30, 365)
)
expiration_date = effective_date + timedelta(days=365)
# Create insurance
insurance = InsuranceInfo.objects.create(
patient=patient,
insurance_type='PRIMARY' if j == 0 else 'SECONDARY',
insurance_company=insurance_company,
plan_name=f"{insurance_company.split()[0]} Premium Plan",
plan_type=random.choice(['HMO', 'PPO', 'EPO']),
policy_number=f"POL{random.randint(100000000, 999999999)}",
member_id=f"MEM{random.randint(100000000, 999999999)}",
group_number=f"GRP{random.randint(10000, 99999)}",
effective_date=effective_date,
expiration_date=expiration_date,
copay=random.choice([50, 75, 100, 150, 200]),
deductible=random.choice([500, 1000, 1500, 2000, 2500]),
subscriber_name=patient.get_full_name(),
subscriber_relationship='SELF',
subscriber_dob=patient.date_of_birth,
created_by=created_by
)
insurance_created += 1
if (i + 1) % 10 == 0:
self.stdout.write(f"Created {i + 1} patients...")
except Exception as e:
self.stdout.write(
self.style.ERROR(f"Error creating patient {i + 1}: {str(e)}")
)
continue
# Show results
self.stdout.write(
self.style.SUCCESS(
f"Successfully created {patients_created} patients and {insurance_created} insurance policies"
)
)
# Show sample data
sample_patients = PatientProfile.objects.filter(tenant=tenant).order_by('-created_at')[:5]
if sample_patients:
self.stdout.write(f"\nSample created patients:")
for patient in sample_patients:
insurance_count = patient.insurance_info.count()
self.stdout.write(
f" - {patient.get_full_name()} (MRN: {patient.mrn}, Insurance policies: {insurance_count})"
)
# Show insurance companies used
used_companies = InsuranceInfo.objects.filter(
patient__tenant=tenant
).values_list('insurance_company', flat=True).distinct()
self.stdout.write(f"\nInsurance companies used ({len(used_companies)}):")
for company in sorted(used_companies)[:10]:
self.stdout.write(f" - {company}")
if len(used_companies) > 10:
self.stdout.write(f" ... and {len(used_companies) - 10} more")
def _get_system_user(self):
"""Get or create a system user for created_by field."""
try:
return User.objects.get(username='system')
except User.DoesNotExist:
# Try to get the first superuser
superuser = User.objects.filter(is_superuser=True).first()
if superuser:
return superuser
# Try to get any user
user = User.objects.first()
if user:
return user
# Create a system user if none exists
return User.objects.create_user(
username='system',
email='system@hospital.local',
first_name='System',
last_name='Generator',
is_active=True
)