168 lines
4.7 KiB
Python
168 lines
4.7 KiB
Python
#!/usr/bin/env python
|
|
"""
|
|
Diagnostic script to check chart data generation
|
|
"""
|
|
import os
|
|
import django
|
|
|
|
# Setup Django
|
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.dev')
|
|
django.setup()
|
|
|
|
from django.utils import timezone
|
|
from datetime import timedelta
|
|
from django.db.models import Count, Avg, Q, F, Case, When, IntegerField
|
|
from django.db.models.functions import TruncDate
|
|
from apps.surveys.models import SurveyInstance
|
|
|
|
print("="*70)
|
|
print("CHART DATA DIAGNOSTIC")
|
|
print("="*70)
|
|
|
|
# Get base queryset
|
|
stats_queryset = SurveyInstance.objects.select_related('survey_template')
|
|
|
|
print(f"\nTotal surveys in database: {stats_queryset.count()}")
|
|
print(f"Total completed: {stats_queryset.filter(status='completed').count()}")
|
|
|
|
# 1. Score Distribution
|
|
print("\n" + "="*70)
|
|
print("SCORE DISTRIBUTION")
|
|
print("="*70)
|
|
|
|
completed_surveys = stats_queryset.filter(status='completed', total_score__isnull=False)
|
|
print(f"Completed surveys with scores: {completed_surveys.count()}")
|
|
|
|
score_ranges = [
|
|
('1-2', 1, 2),
|
|
('2-3', 2, 3),
|
|
('3-4', 3, 4),
|
|
('4-5', 4, 5),
|
|
]
|
|
|
|
for label, min_score, max_score in score_ranges:
|
|
if max_score == 5:
|
|
count = completed_surveys.filter(
|
|
total_score__gte=min_score,
|
|
total_score__lte=max_score
|
|
).count()
|
|
else:
|
|
count = completed_surveys.filter(
|
|
total_score__gte=min_score,
|
|
total_score__lt=max_score
|
|
).count()
|
|
print(f"{label}: {count} surveys")
|
|
|
|
# 2. Engagement Funnel
|
|
print("\n" + "="*70)
|
|
print("ENGAGEMENT FUNNEL")
|
|
print("="*70)
|
|
|
|
sent_count = stats_queryset.filter(status__in=['sent', 'pending']).count()
|
|
viewed_count = stats_queryset.filter(status='viewed').count()
|
|
opened_count = stats_queryset.filter(open_count__gt=0).count()
|
|
in_progress_count = stats_queryset.filter(status='in_progress').count()
|
|
completed_count = stats_queryset.filter(status='completed').count()
|
|
|
|
print(f"Sent/Pending: {sent_count}")
|
|
print(f"Viewed: {viewed_count}")
|
|
print(f"Opened: {opened_count}")
|
|
print(f"In Progress: {in_progress_count}")
|
|
print(f"Completed: {completed_count}")
|
|
|
|
# 3. Completion Time Distribution
|
|
print("\n" + "="*70)
|
|
print("COMPLETION TIME DISTRIBUTION")
|
|
print("="*70)
|
|
|
|
completed_with_time = stats_queryset.filter(
|
|
status='completed',
|
|
time_spent_seconds__isnull=False
|
|
)
|
|
print(f"Completed surveys with time data: {completed_with_time.count()}")
|
|
|
|
completion_time_ranges = [
|
|
('< 1 min', 0, 60),
|
|
('1-5 min', 60, 300),
|
|
('5-10 min', 300, 600),
|
|
('10-20 min', 600, 1200),
|
|
('20+ min', 1200, float('inf')),
|
|
]
|
|
|
|
for label, min_seconds, max_seconds in completion_time_ranges:
|
|
if max_seconds == float('inf'):
|
|
count = completed_with_time.filter(time_spent_seconds__gte=min_seconds).count()
|
|
else:
|
|
count = completed_with_time.filter(
|
|
time_spent_seconds__gte=min_seconds,
|
|
time_spent_seconds__lt=max_seconds
|
|
).count()
|
|
print(f"{label}: {count} surveys")
|
|
|
|
# 4. Device Type Distribution
|
|
print("\n" + "="*70)
|
|
print("DEVICE TYPE DISTRIBUTION")
|
|
print("="*70)
|
|
|
|
from apps.surveys.models import SurveyTracking
|
|
|
|
tracking_events = SurveyTracking.objects.filter(
|
|
survey_instance__in=stats_queryset
|
|
).values('device_type').annotate(
|
|
count=Count('id')
|
|
).order_by('-count')
|
|
|
|
total_tracking = tracking_events.count()
|
|
print(f"Total tracking events: {total_tracking}")
|
|
|
|
for entry in tracking_events:
|
|
print(f"{entry['device_type']}: {entry['count']} events")
|
|
|
|
# 5. Survey Trend
|
|
print("\n" + "="*70)
|
|
print("30-DAY TREND")
|
|
print("="*70)
|
|
|
|
thirty_days_ago = timezone.now() - timedelta(days=30)
|
|
|
|
# Try sent_at first
|
|
trend_queryset = stats_queryset.filter(
|
|
sent_at__gte=thirty_days_ago
|
|
)
|
|
|
|
if not trend_queryset.exists():
|
|
print("No surveys with sent_at in last 30 days, trying created_at...")
|
|
trend_queryset = stats_queryset.filter(
|
|
created_at__gte=thirty_days_ago
|
|
).annotate(date=TruncDate('created_at'))
|
|
else:
|
|
trend_queryset = trend_queryset.annotate(date=TruncDate('sent_at'))
|
|
|
|
trend_data = trend_queryset.values('date').annotate(
|
|
sent=Count('id'),
|
|
completed=Count('id', filter=Q(status='completed'))
|
|
).order_by('date')
|
|
|
|
print(f"Days with survey activity: {trend_data.count()}")
|
|
for entry in trend_data[:5]:
|
|
if entry['date']:
|
|
print(f"{entry['date'].strftime('%Y-%m-%d')}: sent={entry['sent']}, completed={entry['completed']}")
|
|
|
|
# 6. Survey Types
|
|
print("\n" + "="*70)
|
|
print("SURVEY TYPE DISTRIBUTION")
|
|
print("="*70)
|
|
|
|
survey_type_data = stats_queryset.values(
|
|
'survey_template__survey_type'
|
|
).annotate(
|
|
count=Count('id')
|
|
).order_by('-count')
|
|
|
|
for entry in survey_type_data:
|
|
print(f"{entry['survey_template__survey_type']}: {entry['count']} surveys")
|
|
|
|
print("\n" + "="*70)
|
|
print("DIAGNOSTIC COMPLETE")
|
|
print("="*70)
|