[FIX] HELPDESK: Permission for department manager added
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from distutils.util import strtobool
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from urllib.parse import parse_qs
|
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.db.models import ProtectedError, Q
|
||||||
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
|
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.decorators.http import require_http_methods
|
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 base.models import Department, JobPosition, Tags
|
||||||
from employee.models import Employee
|
from employee.models import Employee
|
||||||
|
from employee.views import get_content_type
|
||||||
from helpdesk.decorators import ticket_owner_can_enter
|
from helpdesk.decorators import ticket_owner_can_enter
|
||||||
from helpdesk.filter import FAQCategoryFilter, FAQFilter, TicketFilter, TicketReGroup
|
from helpdesk.filter import FAQCategoryFilter, FAQFilter, TicketFilter, TicketReGroup
|
||||||
from helpdesk.forms import (
|
from helpdesk.forms import (
|
||||||
@@ -37,10 +42,12 @@ from helpdesk.forms import (
|
|||||||
TicketTagForm,
|
TicketTagForm,
|
||||||
TicketTypeForm,
|
TicketTypeForm,
|
||||||
)
|
)
|
||||||
|
from helpdesk.methods import is_department_manager
|
||||||
from helpdesk.models import (
|
from helpdesk.models import (
|
||||||
FAQ,
|
FAQ,
|
||||||
TICKET_STATUS,
|
TICKET_STATUS,
|
||||||
Attachment,
|
Attachment,
|
||||||
|
ClaimRequest,
|
||||||
Comment,
|
Comment,
|
||||||
DepartmentManager,
|
DepartmentManager,
|
||||||
FAQCategory,
|
FAQCategory,
|
||||||
@@ -57,6 +64,8 @@ from horilla.decorators import (
|
|||||||
from horilla.group_by import group_by_queryset
|
from horilla.group_by import group_by_queryset
|
||||||
from notifications.signals import notify
|
from notifications.signals import notify
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
|
|
||||||
@@ -377,11 +386,10 @@ def ticket_view(request):
|
|||||||
Parameters:
|
Parameters:
|
||||||
request (HttpRequest): The HTTP request object.
|
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
|
employee = request.user.employee_get
|
||||||
previous_data = request.GET.urlencode()
|
previous_data = request.GET.urlencode()
|
||||||
if request.method == "GET":
|
|
||||||
tickets = TicketFilter(request.GET).qs
|
|
||||||
my_page_number = request.GET.get("my_page")
|
my_page_number = request.GET.get("my_page")
|
||||||
all_page_number = request.GET.get("all_page")
|
all_page_number = request.GET.get("all_page")
|
||||||
allocated_page_number = request.GET.get("allocated_page")
|
allocated_page_number = request.GET.get("allocated_page")
|
||||||
@@ -422,7 +430,7 @@ def ticket_view(request):
|
|||||||
"f": TicketFilter(request.GET),
|
"f": TicketFilter(request.GET),
|
||||||
"gp_fields": TicketReGroup.fields,
|
"gp_fields": TicketReGroup.fields,
|
||||||
"ticket_status": TICKET_STATUS,
|
"ticket_status": TICKET_STATUS,
|
||||||
"view": request.GET.get("view"),
|
"view": view,
|
||||||
"today": datetime.today().date(),
|
"today": datetime.today().date(),
|
||||||
"filter_dict": data_dict,
|
"filter_dict": data_dict,
|
||||||
}
|
}
|
||||||
@@ -444,10 +452,14 @@ def ticket_create(request):
|
|||||||
POST : return Ticket view
|
POST : return Ticket view
|
||||||
"""
|
"""
|
||||||
|
|
||||||
form = TicketForm(initial={"employee_id": request.user})
|
form = TicketForm()
|
||||||
if request.GET.get("status"):
|
if request.GET.get("status"):
|
||||||
status = 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":
|
if request.method == "POST":
|
||||||
form = TicketForm(request.POST, request.FILES)
|
form = TicketForm(request.POST, request.FILES)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
@@ -489,7 +501,6 @@ def ticket_create(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@hx_request_required
|
@hx_request_required
|
||||||
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
|
|
||||||
def ticket_update(request, ticket_id):
|
def ticket_update(request, ticket_id):
|
||||||
"""
|
"""
|
||||||
This function is responsible for updating the Ticket.
|
This function is responsible for updating the Ticket.
|
||||||
@@ -503,27 +514,44 @@ def ticket_update(request, ticket_id):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
ticket = Ticket.objects.get(id=ticket_id)
|
ticket = Ticket.objects.get(id=ticket_id)
|
||||||
form = TicketForm(instance=ticket)
|
if (
|
||||||
if request.method == "POST":
|
request.user.has_perm("helpdesk.change_ticket")
|
||||||
form = TicketForm(request.POST, request.FILES, instance=ticket)
|
or is_department_manager(request, ticket)
|
||||||
if form.is_valid():
|
or request.user.employee_get == ticket.employee_id
|
||||||
ticket = form.save()
|
or request.user.employee_get in ticket.assigned_to.all()
|
||||||
attachments = form.files.getlist("attachment")
|
):
|
||||||
for attachment in attachments:
|
form = TicketForm(instance=ticket)
|
||||||
attachment_instance = Attachment(file=attachment, ticket=ticket)
|
if request.method == "POST":
|
||||||
attachment_instance.save()
|
form = TicketForm(request.POST, request.FILES, instance=ticket)
|
||||||
messages.success(request, _("The Ticket updated successfully."))
|
if form.is_valid():
|
||||||
return HttpResponse("<script>window.location.reload()</script>")
|
ticket = form.save()
|
||||||
context = {
|
attachments = form.files.getlist("attachment")
|
||||||
"form": form,
|
for attachment in attachments:
|
||||||
"ticket_id": ticket_id,
|
attachment_instance = Attachment(file=attachment, ticket=ticket)
|
||||||
"t_type_form": TicketTypeForm(),
|
attachment_instance.save()
|
||||||
}
|
messages.success(request, _("The Ticket updated successfully."))
|
||||||
return render(request, "helpdesk/ticket/ticket_form.html", context)
|
return HttpResponse("<script>window.location.reload()</script>")
|
||||||
|
context = {
|
||||||
|
"form": form,
|
||||||
|
"ticket_id": 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
|
@login_required
|
||||||
@permission_required("helpdesk.change_ticket")
|
|
||||||
def ticket_archive(request, ticket_id):
|
def ticket_archive(request, ticket_id):
|
||||||
"""
|
"""
|
||||||
This function is responsible for archiving the Ticket.
|
This function is responsible for archiving the Ticket.
|
||||||
@@ -536,15 +564,37 @@ def ticket_archive(request, ticket_id):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
ticket = Ticket.objects.get(id=ticket_id)
|
ticket = Ticket.objects.get(id=ticket_id)
|
||||||
if ticket.is_active:
|
|
||||||
ticket.is_active = False
|
# 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()
|
ticket.save()
|
||||||
messages.success(request, _("The Ticket archived successfully."))
|
|
||||||
|
if ticket.is_active:
|
||||||
|
messages.success(request, _("The Ticket un-archived successfully."))
|
||||||
|
else:
|
||||||
|
messages.success(request, _("The Ticket archived successfully."))
|
||||||
|
|
||||||
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ticket.is_active = True
|
messages.info(request, _("You don't have permission."))
|
||||||
ticket.save()
|
|
||||||
messages.success(request, _("The Ticket un-archived successfully."))
|
previous_url = request.META.get("HTTP_REFERER", "/")
|
||||||
return HttpResponseRedirect(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
|
@login_required
|
||||||
@@ -620,7 +670,7 @@ def change_ticket_status(request, ticket_id):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@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):
|
def ticket_delete(request, ticket_id):
|
||||||
"""
|
"""
|
||||||
This function is responsible for deleting the Ticket.
|
This function is responsible for deleting the Ticket.
|
||||||
@@ -634,37 +684,40 @@ def ticket_delete(request, ticket_id):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
ticket = Ticket.objects.get(id=ticket_id)
|
ticket = Ticket.objects.get(id=ticket_id)
|
||||||
|
if ticket.status == "new":
|
||||||
mail_thread = TicketSendThread(
|
mail_thread = TicketSendThread(
|
||||||
request,
|
request,
|
||||||
ticket,
|
ticket,
|
||||||
type="delete",
|
type="delete",
|
||||||
)
|
)
|
||||||
mail_thread.start()
|
mail_thread.start()
|
||||||
employees = ticket.assigned_to.all()
|
employees = ticket.assigned_to.all()
|
||||||
assignees = [employee.employee_user_id for employee in employees]
|
assignees = [employee.employee_user_id for employee in employees]
|
||||||
assignees.append(ticket.employee_id.employee_user_id)
|
assignees.append(ticket.employee_id.employee_user_id)
|
||||||
if hasattr(ticket.get_raised_on_object(), "dept_manager"):
|
if hasattr(ticket.get_raised_on_object(), "dept_manager"):
|
||||||
if ticket.get_raised_on_object().dept_manager.all():
|
if ticket.get_raised_on_object().dept_manager.all():
|
||||||
manager = (
|
manager = (
|
||||||
ticket.get_raised_on_object().dept_manager.all().first().manager
|
ticket.get_raised_on_object().dept_manager.all().first().manager
|
||||||
)
|
)
|
||||||
assignees.append(manager.employee_user_id)
|
assignees.append(manager.employee_user_id)
|
||||||
notify.send(
|
notify.send(
|
||||||
request.user.employee_get,
|
request.user.employee_get,
|
||||||
recipient=assignees,
|
recipient=assignees,
|
||||||
verb=f"The ticket has been deleted.",
|
verb=f"The ticket has been deleted.",
|
||||||
verb_ar="تم حذف التذكرة.",
|
verb_ar="تم حذف التذكرة.",
|
||||||
verb_de="Das Ticket wurde gelöscht",
|
verb_de="Das Ticket wurde gelöscht",
|
||||||
verb_es="El billete ha sido eliminado.",
|
verb_es="El billete ha sido eliminado.",
|
||||||
verb_fr="Le ticket a été supprimé.",
|
verb_fr="Le ticket a été supprimé.",
|
||||||
icon="infinite",
|
icon="infinite",
|
||||||
redirect=reverse("ticket-view"),
|
redirect=reverse("ticket-view"),
|
||||||
)
|
)
|
||||||
ticket.delete()
|
ticket.delete()
|
||||||
messages.success(
|
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:
|
except ProtectedError:
|
||||||
messages.error(request, _("You cannot delete this Ticket."))
|
messages.error(request, _("You cannot delete this Ticket."))
|
||||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||||
@@ -709,17 +762,17 @@ def ticket_filter(request):
|
|||||||
my_page_number = request.GET.get("my_page")
|
my_page_number = request.GET.get("my_page")
|
||||||
all_page_number = request.GET.get("all_page")
|
all_page_number = request.GET.get("all_page")
|
||||||
allocated_page_number = request.GET.get("allocated_page")
|
allocated_page_number = request.GET.get("allocated_page")
|
||||||
tickets_items1 = []
|
tickets_items1 = Ticket.objects.none()
|
||||||
tickets_items2 = []
|
tickets_items2 = Ticket.objects.none()
|
||||||
|
|
||||||
my_tickets = tickets.filter(employee_id=request.user.employee_get).order_by(
|
my_tickets = tickets.filter(employee_id=request.user.employee_get) | tickets.filter(
|
||||||
"-created_date"
|
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")
|
all_tickets = filtersubordinates(request, tickets, "helpdesk.add_tickets")
|
||||||
|
|
||||||
allocated_tickets = []
|
allocated_tickets = Ticket.objects.none()
|
||||||
user = request.user.employee_get
|
user = request.user.employee_get
|
||||||
department = user.employee_work_info.department_id
|
department = user.employee_work_info.department_id
|
||||||
job_position = user.employee_work_info.job_position_id
|
job_position = user.employee_work_info.job_position_id
|
||||||
@@ -795,149 +848,242 @@ def ticket_filter(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
|
|
||||||
def ticket_detail(request, ticket_id, **kwargs):
|
def ticket_detail(request, ticket_id, **kwargs):
|
||||||
today = datetime.now().date()
|
|
||||||
ticket = Ticket.objects.get(id=ticket_id)
|
ticket = Ticket.objects.get(id=ticket_id)
|
||||||
c_form = CommentForm()
|
if (
|
||||||
f_form = AttachmentForm()
|
request.user.has_perm("helpdesk.view_ticket")
|
||||||
attachments = ticket.ticket_attachment.all()
|
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()
|
||||||
|
|
||||||
activity_list = []
|
activity_list = []
|
||||||
comments = ticket.comment.all()
|
comments = ticket.comment.all()
|
||||||
trackings = ticket.tracking()
|
trackings = ticket.tracking()
|
||||||
for comment in comments:
|
for comment in comments:
|
||||||
activity_list.append(
|
activity_list.append(
|
||||||
{"type": "comment", "comment": comment, "date": comment.date}
|
{"type": "comment", "comment": comment, "date": comment.date}
|
||||||
)
|
)
|
||||||
for history in trackings:
|
for history in trackings:
|
||||||
activity_list.append(
|
activity_list.append(
|
||||||
{
|
{
|
||||||
"type": "history",
|
"type": "history",
|
||||||
"history": history,
|
"history": history,
|
||||||
"date": history["pair"][0].history_date,
|
"date": history["pair"][0].history_date,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
sorted_activity_list = sorted(activity_list, key=itemgetter("date"))
|
sorted_activity_list = sorted(activity_list, key=itemgetter("date"))
|
||||||
|
|
||||||
color = "success"
|
color = "success"
|
||||||
remaining_days = ticket.deadline - today
|
remaining_days = ticket.deadline - today
|
||||||
remaining = f"Due in {remaining_days.days} days"
|
remaining = f"Due in {remaining_days.days} days"
|
||||||
if remaining_days.days < 0:
|
if remaining_days.days < 0:
|
||||||
remaining = f"{abs(remaining_days.days)} days overdue"
|
remaining = f"{abs(remaining_days.days)} days overdue"
|
||||||
color = "danger"
|
color = "danger"
|
||||||
elif remaining_days.days == 0:
|
elif remaining_days.days == 0:
|
||||||
remaining = "Due Today"
|
remaining = "Due Today"
|
||||||
color = "warning"
|
color = "warning"
|
||||||
|
|
||||||
rating = ""
|
rating = ""
|
||||||
if ticket.priority == "low":
|
if ticket.priority == "low":
|
||||||
rating = "1"
|
rating = "1"
|
||||||
elif ticket.priority == "medium":
|
elif ticket.priority == "medium":
|
||||||
rating = "2"
|
rating = "2"
|
||||||
|
else:
|
||||||
|
rating = "3"
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"ticket": ticket,
|
||||||
|
"c_form": c_form,
|
||||||
|
"f_form": f_form,
|
||||||
|
"attachments": attachments,
|
||||||
|
"ticket_status": TICKET_STATUS,
|
||||||
|
"tag_form": TicketTagForm(instance=ticket),
|
||||||
|
"sorted_activity_list": sorted_activity_list,
|
||||||
|
"create_tag_f": TagsForm(),
|
||||||
|
"color": color,
|
||||||
|
"remaining": remaining,
|
||||||
|
"rating": rating,
|
||||||
|
}
|
||||||
|
return render(request, "helpdesk/ticket/ticket_detail.html", context=context)
|
||||||
else:
|
else:
|
||||||
rating = "3"
|
messages.info(request, _("You don't have permission."))
|
||||||
|
previous_url = request.META.get("HTTP_REFERER", "/")
|
||||||
|
|
||||||
context = {
|
# Handle request for HTMX if needed
|
||||||
"ticket": ticket,
|
if "HTTP_HX_REQUEST" in request.META:
|
||||||
"c_form": c_form,
|
return render(request, "decorator_404.html")
|
||||||
"f_form": f_form,
|
else:
|
||||||
"attachments": attachments,
|
return HttpResponse(
|
||||||
"ticket_status": TICKET_STATUS,
|
f'<script>window.location.href = "{previous_url}"</script>'
|
||||||
"tag_form": TicketTagForm(instance=ticket),
|
)
|
||||||
"sorted_activity_list": sorted_activity_list,
|
|
||||||
"create_tag_f": TagsForm(),
|
|
||||||
"color": color,
|
@login_required
|
||||||
"remaining": remaining,
|
def ticket_individual_view(request, ticket_id):
|
||||||
"rating": rating,
|
ticket = Ticket.objects.filter(id=ticket_id).first()
|
||||||
}
|
context = {
|
||||||
return render(request, "helpdesk/ticket/ticket_detail.html", context=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
|
@login_required
|
||||||
# @ticket_owner_can_enter("perms.helpdesk.helpdesk_changeticket", Ticket)
|
|
||||||
def ticket_update_tag(request):
|
def ticket_update_tag(request):
|
||||||
"""
|
"""
|
||||||
method to update the tags of ticket
|
method to update the tags of ticket
|
||||||
"""
|
"""
|
||||||
data = request.GET
|
data = request.GET
|
||||||
ticket = Ticket.objects.get(id=data["ticketId"])
|
ticket = Ticket.objects.get(id=data["ticketId"])
|
||||||
tagids = data.getlist("selectedValues[]")
|
if (
|
||||||
ticket.tags.clear()
|
request.user.has_perm("helpdesk.view_ticket")
|
||||||
for tagId in tagids:
|
or request.user.employee_get == ticket.employee_id
|
||||||
tag = Tags.objects.get(id=tagId)
|
or is_department_manager(request, ticket)
|
||||||
ticket.tags.add(tag)
|
):
|
||||||
response = {
|
tagids = data.getlist("selectedValues[]")
|
||||||
"type": "success",
|
ticket.tags.clear()
|
||||||
"message": _("The Ticket tag updated successfully."),
|
for tagId in tagids:
|
||||||
}
|
tag = Tags.objects.get(id=tagId)
|
||||||
return JsonResponse(response)
|
ticket.tags.add(tag)
|
||||||
|
response = {
|
||||||
|
"type": "success",
|
||||||
|
"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
|
@login_required
|
||||||
@hx_request_required
|
@hx_request_required
|
||||||
@ticket_owner_can_enter(perm="helpdesk.change_ticket", model=Ticket)
|
|
||||||
def ticket_change_raised_on(request, ticket_id):
|
def ticket_change_raised_on(request, ticket_id):
|
||||||
ticket = Ticket.objects.get(id=ticket_id)
|
ticket = Ticket.objects.get(id=ticket_id)
|
||||||
form = TicketRaisedOnForm(instance=ticket)
|
if (
|
||||||
if request.method == "POST":
|
request.user.has_perm("helpdesk.view_ticket")
|
||||||
form = TicketRaisedOnForm(request.POST, instance=ticket)
|
or request.user.employee_get == ticket.employee_id
|
||||||
if form.is_valid():
|
):
|
||||||
form.save()
|
form = TicketRaisedOnForm(instance=ticket)
|
||||||
messages.success(request, _("Responsibility updated for the Ticket"))
|
if request.method == "POST":
|
||||||
return redirect(ticket_detail, ticket_id=ticket_id)
|
form = TicketRaisedOnForm(request.POST, instance=ticket)
|
||||||
return render(
|
if form.is_valid():
|
||||||
request,
|
form.save()
|
||||||
"helpdesk/ticket/forms/change_raised_on.html",
|
messages.success(request, _("Responsibility updated for the Ticket"))
|
||||||
{"form": form, "ticket_id": ticket_id},
|
return redirect(ticket_detail, ticket_id=ticket_id)
|
||||||
)
|
return render(
|
||||||
|
request,
|
||||||
|
"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
|
@login_required
|
||||||
@hx_request_required
|
@hx_request_required
|
||||||
@manager_can_enter("helpdesk.change_ticket")
|
|
||||||
def ticket_change_assignees(request, ticket_id):
|
def ticket_change_assignees(request, ticket_id):
|
||||||
ticket = Ticket.objects.get(id=ticket_id)
|
ticket = Ticket.objects.get(id=ticket_id)
|
||||||
prev_assignee_ids = ticket.assigned_to.values_list("id", flat=True)
|
if request.user.has_perm("helpdesk.change_ticket") or is_department_manager(
|
||||||
form = TicketAssigneesForm(instance=ticket)
|
request, ticket
|
||||||
if request.method == "POST":
|
):
|
||||||
form = TicketAssigneesForm(request.POST, instance=ticket)
|
prev_assignee_ids = ticket.assigned_to.values_list("id", flat=True)
|
||||||
if form.is_valid():
|
form = TicketAssigneesForm(instance=ticket)
|
||||||
form.save(commit=False)
|
if request.method == "POST":
|
||||||
|
form = TicketAssigneesForm(request.POST, instance=ticket)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save(commit=False)
|
||||||
|
|
||||||
new_assignee_ids = form.cleaned_data["assigned_to"].values_list(
|
new_assignee_ids = form.cleaned_data["assigned_to"].values_list(
|
||||||
"id", flat=True
|
"id", flat=True
|
||||||
|
)
|
||||||
|
added_assignee_ids = set(new_assignee_ids) - set(prev_assignee_ids)
|
||||||
|
removed_assignee_ids = set(prev_assignee_ids) - set(new_assignee_ids)
|
||||||
|
added_assignees = Employee.objects.filter(id__in=added_assignee_ids)
|
||||||
|
removed_assignees = Employee.objects.filter(id__in=removed_assignee_ids)
|
||||||
|
|
||||||
|
form.save()
|
||||||
|
|
||||||
|
mail_thread = AddAssigneeThread(
|
||||||
|
request,
|
||||||
|
ticket,
|
||||||
|
added_assignees,
|
||||||
|
)
|
||||||
|
mail_thread.start()
|
||||||
|
mail_thread = RemoveAssigneeThread(
|
||||||
|
request,
|
||||||
|
ticket,
|
||||||
|
removed_assignees,
|
||||||
|
)
|
||||||
|
mail_thread.start()
|
||||||
|
|
||||||
|
messages.success(request, _("Assinees updated for the Ticket"))
|
||||||
|
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>'
|
||||||
)
|
)
|
||||||
added_assignee_ids = set(new_assignee_ids) - set(prev_assignee_ids)
|
|
||||||
removed_assignee_ids = set(prev_assignee_ids) - set(new_assignee_ids)
|
|
||||||
added_assignees = Employee.objects.filter(id__in=added_assignee_ids)
|
|
||||||
removed_assignees = Employee.objects.filter(id__in=removed_assignee_ids)
|
|
||||||
|
|
||||||
form.save()
|
|
||||||
|
|
||||||
mail_thread = AddAssigneeThread(
|
|
||||||
request,
|
|
||||||
ticket,
|
|
||||||
added_assignees,
|
|
||||||
)
|
|
||||||
mail_thread.start()
|
|
||||||
mail_thread = RemoveAssigneeThread(
|
|
||||||
request,
|
|
||||||
ticket,
|
|
||||||
removed_assignees,
|
|
||||||
)
|
|
||||||
mail_thread.start()
|
|
||||||
|
|
||||||
messages.success(request, _("Assinees updated for the Ticket"))
|
|
||||||
|
|
||||||
return redirect(ticket_detail, ticket_id=ticket_id)
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"helpdesk/ticket/forms/change_assinees.html",
|
|
||||||
{"form": form, "ticket_id": ticket_id},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -984,6 +1130,41 @@ def remove_tag(request):
|
|||||||
return JsonResponse({"message": message, "type": type})
|
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
|
@login_required
|
||||||
def comment_create(request, ticket_id):
|
def comment_create(request, ticket_id):
|
||||||
""" "
|
""" "
|
||||||
@@ -1030,14 +1211,14 @@ def comment_edit(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def comment_delete(request, comment_id):
|
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"):
|
if not request.user.has_perm("helpdesk.delete_comment"):
|
||||||
comment = comment.filter(employee_id__employee_user_id=request.user)
|
comment = comment.filter(employee_id__employee_user_id=request.user)
|
||||||
comment.delete()
|
comment.delete()
|
||||||
messages.success(
|
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", "/"))
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||||
|
|
||||||
|
|
||||||
@@ -1077,13 +1258,116 @@ def get_raised_on(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def claim_ticket(request, id):
|
def claim_ticket(request, id):
|
||||||
|
"""
|
||||||
|
This is a function to create a claim request for requested employee
|
||||||
|
"""
|
||||||
ticket = Ticket.objects.get(id=id)
|
ticket = Ticket.objects.get(id=id)
|
||||||
if ticket.employee_id != request.user.employee_get:
|
if not ClaimRequest.objects.filter(
|
||||||
ticket.assigned_to.set([request.user.employee_get])
|
employee_id=request.user.employee_get, ticket_id=ticket
|
||||||
ticket.save()
|
).exists():
|
||||||
|
ClaimRequest(employee_id=request.user.employee_get, ticket_id=ticket).save()
|
||||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
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
|
@login_required
|
||||||
def tickets_select_filter(request):
|
def tickets_select_filter(request):
|
||||||
"""
|
"""
|
||||||
@@ -1142,7 +1426,7 @@ def tickets_bulk_archive(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@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")
|
@permission_required("helpdesk.delete_ticket")
|
||||||
def tickets_bulk_delete(request):
|
def tickets_bulk_delete(request):
|
||||||
"""
|
"""
|
||||||
@@ -1246,7 +1530,7 @@ def update_department_manager(request, dep_id):
|
|||||||
def delete_department_manager(request, dep_id):
|
def delete_department_manager(request, dep_id):
|
||||||
department_manager = DepartmentManager.objects.get(id=dep_id)
|
department_manager = DepartmentManager.objects.get(id=dep_id)
|
||||||
department_manager.delete()
|
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", "/"))
|
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
|
This function is used to update the priority
|
||||||
from the detailed view
|
from the detailed view
|
||||||
"""
|
"""
|
||||||
ti = Ticket.objects.get(id=ticket_id)
|
ticket = Ticket.objects.get(id=ticket_id)
|
||||||
rating = request.POST.get("rating")
|
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":
|
if rating == "1":
|
||||||
ti.priority = "low"
|
ticket.priority = "low"
|
||||||
elif rating == "2":
|
elif rating == "2":
|
||||||
ti.priority = "medium"
|
ticket.priority = "medium"
|
||||||
|
else:
|
||||||
|
ticket.priority = "high"
|
||||||
|
ticket.save()
|
||||||
|
messages.success(request, _("Priority updated successfully."))
|
||||||
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||||
else:
|
else:
|
||||||
ti.priority = "high"
|
messages.info(request, _("You don't have permission."))
|
||||||
ti.save()
|
previous_url = request.META.get("HTTP_REFERER", "/")
|
||||||
messages.success(request, _("Priority updated successfully."))
|
|
||||||
return HttpResponseRedirect(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
|
@login_required
|
||||||
@@ -1356,6 +1658,7 @@ def ticket_type_delete(request, t_type_id):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@permission_required("helpdesk.view_departmentmanager")
|
||||||
def view_department_managers(request):
|
def view_department_managers(request):
|
||||||
department_managers = DepartmentManager.objects.all()
|
department_managers = DepartmentManager.objects.all()
|
||||||
|
|
||||||
@@ -1363,3 +1666,26 @@ def view_department_managers(request):
|
|||||||
"department_managers": department_managers,
|
"department_managers": department_managers,
|
||||||
}
|
}
|
||||||
return render(request, "department_managers/department_managers.html", context)
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user