480 lines
20 KiB
Python
480 lines
20 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, timezone
|
|
from accounts.models import User
|
|
from django.utils import timezone as django_timezone
|
|
from core.models import Tenant, AuditLogEntry, SystemConfiguration, SystemNotification, IntegrationLog
|
|
import uuid
|
|
import json
|
|
|
|
|
|
# Saudi-specific data constants
|
|
SAUDI_CITIES = [
|
|
'Riyadh', 'Jeddah', 'Mecca', 'Medina', 'Dammam', 'Khobar', 'Dhahran',
|
|
'Taif', 'Tabuk', 'Buraidah', 'Khamis Mushait', 'Hofuf', 'Mubarraz',
|
|
'Jubail', 'Yanbu', 'Abha', 'Najran', 'Jazan', 'Hail', 'Arar'
|
|
]
|
|
|
|
SAUDI_PROVINCES = [
|
|
'Riyadh Province', 'Makkah Province', 'Eastern Province', 'Asir Province',
|
|
'Jazan Province', 'Medina Province', 'Qassim Province', 'Tabuk Province',
|
|
'Hail Province', 'Northern Borders Province', 'Najran Province', 'Al Bahah Province',
|
|
"Ha'il Province"
|
|
]
|
|
|
|
SAUDI_HOSPITALS = [
|
|
'King Faisal Specialist Hospital', 'King Fahd Medical City', 'National Guard Health Affairs',
|
|
'Prince Sultan Military Medical City', 'King Abdulaziz Medical City', 'King Saud Medical City',
|
|
'Dr. Sulaiman Al Habib Medical Group', 'Saudi German Hospital', 'International Medical Center',
|
|
'King Khalid University Hospital', 'King Abdulaziz University Hospital',
|
|
'Prince Mohammed bin Abdulaziz Hospital', 'King Fahd Hospital', 'Imam Abdulrahman Bin Faisal Hospital'
|
|
]
|
|
|
|
SAUDI_MEDICAL_SPECIALTIES = [
|
|
'Internal Medicine', 'Cardiology', 'Orthopedics', 'Neurology', 'Oncology',
|
|
'Pediatrics', 'Emergency Medicine', 'Radiology', 'Laboratory Medicine',
|
|
'Pharmacy', 'Surgery', 'Obstetrics and Gynecology', 'Dermatology',
|
|
'Ophthalmology', 'ENT', 'Anesthesiology', 'Pathology', 'Psychiatry'
|
|
]
|
|
|
|
ARABIC_FIRST_NAMES_MALE = [
|
|
'Mohammed', 'Abdullah', 'Ahmed', 'Omar', 'Ali', 'Hassan', 'Khalid', 'Faisal',
|
|
'Saad', 'Fahd', 'Bandar', 'Turki', 'Nasser', 'Saud', 'Abdulrahman',
|
|
'Abdulaziz', 'Salman', 'Waleed', 'Majid', 'Rayan'
|
|
]
|
|
|
|
ARABIC_FIRST_NAMES_FEMALE = [
|
|
'Fatima', 'Aisha', 'Maryam', 'Khadija', 'Sarah', 'Noura', 'Hala', 'Reem',
|
|
'Lina', 'Dana', 'Rana', 'Nada', 'Layla', 'Amira', 'Zahra', 'Yasmin',
|
|
'Dina', 'Noor', 'Rahma', 'Salma'
|
|
]
|
|
|
|
ARABIC_FAMILY_NAMES = [
|
|
'Al-Rashid', 'Al-Harbi', 'Al-Qahtani', 'Al-Dosari', 'Al-Otaibi', 'Al-Mutairi',
|
|
'Al-Shammari', 'Al-Zahrani', 'Al-Ghamdi', 'Al-Maliki', 'Al-Subai', 'Al-Jubayr',
|
|
'Al-Faisal', 'Al-Saud', 'Al-Thani', 'Al-Maktoum', 'Al-Sabah', 'Al-Khalifa',
|
|
'Bin-Laden', 'Al-Rajhi'
|
|
]
|
|
|
|
|
|
def create_saudi_tenants(count=1):
|
|
"""Create Saudi healthcare tenants"""
|
|
tenants = []
|
|
|
|
for i in range(count):
|
|
hospital_name = 'King Faisal Specialist Hospital'
|
|
city = random.choice(SAUDI_CITIES)
|
|
province = random.choice(SAUDI_PROVINCES)
|
|
|
|
tenant = Tenant.objects.create(
|
|
tenant_id=uuid.uuid4(),
|
|
name=f"{hospital_name} - {city}",
|
|
display_name=f"{hospital_name}",
|
|
description=f"Leading healthcare facility in {city}, Saudi Arabia providing comprehensive medical services",
|
|
organization_type=random.choice(['hospital', 'clinic', 'medical_center', 'specialty_hospital']),
|
|
address_line1=f"King {random.choice(['Fahd', 'Faisal', 'Abdullah', 'Salman'])} Road",
|
|
address_line2=f"Building {random.randint(1, 999)}",
|
|
city=city,
|
|
state=province,
|
|
postal_code=f"{random.randint(10000, 99999)}",
|
|
country="Saudi Arabia",
|
|
phone_number=f"+966-{random.randint(1, 9)}-{random.randint(100, 999)}-{random.randint(1000, 9999)}",
|
|
email=f"info@{hospital_name.lower().replace(' ', '').replace('.', '')}.sa",
|
|
website=f"https://www.{hospital_name.lower().replace(' ', '').replace('.', '')}.sa",
|
|
license_number=f"MOH-{random.randint(100000, 999999)}",
|
|
accreditation_body="Saudi Central Board for Accreditation of Healthcare Institutions (CBAHI)",
|
|
accreditation_number=f"CBAHI-{random.randint(1000, 9999)}",
|
|
accreditation_expiry=django_timezone.now() + timedelta(days=random.randint(365, 1095)),
|
|
timezone="Asia/Riyadh",
|
|
locale="ar_SA",
|
|
currency="SAR",
|
|
subscription_plan=random.choice(['basic', 'premium', 'enterprise']),
|
|
max_users=random.randint(50, 1000),
|
|
max_patients=random.randint(1000, 50000),
|
|
is_active=True,
|
|
is_trial=random.choice([True, False]),
|
|
trial_expires_at=django_timezone.now() + timedelta(days=30) if random.choice([True, False]) else None,
|
|
created_at=django_timezone.now() - timedelta(days=random.randint(1, 365)),
|
|
updated_at=django_timezone.now()
|
|
)
|
|
tenants.append(tenant)
|
|
print(f"Created tenant: {tenant.name}")
|
|
|
|
return tenants
|
|
def create_super_user():
|
|
tenant1 = Tenant.objects.get(pk=1)
|
|
User.objects.create_superuser(
|
|
username="admin",
|
|
first_name="Marwan",
|
|
last_name="Alwali",
|
|
email="marwan@tenhal.sa",
|
|
password="Kfsh&rc9788",
|
|
tenant=tenant1 # assumes your User model has a ForeignKey to Tenant named `tenant`
|
|
)
|
|
|
|
# def create_saudi_departments(tenants, departments_per_tenant=15):
|
|
# """Create Saudi healthcare departments"""
|
|
# departments = []
|
|
#
|
|
# department_types = [
|
|
# ('clinical', 'Clinical Department'),
|
|
# ('support', 'Support Department'),
|
|
# ('administrative', 'Administrative Department'),
|
|
# ('diagnostic', 'Diagnostic Department')
|
|
# ]
|
|
#
|
|
# for tenant in tenants:
|
|
# # Create main departments
|
|
# for specialty in SAUDI_MEDICAL_SPECIALTIES[:departments_per_tenant]:
|
|
# dept_type = random.choice(department_types)
|
|
#
|
|
# department = Department.objects.create(
|
|
# tenant=tenant,
|
|
# department_id=uuid.uuid4(),
|
|
# code=specialty.replace(' ', '').upper()[:10],
|
|
# name=f"Department of {specialty}",
|
|
# description=f"Specialized {specialty.lower()} department providing comprehensive medical care",
|
|
# department_type=dept_type[0],
|
|
# parent_department=None, # Main departments
|
|
# phone=f"+966-{random.randint(1, 9)}-{random.randint(100, 999)}-{random.randint(1000, 9999)}",
|
|
# extension=f"{random.randint(1000, 9999)}",
|
|
# email=f"{specialty.lower().replace(' ', '').replace('and', '')}@{tenant.name.lower().replace(' ', '').replace('-', '')}.sa",
|
|
# building=f"Building {random.choice(['A', 'B', 'C', 'D', 'Medical Tower'])}",
|
|
# floor=f"Floor {random.randint(1, 10)}",
|
|
# wing=random.choice(['North Wing', 'South Wing', 'East Wing', 'West Wing', 'Central Wing']),
|
|
# room_numbers=f"{random.randint(100, 999)}-{random.randint(100, 999)}",
|
|
# is_active=True,
|
|
# is_24_hour=specialty in ['Emergency Medicine', 'Internal Medicine', 'Cardiology'],
|
|
# operating_hours={
|
|
# "sunday": {"open": "07:00", "close": "20:00"},
|
|
# "monday": {"open": "07:00", "close": "20:00"},
|
|
# "tuesday": {"open": "07:00", "close": "20:00"},
|
|
# "wednesday": {"open": "07:00", "close": "20:00"},
|
|
# "thursday": {"open": "07:00", "close": "20:00"},
|
|
# "friday": {"open": "14:00", "close": "20:00"}, # Friday afternoon
|
|
# "saturday": {"open": "07:00", "close": "20:00"}
|
|
# },
|
|
# cost_center_code=f"CC-{random.randint(1000, 9999)}",
|
|
# budget_code=f"BG-{specialty.replace(' ', '').upper()[:6]}",
|
|
# authorized_positions=random.randint(5, 50),
|
|
# current_staff_count=random.randint(3, 45),
|
|
# accreditation_required=True,
|
|
# accreditation_body="CBAHI",
|
|
# last_inspection_date=django_timezone.now() - timedelta(days=random.randint(30, 365)),
|
|
# next_inspection_date=django_timezone.now() + timedelta(days=random.randint(30, 365)),
|
|
# created_at=django_timezone.now() - timedelta(days=random.randint(1, 180)),
|
|
# updated_at=django_timezone.now()
|
|
# )
|
|
# departments.append(department)
|
|
#
|
|
# print(f"Created {departments_per_tenant} departments for {tenant.name}")
|
|
#
|
|
# return departments
|
|
|
|
|
|
def create_saudi_system_configurations(tenants):
|
|
"""Create Saudi-specific system configurations"""
|
|
configurations = []
|
|
|
|
saudi_configs = [
|
|
{
|
|
'key': 'default_language',
|
|
'value': 'ar_SA',
|
|
'data_type': 'string',
|
|
'category': 'localization',
|
|
'description': 'Default system language for Saudi users'
|
|
},
|
|
{
|
|
'key': 'currency_code',
|
|
'value': 'SAR',
|
|
'data_type': 'string',
|
|
'category': 'financial',
|
|
'description': 'Saudi Riyal currency code'
|
|
},
|
|
{
|
|
'key': 'timezone',
|
|
'value': 'Asia/Riyadh',
|
|
'data_type': 'string',
|
|
'category': 'system',
|
|
'description': 'Saudi Arabia timezone'
|
|
},
|
|
{
|
|
'key': 'prayer_times_enabled',
|
|
'value': 'true',
|
|
'data_type': 'boolean',
|
|
'category': 'cultural',
|
|
'description': 'Enable prayer time notifications'
|
|
},
|
|
{
|
|
'key': 'weekend_days',
|
|
'value': 'friday,saturday',
|
|
'data_type': 'string',
|
|
'category': 'schedule',
|
|
'description': 'Weekend days in Saudi Arabia'
|
|
},
|
|
{
|
|
'key': 'national_id_format',
|
|
'value': '^[1-2][0-9]{9}$',
|
|
'data_type': 'string',
|
|
'category': 'validation',
|
|
'description': 'Saudi National ID format validation'
|
|
},
|
|
{
|
|
'key': 'hijri_calendar_enabled',
|
|
'value': 'true',
|
|
'data_type': 'boolean',
|
|
'category': 'cultural',
|
|
'description': 'Enable Hijri (Islamic) calendar support'
|
|
}
|
|
]
|
|
|
|
for tenant in tenants:
|
|
for config in saudi_configs:
|
|
configuration = SystemConfiguration.objects.create(
|
|
tenant=tenant,
|
|
key=config['key'],
|
|
value=config['value'],
|
|
data_type=config['data_type'],
|
|
category=config['category'],
|
|
description=config['description'],
|
|
validation_rules={},
|
|
default_value=config['value'],
|
|
is_sensitive=False,
|
|
is_encrypted=False,
|
|
required_permission='admin',
|
|
is_active=True,
|
|
is_readonly=False,
|
|
created_at=django_timezone.now() - timedelta(days=random.randint(1, 30)),
|
|
updated_at=django_timezone.now()
|
|
)
|
|
configurations.append(configuration)
|
|
|
|
print(f"Created system configurations for {len(tenants)} tenants")
|
|
return configurations
|
|
|
|
|
|
def create_saudi_notifications(tenants):
|
|
"""Create Saudi-specific system notifications"""
|
|
notifications = []
|
|
|
|
saudi_notifications = [
|
|
{
|
|
'title': 'Ramadan Schedule Update',
|
|
'message': 'Hospital operating hours have been adjusted for the holy month of Ramadan. Please check the updated schedule.',
|
|
'type': 'INFO',
|
|
'priority': 'HIGH'
|
|
},
|
|
{
|
|
'title': 'CBAHI Accreditation Renewal',
|
|
'message': 'Annual CBAHI accreditation renewal is due. Please ensure all documentation is up to date.',
|
|
'type': 'INFO',
|
|
'priority': 'URGENT'
|
|
},
|
|
{
|
|
'title': 'Ministry of Health Guidelines',
|
|
'message': 'New MOH guidelines for patient data privacy have been published. Review required.',
|
|
'type': 'UPDATE',
|
|
'priority': 'HIGH'
|
|
},
|
|
{
|
|
'title': 'Hajj Season Preparation',
|
|
'message': 'Special preparations for Hajj season medical services are now in effect.',
|
|
'type': 'UPDATE',
|
|
'priority': 'MEDIUM'
|
|
},
|
|
{
|
|
'title': 'Arabic Language Interface',
|
|
'message': 'The system now supports full Arabic language interface. Switch in your profile settings.',
|
|
'type': 'FEATURE',
|
|
'priority': 'LOW'
|
|
}
|
|
]
|
|
|
|
for tenant in tenants:
|
|
for notif_data in saudi_notifications:
|
|
notification = SystemNotification.objects.create(
|
|
tenant=tenant,
|
|
notification_id=uuid.uuid4(),
|
|
title=notif_data['title'],
|
|
message=notif_data['message'],
|
|
notification_type=notif_data['type'],
|
|
priority=notif_data['priority'],
|
|
target_audience='all_users',
|
|
target_roles=['doctor', 'nurse', 'admin', 'staff'],
|
|
is_dismissible=True,
|
|
auto_dismiss_after=30,
|
|
show_on_login=notif_data['priority'] in ['high', 'critical'],
|
|
start_date=django_timezone.now(),
|
|
end_date=django_timezone.now() + timedelta(days=60),
|
|
action_url=f"https://portal.{tenant.name.lower().replace(' ', '')}.sa/notices",
|
|
action_text="View Details",
|
|
is_active=True,
|
|
created_at=django_timezone.now() - timedelta(days=random.randint(1, 15)),
|
|
)
|
|
notifications.append(notification)
|
|
|
|
print(f"Created notifications for {len(tenants)} tenants")
|
|
return notifications
|
|
|
|
|
|
def create_saudi_audit_logs(tenants, count_per_tenant=100):
|
|
"""Create Saudi-specific audit log entries"""
|
|
audit_logs = []
|
|
|
|
saudi_events = [
|
|
'patient_registration', 'medical_record_access', 'prescription_issued',
|
|
'lab_result_viewed', 'appointment_scheduled', 'billing_processed',
|
|
'insurance_claim_submitted', 'discharge_summary_created',
|
|
'vital_signs_recorded', 'medication_administered'
|
|
]
|
|
|
|
risk_levels = AuditLogEntry.RiskLevel.choices
|
|
|
|
for tenant in tenants:
|
|
for _ in range(count_per_tenant):
|
|
event_type = random.choice(saudi_events)
|
|
|
|
audit_log = AuditLogEntry.objects.create(
|
|
tenant=tenant,
|
|
log_id=uuid.uuid4(),
|
|
event_type=event_type,
|
|
event_category='CLINICAL_DATA' if event_type in ['medical_record_access',
|
|
'prescription_issued'] else 'SYSTEM_ADMINISTRATION',
|
|
user_email=f"{random.choice(ARABIC_FIRST_NAMES_MALE + ARABIC_FIRST_NAMES_FEMALE).lower()}@{tenant.name.lower().replace(' ', '')}.sa",
|
|
user_role=random.choice(['doctor', 'nurse', 'pharmacist', 'admin', 'receptionist']),
|
|
session_key=uuid.uuid4(),
|
|
ip_address=f"192.168.{random.randint(1, 255)}.{random.randint(1, 255)}",
|
|
user_agent="Mozilla/5.0 (compatible; Hospital-System/1.0)",
|
|
object_repr=f"Patient Record #{random.randint(100000, 999999)}",
|
|
action=random.choice(['create', 'read', 'update', 'delete']),
|
|
description=f"User performed {event_type.replace('_', ' ')} action",
|
|
changes={'field_updated': 'previous_value -> new_value'},
|
|
additional_data={
|
|
'department': random.choice(SAUDI_MEDICAL_SPECIALTIES),
|
|
'location': random.choice(SAUDI_CITIES),
|
|
'session_duration': random.randint(60, 3600)
|
|
},
|
|
patient_id=f"PAT-{random.randint(100000, 999999)}",
|
|
patient_mrn=f"MRN{random.randint(1000000, 9999999)}",
|
|
risk_level=random.choice(risk_levels),
|
|
hipaa_relevant=True,
|
|
gdpr_relevant=False, # Saudi doesn't use GDPR
|
|
is_successful=random.choice([True, True, True, False]), # Mostly successful
|
|
error_message=None if random.choice([True, True, True, False]) else "Access denied",
|
|
timestamp=django_timezone.now() - timedelta(minutes=random.randint(1, 43200)),
|
|
created_at=django_timezone.now() - timedelta(minutes=random.randint(1, 43200))
|
|
)
|
|
audit_logs.append(audit_log)
|
|
|
|
print(f"Created {count_per_tenant} audit logs per tenant for {len(tenants)} tenants")
|
|
return audit_logs
|
|
|
|
|
|
def create_saudi_integration_logs(tenants, count_per_tenant=50):
|
|
"""Create Saudi-specific integration logs"""
|
|
integration_logs = []
|
|
|
|
saudi_integrations = IntegrationLog.IntegrationType.choices
|
|
|
|
message_types = [
|
|
'patient_eligibility', 'claim_submission', 'payment_notification',
|
|
'drug_verification', 'license_validation', 'tax_invoice'
|
|
]
|
|
|
|
for tenant in tenants:
|
|
for _ in range(count_per_tenant):
|
|
integration_type = random.choice(saudi_integrations)
|
|
message_type = random.choice(message_types)
|
|
|
|
integration_log = IntegrationLog.objects.create(
|
|
tenant=tenant,
|
|
log_id=uuid.uuid4(),
|
|
integration_type=integration_type,
|
|
direction=random.choice(['inbound', 'outbound']),
|
|
external_system=integration_type,
|
|
endpoint=f"https://api.{integration_type}.gov.sa/v1/{message_type}",
|
|
message_type=message_type,
|
|
message_id=f"MSG-{uuid.uuid4().hex[:12].upper()}",
|
|
correlation_id=uuid.uuid4(),
|
|
request_data={
|
|
'patient_id': f"PAT-{random.randint(100000, 999999)}",
|
|
'national_id': f"{random.choice([1, 2])}{random.randint(100000000, 999999999)}",
|
|
'timestamp': django_timezone.now().isoformat()
|
|
},
|
|
response_data={
|
|
'status': 'success',
|
|
'response_code': '200',
|
|
'data': {'verified': True, 'eligibility': 'active'}
|
|
},
|
|
status=random.choice(['SUCCESS', 'SUCCESS', 'SUCCESS', 'FAILED']), # Mostly successful
|
|
error_code=None if random.choice([True, True, True, False]) else 'ERR_401',
|
|
error_message=None if random.choice([True, True, True, False]) else 'Authentication failed',
|
|
processing_time_ms=random.randint(100, 5000),
|
|
timestamp=django_timezone.now() - timedelta(hours=random.randint(1, 168)),
|
|
created_at=django_timezone.now() - timedelta(hours=random.randint(1, 168))
|
|
)
|
|
integration_logs.append(integration_log)
|
|
|
|
print(f"Created {count_per_tenant} integration logs per tenant for {len(tenants)} tenants")
|
|
return integration_logs
|
|
|
|
|
|
def main():
|
|
"""Main function to generate all Saudi healthcare data"""
|
|
print("Starting Saudi Healthcare Data Generation...")
|
|
|
|
# Create tenants
|
|
print("\n1. Creating Saudi Healthcare Tenants...")
|
|
tenants = create_saudi_tenants(1)
|
|
|
|
# Create Super user
|
|
print("\n2. Creating Super User...")
|
|
create_super_user()
|
|
|
|
# Create departments
|
|
# print("\n2. Creating Saudi Medical Departments...")
|
|
# departments = create_saudi_departments(tenants, 12)
|
|
|
|
# Create system configurations
|
|
print("\n3. Creating Saudi System Configurations...")
|
|
configurations = create_saudi_system_configurations(tenants)
|
|
|
|
# Create notifications
|
|
print("\n4. Creating Saudi System Notifications...")
|
|
notifications = create_saudi_notifications(tenants)
|
|
|
|
# Create audit logs
|
|
print("\n5. Creating Saudi Audit Logs...")
|
|
audit_logs = create_saudi_audit_logs(tenants, 75)
|
|
|
|
# Create integration logs
|
|
print("\n6. Creating Saudi Integration Logs...")
|
|
integration_logs = create_saudi_integration_logs(tenants, 40)
|
|
|
|
print(f"\n✅ Saudi Healthcare Data Generation Complete!")
|
|
print(f"📊 Summary:")
|
|
print(f" - Tenants: {len(tenants)}")
|
|
# print(f" - Departments: {len(departments)}")
|
|
print(f" - System Configurations: {len(configurations)}")
|
|
print(f" - Notifications: {len(notifications)}")
|
|
print(f" - Audit Logs: {len(audit_logs)}")
|
|
print(f" - Integration Logs: {len(integration_logs)}")
|
|
|
|
return {
|
|
'tenants': tenants,
|
|
# 'departments': departments,
|
|
'configurations': configurations,
|
|
'notifications': notifications,
|
|
'audit_logs': audit_logs,
|
|
'integration_logs': integration_logs
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |