feat: enhance appointment statistics with percentage calculations for better insights #69
@ -291,7 +291,7 @@ class UserAppointmentsView(generics.ListAPIView):
|
|||||||
|
|
||||||
class AppointmentStatsView(generics.GenericAPIView):
|
class AppointmentStatsView(generics.GenericAPIView):
|
||||||
permission_classes = [IsAuthenticated, IsAdminUser]
|
permission_classes = [IsAuthenticated, IsAdminUser]
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
total = AppointmentRequest.objects.count()
|
total = AppointmentRequest.objects.count()
|
||||||
users = CustomUser.objects.filter(is_staff=False).count()
|
users = CustomUser.objects.filter(is_staff=False).count()
|
||||||
@ -308,26 +308,39 @@ class AppointmentStatsView(generics.GenericAPIView):
|
|||||||
|
|
||||||
availability = get_admin_availability()
|
availability = get_admin_availability()
|
||||||
availability_coverage = 0
|
availability_coverage = 0
|
||||||
|
available_days_count = 0
|
||||||
if availability and availability.availability_schedule:
|
if availability and availability.availability_schedule:
|
||||||
days_with_availability = len(availability.availability_schedule)
|
available_days_count = len(availability.availability_schedule)
|
||||||
availability_coverage = round((days_with_availability / 7) * 100, 2)
|
availability_coverage = round((available_days_count / 7) * 100, 2)
|
||||||
|
|
||||||
|
def pct(count):
|
||||||
|
return round((count / total * 100), 2) if total > 0 else 0
|
||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
'total_requests': total,
|
'total_requests': total,
|
||||||
'pending_review': pending,
|
|
||||||
'scheduled': scheduled,
|
|
||||||
'rejected': rejected,
|
|
||||||
'completed': completed,
|
|
||||||
'users': users,
|
'users': users,
|
||||||
'completion_rate': round((scheduled / total * 100), 2) if total > 0 else 0,
|
'users_pct': pct(users),
|
||||||
'availability_coverage': availability_coverage,
|
'pending_review': pending,
|
||||||
'available_days_count': days_with_availability if availability else 0,
|
'pending_review_pct': pct(pending),
|
||||||
|
|
||||||
|
'scheduled': scheduled,
|
||||||
|
'scheduled_pct': pct(scheduled),
|
||||||
|
|
||||||
|
'rejected': rejected,
|
||||||
|
'rejected_pct': pct(rejected),
|
||||||
|
|
||||||
|
'completed': completed,
|
||||||
|
'completed_pct': pct(completed),
|
||||||
|
|
||||||
'jitsi_meetings_created': jitsi_meetings,
|
'jitsi_meetings_created': jitsi_meetings,
|
||||||
|
'meetings_with_video_pct': pct(jitsi_meetings),
|
||||||
|
|
||||||
'active_upcoming_meetings': active_meetings,
|
'active_upcoming_meetings': active_meetings,
|
||||||
'meetings_with_video': round((jitsi_meetings / total * 100), 2) if total > 0 else 0,
|
|
||||||
|
'available_days_count': available_days_count,
|
||||||
|
'availability_coverage_pct': availability_coverage,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class UserAppointmentStatsView(generics.GenericAPIView):
|
class UserAppointmentStatsView(generics.GenericAPIView):
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
serializer_class = AppointmentDetailSerializer
|
serializer_class = AppointmentDetailSerializer
|
||||||
@ -359,25 +372,27 @@ class UserAppointmentStatsView(generics.GenericAPIView):
|
|||||||
}
|
}
|
||||||
|
|
||||||
total = stats['total']
|
total = stats['total']
|
||||||
|
pending = stats['pending']
|
||||||
|
completed = stats['completed']
|
||||||
scheduled = stats['scheduled']
|
scheduled = stats['scheduled']
|
||||||
completion_rate = round((scheduled / total * 100), 2) if total > 0 else 0
|
|
||||||
|
pending_pct = round((pending / total * 100), 2) if total > 0 else 0
|
||||||
|
completed_pct = round((completed / total * 100), 2) if total > 0 else 0
|
||||||
|
scheduled_pct = round((scheduled / total * 100), 2) if total > 0 else 0
|
||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
'total_requests': total,
|
'total_requests': total,
|
||||||
'pending_review': stats['pending'],
|
'pending_review': pending,
|
||||||
|
'pending_review_pct': pending_pct,
|
||||||
'scheduled': scheduled,
|
'scheduled': scheduled,
|
||||||
|
'scheduled_pct': scheduled_pct,
|
||||||
'rejected': stats['rejected'],
|
'rejected': stats['rejected'],
|
||||||
'completed': stats['completed'],
|
'completed': completed,
|
||||||
|
'completed_pct': completed_pct,
|
||||||
|
'completion_rate': round((scheduled / total * 100), 2) if total > 0 else 0,
|
||||||
'video_meetings': stats['video_meetings'],
|
'video_meetings': stats['video_meetings'],
|
||||||
'completion_rate': completion_rate,
|
|
||||||
'email': request.user.email,
|
|
||||||
'upcoming_video_sessions': queryset.filter(
|
|
||||||
status='scheduled',
|
|
||||||
jitsi_meeting_created=True,
|
|
||||||
scheduled_datetime__gt=timezone.now()
|
|
||||||
).count(),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
class MatchingAvailabilityView(generics.GenericAPIView):
|
class MatchingAvailabilityView(generics.GenericAPIView):
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user