2025-03-22 15:29:19 -10:00

115 lines
4.0 KiB
Python

#!/usr/bin/python
"""
django-helpdesk - A Django powered ticket tracker for small enterprise.
(c) Copyright 2008 Jutda. All Rights Reserved. See LICENSE for details.
scripts/escalate_tickets.py - Easy way to escalate tickets based on their age,
designed to be run from Cron or similar.
"""
from datetime import date, timedelta
from django.core.management.base import BaseCommand
from django.db.models import Q
from django.utils import timezone
from django.utils.translation import gettext as _
from helpdesk.lib import safe_template_context
from helpdesk.models import EscalationExclusion, Queue, Ticket
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
"-q",
"--queues",
nargs="*",
choices=list(Queue.objects.values_list("slug", flat=True)),
help="Queues to include (default: all). Enter the queues slug as space separated list.",
)
parser.add_argument(
"-x",
"--escalate-verbosely",
action="store_true",
default=False,
help="Display escalated tickets",
)
parser.add_argument(
"-n",
"--notify-only",
action="store_true",
default=False,
help="Send email reminder but dont escalate tickets",
)
def handle(self, *args, **options):
verbose = options["escalate_verbosely"]
notify_only = options["notify_only"]
queue_slugs = options["queues"]
# Only include queues with escalation configured
queues = Queue.objects.filter(escalate_days__isnull=False).exclude(
escalate_days=0
)
if queue_slugs is not None:
queues = queues.filter(slug__in=queue_slugs)
if verbose:
self.stdout.write(f"Processing: {queues}")
for queue in queues:
last = date.today() - timedelta(days=queue.escalate_days)
today = date.today()
workdate = last
days = 0
while workdate < today:
if not EscalationExclusion.objects.filter(date=workdate).exists():
days += 1
workdate = workdate + timedelta(days=1)
req_last_escl_date = timezone.now() - timedelta(days=days)
for ticket in (
queue.ticket_set.filter(status__in=Ticket.OPEN_STATUSES)
.exclude(priority=1)
.filter(Q(on_hold__isnull=True) | Q(on_hold=False))
.filter(
Q(last_escalation__lte=req_last_escl_date)
| Q(last_escalation__isnull=True, created__lte=req_last_escl_date)
)
):
ticket.last_escalation = timezone.now()
ticket.priority -= 1
ticket.save()
context = safe_template_context(ticket)
ticket.send(
{
"submitter": ("escalated_submitter", context),
"ticket_cc": ("escalated_cc", context),
"assigned_to": ("escalated_owner", context),
},
fail_silently=True,
)
if verbose:
self.stdout.write(
f" - Esclating {ticket.ticket} from {ticket.priority + 1}>{ticket.priority}"
)
if not notify_only:
followup = ticket.followup_set.create(
title=_("Ticket Escalated"),
public=True,
comment=_("Ticket escalated after %(nb)s days")
% {"nb": queue.escalate_days},
)
followup.ticketchange_set.create(
field=_("Priority"),
old_value=ticket.priority + 1,
new_value=ticket.priority,
)