import os import sys import django import argparse # Set up Django environment os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hospital_management.settings') django.setup() import random from datetime import datetime, date, time, timedelta from django.utils import timezone as django_timezone from django.db import transaction from emr.models import Encounter, VitalSigns, ProblemList, CarePlan, ClinicalNote, NoteTemplate, Icd10, ClinicalRecommendation, AllergyAlert, TreatmentProtocol, ClinicalGuideline, CriticalAlert, DiagnosticSuggestion from patients.models import PatientProfile from accounts.models import User from hr.models import Employee from appointments.models import AppointmentRequest from inpatients.models import Admission from core.models import Tenant import uuid from decimal import Decimal # Optional import for ICD-10 XML parsing try: import xmlschema XMLSCHEMA_AVAILABLE = True except ImportError: XMLSCHEMA_AVAILABLE = False xmlschema = None # Saudi-specific clinical data SAUDI_ENCOUNTER_TYPES = [ 'CONSULTATION', 'FOLLOW_UP', 'EMERGENCY', 'PROCEDURE', 'SURGERY', 'DIAGNOSTIC', 'THERAPY', 'SCREENING', 'VACCINATION', 'TELEMEDICINE' ] SAUDI_ENCOUNTER_CLASSES = [ 'OUTPATIENT', 'INPATIENT', 'EMERGENCY', 'OBSERVATION', 'DAY_SURGERY', 'TELEMEDICINE', 'HOME_VISIT' ] SAUDI_CHIEF_COMPLAINTS = [ 'Chest pain and shortness of breath', 'Abdominal pain and nausea', 'Headache and dizziness', 'Back pain and stiffness', 'Fever and cough', 'Joint pain and swelling', 'Fatigue and weakness', 'Skin rash and itching', 'Diabetes follow-up', 'Hypertension monitoring', 'Regular health checkup', 'Vaccination appointment', 'Pre-operative consultation', 'Post-operative follow-up', 'Pregnancy consultation', 'Child wellness visit', 'Mental health consultation', 'Physical therapy session', 'Diagnostic imaging', 'Laboratory test follow-up', 'Cardiac symptoms evaluation', 'Respiratory symptoms', 'Gastrointestinal complaints', 'Neurological symptoms', 'Endocrine disorders follow-up' ] SAUDI_LOCATIONS = [ 'Main Building - Floor 1', 'Main Building - Floor 2', 'Main Building - Floor 3', 'Emergency Wing', 'Outpatient Clinic - Wing A', 'Outpatient Clinic - Wing B', 'Surgical Suite - Floor 4', 'Radiology Department', 'Laboratory Building', 'Pediatric Wing', 'ICU - Floor 5', 'Cardiology Unit', 'Maternity Ward', 'Dialysis Center' ] SAUDI_PROBLEM_TYPES = [ 'DIAGNOSIS', 'SYMPTOM', 'FINDING', 'COMPLAINT', 'CONDITION', 'DISORDER', 'SYNDROME', 'INJURY', 'ALLERGY', 'INTOLERANCE', 'RISK_FACTOR' ] SAUDI_COMMON_PROBLEMS = [ ('Diabetes Mellitus Type 2', 'E11.9', 'ICD10'), ('Hypertension', 'I10', 'ICD10'), ('Hyperlipidemia', 'E78.5', 'ICD10'), ('Asthma', 'J45.9', 'ICD10'), ('Chronic Kidney Disease', 'N18.9', 'ICD10'), ('Osteoarthritis', 'M19.9', 'ICD10'), ('Depression', 'F32.9', 'ICD10'), ('Anxiety Disorder', 'F41.9', 'ICD10'), ('Obesity', 'E66.9', 'ICD10'), ('Gastroesophageal Reflux', 'K21.9', 'ICD10'), ('Migraine', 'G43.9', 'ICD10'), ('Allergic Rhinitis', 'J30.9', 'ICD10'), ('Hypothyroidism', 'E03.9', 'ICD10'), ('Coronary Artery Disease', 'I25.9', 'ICD10'), ('Chronic Obstructive Pulmonary Disease', 'J44.9', 'ICD10') ] SAUDI_CARE_PLAN_TYPES = [ 'COMPREHENSIVE', 'DISEASE_SPECIFIC', 'PREVENTIVE', 'CHRONIC_CARE', 'ACUTE_CARE', 'DISCHARGE', 'REHABILITATION', 'PALLIATIVE', 'MENTAL_HEALTH', 'MEDICATION', 'NUTRITION', 'EXERCISE' ] SAUDI_NOTE_TYPES = [ 'CONSULTATION', 'PROGRESS', 'DISCHARGE', 'PROCEDURE', 'SURGERY', 'EMERGENCY', 'NURSING', 'THERAPY', 'DIAGNOSTIC', 'MEDICATION_REVIEW', 'FOLLOW_UP' ] def get_providers_for_emr(tenants): """Get healthcare providers for EMR data creation""" providers = [] for tenant in tenants: tenant_providers = User.objects.filter( tenant=tenant, is_active=True, employee_profile__role__in=['PHYSICIAN', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT', 'RADIOLOGIST'] ) providers.extend(list(tenant_providers)) # Create mock providers if none exist if not providers: providers = create_mock_providers_for_emr(tenants) return providers def create_mock_providers_for_emr(tenants): """Create mock healthcare providers for EMR data""" providers = [] mock_providers_data = [ {'first_name': 'Ahmad', 'last_name': 'Al-Rashid', 'role': 'PHYSICIAN'}, {'first_name': 'Fatima', 'last_name': 'Al-Ghamdi', 'role': 'PHYSICIAN'}, {'first_name': 'Mohammed', 'last_name': 'Al-Otaibi', 'role': 'PHYSICIAN'}, {'first_name': 'Sarah', 'last_name': 'Al-Harbi', 'role': 'PHYSICIAN'}, {'first_name': 'Khalid', 'last_name': 'Al-Mutairi', 'role': 'SURGEON'}, {'first_name': 'Nora', 'last_name': 'Al-Zahrani', 'role': 'NURSE_PRACTITIONER'}, {'first_name': 'Omar', 'last_name': 'Al-Dawsari', 'role': 'PHYSICIAN'}, {'first_name': 'Layla', 'last_name': 'Al-Subai', 'role': 'PHYSICIAN'}, ] for tenant in tenants: for provider_data in mock_providers_data: try: email = f"{provider_data['first_name'].lower()}.{provider_data['last_name'].lower().replace('-', '')}@{tenant.domain}" existing_user = User.objects.filter(email=email).first() if not existing_user: user = User.objects.create_user( email=email, first_name=provider_data['first_name'], last_name=provider_data['last_name'], employee_profile__role=provider_data['role'], tenant=tenant, is_active=True, password='temp_password_123' ) providers.append(user) else: providers.append(existing_user) except Exception as e: print(f"Error creating mock provider {provider_data['first_name']} {provider_data['last_name']}: {e}") continue return providers def create_note_templates(tenants): """Create note templates for different specialties""" templates = [] template_configs = [ { 'name': 'General Consultation Note', 'note_type': 'CONSULTATION', 'specialty': 'FAMILY_MEDICINE', 'content': """ CHIEF COMPLAINT: [Chief Complaint] HISTORY OF PRESENT ILLNESS: [History details] PAST MEDICAL HISTORY: [Past medical history] MEDICATIONS: [Current medications] ALLERGIES: [Known allergies] SOCIAL HISTORY: [Social history] PHYSICAL EXAMINATION: General: [General appearance] Vital Signs: [Vital signs] HEENT: [Head, eyes, ears, nose, throat] Cardiovascular: [Heart examination] Respiratory: [Lung examination] Abdomen: [Abdominal examination] Extremities: [Extremity examination] Neurological: [Neurological examination] ASSESSMENT: [Clinical impression] PLAN: [Treatment plan] [Provider Name], [Title] [Date and Time] """, 'structured_fields': [ 'chief_complaint', 'history_present_illness', 'past_medical_history', 'medications', 'allergies', 'social_history', 'physical_exam', 'assessment', 'plan' ] }, { 'name': 'Cardiology Consultation', 'note_type': 'CONSULTATION', 'specialty': 'CARDIOLOGY', 'content': """ CHIEF COMPLAINT: [Cardiac symptoms] HISTORY OF PRESENT ILLNESS: [Cardiac history details] CARDIOVASCULAR RISK FACTORS: [Risk factors assessment] MEDICATIONS: [Cardiac medications] PHYSICAL EXAMINATION: Blood Pressure: [BP measurements] Heart Rate: [HR and rhythm] Cardiovascular: [Detailed cardiac exam] Peripheral Vascular: [Peripheral circulation] ECG: [ECG findings] LABORATORY RESULTS: [Cardiac markers, lipids, etc.] IMAGING: [Echo, stress test, etc.] ASSESSMENT: [Cardiac diagnosis] PLAN: [Cardiac management plan] [Cardiologist Name] [Date and Time] """, 'structured_fields': [ 'chief_complaint', 'cardiac_history', 'risk_factors', 'cardiac_medications', 'cardiac_exam', 'ecg_findings', 'lab_results', 'imaging_results', 'cardiac_assessment', 'cardiac_plan' ] }, { 'name': 'Emergency Department Note', 'note_type': 'EMERGENCY', 'specialty': 'EMERGENCY', 'content': """ TIME OF ARRIVAL: [Arrival time] CHIEF COMPLAINT: [Emergency complaint] TRIAGE LEVEL: [Triage priority] HISTORY OF PRESENT ILLNESS: [Emergency presentation details] PAST MEDICAL HISTORY: [Relevant medical history] MEDICATIONS: [Current medications] ALLERGIES: [Known allergies] PHYSICAL EXAMINATION: General Appearance: [Patient appearance] Vital Signs: [Emergency vital signs] Primary Survey: [ABCDE assessment] Secondary Survey: [Detailed examination] EMERGENCY PROCEDURES: [Procedures performed] LABORATORY/IMAGING: [Emergency testing results] ASSESSMENT: [Emergency diagnosis] DISPOSITION: [Emergency department disposition] [Emergency Physician Name] [Date and Time] """, 'structured_fields': [ 'arrival_time', 'chief_complaint', 'triage_level', 'emergency_history', 'emergency_exam', 'procedures_performed', 'emergency_testing', 'emergency_assessment', 'disposition' ] }, { 'name': 'Surgical Consultation', 'note_type': 'CONSULTATION', 'specialty': 'SURGERY', 'content': """ REASON FOR CONSULTATION: [Surgical consultation reason] HISTORY OF PRESENT ILLNESS: [Surgical problem history] PAST SURGICAL HISTORY: [Previous surgeries] MEDICATIONS: [Current medications] ALLERGIES: [Known allergies] PHYSICAL EXAMINATION: [Surgical examination findings] IMAGING STUDIES: [Relevant imaging] LABORATORY RESULTS: [Preoperative labs] ASSESSMENT: [Surgical assessment] RECOMMENDATIONS: [Surgical recommendations] SURGICAL PLAN: [Proposed surgical intervention] RISKS AND BENEFITS DISCUSSED: [Risk discussion] [Surgeon Name] [Date and Time] """, 'structured_fields': [ 'consultation_reason', 'surgical_history', 'past_surgeries', 'surgical_exam', 'imaging_studies', 'preop_labs', 'surgical_assessment', 'surgical_recommendations', 'surgical_plan' ] }, { 'name': 'Progress Note', 'note_type': 'PROGRESS', 'specialty': 'INTERNAL_MEDICINE', 'content': """ SUBJECTIVE: [Patient's reported symptoms and concerns] OBJECTIVE: Vital Signs: [Current vital signs] Physical Examination: [Current physical findings] Laboratory Results: [Recent lab results] Imaging Studies: [Recent imaging] ASSESSMENT: [Current clinical assessment] PLAN: [Updated treatment plan] [Provider Name] [Date and Time] """, 'structured_fields': [ 'subjective', 'vital_signs', 'physical_exam', 'lab_results', 'imaging', 'assessment', 'plan' ] } ] for tenant in tenants: for config in template_configs: try: template = NoteTemplate.objects.create( tenant=tenant, template_id=uuid.uuid4(), name=config['name'], description=f"Standard {config['name'].lower()} template", note_type=config['note_type'], specialty=config['specialty'], template_content=config['content'].strip(), structured_fields=config['structured_fields'], is_active=True, is_default=config['name'] == 'General Consultation Note', usage_count=random.randint(0, 100), version=1.0, quality_indicators=[ 'completeness', 'accuracy', 'timeliness', 'clarity', 'compliance' ], compliance_requirements=[ 'documentation_complete_within_24h', 'provider_signature_required', 'patient_privacy_maintained' ], created_at=django_timezone.now() - timedelta(days=random.randint(30, 365)), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 30)) ) templates.append(template) except Exception as e: print(f"Error creating template {config['name']}: {e}") continue print(f"Created {len(templates)} note templates") return templates def create_encounters(tenants, days_back=30): """Create patient encounters""" encounters = [] # Get patients and providers patients = list(PatientProfile.objects.filter(tenant__in=tenants)) if not patients: print("No patients found. Skipping encounter creation.") return encounters providers = get_providers_for_emr(tenants) if not providers: print("No providers found. Skipping encounter creation.") return encounters # Get existing appointments to link with encounters appointments = list(AppointmentRequest.objects.filter( tenant__in=tenants, status__in=['COMPLETED', 'IN_PROGRESS'] )) # Get existing admissions admissions = list(Admission.objects.filter(tenant__in=tenants)) start_date = django_timezone.now().date() - timedelta(days=days_back) # Create encounters for the past days_back days for day_offset in range(days_back): encounter_date = start_date + timedelta(days=day_offset) daily_encounters = random.randint(20, 50) # Variable number of encounters per day for _ in range(daily_encounters): patient = random.choice(patients) # Get providers for this patient's tenant tenant_providers = [p for p in providers if p.tenant == patient.tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {patient.tenant.name}. Skipping encounter for {patient.get_full_name()}") continue provider = random.choice(tenant_providers) # Determine encounter type and class encounter_type = random.choices( SAUDI_ENCOUNTER_TYPES, weights=[25, 20, 10, 8, 5, 12, 8, 7, 3, 2] )[0] if encounter_type == 'EMERGENCY': encounter_class = 'EMERGENCY' elif encounter_type in ['SURGERY', 'PROCEDURE']: encounter_class = random.choice(['INPATIENT', 'DAY_SURGERY', 'OUTPATIENT']) elif encounter_type == 'TELEMEDICINE': encounter_class = 'TELEMEDICINE' else: encounter_class = random.choice(['OUTPATIENT', 'INPATIENT']) # Generate encounter timing start_hour = random.randint(8, 20) start_minute = random.choice([0, 15, 30, 45]) start_datetime = django_timezone.make_aware( datetime.combine(encounter_date, time(start_hour, start_minute)) ) duration_minutes = random.randint(15, 180) if encounter_type == 'SURGERY': duration_minutes = random.randint(60, 360) elif encounter_type == 'EMERGENCY': duration_minutes = random.randint(30, 240) end_datetime = start_datetime + timedelta(minutes=duration_minutes) # Determine status if encounter_date < django_timezone.now().date(): status = random.choices( ['PLANNED','COMPLETED', 'CANCELLED'], weights=[30,55, 15] )[0] elif encounter_date == django_timezone.now().date(): status = random.choices( ['IN_PROGRESS', 'COMPLETED'], weights=[30, 70] )[0] else: status = 'SCHEDULED' # Priority and acuity if encounter_type == 'EMERGENCY': priority = random.choices(['EMERGENCY', 'URGENT'], weights=[60, 40])[0] acuity_level = random.randint(2, 5) else: priority = random.choices(['ROUTINE', 'URGENT'], weights=[80, 20])[0] acuity_level = random.randint(1, 3) # Link to appointment if available linked_appointment = None if appointments: suitable_appointments = [ apt for apt in appointments if apt.patient == patient and apt.scheduled_datetime and apt.scheduled_datetime.date() == encounter_date ] if suitable_appointments: linked_appointment = random.choice(suitable_appointments) # Link to admission if inpatient linked_admission = None if encounter_class == 'INPATIENT' and admissions: suitable_admissions = [ adm for adm in admissions if adm.patient == patient and adm.admission_datetime <= start_datetime ] if suitable_admissions: linked_admission = random.choice(suitable_admissions) # Documentation completion documentation_complete = status == 'COMPLETED' signed_off = documentation_complete and random.choice([True, False]) try: encounter = Encounter.objects.create( tenant=patient.tenant, encounter_id=uuid.uuid4(), patient=patient, provider=provider, encounter_type=encounter_type, encounter_class=encounter_class, start_datetime=start_datetime, end_datetime=end_datetime if status in ['COMPLETED', 'CANCELLED'] else None, status=status, location=random.choice(SAUDI_LOCATIONS), room_number=f"Room {random.randint(101, 450)}", appointment=linked_appointment, admission=linked_admission, chief_complaint=random.choice(SAUDI_CHIEF_COMPLAINTS), reason_for_visit=random.choice(SAUDI_CHIEF_COMPLAINTS), priority=priority, acuity_level=acuity_level, documentation_complete=documentation_complete, signed_off=signed_off, signed_by=provider if signed_off else None, signed_datetime=end_datetime if signed_off else None, billable=random.choice([True, False]), billing_codes=[ f"{random.randint(99200, 99499)}", f"{random.randint(99200, 99499)}" ] if random.choice([True, False]) else [], quality_measures={ 'documentation_score': random.randint(70, 100), 'timeliness_score': random.randint(80, 100), 'completeness_score': random.randint(75, 100) }, created_at=start_datetime - timedelta(minutes=random.randint(5, 60)), updated_at=django_timezone.now() - timedelta(minutes=random.randint(0, 30)), created_by=provider ) encounters.append(encounter) except Exception as e: print(f"Error creating encounter for {patient.get_full_name()}: {e}") continue print(f"Created {len(encounters)} encounters") return encounters def create_vital_signs(encounters): """Create vital signs for encounters""" vital_signs = [] providers = User.objects.filter( employee_profile__role__in=['NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN', 'MEDICAL_ASSISTANT'], is_active=True ) if not providers: # Use encounter providers as fallback providers = list(set([enc.provider for enc in encounters])) for encounter in encounters: # Create 1-3 vital signs measurements per encounter num_measurements = random.randint(1, 3) for measurement_num in range(num_measurements): # Time offset for multiple measurements time_offset = measurement_num * random.randint(30, 120) # 30-120 minutes apart measured_datetime = encounter.start_datetime + timedelta(minutes=time_offset) # Generate realistic vital signs based on patient age patient_age = (django_timezone.now().date() - encounter.patient.date_of_birth).days // 365 # Temperature (Celsius) temperature = round(random.uniform(36.0, 39.5), 1) if temperature > 38.5: temperature_method = random.choice(['ORAL', 'RECTAL', 'TYMPANIC']) else: temperature_method = random.choice(['ORAL', 'AXILLARY', 'TYMPANIC']) # Blood pressure if patient_age < 18: systolic_bp = random.randint(90, 120) diastolic_bp = random.randint(50, 80) elif patient_age < 65: systolic_bp = random.randint(100, 140) diastolic_bp = random.randint(60, 90) else: systolic_bp = random.randint(110, 160) diastolic_bp = random.randint(70, 100) bp_position = random.choice(['SITTING', 'LYING', 'STANDING']) bp_cuff_size = 'REGULAR' if patient_age >= 18 else 'PEDIATRIC' # Heart rate if patient_age < 1: heart_rate = random.randint(100, 160) elif patient_age < 12: heart_rate = random.randint(80, 120) else: heart_rate = random.randint(60, 100) heart_rhythm = random.choices( ['REGULAR', 'REGULARLY_IRREGULAR', 'IRREGULARLY_IRREGULAR', 'IRREGULAR_UNSPECIFIED'], weights=[85, 8, 5, 2] )[0] # Respiratory rate if patient_age < 1: respiratory_rate = random.randint(30, 60) elif patient_age < 12: respiratory_rate = random.randint(18, 30) else: respiratory_rate = random.randint(12, 20) # Oxygen saturation oxygen_saturation = random.randint(95, 100) oxygen_delivery = 'ROOM_AIR' oxygen_flow_rate = None if oxygen_saturation < 95: oxygen_delivery = random.choice(['NASAL_CANNULA', 'MASK', 'NON_REBREATHER']) oxygen_flow_rate = random.randint(2, 15) # Pain scale pain_scale = random.randint(0, 10) pain_location = None pain_quality = None if pain_scale > 0: pain_location = random.choice([ 'Head', 'Chest', 'Abdomen', 'Back', 'Extremities', 'Generalized', 'Neck', 'Pelvis' ]) pain_quality = random.choice([ 'Sharp', 'Dull', 'Burning', 'Cramping', 'Stabbing', 'Throbbing', 'Aching' ]) # Weight and height if patient_age < 18: weight = round(random.uniform(3.0, 70.0), 1) height = round(random.uniform(50.0, 180.0), 1) else: weight = round(random.uniform(45.0, 150.0), 1) height = round(random.uniform(150.0, 200.0), 1) # Head circumference for pediatric patients head_circumference = None if patient_age < 2: head_circumference = round(random.uniform(30.0, 50.0), 1) # Critical values detection critical_values = [] if temperature > 39.0 or temperature < 35.0: critical_values.append('temperature') if systolic_bp > 180 or systolic_bp < 90: critical_values.append('systolic_bp') if heart_rate > 120 or heart_rate < 50: critical_values.append('heart_rate') if oxygen_saturation < 90: critical_values.append('oxygen_saturation') alerts_generated = len(critical_values) > 0 try: vital_sign = VitalSigns.objects.create( encounter=encounter, patient=encounter.patient, measurement_id=uuid.uuid4(), measured_datetime=measured_datetime, temperature=Decimal(str(temperature)), temperature_method=temperature_method, systolic_bp=systolic_bp, diastolic_bp=diastolic_bp, bp_position=bp_position, bp_cuff_size=bp_cuff_size, heart_rate=heart_rate, heart_rhythm=heart_rhythm, respiratory_rate=respiratory_rate, oxygen_saturation=oxygen_saturation, oxygen_delivery=oxygen_delivery, oxygen_flow_rate=oxygen_flow_rate, pain_scale=pain_scale, pain_location=pain_location, pain_quality=pain_quality, weight=Decimal(str(weight)), height=Decimal(str(height)), head_circumference=Decimal(str(head_circumference)) if head_circumference else None, device_used=random.choice(['MANUAL', 'AUTOMATED', 'MONITOR']), device_calibrated=random.choice([True, False]), measured_by=random.choice(providers), verified_by=random.choice(providers) if random.choice([True, False]) else None, critical_values=critical_values, alerts_generated=alerts_generated, notes=f"Routine vital signs measurement #{measurement_num + 1}" if measurement_num > 0 else None, created_at=measured_datetime, updated_at=measured_datetime + timedelta(minutes=random.randint(1, 10)) ) vital_signs.append(vital_sign) except Exception as e: print(f"Error creating vital signs for encounter {encounter.encounter_id}: {e}") continue print(f"Created {len(vital_signs)} vital signs records") return vital_signs def create_problem_lists(patients, providers): """Create problem lists for patients""" problems = [] for patient in patients: # Each patient has 1-5 problems num_problems = random.randint(1, 5) for _ in range(num_problems): problem_data = random.choice(SAUDI_COMMON_PROBLEMS) problem_name, problem_code, coding_system = problem_data problem_type = random.choices( SAUDI_PROBLEM_TYPES, weights=[60, 20, 10, 5, 2, 2, 1, 1, 1, 1, 1] )[0] # Onset date (random date in the past) onset_date = django_timezone.now().date() - timedelta( days=random.randint(30, 3650) # 1 month to 10 years ago ) # Severity severity = random.choices( ['MILD', 'MODERATE', 'SEVERE', 'CRITICAL'], weights=[40, 35, 20, 5] )[0] # Priority priority = random.choices( ['HIGH', 'MEDIUM', 'LOW'], weights=[20, 60, 20] )[0] # Status status = random.choices( ['ACTIVE', 'RESOLVED', 'INACTIVE', 'REMISSION'], weights=[50, 20, 10, 20] )[0] # Resolution date for resolved problems resolution_date = None resolution_notes = None if status == 'RESOLVED': resolution_date = onset_date + timedelta( days=random.randint(7, 365) ) resolution_notes = f"Problem resolved after treatment. Patient improved significantly." # Provider assignments tenant_providers = [p for p in providers if p.tenant == patient.tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {patient.tenant.name}. Skipping problem for {patient.get_full_name()}") continue diagnosing_provider = random.choice(tenant_providers) managing_provider = diagnosing_provider if random.choice([True, False]) else random.choice(tenant_providers) # Fix timezone issue verified_date = None if random.choice([True, False]): verified_date = django_timezone.now() try: problem = ProblemList.objects.create( tenant=patient.tenant, patient=patient, problem_id=uuid.uuid4(), problem_name=problem_name, problem_code=problem_code, coding_system=coding_system, problem_type=problem_type, onset_date=onset_date, onset_description=f"Patient reports {problem_name.lower()} started gradually", severity=severity, priority=priority, status=status, resolution_date=resolution_date, resolution_notes=resolution_notes, diagnosing_provider=diagnosing_provider, managing_provider=managing_provider, body_site=random.choice([ 'Chest', 'Abdomen', 'Head', 'Extremities', 'Back', 'Neck' ]) if random.choice([True, False]) else None, laterality=random.choice(['LEFT', 'RIGHT', 'BILATERAL']) if random.choice([True, False]) else None, clinical_notes=f"Patient diagnosed with {problem_name}. {severity.lower()} severity. Status: {status.lower()}.", patient_concerns=f"Patient concerned about {problem_name.lower()} impact on daily activities", treatment_goals=[ f"Manage {problem_name.lower()} symptoms", "Improve quality of life", "Prevent complications" ], outcome_measures=[ "Symptom improvement", "Functional status", "Patient satisfaction" ], verified=random.choice([True, False]), verified_by=managing_provider if random.choice([True, False]) else None, verified_date=verified_date, # Use timezone-aware datetime created_at=django_timezone.make_aware( datetime.combine(onset_date, time(random.randint(8, 17), random.randint(0, 59))) ), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 30)), created_by=diagnosing_provider ) problems.append(problem) except Exception as e: print(f"Error creating problem for {patient.get_full_name()}: {e}") continue print(f"Created {len(problems)} problem list entries") return problems def create_care_plans(patients, providers, problems): """Create care plans for patients""" care_plans = [] for patient in patients: # Each patient has 1-2 care plans num_plans = random.randint(1, 2) patient_problems = [p for p in problems if p.patient == patient] if not patient_problems: continue for _ in range(num_plans): plan_type = random.choice(SAUDI_CARE_PLAN_TYPES) # Select related problems for this care plan related_problems_list = random.sample( patient_problems, min(random.randint(1, 3), len(patient_problems)) ) # Generate care plan title and description main_problem = related_problems_list[0].problem_name title = f"{plan_type.replace('_', ' ').title()} Plan for {main_problem}" description = f"Comprehensive {plan_type.lower().replace('_', ' ')} plan for managing {main_problem} and related conditions." # Care plan category category = random.choice([ 'ASSESSMENT', 'TREATMENT', 'EDUCATION', 'COORDINATION', 'PREVENTION', 'LIFESTYLE', 'MEDICATION', 'FOLLOW_UP', 'EMERGENCY', 'SUPPORT' ]) # Timeline start_date = django_timezone.now().date() end_date = start_date + timedelta(days=random.randint(30, 365)) target_completion_date = end_date - timedelta(days=random.randint(0, 30)) # Status status = random.choices( ['ACTIVE', 'COMPLETED', 'ON_HOLD', 'CANCELLED'], weights=[60, 25, 10, 5] )[0] # Priority priority = random.choices( ['LOW', 'ROUTINE', 'URGENT', 'STAT'], weights=[25, 50, 20, 5] )[0] # Providers tenant_providers = [p for p in providers if p.tenant == patient.tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {patient.tenant.name}. Skipping care plan for {patient.get_full_name()}") continue primary_provider = random.choice(tenant_providers) care_team_list = random.sample( tenant_providers, min(random.randint(2, 4), len(tenant_providers)) ) # Goals and objectives goals = [ f"Manage {main_problem} effectively", "Improve patient quality of life", "Prevent disease progression", "Optimize medication therapy" ] objectives = [ f"Reduce {main_problem.lower()} symptoms by 50%", "Achieve target vital signs", "Improve functional status", "Enhance patient understanding" ] # Interventions and activities interventions = [ "Medication management", "Patient education", "Lifestyle modifications", "Regular monitoring" ] activities = [ "Daily medication review", "Weekly patient assessment", "Monthly provider consultation", "Quarterly outcome evaluation" ] # Completion percentage completion_percentage = random.randint(0, 100) if status in ['ACTIVE', 'COMPLETED'] else 0 if status == 'COMPLETED': completion_percentage = 100 # Approval approved = random.choice([True, False]) approved_date = django_timezone.now() if approved else None try: care_plan = CarePlan.objects.create( tenant=patient.tenant, patient=patient, care_plan_id=uuid.uuid4(), title=title, description=description, plan_type=plan_type, category=category, start_date=start_date, end_date=end_date, target_completion_date=target_completion_date, status=status, priority=priority, primary_provider=primary_provider, goals=goals, objectives=objectives, interventions=interventions, activities=activities, monitoring_parameters=[ "Vital signs", "Symptom severity", "Functional status", "Medication adherence" ], evaluation_criteria=[ "Symptom improvement", "Quality of life measures", "Patient satisfaction", "Clinical outcomes" ], patient_goals=[ "Feel better", "Return to normal activities", "Understand my condition", "Take medications correctly" ], patient_preferences=[ "Prefer oral medications", "Morning appointments preferred", "Family involvement desired" ], patient_barriers=[ "Transportation challenges", "Language barriers", "Financial constraints" ] if random.choice([True, False]) else [], resources_needed=[ "Medication", "Medical equipment", "Educational materials", "Support services" ], support_systems=[ "Family support", "Healthcare team", "Community resources" ], progress_notes=f"Patient progressing well with {plan_type.lower().replace('_', ' ')} plan.", last_reviewed=django_timezone.now().date() - timedelta(days=random.randint(0, 30)), next_review_date=django_timezone.now().date() + timedelta(days=random.randint(7, 90)), outcomes_achieved=[ "Symptom reduction achieved", "Patient education completed" ] if completion_percentage > 50 else ["No outcomes achieved yet"], completion_percentage=completion_percentage, approved=approved, approved_by=primary_provider if approved else None, approved_date=approved_date, # Use timezone-aware datetime created_at=django_timezone.make_aware( datetime.combine(start_date, time(random.randint(8, 17), random.randint(0, 59))) ), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 7)), created_by=primary_provider ) # Set many-to-many relationships after creation care_plan.care_team.set(care_team_list) care_plan.related_problems.set(related_problems_list) care_plans.append(care_plan) except Exception as e: print(f"Error creating care plan for {patient.get_full_name()}: {e}") continue print(f"Created {len(care_plans)} care plans") return care_plans def create_clinical_notes(encounters, templates): """Create clinical notes for encounters""" clinical_notes = [] for encounter in encounters: if encounter.status not in ['COMPLETED', 'IN_PROGRESS']: continue # Each encounter has 1-2 clinical notes num_notes = random.randint(1, 2) for note_num in range(num_notes): # Select appropriate template suitable_templates = [ t for t in templates if t.tenant == encounter.tenant and ( t.note_type == encounter.encounter_type or t.specialty == 'FAMILY_MEDICINE' ) ] template = random.choice(suitable_templates) if suitable_templates else None # Note type based on encounter note_type = encounter.encounter_type if encounter.encounter_type in [nt for nt in SAUDI_NOTE_TYPES] else 'CONSULTATION' # Generate note title titles = { 'CONSULTATION': f"Consultation Note - {encounter.chief_complaint}", 'EMERGENCY': f"Emergency Department Note - {encounter.chief_complaint}", 'PROGRESS': f"Progress Note - Day {note_num + 1}", 'SURGERY': f"Surgical Note - {encounter.chief_complaint}", 'PROCEDURE': f"Procedure Note - {encounter.chief_complaint}", 'DISCHARGE': f"Discharge Summary - {encounter.chief_complaint}" } title = titles.get(note_type, f"Clinical Note - {encounter.chief_complaint}") # Generate note content if template: content = template.template_content # Replace placeholders with actual data content = content.replace('[Chief Complaint]', encounter.chief_complaint) content = content.replace('[Provider Name]', encounter.provider.get_full_name()) content = content.replace('[Date and Time]', encounter.start_datetime.strftime('%Y-%m-%d %H:%M')) content = content.replace('[History details]', f"Patient presents with {encounter.chief_complaint.lower()}.") content = content.replace('[Clinical impression]', f"Impression consistent with {encounter.chief_complaint.lower()}.") content = content.replace('[Treatment plan]', "Continue current management plan and follow up as scheduled.") else: content = f""" ENCOUNTER DATE: {encounter.start_datetime.strftime('%Y-%m-%d %H:%M')} PATIENT: {encounter.patient.get_full_name()} PROVIDER: {encounter.provider.get_full_name()} CHIEF COMPLAINT: {encounter.chief_complaint} HISTORY OF PRESENT ILLNESS: Patient presents with {encounter.chief_complaint.lower()}. Symptoms have been present for several days. PHYSICAL EXAMINATION: Patient appears comfortable. Vital signs stable. ASSESSMENT: Clinical impression consistent with {encounter.chief_complaint.lower()}. PLAN: Continue current management. Follow up in clinic as needed. Electronically signed by: {encounter.provider.get_full_name()} Date: {encounter.start_datetime.strftime('%Y-%m-%d %H:%M')} """.strip() # Note timing note_datetime = encounter.start_datetime + timedelta(minutes=random.randint(15, 120)) # Status and signing if encounter.status == 'COMPLETED': note_status = random.choices( ['SIGNED', 'PENDING_SIGNATURE', 'DRAFT'], weights=[70, 20, 10] )[0] else: note_status = 'DRAFT' electronically_signed = note_status == 'SIGNED' signed_datetime = note_datetime + timedelta( minutes=random.randint(30, 180)) if electronically_signed else None # Co-signers list co_signers_list = [] if random.choice([True, False]): # 50% chance of co-signer potential_cosigners = [ p for p in User.objects.filter( tenant=encounter.tenant, employee_profile__role__in=['PHYSICIAN', 'NURSE_PRACTITIONER'], is_active=True ) if p != encounter.provider ] if potential_cosigners: co_signers_list = [random.choice(potential_cosigners)] # Quality and compliance quality_score = random.randint(75, 100) compliance_flags = [] if quality_score < 85: compliance_flags = ['documentation_incomplete', 'signature_pending'] try: clinical_note = ClinicalNote.objects.create( encounter=encounter, patient=encounter.patient, note_id=uuid.uuid4(), note_type=note_type, title=title, content=content, template=template, structured_data={ 'chief_complaint': encounter.chief_complaint, 'encounter_type': encounter.encounter_type, 'provider': encounter.provider.get_full_name(), 'location': encounter.location }, author=encounter.provider, status=note_status, electronically_signed=electronically_signed, signed_datetime=signed_datetime, signature_method='ELECTRONIC' if electronically_signed else None, quality_score=quality_score, compliance_flags=compliance_flags, note_datetime=note_datetime, confidential=random.choice([True, False]), restricted_access=random.choice([True, False]) if random.random() < 0.1 else False, access_restrictions=['PROVIDER_ONLY'] if random.choice([True, False]) else [], created_at=note_datetime, updated_at=note_datetime + timedelta(minutes=random.randint(5, 60)) ) # Set many-to-many relationship after creation clinical_note.co_signers.set(co_signers_list) clinical_notes.append(clinical_note) except Exception as e: print(f"Error creating clinical note for encounter {encounter.encounter_id}: {e}") continue print(f"Created {len(clinical_notes)} clinical notes") return clinical_notes def create_icd10_codes(tenants): """Create ICD-10 codes for clinical reference""" icd10_codes = [] # Sample ICD-10 codes with descriptions icd10_data = [ # Chapter 1: Certain infectious and parasitic diseases ('A00', 'Cholera', 'Certain infectious and parasitic diseases', 'Cholera and other vibrio infections'), ('A01', 'Typhoid and paratyphoid fevers', 'Certain infectious and parasitic diseases', 'Typhoid and paratyphoid fevers'), ('A02', 'Other salmonella infections', 'Certain infectious and parasitic diseases', 'Other salmonella infections'), ('A03', 'Shigellosis', 'Certain infectious and parasitic diseases', 'Shigellosis'), ('A04', 'Other bacterial intestinal infections', 'Certain infectious and parasitic diseases', 'Other bacterial intestinal infections'), # Chapter 2: Neoplasms ('C00', 'Malignant neoplasm of lip', 'Neoplasms', 'Malignant neoplasms of lip, oral cavity and pharynx'), ('C01', 'Malignant neoplasm of base of tongue', 'Neoplasms', 'Malignant neoplasms of lip, oral cavity and pharynx'), ('C02', 'Malignant neoplasm of other and unspecified parts of tongue', 'Neoplasms', 'Malignant neoplasms of lip, oral cavity and pharynx'), ('C03', 'Malignant neoplasm of gum', 'Neoplasms', 'Malignant neoplasms of lip, oral cavity and pharynx'), ('C04', 'Malignant neoplasm of floor of mouth', 'Neoplasms', 'Malignant neoplasms of lip, oral cavity and pharynx'), # Chapter 9: Diseases of the circulatory system ('I00', 'Rheumatic fever without mention of heart involvement', 'Diseases of the circulatory system', 'Acute rheumatic fever'), ('I01', 'Rheumatic fever with heart involvement', 'Diseases of the circulatory system', 'Acute rheumatic fever'), ('I02', 'Rheumatic chorea', 'Diseases of the circulatory system', 'Acute rheumatic fever'), ('I05', 'Rheumatic mitral valve diseases', 'Diseases of the circulatory system', 'Chronic rheumatic heart diseases'), ('I06', 'Rheumatic aortic valve diseases', 'Diseases of the circulatory system', 'Chronic rheumatic heart diseases'), # Chapter 10: Diseases of the respiratory system ('J00', 'Acute nasopharyngitis [common cold]', 'Diseases of the respiratory system', 'Acute upper respiratory infections'), ('J01', 'Acute sinusitis', 'Diseases of the respiratory system', 'Acute upper respiratory infections'), ('J02', 'Acute pharyngitis', 'Diseases of the respiratory system', 'Acute upper respiratory infections'), ('J03', 'Acute tonsillitis', 'Diseases of the respiratory system', 'Acute upper respiratory infections'), ('J04', 'Acute laryngitis and tracheitis', 'Diseases of the respiratory system', 'Acute upper respiratory infections'), # Chapter 11: Diseases of the digestive system ('K00', 'Disorders of tooth development and eruption', 'Diseases of the digestive system', 'Disorders of teeth and supporting structures'), ('K01', 'Embedded and impacted teeth', 'Diseases of the digestive system', 'Disorders of teeth and supporting structures'), ('K02', 'Dental caries', 'Diseases of the digestive system', 'Disorders of teeth and supporting structures'), ('K03', 'Other diseases of hard tissues of teeth', 'Diseases of the digestive system', 'Disorders of teeth and supporting structures'), ('K04', 'Diseases of pulp and periapical tissues', 'Diseases of the digestive system', 'Disorders of teeth and supporting structures'), # Chapter 14: Diseases of the genitourinary system ('N00', 'Acute nephritic syndrome', 'Diseases of the genitourinary system', 'Glomerular diseases'), ('N01', 'Rapidly progressive nephritic syndrome', 'Diseases of the genitourinary system', 'Glomerular diseases'), ('N02', 'Recurrent and persistent hematuria', 'Diseases of the genitourinary system', 'Glomerular diseases'), ('N03', 'Chronic nephritic syndrome', 'Diseases of the genitourinary system', 'Glomerular diseases'), ('N04', 'Nephrotic syndrome', 'Diseases of the genitourinary system', 'Glomerular diseases'), # Chapter 18: Symptoms, signs and abnormal clinical and laboratory findings ('R00', 'Abnormalities of heart beat', 'Symptoms, signs and abnormal clinical and laboratory findings', 'Symptoms and signs involving the circulatory and respiratory systems'), ('R01', 'Cardiac murmurs and other cardiac sounds', 'Symptoms, signs and abnormal clinical and laboratory findings', 'Symptoms and signs involving the circulatory and respiratory systems'), ('R02', 'Gangrene, not elsewhere classified', 'Symptoms, signs and abnormal clinical and laboratory findings', 'Symptoms and signs involving the circulatory and respiratory systems'), ('R03', 'Abnormal blood-pressure reading, without diagnosis', 'Symptoms, signs and abnormal clinical and laboratory findings', 'Symptoms and signs involving the circulatory and respiratory systems'), ('R04', 'Haemorrhage from respiratory passages', 'Symptoms, signs and abnormal clinical and laboratory findings', 'Symptoms and signs involving the circulatory and respiratory systems'), ] for tenant in tenants: for code_data in icd10_data: code, description, chapter, section = code_data # Determine if it's a header (shorter codes are typically headers) is_header = len(code) <= 3 # Create parent relationship for sub-codes parent = None if len(code) > 3: parent_code = code[:3] try: parent = Icd10.objects.get(code=parent_code, tenant=tenant) except Icd10.DoesNotExist: parent = None try: icd10_code = Icd10.objects.create( tenant=tenant, code=code, description=description, chapter_name=chapter, section_name=section, parent=parent, is_header=is_header, created_at=django_timezone.now() - timedelta(days=random.randint(30, 365)), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 30)) ) icd10_codes.append(icd10_code) except Exception as e: print(f"Error creating ICD-10 code {code}: {e}") continue print(f"Created {len(icd10_codes)} ICD-10 codes") return icd10_codes def create_clinical_recommendations(patients, providers, problems, encounters): """Create clinical recommendations for patients""" recommendations = [] recommendation_templates = [ { 'category': 'PREVENTIVE', 'title': 'Annual Health Screening', 'description': 'Patient due for annual comprehensive health screening including blood work, imaging, and preventive counseling.', 'evidence_level': '1A', 'source': 'USPSTF Guidelines 2023', 'rationale': 'Regular screening improves early detection and prevention of chronic diseases.', 'priority': 'MEDIUM' }, { 'category': 'DIAGNOSTIC', 'title': 'Cardiac Evaluation Recommended', 'description': 'Consider echocardiography and stress testing given patient history and risk factors.', 'evidence_level': '1B', 'source': 'ACC/AHA Guidelines 2022', 'rationale': 'Patient presents with cardiac symptoms requiring further evaluation.', 'priority': 'HIGH' }, { 'category': 'TREATMENT', 'title': 'Optimize Diabetes Management', 'description': 'Consider adjusting diabetes regimen based on recent HbA1c and glucose readings.', 'evidence_level': '1A', 'source': 'ADA Standards of Care 2023', 'rationale': 'Current glycemic control may be suboptimal requiring treatment intensification.', 'priority': 'HIGH' }, { 'category': 'MONITORING', 'title': 'Blood Pressure Monitoring', 'description': 'Increase frequency of blood pressure monitoring and consider 24-hour ambulatory monitoring.', 'evidence_level': '1B', 'source': 'JNC 8 Guidelines', 'rationale': 'Recent readings suggest need for closer monitoring and possible treatment adjustment.', 'priority': 'MEDIUM' }, { 'category': 'LIFESTYLE', 'title': 'Weight Management Program', 'description': 'Recommend enrollment in structured weight management program with dietary counseling.', 'evidence_level': '1A', 'source': 'Obesity Guidelines 2023', 'rationale': 'Patient BMI indicates need for weight reduction to improve health outcomes.', 'priority': 'MEDIUM' }, { 'category': 'MEDICATION', 'title': 'Statin Therapy Consideration', 'description': 'Consider initiating statin therapy based on cardiovascular risk assessment.', 'evidence_level': '1A', 'source': 'ACC/AHA Cholesterol Guidelines', 'rationale': 'Patient risk factors warrant preventive cardiovascular therapy.', 'priority': 'HIGH' }, { 'category': 'FOLLOW_UP', 'title': 'Specialist Consultation', 'description': 'Refer to cardiology/endocrinology for comprehensive evaluation.', 'evidence_level': '2A', 'source': 'Clinical judgment', 'rationale': 'Complex medical condition requires specialist input.', 'priority': 'HIGH' }, { 'category': 'EDUCATION', 'title': 'Diabetes Self-Management Education', 'description': 'Patient would benefit from structured diabetes education program.', 'evidence_level': '1A', 'source': 'ADA Standards', 'rationale': 'Education improves self-management and clinical outcomes.', 'priority': 'MEDIUM' } ] for patient in patients: # Create 1-3 recommendations per patient num_recommendations = random.randint(1, 3) patient_problems = [p for p in problems if p.patient == patient] patient_encounters = [e for e in encounters if e.patient == patient] for _ in range(num_recommendations): template = random.choice(recommendation_templates) # Generate unique title based on patient context if patient_problems: main_problem = random.choice(patient_problems).problem_name title = f"{template['title']} - {main_problem}" else: title = template['title'] # Status progression status = random.choices( ['PENDING', 'ACTIVE', 'ACCEPTED', 'DEFERRED', 'COMPLETED'], weights=[40, 30, 15, 10, 5] )[0] # Provider assignments tenant_providers = [p for p in providers if p.tenant == patient.tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {patient.tenant.name}. Skipping recommendation for {patient.get_full_name()}") continue created_by_provider = random.choice(tenant_providers) accepted_by = None accepted_at = None if status in ['ACCEPTED', 'COMPLETED']: accepted_by = random.choice(tenant_providers) accepted_at = django_timezone.now() - timedelta(days=random.randint(1, 30)) deferred_by = None deferred_at = None if status == 'DEFERRED': deferred_by = random.choice(tenant_providers) deferred_at = django_timezone.now() - timedelta(days=random.randint(1, 14)) dismissed_by = None dismissed_at = None if status == 'DISMISSED': dismissed_by = random.choice(tenant_providers) dismissed_at = django_timezone.now() - timedelta(days=random.randint(1, 7)) # Expiration expires_at = django_timezone.now() + timedelta(days=random.randint(30, 180)) # Related data related_problems_list = random.sample( patient_problems, min(random.randint(0, 2), len(patient_problems)) ) if patient_problems else [] related_encounter = random.choice(patient_encounters) if patient_encounters else None try: recommendation = ClinicalRecommendation.objects.create( tenant=patient.tenant, patient=patient, recommendation_id=uuid.uuid4(), title=title, description=template['description'], category=template['category'], priority=template['priority'], evidence_level=template['evidence_level'], source=template['source'], rationale=template['rationale'], status=status, accepted_by=accepted_by, accepted_at=accepted_at, deferred_by=deferred_by, deferred_at=deferred_at, dismissed_by=dismissed_by, dismissed_at=dismissed_at, expires_at=expires_at, related_encounter=related_encounter, created_by=created_by_provider, created_at=django_timezone.now() - timedelta(days=random.randint(1, 60)), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 7)) ) # Set many-to-many relationships if related_problems_list: recommendation.related_problems.set(related_problems_list) recommendations.append(recommendation) except Exception as e: print(f"Error creating clinical recommendation for {patient.get_full_name()}: {e}") continue print(f"Created {len(recommendations)} clinical recommendations") return recommendations def create_allergy_alerts(patients, providers): """Create allergy alerts for patients""" alerts = [] common_allergens = [ 'Penicillin', 'Aspirin', 'Ibuprofen', 'Codeine', 'Morphine', 'Latex', 'Shellfish', 'Peanuts', 'Tree Nuts', 'Eggs', 'Milk', 'Soy', 'Wheat', 'Sulfa Drugs', 'Tetracycline', 'Erythromycin', 'Cephalosporins', 'NSAIDs', 'Contrast Dye', 'Local Anesthetics', 'Insulin', 'ACE Inhibitors' ] reaction_types = [ 'Anaphylaxis', 'Angioedema', 'Urticaria', 'Rash', 'Pruritus', 'Nausea/Vomiting', 'Diarrhea', 'Dyspnea', 'Wheezing', 'Hypotension', 'Tachycardia', 'Bronchospasm', 'Stevens-Johnson Syndrome', 'Toxic Epidermal Necrolysis' ] severities = ['MILD', 'MODERATE', 'SEVERE', 'LIFE_THREATENING'] for patient in patients: # 20% of patients have allergies if random.random() > 0.2: continue # Each allergic patient has 1-3 allergies num_allergies = random.randint(1, 3) for _ in range(num_allergies): allergen = random.choice(common_allergens) # Ensure no duplicate allergens for same patient existing_allergens = [alert.allergen for alert in alerts if alert.patient == patient] while allergen in existing_allergens: allergen = random.choice(common_allergens) reaction_type = random.choice(reaction_types) # Severity based on reaction type if 'Anaphylaxis' in reaction_type or 'Stevens-Johnson' in reaction_type: severity = random.choices(severities, weights=[0, 10, 30, 60])[0] elif 'Angioedema' in reaction_type or 'Bronchospasm' in reaction_type: severity = random.choices(severities, weights=[10, 30, 40, 20])[0] else: severity = random.choices(severities, weights=[40, 40, 15, 5])[0] # Symptoms based on reaction type symptoms = [] if 'Rash' in reaction_type or 'Urticaria' in reaction_type: symptoms.extend(['Hives', 'Itching', 'Redness']) if 'Anaphylaxis' in reaction_type: symptoms.extend(['Difficulty breathing', 'Swelling of throat', 'Dizziness', 'Nausea']) if 'Angioedema' in reaction_type: symptoms.extend(['Facial swelling', 'Tongue swelling', 'Lip swelling']) if 'Dyspnea' in reaction_type or 'Wheezing' in reaction_type: symptoms.extend(['Shortness of breath', 'Wheezing', 'Chest tightness']) symptoms = symptoms[:random.randint(1, 4)] if symptoms else ['Unknown symptoms'] # Onset timing onset = random.choice([ 'Immediate (< 1 hour)', 'Early (1-6 hours)', 'Delayed (6-24 hours)', 'Late (> 24 hours)', 'Unknown' ]) # Status tenant_providers = [p for p in providers if p.tenant == patient.tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {patient.tenant.name}. Skipping allergy alert for {patient.get_full_name()}") continue resolved = random.choice([True, False]) resolved_at = django_timezone.now() - timedelta(days=random.randint(1, 365)) if resolved else None resolved_by = random.choice(tenant_providers) if resolved else None try: alert = AllergyAlert.objects.create( tenant=patient.tenant, patient=patient, alert_id=uuid.uuid4(), allergen=allergen, reaction_type=reaction_type, severity=severity, symptoms=symptoms, onset=onset, resolved=resolved, resolved_at=resolved_at, resolved_by=resolved_by, detected_at=django_timezone.now() - timedelta(days=random.randint(1, 3650)), created_at=django_timezone.now() - timedelta(days=random.randint(1, 3650)), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 30)) ) alerts.append(alert) except Exception as e: print(f"Error creating allergy alert for {patient.get_full_name()}: {e}") continue print(f"Created {len(alerts)} allergy alerts") return alerts def create_treatment_protocols(tenants, providers): """Create treatment protocols""" protocols = [] protocol_templates = [ { 'name': 'Acute Coronary Syndrome Management', 'indication': 'Management of patients with suspected or confirmed acute coronary syndrome', 'goals': ['Rapid reperfusion', 'Pain control', 'Complication prevention'], 'interventions': ['ECG within 10 minutes', 'Cardiac enzymes', 'Antiplatelet therapy', 'Anticoagulation'], 'monitoring_parameters': ['ECG changes', 'Cardiac enzymes', 'Vital signs', 'Pain assessment'], 'success_rate': 85.0, 'average_duration': 7 }, { 'name': 'Diabetes Mellitus Type 2 Management', 'indication': 'Comprehensive management of type 2 diabetes mellitus', 'goals': ['Glycemic control (HbA1c < 7%)', 'Cardiovascular risk reduction', 'Prevention of complications'], 'interventions': ['Lifestyle modification', 'Oral hypoglycemics', 'Insulin therapy', 'Regular monitoring'], 'monitoring_parameters': ['HbA1c', 'Fasting glucose', 'Blood pressure', 'Lipid profile'], 'success_rate': 75.0, 'average_duration': 365 }, { 'name': 'Community Acquired Pneumonia Treatment', 'indication': 'Treatment of community-acquired pneumonia in adults', 'goals': ['Clinical cure', 'Prevention of complications', 'Appropriate antibiotic use'], 'interventions': ['Appropriate antibiotics', 'Supportive care', 'Vaccination assessment'], 'monitoring_parameters': ['Clinical improvement', 'Fever resolution', 'Oxygen saturation'], 'success_rate': 90.0, 'average_duration': 10 }, { 'name': 'Hypertension Management Protocol', 'indication': 'Management of essential hypertension', 'goals': ['BP control (< 130/80 mmHg)', 'Cardiovascular risk reduction', 'Organ protection'], 'interventions': ['Lifestyle modification', 'Antihypertensive therapy', 'Regular monitoring'], 'monitoring_parameters': ['Blood pressure', 'Electrolyte levels', 'Renal function'], 'success_rate': 70.0, 'average_duration': 180 }, { 'name': 'Acute Asthma Exacerbation Protocol', 'indication': 'Management of acute asthma exacerbations', 'goals': ['Rapid symptom relief', 'Prevention of respiratory failure', 'Hospitalization prevention'], 'interventions': ['Bronchodilators', 'Systemic corticosteroids', 'Oxygen therapy', 'Monitoring'], 'monitoring_parameters': ['Peak flow', 'Oxygen saturation', 'Respiratory rate', 'Clinical symptoms'], 'success_rate': 88.0, 'average_duration': 3 } ] for tenant in tenants: for template in protocol_templates: # Get providers for this tenant tenant_providers = [p for p in providers if p.tenant == tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {tenant.name}. Skipping protocol {template['name']}") continue try: protocol = TreatmentProtocol.objects.create( tenant=tenant, protocol_id=uuid.uuid4(), name=template['name'], description=f"Standardized protocol for {template['name'].lower()}", indication=template['indication'], goals=template['goals'], interventions=template['interventions'], monitoring_parameters=template['monitoring_parameters'], success_rate=Decimal(str(template['success_rate'])), average_duration=template['average_duration'], is_active=True, usage_count=random.randint(10, 200), created_at=django_timezone.now() - timedelta(days=random.randint(30, 365)), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 30)), created_by=random.choice(tenant_providers) ) protocols.append(protocol) except Exception as e: print(f"Error creating treatment protocol {template['name']}: {e}") continue print(f"Created {len(protocols)} treatment protocols") return protocols def create_clinical_guidelines(tenants): """Create clinical guidelines""" guidelines = [] guideline_templates = [ { 'title': 'Management of Heart Failure', 'organization': 'American Heart Association', 'summary': 'Comprehensive guidelines for the diagnosis and management of heart failure', 'publication_date': date(2022, 4, 1), 'version': '2022', 'keywords': ['heart failure', 'cardiology', 'HFrEF', 'HFpEF'], 'specialties': ['Cardiology', 'Internal Medicine', 'Family Medicine'] }, { 'title': 'Standards of Medical Care in Diabetes', 'organization': 'American Diabetes Association', 'summary': 'Comprehensive guidelines for the diagnosis and management of diabetes mellitus', 'publication_date': date(2023, 1, 1), 'version': '2023', 'keywords': ['diabetes', 'glycemia', 'complications', 'prevention'], 'specialties': ['Endocrinology', 'Internal Medicine', 'Family Medicine'] }, { 'title': 'Guidelines for the Prevention, Detection, Evaluation, and Management of High Blood Pressure', 'organization': 'American College of Cardiology/American Heart Association', 'summary': 'Evidence-based guidelines for hypertension management', 'publication_date': date(2017, 11, 13), 'version': '2017', 'keywords': ['hypertension', 'blood pressure', 'cardiovascular', 'risk'], 'specialties': ['Cardiology', 'Internal Medicine', 'Nephrology'] }, { 'title': 'Global Initiative for Asthma (GINA) Report', 'organization': 'Global Initiative for Asthma', 'summary': 'Global strategy for asthma management and prevention', 'publication_date': date(2023, 5, 1), 'version': '2023', 'keywords': ['asthma', 'respiratory', 'inhalers', 'control'], 'specialties': ['Pulmonology', 'Allergy', 'Pediatrics'] }, { 'title': 'Prevention and Management of Osteoporosis', 'organization': 'World Health Organization', 'summary': 'Guidelines for osteoporosis prevention and treatment', 'publication_date': date(2022, 1, 1), 'version': '2022', 'keywords': ['osteoporosis', 'bone density', 'fracture', 'calcium'], 'specialties': ['Endocrinology', 'Rheumatology', 'Geriatrics'] } ] for tenant in tenants: for template in guideline_templates: try: guideline = ClinicalGuideline.objects.create( tenant=tenant, guideline_id=uuid.uuid4(), title=template['title'], organization=template['organization'], summary=template['summary'], url=f"https://example.com/guidelines/{template['title'].lower().replace(' ', '_')}", publication_date=template['publication_date'], last_updated=django_timezone.now().date() - timedelta(days=random.randint(0, 365)), version=template['version'], is_active=True, keywords=template['keywords'], specialties=template['specialties'], created_at=django_timezone.now() - timedelta(days=random.randint(30, 365)), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 30)) ) guidelines.append(guideline) except Exception as e: print(f"Error creating clinical guideline {template['title']}: {e}") continue print(f"Created {len(guidelines)} clinical guidelines") return guidelines def create_critical_alerts(patients, providers, encounters): """Create critical alerts for patients""" alerts = [] alert_templates = [ { 'title': 'Critical Lab Value Alert', 'description': 'Potassium level critically elevated at 7.2 mEq/L', 'priority': 'CRITICAL', 'recommendation': 'Immediate treatment with calcium gluconate, insulin, and glucose. Transfer to ICU.' }, { 'title': 'Acute Coronary Syndrome Alert', 'description': 'ST-elevation myocardial infarction detected on ECG', 'priority': 'CRITICAL', 'recommendation': 'Activate cardiac catheterization lab. Administer aspirin, heparin, and prepare for PCI.' }, { 'title': 'Severe Hypoglycemia Alert', 'description': 'Blood glucose critically low at 35 mg/dL', 'priority': 'CRITICAL', 'recommendation': 'Administer IV dextrose immediately. Recheck glucose in 15 minutes.' }, { 'title': 'Acute Stroke Alert', 'description': 'Suspected acute ischemic stroke with NIHSS score of 18', 'priority': 'URGENT', 'recommendation': 'Activate stroke team. Obtain CT brain immediately. Prepare for thrombolytic therapy.' }, { 'title': 'Sepsis Alert', 'description': 'SIRS criteria met with suspected infection. Lactate elevated at 4.2 mmol/L', 'priority': 'URGENT', 'recommendation': 'Obtain blood cultures, start broad-spectrum antibiotics within 1 hour, fluid resuscitation.' }, { 'title': 'Drug Interaction Alert', 'description': 'Critical drug interaction between warfarin and newly prescribed antibiotic', 'priority': 'HIGH', 'recommendation': 'Monitor INR closely. Consider dose adjustment or alternative antibiotic.' }, { 'title': 'Allergy Alert - Severe Reaction', 'description': 'Patient with history of anaphylaxis to penicillin now prescribed amoxicillin', 'priority': 'HIGH', 'recommendation': 'Discontinue amoxicillin. Prescribe alternative antibiotic. Consider premedication if necessary.' } ] for patient in patients: # 5% of patients have critical alerts if random.random() > 0.05: continue # Each patient with alerts has 1-2 critical alerts num_alerts = random.randint(1, 2) patient_encounters = [e for e in encounters if e.patient == patient] for _ in range(num_alerts): template = random.choice(alert_templates) # Status tenant_providers = [p for p in providers if p.tenant == patient.tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {patient.tenant.name}. Skipping critical alert for {patient.get_full_name()}") continue acknowledged = random.choice([True, False]) acknowledged_by = random.choice(tenant_providers) if acknowledged else None acknowledged_at = django_timezone.now() - timedelta(hours=random.randint(1, 24)) if acknowledged else None # Expiration expires_at = django_timezone.now() + timedelta(hours=random.randint(24, 168)) # Related encounter related_encounter = random.choice(patient_encounters) if patient_encounters else None try: alert = CriticalAlert.objects.create( tenant=patient.tenant, patient=patient, alert_id=uuid.uuid4(), title=template['title'], description=template['description'], priority=template['priority'], recommendation=template['recommendation'], acknowledged=acknowledged, acknowledged_by=acknowledged_by, acknowledged_at=acknowledged_at, expires_at=expires_at, related_encounter=related_encounter, created_by=random.choice(tenant_providers), created_at=django_timezone.now() - timedelta(hours=random.randint(1, 48)), updated_at=django_timezone.now() - timedelta(minutes=random.randint(0, 60)) ) alerts.append(alert) except Exception as e: print(f"Error creating critical alert for {patient.get_full_name()}: {e}") continue print(f"Created {len(alerts)} critical alerts") return alerts def create_diagnostic_suggestions(patients, providers, encounters): """Create diagnostic suggestions for patients""" suggestions = [] suggestion_templates = [ { 'test_name': 'Echocardiogram', 'test_code': 'ECHO', 'indication': 'Evaluate cardiac function and structure', 'confidence': 85.0 }, { 'test_name': 'Coronary Angiography', 'test_code': 'CATH', 'indication': 'Assess coronary artery disease', 'confidence': 78.0 }, { 'test_name': 'MRI Brain', 'test_code': 'MRI_BRAIN', 'indication': 'Evaluate neurological symptoms', 'confidence': 72.0 }, { 'test_name': 'CT Chest', 'test_code': 'CT_CHEST', 'indication': 'Assess pulmonary pathology', 'confidence': 80.0 }, { 'test_name': 'Colonoscopy', 'test_code': 'COLON', 'indication': 'Screen for colorectal cancer', 'confidence': 88.0 }, { 'test_name': 'DEXA Scan', 'test_code': 'DEXA', 'indication': 'Assess bone mineral density', 'confidence': 90.0 }, { 'test_name': 'Thyroid Function Tests', 'test_code': 'TFT', 'indication': 'Evaluate thyroid dysfunction', 'confidence': 75.0 }, { 'test_name': 'HbA1c', 'test_code': 'HBA1C', 'indication': 'Assess long-term glycemic control', 'confidence': 95.0 } ] for patient in patients: # 15% of patients have diagnostic suggestions if random.random() > 0.15: continue # Each patient with suggestions has 1-3 suggestions num_suggestions = random.randint(1, 3) patient_encounters = [e for e in encounters if e.patient == patient] for _ in range(num_suggestions): template = random.choice(suggestion_templates) # Status status = random.choices( ['PENDING', 'ORDERED', 'COMPLETED'], weights=[50, 30, 20] )[0] # Provider assignments tenant_providers = [p for p in providers if p.tenant == patient.tenant] if not tenant_providers: print(f"Warning: No providers found for tenant {patient.tenant.name}. Skipping diagnostic suggestion for {patient.get_full_name()}") continue ordered_by = None ordered_at = None if status in ['ORDERED', 'COMPLETED']: ordered_by = random.choice(tenant_providers) ordered_at = django_timezone.now() - timedelta(days=random.randint(1, 14)) try: suggestion = DiagnosticSuggestion.objects.create( tenant=patient.tenant, patient=patient, suggestion_id=uuid.uuid4(), test_name=template['test_name'], test_code=template['test_code'], indication=template['indication'], confidence=Decimal(str(template['confidence'])), status=status, ordered_by=ordered_by, ordered_at=ordered_at, created_by=random.choice(tenant_providers), created_at=django_timezone.now() - timedelta(days=random.randint(1, 30)), updated_at=django_timezone.now() - timedelta(days=random.randint(0, 7)) ) suggestions.append(suggestion) except Exception as e: print(f"Error creating diagnostic suggestion for {patient.get_full_name()}: {e}") continue print(f"Created {len(suggestions)} diagnostic suggestions") return suggestions # ============================================================================ # ICD-10 XML IMPORT FUNCTIONS (from import_icd10.py management command) # ============================================================================ def _as_text(val): """Convert value to text string""" if val is None: return None if isinstance(val, dict): return val.get("#text") or val.get("@value") or val.get("value") or str(val) return str(val) def _ensure_list(maybe_list): """Ensure value is a list""" if maybe_list is None: return [] if isinstance(maybe_list, list): return maybe_list return [maybe_list] def _find_first_with_key(data, key): """Depth-first search: return the first dict that directly contains `key`""" if isinstance(data, dict): if key in data: return data for v in data.values(): found = _find_first_with_key(v, key) if found is not None: return found elif isinstance(data, list): for item in data: found = _find_first_with_key(item, key) if found is not None: return found return None def _collect_icd10_rows(chapters, tenants): """ Build Icd10 rows + parent links from chapters dict/list. Expected structure: chapter -> section? -> diag (recursive) """ rows = [] parent_links = [] def import_diag(diag, chapter_name, section_name, parent_code, tenant): code = _as_text(diag.get("name")) desc = _as_text(diag.get("desc")) if not code: return children = _ensure_list(diag.get("diag")) is_header = bool(children) and not (desc and desc.strip()) rows.append(Icd10( tenant=tenant, code=code, description=desc, chapter_name=_as_text(chapter_name), section_name=_as_text(section_name), parent=None, # set later is_header=is_header, )) if parent_code: parent_links.append((code, parent_code, tenant)) for child in children: import_diag(child, chapter_name, section_name, parent_code=code, tenant=tenant) # Normalize chapters to a list chapters = _ensure_list(chapters) # Process for each tenant for tenant in tenants: for ch in chapters: ch_name = _as_text(ch.get("name")) # Sections may be missing; diags may be directly under chapter sections = _ensure_list(ch.get("section")) if sections: for sec in sections: sec_name = _as_text(sec.get("name")) for d in _ensure_list(sec.get("diag")): import_diag(d, ch_name, sec_name, parent_code=None, tenant=tenant) else: # If no sections, look for diags at chapter level for d in _ensure_list(ch.get("diag")): import_diag(d, ch_name, None, parent_code=None, tenant=tenant) return rows, parent_links def import_icd10_from_xml(xsd_path, xml_path, tenants, truncate=False): """ Import ICD-10-CM codes from XML file. Args: xsd_path: Path to XSD schema file xml_path: Path to XML data file tenants: List of tenant objects to import codes for truncate: Whether to delete existing codes first Returns: Number of codes imported """ if not XMLSCHEMA_AVAILABLE: print("āŒ Error: xmlschema library not installed.") print(" Install it with: pip install xmlschema") return 0 print(f"\nšŸ“„ Importing ICD-10 codes from XML...") print(f" XSD: {xsd_path}") print(f" XML: {xml_path}") try: xs = xmlschema.XMLSchema(xsd_path) except Exception as e: print(f"āŒ Failed to load XSD: {e}") return 0 try: data = xs.to_dict(xml_path) except Exception as e: print(f"āŒ Failed to parse XML: {e}") return 0 # Unwrap root if single-key dict if isinstance(data, dict) and len(data) == 1: root_key, root_val = next(iter(data.items())) root = root_val else: root = data # Find container with "chapter" key container_with_chapter = _find_first_with_key(root, "chapter") if not container_with_chapter: container_with_chapter = _find_first_with_key(root, "chapters") if container_with_chapter and isinstance(container_with_chapter.get("chapters"), dict): if "chapter" in container_with_chapter["chapters"]: container_with_chapter = container_with_chapter["chapters"] if not container_with_chapter or ("chapter" not in container_with_chapter): preview_keys = list(root.keys()) if isinstance(root, dict) else type(root) print(f"āŒ Could not locate 'chapter' in XML. Top-level keys: {preview_keys}") return 0 chapters = container_with_chapter.get("chapter") if chapters is None: print("āŒ Found container for chapters, but 'chapter' is empty.") return 0 # Optionally truncate if truncate: print("āš ļø Truncating existing ICD-10 data...") Icd10.objects.all().delete() # Collect rows + parent links print("šŸ“Š Collecting ICD-10 rows...") rows, parent_links = _collect_icd10_rows(chapters, tenants) print(f"āœ… Collected {len(rows)} rows. Inserting...") BATCH = 1000 with transaction.atomic(): for i in range(0, len(rows), BATCH): Icd10.objects.bulk_create(rows[i:i+BATCH], ignore_conflicts=True) # Link parents if parent_links: print("šŸ”— Linking parent relationships...") code_to_obj = {} for tenant in tenants: tenant_codes = {o.code: o for o in Icd10.objects.filter(tenant=tenant).only("id", "code")} code_to_obj[tenant.id] = tenant_codes updates = [] for child_code, parent_code, tenant in parent_links: tenant_codes = code_to_obj.get(tenant.id, {}) child = tenant_codes.get(child_code) parent = tenant_codes.get(parent_code) if child and parent and child.parent_id != parent.id: child.parent_id = parent.id updates.append(child) for i in range(0, len(updates), BATCH): Icd10.objects.bulk_update(updates[i:i+BATCH], ["parent"]) print(f"āœ… Linked {len(updates)} parent relations.") print(f"āœ… ICD-10 import completed: {len(rows)} codes imported") return len(rows) # ============================================================================ # MAIN DATA GENERATION FUNCTIONS # ============================================================================ def parse_arguments(): """Parse command-line arguments""" parser = argparse.ArgumentParser( description='Generate EMR sample data and optionally import ICD-10 codes from XML' ) parser.add_argument( '--import-icd10', action='store_true', help='Import full ICD-10 codes from XML files' ) parser.add_argument( '--xsd', type=str, help='Path to ICD-10 XSD schema file (required with --import-icd10)' ) parser.add_argument( '--xml', type=str, help='Path to ICD-10 XML data file (required with --import-icd10)' ) parser.add_argument( '--icd10-only', action='store_true', help='Only import ICD-10 codes, skip other EMR data generation' ) parser.add_argument( '--truncate', action='store_true', help='Delete existing ICD-10 codes before importing' ) return parser.parse_args() def main(): """Main function to generate all EMR data""" # Parse command-line arguments args = parse_arguments() # Validate ICD-10 import arguments if args.import_icd10 or args.icd10_only: if not args.xsd or not args.xml: print("āŒ Error: --xsd and --xml are required when using --import-icd10 or --icd10-only") sys.exit(1) if not XMLSCHEMA_AVAILABLE: print("āŒ Error: xmlschema library not installed.") print(" Install it with: pip install xmlschema") sys.exit(1) # Get existing tenants tenants = list(Tenant.objects.all()) if not tenants: print("āŒ No tenants found. Please run the core data generator first.") return # ICD-10 only mode if args.icd10_only: print("šŸ„ ICD-10 Import Mode (skipping other EMR data)") import_icd10_from_xml(args.xsd, args.xml, tenants, truncate=args.truncate) return # Standard EMR data generation print("Starting Saudi Healthcare EMR Data Generation...") # Get existing tenants tenants = list(Tenant.objects.all()) if not tenants: print("āŒ No tenants found. Please run the core data generator first.") return # Create note templates print("\n1. Creating Note Templates...") templates = create_note_templates(tenants) # Create encounters print("\n2. Creating Patient Encounters...") encounters = create_encounters(tenants, days_back=30) # Create vital signs print("\n3. Creating Vital Signs...") vital_signs = create_vital_signs(encounters) # Get patients and providers for remaining models patients = list(PatientProfile.objects.filter(tenant__in=tenants)) providers = get_providers_for_emr(tenants) # Create problem lists print("\n4. Creating Problem Lists...") problems = create_problem_lists(patients, providers) # Create care plans print("\n5. Creating Care Plans...") care_plans = create_care_plans(patients, providers, problems) # Create clinical notes print("\n6. Creating Clinical Notes...") clinical_notes = create_clinical_notes(encounters, templates) # Create ICD-10 codes (sample or full import) print("\n7. Creating ICD-10 Codes...") if args.import_icd10: # Import full ICD-10 from XML num_imported = import_icd10_from_xml(args.xsd, args.xml, tenants, truncate=args.truncate) icd10_codes = list(Icd10.objects.filter(tenant__in=tenants)) else: # Create sample ICD-10 codes icd10_codes = create_icd10_codes(tenants) # Create clinical recommendations print("\n8. Creating Clinical Recommendations...") clinical_recommendations = create_clinical_recommendations(patients, providers, problems, encounters) # Create allergy alerts print("\n9. Creating Allergy Alerts...") allergy_alerts = create_allergy_alerts(patients, providers) # Create treatment protocols print("\n10. Creating Treatment Protocols...") treatment_protocols = create_treatment_protocols(tenants, providers) # Create clinical guidelines print("\n11. Creating Clinical Guidelines...") clinical_guidelines = create_clinical_guidelines(tenants) # Create critical alerts print("\n12. Creating Critical Alerts...") critical_alerts = create_critical_alerts(patients, providers, encounters) # Create diagnostic suggestions print("\n13. Creating Diagnostic Suggestions...") diagnostic_suggestions = create_diagnostic_suggestions(patients, providers, encounters) print(f"\nāœ… Saudi Healthcare EMR Data Generation Complete!") print(f"šŸ“Š Summary:") print(f" - Note Templates: {len(templates)}") print(f" - Patient Encounters: {len(encounters)}") print(f" - Vital Signs Records: {len(vital_signs)}") print(f" - Problem List Entries: {len(problems)}") print(f" - Care Plans: {len(care_plans)}") print(f" - Clinical Notes: {len(clinical_notes)}") print(f" - ICD-10 Codes: {len(icd10_codes)}") print(f" - Clinical Recommendations: {len(clinical_recommendations)}") print(f" - Allergy Alerts: {len(allergy_alerts)}") print(f" - Treatment Protocols: {len(treatment_protocols)}") print(f" - Clinical Guidelines: {len(clinical_guidelines)}") print(f" - Critical Alerts: {len(critical_alerts)}") print(f" - Diagnostic Suggestions: {len(diagnostic_suggestions)}") # Statistics if encounters: encounter_type_counts = {} for encounter in encounters: encounter_type_counts[encounter.encounter_type] = encounter_type_counts.get(encounter.encounter_type, 0) + 1 print(f"\nšŸ“ˆ Encounter Type Distribution:") for enc_type, count in sorted(encounter_type_counts.items(), key=lambda x: x[1], reverse=True)[:10]: print(f" - {enc_type.replace('_', ' ').title()}: {count}") if problems: problem_status_counts = {} for problem in problems: problem_status_counts[problem.status] = problem_status_counts.get(problem.status, 0) + 1 print(f"\nšŸ“‹ Problem Status Distribution:") for status, count in problem_status_counts.items(): print(f" - {status.title()}: {count}") return { 'templates': templates, 'encounters': encounters, 'vital_signs': vital_signs, 'problems': problems, 'care_plans': care_plans, 'clinical_notes': clinical_notes, 'icd10_codes': icd10_codes, 'clinical_recommendations': clinical_recommendations, 'allergy_alerts': allergy_alerts, 'treatment_protocols': treatment_protocols, 'clinical_guidelines': clinical_guidelines, 'critical_alerts': critical_alerts, 'diagnostic_suggestions': diagnostic_suggestions } if __name__ == "__main__": main()