from decimal import Decimal from django.test import TestCase from django.contrib.auth import get_user_model from rest_framework.test import APIClient from rest_framework import status from apps.profiles.models import Institution from apps.projects.models import Project from apps.lms.models import Course, CourseCategory, CourseLevel, CourseLanguage from apps.tickets.models import Ticket, TicketCategory, TicketPriority, TicketStatus from apps.donations.models import DonationCampaign, CampaignCategory, CampaignPriority from apps.diplomacy.models import RepresentativeReport, ReportStatus User = get_user_model() class Phase9AnalyticsAPITests(TestCase): """ Automated test suite for Phase 9: Executive Analytics Dashboard - Multi-Module Real-Time Aggregated Metrics - Breakdown by Institution Type, Project Status, LMS Stats, Ticketing & Donations """ def setUp(self): self.client = APIClient() self.user = User.objects.create_user( email="analytics.viewer@astan.org", password="Password123!", fullname="Executive Observer", ) # Seed data self.inst = Institution.objects.create( name="Mashhad Razavi Center", country="Iran", city="Mashhad", type=Institution.InstitutionType.CULTURAL_CENTER, verification_status=Institution.VerificationStatus.APPROVED, ) self.proj = Project.objects.create( title="Global Interfaith Forum", owner_institution=self.inst, status=Project.Status.ACTIVE, ) self.course = Course.objects.create( title="Diplomacy 101", category=CourseCategory.CULTURAL_DIPLOMACY, language=CourseLanguage.EN, level=CourseLevel.INTRODUCTORY, instructor_name="Prof. Seyed", description="Introduction to diplomacy.", is_published=True, ) self.ticket = Ticket.objects.create( user=self.user, subject="Assistance with registration", category=TicketCategory.GENERAL, status=TicketStatus.CLOSED, satisfaction_rating=5, ) self.campaign = DonationCampaign.objects.create( title="Winter Relief", description="Relief campaign", target_amount=Decimal('10000.00'), raised_amount=Decimal('4500.00'), category=CampaignCategory.HUMANITARIAN_RELIEF, priority=CampaignPriority.HIGH, is_active=True, ) self.report = RepresentativeReport.objects.create( representative=self.user, title="Monthly Report", region_hub="Europe", period="Feb 2026", activities_summary="Activities summary", centers_visited_count=6, status=ReportStatus.APPROVED, ) def test_executive_dashboard_kpis(self): response = self.client.get("/api/v1/analytics/dashboard/") self.assertEqual(response.status_code, status.HTTP_200_OK) # 1. Institutions self.assertEqual(response.data["institutions"]["total_institutions"], 1) self.assertEqual(response.data["institutions"]["verified_institutions"], 1) self.assertEqual(response.data["institutions"]["countries_count"], 1) # 2. Projects self.assertEqual(response.data["projects"]["total_projects"], 1) self.assertEqual(response.data["projects"]["active_projects"], 1) # 3. LMS self.assertEqual(response.data["lms"]["total_courses"], 1) # 4. Ticketing self.assertEqual(response.data["ticketing"]["total_tickets"], 1) self.assertEqual(response.data["ticketing"]["average_satisfaction_rating"], 5.0) # 5. Donations self.assertEqual(response.data["donations"]["active_campaigns_count"], 1) self.assertEqual(response.data["donations"]["total_funds_raised_usd"], 4500.0) # 6. Diplomacy self.assertEqual(response.data["diplomacy"]["total_reports_submitted"], 1) self.assertEqual(response.data["diplomacy"]["approved_reports_count"], 1) self.assertEqual(response.data["diplomacy"]["total_centers_visited"], 6)