hospital-management/inpatients_data.py
Marwan Alwali f941a8e608 update
2025-08-19 16:22:19 +03:00

814 lines
36 KiB
Python

import os
import django
# Set up Django environment
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hospital_management.settings')
django.setup()
import random
from datetime import datetime, timedelta, date, time
from django.utils import timezone as django_timezone
from inpatients.models import Ward, Bed, Admission, Transfer, DischargeSummary, SurgerySchedule
from accounts.models import User
from patients.models import PatientProfile
from core.models import Tenant
import uuid
# Saudi-specific data constants
SAUDI_WARD_NAMES = [
'King Fahd Ward', 'King Abdulaziz Ward', 'Prince Sultan Ward', 'Princess Noura Ward',
'Al-Faisal Ward', 'Al-Rashid Ward', 'Al-Salam Ward', 'Al-Noor Ward',
'Al-Shifa Ward', 'Al-Amal Ward', 'Al-Rahma Ward', 'Al-Baraka Ward',
'Cardiac Care Unit', 'Intensive Care Unit', 'Pediatric ICU', 'Neonatal ICU',
'Medical Ward A', 'Medical Ward B', 'Surgical Ward A', 'Surgical Ward B',
'Orthopedic Ward', 'Maternity Ward', 'Pediatric Ward', 'Oncology Ward'
]
SAUDI_SPECIALTIES = [
'Internal Medicine', 'Cardiology', 'Cardiac Surgery', 'Orthopedics',
'General Surgery', 'Neurology', 'Neurosurgery', 'Oncology',
'Pediatrics', 'Obstetrics and Gynecology', 'Emergency Medicine',
'Intensive Care', 'Anesthesiology', 'Psychiatry', 'Dermatology',
'Ophthalmology', 'ENT', 'Urology', 'Nephrology', 'Endocrinology'
]
SAUDI_BUILDINGS = [
'King Fahd Medical Tower', 'Prince Sultan Building', 'Al-Faisal Complex',
'Medical Center A', 'Medical Center B', 'Specialty Care Building',
'Emergency Services Building', 'Outpatient Complex', 'Research Center'
]
SAUDI_WINGS = [
'North Wing', 'South Wing', 'East Wing', 'West Wing', 'Central Wing',
'VIP Wing', 'Family Wing', 'Isolation Wing'
]
SAUDI_COMMON_DIAGNOSES = [
'Diabetes Mellitus Type 2', 'Hypertension', 'Coronary Artery Disease',
'Chronic Kidney Disease', 'Heart Failure', 'Pneumonia', 'Gastritis',
'Cholecystitis', 'Appendicitis', 'Urinary Tract Infection',
'Acute Myocardial Infarction', 'Stroke', 'Pulmonary Embolism',
'Deep Vein Thrombosis', 'Sepsis', 'Acute Renal Failure',
'Chronic Obstructive Pulmonary Disease', 'Asthma', 'Anemia'
]
SAUDI_SURGICAL_PROCEDURES = [
'Coronary Artery Bypass Graft', 'Percutaneous Coronary Intervention',
'Appendectomy', 'Cholecystectomy', 'Hernia Repair', 'Hip Replacement',
'Knee Replacement', 'Cataract Surgery', 'Thyroidectomy',
'Prostatectomy', 'Hysterectomy', 'Cesarean Section',
'Arthroscopy', 'Endoscopy', 'Colonoscopy', 'Angioplasty'
]
SAUDI_MEDICATIONS = [
'Metformin', 'Insulin', 'Lisinopril', 'Amlodipine', 'Atorvastatin',
'Aspirin', 'Warfarin', 'Furosemide', 'Omeprazole', 'Paracetamol',
'Amoxicillin', 'Ciprofloxacin', 'Prednisolone', 'Morphine', 'Tramadol'
]
def create_saudi_wards(tenants, wards_per_tenant=12):
"""Create Saudi hospital wards"""
wards = []
ward_types = [
('medical', 'Medical Ward'),
('surgical', 'Surgical Ward'),
('icu', 'Intensive Care Unit'),
('pediatric', 'Pediatric Ward'),
('maternity', 'Maternity Ward'),
('emergency', 'Emergency Ward'),
('psychiatric', 'Psychiatric Ward'),
('rehabilitation', 'Rehabilitation Ward')
]
for tenant in tenants:
for i in range(wards_per_tenant):
ward_name = random.choice(SAUDI_WARD_NAMES)
ward_type = random.choice(ward_types)
specialty = random.choice(SAUDI_SPECIALTIES)
# Ensure unique ward names per tenant
counter = 1
original_name = ward_name
while Ward.objects.filter(tenant=tenant, name=ward_name).exists():
ward_name = f"{original_name} {counter}"
counter += 1
# Get nursing staff for the ward
nurses = User.objects.filter(
tenant=tenant,
role__in=['NURSE', 'NURSE_PRACTITIONER']
)
physicians = User.objects.filter(
tenant=tenant,
role='PHYSICIAN'
)
nurse_manager = random.choice(nurses) if nurses else None
attending_physicians = list(physicians[:random.randint(2, 5)]) if physicians else []
total_beds = random.randint(20, 60)
private_rooms = random.randint(5, 15)
semi_private_rooms = random.randint(8, 20)
shared_rooms = total_beds - private_rooms - (semi_private_rooms * 2)
# Calculate nurse to patient ratio as decimal (e.g., 1:4 = 0.25, 1:5 = 0.2)
ratio_options = [4, 5, 6, 8] # 1:4, 1:5, 1:6, 1:8
selected_ratio = random.choice(ratio_options)
nurse_patient_ratio = round(1.0 / selected_ratio, 3) # Convert to decimal
ward = Ward.objects.create(
tenant=tenant,
ward_id=uuid.uuid4(),
name=ward_name,
description=f"Specialized {specialty.lower()} ward providing comprehensive inpatient care",
ward_type=ward_type[0],
specialty=specialty,
total_beds=total_beds,
private_rooms=private_rooms,
semi_private_rooms=semi_private_rooms,
shared_rooms=max(0, shared_rooms),
building=random.choice(SAUDI_BUILDINGS),
floor=random.randint(1, 10),
wing=random.choice(SAUDI_WINGS),
nurse_manager=nurse_manager,
min_nurses_day=random.randint(8, 15),
min_nurses_night=random.randint(5, 10),
nurse_to_patient_ratio=nurse_patient_ratio, # Now using decimal value
equipment_list=[
'Cardiac Monitors', 'IV Pumps', 'Ventilators', 'Defibrillators',
'Oxygen Supply', 'Suction Units', 'Patient Beds', 'Wheelchairs'
],
special_features=[
'Prayer Room', 'Family Waiting Area', 'Isolation Rooms',
'Nurse Station', 'Clean Utility Room', 'Dirty Utility Room'
],
admission_criteria=f"Patients requiring {specialty.lower()} specialized care",
age_restrictions=random.choice([
'Adults only (18+)', 'Pediatric only (<18)', 'All ages', 'Adults (16+)'
]),
gender_restrictions=random.choice([
'Mixed gender', 'Male only', 'Female only', 'Separate sections'
]),
is_active=True,
is_accepting_admissions=random.choice([True, True, True, False]),
closure_reason=None if random.choice([True, True, True, False]) else 'Maintenance',
phone_number=f"+966-11-{random.randint(100, 999)}-{random.randint(1000, 9999)}",
extension=f"{random.randint(1000, 9999)}",
created_at=django_timezone.now() - timedelta(days=random.randint(30, 365)),
updated_at=django_timezone.now() - timedelta(days=random.randint(0, 30))
)
# Set attending physicians many-to-many relationship
if attending_physicians:
ward.attending_physicians.set(attending_physicians)
wards.append(ward)
print(f"Created {wards_per_tenant} wards for {tenant.name}")
return wards
def create_saudi_beds(wards):
"""Create beds for Saudi hospital wards"""
beds = []
bed_types = [
('standard', 'Standard Hospital Bed'),
('electric', 'Electric Adjustable Bed'),
('icu', 'ICU Bed'),
('bariatric', 'Bariatric Bed'),
('pediatric', 'Pediatric Bed')
]
room_types = [
('private', 'Private Room'),
('semi_private', 'Semi-Private Room'),
('shared', 'Shared Room'),
('isolation', 'Isolation Room')
]
bed_statuses = ['available', 'occupied', 'maintenance', 'blocked']
cleaning_levels = ['standard', 'deep', 'isolation', 'terminal']
for ward in wards:
for bed_num in range(1, ward.total_beds + 1):
bed_number = f"{ward.name[:3].upper()}-{bed_num:03d}"
room_number = f"{ward.floor}{random.randint(10, 99)}"
bed_type = random.choice(bed_types)
room_type = random.choice(room_types)
status = random.choice(bed_statuses)
# Determine bed position
bed_positions = ['A', 'B', 'C', 'D'] if room_type[0] == 'shared' else ['A', 'B'] if room_type[
0] == 'semi_private' else [
'A']
bed_position = random.choice(bed_positions)
bed = Bed.objects.create(
ward=ward,
bed_number=bed_number,
room_number=room_number,
bed_type=bed_type[0],
room_type=room_type[0],
status=status,
occupied_since=django_timezone.now() - timedelta(
days=random.randint(1, 30)) if status == 'occupied' else None,
reserved_until=django_timezone.now() + timedelta(
hours=random.randint(1, 24)) if status == 'available' and random.choice([True, False]) else None,
equipment=[
'Cardiac Monitor', 'IV Pole', 'Oxygen Outlet', 'Suction Outlet',
'Nurse Call System', 'Bedside Table', 'Privacy Curtain'
],
features=[
'Adjustable Height', 'Side Rails', 'Trendelenburg Position',
'Reverse Trendelenburg', 'Patient Controls', 'LED Reading Light'
],
last_maintenance=django_timezone.now() - timedelta(days=random.randint(7, 90)),
next_maintenance=django_timezone.now() + timedelta(days=random.randint(30, 180)),
maintenance_notes="Routine maintenance completed" if random.choice([True, False]) else None,
last_cleaned=django_timezone.now() - timedelta(hours=random.randint(1, 24)),
cleaning_level=random.choice(cleaning_levels),
blocked_reason="Maintenance required" if status == 'blocked' else None,
blocked_until=django_timezone.now() + timedelta(
hours=random.randint(2, 48)) if status == 'blocked' else None,
bed_position=bed_position,
created_at=django_timezone.now() - timedelta(days=random.randint(1, 365)),
updated_at=django_timezone.now() - timedelta(hours=random.randint(1, 48))
)
beds.append(bed)
print(f"Created {len(beds)} beds across all wards")
return beds
def create_saudi_admissions(tenants, beds, admissions_per_tenant=100):
"""Create Saudi hospital admissions"""
admissions = []
admission_types = [
('emergency', 'Emergency Admission'),
('elective', 'Elective Admission'),
('urgent', 'Urgent Admission'),
('transfer', 'Transfer from Another Facility')
]
admission_sources = [
('emergency_department', 'Emergency Department'),
('outpatient_clinic', 'Outpatient Clinic'),
('physician_office', 'Physician Office'),
('transfer_acute', 'Transfer from Acute Care'),
('transfer_ltc', 'Transfer from Long-term Care'),
('direct_admission', 'Direct Admission')
]
statuses = ['active', 'discharged', 'transferred']
priorities = ['routine', 'urgent', 'emergent', 'critical']
acuity_levels = ['1', '2', '3', '4', '5'] # 1 = highest acuity
isolation_types = [
'contact', 'droplet', 'airborne', 'protective', 'contact_plus',
'strict_isolation', 'reverse_isolation'
]
code_statuses = [
'full_code', 'dnr', 'dni', 'comfort_care', 'limited_intervention'
]
for tenant in tenants:
# Get patients and staff for this tenant
patients = list(PatientProfile.objects.filter(tenant=tenant))
physicians = list(User.objects.filter(tenant=tenant, role='PHYSICIAN'))
nurses = list(User.objects.filter(tenant=tenant, role__in=['NURSE', 'NURSE_PRACTITIONER']))
tenant_beds = [bed for bed in beds if bed.ward.tenant == tenant]
if not patients or not physicians or not tenant_beds:
continue
for i in range(admissions_per_tenant):
patient = random.choice(patients)
admitting_physician = random.choice(physicians)
attending_physician = random.choice(physicians)
current_bed = random.choice(tenant_beds)
current_ward = current_bed.ward
admission_datetime = django_timezone.now() - timedelta(days=random.randint(0, 30))
status = random.choice(statuses)
# If discharged, set discharge datetime
discharge_datetime = None
if status == 'discharged':
discharge_datetime = admission_datetime + timedelta(days=random.randint(1, 14))
admission = Admission.objects.create(
tenant=tenant,
admission_id=uuid.uuid4(),
patient=patient,
admission_datetime=admission_datetime,
admission_type=random.choice(admission_types)[0],
admission_source=random.choice(admission_sources)[0],
chief_complaint=random.choice([
'Chest pain', 'Shortness of breath', 'Abdominal pain',
'Fever and chills', 'Weakness and fatigue', 'Nausea and vomiting',
'Headache', 'Dizziness', 'Joint pain', 'Back pain'
]),
admitting_diagnosis=random.choice(SAUDI_COMMON_DIAGNOSES),
secondary_diagnoses=[random.choice(SAUDI_COMMON_DIAGNOSES) for _ in range(random.randint(0, 3))],
admitting_physician=admitting_physician,
attending_physician=attending_physician,
current_ward=current_ward,
current_bed=current_bed,
status=status,
priority=random.choice(priorities),
acuity_level=random.choice(acuity_levels),
insurance_verified=random.choice([True, False]),
authorization_number=f"AUTH-{random.randint(100000, 999999)}" if random.choice([True, False]) else None,
estimated_length_of_stay=random.randint(2, 14),
discharge_planning_started=random.choice([True, False]),
anticipated_discharge_date=admission_datetime.date() + timedelta(days=random.randint(1, 10)),
discharge_datetime=discharge_datetime,
isolation_required=random.choice([True, False, False, False]),
isolation_type=random.choice(isolation_types) if random.choice([True, False]) else None,
special_needs=[
'Interpreter services', 'Dietary restrictions', 'Mobility assistance',
'Vision/hearing impairment', 'Cultural considerations'
] if random.choice([True, False]) else [],
allergies=[
'Penicillin', 'Sulfa drugs', 'Shellfish', 'Latex', 'Contrast dye'
] if random.choice([True, False]) else [],
alerts=[
'Fall risk', 'Suicide risk', 'Flight risk', 'Combative',
'Infection control', 'Allergy alert'
] if random.choice([True, False]) else [],
code_status=random.choice(code_statuses),
advance_directive=random.choice([True, False]),
admission_notes=f"Patient admitted with {random.choice(SAUDI_COMMON_DIAGNOSES).lower()} requiring inpatient management",
created_at=admission_datetime,
updated_at=admission_datetime + timedelta(hours=random.randint(1, 24))
)
# Set consulting physicians
consulting_physicians = random.sample(physicians, random.randint(0, 3))
if consulting_physicians:
admission.consulting_physicians.set(consulting_physicians)
# Update bed status if occupied
if status == 'active':
current_bed.status = 'occupied'
current_bed.current_patient = patient
current_bed.current_admission = admission
current_bed.occupied_since = admission_datetime
current_bed.save()
admissions.append(admission)
print(f"Created {admissions_per_tenant} admissions for {tenant.name}")
return admissions
def create_saudi_transfers(admissions):
"""Create transfer records for Saudi patients"""
transfers = []
transfer_types = [
('ward_to_ward', 'Ward to Ward'),
('ward_to_icu', 'Ward to ICU'),
('icu_to_ward', 'ICU to Ward'),
('er_to_ward', 'ER to Ward'),
('ward_to_or', 'Ward to OR')
]
transfer_statuses = ['requested', 'approved', 'in_progress', 'completed', 'cancelled']
transport_methods = ['bed', 'wheelchair', 'stretcher', 'walking', 'ambulance']
priorities = ['routine', 'urgent', 'emergent', 'stat']
# Create transfers for 30% of admissions
for admission in random.sample(admissions, int(len(admissions) * 0.3)):
transfer_type = random.choice(transfer_types)
# Get available beds in different wards
available_beds = Bed.objects.filter(
ward__tenant=admission.tenant,
status='available'
).exclude(ward=admission.current_ward)
if not available_beds:
continue
to_bed = random.choice(available_beds)
to_ward = to_bed.ward
# Get users who can request transfers (physicians, nurses, etc.)
requesting_users = User.objects.filter(
tenant=admission.tenant,
is_active=True,
role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT']
)
if not requesting_users.exists():
# Fallback to any active user from the tenant
requesting_users = User.objects.filter(tenant=admission.tenant, is_active=True)
if not requesting_users.exists():
continue # Skip if no users available
requested_by = random.choice(requesting_users)
requested_datetime = admission.admission_datetime + timedelta(hours=random.randint(1, 72))
status = random.choice(transfer_statuses)
scheduled_datetime = None
actual_datetime = None
if status in ['approved', 'in_progress', 'completed']:
scheduled_datetime = requested_datetime + timedelta(hours=random.randint(1, 12))
if status in ['in_progress', 'completed']:
actual_datetime = scheduled_datetime + timedelta(minutes=random.randint(-30, 60))
# Get transport team members
transport_team_members = []
nurses = User.objects.filter(
tenant=admission.tenant,
role__in=['NURSE', 'NURSE_PRACTITIONER']
)
if nurses:
transport_team_members = random.sample(list(nurses), min(2, nurses.count()))
transfer = Transfer.objects.create(
transfer_id=uuid.uuid4(),
admission=admission,
patient=admission.patient,
transfer_type=transfer_type[0],
from_ward=admission.current_ward,
from_bed=admission.current_bed,
to_ward=to_ward,
to_bed=to_bed,
requested_by=requested_by, # Add the required field
requested_datetime=requested_datetime,
scheduled_datetime=scheduled_datetime,
actual_datetime=actual_datetime,
status=status,
reason=random.choice([
'Clinical deterioration', 'Need for higher level of care',
'Bed availability', 'Specialist consultation required',
'Patient preference', 'Isolation requirements'
]),
priority=random.choice(priorities),
transport_method=random.choice(transport_methods),
equipment_needed=['IV pole', 'Oxygen tank', 'Monitor'] if random.choice([True, False]) else [],
supplies_needed=['Medications', 'Patient chart', 'Personal items'] if random.choice([True, False]) else [],
patient_condition=random.choice(['stable', 'unstable', 'critical', 'improving']),
vital_signs={
'blood_pressure': f"{random.randint(90, 180)}/{random.randint(60, 100)}",
'heart_rate': random.randint(60, 120),
'respiratory_rate': random.randint(12, 24),
'temperature': round(random.uniform(36.0, 39.0), 1),
'oxygen_saturation': random.randint(92, 100)
},
handoff_report=f"Patient transferred for {random.choice(['specialized care', 'higher acuity monitoring', 'bed availability'])}",
medications_transferred=random.sample(SAUDI_MEDICATIONS, random.randint(2, 5)),
delay_reason="Bed not ready" if status == 'approved' and random.choice([True, False]) else None,
complications="None noted" if status == 'completed' else None,
notes=f"Transfer completed successfully" if status == 'completed' else None,
created_at=requested_datetime,
updated_at=requested_datetime + timedelta(hours=random.randint(1, 24))
)
# Set transport team using .set() method for many-to-many relationship
if transport_team_members:
transfer.transport_team.set(transport_team_members)
# Update admission current location if transfer completed
if status == 'completed':
admission.current_ward = to_ward
admission.current_bed = to_bed
admission.save()
# Update bed statuses
transfer.from_bed.status = 'available'
transfer.from_bed.current_patient = None
transfer.from_bed.current_admission = None
transfer.from_bed.occupied_since = None
transfer.from_bed.save()
to_bed.status = 'occupied'
to_bed.current_patient = admission.patient
to_bed.current_admission = admission
to_bed.occupied_since = actual_datetime
to_bed.save()
transfers.append(transfer)
print(f"Created {len(transfers)} transfers")
return transfers
def create_saudi_discharge_summaries(admissions):
"""Create discharge summaries for discharged Saudi patients"""
summaries = []
discharged_admissions = [adm for adm in admissions if adm.status == 'discharged' and adm.discharge_datetime]
discharge_dispositions = [
('home', 'Home'),
('home_health', 'Home with Health Services'),
('skilled_nursing', 'Skilled Nursing Facility'),
('rehabilitation', 'Rehabilitation Facility'),
('ltac', 'Long-term Acute Care'),
('hospice', 'Hospice Care'),
('transfer_acute', 'Transfer to Acute Care'),
('ama', 'Against Medical Advice')
]
for admission in discharged_admissions:
length_of_stay = (admission.discharge_datetime.date() - admission.admission_datetime.date()).days
summary = DischargeSummary.objects.create(
admission=admission,
summary_id=uuid.uuid4(),
discharge_date=admission.discharge_datetime.date(),
discharge_time=admission.discharge_datetime.time(),
length_of_stay=length_of_stay,
admission_diagnosis=admission.admitting_diagnosis,
final_diagnosis=random.choice(SAUDI_COMMON_DIAGNOSES),
secondary_diagnoses=admission.secondary_diagnoses or [],
procedures_performed=random.sample(SAUDI_SURGICAL_PROCEDURES, random.randint(0, 3)),
hospital_course=f"Patient admitted with {admission.admitting_diagnosis.lower()} and responded well to treatment. No significant complications during stay.",
complications="None" if random.choice(
[True, True, False]) else "Minor wound infection, resolved with antibiotics",
discharge_medications=random.sample(SAUDI_MEDICATIONS, random.randint(3, 8)),
medication_changes=[
"Started on new antihypertensive",
"Increased insulin dose",
"Discontinued antibiotic"
] if random.choice([True, False]) else [],
activity_restrictions=random.choice([
"No lifting >10 lbs for 2 weeks",
"Bedrest x 24 hours",
"No driving until follow-up",
"Activity as tolerated"
]),
diet_instructions=random.choice([
"Diabetic diet", "Low sodium diet", "Cardiac diet",
"Regular diet", "Soft mechanical diet"
]),
wound_care="Keep incision clean and dry. Change dressing daily." if random.choice([True, False]) else None,
special_instructions=[
"Monitor blood pressure daily",
"Check blood sugar twice daily",
"Weigh yourself daily"
] if random.choice([True, False]) else [],
follow_up_appointments=[
{
'provider': 'Primary Care Physician',
'date': (admission.discharge_datetime.date() + timedelta(days=7)).isoformat(),
'time': '10:00 AM'
},
{
'provider': 'Cardiologist',
'date': (admission.discharge_datetime.date() + timedelta(days=14)).isoformat(),
'time': '2:00 PM'
}
],
follow_up_instructions="Follow up with primary care physician in 1 week and specialist in 2 weeks",
warning_signs=[
"Fever >38.5°C", "Increased shortness of breath",
"Chest pain", "Swelling in legs", "Unusual bleeding"
],
when_to_call="Call physician or return to emergency department if experiencing any warning signs",
discharge_disposition=random.choice(discharge_dispositions)[0],
discharge_location="Home" if random.choice([True, True, False]) else "Rehabilitation facility",
transportation_arranged=True,
transportation_method=random.choice(['private_vehicle', 'taxi', 'ambulance', 'hospital_transport']),
durable_medical_equipment=['Walker', 'Hospital bed', 'Oxygen concentrator'] if random.choice(
[True, False]) else [],
supplies_provided=['Wound care supplies', 'Medications', 'Educational materials'] if random.choice(
[True, False]) else [],
education_provided=[
'Disease management', 'Medication administration',
'Signs and symptoms to report', 'Activity restrictions'
],
education_materials=['Discharge instructions', 'Medication list', 'Educational brochures'],
patient_understanding='Good' if random.choice([True, True, False]) else 'Fair',
social_worker_involved=random.choice([True, False]),
case_manager_involved=random.choice([True, False]),
readmission_risk=random.choice(['low', 'moderate', 'high']),
patient_satisfaction=random.randint(1, 5), # Changed to numeric scale (1-5)
discharging_physician=admission.attending_physician,
summary_completed=True,
summary_signed=True,
patient_copy_provided=True,
created_at=admission.discharge_datetime,
updated_at=admission.discharge_datetime + timedelta(hours=2)
)
summaries.append(summary)
print(f"Created {len(summaries)} discharge summaries")
return summaries
def create_saudi_surgery_schedules(tenants, surgeries_per_tenant=30):
"""Create surgery schedules for Saudi patients"""
surgeries = []
surgery_types = [
('elective', 'Elective Surgery'),
('emergency', 'Emergency Surgery'),
('urgent', 'Urgent Surgery'),
('add_on', 'Add-on Surgery')
]
anesthesia_types = [
('general', 'General Anesthesia'),
('regional', 'Regional Anesthesia'),
('local', 'Local Anesthesia'),
('mac', 'Monitored Anesthesia Care'),
('spinal', 'Spinal Anesthesia'),
('epidural', 'Epidural Anesthesia')
]
surgery_statuses = [
('scheduled', 'Scheduled'),
('confirmed', 'Confirmed'),
('in_progress', 'In Progress'),
('completed', 'Completed'),
('cancelled', 'Cancelled'),
('delayed', 'Delayed')
]
priorities = ['routine', 'urgent', 'emergent', 'elective']
for tenant in tenants:
# Get required staff and patients
patients = list(PatientProfile.objects.filter(tenant=tenant))
surgeons = list(User.objects.filter(tenant=tenant, role='PHYSICIAN'))
anesthesiologists = list(User.objects.filter(tenant=tenant, role='PHYSICIAN'))
nurses = list(User.objects.filter(tenant=tenant, role__in=['NURSE', 'NURSE_PRACTITIONER']))
admissions = list(Admission.objects.filter(tenant=tenant, status='active'))
if not patients or not surgeons or not nurses or not admissions:
print(f"Insufficient data for tenant {tenant.name}: patients={len(patients)}, surgeons={len(surgeons)}, nurses={len(nurses)}, admissions={len(admissions)}")
continue
for i in range(min(surgeries_per_tenant, len(admissions))): # Don't exceed available admissions
# Always use an admission - required field
admission = random.choice(admissions)
patient = admission.patient # Use patient from the admission
procedure = random.choice(SAUDI_SURGICAL_PROCEDURES)
# Generate surgery date (within next 30 days)
surgery_date = (django_timezone.now() + timedelta(days=random.randint(0, 30))).date()
start_time = time(hour=random.randint(7, 16), minute=random.choice([0, 30]))
estimated_duration = random.randint(60, 480) # 1-8 hours
status = random.choice(surgery_statuses)[0]
# Actual times if surgery completed
actual_start_time = None
actual_end_time = None
actual_duration = None
if status in ['in_progress', 'completed']:
actual_start_time = datetime.combine(surgery_date, start_time)
if status == 'completed':
actual_duration = estimated_duration + random.randint(-30, 60)
actual_end_time = actual_start_time + timedelta(minutes=actual_duration)
surgery = SurgerySchedule.objects.create(
tenant=tenant,
surgery_id=uuid.uuid4(),
patient=patient,
admission=admission, # Always provide admission - required field
procedure_name=procedure,
procedure_code=f"CPT-{random.randint(10000, 99999)}",
surgery_type=random.choice(surgery_types)[0],
scheduled_date=surgery_date,
scheduled_start_time=start_time,
estimated_duration_minutes=estimated_duration,
operating_room=f"OR-{random.randint(1, 12)}",
or_block_time=f"{start_time} - {(datetime.combine(surgery_date, start_time) + timedelta(minutes=estimated_duration)).time()}",
primary_surgeon=random.choice(surgeons),
anesthesiologist=random.choice(anesthesiologists),
scrub_nurse=random.choice(nurses),
circulating_nurse=random.choice(nurses),
anesthesia_type=random.choice(anesthesia_types)[0],
preop_diagnosis=random.choice(SAUDI_COMMON_DIAGNOSES),
preop_orders=[
'NPO after midnight', 'Pre-op antibiotics', 'Type and crossmatch',
'Pre-op labs', 'Consent signed'
],
consent_obtained=True,
consent_date=surgery_date - timedelta(days=random.randint(0, 7)),
special_equipment=['Laparoscopic equipment', 'C-arm', 'Microscope'] if random.choice(
[True, False]) else [],
implants_needed=['Orthopedic implants', 'Cardiac devices'] if random.choice([True, False]) else [],
blood_products=['Packed RBCs', 'FFP', 'Platelets'] if random.choice([True, False]) else [],
status=status,
actual_start_time=actual_start_time,
actual_end_time=actual_end_time,
actual_duration_minutes=actual_duration,
postop_diagnosis=random.choice(SAUDI_COMMON_DIAGNOSES) if status == 'completed' else None,
procedure_performed=procedure if status == 'completed' else None,
complications="None" if status == 'completed' and random.choice([True, True, False]) else None,
recovery_location=random.choice(
['PACU', 'ICU', 'Ward', 'Same Day Surgery']) if status == 'completed' else None,
priority=random.choice(priorities),
surgery_notes=f"Successful {procedure.lower()} performed without complications" if status == 'completed' else None,
created_at=django_timezone.now() - timedelta(days=random.randint(1, 30)),
updated_at=django_timezone.now() - timedelta(hours=random.randint(1, 24))
)
# Set assistant surgeons using .set() method for many-to-many relationship
assistant_surgeons = random.sample(surgeons, random.randint(0, 2))
if assistant_surgeons:
surgery.assistant_surgeons.set(assistant_surgeons)
surgeries.append(surgery)
print(f"Created {min(surgeries_per_tenant, len(admissions))} surgeries for {tenant.name}")
return surgeries
def main():
"""Main function to generate all Saudi inpatients data"""
print("Starting Saudi Healthcare Inpatients 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 wards
print("\n1. Creating Saudi Hospital Wards...")
wards = create_saudi_wards(tenants, 10)
# Create beds
print("\n2. Creating Hospital Beds...")
beds = create_saudi_beds(wards)
# Create admissions
print("\n3. Creating Patient Admissions...")
admissions = create_saudi_admissions(tenants, beds, 80)
# Create transfers
print("\n4. Creating Patient Transfers...")
transfers = create_saudi_transfers(admissions)
# Create discharge summaries
print("\n5. Creating Discharge Summaries...")
summaries = create_saudi_discharge_summaries(admissions)
# Create surgery schedules
print("\n6. Creating Surgery Schedules...")
surgeries = create_saudi_surgery_schedules(tenants, 25)
print(f"\n✅ Saudi Healthcare Inpatients Data Generation Complete!")
print(f"📊 Summary:")
print(f" - Wards: {len(wards)}")
print(f" - Beds: {len(beds)}")
print(f" - Admissions: {len(admissions)}")
print(f" - Transfers: {len(transfers)}")
print(f" - Discharge Summaries: {len(summaries)}")
print(f" - Surgery Schedules: {len(surgeries)}")
# Status distribution
admission_statuses = {}
for admission in admissions:
admission_statuses[admission.status] = admission_statuses.get(admission.status, 0) + 1
print(f"\n🏥 Admission Status Distribution:")
for status, count in admission_statuses.items():
print(f" - {status.title()}: {count}")
# Nurse-to-patient ratio summary
print(f"\n👩‍⚕️ Nurse-to-Patient Ratios Used:")
ratios_used = set()
for ward in wards:
ratio_value = ward.nurse_to_patient_ratio
# Convert back to ratio format for display
patients_per_nurse = int(1 / ratio_value) if ratio_value > 0 else 0
ratios_used.add(f"1:{patients_per_nurse}")
for ratio in sorted(ratios_used):
print(f" - {ratio}")
return {
'wards': wards,
'beds': beds,
'admissions': admissions,
'transfers': transfers,
'summaries': summaries,
'surgeries': surgeries
}
if __name__ == "__main__":
main()