212 lines
7.1 KiB
Python
212 lines
7.1 KiB
Python
#!/usr/bin/env python
|
|
"""
|
|
Generate comprehensive test data for survey charts
|
|
Creates surveys with various scores, statuses, and completion times
|
|
"""
|
|
import os
|
|
import django
|
|
import random
|
|
from datetime import timedelta
|
|
|
|
# Setup Django
|
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.dev')
|
|
django.setup()
|
|
|
|
from django.utils import timezone
|
|
from apps.surveys.models import SurveyInstance, SurveyTemplate
|
|
from apps.organizations.models import Hospital, Patient
|
|
|
|
print("="*70)
|
|
print("GENERATING SURVEY CHART TEST DATA")
|
|
print("="*70)
|
|
|
|
# Get existing resources
|
|
hospital = Hospital.objects.first()
|
|
if not hospital:
|
|
hospital = Hospital.objects.create(
|
|
name='Test Hospital',
|
|
name_ar='مستشفى تجريبي',
|
|
code='TEST'
|
|
)
|
|
|
|
# Get or create template
|
|
template = SurveyTemplate.objects.first()
|
|
if not template:
|
|
template = SurveyTemplate.objects.create(
|
|
name='Patient Satisfaction Survey',
|
|
name_ar='استبيان رضا المرضى',
|
|
hospital=hospital,
|
|
survey_type='general',
|
|
scoring_method='average',
|
|
negative_threshold=3.0,
|
|
is_active=True
|
|
)
|
|
|
|
# Get or create patients
|
|
patients = []
|
|
for i in range(1, 20):
|
|
patient, _ = Patient.objects.get_or_create(
|
|
mrn=f'TEST{i:03d}',
|
|
defaults={
|
|
'first_name': f'Test',
|
|
'last_name': f'Patient{i}',
|
|
'primary_hospital': hospital
|
|
}
|
|
)
|
|
patients.append(patient)
|
|
|
|
# Generate survey instances
|
|
surveys_to_create = [
|
|
# Completed surveys with different scores
|
|
{'status': 'completed', 'score': 5.0, 'time': 120},
|
|
{'status': 'completed', 'score': 4.8, 'time': 180},
|
|
{'status': 'completed', 'score': 4.5, 'time': 240},
|
|
{'status': 'completed', 'score': 4.2, 'time': 300},
|
|
{'status': 'completed', 'score': 4.0, 'time': 150},
|
|
{'status': 'completed', 'score': 3.8, 'time': 210},
|
|
{'status': 'completed', 'score': 3.5, 'time': 270},
|
|
{'status': 'completed', 'score': 3.2, 'time': 330},
|
|
{'status': 'completed', 'score': 3.0, 'time': 390},
|
|
{'status': 'completed', 'score': 2.8, 'time': 450},
|
|
{'status': 'completed', 'score': 2.5, 'time': 510},
|
|
{'status': 'completed', 'score': 2.2, 'time': 570},
|
|
{'status': 'completed', 'score': 2.0, 'time': 630},
|
|
{'status': 'completed', 'score': 1.8, 'time': 690},
|
|
{'status': 'completed', 'score': 1.5, 'time': 750},
|
|
{'status': 'completed', 'score': 1.2, 'time': 810},
|
|
{'status': 'completed', 'score': 1.0, 'time': 870},
|
|
|
|
# Very short completion times
|
|
{'status': 'completed', 'score': 4.0, 'time': 30},
|
|
{'status': 'completed', 'score': 3.5, 'time': 45},
|
|
{'status': 'completed', 'score': 3.0, 'time': 50},
|
|
|
|
# Very long completion times
|
|
{'status': 'completed', 'score': 2.5, 'time': 1500},
|
|
{'status': 'completed', 'score': 2.0, 'time': 2000},
|
|
{'status': 'completed', 'score': 3.0, 'time': 2500},
|
|
|
|
# Sent surveys
|
|
{'status': 'sent', 'score': None, 'time': None},
|
|
{'status': 'sent', 'score': None, 'time': None},
|
|
{'status': 'sent', 'score': None, 'time': None},
|
|
|
|
# Pending surveys
|
|
{'status': 'pending', 'score': None, 'time': None},
|
|
{'status': 'pending', 'score': None, 'time': None},
|
|
{'status': 'pending', 'score': None, 'time': None},
|
|
|
|
# Viewed surveys
|
|
{'status': 'viewed', 'score': None, 'time': None},
|
|
{'status': 'viewed', 'score': None, 'time': None},
|
|
|
|
# Opened surveys (with open_count > 0)
|
|
{'status': 'sent', 'score': None, 'time': None, 'opened': True},
|
|
{'status': 'sent', 'score': None, 'time': None, 'opened': True},
|
|
{'status': 'sent', 'score': None, 'time': None, 'opened': True},
|
|
|
|
# In progress
|
|
{'status': 'in_progress', 'score': None, 'time': None},
|
|
{'status': 'in_progress', 'score': None, 'time': None},
|
|
{'status': 'in_progress', 'score': None, 'time': None},
|
|
|
|
# Abandoned
|
|
{'status': 'abandoned', 'score': None, 'time': None},
|
|
{'status': 'abandoned', 'score': None, 'time': None},
|
|
]
|
|
|
|
# Create surveys
|
|
now = timezone.now()
|
|
created_count = 0
|
|
|
|
for i, survey_data in enumerate(surveys_to_create):
|
|
patient = patients[i % len(patients)]
|
|
|
|
# Calculate sent_at to spread over last 30 days
|
|
days_ago = random.randint(0, 30)
|
|
sent_at = now - timedelta(days=days_ago)
|
|
|
|
survey = SurveyInstance.objects.create(
|
|
survey_template=template,
|
|
patient=patient,
|
|
hospital=hospital,
|
|
status=survey_data['status'],
|
|
total_score=survey_data['score'],
|
|
sent_at=sent_at,
|
|
time_spent_seconds=survey_data['time'],
|
|
open_count=random.randint(0, 3) if survey_data.get('opened') else 0,
|
|
)
|
|
|
|
# Set timestamps based on status
|
|
if survey_data['status'] == 'viewed':
|
|
survey.viewed_at = sent_at + timedelta(minutes=5)
|
|
elif survey_data['status'] == 'completed':
|
|
survey.opened_at = sent_at + timedelta(minutes=random.randint(1, 10))
|
|
survey.viewed_at = survey.opened_at + timedelta(minutes=1)
|
|
survey.completed_at = survey.opened_at + timedelta(seconds=survey_data['time'] or 60)
|
|
elif survey_data['status'] == 'abandoned':
|
|
survey.opened_at = sent_at + timedelta(minutes=random.randint(1, 10))
|
|
survey.viewed_at = survey.opened_at + timedelta(minutes=1)
|
|
|
|
survey.save()
|
|
created_count += 1
|
|
|
|
if i < 5: # Show first few
|
|
print(f" ✓ Created survey {i+1}: {survey_data['status']}, score={survey_data['score']}")
|
|
|
|
print(f"\n✓ Created {created_count} survey instances")
|
|
|
|
# Show statistics
|
|
print("\n" + "="*70)
|
|
print("SURVEY STATISTICS")
|
|
print("="*70)
|
|
|
|
total = SurveyInstance.objects.count()
|
|
completed = SurveyInstance.objects.filter(status='completed').count()
|
|
sent = SurveyInstance.objects.filter(status__in=['sent', 'pending']).count()
|
|
viewed = SurveyInstance.objects.filter(status='viewed').count()
|
|
opened = SurveyInstance.objects.filter(open_count__gt=0).count()
|
|
in_progress = SurveyInstance.objects.filter(status='in_progress').count()
|
|
abandoned = SurveyInstance.objects.filter(status='abandoned').count()
|
|
|
|
print(f"Total surveys: {total}")
|
|
print(f"Completed: {completed}")
|
|
print(f"Sent/Pending: {sent}")
|
|
print(f"Viewed: {viewed}")
|
|
print(f"Opened: {opened}")
|
|
print(f"In Progress: {in_progress}")
|
|
print(f"Abandoned: {abandoned}")
|
|
|
|
# Score distribution
|
|
print("\n" + "="*70)
|
|
print("SCORE DISTRIBUTION")
|
|
print("="*70)
|
|
|
|
completed_with_scores = SurveyInstance.objects.filter(status='completed', total_score__isnull=False)
|
|
ranges = [
|
|
('1-2', 1, 2),
|
|
('2-3', 2, 3),
|
|
('3-4', 3, 4),
|
|
('4-5', 4, 5),
|
|
]
|
|
|
|
for label, min_score, max_score in ranges:
|
|
if max_score == 5:
|
|
count = completed_with_scores.filter(
|
|
total_score__gte=min_score,
|
|
total_score__lte=max_score
|
|
).count()
|
|
else:
|
|
count = completed_with_scores.filter(
|
|
total_score__gte=min_score,
|
|
total_score__lt=max_score
|
|
).count()
|
|
percentage = round((count / completed * 100) if completed > 0 else 0, 1)
|
|
print(f"{label}: {count} surveys ({percentage}%)")
|
|
|
|
print("\n" + "="*70)
|
|
print("✓ TEST DATA GENERATION COMPLETE!")
|
|
print("="*70)
|
|
print("\nNow visit: http://localhost:8000/surveys/instances/")
|
|
print("All charts should display data properly!\n")
|