""" Analytics Console UI views """ from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator from django.db.models import Avg, Count from django.shortcuts import render from apps.complaints.models import Complaint from apps.organizations.models import Department, Hospital from apps.px_action_center.models import PXAction from apps.surveys.models import SurveyInstance from .models import KPI, KPIValue @login_required def analytics_dashboard(request): """ Analytics dashboard with KPIs and charts. Features: - KPI cards with current values - Trend charts - Department rankings - Physician rankings """ user = request.user # Get hospital filter hospital_filter = request.GET.get('hospital') if hospital_filter: hospital = Hospital.objects.filter(id=hospital_filter).first() elif user.hospital: hospital = user.hospital else: hospital = None # Calculate key metrics complaints_queryset = Complaint.objects.all() actions_queryset = PXAction.objects.all() surveys_queryset = SurveyInstance.objects.filter(status='completed') if hospital: complaints_queryset = complaints_queryset.filter(hospital=hospital) actions_queryset = actions_queryset.filter(hospital=hospital) surveys_queryset = surveys_queryset.filter(survey_template__hospital=hospital) # KPI calculations kpis = { 'total_complaints': complaints_queryset.count(), 'open_complaints': complaints_queryset.filter(status='open').count(), 'overdue_complaints': complaints_queryset.filter(is_overdue=True).count(), 'total_actions': actions_queryset.count(), 'open_actions': actions_queryset.filter(status='open').count(), 'overdue_actions': actions_queryset.filter(is_overdue=True).count(), 'avg_survey_score': surveys_queryset.aggregate(avg=Avg('total_score'))['avg'] or 0, 'negative_surveys': surveys_queryset.filter(is_negative=True).count(), } # Department rankings (top 5 by survey score) department_rankings = Department.objects.filter( status='active' ).annotate( avg_score=Avg('journey_stages__survey_instance__total_score'), survey_count=Count('journey_stages__survey_instance') ).filter( survey_count__gt=0 ).order_by('-avg_score')[:5] # Get hospitals for filter hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) context = { 'kpis': kpis, 'department_rankings': department_rankings, 'hospitals': hospitals, 'selected_hospital': hospital, } return render(request, 'analytics/dashboard.html', context) @login_required def kpi_list(request): """KPI definitions list view""" queryset = KPI.objects.all() # Apply filters category_filter = request.GET.get('category') if category_filter: queryset = queryset.filter(category=category_filter) is_active = request.GET.get('is_active') if is_active == 'true': queryset = queryset.filter(is_active=True) elif is_active == 'false': queryset = queryset.filter(is_active=False) # Ordering queryset = queryset.order_by('category', 'name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) context = { 'page_obj': page_obj, 'kpis': page_obj.object_list, 'filters': request.GET, } return render(request, 'analytics/kpi_list.html', context)