from typing import Any, Dict, Tuple from django.db.models import Prefetch from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page from rest_framework.decorators import (api_view, permission_classes, throttle_classes) from rest_framework.mixins import (CreateModelMixin, ListModelMixin, UpdateModelMixin) from rest_framework.pagination import LimitOffsetPagination from rest_framework.permissions import AllowAny from rest_framework.request import Request from rest_framework.response import Response from rest_framework.status import (HTTP_400_BAD_REQUEST, HTTP_501_NOT_IMPLEMENTED) from rest_framework.viewsets import GenericViewSet, ReadOnlyModelViewSet from config.utils.throttles import NoApiKeyAnonRateThrottle from taskbar.views import get_location from .models import Department, Issue from .reciever import synchronize_reciever from .serializers import (DepartmentFullInfoSerializer, IssueHistorySerializer, IssuePerWorkplaceSerializer, IssueSerializer, IssueUpdateSerializer) class DepartmentViewSet(ReadOnlyModelViewSet): # type: ignore ''' Viewset for getting helpdesk problem categories for departments in location. ''' queryset = Department.objects.all() serializer_class = DepartmentFullInfoSerializer def list(self, request: Request) -> Response: # type: ignore location = get_location(request) if location: prefetch_categories = Prefetch('categories_set__categories') prefetch_problems = Prefetch( 'categories_set__categories__problems') departments = Department.objects.select_related( 'location', 'categories_set', 'reciever', ).prefetch_related( prefetch_categories, prefetch_problems, ).filter(location=location) serializer = DepartmentFullInfoSerializer(departments, many=True) result = serializer.data return Response(result) return Response({}) class IssueViewSet( GenericViewSet, # type: ignore CreateModelMixin, UpdateModelMixin, ListModelMixin): ''' Viewset creating ticket ''' queryset = Issue.objects.all() serializers = { "default": IssueHistorySerializer, "create": IssueSerializer, "partial_update": IssueUpdateSerializer, } pagination_class = LimitOffsetPagination def list(self, request: Request) -> Response: # type: ignore return Response(status=HTTP_501_NOT_IMPLEMENTED) def get_serializer_class(self): # type: ignore return self.serializers.get(self.action, self.serializers['default']) @method_decorator(cache_page(0)) def retrieve(self, request: Request, pk: int) -> Response: instance = Issue.objects.filter(pk=pk).first() instance = synchronize_reciever(instance) serializer = IssueSerializer(instance, many=False) return Response(serializer.data) def partial_update(self, request: Request, *args: Tuple[str, Any], **kwargs: Dict[str, Any]) -> Response: kwargs['partial'] = True # type: ignore return self.update(request, *args, **kwargs) class HistoryViewSet(GenericViewSet, ListModelMixin): # type: ignore queryset = Issue.objects.all() serializer_class = IssueHistorySerializer pagination_class = LimitOffsetPagination @method_decorator(cache_page(0)) def list( # type: ignore self, request: Request, hostname: str) -> Response: queryset = Issue.objects.select_related( 'department__reciever', 'status', ).filter(hostname=hostname) page = self.paginate_queryset(queryset) if page is not None: issues = [] for issue in page: instance = synchronize_reciever(issue) issues.append(instance) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) @api_view(['POST']) @permission_classes([AllowAny]) @throttle_classes([NoApiKeyAnonRateThrottle]) def issues_per_hostname_view(request: Request) -> Response: serializer = IssuePerWorkplaceSerializer(data=request.data) if serializer.is_valid(raise_exception=False): return Response(serializer.validated_data) return Response(status=HTTP_400_BAD_REQUEST, data=serializer.errors)