Browse Source

more data stats added for the dashboard stats

top blogs , top students , professional charts and more card data
master
Mohsen Taba 2 months ago
parent
commit
7cc52e97cd
  1. 132
      apps/api/views/admin_dashboard.py

132
apps/api/views/admin_dashboard.py

@ -3,13 +3,16 @@ from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser from rest_framework.permissions import IsAuthenticated, IsAdminUser
from django.utils import timezone from django.utils import timezone
from datetime import timedelta from datetime import timedelta
from django.db.models import Count
from django.db.models import Count, Sum
from django.db.models.functions import TruncDate
from apps.account.models import User
from apps.course.models import Course, Participant
from apps.account.models import User, LoginHistory
from apps.course.models import Course, Participant, CourseLiveSession
from apps.quiz.models import QuizParticipant
from apps.blog.models import Blog from apps.blog.models import Blog
from apps.chat.models import ChatMessage, RoomMessage
from apps.transaction.models import TransactionParticipant
from apps.certificate.models import Certificate from apps.certificate.models import Certificate
# Import your Transaction model here
class AdminDashboardStatsView(APIView): class AdminDashboardStatsView(APIView):
permission_classes = [IsAuthenticated, IsAdminUser] permission_classes = [IsAuthenticated, IsAdminUser]
@ -18,37 +21,107 @@ class AdminDashboardStatsView(APIView):
now = timezone.now() now = timezone.now()
thirty_days_ago = now - timedelta(days=30) thirty_days_ago = now - timedelta(days=30)
# 1. Basic Counts
# ---------------------------------------------------------
# 1. CARDS & BASIC STATS
# ---------------------------------------------------------
active_students = User.objects.filter(groups__name="Student Group", is_active=True).count() active_students = User.objects.filter(groups__name="Student Group", is_active=True).count()
professors = User.objects.filter(groups__name="Professor Group", is_active=True).count() professors = User.objects.filter(groups__name="Professor Group", is_active=True).count()
active_courses = Course.objects.filter(status=Course.StatusChoices.ONGOING).count() active_courses = Course.objects.filter(status=Course.StatusChoices.ONGOING).count()
total_blogs = Blog.objects.count() total_blogs = Blog.objects.count()
pending_certificates = Certificate.objects.filter(status='pending').count() pending_certificates = Certificate.objects.filter(status='pending').count()
active_live_sessions = CourseLiveSession.objects.filter(ended_at__isnull=True).count()
# 2. Revenue (Mocked - replace with your actual Transaction logic)
# revenue_30d = Transaction.objects.filter(status='success', created_at__gte=thirty_days_ago).aggregate(Sum('amount'))['amount__sum'] or 0
# Revenue (Mocked for 30d sum)
revenue_30d = 12500.00 # Dummy data revenue_30d = 12500.00 # Dummy data
# 3. Transaction Chart Data (Mocked - replace with actual grouped query)
transactions_data = [
{"name": "Success", "value": 450, "fill": "var(--color-success)"},
{"name": "Pending", "value": 85, "fill": "var(--color-pending)"},
{"name": "Waiting", "value": 40, "fill": "var(--color-waiting)"},
{"name": "Failed", "value": 25, "fill": "var(--color-failed)"},
# Private vs Group Chat Usage
chat_types = RoomMessage.objects.values('room_type').annotate(count=Count('id'))
chat_type_stats = {item['room_type']: item['count'] for item in chat_types}
# ---------------------------------------------------------
# 2. CHARTS DATA
# ---------------------------------------------------------
# Payment Methods (Pie Chart)
payment_methods = TransactionParticipant.objects.values('payment_method').annotate(total=Count('id'))
payment_method_chart = [
{"name": item['payment_method'], "value": item['total']}
for item in payment_methods
]
# Transaction Status (Donut Chart)
transaction_status = TransactionParticipant.objects.values('status').annotate(total=Count('id'))
transaction_chart = [
{"name": item['status'], "value": item['total']}
for item in transaction_status
] ]
# 4. Top 5 Popular Courses
top_courses = Course.objects.annotate(
participant_count=Count('participants')
).order_by('-participant_count')[:5]
# Global Student Distribution (Bar Chart)
top_countries = LoginHistory.objects.exclude(country__isnull=True).exclude(country="").values('country').annotate(
count=Count('id')
).order_by('-count')[:5]
country_chart = [{"country": item['country'], "students": item['count']} for item in top_countries]
# New User Registrations Trend (Line Chart)
registrations = User.objects.filter(date_joined__gte=thirty_days_ago).annotate(
date=TruncDate('date_joined')
).values('date').annotate(count=Count('id')).order_by('date')
registration_chart = [{"date": item['date'].strftime('%Y-%m-%d'), "users": item['count']} for item in registrations]
# Community Chat Volume Trend (Area Chart)
chat_volume = ChatMessage.objects.filter(sent_at__gte=thirty_days_ago).annotate(
date=TruncDate('sent_at')
).values('date').annotate(count=Count('id')).order_by('date')
chat_chart = [{"date": item['date'].strftime('%Y-%m-%d'), "messages": item['count']} for item in chat_volume]
# Course Pipeline (Stacked Bar)
course_statuses = Course.objects.values('status').annotate(count=Count('id'))
course_pipeline = {"name": "Courses"}
for status in course_statuses:
course_pipeline[status['status']] = status['count']
top_courses_data = [
# Course Efficacy: Completed vs Enrolled (Bar Chart)
# We take the top 5 courses, check how many users are enrolled, and how many have at least 1 completed lesson
top_courses_qs = Course.objects.annotate(participant_count=Count('participants')).order_by('-participant_count')[:5]
course_efficacy = []
for course in top_courses_qs:
enrolled = course.participant_count
completed = Participant.objects.filter(
course=course,
student__lesson_completions__course_lesson__course=course
).distinct().count()
course_efficacy.append({
"title": course.title[:20] + "..." if len(course.title) > 20 else course.title,
"enrolled": enrolled,
"completed": completed
})
# ---------------------------------------------------------
# 3. LISTS & LEADERBOARDS
# ---------------------------------------------------------
# Top 5 Courses (List)
top_courses_list = [
{ {
"id": c.id, "id": c.id,
"title": c.title, "title": c.title,
"professor": c.professor.fullname if c.professor else "Unknown", "professor": c.professor.fullname if c.professor else "Unknown",
"participants": c.participant_count "participants": c.participant_count
} for c in top_courses
} for c in top_courses_qs
]
# Top 5 Blogs (List)
top_blogs = Blog.objects.order_by('-views_count')[:5]
top_blogs_list = [
{"id": b.id, "title": b._extract_text_from_json(b.title), "views": b.views_count}
for b in top_blogs
]
# Top Performing Students (Leaderboard)
top_students = QuizParticipant.objects.select_related('user').order_by('-total_score', 'total_timing')[:5]
leaderboard = [
{"id": s.user.id, "name": s.user.fullname, "score": s.total_score, "time": s.total_timing}
for s in top_students
] ]
return Response({ return Response({
@ -58,8 +131,23 @@ class AdminDashboardStatsView(APIView):
"active_courses": active_courses, "active_courses": active_courses,
"total_blogs": total_blogs, "total_blogs": total_blogs,
"revenue_30d": revenue_30d, "revenue_30d": revenue_30d,
"pending_certificates": pending_certificates
"pending_certificates": pending_certificates,
"active_live_sessions": active_live_sessions,
"group_rooms": chat_type_stats.get('group', 0),
"private_rooms": chat_type_stats.get('private', 0),
},
"charts": {
"transactions_status": transaction_chart,
"payment_methods": payment_method_chart,
"countries": country_chart,
"registrations": registration_chart,
"chat_volume": chat_chart,
"course_pipeline": [course_pipeline],
"course_efficacy": course_efficacy
}, },
"transactions_chart": transactions_data,
"top_courses": top_courses_data
"lists": {
"top_courses": top_courses_list,
"top_blogs": top_blogs_list,
"leaderboard": leaderboard
}
}) })
Loading…
Cancel
Save