Working on Ticket API

Improved filters and added TicketCount API View.
This commit is contained in:
Corban-Lee Jones 2024-01-14 01:50:22 +00:00
parent a20fba656a
commit a708a8b151
2 changed files with 113 additions and 16 deletions

View File

@ -2,8 +2,9 @@
from django.urls import path
from .views import TicketListApiView
from .views import TicketListApiView, FilterCountApiView
urlpatterns = [
path("ticket/", TicketListApiView.as_view(), name="ticket"),
path("filter-counts/", FilterCountApiView.as_view(), name="filter-counts"),
]

View File

@ -1,37 +1,60 @@
# -*- encoding: utf-8 -*-
import json
import logging
from typing import Any
from django.conf import settings
from django.db.models import Q
from django.http import HttpRequest
from django.core.cache import cache
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator
from django.core.exceptions import ValidationError
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions
from rest_framework.pagination import PageNumberPagination
from apps.home.models import Ticket, TicketPriority, TicketTag
from apps.authentication.models import Department
from .serializers import (
TicketSerializer, TicketTagSerializer, TicketPrioritySerializer,
UserSerializer
)
log = logging.getLogger(__name__)
def respond_error(error: Exception, status: Any) -> Response:
logging.error(error)
return Response({
"detail": str(error),
"error": error.__class__.__name__
}, status=status)
class TicketPaginiation(PageNumberPagination):
page_size = 25
page_size_query_param = "page_size"
max_page_size = 100
class TicketListApiView(APIView):
permission_classes = [permissions.IsAuthenticated]
pagination_class = TicketPaginiation
def get(self, request):
"""Return all tickets."""
ALLOWED_FILTERS = ("uuid__in", "priority__in", "tags__in", "author__department__in")
filters = json.loads(request.GET.get("filters", "{}"))
queryset = Ticket.objects.all()
# @method_decorator(cache_page(60 * 5))
def get(self, request: HttpRequest) -> Response:
"""Returns a response containing tickets matching the given filters."""
for key, values in filters.items():
for value in values:
if value == "all": continue
queryset = queryset.filter(**{key: [value]})
try:
return self._get_tickets(request)
tickets = queryset.order_by("-create_timestamp")
serializer = TicketSerializer(tickets, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
except KeyError as error:
return respond_error(error, status.HTTP_400_BAD_REQUEST)
except ValidationError as error:
return respond_error(error, status.HTTP_400_BAD_REQUEST)
def post(self, request):
"""Create a new ticket"""
@ -40,7 +63,80 @@ class TicketListApiView(APIView):
})
if not serializer.is_valid():
return Response(serlializer.errors, status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
def _get_tickets(self, request: HttpRequest) -> Response:
"""Returns a response containing tickets matching the given filters.
Parameters
----------
request : HttpRequest
The request containing the filters.
Returns
-------
Response
A response containing the tickets data.
Raises
------
KeyError
If any given filter key isn't in `self.ALLOWED_FILTERS`.
ValidationError
If any ValidationErrors are raised by Django while applying filters.
"""
queryset = Ticket.objects.all()
for key in request.GET.keys():
values = request.GET.getlist(key) if key.endswith("[]") else [request.GET.get(key)]
key = key.removesuffix("[]")
if key not in self.ALLOWED_FILTERS:
raise KeyError(key)
for value in values:
if value == "all": continue
queryset = queryset.filter(Q(**{key: [value]}))
tickets = queryset.order_by("-create_timestamp")
serializer = TicketSerializer(tickets, many=True)
response_data = serializer.data
log.debug("Query successful showing %s results", tickets.count())
return Response(response_data, status=status.HTTP_200_OK)
class FilterCountApiView(APIView):
permission_classes = [permissions.IsAuthenticated]
@method_decorator(cache_page(60 * 5))
def get(self, request):
priorities = TicketPriority.objects.all()
tags = TicketTag.objects.all()
departments = Department.objects.all()
tickets = Ticket.objects.all()
data = {
"priority_counts": {},
"tag_counts": {},
"department_counts": {},
"ticket_count": tickets.count()
}
for priority in priorities:
data["priority_counts"][str(priority.uuid)] = tickets.filter(priority=priority).count()
for tag in tags:
data["tag_counts"][str(tag.uuid)] = tickets.filter(tags__in=[tag]).count()
for department in departments:
data["department_counts"][str(department.uuid)] = tickets.filter(author__department=department).count()
return Response(data, status=status.HTTP_200_OK)