789 lines
32 KiB
Python
789 lines
32 KiB
Python
"""
|
|
Saudi-influenced data generator for PX360
|
|
|
|
This script generates realistic test data for the PX360 system with:
|
|
- Saudi hospital names
|
|
- Arabic names for patients and staff
|
|
- Saudi cities and regions
|
|
- Realistic medical specializations
|
|
- Sample complaints, surveys, and actions
|
|
"""
|
|
import os
|
|
import random
|
|
from datetime import datetime, timedelta
|
|
|
|
import django
|
|
|
|
# Setup Django
|
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.dev')
|
|
django.setup()
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.utils import timezone
|
|
|
|
from apps.accounts.models import User
|
|
from apps.complaints.models import Complaint, ComplaintUpdate
|
|
from apps.journeys.models import (
|
|
PatientJourneyInstance,
|
|
PatientJourneyStageInstance,
|
|
PatientJourneyStageTemplate,
|
|
PatientJourneyTemplate,
|
|
)
|
|
from apps.organizations.models import Department, Hospital, Patient, Physician
|
|
from apps.projects.models import QIProject
|
|
from apps.px_action_center.models import PXAction
|
|
from apps.surveys.models import SurveyInstance, SurveyQuestion, SurveyResponse, SurveyTemplate
|
|
|
|
# Saudi-specific data
|
|
SAUDI_HOSPITALS = [
|
|
{'name': 'Alhammadi Hospital', 'name_ar': 'مستشفى الحمادي', 'city': 'Riyadh', 'code': 'HH'},
|
|
# {'name': 'King Faisal Specialist Hospital', 'name_ar': 'مستشفى الملك فيصل التخصصي', 'city': 'Riyadh', 'code': 'KFSH'},
|
|
# {'name': 'King Abdulaziz Medical City', 'name_ar': 'مدينة الملك عبدالعزيز الطبية', 'city': 'Riyadh', 'code': 'KAMC'},
|
|
# {'name': 'King Khalid University Hospital', 'name_ar': 'مستشفى الملك خالد الجامعي', 'city': 'Riyadh', 'code': 'KKUH'},
|
|
# {'name': 'King Abdullah Medical Complex', 'name_ar': 'مجمع الملك عبدالله الطبي', 'city': 'Jeddah', 'code': 'KAMC-JED'},
|
|
]
|
|
|
|
SAUDI_CITIES = ['Riyadh', 'Jeddah', 'Mecca', 'Medina', 'Dammam', 'Khobar', 'Dhahran', 'Taif', 'Buraidah', 'Tabuk']
|
|
|
|
ARABIC_FIRST_NAMES_MALE = ['محمد', 'أحمد', 'عبدالله', 'خالد', 'سعود', 'فهد', 'عبدالعزيز', 'سلطان', 'فيصل', 'عمر']
|
|
ARABIC_FIRST_NAMES_FEMALE = ['فاطمة', 'عائشة', 'مريم', 'نورة', 'سارة', 'هند', 'لطيفة', 'منى', 'ريم', 'جواهر']
|
|
ARABIC_LAST_NAMES = ['العتيبي', 'الدوسري', 'القحطاني', 'الشمري', 'الحربي', 'المطيري', 'العنزي', 'الزهراني', 'الغامدي', 'الشهري']
|
|
|
|
ENGLISH_FIRST_NAMES_MALE = ['Mohammed', 'Ahmed', 'Abdullah', 'Khalid', 'Saud', 'Fahd', 'Abdulaziz', 'Sultan', 'Faisal', 'Omar']
|
|
ENGLISH_FIRST_NAMES_FEMALE = ['Fatimah', 'Aisha', 'Maryam', 'Noura', 'Sarah', 'Hind', 'Latifa', 'Mona', 'Reem', 'Jawaher']
|
|
ENGLISH_LAST_NAMES = ['Al-Otaibi', 'Al-Dosari', 'Al-Qahtani', 'Al-Shammari', 'Al-Harbi', 'Al-Mutairi', 'Al-Anazi', 'Al-Zahrani', 'Al-Ghamdi', 'Al-Shehri']
|
|
|
|
DEPARTMENTS = [
|
|
{'name': 'Emergency Department', 'name_ar': 'قسم الطوارئ', 'code': 'ER'},
|
|
{'name': 'Outpatient Department', 'name_ar': 'قسم العيادات الخارجية', 'code': 'OPD'},
|
|
{'name': 'Internal Medicine', 'name_ar': 'الطب الباطني', 'code': 'IM'},
|
|
{'name': 'Surgery', 'name_ar': 'الجراحة', 'code': 'SURG'},
|
|
{'name': 'Pediatrics', 'name_ar': 'طب الأطفال', 'code': 'PEDS'},
|
|
{'name': 'Obstetrics & Gynecology', 'name_ar': 'النساء والولادة', 'code': 'OBGYN'},
|
|
{'name': 'Radiology', 'name_ar': 'الأشعة', 'code': 'RAD'},
|
|
{'name': 'Laboratory', 'name_ar': 'المختبر', 'code': 'LAB'},
|
|
{'name': 'Pharmacy', 'name_ar': 'الصيدلية', 'code': 'PHARM'},
|
|
{'name': 'Cardiology', 'name_ar': 'أمراض القلب', 'code': 'CARD'},
|
|
]
|
|
|
|
SPECIALIZATIONS = [
|
|
'Internal Medicine', 'General Surgery', 'Pediatrics', 'Obstetrics & Gynecology',
|
|
'Cardiology', 'Orthopedics', 'Neurology', 'Dermatology', 'Ophthalmology',
|
|
'ENT', 'Urology', 'Nephrology', 'Gastroenterology', 'Pulmonology'
|
|
]
|
|
|
|
COMPLAINT_TITLES = [
|
|
'Long waiting time in emergency department',
|
|
'Poor communication from nursing staff',
|
|
'Delayed lab results',
|
|
'Billing discrepancy',
|
|
'Unclean patient room',
|
|
'Medication error',
|
|
'Rude behavior from reception staff',
|
|
'Difficulty scheduling appointment',
|
|
'Lost medical records',
|
|
'Inadequate pain management',
|
|
]
|
|
|
|
COMPLAINT_TITLES_AR = [
|
|
'وقت انتظار طويل في قسم الطوارئ',
|
|
'ضعف التواصل من طاقم التمريض',
|
|
'تأخر نتائج المختبر',
|
|
'خطأ في الفاتورة',
|
|
'غرفة المريض غير نظيفة',
|
|
'خطأ في الدواء',
|
|
'سلوك غير لائق من موظف الاستقبال',
|
|
'صعوبة في حجز موعد',
|
|
'فقدان السجلات الطبية',
|
|
'إدارة غير كافية للألم',
|
|
]
|
|
|
|
|
|
def clear_existing_data():
|
|
"""Clear all existing data from the database"""
|
|
print("\n" + "="*60)
|
|
print("Clearing Existing Data...")
|
|
print("="*60 + "\n")
|
|
|
|
from apps.feedback.models import Feedback, FeedbackAttachment, FeedbackResponse
|
|
from apps.social.models import SocialMention
|
|
from apps.callcenter.models import CallCenterInteraction
|
|
|
|
# Delete in reverse order of dependencies
|
|
print("Deleting survey instances...")
|
|
SurveyResponse.objects.all().delete()
|
|
SurveyInstance.objects.all().delete()
|
|
|
|
print("Deleting journey instances...")
|
|
PatientJourneyStageInstance.objects.all().delete()
|
|
PatientJourneyInstance.objects.all().delete()
|
|
|
|
print("Deleting PX actions...")
|
|
PXAction.objects.all().delete()
|
|
|
|
print("Deleting QI projects...")
|
|
QIProject.objects.all().delete()
|
|
|
|
print("Deleting social mentions...")
|
|
SocialMention.objects.all().delete()
|
|
|
|
print("Deleting call center interactions...")
|
|
CallCenterInteraction.objects.all().delete()
|
|
|
|
print("Deleting feedback...")
|
|
FeedbackResponse.objects.all().delete()
|
|
FeedbackAttachment.objects.all().delete()
|
|
Feedback.objects.all().delete()
|
|
|
|
print("Deleting complaints...")
|
|
ComplaintUpdate.objects.all().delete()
|
|
Complaint.objects.all().delete()
|
|
|
|
print("Deleting survey templates...")
|
|
SurveyQuestion.objects.all().delete()
|
|
SurveyTemplate.objects.all().delete()
|
|
|
|
print("Deleting journey templates...")
|
|
PatientJourneyStageTemplate.objects.all().delete()
|
|
PatientJourneyTemplate.objects.all().delete()
|
|
|
|
print("Deleting patients...")
|
|
Patient.objects.all().delete()
|
|
|
|
print("Deleting physicians...")
|
|
Physician.objects.all().delete()
|
|
|
|
print("Deleting departments...")
|
|
Department.objects.all().delete()
|
|
|
|
print("Deleting hospitals...")
|
|
Hospital.objects.all().delete()
|
|
|
|
print("Deleting users (except superusers)...")
|
|
User.objects.filter(is_superuser=False).delete()
|
|
|
|
print("\n✓ All existing data cleared successfully!\n")
|
|
|
|
|
|
def generate_saudi_phone():
|
|
"""Generate Saudi phone number"""
|
|
return f"+966{random.choice(['50', '53', '54', '55', '56', '58'])}{random.randint(1000000, 9999999)}"
|
|
|
|
|
|
def generate_mrn():
|
|
"""Generate Medical Record Number"""
|
|
return f"MRN{random.randint(100000, 999999)}"
|
|
|
|
|
|
def generate_national_id():
|
|
"""Generate Saudi National ID"""
|
|
return f"{random.randint(1000000000, 2999999999)}"
|
|
|
|
|
|
def create_hospitals():
|
|
"""Create Saudi hospitals"""
|
|
print("Creating hospitals...")
|
|
hospitals = []
|
|
for hosp_data in SAUDI_HOSPITALS:
|
|
hospital, created = Hospital.objects.get_or_create(
|
|
code=hosp_data['code'],
|
|
defaults={
|
|
'name': hosp_data['name'],
|
|
'name_ar': hosp_data['name_ar'],
|
|
'city': hosp_data['city'],
|
|
'phone': generate_saudi_phone(),
|
|
'status': 'active',
|
|
'capacity': random.randint(200, 800),
|
|
}
|
|
)
|
|
hospitals.append(hospital)
|
|
if created:
|
|
print(f" Created: {hospital.name}")
|
|
return hospitals
|
|
|
|
|
|
def create_departments(hospitals):
|
|
"""Create departments for each hospital"""
|
|
print("Creating departments...")
|
|
departments = []
|
|
for hospital in hospitals:
|
|
for dept_data in DEPARTMENTS:
|
|
dept, created = Department.objects.get_or_create(
|
|
hospital=hospital,
|
|
code=dept_data['code'],
|
|
defaults={
|
|
'name': dept_data['name'],
|
|
'name_ar': dept_data['name_ar'],
|
|
'status': 'active',
|
|
}
|
|
)
|
|
departments.append(dept)
|
|
if created:
|
|
print(f" Created: {hospital.name} - {dept.name}")
|
|
return departments
|
|
|
|
|
|
def create_physicians(hospitals, departments):
|
|
"""Create physicians"""
|
|
print("Creating physicians...")
|
|
physicians = []
|
|
for i in range(50):
|
|
hospital = random.choice(hospitals)
|
|
dept = random.choice([d for d in departments if d.hospital == hospital])
|
|
|
|
first_name_ar = random.choice(ARABIC_FIRST_NAMES_MALE)
|
|
last_name_ar = random.choice(ARABIC_LAST_NAMES)
|
|
first_name = random.choice(ENGLISH_FIRST_NAMES_MALE)
|
|
last_name = random.choice(ENGLISH_LAST_NAMES)
|
|
|
|
physician, created = Physician.objects.get_or_create(
|
|
license_number=f"LIC{random.randint(10000, 99999)}",
|
|
defaults={
|
|
'first_name': first_name,
|
|
'last_name': last_name,
|
|
'first_name_ar': first_name_ar,
|
|
'last_name_ar': last_name_ar,
|
|
'specialization': random.choice(SPECIALIZATIONS),
|
|
'hospital': hospital,
|
|
'department': dept,
|
|
'phone': generate_saudi_phone(),
|
|
'status': 'active',
|
|
}
|
|
)
|
|
physicians.append(physician)
|
|
print(f" Created {len(physicians)} physicians")
|
|
return physicians
|
|
|
|
|
|
def create_patients(hospitals):
|
|
"""Create patients"""
|
|
print("Creating patients...")
|
|
patients = []
|
|
for i in range(100):
|
|
gender = random.choice(['male', 'female'])
|
|
if gender == 'male':
|
|
first_name_ar = random.choice(ARABIC_FIRST_NAMES_MALE)
|
|
first_name = random.choice(ENGLISH_FIRST_NAMES_MALE)
|
|
else:
|
|
first_name_ar = random.choice(ARABIC_FIRST_NAMES_FEMALE)
|
|
first_name = random.choice(ENGLISH_FIRST_NAMES_FEMALE)
|
|
|
|
last_name_ar = random.choice(ARABIC_LAST_NAMES)
|
|
last_name = random.choice(ENGLISH_LAST_NAMES)
|
|
|
|
patient, created = Patient.objects.get_or_create(
|
|
mrn=generate_mrn(),
|
|
defaults={
|
|
'first_name': first_name,
|
|
'last_name': last_name,
|
|
'first_name_ar': first_name_ar,
|
|
'last_name_ar': last_name_ar,
|
|
'national_id': generate_national_id(),
|
|
'phone': generate_saudi_phone(),
|
|
'email': f"{first_name.lower()}.{last_name.lower()}@example.com",
|
|
'gender': gender,
|
|
'date_of_birth': datetime.now().date() - timedelta(days=random.randint(365*18, 365*80)),
|
|
'city': random.choice(SAUDI_CITIES),
|
|
'primary_hospital': random.choice(hospitals),
|
|
'status': 'active',
|
|
}
|
|
)
|
|
patients.append(patient)
|
|
print(f" Created {len(patients)} patients")
|
|
return patients
|
|
|
|
|
|
def create_users(hospitals):
|
|
"""Create system users"""
|
|
print("Creating users...")
|
|
from django.contrib.auth.models import Group
|
|
|
|
# Create or get groups
|
|
px_admin_group, _ = Group.objects.get_or_create(name='PX Admin')
|
|
hospital_admin_group, _ = Group.objects.get_or_create(name='Hospital Admin')
|
|
|
|
# Create PX Admin
|
|
px_admin, created = User.objects.get_or_create(
|
|
username='px_admin',
|
|
defaults={
|
|
'email': 'px.admin@alhammadi.sa',
|
|
'first_name': 'PX',
|
|
'last_name': 'Administrator',
|
|
'is_staff': True,
|
|
'is_superuser': True,
|
|
}
|
|
)
|
|
if created:
|
|
px_admin.set_password('admin123')
|
|
px_admin.save()
|
|
px_admin.groups.add(px_admin_group)
|
|
print(" Created PX Admin")
|
|
|
|
# Create Hospital Admins
|
|
for hospital in hospitals:
|
|
user, created = User.objects.get_or_create(
|
|
username=f'admin_{hospital.code.lower()}',
|
|
defaults={
|
|
'email': f'admin@{hospital.code.lower()}.sa',
|
|
'first_name': 'Hospital',
|
|
'last_name': 'Admin',
|
|
'hospital': hospital,
|
|
'is_staff': True,
|
|
}
|
|
)
|
|
if created:
|
|
user.set_password('admin123')
|
|
user.save()
|
|
user.groups.add(hospital_admin_group)
|
|
print(f" Created Hospital Admin for {hospital.name}")
|
|
|
|
|
|
def create_complaints(patients, hospitals, physicians, users):
|
|
"""Create sample complaints"""
|
|
print("Creating complaints...")
|
|
complaints = []
|
|
for i in range(30):
|
|
patient = random.choice(patients)
|
|
hospital = patient.primary_hospital or random.choice(hospitals)
|
|
|
|
complaint = Complaint.objects.create(
|
|
patient=patient,
|
|
hospital=hospital,
|
|
department=random.choice(hospital.departments.all()) if hospital.departments.exists() else None,
|
|
physician=random.choice(physicians) if random.random() > 0.5 else None,
|
|
title=random.choice(COMPLAINT_TITLES),
|
|
description=f"Detailed description of the complaint. Patient experienced issues during their visit.",
|
|
category=random.choice(['clinical_care', 'staff_behavior', 'facility', 'wait_time', 'billing']),
|
|
priority=random.choice(['low', 'medium', 'high', 'urgent']),
|
|
severity=random.choice(['low', 'medium', 'high', 'critical']),
|
|
source=random.choice(['patient', 'family', 'survey', 'call_center']),
|
|
status=random.choice(['open', 'in_progress', 'resolved', 'closed']),
|
|
encounter_id=f"ENC{random.randint(100000, 999999)}",
|
|
assigned_to=random.choice(users) if random.random() > 0.5 else None,
|
|
)
|
|
complaints.append(complaint)
|
|
print(f" Created {len(complaints)} complaints")
|
|
return complaints
|
|
|
|
|
|
def create_feedback(patients, hospitals, physicians, users):
|
|
"""Create sample feedback"""
|
|
print("Creating feedback...")
|
|
from apps.feedback.models import Feedback, FeedbackResponse
|
|
|
|
feedback_titles = [
|
|
'Excellent care from Dr. Ahmed',
|
|
'Very satisfied with the service',
|
|
'Suggestion to improve waiting area',
|
|
'Great experience at the hospital',
|
|
'Staff was very helpful and kind',
|
|
'Clean and well-maintained facility',
|
|
'Quick and efficient service',
|
|
'Appreciate the professionalism',
|
|
'Suggestion for better parking',
|
|
'Outstanding nursing care',
|
|
]
|
|
|
|
feedback_messages = [
|
|
'I had a wonderful experience. The staff was very professional and caring.',
|
|
'The doctor took time to explain everything clearly. Very satisfied.',
|
|
'I suggest adding more seating in the waiting area for better comfort.',
|
|
'Everything was excellent from registration to discharge.',
|
|
'The nurses were extremely helpful and answered all my questions.',
|
|
'The facility is very clean and well-organized.',
|
|
'I was seen quickly and the process was very smooth.',
|
|
'I appreciate the high level of professionalism shown by all staff.',
|
|
'The parking area could be improved with better signage.',
|
|
'The nursing staff provided outstanding care during my stay.',
|
|
]
|
|
|
|
feedbacks = []
|
|
for i in range(40):
|
|
patient = random.choice(patients)
|
|
hospital = patient.primary_hospital or random.choice(hospitals)
|
|
is_anonymous = random.random() < 0.2 # 20% anonymous
|
|
|
|
feedback = Feedback.objects.create(
|
|
patient=None if is_anonymous else patient,
|
|
is_anonymous=is_anonymous,
|
|
contact_name=f"{random.choice(ENGLISH_FIRST_NAMES_MALE)} {random.choice(ENGLISH_LAST_NAMES)}" if is_anonymous else '',
|
|
contact_email=f"anonymous{i}@example.com" if is_anonymous else '',
|
|
contact_phone=generate_saudi_phone() if is_anonymous else '',
|
|
hospital=hospital,
|
|
department=random.choice(hospital.departments.all()) if hospital.departments.exists() and random.random() > 0.5 else None,
|
|
physician=random.choice(physicians) if random.random() > 0.6 else None,
|
|
feedback_type=random.choice(['compliment', 'suggestion', 'general', 'inquiry']),
|
|
title=random.choice(feedback_titles),
|
|
message=random.choice(feedback_messages),
|
|
category=random.choice(['clinical_care', 'staff_service', 'facility', 'communication', 'appointment', 'cleanliness']),
|
|
rating=random.randint(3, 5) if random.random() > 0.3 else None,
|
|
priority=random.choice(['low', 'medium', 'high']),
|
|
sentiment=random.choice(['positive', 'neutral', 'negative']),
|
|
sentiment_score=random.uniform(0.3, 1.0) if random.random() > 0.7 else None,
|
|
status=random.choice(['submitted', 'reviewed', 'acknowledged', 'closed']),
|
|
encounter_id=f"ENC{random.randint(100000, 999999)}" if random.random() > 0.5 else '',
|
|
assigned_to=random.choice(users) if random.random() > 0.5 else None,
|
|
is_featured=random.random() < 0.15, # 15% featured
|
|
requires_follow_up=random.random() < 0.2, # 20% require follow-up
|
|
)
|
|
|
|
# Add initial response
|
|
FeedbackResponse.objects.create(
|
|
feedback=feedback,
|
|
response_type='note',
|
|
message=f"Feedback received and logged in the system.",
|
|
created_by=random.choice(users),
|
|
is_internal=True,
|
|
)
|
|
|
|
# Add additional responses for some feedback
|
|
if feedback.status in ['reviewed', 'acknowledged', 'closed'] and random.random() > 0.5:
|
|
FeedbackResponse.objects.create(
|
|
feedback=feedback,
|
|
response_type='response',
|
|
message="Thank you for your feedback. We appreciate your input and will work to improve our services.",
|
|
created_by=random.choice(users),
|
|
is_internal=False,
|
|
)
|
|
|
|
feedbacks.append(feedback)
|
|
|
|
print(f" Created {len(feedbacks)} feedback items")
|
|
return feedbacks
|
|
|
|
|
|
def create_survey_templates(hospitals):
|
|
"""Create survey templates"""
|
|
print("Creating survey templates...")
|
|
# Check if templates already exist
|
|
existing_count = SurveyTemplate.objects.count()
|
|
if existing_count > 0:
|
|
print(f" Survey templates already exist ({existing_count} found), skipping creation...")
|
|
return
|
|
|
|
for hospital in hospitals[:2]: # Create for first 2 hospitals
|
|
# OPD Survey
|
|
template = SurveyTemplate.objects.create(
|
|
name=f'OPD Patient Satisfaction Survey - {hospital.code}',
|
|
name_ar='استبيان رضا مرضى العيادات الخارجية',
|
|
description='Survey for outpatient department visits',
|
|
description_ar='استبيان لزيارات قسم العيادات الخارجية',
|
|
hospital=hospital,
|
|
survey_type='stage',
|
|
scoring_method='average',
|
|
negative_threshold=3.0,
|
|
is_active=True,
|
|
)
|
|
|
|
# Create questions
|
|
questions_data = [
|
|
{'text': 'How would you rate your overall experience?', 'text_ar': 'كيف تقيم تجربتك الإجمالية؟', 'type': 'rating'},
|
|
{'text': 'How likely are you to recommend us?', 'text_ar': 'ما مدى احتمالية توصيتك بنا؟', 'type': 'nps'},
|
|
{'text': 'Was the staff courteous and helpful?', 'text_ar': 'هل كان الموظفون مهذبين ومتعاونين؟', 'type': 'yes_no'},
|
|
{'text': 'Any additional comments?', 'text_ar': 'أي تعليقات إضافية؟', 'type': 'textarea'},
|
|
]
|
|
|
|
for idx, q_data in enumerate(questions_data):
|
|
SurveyQuestion.objects.create(
|
|
survey_template=template,
|
|
text=q_data['text'],
|
|
text_ar=q_data['text_ar'],
|
|
question_type=q_data['type'],
|
|
order=idx,
|
|
is_required=True if idx < 2 else False,
|
|
)
|
|
|
|
print(f" Created survey template for {hospital.name}")
|
|
|
|
|
|
def create_journey_templates(hospitals):
|
|
"""Create journey templates"""
|
|
print("Creating journey templates...")
|
|
for hospital in hospitals[:2]:
|
|
# OPD Journey
|
|
journey_template, created = PatientJourneyTemplate.objects.get_or_create(
|
|
hospital=hospital,
|
|
journey_type='opd',
|
|
name='OPD Journey',
|
|
defaults={
|
|
'name_ar': 'رحلة العيادات الخارجية',
|
|
'is_active': True,
|
|
'is_default': True,
|
|
}
|
|
)
|
|
|
|
if created:
|
|
# Create stages
|
|
stages_data = [
|
|
{'name': 'Registration', 'name_ar': 'التسجيل', 'code': 'REG', 'trigger': 'OPD_REGISTRATION'},
|
|
{'name': 'MD Consultation', 'name_ar': 'استشارة الطبيب', 'code': 'MD', 'trigger': 'OPD_VISIT_COMPLETED'},
|
|
{'name': 'Laboratory', 'name_ar': 'المختبر', 'code': 'LAB', 'trigger': 'LAB_COMPLETED'},
|
|
{'name': 'Pharmacy', 'name_ar': 'الصيدلية', 'code': 'PHARM', 'trigger': 'PHARMACY_DISPENSED'},
|
|
]
|
|
|
|
for idx, stage_data in enumerate(stages_data):
|
|
PatientJourneyStageTemplate.objects.create(
|
|
journey_template=journey_template,
|
|
name=stage_data['name'],
|
|
name_ar=stage_data['name_ar'],
|
|
code=stage_data['code'],
|
|
order=idx,
|
|
trigger_event_code=stage_data['trigger'],
|
|
is_active=True,
|
|
)
|
|
|
|
print(f" Created journey template for {hospital.name}")
|
|
|
|
|
|
def create_qi_projects(hospitals):
|
|
"""Create QI projects"""
|
|
print("Creating QI projects...")
|
|
project_names = [
|
|
('Reduce ER Wait Times', 'تقليل أوقات الانتظار في الطوارئ'),
|
|
('Improve Patient Satisfaction Scores', 'تحسين درجات رضا المرضى'),
|
|
('Enhance Medication Safety', 'تعزيز سلامة الأدوية'),
|
|
('Streamline Discharge Process', 'تبسيط عملية الخروج'),
|
|
]
|
|
|
|
projects = []
|
|
for hospital in hospitals[:2]:
|
|
for name_en, name_ar in project_names[:2]:
|
|
project = QIProject.objects.create(
|
|
name=name_en,
|
|
name_ar=name_ar,
|
|
description=f"Quality improvement initiative to {name_en.lower()}",
|
|
hospital=hospital,
|
|
status=random.choice(['active', 'pending', 'completed']),
|
|
start_date=datetime.now().date() - timedelta(days=random.randint(30, 180)),
|
|
target_completion_date=datetime.now().date() + timedelta(days=random.randint(30, 180)),
|
|
)
|
|
projects.append(project)
|
|
print(f" Created {len(projects)} QI projects")
|
|
return projects
|
|
|
|
|
|
def create_px_actions(complaints, hospitals, users):
|
|
"""Create PX actions"""
|
|
print("Creating PX actions...")
|
|
actions = []
|
|
for i in range(20):
|
|
hospital = random.choice(hospitals)
|
|
action = PXAction.objects.create(
|
|
source_type=random.choice(['survey', 'complaint', 'social_media', 'call_center']),
|
|
title=f"Action: {random.choice(COMPLAINT_TITLES)}",
|
|
description="Action created to address patient feedback and improve experience.",
|
|
hospital=hospital,
|
|
department=random.choice(hospital.departments.all()) if hospital.departments.exists() else None,
|
|
category=random.choice(['clinical_quality', 'patient_safety', 'service_quality', 'staff_behavior']),
|
|
priority=random.choice(['low', 'medium', 'high', 'urgent']),
|
|
severity=random.choice(['low', 'medium', 'high', 'critical']),
|
|
status=random.choice(['open', 'in_progress', 'pending_approval', 'approved', 'closed']),
|
|
assigned_to=random.choice(users) if random.random() > 0.3 else None,
|
|
)
|
|
actions.append(action)
|
|
print(f" Created {len(actions)} PX actions")
|
|
return actions
|
|
|
|
|
|
def create_journey_instances(journey_templates, patients):
|
|
"""Create journey instances"""
|
|
print("Creating journey instances...")
|
|
from apps.journeys.models import PatientJourneyTemplate
|
|
|
|
templates = PatientJourneyTemplate.objects.filter(is_active=True)
|
|
if not templates.exists():
|
|
print(" No journey templates found, skipping...")
|
|
return []
|
|
|
|
instances = []
|
|
for i in range(20):
|
|
template = random.choice(templates)
|
|
patient = random.choice(patients)
|
|
|
|
instance = PatientJourneyInstance.objects.create(
|
|
journey_template=template,
|
|
patient=patient,
|
|
encounter_id=f"ENC{random.randint(100000, 999999)}",
|
|
hospital=template.hospital,
|
|
status=random.choice(['active', 'completed']),
|
|
)
|
|
|
|
# Create stage instances
|
|
for stage_template in template.stages.all():
|
|
PatientJourneyStageInstance.objects.create(
|
|
journey_instance=instance,
|
|
stage_template=stage_template,
|
|
status=random.choice(['pending', 'completed']),
|
|
)
|
|
|
|
instances.append(instance)
|
|
print(f" Created {len(instances)} journey instances")
|
|
return instances
|
|
|
|
|
|
def create_survey_instances(survey_templates, patients):
|
|
"""Create survey instances"""
|
|
print("Creating survey instances...")
|
|
from apps.surveys.models import SurveyTemplate
|
|
|
|
templates = SurveyTemplate.objects.filter(is_active=True)
|
|
if not templates.exists():
|
|
print(" No survey templates found, skipping...")
|
|
return []
|
|
|
|
instances = []
|
|
for i in range(30):
|
|
template = random.choice(templates)
|
|
patient = random.choice(patients)
|
|
|
|
instance = SurveyInstance.objects.create(
|
|
survey_template=template,
|
|
patient=patient,
|
|
delivery_channel=random.choice(['sms', 'whatsapp', 'email']),
|
|
recipient_phone=patient.phone,
|
|
recipient_email=patient.email,
|
|
status=random.choice(['sent', 'completed']),
|
|
sent_at=timezone.now() - timedelta(days=random.randint(1, 30)),
|
|
)
|
|
|
|
# If completed, add responses
|
|
if instance.status == 'completed':
|
|
instance.completed_at = timezone.now() - timedelta(days=random.randint(0, 29))
|
|
for question in template.questions.all():
|
|
if question.question_type in ['rating', 'likert']:
|
|
SurveyResponse.objects.create(
|
|
survey_instance=instance,
|
|
question=question,
|
|
numeric_value=random.randint(1, 5),
|
|
)
|
|
elif question.question_type == 'nps':
|
|
SurveyResponse.objects.create(
|
|
survey_instance=instance,
|
|
question=question,
|
|
numeric_value=random.randint(0, 10),
|
|
)
|
|
instance.calculate_score()
|
|
instance.save()
|
|
|
|
instances.append(instance)
|
|
print(f" Created {len(instances)} survey instances")
|
|
return instances
|
|
|
|
|
|
def create_call_center_interactions(patients, hospitals, users):
|
|
"""Create call center interactions"""
|
|
print("Creating call center interactions...")
|
|
from apps.callcenter.models import CallCenterInteraction
|
|
|
|
interactions = []
|
|
for i in range(25):
|
|
patient = random.choice(patients)
|
|
hospital = patient.primary_hospital or random.choice(hospitals)
|
|
|
|
interaction = CallCenterInteraction.objects.create(
|
|
patient=patient,
|
|
hospital=hospital,
|
|
agent=random.choice(users) if random.random() > 0.3 else None,
|
|
call_type=random.choice(['inquiry', 'complaint', 'appointment', 'follow_up', 'feedback']),
|
|
subject=f"Call regarding {random.choice(['appointment', 'billing', 'test results', 'medication'])}",
|
|
notes="Patient called with inquiry. Issue resolved during call.",
|
|
satisfaction_rating=random.randint(1, 5),
|
|
wait_time_seconds=random.randint(30, 600),
|
|
call_duration_seconds=random.randint(120, 900),
|
|
resolved=random.choice([True, False]),
|
|
)
|
|
interactions.append(interaction)
|
|
print(f" Created {len(interactions)} call center interactions")
|
|
return interactions
|
|
|
|
|
|
def create_social_mentions(hospitals):
|
|
"""Create social media mentions"""
|
|
print("Creating social media mentions...")
|
|
from apps.social.models import SocialMention
|
|
|
|
mentions = []
|
|
for i in range(15):
|
|
hospital = random.choice(hospitals)
|
|
|
|
mention = SocialMention.objects.create(
|
|
platform=random.choice(['twitter', 'facebook', 'instagram']),
|
|
post_url=f"https://twitter.com/user/status/{random.randint(1000000, 9999999)}",
|
|
post_id=f"POST{random.randint(100000, 999999)}",
|
|
author_username=f"user{random.randint(100, 999)}",
|
|
author_name=f"{random.choice(ENGLISH_FIRST_NAMES_MALE)} {random.choice(ENGLISH_LAST_NAMES)}",
|
|
content=f"Great experience at {hospital.name}! The staff was very professional.",
|
|
hospital=hospital,
|
|
sentiment=random.choice(['positive', 'neutral', 'negative']),
|
|
sentiment_score=random.uniform(-1, 1),
|
|
likes_count=random.randint(0, 100),
|
|
shares_count=random.randint(0, 50),
|
|
comments_count=random.randint(0, 30),
|
|
posted_at=timezone.now() - timedelta(days=random.randint(1, 30)),
|
|
)
|
|
mentions.append(mention)
|
|
print(f" Created {len(mentions)} social media mentions")
|
|
return mentions
|
|
|
|
|
|
def main():
|
|
"""Main data generation function"""
|
|
print("\n" + "="*60)
|
|
print("PX360 - Saudi-Influenced Data Generator")
|
|
print("="*60 + "\n")
|
|
|
|
# Clear existing data first
|
|
clear_existing_data()
|
|
|
|
# Create base data
|
|
hospitals = create_hospitals()
|
|
departments = create_departments(hospitals)
|
|
physicians = create_physicians(hospitals, departments)
|
|
patients = create_patients(hospitals)
|
|
create_users(hospitals)
|
|
|
|
# Get all users for assignments
|
|
users = list(User.objects.all())
|
|
|
|
# Create operational data
|
|
complaints = create_complaints(patients, hospitals, physicians, users)
|
|
feedbacks = create_feedback(patients, hospitals, physicians, users)
|
|
create_survey_templates(hospitals)
|
|
create_journey_templates(hospitals)
|
|
projects = create_qi_projects(hospitals)
|
|
actions = create_px_actions(complaints, hospitals, users)
|
|
journey_instances = create_journey_instances(None, patients)
|
|
survey_instances = create_survey_instances(None, patients)
|
|
call_interactions = create_call_center_interactions(patients, hospitals, users)
|
|
social_mentions = create_social_mentions(hospitals)
|
|
|
|
print("\n" + "="*60)
|
|
print("Data Generation Complete!")
|
|
print("="*60)
|
|
print(f"\nCreated:")
|
|
print(f" - {len(hospitals)} Hospitals")
|
|
print(f" - {len(departments)} Departments")
|
|
print(f" - {len(physicians)} Physicians")
|
|
print(f" - {len(patients)} Patients")
|
|
print(f" - {len(users)} Users")
|
|
print(f" - {len(complaints)} Complaints")
|
|
print(f" - {len(feedbacks)} Feedback Items")
|
|
print(f" - {len(actions)} PX Actions")
|
|
print(f" - {len(journey_instances)} Journey Instances")
|
|
print(f" - {len(survey_instances)} Survey Instances")
|
|
print(f" - {len(call_interactions)} Call Center Interactions")
|
|
print(f" - {len(social_mentions)} Social Media Mentions")
|
|
print(f" - {len(projects)} QI Projects")
|
|
print(f"\nYou can now login with:")
|
|
print(f" Username: px_admin")
|
|
print(f" Password: admin123")
|
|
print(f"\nOr hospital admins:")
|
|
print(f" Username: admin_kfmc (or admin_kfsh, admin_kamc, etc.)")
|
|
print(f" Password: admin123")
|
|
print(f"\nAccess the system at: http://127.0.0.1:8000/")
|
|
print("\n")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|