2025-10-03 20:11:25 +03:00

1279 lines
56 KiB
Python

# """
# Saudi-influenced data generator for Operating Theatre models.
# Generates realistic test data with Saudi Arabian healthcare context using English.
#
# Save this file as: operating_theatre/management/commands/generate_saudi_or_data.py
# """
#
# import random
# from datetime import datetime, timedelta
# from decimal import Decimal
# from django.core.management.base import BaseCommand
# from django.contrib.auth import get_user_model
# from django.utils import timezone
# from faker import Faker
# from faker.providers import BaseProvider
#
# from core.models import Tenant, Department
# from accounts.models import User
# from patients.models import PatientProfile
# from operating_theatre.models import (
# OperatingRoom, ORBlock, SurgicalCase, SurgicalNote,
# EquipmentUsage, SurgicalNoteTemplate
# )
#
# User = get_user_model()
#
# # Custom Saudi provider for Faker
# class SaudiProvider(BaseProvider):
# """Custom provider for Saudi Arabian healthcare data in English."""
#
# # Saudi male names (transliterated to English)
# saudi_male_first_names = [
# 'Mohammed', 'Ahmed', 'Abdullah', 'Abdulrahman', 'Ali', 'Khalid', 'Saad', 'Fahd', 'Abdulaziz',
# 'Sultan', 'Turki', 'Bandar', 'Nawaf', 'Mishaal', 'Faisal', 'Salman', 'Abdulmajeed', 'Yasser',
# 'Omar', 'Hussam', 'Talal', 'Waleed', 'Majed', 'Rashid', 'Sami', 'Hisham', 'Adel', 'Kareem',
# 'Nasser', 'Mansour', 'Hamad', 'Badr', 'Zaid', 'Yazeed', 'Rayan', 'Osama', 'Tariq', 'Mazen'
# ]
#
# # Saudi female names (transliterated to English)
# saudi_female_first_names = [
# 'Fatimah', 'Aisha', 'Khadijah', 'Maryam', 'Zainab', 'Sarah', 'Nora', 'Hind', 'Lateefah', 'Mona',
# 'Amal', 'Salma', 'Reem', 'Dana', 'Lina', 'Rana', 'Haya', 'Jawaher', 'Shahd', 'Ghada',
# 'Raghad', 'Asma', 'Hanan', 'Wafa', 'Iman', 'Samira', 'Nadia', 'Abeer', 'Suad', 'Layla',
# 'Nouf', 'Rania', 'Dina', 'Rima', 'Najla', 'Arwa', 'Lamya', 'Thuraya', 'Widad', 'Amina'
# ]
#
# # Saudi family names (transliterated)
# saudi_family_names = [
# 'Al Saud', 'Al Otaibi', 'Al Qahtani', 'Al Ghamdi', 'Al Zahrani', 'Al Shehri', 'Al Anzi', 'Al Harbi',
# 'Al Mutairi', 'Al Dosari', 'Al Khalidi', 'Al Subaie', 'Al Rashid', 'Al Baqmi', 'Al Juhani', 'Al Asiri',
# 'Al Faisal', 'Al Maliki', 'Al Shammari', 'Al Balawi', 'Al Saadi', 'Al Thaqafi', 'Al Ahmadi', 'Al Salmi',
# 'Al Hasani', 'Al Omari', 'Al Fahd', 'Al Nuaimi', 'Al Rajhi', 'Al Olayan', 'Al Sudairi', 'Al Tamimi',
# 'Bin Laden', 'Bin Mahfouz', 'Al Amoudi', 'Al Gosaibi', 'Al Zamil', 'Al Juffali', 'Al Hokair'
# ]
#
# # Saudi cities
# saudi_cities = [
# 'Riyadh', 'Jeddah', 'Mecca', 'Medina', 'Dammam', 'Khobar', 'Taif',
# 'Buraidah', 'Tabuk', 'Khamis Mushait', 'Hail', 'Jubail', 'Al Ahsa', 'Najran', 'Yanbu',
# 'Abha', 'Arar', 'Sakaka', 'Jazan', 'Qatif', 'Al Bahah', 'Rafha', 'Wadi Al Dawasir',
# 'Al Kharj', 'Hafar Al Batin', 'Al Qunfudhah', 'Unaizah', 'Al Majmaah', 'Dhahran'
# ]
#
# # Medical specialties
# medical_specialties = [
# 'General Surgery', 'Cardiac Surgery', 'Neurosurgery', 'Orthopedic Surgery', 'Plastic Surgery',
# 'Urology', 'Pediatric Surgery', 'Vascular Surgery', 'Thoracic Surgery', 'Ophthalmology',
# 'ENT Surgery', 'Gynecology', 'Emergency Medicine', 'Anesthesiology', 'Radiology'
# ]
#
# # Common surgical procedures
# surgical_procedures = [
# 'Laparoscopic Cholecystectomy', 'Appendectomy', 'Inguinal Hernia Repair',
# 'Thyroidectomy', 'Open Heart Surgery', 'Cardiac Catheterization', 'Knee Replacement',
# 'Hip Replacement', 'Mastectomy', 'Cataract Surgery', 'Tonsillectomy', 'Septoplasty',
# 'Hysterectomy', 'Cesarean Section', 'Prostatectomy', 'Lumbar Spine Surgery',
# 'Discectomy', 'Rhinoplasty', 'Liposuction', 'Hair Transplant', 'Kidney Stone Removal',
# 'Varicose Vein Surgery', 'Coronary Artery Bypass', 'Angioplasty', 'Gallbladder Surgery'
# ]
#
# # Medical equipment names
# medical_equipment = [
# 'Ventilator', 'Cardiac Monitor', 'Defibrillator', 'Laparoscope',
# 'Endoscope', 'Portable X-Ray', 'Infusion Pump', 'Blood Pressure Monitor',
# 'Ultrasound Machine', 'Electrocautery Unit', 'Surgical Laser',
# 'Arthroscope', 'Dialysis Machine', 'Incubator', 'Physical Therapy Equipment',
# 'CT Scanner', 'MRI Machine', 'Anesthesia Machine', 'Operating Microscope'
# ]
#
# # Hospital departments
# hospital_departments = [
# 'Emergency Department', 'Surgery Department', 'Internal Medicine', 'Pediatrics', 'Obstetrics & Gynecology',
# 'Orthopedics', 'Cardiology', 'Neurology', 'Ophthalmology', 'ENT Department',
# 'Dermatology', 'Psychiatry', 'Radiology', 'Laboratory', 'Pharmacy',
# 'Intensive Care Unit', 'Operating Theater', 'Outpatient Clinic'
# ]
#
# # Saudi hospital names
# saudi_hospitals = [
# 'King Fahd University Hospital', 'King Khalid University Hospital', 'King Abdulaziz Medical City',
# 'King Faisal Specialist Hospital', 'Prince Sultan Military Medical City', 'King Saud Medical City',
# 'National Guard Health Affairs', 'Saudi German Hospital', 'Dr. Sulaiman Al Habib Medical Group',
# 'Dallah Healthcare', 'Mouwasat Medical Services', 'Al Hammadi Hospital'
# ]
#
# def saudi_male_name(self):
# """Generate a Saudi male name."""
# first_name = self.random_element(self.saudi_male_first_names)
# family_name = self.random_element(self.saudi_family_names)
# return f"{first_name} {family_name}"
#
# def saudi_female_name(self):
# """Generate a Saudi female name."""
# first_name = self.random_element(self.saudi_female_first_names)
# family_name = self.random_element(self.saudi_family_names)
# return f"{first_name} {family_name}"
#
# def saudi_city(self):
# """Generate a Saudi city name."""
# return self.random_element(self.saudi_cities)
#
# def medical_specialty(self):
# """Generate a medical specialty."""
# return self.random_element(self.medical_specialties)
#
# def surgical_procedure(self):
# """Generate a surgical procedure name."""
# return self.random_element(self.surgical_procedures)
#
# def medical_equipment_name(self):
# """Generate medical equipment name."""
# return self.random_element(self.medical_equipment)
#
# def hospital_department(self):
# """Generate hospital department name."""
# return self.random_element(self.hospital_departments)
#
# def saudi_hospital_name(self):
# """Generate Saudi hospital name."""
# return self.random_element(self.saudi_hospitals)
#
# def saudi_national_id(self):
# """Generate a Saudi national ID (10 digits starting with 1 or 2)."""
# first_digit = random.choice(['1', '2']) # 1 for Saudi, 2 for resident
# remaining_digits = ''.join([str(random.randint(0, 9)) for _ in range(9)])
# return first_digit + remaining_digits
#
# def saudi_phone_number(self):
# """Generate a Saudi phone number."""
# prefixes = ['050', '053', '054', '055', '056', '057', '058', '059']
# prefix = random.choice(prefixes)
# number = ''.join([str(random.randint(0, 9)) for _ in range(7)])
# return f"+966{prefix[1:]}{number}"
#
# def saudi_medical_license(self):
# """Generate Saudi medical license number."""
# return f"SCFHS-{random.randint(10000, 99999)}"
#
#
# class Command(BaseCommand):
# help = 'Generate Saudi-influenced test data for Operating Theatre models'
#
# def __init__(self):
# super().__init__()
# self.fake = Faker(['en_US'])
# self.fake.add_provider(SaudiProvider)
#
# def add_arguments(self, parser):
# parser.add_argument(
# '--rooms',
# type=int,
# default=12,
# help='Number of operating rooms to create'
# )
# parser.add_argument(
# '--cases',
# type=int,
# default=75,
# help='Number of surgical cases to create'
# )
# parser.add_argument(
# '--notes',
# type=int,
# default=50,
# help='Number of surgical notes to create'
# )
# parser.add_argument(
# '--templates',
# type=int,
# default=20,
# help='Number of surgical note templates to create'
# )
# parser.add_argument(
# '--blocks',
# type=int,
# default=30,
# help='Number of OR blocks to create'
# )
# parser.add_argument(
# '--equipment',
# type=int,
# default=60,
# help='Number of equipment usage records to create'
# )
# parser.add_argument(
# '--tenant',
# type=str,
# default=None,
# help='Tenant name (will use random Saudi hospital if not provided)'
# )
#
# def handle(self, *args, **options):
# self.stdout.write(
# self.style.SUCCESS('Starting Saudi-influenced Operating Theatre data generation...')
# )
#
# # Get or create tenant
# tenant_name = options['tenant'] or self.fake.saudi_hospital_name()
# tenant = self.get_or_create_tenant(tenant_name)
#
# # Create users (doctors, nurses, etc.)
# users = self.create_users(tenant)
#
# # Create patients
# patients = self.create_patients(tenant)
#
# # Create operating rooms
# operating_rooms = self.create_operating_rooms(tenant, options['rooms'])
#
# # Create surgical note templates
# templates = self.create_surgical_note_templates(tenant, users, options['templates'])
#
# # Create OR blocks
# or_blocks = self.create_or_blocks(tenant, operating_rooms, users, options['blocks'])
#
# # Create surgical cases
# surgical_cases = self.create_surgical_cases(
# tenant, patients, users, operating_rooms, options['cases']
# )
#
# # Create surgical notes
# surgical_notes = self.create_surgical_notes(
# tenant, surgical_cases, users, templates, options['notes']
# )
#
# # Create equipment usage records
# equipment_usage = self.create_equipment_usage(
# tenant, surgical_cases, operating_rooms, options['equipment']
# )
#
# self.stdout.write(
# self.style.SUCCESS(
# f'Successfully generated Saudi-influenced data:\n'
# f'- {len(operating_rooms)} Operating Rooms\n'
# f'- {len(surgical_cases)} Surgical Cases\n'
# f'- {len(surgical_notes)} Surgical Notes\n'
# f'- {len(templates)} Note Templates\n'
# f'- {len(or_blocks)} OR Blocks\n'
# f'- {len(equipment_usage)} Equipment Usage Records\n'
# f'- Tenant: {tenant.name}'
# )
# )
#
# def get_or_create_tenant(self, tenant_name):
# """Get or create tenant."""
# slug = tenant_name.lower().replace(' ', '-').replace('&', 'and')
# tenant, created = Tenant.objects.get_or_create(
# name=tenant_name,
# defaults={
# 'slug': slug,
# 'is_active': True,
# 'subscription_plan': 'enterprise',
# 'max_users': 1000,
# 'country': 'Saudi Arabia',
# 'timezone': 'Asia/Riyadh'
# }
# )
# if created:
# self.stdout.write(f'Created tenant: {tenant_name}')
# return tenant
#
#
# def create_users(self, tenant):
# """Create medical staff users with Saudi names."""
# users = []
#
# # Create surgeons
# for i in range(20):
# gender = random.choice(["M", "F"])
# if gender == "M":
# full_name = self.fake.saudi_male_name()
# else:
# full_name = self.fake.saudi_female_name()
#
# name_parts = full_name.split()
# first_name = name_parts[0]
# last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else name_parts[0]
#
# username = f"dr_{first_name.lower()}_{i}"
# email = f"{username}@{tenant.slug}.sa"
#
# user = User.objects.create_user(
# username=username,
# email=email,
# first_name=first_name,
# last_name=last_name,
# tenant=tenant,
# is_active=True
# )
#
# # Create user profile
# User.objects.create(
# user=user,
# title="Dr." if gender == "M" else "Dr.",
# specialty=self.fake.medical_specialty(),
# license_number=self.fake.saudi_medical_license(),
# phone_number=self.fake.saudi_phone_number(),
# department=self.fake.hospital_department(),
# is_verified=True,
# years_of_experience=random.randint(3, 25),
# education=f"MD from King Saud University, {random.choice(["Fellowship", "Residency"])} in {self.fake.medical_specialty()}"
# )
#
# users.append(user)
#
# # Create anesthesiologists
# for i in range(10):
# gender = random.choice(["M", "F"])
# if gender == "M":
# full_name = self.fake.saudi_male_name()
# else:
# full_name = self.fake.saudi_female_name()
#
# name_parts = full_name.split()
# first_name = name_parts[0]
# last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else name_parts[0]
#
# username = f"anesth_{first_name.lower()}_{i}"
# email = f"{username}@{tenant.slug}.sa"
#
# user = User.objects.create_user(
# username=username,
# email=email,
# first_name=first_name,
# last_name=last_name,
# tenant=tenant,
# is_active=True
# )
#
# User.objects.create(
# user=user,
# title="Dr.",
# specialty="Anesthesiology",
# license_number=self.fake.saudi_medical_license(),
# phone_number=self.fake.saudi_phone_number(),
# department="Anesthesia Department",
# is_verified=True,
# years_of_experience=random.randint(5, 20),
# education=f"MD from {random.choice(["King Saud University", "King Abdulaziz University", "Imam Abdulrahman Bin Faisal University"])}"
# )
#
# users.append(user)
#
# self.stdout.write(f"Created {len(users)} medical staff users with Saudi names")
# return users
#
#
# def create_patients(self, tenant):
# """Create patient records with Saudi demographics."""
# patients = []
#
# for i in range(150):
# gender = random.choice(["M", "F"])
# if gender == "M":
# full_name = self.fake.saudi_male_name()
# else:
# full_name = self.fake.saudi_female_name()
#
# name_parts = full_name.split()
# first_name = name_parts[0]
# last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else name_parts[0]
#
# birth_date = self.fake.date_of_birth(minimum_age=1, maximum_age=85)
#
# patient = PatientProfile.objects.create(
# tenant=tenant,
# medical_record_number=f"MRN{random.randint(100000, 999999)}",
# first_name=first_name,
# last_name=last_name,
# date_of_birth=birth_date,
# gender=gender,
# national_id=self.fake.saudi_national_id(),
# phone_number=self.fake.saudi_phone_number(),
# email=f"patient{i}@email.com",
# address=f"{self.fake.street_address()}, {self.fake.saudi_city()}, Saudi Arabia",
# emergency_contact_name=self.fake.saudi_male_name() if random.choice(
# [True, False]) else self.fake.saudi_female_name(),
# emergency_contact_phone=self.fake.saudi_phone_number(),
# blood_type=random.choice(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]),
# nationality="Saudi Arabian" if random.random() > 0.3 else random.choice(
# ["Egyptian", "Pakistani", "Indian", "Bangladeshi", "Filipino"]),
# is_active=True
# )
#
# patients.append(patient)
#
# self.stdout.write(f"Created {len(patients)} patients with Saudi demographics")
# return patients
#
#
# def create_operating_rooms(self, tenant, count):
# """Create operating rooms with Saudi hospital context."""
# operating_rooms = []
#
# room_types = [
# ("GENERAL", "General Surgery OR"),
# ("CARDIAC", "Cardiac Surgery OR"),
# ("NEURO", "Neurosurgery OR"),
# ("ORTHOPEDIC", "Orthopedic Surgery OR"),
# ("PEDIATRIC", "Pediatric Surgery OR"),
# ("TRAUMA", "Trauma Surgery OR"),
# ("OPHTHALMOLOGY", "Eye Surgery OR"),
# ("ENT", "ENT Surgery OR")
# ]
#
# floors = ["2nd Floor - Surgical Wing", "3rd Floor - Cardiac Wing", "4th Floor - Specialty Wing"]
#
# for i in range(1, count + 1):
# room_type, room_name = random.choice(room_types)
#
# operating_room = OperatingRoom.objects.create(
# tenant=tenant,
# room_number=f"OR-{i:02d}",
# room_name=f"{room_name} {i}",
# room_type=room_type,
# floor=random.randint(2, 5),
# location=random.choice(floors),
# capacity=random.randint(10, 18),
# status=random.choice(["AVAILABLE", "IN_USE", "MAINTENANCE", "CLEANING"]),
# equipment_list=f"Ventilator, Cardiac Monitor, {self.fake.medical_equipment_name()}, Anesthesia Machine",
# special_requirements=f"Special requirements for {room_name.lower()}",
# is_active=True,
# last_maintenance=timezone.now().date() - timedelta(days=random.randint(1, 30)),
# next_maintenance=timezone.now().date() + timedelta(days=random.randint(30, 90))
# )
#
# operating_rooms.append(operating_room)
#
# self.stdout.write(f"Created {count} operating rooms")
# return operating_rooms
#
#
# def create_surgical_note_templates(self, tenant, users, count):
# """Create surgical note templates for common Saudi procedures."""
# templates = []
#
# specialties = [
# "General Surgery", "Cardiac Surgery", "Neurosurgery", "Orthopedic Surgery",
# "Plastic Surgery", "Urology", "Pediatric Surgery", "Ophthalmology"
# ]
#
# for i in range(count):
# specialty = random.choice(specialties)
# procedure = self.fake.surgical_procedure()
#
# template = SurgicalNoteTemplate.objects.create(
# tenant=tenant,
# template_name=f"{procedure} Template",
# procedure_type=procedure,
# specialty=specialty,
# pre_operative_diagnosis_template=f"Pre-operative diagnosis for {procedure}",
# post_operative_diagnosis_template=f"Post-operative diagnosis following {procedure}",
# procedure_template=f"Detailed description of {procedure} procedure",
# findings_template=f"Expected findings for {procedure}",
# technique_template=f"Surgical technique used in {procedure}",
# complications_template="No complications noted",
# instructions_template=f"Post-operative instructions for {procedure}",
# created_by=random.choice(users),
# is_active=True,
# version=f"v{random.randint(1, 5)}.{random.randint(0, 9)}"
# )
#
# templates.append(template)
#
# self.stdout.write(f"Created {count} surgical note templates")
# return templates
#
#
# def create_or_blocks(self, tenant, operating_rooms, users, count):
# """Create OR blocks (time slots) with Saudi working hours."""
# or_blocks = []
#
# # Saudi working hours: typically 7 AM to 3 PM for morning shift, 3 PM to 11 PM for evening
# working_hours = [
# (7, 15), # Morning shift
# (15, 23), # Evening shift
# ]
#
# for i in range(count):
# start_date = timezone.now().date() + timedelta(days=random.randint(-15, 45))
# shift_start, shift_end = random.choice(working_hours)
#
# start_hour = random.randint(shift_start, shift_end - 4)
# start_time = timezone.make_aware(
# datetime.combine(start_date, datetime.min.time().replace(
# hour=start_hour,
# minute=random.choice([0, 30])
# ))
# )
# end_time = start_time + timedelta(hours=random.randint(2, 6))
#
# or_block = ORBlock.objects.create(
# tenant=tenant,
# operating_room=random.choice(operating_rooms),
# date=start_date,
# start_time=start_time.time(),
# end_time=end_time.time(),
# assigned_surgeon=random.choice(users),
# block_type=random.choice(["ELECTIVE", "EMERGENCY", "URGENT"]),
# specialty=self.fake.medical_specialty(),
# notes=f"OR Block {i + 1} - {self.fake.medical_specialty()}",
# is_active=True,
# utilization_rate=random.randint(70, 100)
# )
#
# or_blocks.append(or_block)
#
# self.stdout.write(f"Created {count} OR blocks")
# return or_blocks
#
#
# def create_surgical_cases(self, tenant, patients, users, operating_rooms, count):
# """Create surgical cases with Saudi medical context."""
# surgical_cases = []
#
# priorities = ["ROUTINE", "URGENT", "EMERGENCY"]
# statuses = ["SCHEDULED", "IN_PROGRESS", "COMPLETED", "CANCELLED", "POSTPONED"]
#
# # Weight the statuses to be more realistic
# status_weights = [0.4, 0.1, 0.4, 0.05, 0.05]
#
# for i in range(count):
# scheduled_start = timezone.now() + timedelta(
# days=random.randint(-30, 30),
# hours=random.randint(7, 20),
# minutes=random.choice([0, 15, 30, 45])
# )
#
# status = random.choices(statuses, weights=status_weights)[0]
# actual_start = None
# actual_end = None
#
# if status in ["IN_PROGRESS", "COMPLETED"]:
# actual_start = scheduled_start + timedelta(minutes=random.randint(-15, 45))
#
# if status == "COMPLETED":
# duration_hours = random.randint(1, 8)
# actual_end = actual_start + timedelta(
# hours=duration_hours,
# minutes=random.randint(0, 59)
# )
#
# procedure = self.fake.surgical_procedure()
# priority = random.choices(priorities, weights=[0.7, 0.2, 0.1])[0]
#
# # Create case number with Saudi format
# case_number = f"CASE-{tenant.slug.upper()}-{timezone.now().year}-{i + 1:05d}"
#
# surgical_case = SurgicalCase.objects.create(
# tenant=tenant,
# case_number=case_number,
# patient=random.choice(patients),
# primary_surgeon=random.choice(users),
# anesthesiologist=random.choice(users),
# operating_room=random.choice(operating_rooms),
# procedure_name=procedure,
# scheduled_start_time=scheduled_start,
# scheduled_end_time=scheduled_start + timedelta(hours=random.randint(2, 8)),
# actual_start_time=actual_start,
# actual_end_time=actual_end,
# priority=priority,
# status=status,
# diagnosis=f"Diagnosis requiring {procedure}",
# notes=f"Surgical case notes for {procedure} - Patient from {self.fake.saudi_city()}",
# estimated_duration=timedelta(hours=random.randint(2, 6)),
# is_emergency=(priority == "EMERGENCY"),
# insurance_type=random.choice(["Government", "Private", "Self-Pay", "Company Insurance"]),
# consent_obtained=True if status != "SCHEDULED" else random.choice([True, False])
# )
#
# surgical_cases.append(surgical_case)
#
# self.stdout.write(f"Created {count} surgical cases")
# return surgical_cases
#
#
# def create_surgical_notes(self, tenant, surgical_cases, users, templates, count):
# """Create surgical notes with Saudi medical documentation standards."""
# surgical_notes = []
#
# # Only create notes for completed or in-progress cases
# eligible_cases = [case for case in surgical_cases if case.status in ["COMPLETED", "IN_PROGRESS"]]
#
# for i in range(min(count, len(eligible_cases))):
# case = eligible_cases[i]
# template = random.choice(templates) if templates and random.random() > 0.3 else None
#
# # Create realistic surgical note content
# complications = "No complications noted" if random.random() > 0.15 else random.choice([
# "Minor bleeding controlled with electrocautery",
# "Slight tissue adhesions noted and carefully dissected",
# "Temporary hypotension managed with fluids"
# ])
#
# surgical_note = SurgicalNote.objects.create(
# tenant=tenant,
# surgical_case=case,
# template=template,
# pre_operative_diagnosis=f"Pre-operative diagnosis: {case.diagnosis}",
# post_operative_diagnosis=f"Post-operative diagnosis: Successful {case.procedure_name}",
# procedure_performed=f"{case.procedure_name} performed according to standard protocol at {tenant.name}",
# operative_findings=f"Surgical findings: Procedure completed successfully without major complications",
# technique=f"Standard technique used for {case.procedure_name} with modern equipment",
# complications=complications,
# post_operative_instructions=f"Post-operative care instructions for {case.procedure_name} - Follow up in 1-2 weeks",
# additional_notes=f"Additional notes for case {case.case_number} - Patient tolerated procedure well",
# created_by=case.primary_surgeon,
# status=random.choices(["DRAFT", "SIGNED", "FINALIZED"], weights=[0.2, 0.3, 0.5])[0],
# signed_at=timezone.now() - timedelta(hours=random.randint(1, 48)) if random.choice([True, False]) else None,
# dictation_time=random.randint(15, 45), # minutes
# transcription_time=random.randint(30, 90) # minutes
# )
#
# surgical_notes.append(surgical_note)
#
# self.stdout.write(f"Created {len(surgical_notes)} surgical notes")
# return surgical_notes
#
#
# def create_equipment_usage(self, tenant, surgical_cases, operating_rooms, count):
# """Create equipment usage records with Saudi hospital equipment."""
# equipment_usage_records = []
#
# equipment_names = [
# "Ventilator Model SV-300", "Cardiac Monitor CM-2000", "Defibrillator DF-500",
# "Laparoscope HD-Pro", "Electrocautery Unit ECU-400", "Ultrasound Machine US-Elite",
# "Infusion Pump IP-Smart", "Blood Pressure Monitor BPM-Digital", "Surgical Laser SL-2000",
# "Anesthesia Machine AM-Pro", "Operating Microscope OM-HD", "Arthroscope AS-Flex"
# ]
#
# statuses = ["IN_USE", "COMPLETED", "MAINTENANCE", "AVAILABLE"]
# status_weights = [0.15, 0.6, 0.1, 0.15]
#
# for i in range(count):
# case = random.choice(surgical_cases)
# equipment_name = random.choice(equipment_names)
#
# start_time = case.actual_start_time or case.scheduled_start_time
# end_time = None
# status = random.choices(statuses, weights=status_weights)[0]
#
# if status == "COMPLETED" and case.actual_end_time:
# end_time = case.actual_end_time
# elif status == "IN_USE":
# end_time = None
# else:
# end_time = start_time + timedelta(hours=random.randint(1, 6))
#
# # Generate Saudi equipment serial numbers
# serial_prefix = random.choice(["KSA", "RYD", "JED", "DMM"])
# serial_number = f"{serial_prefix}-{random.randint(1000, 9999)}"
#
# equipment_usage = EquipmentUsage.objects.create(
# tenant=tenant,
# surgical_case=case,
# operating_room=case.operating_room,
# equipment_name=equipment_name,
# equipment_serial=serial_number,
# start_time=start_time,
# end_time=end_time,
# status=status,
# notes=f"Equipment usage for {case.procedure_name} - {equipment_name}",
# maintenance_required=random.choice([True, False]),
# operator_name=case.primary_surgeon.get_full_name(),
# usage_duration=end_time - start_time if end_time else None
# )
#
# equipment_usage_records.append(equipment_usage)
#
# self.stdout.write(f"Created {count} equipment usage records")
# return equipment_usage_records
#
#
"""
Operating Theatre Data Generator
Generates realistic test data for operating theatre models in Saudi hospital context.
Uses existing tenants, users, and patients from the database.
"""
import os
import django
# Set up Django environment
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hospital_management.settings')
django.setup()
import random
import uuid
from datetime import datetime, date, time, timedelta
from decimal import Decimal
from django.utils import timezone
from django.contrib.auth import get_user_model
# Import models
from operating_theatre.models import (
OperatingRoom, ORBlock, SurgicalCase, SurgicalNote,
EquipmentUsage, SurgicalNoteTemplate
)
from core.models import Tenant
from patients.models import PatientProfile
from emr.models import Encounter
from inpatients.models import Admission
User = get_user_model()
class OperatingTheatreDataGenerator:
"""Generate Saudi-influenced operating theatre data"""
def __init__(self):
self.setup_saudi_data()
def setup_saudi_data(self):
"""Setup Saudi-specific data for generation"""
# Arabic-influenced room names
self.room_names = [
"First Operating Room", "Second Operating Room", "Third Operating Room",
"General Surgery Wing", "Cardiac Surgery Wing", "Neurosurgery Wing",
"Emergency Surgery Unit", "Robotic Surgery Center", "Orthopedic Surgery Department"
]
# Common Saudi procedures (Arabic + English)
self.procedures = [
"Laparoscopic Cholecystectomy","Open Heart Surgery",
"Total Knee Replacement", "Inguinal Hernia Repair",
"Appendectomy", "Diagnostic Laparoscopy",
"Thyroidectomy", "Cataract Surgery",
"Tonsillectomy", "Hemorrhoidectomy"
]
# Saudi medical equipment (common in Saudi hospitals)
self.equipment = [
"Carl Zeiss Laparoscope","Electrocautery Unit",
"Drager Anesthesia Machine", "Leica Surgical Microscope",
"da Vinci Surgical Robot", "Portable CT Scanner",
"Cystoscope", "Heart-Lung Machine"
]
# Common diagnoses in Arabic and English
self.diagnoses = [
"Acute Cholecystitis", "Bowel Obstruction",
"Femur Fracture", "Thyroid Nodules",
"Kidney Stones", "Appendicitis",
"Inguinal Hernia", "Colorectal Cancer"
]
def get_existing_data(self):
"""Retrieve existing data from database"""
print("Retrieving existing data from database...")
# Get tenants
tenants = list(Tenant.objects.all())
if not tenants:
raise ValueError("No tenants found in database. Please create tenants first.")
# Get users with different roles
users = list(User.objects.all())
if not users:
raise ValueError("No users found in database. Please create users first.")
# Try to categorize users by role/specialty
surgeons = list(User.objects.filter(
groups__name__icontains='SURGEON'
).distinct()) or users[:max(1, len(users) // 3)]
anesthesiologists = list(User.objects.filter(
groups__name__icontains='ANESTHESIA'
).distinct()) or users[len(users) // 3:2 * len(users) // 3]
nurses = list(User.objects.filter(
groups__name__icontains='NURSE'
).distinct()) or users[2 * len(users) // 3:]
# Get patients
patients = list(PatientProfile.objects.all())
if not patients:
raise ValueError("No patients found in database. Please create patients first.")
# Get encounters and admissions if available
encounters = list(Encounter.objects.all()) if hasattr(Encounter, 'objects') else []
admissions = list(Admission.objects.all()) if hasattr(Admission, 'objects') else []
print(f"Found: {len(tenants)} tenants, {len(users)} users, {len(patients)} patients")
print(
f"Categorized: {len(surgeons)} surgeons, {len(anesthesiologists)} anesthesiologists, {len(nurses)} nurses")
return {
'tenants': tenants,
'users': users,
'surgeons': surgeons,
'anesthesiologists': anesthesiologists,
'nurses': nurses,
'patients': patients,
'encounters': encounters,
'admissions': admissions
}
def generate_operating_rooms(self, data, count=15):
"""Generate operating rooms"""
print(f"Generating {count} operating rooms...")
operating_rooms = []
for tenant in data['tenants']:
rooms_per_tenant = count // len(data['tenants']) + (1 if tenant == data['tenants'][0] else 0)
for i in range(rooms_per_tenant):
room = OperatingRoom.objects.create(
tenant=tenant,
room_number=f"OR-{i + 1:02d}",
room_name=random.choice(self.room_names),
room_type=random.choice([choice[0] for choice in OperatingRoom.OperatingRoomType.choices]),
status=random.choice([choice[0] for choice in OperatingRoom.ORStatus.choices]),
floor_number=random.randint(2, 8),
room_size=random.uniform(25.0, 60.0),
ceiling_height=random.uniform(3.0, 4.5),
temperature_min=random.uniform(16.0, 20.0),
temperature_max=random.uniform(22.0, 28.0),
humidity_min=random.uniform(25.0, 35.0),
humidity_max=random.uniform(55.0, 65.0),
air_changes_per_hour=random.randint(15, 25),
positive_pressure=random.choice([True, False]),
# equipment_list=random.sample(self.equipment, k=random.randint(3, 8)),
special_features=random.sample([
"HEPA Filtration", "Temperature Control", "Humidity Control",
"Integrated Monitors", "Surgical Lights", "Emergency Power"
], k=random.randint(2, 4)),
has_c_arm=random.choice([True, False]),
has_ct=random.choice([True, False]) if random.random() > 0.7 else False,
has_mri=random.choice([True, False]) if random.random() > 0.8 else False,
has_ultrasound=random.choice([True, False]),
has_neuromonitoring=random.choice([True, False]) if random.random() > 0.6 else False,
supports_robotic=random.choice([True, False]) if random.random() > 0.7 else False,
supports_laparoscopic=random.choice([True, True, True, False]), # More likely True
supports_microscopy=random.choice([True, False]),
supports_laser=random.choice([True, False]),
max_case_duration=random.choice([240, 360, 480, 600, 720]),
turnover_time=random.randint(20, 45),
cleaning_time=random.randint(30, 60),
required_nurses=random.randint(2, 4),
required_techs=random.randint(1, 3),
is_active=random.choice([True, True, True, False]), # More likely active
accepts_emergency=random.choice([True, True, False]), # More likely to accept
building=random.choice(["Main Hospital", "Surgical Center", "Medical Tower"]),
wing=random.choice(["North Wing", "South Wing", "East Wing", "West Wing"]),
created_by=random.choice(data['users'])
)
operating_rooms.append(room)
print(f"Generated {len(operating_rooms)} operating rooms")
return operating_rooms
def generate_surgical_note_templates(self, data, count=20):
"""Generate surgical note templates"""
print(f"Generating {count} surgical note templates...")
templates = []
template_data = [
{
'name': 'General Laparoscopic Surgery',
'specialty': 'GENERAL',
'procedure_type': 'Laparoscopic Surgery',
'preoperative_diagnosis': 'Acute cholecystitis with cholelithiasis',
'planned_procedure': 'Laparoscopic cholecystectomy',
'indication': 'Symptomatic gallstone disease with acute inflammation'
},
{
'name': 'Cardiac Surgery Standard',
'specialty': 'CARDIAC',
'procedure_type': 'Open Heart Surgery',
'preoperative_diagnosis': 'Coronary artery disease, three vessel',
'planned_procedure': 'Coronary artery bypass grafting',
'indication': 'Significant coronary artery stenosis'
},
{
'name': 'Orthopedic Joint Replacement',
'specialty': 'ORTHOPEDIC',
'procedure_type': 'Joint Replacement',
'preoperative_diagnosis': 'Severe osteoarthritis of the knee',
'planned_procedure': 'Total knee arthroplasty',
'indication': 'End-stage arthritis with functional limitation'
},
{
'name': 'Neurosurgical Craniotomy',
'specialty': 'NEURO',
'procedure_type': 'Craniotomy',
'preoperative_diagnosis': 'Brain tumor, frontal lobe',
'planned_procedure': 'Craniotomy and tumor resection',
'indication': 'Mass lesion with neurological symptoms'
},
{
'name': 'Emergency Appendectomy',
'specialty': 'GENERAL',
'procedure_type': 'Emergency Surgery',
'preoperative_diagnosis': 'Acute appendicitis',
'planned_procedure': 'Laparoscopic appendectomy',
'indication': 'Acute inflammatory process of the appendix'
}
]
for tenant in data['tenants']:
for template_info in template_data:
template = SurgicalNoteTemplate.objects.create(
tenant=tenant,
name=template_info['name'],
description=f"Standard template for {template_info['procedure_type']}",
procedure_type=template_info['procedure_type'],
specialty=template_info['specialty'],
preoperative_diagnosis_template=template_info['preoperative_diagnosis'],
planned_procedure_template=template_info['planned_procedure'],
indication_template=template_info['indication'],
procedure_performed_template=template_info['planned_procedure'],
surgical_approach_template="Standard laparoscopic approach with CO2 insufflation",
findings_template="Findings consistent with preoperative diagnosis",
technique_template="Standard surgical technique employed",
postoperative_diagnosis_template=template_info['preoperative_diagnosis'],
complications_template="No intraoperative complications",
specimens_template="Specimen sent to pathology for routine examination",
implants_template="No implants used",
closure_template="Fascia closed with absorbable sutures, skin closed with skin adhesive",
postop_instructions_template="NPO until bowel function returns, progressive diet advancement",
is_active=True,
is_default=random.choice([True, False]),
created_by=random.choice(data['users'])
)
templates.append(template)
# Generate additional random templates
for i in range(count - len(template_data)):
template = SurgicalNoteTemplate.objects.create(
tenant=tenant,
name=f"Custom Template {i + 1}",
description=f"Custom surgical note template {i + 1}",
procedure_type=random.choice(self.procedures),
specialty=random.choice([choice[0] for choice in SurgicalNoteTemplate.SurgicalSpecialty.choices]),
preoperative_diagnosis_template=random.choice(self.diagnoses),
planned_procedure_template=random.choice(self.procedures),
indication_template="Standard indication for procedure",
procedure_performed_template=random.choice(self.procedures),
surgical_approach_template="Standard surgical approach",
findings_template="Findings as expected",
technique_template="Standard technique employed",
postoperative_diagnosis_template=random.choice(self.diagnoses),
is_active=random.choice([True, False]),
created_by=random.choice(data['users'])
)
templates.append(template)
print(f"Generated {len(templates)} surgical note templates")
return templates
def generate_or_blocks(self, operating_rooms, data, count=50):
"""Generate OR blocks"""
print(f"Generating {count} OR blocks...")
blocks = []
for i in range(count):
# Generate dates for the next 30 days
block_date = date.today() + timedelta(days=random.randint(0, 30))
# Generate time slots
start_hour = random.randint(6, 20)
start_minute = random.choice([0, 30])
start_time = time(start_hour, start_minute)
duration_hours = random.randint(2, 8)
end_hour = min(23, start_hour + duration_hours)
end_time = time(end_hour, start_minute)
block = ORBlock.objects.create(
operating_room=random.choice(operating_rooms),
date=block_date,
start_time=start_time,
end_time=end_time,
block_type=random.choice([choice[0] for choice in ORBlock.BlockType.choices]),
primary_surgeon=random.choice(data['surgeons']),
service=random.choice([choice[0] for choice in ORBlock.ORService.choices]),
status=random.choice([choice[0] for choice in ORBlock.BlockStatus.choices]),
special_equipment=random.sample(self.equipment, k=random.randint(1, 4)),
special_setup=random.choice([
"Standard setup required", "Special positioning needed",
"Additional monitoring required", "Robotic system preparation",
None
]),
notes=random.choice([
"Standard block", "Priority case", "Complex procedure expected",
"Patient has multiple comorbidities", None
]),
created_by=random.choice(data['users'])
)
# Add assistant surgeons
if random.random() > 0.5:
assistants = random.sample(data['surgeons'], k=random.randint(1, 2))
block.assistant_surgeons.set(assistants)
blocks.append(block)
print(f"Generated {len(blocks)} OR blocks")
return blocks
def generate_surgical_cases(self, or_blocks, data, count=80):
"""Generate surgical cases"""
print(f"Generating {count} surgical cases...")
cases = []
for i in range(count):
block = random.choice(or_blocks)
# Generate procedure information
primary_procedure = random.choice(self.procedures)
diagnosis = random.choice(self.diagnoses)
# Generate timing
scheduled_start = datetime.combine(
block.date,
block.start_time
) + timedelta(minutes=random.randint(0, 60))
estimated_duration = random.randint(30, 360)
# Generate actual times for some cases
actual_start = None
actual_end = None
if random.random() > 0.4: # 60% of cases have actual times
actual_start = scheduled_start + timedelta(minutes=random.randint(-15, 45))
actual_end = actual_start + timedelta(
minutes=estimated_duration + random.randint(-30, 60)
)
case = SurgicalCase.objects.create(
or_block=block,
patient=random.choice(data['patients']),
primary_surgeon=block.primary_surgeon,
anesthesiologist=random.choice(data['anesthesiologists']) if data['anesthesiologists'] else None,
circulating_nurse=random.choice(data['nurses']) if data['nurses'] else None,
scrub_nurse=random.choice(data['nurses']) if data['nurses'] else None,
primary_procedure=primary_procedure,
secondary_procedures=random.sample(self.procedures, k=random.randint(0, 2)),
procedure_codes=[f"CPT-{random.randint(10000, 99999)}" for _ in range(random.randint(1, 3))],
case_type=random.choice([choice[0] for choice in SurgicalCase.CaseType.choices]),
approach=random.choice([choice[0] for choice in SurgicalCase.SurgicalApproach.choices]),
anesthesia_type=random.choice([choice[0] for choice in SurgicalCase.AnesthesiaType.choices]),
scheduled_start=scheduled_start,
estimated_duration=estimated_duration,
actual_start=actual_start,
actual_end=actual_end,
status=random.choice([choice[0] for choice in SurgicalCase.CaseStatus.choices]),
diagnosis=diagnosis,
diagnosis_codes=[
f"ICD10-{chr(65 + random.randint(0, 25))}{random.randint(10, 99)}.{random.randint(0, 9)}"
for _ in range(random.randint(1, 2))],
clinical_notes=f"Patient presents with {diagnosis.lower()}. Surgical intervention indicated.",
special_equipment=random.sample(self.equipment, k=random.randint(0, 3)),
blood_products=random.sample([
"Packed RBC", "Fresh Frozen Plasma", "Platelets", "Cryoprecipitate"
], k=random.randint(0, 2)) if random.random() > 0.7 else [],
implants=random.sample([
"Titanium Plate", "Mesh", "Stent", "Joint Prosthesis", "Screws"
], k=random.randint(0, 2)) if random.random() > 0.6 else [],
patient_position=random.choice(
[choice[0] for choice in SurgicalCase.PatientPosition.choices]) if random.random() > 0.2 else None,
complications=random.sample([
"Minor bleeding", "Adhesions encountered", "Technical difficulty"
], k=random.randint(0, 1)) if random.random() > 0.8 else [],
estimated_blood_loss=random.randint(10, 500) if random.random() > 0.3 else None,
encounter=random.choice(data['encounters']) if data['encounters'] and random.random() > 0.5 else None,
admission=random.choice(data['admissions']) if data['admissions'] and random.random() > 0.4 else None,
created_by=random.choice(data['users'])
)
# Add assistant surgeons
if random.random() > 0.4:
assistants = random.sample(data['surgeons'], k=random.randint(1, 2))
case.assistant_surgeons.set(assistants)
cases.append(case)
print(f"Generated {len(cases)} surgical cases")
return cases
def generate_surgical_notes(self, surgical_cases, templates, data):
"""Generate surgical notes for surgical cases"""
print(f"Generating surgical notes...")
notes = []
for case in surgical_cases:
# Only create notes for completed cases
if case.status not in ['COMPLETED', 'IN_PROGRESS'] or random.random() > 0.7:
continue
# Find appropriate template
template = None
case_templates = [t for t in templates if t.tenant == case.tenant]
if case_templates:
template = random.choice(case_templates)
note = SurgicalNote.objects.create(
surgical_case=case,
surgeon=case.primary_surgeon,
preoperative_diagnosis=case.diagnosis,
planned_procedure=case.primary_procedure,
indication=f"Surgical treatment indicated for {case.diagnosis.lower()}",
procedure_performed=case.primary_procedure,
surgical_approach=f"{case.approach.lower()} approach utilized",
findings=random.choice([
"Findings consistent with preoperative diagnosis",
"Moderate inflammation noted",
"Adhesions present as expected",
"Anatomy within normal limits",
"Pathology confirmed intraoperatively"
]),
technique=f"Standard {case.approach.lower()} technique employed with appropriate surgical instruments",
postoperative_diagnosis=case.diagnosis,
condition=random.choice([choice[0] for choice in SurgicalNote.PatientCondition.choices]),
disposition=random.choice([choice[0] for choice in SurgicalNote.Disposition.choices]),
complications=random.choice([
"No intraoperative complications",
"Minor bleeding encountered and controlled",
"Technical difficulty with adhesions",
None
]) if case.complications else "No intraoperative complications",
estimated_blood_loss=case.estimated_blood_loss,
blood_transfusion=random.choice([
None, "No blood transfusion required",
"2 units packed RBC transfused"
]) if random.random() > 0.8 else None,
specimens=random.choice([
f"Specimen sent to pathology for routine examination",
"Tissue specimen sent for histopathological analysis",
"No specimens obtained",
None
]),
implants=", ".join(case.implants) if case.implants else None,
drains=random.choice([
"Jackson-Pratt drain placed", "No drains required",
"Blake drain inserted", None
]) if random.random() > 0.6 else None,
closure=random.choice([
"Fascia closed with interrupted sutures, skin closed with staples",
"Layered closure performed, skin closed with absorbable sutures",
"Standard closure technique employed"
]),
postop_instructions=random.choice([
"NPO until bowel function returns, then clear liquids",
"Regular diet as tolerated, ambulate as able",
"Standard postoperative care protocol"
]),
follow_up="Follow-up in clinic in 2-4 weeks, sooner if concerns",
status=random.choice(['COMPLETED', 'SIGNED', 'DRAFT']),
signed_datetime=timezone.now() - timedelta(
days=random.randint(0, 5)) if random.random() > 0.3 else None,
template_used=template
)
notes.append(note)
print(f"Generated {len(notes)} surgical notes")
return notes
def generate_equipment_usage(self, surgical_cases, data, count=200):
"""Generate equipment usage records"""
print(f"Generating {count} equipment usage records...")
usage_records = []
for _ in range(count):
case = random.choice([c for c in surgical_cases if c.status in ['COMPLETED', 'IN_PROGRESS']])
equipment_name = random.choice(self.equipment)
# Generate usage timing
start_time = None
end_time = None
if case.actual_start:
start_time = case.actual_start + timedelta(minutes=random.randint(0, 60))
end_time = start_time + timedelta(minutes=random.randint(15, 180))
usage = EquipmentUsage.objects.create(
surgical_case=case,
equipment_name=equipment_name,
equipment_type=random.choice([choice[0] for choice in EquipmentUsage.EquipmentType.choices]),
manufacturer=random.choice([
"Medtronic", "Johnson & Johnson", "Stryker", "Olympus",
"Karl Storz", "Ethicon", "Boston Scientific", "Abbott"
]),
model=f"Model-{random.randint(1000, 9999)}",
serial_number=f"SN{random.randint(100000, 999999)}",
quantity_used=random.randint(1, 5),
unit_of_measure=random.choice([choice[0] for choice in EquipmentUsage.UnitOfMeasure.choices]),
start_time=start_time,
end_time=end_time,
unit_cost=Decimal(str(random.uniform(10, 1000))).quantize(Decimal('0.01')),
lot_number=f"LOT{random.randint(1000, 9999)}" if random.random() > 0.3 else None,
expiration_date=date.today() + timedelta(
days=random.randint(30, 730)) if random.random() > 0.4 else None,
sterilization_date=date.today() - timedelta(
days=random.randint(1, 7)) if random.random() > 0.5 else None,
notes=random.choice([
"Equipment functioned normally",
"Routine maintenance required after use",
"Minor technical issue resolved",
None
]),
recorded_by=random.choice(data['nurses']) if data['nurses'] else random.choice(data['users'])
)
usage_records.append(usage)
print(f"Generated {len(usage_records)} equipment usage records")
return usage_records
def generate_all_data(self, or_count=15, block_count=50, case_count=80, equipment_count=200):
"""Generate all operating theatre data"""
print("Starting Operating Theatre data generation...")
# Get existing data
data = self.get_existing_data()
# Generate data in order of dependencies
operating_rooms = self.generate_operating_rooms(data, or_count)
templates = self.generate_surgical_note_templates(data)
or_blocks = self.generate_or_blocks(operating_rooms, data, block_count)
surgical_cases = self.generate_surgical_cases(or_blocks, data, case_count)
surgical_notes = self.generate_surgical_notes(surgical_cases, templates, data)
equipment_usage = self.generate_equipment_usage(surgical_cases, data, equipment_count)
summary = {
'operating_rooms': len(operating_rooms),
'surgical_note_templates': len(templates),
'or_blocks': len(or_blocks),
'surgical_cases': len(surgical_cases),
'surgical_notes': len(surgical_notes),
'equipment_usage': len(equipment_usage)
}
print("\n" + "=" * 50)
print("OPERATING THEATRE DATA GENERATION COMPLETE")
print("=" * 50)
for model, count in summary.items():
print(f"{model.replace('_', ' ').title()}: {count}")
print("=" * 50)
return summary
# Usage example:
def generate_operating_theatre_data():
"""Main function to generate operating theatre data"""
generator = OperatingTheatreDataGenerator()
return generator.generate_all_data(
or_count=20, # Number of operating rooms
block_count=60, # Number of OR blocks
case_count=100, # Number of surgical cases
equipment_count=250 # Number of equipment usage records
)
if __name__ == "__main__":
# Run the generator
summary = generate_operating_theatre_data()
print("\nGeneration completed successfully!")