604 lines
23 KiB
Python
604 lines
23 KiB
Python
"""
|
|
horilla_api/api_views/helpdesk/views.py
|
|
"""
|
|
|
|
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 base.methods import filtersubordinates
|
|
from helpdesk.filter import FAQCategoryFilter, FAQFilter, TicketFilter
|
|
from helpdesk.models import (
|
|
FAQ,
|
|
Attachment,
|
|
ClaimRequest,
|
|
Comment,
|
|
DepartmentManager,
|
|
FAQCategory,
|
|
Ticket,
|
|
TicketType,
|
|
)
|
|
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 ...api_methods.base.methods import groupby_queryset, permission_based_queryset
|
|
|
|
|
|
def object_check(cls, pk):
|
|
try:
|
|
obj = cls.objects.get(id=pk)
|
|
return obj
|
|
except cls.DoesNotExist:
|
|
return None
|
|
|
|
|
|
# Ticket Type Views
|
|
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):
|
|
return TicketType.objects.none()
|
|
return TicketType.objects.all()
|
|
|
|
def get(self, request):
|
|
ticket_types = self.get_queryset()
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(ticket_types, request)
|
|
serializer = TicketTypeSerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
@permission_required("helpdesk.add_tickettype")
|
|
def post(self, request):
|
|
serializer = TicketTypeSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class TicketTypeGetUpdateDeleteAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
ticket_type = object_check(TicketType, pk)
|
|
if ticket_type is None:
|
|
return Response({"error": "TicketType not found"}, status=404)
|
|
serializer = TicketTypeSerializer(ticket_type)
|
|
return Response(serializer.data, status=200)
|
|
|
|
@permission_required("helpdesk.change_tickettype")
|
|
def put(self, request, pk):
|
|
ticket_type = object_check(TicketType, pk)
|
|
if ticket_type is None:
|
|
return Response({"error": "TicketType not found"}, status=404)
|
|
serializer = TicketTypeSerializer(ticket_type, data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=200)
|
|
return Response(serializer.errors, status=400)
|
|
|
|
@permission_required("helpdesk.delete_tickettype")
|
|
def delete(self, request, pk):
|
|
ticket_type = object_check(TicketType, pk)
|
|
if ticket_type is None:
|
|
return Response({"error": "TicketType not found"}, status=404)
|
|
try:
|
|
ticket_type.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
except Exception as e:
|
|
return Response({"error": str(e)}, status=400)
|
|
|
|
|
|
# FAQ Category Views
|
|
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):
|
|
return FAQCategory.objects.none()
|
|
return FAQCategory.objects.all()
|
|
|
|
def get(self, request):
|
|
faq_categories = self.get_queryset()
|
|
filterset = self.filterset_class(request.GET, queryset=faq_categories)
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(filterset.qs, request)
|
|
serializer = FAQCategorySerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
@permission_required("helpdesk.add_faqcategory")
|
|
def post(self, request):
|
|
serializer = FAQCategorySerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class FAQCategoryGetUpdateDeleteAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
faq_category = object_check(FAQCategory, pk)
|
|
if faq_category is None:
|
|
return Response({"error": "FAQCategory not found"}, status=404)
|
|
serializer = FAQCategorySerializer(faq_category)
|
|
return Response(serializer.data, status=200)
|
|
|
|
@permission_required("helpdesk.change_faqcategory")
|
|
def put(self, request, pk):
|
|
faq_category = object_check(FAQCategory, pk)
|
|
if faq_category is None:
|
|
return Response({"error": "FAQCategory not found"}, status=404)
|
|
serializer = FAQCategorySerializer(faq_category, data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=200)
|
|
return Response(serializer.errors, status=400)
|
|
|
|
@permission_required("helpdesk.delete_faqcategory")
|
|
def delete(self, request, pk):
|
|
faq_category = object_check(FAQCategory, pk)
|
|
if faq_category is None:
|
|
return Response({"error": "FAQCategory not found"}, status=404)
|
|
try:
|
|
faq_category.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
except Exception as e:
|
|
return Response({"error": str(e)}, status=400)
|
|
|
|
|
|
# FAQ Views
|
|
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):
|
|
return FAQ.objects.none()
|
|
return FAQ.objects.all()
|
|
|
|
def get(self, request, category_id=None):
|
|
if category_id:
|
|
faqs = FAQ.objects.filter(category_id=category_id)
|
|
else:
|
|
faqs = self.get_queryset()
|
|
filterset = self.filterset_class(request.GET, queryset=faqs)
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(filterset.qs, request)
|
|
serializer = FAQSerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
@permission_required("helpdesk.add_faq")
|
|
def post(self, request):
|
|
serializer = FAQSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class FAQGetUpdateDeleteAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
faq = object_check(FAQ, pk)
|
|
if faq is None:
|
|
return Response({"error": "FAQ not found"}, status=404)
|
|
serializer = FAQSerializer(faq)
|
|
return Response(serializer.data, status=200)
|
|
|
|
@permission_required("helpdesk.change_faq")
|
|
def put(self, request, pk):
|
|
faq = object_check(FAQ, pk)
|
|
if faq is None:
|
|
return Response({"error": "FAQ not found"}, status=404)
|
|
serializer = FAQSerializer(faq, data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=200)
|
|
return Response(serializer.errors, status=400)
|
|
|
|
@permission_required("helpdesk.delete_faq")
|
|
def delete(self, request, pk):
|
|
faq = object_check(FAQ, pk)
|
|
if faq is None:
|
|
return Response({"error": "FAQ not found"}, status=404)
|
|
try:
|
|
faq.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
except Exception as e:
|
|
return Response({"error": str(e)}, status=400)
|
|
|
|
|
|
# Ticket Views
|
|
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):
|
|
return Ticket.objects.none()
|
|
if not self.request.user.is_authenticated:
|
|
return Ticket.objects.none()
|
|
user = self.request.user
|
|
perm = "helpdesk.view_ticket"
|
|
queryset = Ticket.objects.all()
|
|
queryset = permission_based_queryset(user, perm, queryset, user_obj=True)
|
|
return queryset
|
|
|
|
def get(self, request):
|
|
tickets = self.get_queryset()
|
|
filterset = self.filterset_class(request.GET, queryset=tickets)
|
|
field_name = request.GET.get("groupby_field", None)
|
|
if field_name:
|
|
url = request.build_absolute_uri()
|
|
return groupby_queryset(request, url, field_name, filterset.qs)
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(filterset.qs, request)
|
|
serializer = TicketSerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
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
|
|
):
|
|
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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class TicketGetUpdateDeleteAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
ticket = object_check(Ticket, pk)
|
|
if ticket is None:
|
|
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()
|
|
):
|
|
return Response({"error": "Permission denied"}, status=403)
|
|
serializer = TicketSerializer(ticket)
|
|
return Response(serializer.data, status=200)
|
|
|
|
@permission_required("helpdesk.change_ticket")
|
|
def put(self, request, pk):
|
|
ticket = object_check(Ticket, pk)
|
|
if ticket is None:
|
|
return Response({"error": "Ticket not found"}, status=404)
|
|
serializer = TicketSerializer(ticket, data=request.data, partial=True)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=200)
|
|
return Response(serializer.errors, status=400)
|
|
|
|
@permission_required("helpdesk.delete_ticket")
|
|
def delete(self, request, pk):
|
|
ticket = object_check(Ticket, pk)
|
|
if ticket is None:
|
|
return Response({"error": "Ticket not found"}, status=404)
|
|
try:
|
|
ticket.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
except Exception as e:
|
|
return Response({"error": str(e)}, status=400)
|
|
|
|
|
|
class TicketChangeStatusAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
@permission_required("helpdesk.change_ticket")
|
|
def put(self, request, pk):
|
|
ticket = object_check(Ticket, pk)
|
|
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
|
|
]:
|
|
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)
|
|
|
|
|
|
class TicketArchiveAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
@permission_required("helpdesk.change_ticket")
|
|
def put(self, request, pk):
|
|
ticket = object_check(Ticket, pk)
|
|
if ticket is None:
|
|
return Response({"error": "Ticket not found"}, status=404)
|
|
ticket.is_active = False
|
|
ticket.save()
|
|
return Response(TicketSerializer(ticket).data, status=200)
|
|
|
|
|
|
# Comment Views
|
|
class CommentGetCreateAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, ticket_id):
|
|
ticket = object_check(Ticket, ticket_id)
|
|
if ticket is None:
|
|
return Response({"error": "Ticket not found"}, status=404)
|
|
comments = Comment.objects.filter(ticket_id=ticket_id)
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(comments, request)
|
|
serializer = CommentSerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
def post(self, request, ticket_id):
|
|
ticket = object_check(Ticket, ticket_id)
|
|
if ticket is None:
|
|
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
|
|
):
|
|
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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class CommentGetUpdateDeleteAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
comment = object_check(Comment, pk)
|
|
if comment is None:
|
|
return Response({"error": "Comment not found"}, status=404)
|
|
serializer = CommentSerializer(comment)
|
|
return Response(serializer.data, status=200)
|
|
|
|
def put(self, request, pk):
|
|
comment = object_check(Comment, pk)
|
|
if comment is None:
|
|
return Response({"error": "Comment not found"}, status=404)
|
|
# Check if user owns the comment
|
|
if comment.employee_id != request.user.employee_get:
|
|
return Response({"error": "Permission denied"}, status=403)
|
|
serializer = CommentSerializer(comment, data=request.data, partial=True)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=200)
|
|
return Response(serializer.errors, status=400)
|
|
|
|
def delete(self, request, pk):
|
|
comment = object_check(Comment, pk)
|
|
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")
|
|
):
|
|
return Response({"error": "Permission denied"}, status=403)
|
|
try:
|
|
comment.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
except Exception as e:
|
|
return Response({"error": str(e)}, status=400)
|
|
|
|
|
|
# Attachment Views
|
|
class AttachmentGetCreateAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, ticket_id=None, comment_id=None):
|
|
if ticket_id:
|
|
attachments = Attachment.objects.filter(ticket_id=ticket_id)
|
|
elif comment_id:
|
|
attachments = Attachment.objects.filter(comment_id=comment_id)
|
|
else:
|
|
return Response({"error": "ticket_id or comment_id required"}, status=400)
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(attachments, request)
|
|
serializer = AttachmentSerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
def post(self, request):
|
|
serializer = AttachmentSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
attachment = serializer.save()
|
|
return Response(
|
|
AttachmentSerializer(attachment).data, status=status.HTTP_201_CREATED
|
|
)
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class AttachmentGetDeleteAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
attachment = object_check(Attachment, pk)
|
|
if attachment is None:
|
|
return Response({"error": "Attachment not found"}, status=404)
|
|
serializer = AttachmentSerializer(attachment)
|
|
return Response(serializer.data, status=200)
|
|
|
|
def delete(self, request, pk):
|
|
attachment = object_check(Attachment, pk)
|
|
if attachment is None:
|
|
return Response({"error": "Attachment not found"}, status=404)
|
|
try:
|
|
attachment.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
except Exception as e:
|
|
return Response({"error": str(e)}, status=400)
|
|
|
|
|
|
# Claim Request Views
|
|
class ClaimRequestGetCreateAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, ticket_id=None):
|
|
if ticket_id:
|
|
claim_requests = ClaimRequest.objects.filter(ticket_id=ticket_id)
|
|
else:
|
|
claim_requests = ClaimRequest.objects.all()
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(claim_requests, request)
|
|
serializer = ClaimRequestSerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
def post(self, request):
|
|
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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class ClaimRequestApproveAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
@permission_required("helpdesk.change_ticket")
|
|
def put(self, request, pk):
|
|
claim_request = object_check(ClaimRequest, pk)
|
|
if claim_request is None:
|
|
return Response({"error": "ClaimRequest not found"}, status=404)
|
|
claim_request.is_approved = True
|
|
claim_request.is_rejected = False
|
|
claim_request.save()
|
|
# Add employee to assigned_to
|
|
ticket = claim_request.ticket_id
|
|
ticket.assigned_to.add(claim_request.employee_id)
|
|
return Response(ClaimRequestSerializer(claim_request).data, status=200)
|
|
|
|
|
|
class ClaimRequestRejectAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
@permission_required("helpdesk.change_ticket")
|
|
def put(self, request, pk):
|
|
claim_request = object_check(ClaimRequest, pk)
|
|
if claim_request is None:
|
|
return Response({"error": "ClaimRequest not found"}, status=404)
|
|
claim_request.is_approved = False
|
|
claim_request.is_rejected = True
|
|
claim_request.save()
|
|
return Response(ClaimRequestSerializer(claim_request).data, status=200)
|
|
|
|
|
|
# Department Manager Views
|
|
class DepartmentManagerGetCreateAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get_queryset(self):
|
|
# Handle schema generation for DRF-YASG
|
|
if getattr(self, "swagger_fake_view", False):
|
|
return DepartmentManager.objects.none()
|
|
return DepartmentManager.objects.all()
|
|
|
|
def get(self, request):
|
|
department_managers = self.get_queryset()
|
|
paginator = PageNumberPagination()
|
|
page = paginator.paginate_queryset(department_managers, request)
|
|
serializer = DepartmentManagerSerializer(page, many=True)
|
|
return paginator.get_paginated_response(serializer.data)
|
|
|
|
@permission_required("helpdesk.add_departmentmanager")
|
|
def post(self, request):
|
|
serializer = DepartmentManagerSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DepartmentManagerGetUpdateDeleteAPIView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request, pk):
|
|
department_manager = object_check(DepartmentManager, pk)
|
|
if department_manager is None:
|
|
return Response({"error": "DepartmentManager not found"}, status=404)
|
|
serializer = DepartmentManagerSerializer(department_manager)
|
|
return Response(serializer.data, status=200)
|
|
|
|
@permission_required("helpdesk.change_departmentmanager")
|
|
def put(self, request, pk):
|
|
department_manager = object_check(DepartmentManager, pk)
|
|
if department_manager is None:
|
|
return Response({"error": "DepartmentManager not found"}, status=404)
|
|
serializer = DepartmentManagerSerializer(department_manager, data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save()
|
|
return Response(serializer.data, status=200)
|
|
return Response(serializer.errors, status=400)
|
|
|
|
@permission_required("helpdesk.delete_departmentmanager")
|
|
def delete(self, request, pk):
|
|
department_manager = object_check(DepartmentManager, pk)
|
|
if department_manager is None:
|
|
return Response({"error": "DepartmentManager not found"}, status=404)
|
|
try:
|
|
department_manager.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
except Exception as e:
|
|
return Response({"error": str(e)}, status=400)
|