* Fixed svn:keywords

* Added escalation system that allows certain days to be excluded from escalation
* New script to automatically create exclusions on user-defined days, eg easily add a years worth of saturdays & sundays to the exclusion system
This commit is contained in:
Ross Poulton
2008-01-22 05:54:22 +00:00
parent 0f3c979650
commit 274b9300f4
4 changed files with 204 additions and 21 deletions

View File

@ -0,0 +1,114 @@
""" ..
.,::;::::::
..,::::::::,,,,::: Jutda Helpdesk - A Django
.,,::::::,,,,,,,,,,,,,:: powered ticket tracker for
.,::::::,,,,,,,,,,,,,,,,,,:;r. small enterprise
.::::,,,,,,,,,,,,,,,,,,,,,,:;;rr.
.:::,,,,,,,,,,,,,,,,,,,,,,,:;;;;;rr (c) Copyright 2008
.:::,,,,,,,,,,,,,,,,,,,,,,,:;;;:::;;rr
.:::,,,,,,,,,,,,,,,,,,,,. ,;;;::::::;;rr Jutda
.:::,,,,,,,,,,,,,,,,,,. .:;;:::::::::;;rr
.:::,,,,,,,,,,,,,,,. .;r;::::::::::::;r; All Rights Reserved
.:::,,,,,,,,,,,,,,, .;r;;:::::::::::;;:.
.:::,,,,,,,,,,,,,,,. .;r;;::::::::::::;:.
.;:,,,,,,,,,,,,,,, .,;rr;::::::::::::;:. This software is released
.,:,,,,,,,,,,,,,. .,:;rrr;;::::::::::::;;. under a limited-use license that
:,,,,,,,,,,,,,..:;rrrrr;;;::::::::::::;;. allows you to freely download this
:,,,,,,,:::;;;rr;;;;;;:::::::::::::;;, software from it's manufacturer and
::::;;;;;;;;;;;:::::::::::::::::;;, use it yourself, however you may not
.r;;;;:::::::::::::::::::::::;;;, distribute it. For further details, see
.r;::::::::::::::::::::;;;;;:, the enclosed LICENSE file.
.;;::::::::::::::;;;;;:,.
.;;:::::::;;;;;;:,. Please direct people who wish to download this
.r;;;;;;;;:,. software themselves to www.jutda.com.au.
,,,..
$Id$
"""
from datetime import datetime, timedelta, date
from django.db.models import Q
from helpdesk.models import EscalationExclusion, Queue
import sys, getopt
day_names = {
'monday': 0,
'tuesday': 1,
'wednesday': 2,
'thursday': 3,
'friday': 4,
'saturday': 5,
'sunday': 6,
}
def create_exclusions(days, occurrences, verbose, queues):
days = days.split(',')
for day in days:
day_name = day
day = day_names[day]
workdate = date.today()
i = 0
while i < occurrences:
if day == workdate.weekday():
if EscalationExclusion.objects.filter(date=workdate).count() == 0:
esc = EscalationExclusion(name='Auto Exclusion for %s' % day_name, date=workdate)
esc.save()
if verbose:
print "Created exclusion for %s %s" % (day_name, workdate)
for q in queues:
esc.queues.add(q)
if verbose:
print " - for queue %s" % q
i += 1
workdate += timedelta(days=1)
def usage():
print "Options:"
print " --days, -d: Days of week (monday, tuesday, etc)"
print " --occurrences, -o: Occurrences: How many weeks ahead to exclude this day"
print " --queues, -q: Queues to include (default: all). Use queue slugs"
print " --verbose, -v: Display a list of dates excluded"
if __name__ == '__main__':
try:
opts, args = getopt.getopt(sys.argv[1:], 'd:o:q:v', ['days=', 'occurrences=', 'verbose', 'queues='])
except getopt.GetoptError:
usage()
sys.exit(2)
days = None
occurrences = None
verbose = False
queue_slugs = None
queues = []
for o, a in opts:
if o in ('-v', '--verbose'):
verbose = True
if o in ('-d', '--days'):
days = a
if o in ('-q', '--queues'):
queue_slugs = a
if o in ('-o', '--occurrences'):
occurrences = int(a)
if not occurrences: occurrences = 1
if not (days and occurrences):
usage()
sys.exit(2)
if queue_slugs is not None:
queue_set = queue_slugs.split(',')
for queue in queue_set:
try:
q = Queue.objects.get(slug__exact=queue)
except:
print "Queue %s does not exist." % queue
sys.exit(2)
queues.append(q)
create_exclusions(days=days, occurrences=occurrences, verbose=verbose, queues=queues)

