229 lines
9.4 KiB
Python
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
|
|
)
|
|
|