production-taskbar / backend / helpdesk / views.py
views.py
Raw
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)