View File

@ -26,44 +26,91 @@
$Id$
"""
from datetime import datetime, timedelta
from datetime import datetime, timedelta, date
from django.db.models import Q
from helpdesk.models import Queue, Ticket, FollowUp
from helpdesk.models import Queue, Ticket, FollowUp, EscalationExclusion, TicketChange
from helpdesk.lib import send_multipart_mail
import sys, getopt
def escalate_tickets():
for q in Queue.objects.filter(escalate_hours__isnull=False).exclude(escalate_hours=0):
def escalate_tickets(queues, verbose):
""" Only include queues with escalation configured """
queryset = Queue.objects.filter(escalate_days__isnull=False).exclude(escalate_days=0)
if queues:
queryset = queryset.filter(slug__in=queues)
for q in queryset:
last = date.today() - timedelta(days=q.escalate_days)
today = date.today()
workdate = last
days = 0
while workdate < today:
if EscalationExclusion.objects.filter(date=workdate).count() == 0:
days += 1
workdate = workdate + timedelta(days=1)
req_last_escl_date = date.today() - timedelta(days=days)
if verbose:
print "Processing: %s" % q
if not q.last_escalation: q.last_escalation = datetime.now()-timedelta(hours=q.escalate_hours)
if (q.last_escalation + timedelta(hours=q.escalate_hours) - timedelta(minutes=2)) > datetime.now():
continue
print "Processing: %s" % q
q.last_escalation = datetime.now()
q.save()
for t in q.ticket_set.filter(Q(status=Ticket.OPEN_STATUS) | Q(status=Ticket.REOPENED_STATUS)).exclude(priority=1).exclude(on_hold=True):
for t in q.ticket_set.filter(Q(status=Ticket.OPEN_STATUS) | Q(status=Ticket.REOPENED_STATUS)).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)):
t.last_escalation = datetime.now()
t.priority -= 1
t.save()
if verbose:
print " - Esclating %s from %s>%s" % (t.ticket, t.priority+1, t.priority)
f = FollowUp(
ticket = t,
title = 'Ticket Escalated',
date=q.last_escalation,
date=datetime.now(),
public=True,
comment='Ticket escalated after %s hours' % q.escalate_hours,
comment='Ticket escalated after %s days' % q.escalate_days,
)
f.save()
tc = TicketChange(
followup = f,
field = 'priority',
field = 'Priority',
old_value = t.priority + 1,
new_value = t.priority,
)
tc.save()
def usage():
print "Options:"
print " --queues, -q: Queues to include (default: all). Use queue slugs"
print " --verbose, -v: Display a list of dates excluded"
if __name__ == '__main__':
escalate_tickets()
try:
opts, args = getopt.getopt(sys.argv[1:], 'q:v', ['queues=', 'verbose'])
except getopt.GetoptError:
usage()
sys.exit(2)
verbose = False
queue_slugs = None
queues = []
for o, a in opts:
if o in ('-v', '--verbose'):
verbose = True
if o in ('-q', '--queues'):
queue_slugs = a
if queue_slugs is not None:
queue_set = queue_slugs.split(',')
for queue in queue_set:
try:
q = Queue.objects.get(slug__exact=queue)
except:
print "Queue %s does not exist." % queue
sys.exit(2)
queues.append(queue)
escalate_tickets(queues=queues, verbose=verbose)