523 lines
22 KiB
Python
523 lines
22 KiB
Python
import os
|
||
import django
|
||
|
||
# Set up Django environment
|
||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hospital_management.settings')
|
||
django.setup()
|
||
|
||
import uuid
|
||
import random
|
||
from datetime import datetime, timedelta, date
|
||
from django.utils import timezone as django_timezone
|
||
from django.contrib.auth import get_user_model
|
||
from core.models import Tenant
|
||
from patients.models import (
|
||
PatientProfile, EmergencyContact, InsuranceInfo,
|
||
ConsentTemplate, ConsentForm, PatientNote
|
||
)
|
||
|
||
User = get_user_model()
|
||
|
||
# Saudi-inspired names and data
|
||
SAUDI_FIRST_NAMES_MALE = [
|
||
'Abdullah', 'Mohammed', 'Ahmad', 'Ali', 'Omar', 'Khalid', 'Fahd', 'Sultan',
|
||
'Faisal', 'Saud', 'Abdulrahman', 'Abdulaziz', 'Turki', 'Bandar', 'Nasser',
|
||
'Saad', 'Majed', 'Waleed', 'Yousef', 'Ibrahim', 'Hassan', 'Hussein'
|
||
]
|
||
|
||
SAUDI_FIRST_NAMES_FEMALE = [
|
||
'Fatima', 'Aisha', 'Khadija', 'Maryam', 'Nora', 'Sarah', 'Hala', 'Reem',
|
||
'Layla', 'Amina', 'Zahra', 'Lina', 'Nada', 'Rana', 'Dina', 'Hind',
|
||
'Najla', 'Arwa', 'Ghada', 'Nouf', 'Abeer', 'Thuraya', 'Wafa', 'Lama'
|
||
]
|
||
|
||
SAUDI_FAMILY_NAMES = [
|
||
'Al-Saud', 'Al-Rashid', 'Al-Mutairi', 'Al-Otaibi', 'Al-Qarni', 'Al-Harbi',
|
||
'Al-Dawsari', 'Al-Subai', 'Al-Sharani', 'Al-Ghamdi', 'Al-Zahrani', 'Al-Maliki',
|
||
'Al-Shehri', 'Al-Qahtani', 'Al-Ansari', 'Al-Hakim', 'Al-Rashidi', 'Al-Bakr'
|
||
]
|
||
|
||
SAUDI_CITIES = [
|
||
'Riyadh', 'Jeddah', 'Mecca', 'Medina', 'Dammam', 'Khobar', 'Dhahran',
|
||
'Taif', 'Tabuk', 'Buraidah', 'Khamis Mushait', 'Hail', 'Najran'
|
||
]
|
||
|
||
SAUDI_STATES = [
|
||
'Riyadh Province', 'Makkah Province', 'Eastern Province', 'Asir Province',
|
||
'Jazan Province', 'Madinah Province', 'Qassim Province', 'Tabuk Province'
|
||
]
|
||
|
||
SAUDI_LANGUAGES = ['Arabic', 'English']
|
||
|
||
SAUDI_ALLERGIES = [
|
||
'Penicillin', 'Aspirin', 'Ibuprofen', 'Sulfa drugs', 'Contrast dye',
|
||
'Peanuts', 'Shellfish', 'Dairy', 'Eggs', 'Tree nuts', 'Latex'
|
||
]
|
||
|
||
SAUDI_INSURANCE_COMPANIES = [
|
||
'Saudi Enaya Cooperative Insurance', 'Bupa Arabia', 'Tawuniya',
|
||
'Malath Insurance', 'Walaa Insurance', 'Gulf Union Alahlia Insurance'
|
||
]
|
||
|
||
SAUDI_CONSENT_CATEGORIES = [
|
||
'TREATMENT', 'PROCEDURE', 'SURGERY', 'ANESTHESIA', 'RESEARCH'
|
||
]
|
||
|
||
|
||
def generate_saudi_phone():
|
||
"""Generate Saudi phone number"""
|
||
return f"+966{random.randint(11, 17)}{random.randint(1000000, 9999999)}"
|
||
|
||
|
||
def generate_saudi_mobile():
|
||
"""Generate Saudi mobile number"""
|
||
return f"+966{random.randint(50, 59)}{random.randint(1000000, 9999999)}"
|
||
|
||
|
||
def generate_saudi_medical_record_number():
|
||
"""Generate medical record number"""
|
||
return f"MRN{random.randint(100000, 999999)}"
|
||
|
||
|
||
def create_saudi_patient_profiles():
|
||
"""Create Saudi patient profiles using only valid model fields"""
|
||
print("Creating Saudi patient profiles...")
|
||
|
||
tenants = list(Tenant.objects.all())
|
||
if not tenants:
|
||
print("No tenants found. Please create tenants first.")
|
||
return []
|
||
|
||
profiles_created = 0
|
||
created_profiles = []
|
||
|
||
for i in range(50): # Start with 50 patients
|
||
try:
|
||
tenant = random.choice(tenants)
|
||
gender = random.choice(['MALE', 'FEMALE'])
|
||
|
||
if gender == 'MALE':
|
||
first_name = random.choice(SAUDI_FIRST_NAMES_MALE)
|
||
else:
|
||
first_name = random.choice(SAUDI_FIRST_NAMES_FEMALE)
|
||
|
||
last_name = random.choice(SAUDI_FAMILY_NAMES)
|
||
|
||
# Generate birth date (18-85 years old)
|
||
birth_year = random.randint(1939, 2006)
|
||
birth_month = random.randint(1, 12)
|
||
birth_day = random.randint(1, 28)
|
||
date_of_birth = date(birth_year, birth_month, birth_day)
|
||
|
||
# Generate unique MRN
|
||
mrn = random.randint(100000, 999999)
|
||
|
||
# Check if MRN already exists
|
||
while PatientProfile.objects.filter(mrn=mrn).exists():
|
||
mrn = f"MRN{tenant.id}{random.randint(100000, 999999)}"
|
||
|
||
# Only use fields that actually exist in the model
|
||
profile = PatientProfile.objects.create(
|
||
tenant=tenant,
|
||
mrn=mrn,
|
||
first_name=first_name,
|
||
last_name=last_name,
|
||
middle_name=random.choice(SAUDI_FIRST_NAMES_MALE + SAUDI_FIRST_NAMES_FEMALE) if random.choice(
|
||
[True, False]) else None,
|
||
preferred_name=first_name if random.choice([True, False]) else None,
|
||
suffix=random.choice([None, 'Jr.', 'Sr.']) if random.random() < 0.05 else None,
|
||
date_of_birth=date_of_birth,
|
||
gender=gender,
|
||
|
||
# Contact Information
|
||
email=f"{first_name.lower()}.{last_name.lower().replace('-', '').replace(' ', '')}@email.com" if random.choice(
|
||
[True, False]) else None,
|
||
phone_number=generate_saudi_phone() if random.choice([True, False]) else None,
|
||
mobile_number=generate_saudi_mobile(),
|
||
|
||
# Address - using correct field names from model
|
||
address_line_1=f"{random.randint(1, 999)} {random.choice(['King Fahd Road', 'Prince Sultan Street', 'Al Malik Road'])}",
|
||
address_line_2=f"Apt {random.randint(1, 50)}" if random.choice([True, False]) else None,
|
||
city=random.choice(SAUDI_CITIES),
|
||
state=random.choice(SAUDI_STATES),
|
||
zip_code=f"{random.randint(10000, 99999)}",
|
||
country='Saudi Arabia',
|
||
|
||
# Demographics
|
||
marital_status=random.choice(['SINGLE', 'MARRIED', 'DIVORCED', 'WIDOWED']),
|
||
occupation=random.choice([
|
||
'Engineer', 'Teacher', 'Doctor', 'Nurse', 'Government Employee',
|
||
'Business Owner', 'Student', 'Retired', 'Homemaker'
|
||
]) if random.choice([True, False]) else None,
|
||
employer=random.choice([
|
||
'Saudi Aramco', 'SABIC', 'Ministry of Health', 'King Saud University',
|
||
'Saudi Telecom Company', 'Al Rajhi Bank'
|
||
]) if random.choice([True, False]) else None,
|
||
|
||
# Language and Communication
|
||
primary_language=random.choice(SAUDI_LANGUAGES),
|
||
interpreter_needed=random.choice([True, False]) if random.random() < 0.1 else False,
|
||
communication_preference=random.choice(['PHONE', 'EMAIL', 'SMS', 'MAIL']),
|
||
|
||
# Healthcare Information
|
||
primary_care_physician=f"Dr. {random.choice(SAUDI_FIRST_NAMES_MALE + SAUDI_FIRST_NAMES_FEMALE)} {random.choice(SAUDI_FAMILY_NAMES)}" if random.choice(
|
||
[True, False]) else None,
|
||
|
||
# Medical Information
|
||
allergies=', '.join(random.sample(SAUDI_ALLERGIES, random.randint(0, 3))) if random.choice(
|
||
[True, False]) else None,
|
||
medical_alerts=random.choice([
|
||
'Patient has diabetes - monitor blood sugar',
|
||
'Hypertension - check BP regularly',
|
||
'Patient requires wheelchair assistance',
|
||
'Arabic speaking only'
|
||
]) if random.choice([True, False]) else None,
|
||
|
||
# Advance Directives
|
||
has_advance_directive=random.choice([True, False]) if random.random() < 0.2 else False,
|
||
advance_directive_type=random.choice(['LIVING_WILL', 'HEALTHCARE_PROXY', 'DNR']) if random.choice(
|
||
[True, False]) else None,
|
||
|
||
# Status
|
||
is_active=True,
|
||
is_deceased=False,
|
||
is_vip=random.choice([True, False]) if random.random() < 0.05 else False,
|
||
confidential_patient=random.choice([True, False]) if random.random() < 0.02 else False,
|
||
|
||
# Registration date in the past
|
||
registration_date=django_timezone.now() - timedelta(days=random.randint(1, 365)),
|
||
last_visit_date=django_timezone.now() - timedelta(days=random.randint(1, 90)) if random.choice(
|
||
[True, False]) else None,
|
||
)
|
||
|
||
created_profiles.append(profile)
|
||
profiles_created += 1
|
||
|
||
if profiles_created % 10 == 0:
|
||
print(f"Created {profiles_created} patient profiles...")
|
||
|
||
except Exception as e:
|
||
print(f"Error creating patient profile {i}: {str(e)}")
|
||
continue
|
||
|
||
print(f"Successfully created {profiles_created} Saudi patient profiles.")
|
||
return created_profiles
|
||
|
||
|
||
def create_saudi_emergency_contacts(patients):
|
||
"""Create emergency contacts for patients"""
|
||
print("Creating Saudi emergency contacts...")
|
||
|
||
contacts_created = 0
|
||
|
||
for patient in patients:
|
||
# Create 1-2 emergency contacts per patient
|
||
num_contacts = random.randint(1, 2)
|
||
|
||
for i in range(num_contacts):
|
||
try:
|
||
gender = random.choice(['MALE', 'FEMALE'])
|
||
|
||
if gender == 'MALE':
|
||
first_name = random.choice(SAUDI_FIRST_NAMES_MALE)
|
||
else:
|
||
first_name = random.choice(SAUDI_FIRST_NAMES_FEMALE)
|
||
|
||
EmergencyContact.objects.create(
|
||
patient=patient,
|
||
first_name=first_name,
|
||
last_name=random.choice(SAUDI_FAMILY_NAMES),
|
||
relationship=random.choice([
|
||
'SPOUSE', 'PARENT', 'CHILD', 'SIBLING', 'FRIEND', 'OTHER'
|
||
]),
|
||
phone_number=generate_saudi_mobile(),
|
||
mobile_number=generate_saudi_phone() if random.choice([True, False]) else None,
|
||
email=f"{first_name.lower()}@email.com" if random.choice([True, False]) else None,
|
||
address_line_1=f"{random.randint(1, 999)} {random.choice(['King Fahd Road', 'Prince Sultan Street'])}",
|
||
city=random.choice(SAUDI_CITIES),
|
||
state=random.choice(SAUDI_STATES),
|
||
zip_code=f"{random.randint(10000, 99999)}",
|
||
priority=i + 1,
|
||
is_authorized_for_medical_decisions=i == 0,
|
||
is_authorized_for_information=True,
|
||
notes=random.choice([
|
||
'Available during business hours',
|
||
'Contact only in emergencies',
|
||
'Primary caregiver'
|
||
]) if random.choice([True, False]) else None,
|
||
)
|
||
|
||
contacts_created += 1
|
||
|
||
except Exception as e:
|
||
print(f"Error creating emergency contact for patient {patient.mrn}: {str(e)}")
|
||
continue
|
||
|
||
print(f"Successfully created {contacts_created} emergency contacts.")
|
||
return contacts_created
|
||
|
||
|
||
def create_saudi_insurance_info(patients):
|
||
"""Create insurance information for patients"""
|
||
print("Creating Saudi insurance information...")
|
||
|
||
insurance_created = 0
|
||
|
||
for patient in patients:
|
||
# 80% of patients have insurance
|
||
if random.random() < 0.8:
|
||
try:
|
||
company = random.choice(SAUDI_INSURANCE_COMPANIES)
|
||
|
||
InsuranceInfo.objects.create(
|
||
patient=patient,
|
||
insurance_type=random.choice(['PRIMARY', 'SECONDARY']),
|
||
insurance_company=company,
|
||
plan_name=f"{company} Standard Plan" if random.choice([True, False]) else None,
|
||
plan_type=random.choice(['HMO', 'PPO', 'OTHER']),
|
||
policy_number=f"{company[:3].upper()}{random.randint(100000, 999999)}",
|
||
group_number=f"GRP{random.randint(1000, 9999)}" if random.choice([True, False]) else None,
|
||
subscriber_name=f"{patient.first_name} {patient.last_name}",
|
||
subscriber_relationship=random.choice(['SELF', 'SPOUSE', 'CHILD', 'PARENT']),
|
||
subscriber_dob=patient.date_of_birth if random.choice([True, False]) else None,
|
||
effective_date=date.today() - timedelta(days=random.randint(30, 730)),
|
||
termination_date=date.today() + timedelta(days=random.randint(30, 365)) if random.choice(
|
||
[True, False]) else None,
|
||
copay_amount=random.choice([50, 100, 150, 200]),
|
||
deductible_amount=random.choice([500, 1000, 2000, 3000]),
|
||
out_of_pocket_max=random.choice([5000, 7500, 10000]) if random.choice([True, False]) else None,
|
||
is_verified=random.choice([True, False]),
|
||
verification_date=django_timezone.now() - timedelta(days=random.randint(1, 30)) if random.choice(
|
||
[True, False]) else None,
|
||
)
|
||
|
||
insurance_created += 1
|
||
|
||
except Exception as e:
|
||
print(f"Error creating insurance info for patient {patient.mrn}: {str(e)}")
|
||
continue
|
||
|
||
print(f"Successfully created {insurance_created} insurance records.")
|
||
return insurance_created
|
||
|
||
|
||
def create_saudi_consent_templates():
|
||
"""Create consent form templates"""
|
||
print("Creating Saudi consent templates...")
|
||
|
||
tenants = list(Tenant.objects.all())
|
||
templates_created = 0
|
||
|
||
consent_data = [
|
||
('General Treatment Consent', 'TREATMENT', 'Standard consent for medical treatment'),
|
||
('Surgery Consent', 'SURGERY', 'Consent for surgical procedures'),
|
||
('Anesthesia Consent', 'ANESTHESIA', 'Consent for anesthesia administration'),
|
||
('Procedure Consent', 'PROCEDURE', 'Consent for medical procedures'),
|
||
('Research Consent', 'RESEARCH', 'Consent for research participation'),
|
||
]
|
||
|
||
for tenant in tenants:
|
||
for name, category, description in consent_data:
|
||
try:
|
||
ConsentTemplate.objects.create(
|
||
tenant=tenant,
|
||
name=name,
|
||
description=description,
|
||
category=category,
|
||
content=f"""
|
||
CONSENT FOR {name.upper()}
|
||
|
||
I, the undersigned patient, acknowledge that I have been informed about the nature of the proposed {name.lower()}.
|
||
|
||
I understand that:
|
||
1. The procedure/treatment has been explained to me
|
||
2. Alternative treatments have been discussed
|
||
3. Risks and benefits have been explained
|
||
4. I have had the opportunity to ask questions
|
||
|
||
I hereby give my informed consent.
|
||
|
||
Patient Signature: _____________________ Date: ___________
|
||
""".strip(),
|
||
version='1.0',
|
||
is_active=True,
|
||
requires_signature=True,
|
||
requires_witness=random.choice([True, False]),
|
||
requires_guardian=random.choice([True, False]),
|
||
effective_date=django_timezone.now().date(),
|
||
expiry_date=django_timezone.now().date() + timedelta(days=365) if random.choice(
|
||
[True, False]) else None,
|
||
)
|
||
|
||
templates_created += 1
|
||
|
||
except Exception as e:
|
||
print(f"Error creating consent template '{name}' for tenant {tenant.name}: {str(e)}")
|
||
continue
|
||
|
||
print(f"Successfully created {templates_created} consent templates.")
|
||
return templates_created
|
||
|
||
|
||
def create_saudi_consent_forms(patients, templates):
|
||
"""Create completed consent forms for patients"""
|
||
print("Creating Saudi consent forms...")
|
||
|
||
users = list(User.objects.filter(is_active=True))
|
||
forms_created = 0
|
||
|
||
for patient in patients:
|
||
# Each patient has 1-2 consent forms
|
||
num_forms = random.randint(1, 2)
|
||
patient_templates = [t for t in templates if t.tenant == patient.tenant]
|
||
|
||
if not patient_templates:
|
||
continue
|
||
|
||
selected_templates = random.sample(patient_templates, min(num_forms, len(patient_templates)))
|
||
|
||
for template in selected_templates:
|
||
try:
|
||
signed_datetime = django_timezone.now() - timedelta(days=random.randint(1, 180))
|
||
|
||
ConsentForm.objects.create(
|
||
patient=patient,
|
||
template=template,
|
||
status='SIGNED', # Use the correct field name from model
|
||
patient_signature=f"Digital signature by {patient.get_full_name()}",
|
||
patient_signed_at=signed_datetime, # Use the correct field name
|
||
guardian_signature=f"Guardian signature for {patient.get_full_name()}" if template.requires_guardian and patient.age and patient.age < 18 else None,
|
||
guardian_signed_at=signed_datetime if template.requires_guardian and patient.age and patient.age < 18 else None,
|
||
guardian_name=f"{random.choice(SAUDI_FIRST_NAMES_MALE + SAUDI_FIRST_NAMES_FEMALE)} {random.choice(SAUDI_FAMILY_NAMES)}" if template.requires_guardian and patient.age and patient.age < 18 else None,
|
||
guardian_relationship=random.choice(['PARENT',
|
||
'GUARDIAN']) if template.requires_guardian and patient.age and patient.age < 18 else None,
|
||
witness_signature=f"Witness signature" if template.requires_witness else None,
|
||
witness_signed_at=signed_datetime if template.requires_witness else None, # Use correct field name
|
||
witness_name=f"{random.choice(SAUDI_FIRST_NAMES_MALE + SAUDI_FIRST_NAMES_FEMALE)} {random.choice(SAUDI_FAMILY_NAMES)}" if template.requires_witness else None,
|
||
witness_title=random.choice(
|
||
['Nurse', 'Administrator', 'Staff']) if template.requires_witness else None,
|
||
provider_name=f"Dr. {random.choice(SAUDI_FIRST_NAMES_MALE + SAUDI_FIRST_NAMES_FEMALE)} {random.choice(SAUDI_FAMILY_NAMES)}" if random.choice(
|
||
[True, False]) else None,
|
||
effective_date=signed_datetime,
|
||
expiry_date=signed_datetime + timedelta(days=365) if template.expiry_date else None,
|
||
created_by=random.choice(users) if users and random.choice([True, False]) else None,
|
||
notes=random.choice([
|
||
'Patient fully understood the procedure',
|
||
'All questions answered satisfactorily',
|
||
'Consent obtained in Arabic',
|
||
'Interpreter services provided'
|
||
]) if random.choice([True, False]) else None,
|
||
)
|
||
|
||
forms_created += 1
|
||
|
||
except Exception as e:
|
||
print(f"Error creating consent form for patient {patient.mrn}: {str(e)}")
|
||
continue
|
||
|
||
print(f"Successfully created {forms_created} consent forms.")
|
||
return forms_created
|
||
|
||
|
||
def create_saudi_patient_notes(patients):
|
||
"""Create patient notes"""
|
||
print("Creating Saudi patient notes...")
|
||
|
||
users = list(User.objects.filter(is_active=True))
|
||
notes_created = 0
|
||
|
||
note_data = [
|
||
('Routine Check-up', 'Patient presents for routine examination. Vital signs stable.', 'CLINICAL'),
|
||
('Insurance Verification', 'Insurance information verified and updated.', 'ADMINISTRATIVE'),
|
||
('Follow-up Required', 'Patient requires follow-up in 2 weeks.', 'CLINICAL'),
|
||
('Billing Note', 'Updated billing information and payment plan.', 'BILLING'),
|
||
('Medication Review', 'Reviewed current medications with patient.', 'CLINICAL'),
|
||
('Contact Update', 'Updated emergency contact information.', 'ADMINISTRATIVE'),
|
||
]
|
||
|
||
for patient in patients:
|
||
# Each patient has 2-4 notes
|
||
num_notes = random.randint(2, 4)
|
||
|
||
for i in range(num_notes):
|
||
try:
|
||
title, content, category = random.choice(note_data)
|
||
|
||
PatientNote.objects.create(
|
||
patient=patient,
|
||
title=title,
|
||
content=content,
|
||
category=category,
|
||
priority=random.choice(['LOW', 'NORMAL', 'HIGH']),
|
||
is_confidential=random.choice([True, False]),
|
||
is_alert=random.choice([True, False]) if random.random() < 0.1 else False,
|
||
created_by=random.choice(users) if users else None,
|
||
created_at=django_timezone.now() - timedelta(days=random.randint(1, 365)),
|
||
)
|
||
|
||
notes_created += 1
|
||
|
||
except Exception as e:
|
||
print(f"Error creating note for patient {patient.mrn}: {str(e)}")
|
||
continue
|
||
|
||
print(f"Successfully created {notes_created} patient notes.")
|
||
return notes_created
|
||
|
||
|
||
def main():
|
||
"""Main function to create all Saudi patient data"""
|
||
print("🏥 Creating Saudi Patient Data")
|
||
|
||
try:
|
||
# Check if tenants exist
|
||
tenants = list(Tenant.objects.all())
|
||
if not tenants:
|
||
print("❌ No tenants found. Please run core_data.py first.")
|
||
return
|
||
|
||
print(f"📋 Found {len(tenants)} tenants")
|
||
|
||
# Create patient profiles first
|
||
print("\n1️⃣ Creating Patient Profiles...")
|
||
patients = create_saudi_patient_profiles()
|
||
if not patients:
|
||
print("❌ No patients created. Stopping.")
|
||
return
|
||
|
||
# Create emergency contacts
|
||
print("\n2️⃣ Creating Emergency Contacts...")
|
||
contacts_count = create_saudi_emergency_contacts(patients)
|
||
|
||
# Create insurance info
|
||
print("\n3️⃣ Creating Insurance Information...")
|
||
insurance_count = create_saudi_insurance_info(patients)
|
||
|
||
# Create consent templates
|
||
print("\n4️⃣ Creating Consent Templates...")
|
||
templates_count = create_saudi_consent_templates()
|
||
templates = list(ConsentTemplate.objects.all())
|
||
|
||
# Create consent forms
|
||
print("\n5️⃣ Creating Consent Forms...")
|
||
forms_count = create_saudi_consent_forms(patients, templates)
|
||
|
||
# Create patient notes
|
||
print("\n6️⃣ Creating Patient Notes...")
|
||
notes_count = create_saudi_patient_notes(patients)
|
||
|
||
print("\n🎉 Saudi Patient Data Creation Complete!")
|
||
print(f"📊 Summary:")
|
||
print(f" - Patient Profiles: {len(patients)}")
|
||
print(f" - Emergency Contacts: {contacts_count}")
|
||
print(f" - Insurance Records: {insurance_count}")
|
||
print(f" - Consent Templates: {templates_count}")
|
||
print(f" - Consent Forms: {forms_count}")
|
||
print(f" - Patient Notes: {notes_count}")
|
||
|
||
except Exception as e:
|
||
print(f"❌ Error in main execution: {str(e)}")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main() |