Files
job-tracker/api/jobs/views.py

90 lines
3.1 KiB
Python

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)