from django.db.models import Count, Q from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated from rest_framework.request import Request from rest_framework.response import Response from .models import JobApplication, JobUpdate from .serializers import ( DashboardMetricsSerializer, JobApplicationSerializer, JobUpdateSerializer, ) class JobApplicationViewSet(viewsets.ModelViewSet): serializer_class = JobApplicationSerializer permission_classes = [IsAuthenticated] def get_queryset(self): """Filter by user for non-admin users; admins see all.""" user = self.request.user qs = JobApplication.objects.all().prefetch_related("updates") if not user.is_admin: qs = qs.filter(user=user) return qs class JobUpdateViewSet(viewsets.ModelViewSet): serializer_class = JobUpdateSerializer permission_classes = [IsAuthenticated] def get_queryset(self): """Filter by user via job_application for non-admin users.""" user = self.request.user qs = JobUpdate.objects.select_related("job_application").all() if not user.is_admin: qs = qs.filter(job_application__user=user) return qs @action(detail=False, methods=["get"]) def latest(self, request: Request) -> Response: """Return the 3 most recent job updates with job info and metrics.""" updates = ( self.get_queryset() .select_related("job_application") .order_by("-created_at")[:3] ) serializer = self.get_serializer(updates, many=True) return Response(serializer.data) @action(detail=False, methods=["get"]) def metrics(self, request: Request) -> Response: """Return dashboard metrics: total apps, status breakdown, interview/offer counts.""" qs = self.get_queryset() total = qs.values("job_application").distinct().count() # Get status counts from the distinct job applications the user owns app_qs = JobApplication.objects.all() if not request.user.is_admin: app_qs = app_qs.filter(user=request.user) total = app_qs.count() status_counts = dict( app_qs.values("status") .annotate(count=Count("id")) .values_list("status", "count") ) interview_count = app_qs.filter( Q(status="INTERVIEW") | Q(status="OFFER") ).count() offer_count = app_qs.filter(status="OFFER").count() rejection_rate = ( round( status_counts.get("REJECTED", 0) / total * 100, 1 ) if total > 0 else 0.0 ) serializer = DashboardMetricsSerializer( instance={ "total_applications": total, "status_breakdown": status_counts, "interviews_count": interview_count, "offers_count": offer_count, "rejection_rate": rejection_rate, } ) return Response(serializer.data)