[FIX] HELPDESK: Permission for department manager added

This commit is contained in:
Horilla
2024-10-11 12:26:13 +05:30
parent 203b61f827
commit c0dc07dfcf

View File

@@ -1,5 +1,8 @@
import json
import logging
import os
from datetime import datetime
from distutils.util import strtobool
from operator import itemgetter
from urllib.parse import parse_qs
@@ -8,6 +11,7 @@ from django.core.paginator import Paginator
from django.db.models import ProtectedError, Q
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import redirect, render
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.translation import gettext as _
from django.views.decorators.http import require_http_methods
@@ -23,6 +27,7 @@ from base.methods import (
)
from base.models import Department, JobPosition, Tags
from employee.models import Employee
from employee.views import get_content_type
from helpdesk.decorators import ticket_owner_can_enter
from helpdesk.filter import FAQCategoryFilter, FAQFilter, TicketFilter, TicketReGroup
from helpdesk.forms import (
@@ -37,10 +42,12 @@ from helpdesk.forms import (
TicketTagForm,
TicketTypeForm,
)
from helpdesk.methods import is_department_manager
from helpdesk.models import (
FAQ,
TICKET_STATUS,
Attachment,
ClaimRequest,
Comment,
DepartmentManager,
FAQCategory,
@@ -57,6 +64,8 @@ from horilla.decorators import (
from horilla.group_by import group_by_queryset
from notifications.signals import notify
logger = logging.getLogger(__name__)
# Create your views here.
@@ -377,11 +386,10 @@ def ticket_view(request):
Parameters:
request (HttpRequest): The HTTP request object.
"""
tickets = Ticket.objects.filter(is_active=True).order_by("-created_date")
tickets = Ticket.objects.filter(is_active=True)
view = request.GET.get("view") if request.GET.get("view") else "list"
employee = request.user.employee_get
previous_data = request.GET.urlencode()
if request.method == "GET":
tickets = TicketFilter(request.GET).qs
my_page_number = request.GET.get("my_page")
all_page_number = request.GET.get("all_page")
allocated_page_number = request.GET.get("allocated_page")
@@ -422,7 +430,7 @@ def ticket_view(request):
"f": TicketFilter(request.GET),
"gp_fields": TicketReGroup.fields,
"ticket_status": TICKET_STATUS,
"view": request.GET.get("view"),
"view": view,
"today": datetime.today().date(),
"filter_dict": data_dict,
}
@@ -444,10 +452,14 @@ def ticket_create(request):
POST : return Ticket view
"""
form = TicketForm(initial={"employee_id": request.user})
form = TicketForm()
if request.GET.get("status"):
status = request.GET.get("status")
form = TicketForm(initial={"status": status, "employee_id": request.user})
form = TicketForm(
initial={
"status": status,
}
)
if request.method == "POST":
form = TicketForm(request.POST, request.FILES)
if form.is_valid():
@@ -489,7 +501,6 @@ def ticket_create(request):
@login_required
@hx_request_required
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
def ticket_update(request, ticket_id):
"""
This function is responsible for updating the Ticket.
@@ -503,6 +514,12 @@ def ticket_update(request, ticket_id):
"""
ticket = Ticket.objects.get(id=ticket_id)
if (
request.user.has_perm("helpdesk.change_ticket")
or is_department_manager(request, ticket)
or request.user.employee_get == ticket.employee_id
or request.user.employee_get in ticket.assigned_to.all()
):
form = TicketForm(instance=ticket)
if request.method == "POST":
form = TicketForm(request.POST, request.FILES, instance=ticket)
@@ -520,10 +537,21 @@ def ticket_update(request, ticket_id):
"t_type_form": TicketTypeForm(),
}
return render(request, "helpdesk/ticket/ticket_form.html", context)
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
@permission_required("helpdesk.change_ticket")
def ticket_archive(request, ticket_id):
"""
This function is responsible for archiving the Ticket.
@@ -536,16 +564,38 @@ def ticket_archive(request, ticket_id):
"""
ticket = Ticket.objects.get(id=ticket_id)
# Check if the user has permission or is the employee or their reporting manager
if (
request.user.has_perm("helpdesk.delete_ticket")
or ticket.employee_id == request.user.employee_get
or is_department_manager(request, ticket)
):
# Toggle the ticket's active state
ticket.is_active = not ticket.is_active
ticket.save()
if ticket.is_active:
ticket.is_active = False
ticket.save()
messages.success(request, _("The Ticket archived successfully."))
else:
ticket.is_active = True
ticket.save()
messages.success(request, _("The Ticket un-archived successfully."))
else:
messages.success(request, _("The Ticket archived successfully."))
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
@@ -620,7 +670,7 @@ def change_ticket_status(request, ticket_id):
@login_required
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
@ticket_owner_can_enter(perm="helpdesk.delete_ticket", model=Ticket)
def ticket_delete(request, ticket_id):
"""
This function is responsible for deleting the Ticket.
@@ -634,7 +684,7 @@ def ticket_delete(request, ticket_id):
"""
try:
ticket = Ticket.objects.get(id=ticket_id)
if ticket.status == "new":
mail_thread = TicketSendThread(
request,
ticket,
@@ -663,8 +713,11 @@ def ticket_delete(request, ticket_id):
)
ticket.delete()
messages.success(
request, _('The Ticket "{}" has been deleted successfully.').format(ticket)
request,
_('The Ticket "{}" has been deleted successfully.').format(ticket),
)
else:
messages.error(request, _('The ticket is not in the "New" status'))
except ProtectedError:
messages.error(request, _("You cannot delete this Ticket."))
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
@@ -709,17 +762,17 @@ def ticket_filter(request):
my_page_number = request.GET.get("my_page")
all_page_number = request.GET.get("all_page")
allocated_page_number = request.GET.get("allocated_page")
tickets_items1 = []
tickets_items2 = []
tickets_items1 = Ticket.objects.none()
tickets_items2 = Ticket.objects.none()
my_tickets = tickets.filter(employee_id=request.user.employee_get).order_by(
"-created_date"
my_tickets = tickets.filter(employee_id=request.user.employee_get) | tickets.filter(
created_by=request.user
)
all_tickets = tickets.filter(is_active=True).order_by("-created_date")
all_tickets = tickets.filter(is_active=True)
all_tickets = filtersubordinates(request, tickets, "helpdesk.add_tickets")
allocated_tickets = []
allocated_tickets = Ticket.objects.none()
user = request.user.employee_get
department = user.employee_work_info.department_id
job_position = user.employee_work_info.job_position_id
@@ -795,10 +848,16 @@ def ticket_filter(request):
@login_required
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
def ticket_detail(request, ticket_id, **kwargs):
today = datetime.now().date()
ticket = Ticket.objects.get(id=ticket_id)
if (
request.user.has_perm("helpdesk.view_ticket")
or ticket.employee_id.get_reporting_manager() == request.user.employee_get
or is_department_manager(request, ticket)
or request.user.employee_get == ticket.employee_id
or request.user.employee_get in ticket.assigned_to.all()
):
today = datetime.now().date()
c_form = CommentForm()
f_form = AttachmentForm()
attachments = ticket.ticket_attachment.all()
@@ -853,16 +912,66 @@ def ticket_detail(request, ticket_id, **kwargs):
"rating": rating,
}
return render(request, "helpdesk/ticket/ticket_detail.html", context=context)
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
def ticket_individual_view(request, ticket_id):
ticket = Ticket.objects.filter(id=ticket_id).first()
context = {
"ticket": ticket,
}
return render(
request, "helpdesk/ticket/ticket_individual_view.html", context=context
)
@login_required
def view_ticket_claim_request(request, ticket_id):
ticket = Ticket.objects.filter(id=ticket_id).first()
if request.user.has_perm("helpdesk.change_ticket") or is_department_manager(
request, ticket
):
claim_requests = ticket.claimrequest_set.all()
context = {
"claim_requests": claim_requests,
}
return render(request, "helpdesk/ticket/ticket_claim_requests.html", context)
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
# @ticket_owner_can_enter("perms.helpdesk.helpdesk_changeticket", Ticket)
def ticket_update_tag(request):
"""
method to update the tags of ticket
"""
data = request.GET
ticket = Ticket.objects.get(id=data["ticketId"])
if (
request.user.has_perm("helpdesk.view_ticket")
or request.user.employee_get == ticket.employee_id
or is_department_manager(request, ticket)
):
tagids = data.getlist("selectedValues[]")
ticket.tags.clear()
for tagId in tagids:
@@ -873,13 +982,27 @@ def ticket_update_tag(request):
"message": _("The Ticket tag updated successfully."),
}
return JsonResponse(response)
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
@hx_request_required
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
def ticket_change_raised_on(request, ticket_id):
ticket = Ticket.objects.get(id=ticket_id)
if (
request.user.has_perm("helpdesk.view_ticket")
or request.user.employee_get == ticket.employee_id
):
form = TicketRaisedOnForm(instance=ticket)
if request.method == "POST":
form = TicketRaisedOnForm(request.POST, instance=ticket)
@@ -892,13 +1015,26 @@ def ticket_change_raised_on(request, ticket_id):
"helpdesk/ticket/forms/change_raised_on.html",
{"form": form, "ticket_id": ticket_id},
)
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
@hx_request_required
@manager_can_enter("helpdesk.change_ticket")
def ticket_change_assignees(request, ticket_id):
ticket = Ticket.objects.get(id=ticket_id)
if request.user.has_perm("helpdesk.change_ticket") or is_department_manager(
request, ticket
):
prev_assignee_ids = ticket.assigned_to.values_list("id", flat=True)
form = TicketAssigneesForm(instance=ticket)
if request.method == "POST":
@@ -930,14 +1066,24 @@ def ticket_change_assignees(request, ticket_id):
mail_thread.start()
messages.success(request, _("Assinees updated for the Ticket"))
return redirect(ticket_detail, ticket_id=ticket_id)
return HttpResponse("<script>window.location.reload()</script>")
return render(
request,
"helpdesk/ticket/forms/change_assinees.html",
{"form": form, "ticket_id": ticket_id},
)
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
@@ -984,6 +1130,41 @@ def remove_tag(request):
return JsonResponse({"message": message, "type": type})
@login_required
@hx_request_required
def view_ticket_document(request, doc_id):
"""
This function used to view the uploaded document in the modal.
Parameters:
request (HttpRequest): The HTTP request object.
id (int): The id of the document.
Returns: return view_file template
"""
document_obj = Attachment.objects.filter(id=doc_id).first()
context = {
"document": document_obj,
}
if document_obj.file:
file_path = document_obj.file.path
file_extension = os.path.splitext(file_path)[1][
1:
].lower() # Get the lowercase file extension
content_type = get_content_type(file_extension)
try:
with open(file_path, "rb") as file:
file_content = file.read() # Decode the binary content for display
except:
file_content = None
context["file_content"] = file_content
context["file_extension"] = file_extension
context["content_type"] = content_type
return render(request, "helpdesk/ticket/ticket_document.html", context)
@login_required
def comment_create(request, ticket_id):
""" "
@@ -1030,14 +1211,14 @@ def comment_edit(request):
@login_required
def comment_delete(request, comment_id):
comment = Comment.objects.filter(id=comment_id)
comment = Comment.objects.filter(id=comment_id).first()
employee = comment.employee_id
if not request.user.has_perm("helpdesk.delete_comment"):
comment = comment.filter(employee_id__employee_user_id=request.user)
comment.delete()
messages.success(
request, _('The comment "{}" has been deleted successfully.').format(comment)
request, _("{}'s comment has been deleted successfully.").format(employee)
)
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
@@ -1077,13 +1258,116 @@ def get_raised_on(request):
@login_required
def claim_ticket(request, id):
"""
This is a function to create a claim request for requested employee
"""
ticket = Ticket.objects.get(id=id)
if ticket.employee_id != request.user.employee_get:
ticket.assigned_to.set([request.user.employee_get])
ticket.save()
if not ClaimRequest.objects.filter(
employee_id=request.user.employee_get, ticket_id=ticket
).exists():
ClaimRequest(employee_id=request.user.employee_get, ticket_id=ticket).save()
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
@login_required
def approve_claim_request(request, req_id):
"""
Function for approve claim request and send notifications to the responsibles.
"""
claim_request = ClaimRequest.objects.filter(id=req_id).first()
if not claim_request:
return HttpResponse("Invalid claim request", status=404)
approve = strtobool(
request.GET.get("approve", "False")
) # Safely convert to boolean
ticket = claim_request.ticket_id
employee = claim_request.employee_id
refresh = False
if approve:
# message
message = _("Claim request approved successfully.")
refresh = True
if employee not in ticket.assigned_to.all():
ticket.assigned_to.add(employee) # Approve and assign to employee
try:
# send notification
notify.send(
request.user.employee_get,
recipient=employee.employee_user_id,
verb=f"You have been assigned to a new Ticket-{ticket}.",
verb_ar=f"لقد تم تعيينك لتذكرة جديدة {ticket}.",
verb_de=f"Ihnen wurde ein neues Ticket {ticket} zugewiesen.",
verb_es=f"Se te ha asignado un nuevo ticket {ticket}.",
verb_fr=f"Un nouveau ticket {ticket} vous a été attribué.",
icon="infinite",
redirect=reverse("ticket-detail", kwargs={"ticket_id": ticket.id}),
)
except Exception as e:
logger.error(e)
if not ticket.employee_id == ticket.created_by.employee_get:
for emp in [ticket.created_by.employee_get, ticket.employee_id]:
try:
notify.send(
request.user.employee_get,
recipient=emp.employee_user_id,
verb=f"{employee} assigned to your ticket - {ticket}.",
verb_ar=f"تم تعيين {employee} إلى تذكرتك - {ticket}.",
verb_de=f"{employee} wurde Ihrem Ticket {ticket} zugewiesen.",
verb_es=f"{employee} ha sido asignado a tu ticket - {ticket}.",
verb_fr=f"{employee} a été assigné à votre ticket - {ticket}.",
icon="infinite",
redirect=reverse(
"ticket-detail", kwargs={"ticket_id": ticket.id}
),
)
except Exception as e:
logger.error(e)
try:
notify.send(
request.user.employee_get,
recipient=ticket.employee_id.employee_user_id,
verb=f"{employee} assigned to your ticket - {ticket}.",
verb_ar=f"تم تعيين {employee} إلى تذكرتك - {ticket}.",
verb_de=f"{employee} wurde Ihrem Ticket {ticket} zugewiesen.",
verb_es=f"{employee} ha sido asignado a tu ticket - {ticket}.",
verb_fr=f"{employee} a été assigné à votre ticket - {ticket}.",
icon="infinite",
redirect=reverse("ticket-detail", kwargs={"ticket_id": ticket.id}),
)
except Exception as e:
logger.error(e)
else:
# message
message = _("Claim request rejected successfully.")
refresh = True
if employee in ticket.assigned_to.all():
ticket.assigned_to.remove(employee) # Reject and remove from assignment
# send notification
notify.send(
request.user.employee_get,
recipient=employee.employee_user_id,
verb=f"Your claim request is rejected for Ticket-{ticket}",
verb_ar=f"تم رفض طلبك للمطالبة بالتذكرة {ticket}.",
verb_de=f"Ihre Anspruchsanfrage für Ticket-{ticket} wurde abgelehnt.",
verb_es=f"Tu solicitud de reclamación ha sido rechazada para el ticket {ticket}.",
verb_fr=f"Votre demande de réclamation pour le ticket {ticket} a été rejetée.",
icon="infinite",
)
ticket.save()
claim_request.is_approved = approve
claim_request.is_rejected = not approve
claim_request.save()
html = render_to_string(
"helpdesk/ticket/ticket_claim_requests.html",
{"claim_requests": ticket.claimrequest_set.all(), "refresh": refresh},
)
messages.success(request, message)
return HttpResponse(html)
@login_required
def tickets_select_filter(request):
"""
@@ -1142,7 +1426,7 @@ def tickets_bulk_archive(request):
@login_required
# @ticket_owner_can_enter("perms.helpdesk.helpdesk_changeticket", Ticket)
# @ticket_owner_can_enter("perms.helpdesk.helpdesk_change_ticket", Ticket)
@permission_required("helpdesk.delete_ticket")
def tickets_bulk_delete(request):
"""
@@ -1246,7 +1530,7 @@ def update_department_manager(request, dep_id):
def delete_department_manager(request, dep_id):
department_manager = DepartmentManager.objects.get(id=dep_id)
department_manager.delete()
messages.error(request, _("The department manager has been deleted successfully"))
messages.success(request, _("The department manager has been deleted successfully"))
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
@@ -1257,18 +1541,36 @@ def update_priority(request, ticket_id):
This function is used to update the priority
from the detailed view
"""
ti = Ticket.objects.get(id=ticket_id)
ticket = Ticket.objects.get(id=ticket_id)
if (
request.user.has_perm("helpdesk.view_ticket")
or ticket.employee_id.get_reporting_manager() == request.user.employee_get
or is_department_manager(request, ticket)
or request.user.employee_get == ticket.employee_id
or request.user.employee_get in ticket.assigned_to.all()
):
rating = request.POST.get("rating")
if rating == "1":
ti.priority = "low"
ticket.priority = "low"
elif rating == "2":
ti.priority = "medium"
ticket.priority = "medium"
else:
ti.priority = "high"
ti.save()
ticket.priority = "high"
ticket.save()
messages.success(request, _("Priority updated successfully."))
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
else:
messages.info(request, _("You don't have permission."))
previous_url = request.META.get("HTTP_REFERER", "/")
# Handle request for HTMX if needed
if "HTTP_HX_REQUEST" in request.META:
return render(request, "decorator_404.html")
else:
return HttpResponse(
f'<script>window.location.href = "{previous_url}"</script>'
)
@login_required
@@ -1356,6 +1658,7 @@ def ticket_type_delete(request, t_type_id):
@login_required
@permission_required("helpdesk.view_departmentmanager")
def view_department_managers(request):
department_managers = DepartmentManager.objects.all()
@@ -1363,3 +1666,26 @@ def view_department_managers(request):
"department_managers": department_managers,
}
return render(request, "department_managers/department_managers.html", context)
@login_required
@permission_required("helpdesk.change_departmentmanager")
def get_department_employees(request):
"""
Method to return employee in the department
"""
department = (
Department.objects.filter(id=request.GET.get("dep_id")).first()
if request.GET.get("dep_id")
else None
)
if department:
employees_queryset = department.employeeworkinformation_set.all().values_list(
"employee_id__id", "employee_id__employee_first_name"
)
else:
employees_queryset = None
employees = list(employees_queryset)
context = {"employees": employees}
employee_html = render_to_string("employee/employees_select.html", context)
return HttpResponse(employee_html)