You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
5.6 KiB
151 lines
5.6 KiB
from rest_framework import generics, permissions
|
|
from rest_framework.viewsets import ModelViewSet
|
|
from rest_framework.authentication import TokenAuthentication
|
|
from drf_yasg.utils import swagger_auto_schema
|
|
from drf_yasg import openapi
|
|
from django.db.models import Q
|
|
|
|
from apps.certificate.models import Certificate
|
|
from apps.certificate.serializers import AdminCertificateSerializer, CertificateRequestSerializer, CertificateSerializer
|
|
from apps.account.permissions import IsSuperAdmin
|
|
from apps.course.models import Course
|
|
from apps.course.models.course import extract_text_from_json
|
|
from utils.pagination import StandardResultsSetPagination
|
|
|
|
|
|
def find_matching_course_ids(search_term: str):
|
|
normalized = (search_term or "").strip().lower()
|
|
if not normalized:
|
|
return []
|
|
|
|
matching_ids = list(
|
|
Course.objects.filter(
|
|
Q(title__icontains=search_term) | Q(slug__icontains=search_term)
|
|
).values_list("id", flat=True)
|
|
)
|
|
|
|
if matching_ids:
|
|
return matching_ids
|
|
|
|
for course in Course.objects.all().only("id", "title", "slug"):
|
|
title_text = extract_text_from_json(course.title).lower()
|
|
slug_text = extract_text_from_json(course.slug).lower()
|
|
if normalized in title_text or normalized in slug_text:
|
|
matching_ids.append(course.id)
|
|
|
|
return matching_ids
|
|
|
|
|
|
|
|
class CertificateRequestView(generics.CreateAPIView):
|
|
queryset = Certificate.objects.all()
|
|
serializer_class = CertificateRequestSerializer
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
authentication_classes = [TokenAuthentication]
|
|
|
|
@swagger_auto_schema(
|
|
operation_description="Request a certificate for completed course",
|
|
tags=["Imam-Javad - Certificate"],
|
|
responses={
|
|
201: openapi.Response(
|
|
description="Certificate request created successfully"
|
|
)
|
|
}
|
|
)
|
|
def post(self, request, *args, **kwargs):
|
|
return super().post(request, *args, **kwargs)
|
|
|
|
def perform_create(self, serializer):
|
|
serializer.save(student=self.request.user)
|
|
|
|
|
|
class UserCertificatesListView(generics.ListAPIView):
|
|
serializer_class = CertificateSerializer
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
authentication_classes = [TokenAuthentication]
|
|
pagination_class = StandardResultsSetPagination
|
|
|
|
@swagger_auto_schema(
|
|
operation_description="Get list of user's certificates",
|
|
tags=["Imam-Javad - Certificate"],
|
|
responses={
|
|
200: openapi.Response(
|
|
description="List of user certificates",
|
|
schema=CertificateSerializer(many=True)
|
|
)
|
|
}
|
|
)
|
|
def get(self, request, *args, **kwargs):
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def get_queryset(self):
|
|
return Certificate.objects.filter(student=self.request.user).order_by('-created_at')
|
|
|
|
|
|
def is_professor(request):
|
|
return getattr(request.user, 'user_type', None) == 'professor'
|
|
|
|
|
|
class AdminCertificateViewSet(ModelViewSet):
|
|
queryset = Certificate.objects.all()
|
|
serializer_class = AdminCertificateSerializer
|
|
permission_classes = [permissions.IsAuthenticated, IsSuperAdmin]
|
|
authentication_classes = [TokenAuthentication]
|
|
pagination_class = StandardResultsSetPagination
|
|
|
|
def get_queryset(self):
|
|
queryset = Certificate.objects.all().select_related('student', 'course')
|
|
|
|
# Professors can only see certificates for students in their courses
|
|
if is_professor(self.request):
|
|
queryset = queryset.filter(course__professor_id=self.request.user.id)
|
|
|
|
# Search query
|
|
search_query = self.request.query_params.get('search', None)
|
|
has_search = False
|
|
if search_query:
|
|
has_search = True
|
|
matching_course_ids = find_matching_course_ids(search_query)
|
|
from django.db.models import Case, When, Value, IntegerField
|
|
queryset = queryset.filter(
|
|
Q(student__fullname__icontains=search_query) |
|
|
Q(student__email__icontains=search_query) |
|
|
Q(course_id__in=matching_course_ids)
|
|
).annotate(
|
|
search_relevance=Case(
|
|
When(student__fullname__icontains=search_query, then=Value(3)),
|
|
When(student__email__icontains=search_query, then=Value(2)),
|
|
When(course_id__in=matching_course_ids, then=Value(1)),
|
|
default=Value(0),
|
|
output_field=IntegerField()
|
|
)
|
|
)
|
|
|
|
# Filters
|
|
status_param = self.request.query_params.get('status', None)
|
|
if status_param:
|
|
queryset = queryset.filter(status=status_param)
|
|
|
|
course_id = self.request.query_params.get('course', None)
|
|
if course_id:
|
|
queryset = queryset.filter(course_id=course_id)
|
|
|
|
student_id = self.request.query_params.get('student', None)
|
|
if student_id:
|
|
queryset = queryset.filter(student_id=student_id)
|
|
|
|
issued_date = self.request.query_params.get('issued_date', None)
|
|
if issued_date:
|
|
queryset = queryset.filter(created_at__date=issued_date)
|
|
|
|
issued_after = self.request.query_params.get('issued_after', None)
|
|
if issued_after:
|
|
queryset = queryset.filter(created_at__date__gte=issued_after)
|
|
|
|
issued_before = self.request.query_params.get('issued_before', None)
|
|
if issued_before:
|
|
queryset = queryset.filter(created_at__date__lte=issued_before)
|
|
|
|
if has_search:
|
|
return queryset.order_by('-search_relevance', '-created_at')
|
|
return queryset.order_by('-created_at')
|