[FIX] HORILLA_API: #1028
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
"""
|
||||
horilla_api/api_serializers/helpdesk/__init__.py
|
||||
"""
|
||||
|
||||
|
||||
@@ -3,18 +3,19 @@ horilla_api/api_serializers/helpdesk/serializers.py
|
||||
"""
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from base.models import Tags
|
||||
from employee.models import Employee
|
||||
from helpdesk.models import (
|
||||
Ticket,
|
||||
TicketType,
|
||||
FAQ,
|
||||
FAQCategory,
|
||||
Comment,
|
||||
Attachment,
|
||||
ClaimRequest,
|
||||
Comment,
|
||||
DepartmentManager,
|
||||
FAQCategory,
|
||||
Ticket,
|
||||
TicketType,
|
||||
)
|
||||
from employee.models import Employee
|
||||
from base.models import Tags
|
||||
|
||||
|
||||
class TicketTypeSerializer(serializers.ModelSerializer):
|
||||
@@ -73,7 +74,10 @@ class DepartmentManagerSerializer(serializers.ModelSerializer):
|
||||
class CommentSerializer(serializers.ModelSerializer):
|
||||
employee_id = serializers.SerializerMethodField()
|
||||
employee_id_write = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Employee.objects.all(), source="employee_id", write_only=True, required=False
|
||||
queryset=Employee.objects.all(),
|
||||
source="employee_id",
|
||||
write_only=True,
|
||||
required=False,
|
||||
)
|
||||
ticket_id = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Ticket.objects.all(), source="ticket", write_only=True
|
||||
@@ -99,7 +103,10 @@ class AttachmentSerializer(serializers.ModelSerializer):
|
||||
queryset=Ticket.objects.all(), source="ticket", write_only=True, required=False
|
||||
)
|
||||
comment_id = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Comment.objects.all(), source="comment", write_only=True, required=False
|
||||
queryset=Comment.objects.all(),
|
||||
source="comment",
|
||||
write_only=True,
|
||||
required=False,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@@ -143,7 +150,10 @@ class ClaimRequestSerializer(serializers.ModelSerializer):
|
||||
class TicketSerializer(serializers.ModelSerializer):
|
||||
employee_id = serializers.SerializerMethodField()
|
||||
employee_id_write = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Employee.objects.all(), source="employee_id", write_only=True, required=False
|
||||
queryset=Employee.objects.all(),
|
||||
source="employee_id",
|
||||
write_only=True,
|
||||
required=False,
|
||||
)
|
||||
ticket_type = TicketTypeSerializer(read_only=True)
|
||||
ticket_type_id = serializers.PrimaryKeyRelatedField(
|
||||
@@ -151,11 +161,19 @@ class TicketSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
assigned_to = serializers.SerializerMethodField()
|
||||
assigned_to_ids = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Employee.objects.all(), many=True, source="assigned_to", write_only=True, required=False
|
||||
queryset=Employee.objects.all(),
|
||||
many=True,
|
||||
source="assigned_to",
|
||||
write_only=True,
|
||||
required=False,
|
||||
)
|
||||
tags = serializers.SerializerMethodField()
|
||||
tags_ids = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Tags.objects.all(), many=True, source="tags", write_only=True, required=False
|
||||
queryset=Tags.objects.all(),
|
||||
many=True,
|
||||
source="tags",
|
||||
write_only=True,
|
||||
required=False,
|
||||
)
|
||||
raised_on_display = serializers.SerializerMethodField()
|
||||
comments = CommentSerializer(many=True, read_only=True)
|
||||
@@ -165,8 +183,8 @@ class TicketSerializer(serializers.ModelSerializer):
|
||||
model = Ticket
|
||||
fields = "__all__"
|
||||
extra_kwargs = {
|
||||
'assigned_to': {'read_only': True},
|
||||
'tags': {'read_only': True},
|
||||
"assigned_to": {"read_only": True},
|
||||
"tags": {"read_only": True},
|
||||
}
|
||||
|
||||
def get_employee_id(self, obj):
|
||||
@@ -202,4 +220,3 @@ class TicketSerializer(serializers.ModelSerializer):
|
||||
return obj.get_raised_on()
|
||||
except:
|
||||
return obj.raised_on
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"""
|
||||
horilla_api/api_urls/helpdesk/__init__.py
|
||||
"""
|
||||
|
||||
|
||||
@@ -3,45 +3,43 @@ horilla_api/api_urls/helpdesk/urls.py
|
||||
"""
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from horilla_api.api_views.helpdesk.views import *
|
||||
|
||||
urlpatterns = [
|
||||
# Ticket Type URLs
|
||||
path("ticket-type/", TicketTypeGetCreateAPIView.as_view()),
|
||||
path("ticket-type/<int:pk>/", TicketTypeGetUpdateDeleteAPIView.as_view()),
|
||||
|
||||
# FAQ Category URLs
|
||||
path("faq-category/", FAQCategoryGetCreateAPIView.as_view()),
|
||||
path("faq-category/<int:pk>/", FAQCategoryGetUpdateDeleteAPIView.as_view()),
|
||||
|
||||
# FAQ URLs
|
||||
path("faq/", FAQGetCreateAPIView.as_view()),
|
||||
path("faq/<int:pk>/", FAQGetUpdateDeleteAPIView.as_view()),
|
||||
path("faq/category/<int:category_id>/", FAQGetCreateAPIView.as_view()),
|
||||
|
||||
# Ticket URLs
|
||||
path("ticket/", TicketGetCreateAPIView.as_view()),
|
||||
path("ticket/<int:pk>/", TicketGetUpdateDeleteAPIView.as_view()),
|
||||
path("ticket/<int:pk>/status/", TicketChangeStatusAPIView.as_view()),
|
||||
path("ticket/<int:pk>/archive/", TicketArchiveAPIView.as_view()),
|
||||
|
||||
# Comment URLs
|
||||
path("ticket/<int:ticket_id>/comment/", CommentGetCreateAPIView.as_view()),
|
||||
path("comment/<int:pk>/", CommentGetUpdateDeleteAPIView.as_view()),
|
||||
|
||||
# Attachment URLs
|
||||
path("ticket/<int:ticket_id>/attachment/", AttachmentGetCreateAPIView.as_view()),
|
||||
path("comment/<int:comment_id>/attachment/", AttachmentGetCreateAPIView.as_view()),
|
||||
path("attachment/<int:pk>/", AttachmentGetDeleteAPIView.as_view()),
|
||||
|
||||
# Claim Request URLs
|
||||
path("claim-request/", ClaimRequestGetCreateAPIView.as_view()),
|
||||
path("ticket/<int:ticket_id>/claim-request/", ClaimRequestGetCreateAPIView.as_view()),
|
||||
path(
|
||||
"ticket/<int:ticket_id>/claim-request/", ClaimRequestGetCreateAPIView.as_view()
|
||||
),
|
||||
path("claim-request/<int:pk>/approve/", ClaimRequestApproveAPIView.as_view()),
|
||||
path("claim-request/<int:pk>/reject/", ClaimRequestRejectAPIView.as_view()),
|
||||
|
||||
# Department Manager URLs
|
||||
path("department-manager/", DepartmentManagerGetCreateAPIView.as_view()),
|
||||
path("department-manager/<int:pk>/", DepartmentManagerGetUpdateDeleteAPIView.as_view()),
|
||||
path(
|
||||
"department-manager/<int:pk>/",
|
||||
DepartmentManagerGetUpdateDeleteAPIView.as_view(),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ class AssetAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = AssetFilter
|
||||
queryset = Asset.objects.all()
|
||||
|
||||
def get_asset(self, pk):
|
||||
try:
|
||||
@@ -63,6 +64,7 @@ class AssetCategoryAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = AssetCategoryFilter
|
||||
queryset = AssetCategory.objects.all()
|
||||
|
||||
def get_asset_category(self, pk):
|
||||
try:
|
||||
|
||||
@@ -921,6 +921,7 @@ class ShiftRequestView(APIView):
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = ShiftRequestFilter
|
||||
permission_classes = [IsAuthenticated]
|
||||
queryset = ShiftRequest.objects.all()
|
||||
|
||||
def get_queryset(self, request=None):
|
||||
# Handle schema generation for DRF-YASG
|
||||
|
||||
@@ -98,6 +98,7 @@ class EmployeeAPIView(APIView):
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = EmployeeFilter
|
||||
permission_classes = [IsAuthenticated]
|
||||
queryset = Employee.objects.all()
|
||||
|
||||
def get(self, request, pk):
|
||||
user = request.user
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"""
|
||||
horilla_api/api_views/helpdesk/__init__.py
|
||||
"""
|
||||
|
||||
|
||||
@@ -2,44 +2,45 @@
|
||||
horilla_api/api_views/helpdesk/views.py
|
||||
"""
|
||||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.http import Http404
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.db.models import Q
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import status
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from horilla_api.api_serializers.helpdesk.serializers import (
|
||||
TicketSerializer,
|
||||
TicketTypeSerializer,
|
||||
FAQSerializer,
|
||||
FAQCategorySerializer,
|
||||
CommentSerializer,
|
||||
AttachmentSerializer,
|
||||
ClaimRequestSerializer,
|
||||
DepartmentManagerSerializer,
|
||||
)
|
||||
from base.methods import filtersubordinates
|
||||
from helpdesk.filter import FAQCategoryFilter, FAQFilter, TicketFilter
|
||||
from helpdesk.models import (
|
||||
Ticket,
|
||||
TicketType,
|
||||
FAQ,
|
||||
FAQCategory,
|
||||
Comment,
|
||||
Attachment,
|
||||
ClaimRequest,
|
||||
Comment,
|
||||
DepartmentManager,
|
||||
FAQCategory,
|
||||
Ticket,
|
||||
TicketType,
|
||||
)
|
||||
from helpdesk.filter import TicketFilter, FAQFilter, FAQCategoryFilter
|
||||
from ...api_methods.base.methods import groupby_queryset, permission_based_queryset
|
||||
from horilla_api.api_serializers.helpdesk.serializers import (
|
||||
AttachmentSerializer,
|
||||
ClaimRequestSerializer,
|
||||
CommentSerializer,
|
||||
DepartmentManagerSerializer,
|
||||
FAQCategorySerializer,
|
||||
FAQSerializer,
|
||||
TicketSerializer,
|
||||
TicketTypeSerializer,
|
||||
)
|
||||
|
||||
from ...api_decorators.base.decorators import (
|
||||
manager_permission_required,
|
||||
permission_required,
|
||||
)
|
||||
from base.methods import filtersubordinates
|
||||
from ...api_methods.base.methods import groupby_queryset, permission_based_queryset
|
||||
|
||||
|
||||
def object_check(cls, pk):
|
||||
@@ -54,10 +55,11 @@ def object_check(cls, pk):
|
||||
class TicketTypeGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
queryset = TicketType.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
if getattr(self, 'swagger_fake_view', False):
|
||||
if getattr(self, "swagger_fake_view", False):
|
||||
return TicketType.objects.none()
|
||||
return TicketType.objects.all()
|
||||
|
||||
@@ -115,10 +117,11 @@ class FAQCategoryGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = FAQCategoryFilter
|
||||
queryset = FAQCategory.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
if getattr(self, 'swagger_fake_view', False):
|
||||
if getattr(self, "swagger_fake_view", False):
|
||||
return FAQCategory.objects.none()
|
||||
return FAQCategory.objects.all()
|
||||
|
||||
@@ -177,10 +180,11 @@ class FAQGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = FAQFilter
|
||||
queryset = FAQ.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
if getattr(self, 'swagger_fake_view', False):
|
||||
if getattr(self, "swagger_fake_view", False):
|
||||
return FAQ.objects.none()
|
||||
return FAQ.objects.all()
|
||||
|
||||
@@ -242,10 +246,11 @@ class TicketGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = TicketFilter
|
||||
queryset = Ticket.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
if getattr(self, 'swagger_fake_view', False):
|
||||
if getattr(self, "swagger_fake_view", False):
|
||||
return Ticket.objects.none()
|
||||
if not self.request.user.is_authenticated:
|
||||
return Ticket.objects.none()
|
||||
@@ -270,12 +275,18 @@ class TicketGetCreateAPIView(APIView):
|
||||
def post(self, request):
|
||||
# Set employee_id from request user if not provided
|
||||
data = request.data.copy()
|
||||
if not data.get("employee_id_write") and not data.get("employee_id") and request.user.is_authenticated:
|
||||
if (
|
||||
not data.get("employee_id_write")
|
||||
and not data.get("employee_id")
|
||||
and request.user.is_authenticated
|
||||
):
|
||||
data["employee_id_write"] = request.user.employee_get.id
|
||||
serializer = TicketSerializer(data=data)
|
||||
if serializer.is_valid():
|
||||
ticket = serializer.save()
|
||||
return Response(TicketSerializer(ticket).data, status=status.HTTP_201_CREATED)
|
||||
return Response(
|
||||
TicketSerializer(ticket).data, status=status.HTTP_201_CREATED
|
||||
)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@@ -288,9 +299,11 @@ class TicketGetUpdateDeleteAPIView(APIView):
|
||||
return Response({"error": "Ticket not found"}, status=404)
|
||||
# Check permissions
|
||||
user = request.user
|
||||
if not (user.has_perm("helpdesk.view_ticket") or
|
||||
ticket.employee_id == user.employee_get or
|
||||
ticket.assigned_to.filter(id=user.employee_get.id).exists()):
|
||||
if not (
|
||||
user.has_perm("helpdesk.view_ticket")
|
||||
or ticket.employee_id == user.employee_get
|
||||
or ticket.assigned_to.filter(id=user.employee_get.id).exists()
|
||||
):
|
||||
return Response({"error": "Permission denied"}, status=403)
|
||||
serializer = TicketSerializer(ticket)
|
||||
return Response(serializer.data, status=200)
|
||||
@@ -327,11 +340,14 @@ class TicketChangeStatusAPIView(APIView):
|
||||
if ticket is None:
|
||||
return Response({"error": "Ticket not found"}, status=404)
|
||||
status_value = request.data.get("status")
|
||||
if status_value not in [choice[0] for choice in Ticket._meta.get_field("status").choices]:
|
||||
if status_value not in [
|
||||
choice[0] for choice in Ticket._meta.get_field("status").choices
|
||||
]:
|
||||
return Response({"error": "Invalid status"}, status=400)
|
||||
ticket.status = status_value
|
||||
if status_value == "resolved":
|
||||
from datetime import date
|
||||
|
||||
ticket.resolved_date = date.today()
|
||||
ticket.save()
|
||||
return Response(TicketSerializer(ticket).data, status=200)
|
||||
@@ -370,12 +386,18 @@ class CommentGetCreateAPIView(APIView):
|
||||
return Response({"error": "Ticket not found"}, status=404)
|
||||
data = request.data.copy()
|
||||
data["ticket_id"] = ticket_id
|
||||
if not data.get("employee_id_write") and not data.get("employee_id") and request.user.is_authenticated:
|
||||
if (
|
||||
not data.get("employee_id_write")
|
||||
and not data.get("employee_id")
|
||||
and request.user.is_authenticated
|
||||
):
|
||||
data["employee_id_write"] = request.user.employee_get.id
|
||||
serializer = CommentSerializer(data=data)
|
||||
if serializer.is_valid():
|
||||
comment = serializer.save()
|
||||
return Response(CommentSerializer(comment).data, status=status.HTTP_201_CREATED)
|
||||
return Response(
|
||||
CommentSerializer(comment).data, status=status.HTTP_201_CREATED
|
||||
)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@@ -407,7 +429,10 @@ class CommentGetUpdateDeleteAPIView(APIView):
|
||||
if comment is None:
|
||||
return Response({"error": "Comment not found"}, status=404)
|
||||
# Check if user owns the comment or has permission
|
||||
if comment.employee_id != request.user.employee_get and not request.user.has_perm("helpdesk.delete_comment"):
|
||||
if (
|
||||
comment.employee_id != request.user.employee_get
|
||||
and not request.user.has_perm("helpdesk.delete_comment")
|
||||
):
|
||||
return Response({"error": "Permission denied"}, status=403)
|
||||
try:
|
||||
comment.delete()
|
||||
@@ -436,7 +461,9 @@ class AttachmentGetCreateAPIView(APIView):
|
||||
serializer = AttachmentSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
attachment = serializer.save()
|
||||
return Response(AttachmentSerializer(attachment).data, status=status.HTTP_201_CREATED)
|
||||
return Response(
|
||||
AttachmentSerializer(attachment).data, status=status.HTTP_201_CREATED
|
||||
)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@@ -479,7 +506,10 @@ class ClaimRequestGetCreateAPIView(APIView):
|
||||
serializer = ClaimRequestSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
claim_request = serializer.save()
|
||||
return Response(ClaimRequestSerializer(claim_request).data, status=status.HTTP_201_CREATED)
|
||||
return Response(
|
||||
ClaimRequestSerializer(claim_request).data,
|
||||
status=status.HTTP_201_CREATED,
|
||||
)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@@ -520,7 +550,7 @@ class DepartmentManagerGetCreateAPIView(APIView):
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
if getattr(self, 'swagger_fake_view', False):
|
||||
if getattr(self, "swagger_fake_view", False):
|
||||
return DepartmentManager.objects.none()
|
||||
return DepartmentManager.objects.all()
|
||||
|
||||
@@ -571,4 +601,3 @@ class DepartmentManagerGetUpdateDeleteAPIView(APIView):
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
except Exception as e:
|
||||
return Response({"error": str(e)}, status=400)
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ class EmployeeLeaveRequestGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = UserLeaveRequestFilter
|
||||
queryset = LeaveRequest.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
@@ -151,6 +152,7 @@ class LeaveTypeGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = LeaveTypeFilter
|
||||
queryset = LeaveType.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
@@ -223,6 +225,7 @@ class LeaveAllocationRequestGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = LeaveAllocationRequestFilter
|
||||
queryset = LeaveAllocationRequest.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
@@ -330,6 +333,7 @@ class AssignLeaveGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = AssignedLeaveFilter
|
||||
queryset = AvailableLeave.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
@@ -441,6 +445,7 @@ class LeaveRequestGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = LeaveRequestFilter
|
||||
queryset = LeaveRequest.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
@@ -970,6 +975,7 @@ class EmployeeLeaveAllocationGetCreateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_class = LeaveAllocationRequestFilter
|
||||
queryset = LeaveAllocationRequest.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
# Handle schema generation for DRF-YASG
|
||||
|
||||
Reference in New Issue
Block a user