2008-02-06 05:36:07 +01:00
"""
2011-01-26 00:08:41 +01:00
django - helpdesk - A Django powered ticket tracker for small enterprise .
2007-12-27 01:29:17 +01:00
2008-02-06 05:36:07 +01:00
( c ) Copyright 2008 Jutda . All Rights Reserved . See LICENSE for details .
2007-12-27 01:29:17 +01:00
2008-08-19 10:50:38 +02:00
views / staff . py - The bulk of the application - provides most business logic and
2008-05-21 23:16:44 +02:00
renders all staff - facing views .
2007-12-27 01:29:17 +01:00
"""
2008-08-19 10:50:38 +02:00
2007-12-27 01:29:17 +01:00
from datetime import datetime
2011-09-01 13:01:03 +02:00
import sys
2007-12-27 01:29:17 +01:00
2009-01-20 09:12:05 +01:00
from django . conf import settings
2007-12-27 01:29:17 +01:00
from django . contrib . auth . models import User
2008-10-25 00:52:34 +02:00
from django . contrib . auth . decorators import login_required , user_passes_test
2008-08-13 23:42:57 +02:00
from django . core . files . base import ContentFile
2008-01-15 01:20:00 +01:00
from django . core . urlresolvers import reverse
2009-08-18 14:12:35 +02:00
from django . core import paginator
2008-08-19 10:50:38 +02:00
from django . db import connection
2007-12-27 01:29:17 +01:00
from django . db . models import Q
2009-07-22 10:19:46 +02:00
from django . http import HttpResponseRedirect , Http404 , HttpResponse , HttpResponseForbidden
2008-01-15 01:20:00 +01:00
from django . shortcuts import render_to_response , get_object_or_404
from django . template import loader , Context , RequestContext
2008-05-07 11:04:18 +02:00
from django . utils . translation import ugettext as _
2011-01-29 07:02:03 +01:00
from django . utils . html import escape
2011-11-28 15:17:54 +01:00
from django import forms
2007-12-27 01:29:17 +01:00
2011-05-10 11:27:11 +02:00
from helpdesk . forms import TicketForm , UserSettingsForm , EmailIgnoreForm , EditTicketForm , TicketCCForm , EditFollowUpForm , TicketDependencyForm
2011-05-11 12:07:46 +02:00
from helpdesk . lib import send_templated_mail , query_to_dict , apply_query , safe_template_context
2011-05-10 11:27:11 +02:00
from helpdesk . models import Ticket , Queue , FollowUp , TicketChange , PreSetReply , Attachment , SavedSearch , IgnoreEmail , TicketCC , TicketDependency
2009-09-09 11:11:05 +02:00
from helpdesk . settings import HAS_TAG_SUPPORT
2011-11-19 09:34:07 +01:00
from helpdesk import settings as helpdesk_settings
2009-09-09 11:11:05 +02:00
if HAS_TAG_SUPPORT :
from tagging . models import Tag , TaggedItem
2008-10-25 00:52:34 +02:00
2011-11-19 09:34:07 +01:00
if helpdesk_settings . HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE :
# treat 'normal' users like 'staff'
staff_member_required = user_passes_test ( lambda u : u . is_authenticated ( ) and u . is_active )
else :
staff_member_required = user_passes_test ( lambda u : u . is_authenticated ( ) and u . is_active and u . is_staff )
2008-10-25 00:52:34 +02:00
2011-11-19 09:34:07 +01:00
superuser_required = user_passes_test ( lambda u : u . is_authenticated ( ) and u . is_active and u . is_superuser )
2007-12-27 01:29:17 +01:00
2008-08-19 10:50:38 +02:00
2007-12-27 01:29:17 +01:00
def dashboard ( request ) :
2008-01-16 01:26:24 +01:00
"""
2008-05-21 23:16:44 +02:00
A quick summary overview for users : A list of their own tickets , a table
2008-08-19 10:50:38 +02:00
showing ticket counts by queue / status , and a list of unassigned tickets
2008-05-21 23:16:44 +02:00
with options for them to ' Take ' ownership of said tickets .
2008-01-16 01:26:24 +01:00
"""
2011-11-19 09:34:07 +01:00
# open & reopened tickets
2008-08-20 03:57:41 +02:00
tickets = Ticket . objects . filter (
assigned_to = request . user ,
) . exclude (
2011-11-19 09:34:07 +01:00
status__in = [ Ticket . CLOSED_STATUS , Ticket . RESOLVED_STATUS ] ,
2008-08-20 03:57:41 +02:00
)
2008-08-19 10:50:38 +02:00
2011-11-19 09:34:07 +01:00
# closed & resolved tickets
tickets_closed_resolved = Ticket . objects . filter (
assigned_to = request . user ,
status__in = [ Ticket . CLOSED_STATUS , Ticket . RESOLVED_STATUS ] )
2008-08-20 03:57:41 +02:00
unassigned_tickets = Ticket . objects . filter (
assigned_to__isnull = True ,
) . exclude (
status = Ticket . CLOSED_STATUS ,
)
2008-08-19 10:50:38 +02:00
# The following query builds a grid of queues & ticket statuses,
# to be displayed to the user. EG:
# Open Resolved
# Queue 1 10 4
# Queue 2 4 12
2008-05-21 23:16:44 +02:00
cursor = connection . cursor ( )
cursor . execute ( """
SELECT q . id as queue ,
q . title AS name ,
COUNT ( CASE t . status WHEN ' 1 ' THEN t . id WHEN ' 2 ' THEN t . id END ) AS open ,
2011-11-19 09:34:07 +01:00
COUNT ( CASE t . status WHEN ' 3 ' THEN t . id END ) AS resolved ,
COUNT ( CASE t . status WHEN ' 4 ' THEN t . id END ) AS closed
2008-05-21 23:16:44 +02:00
FROM helpdesk_ticket t ,
helpdesk_queue q
WHERE q . id = t . queue_id
GROUP BY queue , name
ORDER BY q . id ;
""" )
dash_tickets = query_to_dict ( cursor . fetchall ( ) , cursor . description )
return render_to_response ( ' helpdesk/dashboard.html ' ,
RequestContext ( request , {
' user_tickets ' : tickets ,
2011-11-19 09:34:07 +01:00
' user_tickets_closed_resolved ' : tickets_closed_resolved ,
2008-05-21 23:16:44 +02:00
' unassigned_tickets ' : unassigned_tickets ,
' dash_tickets ' : dash_tickets ,
} ) )
2009-01-11 01:26:00 +01:00
dashboard = staff_member_required ( dashboard )
2007-12-27 01:29:17 +01:00
2008-08-19 10:50:38 +02:00
2008-01-15 05:00:19 +01:00
def delete_ticket ( request , ticket_id ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
2008-08-19 10:50:38 +02:00
2008-01-15 05:00:19 +01:00
if request . method == ' GET ' :
return render_to_response ( ' helpdesk/delete_ticket.html ' ,
RequestContext ( request , {
' ticket ' : ticket ,
} ) )
else :
ticket . delete ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_home ' ) )
2009-01-11 01:26:00 +01:00
delete_ticket = staff_member_required ( delete_ticket )
2008-01-15 05:00:19 +01:00
2011-01-29 07:02:03 +01:00
def followup_edit ( request , ticket_id , followup_id , ) :
" Edit followup options with an ability to change the ticket. "
followup = get_object_or_404 ( FollowUp , id = followup_id )
ticket = get_object_or_404 ( Ticket , id = ticket_id )
if request . method == ' GET ' :
form = EditFollowUpForm ( initial =
{ ' title ' : escape ( followup . title ) ,
' ticket ' : followup . ticket ,
' comment ' : escape ( followup . comment ) ,
' public ' : followup . public ,
' new_status ' : followup . new_status ,
} )
return render_to_response ( ' helpdesk/followup_edit.html ' ,
RequestContext ( request , {
' followup ' : followup ,
' ticket ' : ticket ,
' form ' : form ,
} ) )
elif request . method == ' POST ' :
form = EditFollowUpForm ( request . POST )
if form . is_valid ( ) :
title = form . cleaned_data [ ' title ' ]
_ticket = form . cleaned_data [ ' ticket ' ]
comment = form . cleaned_data [ ' comment ' ]
public = form . cleaned_data [ ' public ' ]
new_status = form . cleaned_data [ ' new_status ' ]
#will save previous date
old_date = followup . date
new_followup = FollowUp ( title = title , date = old_date , ticket = _ticket , comment = comment , public = public , new_status = new_status , )
2011-11-19 09:34:07 +01:00
# keep old user if one did exist before.
if followup . user :
new_followup . user = followup . user
2011-01-29 07:02:03 +01:00
new_followup . save ( )
2011-11-19 09:34:07 +01:00
# get list of old attachments & link them to new_followup
attachments = Attachment . objects . filter ( followup = followup )
for attachment in attachments :
attachment . followup = new_followup
attachment . save ( )
# delete old followup
followup . delete ( )
2011-01-29 07:02:03 +01:00
return HttpResponseRedirect ( reverse ( ' helpdesk_view ' , args = [ ticket . id ] ) )
2007-12-27 01:29:17 +01:00
def view_ticket ( request , ticket_id ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
2008-08-19 10:50:38 +02:00
2007-12-27 01:29:17 +01:00
if request . GET . has_key ( ' take ' ) :
2008-08-19 10:50:38 +02:00
# Allow the user to assign the ticket to themselves whilst viewing it.
2011-09-05 20:40:53 +02:00
# Trick the update_ticket() view into thinking it's being called with
# a valid POST.
request . POST = {
' owner ' : request . user . id ,
' public ' : 1 ,
' title ' : ticket . title ,
' comment ' : ' '
}
return update_ticket ( request , ticket_id )
2008-01-15 01:20:00 +01:00
2008-01-07 21:22:13 +01:00
if request . GET . has_key ( ' close ' ) and ticket . status == Ticket . RESOLVED_STATUS :
2008-08-19 10:50:38 +02:00
if not ticket . assigned_to :
2008-01-07 21:22:13 +01:00
owner = 0
else :
owner = ticket . assigned_to . id
2008-08-19 10:50:38 +02:00
# Trick the update_ticket() view into thinking it's being called with
# a valid POST.
request . POST = {
' new_status ' : Ticket . CLOSED_STATUS ,
' public ' : 1 ,
' owner ' : owner ,
' title ' : ticket . title ,
' comment ' : _ ( ' Accepted resolution and closed ticket ' ) ,
}
2008-01-07 21:22:13 +01:00
return update_ticket ( request , ticket_id )
2007-12-27 01:29:17 +01:00
return render_to_response ( ' helpdesk/ticket.html ' ,
RequestContext ( request , {
' ticket ' : ticket ,
2011-11-19 09:34:07 +01:00
' active_users ' : User . objects . filter ( is_active = True ) . order_by ( ' username ' ) ,
2008-01-10 01:28:45 +01:00
' priorities ' : Ticket . PRIORITY_CHOICES ,
2008-01-11 02:00:01 +01:00
' preset_replies ' : PreSetReply . objects . filter ( Q ( queues = ticket . queue ) | Q ( queues__isnull = True ) ) ,
2011-02-02 13:50:03 +01:00
' tags_enabled ' : HAS_TAG_SUPPORT ,
2007-12-27 01:29:17 +01:00
} ) )
2009-01-11 01:26:00 +01:00
view_ticket = staff_member_required ( view_ticket )
2007-12-27 01:29:17 +01:00
2008-08-19 10:50:38 +02:00
2009-07-22 10:19:46 +02:00
def update_ticket ( request , ticket_id , public = False ) :
2011-11-19 09:34:07 +01:00
if not ( public or ( request . user . is_authenticated ( ) and request . user . is_active and ( request . user . is_staff or helpdesk_settings . HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE ) ) ) :
2009-07-22 10:19:46 +02:00
return HttpResponseForbidden ( _ ( ' Sorry, you need to login to do that. ' ) )
2007-12-27 01:29:17 +01:00
ticket = get_object_or_404 ( Ticket , id = ticket_id )
comment = request . POST . get ( ' comment ' , ' ' )
new_status = int ( request . POST . get ( ' new_status ' , ticket . status ) )
title = request . POST . get ( ' title ' , ' ' )
public = request . POST . get ( ' public ' , False )
owner = int ( request . POST . get ( ' owner ' , None ) )
2008-01-10 01:28:45 +01:00
priority = int ( request . POST . get ( ' priority ' , ticket . priority ) )
2009-09-09 11:11:05 +02:00
tags = request . POST . get ( ' tags ' , ' ' )
2008-08-19 10:50:38 +02:00
2008-08-29 11:11:02 +02:00
# We need to allow the 'ticket' and 'queue' contexts to be applied to the
# comment.
from django . template import loader , Context
2009-07-22 10:19:46 +02:00
context = safe_template_context ( ticket )
2011-11-19 09:34:07 +01:00
# this line sometimes creates problems if code is sent as a comment.
# if comment contains some django code, like "why does {% if bla %} crash",
# then the following line will give us a crash, since django expects {% if %}
# to be closed with an {% endif %} tag.
2009-07-22 10:19:46 +02:00
comment = loader . get_template_from_string ( comment ) . render ( Context ( context ) )
2008-08-29 11:11:02 +02:00
2010-01-26 00:59:16 +01:00
if owner is None and ticket . assigned_to :
2007-12-27 01:29:17 +01:00
owner = ticket . assigned_to . id
2009-01-23 11:35:14 +01:00
f = FollowUp ( ticket = ticket , date = datetime . now ( ) , comment = comment )
2009-03-08 07:03:55 +01:00
2011-11-19 09:34:07 +01:00
if request . user . is_staff or helpdesk_settings . HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE :
2009-01-23 11:35:14 +01:00
f . user = request . user
2009-03-08 07:03:55 +01:00
2008-08-19 10:50:38 +02:00
f . public = public
2007-12-27 01:29:17 +01:00
2008-01-21 02:02:12 +01:00
reassigned = False
2010-01-26 00:59:16 +01:00
if owner is not None :
2008-11-09 06:34:51 +01:00
if owner != 0 and ( ( ticket . assigned_to and owner != ticket . assigned_to . id ) or not ticket . assigned_to ) :
2007-12-27 01:29:17 +01:00
new_user = User . objects . get ( id = owner )
2008-08-19 10:50:38 +02:00
f . title = _ ( ' Assigned to %(username)s ' ) % {
' username ' : new_user . username ,
}
2007-12-27 01:29:17 +01:00
ticket . assigned_to = new_user
2008-01-21 02:02:12 +01:00
reassigned = True
2011-11-28 14:49:37 +01:00
# user changed owner to 'unassign'
elif owner == 0 and ticket . assigned_to is not None :
f . title = _ ( ' Unassigned ' )
ticket . assigned_to = None
2008-08-19 10:50:38 +02:00
2007-12-27 01:29:17 +01:00
if new_status != ticket . status :
ticket . status = new_status
ticket . save ( )
f . new_status = new_status
if f . title :
f . title + = ' and %s ' % ticket . get_status_display ( )
else :
f . title = ' %s ' % ticket . get_status_display ( )
if not f . title :
if f . comment :
2008-05-07 11:04:18 +02:00
f . title = _ ( ' Comment ' )
2007-12-27 01:29:17 +01:00
else :
2008-05-07 11:04:18 +02:00
f . title = _ ( ' Updated ' )
2007-12-27 01:29:17 +01:00
f . save ( )
2009-03-08 07:03:55 +01:00
2009-01-20 09:12:05 +01:00
files = [ ]
if request . FILES :
import mimetypes , os
for file in request . FILES . getlist ( ' attachment ' ) :
filename = file . name . replace ( ' ' , ' _ ' )
a = Attachment (
followup = f ,
filename = filename ,
mime_type = mimetypes . guess_type ( filename ) [ 0 ] or ' application/octet-stream ' ,
size = file . size ,
)
a . file . save ( file . name , file , save = False )
a . save ( )
2009-03-08 07:03:55 +01:00
2009-01-20 09:12:05 +01:00
if file . size < getattr ( settings , ' MAX_EMAIL_ATTACHMENT_SIZE ' , 512000 ) :
2009-03-08 07:03:55 +01:00
# Only files smaller than 512kb (or as defined in
2009-01-20 09:12:05 +01:00
# settings.MAX_EMAIL_ATTACHMENT_SIZE) are sent via email.
files . append ( a . file . path )
2008-08-19 10:50:38 +02:00
2007-12-27 01:29:17 +01:00
if title != ticket . title :
2008-08-19 10:50:38 +02:00
c = TicketChange (
followup = f ,
field = _ ( ' Title ' ) ,
old_value = ticket . title ,
new_value = title ,
)
2007-12-27 01:29:17 +01:00
c . save ( )
ticket . title = title
2008-01-10 01:28:45 +01:00
if priority != ticket . priority :
2008-08-19 10:50:38 +02:00
c = TicketChange (
followup = f ,
field = _ ( ' Priority ' ) ,
old_value = ticket . priority ,
new_value = priority ,
)
2008-01-10 01:28:45 +01:00
c . save ( )
ticket . priority = priority
2009-09-09 11:11:05 +02:00
if HAS_TAG_SUPPORT :
if tags != ticket . tags :
c = TicketChange (
followup = f ,
field = _ ( ' Tags ' ) ,
old_value = ticket . tags ,
new_value = tags ,
)
c . save ( )
ticket . tags = tags
2011-11-19 09:34:07 +01:00
if new_status == Ticket . RESOLVED_STATUS :
2008-01-07 21:22:13 +01:00
ticket . resolution = comment
2008-08-19 10:50:38 +02:00
2009-08-11 11:02:48 +02:00
messages_sent_to = [ ]
2011-02-08 22:19:17 +01:00
# ticket might have changed above, so we re-instantiate context with the
# (possibly) updated ticket.
context = safe_template_context ( ticket )
2009-08-18 14:12:35 +02:00
context . update (
resolution = ticket . resolution ,
comment = f . comment ,
)
2008-10-25 00:52:34 +02:00
if ticket . submitter_email and public and ( f . comment or ( f . new_status in ( Ticket . RESOLVED_STATUS , Ticket . CLOSED_STATUS ) ) ) :
2008-08-19 10:50:38 +02:00
2008-01-07 21:22:13 +01:00
if f . new_status == Ticket . RESOLVED_STATUS :
2008-04-02 01:26:12 +02:00
template = ' resolved_submitter '
2008-01-21 02:02:12 +01:00
elif f . new_status == Ticket . CLOSED_STATUS :
2008-04-02 01:26:12 +02:00
template = ' closed_submitter '
2008-01-07 21:22:13 +01:00
else :
2008-04-02 01:26:12 +02:00
template = ' updated_submitter '
2008-08-19 10:50:38 +02:00
send_templated_mail (
template ,
context ,
recipients = ticket . submitter_email ,
sender = ticket . queue . from_address ,
fail_silently = True ,
2009-01-20 09:12:05 +01:00
files = files ,
2008-08-19 10:50:38 +02:00
)
2009-08-11 11:02:48 +02:00
messages_sent_to . append ( ticket . submitter_email )
2008-01-07 21:22:13 +01:00
2009-09-09 10:47:48 +02:00
for cc in ticket . ticketcc_set . all ( ) :
if cc . email_address not in messages_sent_to :
send_templated_mail (
template ,
context ,
recipients = cc . email_address ,
sender = ticket . queue . from_address ,
fail_silently = True ,
)
messages_sent_to . append ( cc . email_address )
2009-08-11 11:02:48 +02:00
if ticket . assigned_to and request . user != ticket . assigned_to and ticket . assigned_to . email and ticket . assigned_to . email not in messages_sent_to :
2008-08-19 10:50:38 +02:00
# We only send e-mails to staff members if the ticket is updated by
2009-07-22 10:19:46 +02:00
# another user. The actual template varies, depending on what has been
# changed.
2008-01-21 02:02:12 +01:00
if reassigned :
2008-04-02 01:26:12 +02:00
template_staff = ' assigned_owner '
2008-01-21 02:02:12 +01:00
elif f . new_status == Ticket . RESOLVED_STATUS :
2008-04-02 01:26:12 +02:00
template_staff = ' resolved_owner '
2008-01-21 02:02:12 +01:00
elif f . new_status == Ticket . CLOSED_STATUS :
2008-04-02 01:26:12 +02:00
template_staff = ' closed_owner '
2008-01-21 02:02:12 +01:00
else :
2008-04-02 01:26:12 +02:00
template_staff = ' updated_owner '
2008-08-19 10:50:38 +02:00
2009-07-22 10:19:46 +02:00
if ( not reassigned or ( reassigned and ticket . assigned_to . usersettings . settings . get ( ' email_on_ticket_assign ' , False ) ) ) or ( not reassigned and ticket . assigned_to . usersettings . settings . get ( ' email_on_ticket_change ' , False ) ) :
2008-09-09 10:32:01 +02:00
send_templated_mail (
template_staff ,
context ,
recipients = ticket . assigned_to . email ,
sender = ticket . queue . from_address ,
fail_silently = True ,
2009-01-20 09:12:05 +01:00
files = files ,
2008-09-09 10:32:01 +02:00
)
2009-08-11 11:02:48 +02:00
messages_sent_to . append ( ticket . assigned_to . email )
2008-08-19 10:50:38 +02:00
2009-08-11 11:02:48 +02:00
if ticket . queue . updated_ticket_cc and ticket . queue . updated_ticket_cc not in messages_sent_to :
2008-04-02 01:26:12 +02:00
if reassigned :
template_cc = ' assigned_cc '
elif f . new_status == Ticket . RESOLVED_STATUS :
template_cc = ' resolved_cc '
elif f . new_status == Ticket . CLOSED_STATUS :
template_cc = ' closed_cc '
else :
template_cc = ' updated_cc '
2008-08-19 10:50:38 +02:00
send_templated_mail (
template_cc ,
context ,
recipients = ticket . queue . updated_ticket_cc ,
sender = ticket . queue . from_address ,
fail_silently = True ,
2009-01-20 09:12:05 +01:00
files = files ,
2008-08-19 10:50:38 +02:00
)
2008-02-08 01:19:58 +01:00
2007-12-27 01:29:17 +01:00
ticket . save ( )
2008-08-19 10:50:38 +02:00
2011-11-19 09:34:07 +01:00
if request . user . is_staff or helpdesk_settings . HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE :
2009-01-23 11:35:14 +01:00
return HttpResponseRedirect ( ticket . get_absolute_url ( ) )
else :
return HttpResponseRedirect ( ticket . ticket_url )
2007-12-27 01:29:17 +01:00
2008-08-19 10:50:38 +02:00
2009-03-08 07:03:55 +01:00
def mass_update ( request ) :
tickets = request . POST . getlist ( ' ticket_id ' )
action = request . POST . get ( ' action ' , None )
if not ( tickets and action ) :
return HttpResponseRedirect ( reverse ( ' helpdesk_list ' ) )
if action . startswith ( ' assign_ ' ) :
parts = action . split ( ' _ ' )
user = User . objects . get ( id = parts [ 1 ] )
action = ' assign '
elif action == ' take ' :
user = request . user
action = ' assign '
for t in Ticket . objects . filter ( id__in = tickets ) :
if action == ' assign ' and t . assigned_to != user :
t . assigned_to = user
t . save ( )
f = FollowUp ( ticket = t , date = datetime . now ( ) , title = _ ( ' Assigned to %(username)s in bulk update ' % { ' username ' : user . username } ) , public = True , user = request . user )
f . save ( )
elif action == ' unassign ' and t . assigned_to is not None :
t . assigned_to = None
t . save ( )
f = FollowUp ( ticket = t , date = datetime . now ( ) , title = _ ( ' Unassigned in bulk update ' ) , public = True , user = request . user )
f . save ( )
elif action == ' close ' and t . status != Ticket . CLOSED_STATUS :
t . status = Ticket . CLOSED_STATUS
t . save ( )
f = FollowUp ( ticket = t , date = datetime . now ( ) , title = _ ( ' Closed in bulk update ' ) , public = False , user = request . user , new_status = Ticket . CLOSED_STATUS )
f . save ( )
elif action == ' close_public ' and t . status != Ticket . CLOSED_STATUS :
t . status = Ticket . CLOSED_STATUS
t . save ( )
f = FollowUp ( ticket = t , date = datetime . now ( ) , title = _ ( ' Closed in bulk update ' ) , public = True , user = request . user , new_status = Ticket . CLOSED_STATUS )
f . save ( )
# Send email to Submitter, Owner, Queue CC
2011-11-19 09:34:07 +01:00
context = safe_template_context ( t )
context . update (
resolution = t . resolution ,
queue = t . queue ,
)
2009-03-08 07:03:55 +01:00
2009-08-11 11:02:48 +02:00
messages_sent_to = [ ]
2009-03-08 07:03:55 +01:00
if t . submitter_email :
send_templated_mail (
' closed_submitter ' ,
context ,
recipients = t . submitter_email ,
sender = t . queue . from_address ,
fail_silently = True ,
)
2009-08-11 11:02:48 +02:00
messages_sent_to . append ( t . submitter_email )
2009-03-08 07:03:55 +01:00
2010-09-04 08:47:55 +02:00
for cc in t . ticketcc_set . all ( ) :
2009-09-09 10:47:48 +02:00
if cc . email_address not in messages_sent_to :
send_templated_mail (
' closed_submitter ' ,
context ,
recipients = cc . email_address ,
2010-09-04 08:47:55 +02:00
sender = t . queue . from_address ,
2009-09-09 10:47:48 +02:00
fail_silently = True ,
)
messages_sent_to . append ( cc . email_address )
2009-08-11 11:02:48 +02:00
if t . assigned_to and request . user != t . assigned_to and t . assigned_to . email and t . assigned_to . email not in messages_sent_to :
2009-03-08 07:03:55 +01:00
send_templated_mail (
' closed_owner ' ,
context ,
recipients = t . assigned_to . email ,
sender = t . queue . from_address ,
fail_silently = True ,
)
2009-08-11 11:02:48 +02:00
messages_sent_to . append ( t . assigned_to . email )
2009-03-08 07:03:55 +01:00
2009-08-11 11:02:48 +02:00
if t . queue . updated_ticket_cc and t . queue . updated_ticket_cc not in messages_sent_to :
2009-03-08 07:03:55 +01:00
send_templated_mail (
' closed_cc ' ,
context ,
recipients = t . queue . updated_ticket_cc ,
sender = t . queue . from_address ,
fail_silently = True ,
)
elif action == ' delete ' :
t . delete ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_list ' ) )
mass_update = staff_member_required ( mass_update )
2007-12-27 01:29:17 +01:00
def ticket_list ( request ) :
context = { }
2009-03-08 07:03:55 +01:00
# Query_params will hold a dictionary of paramaters relating to
2008-08-28 11:06:24 +02:00
# a query, to be saved if needed:
query_params = {
' filtering ' : { } ,
' sorting ' : None ,
2008-10-25 00:52:34 +02:00
' sortreverse ' : False ,
2008-08-28 11:06:24 +02:00
' keyword ' : None ,
' other_filter ' : None ,
}
2007-12-27 01:29:17 +01:00
2008-08-29 11:11:02 +02:00
from_saved_query = False
2009-03-08 06:55:35 +01:00
# If the user is coming from the header/navigation search box, lets' first
# look at their query to see if they have entered a valid ticket number. If
# they have, just redirect to that ticket number. Otherwise, we treat it as
# a keyword search.
if request . GET . get ( ' search_type ' , None ) == ' header ' :
query = request . GET . get ( ' q ' )
filter = None
if query . find ( ' - ' ) > 0 :
queue , id = query . split ( ' - ' )
try :
id = int ( id )
except ValueError :
id = None
if id :
filter = { ' queue__slug ' : queue , ' id ' : id }
else :
try :
query = int ( query )
except ValueError :
query = None
if query :
filter = { ' id ' : int ( query ) }
if filter :
try :
ticket = Ticket . objects . get ( * * filter )
return HttpResponseRedirect ( ticket . staff_url )
except Ticket . DoesNotExist :
# Go on to standard keyword searching
pass
2011-05-06 08:55:52 +02:00
saved_query = None
2008-08-28 11:06:24 +02:00
if request . GET . get ( ' saved_query ' , None ) :
from_saved_query = True
try :
saved_query = SavedSearch . objects . get ( pk = request . GET . get ( ' saved_query ' ) )
except SavedSearch . DoesNotExist :
return HttpResponseRedirect ( reverse ( ' helpdesk_list ' ) )
if not ( saved_query . shared or saved_query . user == request . user ) :
return HttpResponseRedirect ( reverse ( ' helpdesk_list ' ) )
2008-11-18 01:14:36 +01:00
import cPickle
from helpdesk . lib import b64decode
query_params = cPickle . loads ( b64decode ( str ( saved_query . query ) ) )
2008-08-29 11:11:02 +02:00
elif not ( request . GET . has_key ( ' queue ' )
or request . GET . has_key ( ' assigned_to ' )
or request . GET . has_key ( ' status ' )
or request . GET . has_key ( ' q ' )
2008-10-25 00:52:34 +02:00
or request . GET . has_key ( ' sort ' )
2009-09-09 11:11:05 +02:00
or request . GET . has_key ( ' sortreverse ' )
or request . GET . has_key ( ' tags ' ) ) :
2008-08-29 11:11:02 +02:00
2009-03-08 07:03:55 +01:00
# Fall-back if no querying is being done, force the list to only
2008-08-29 11:11:02 +02:00
# show open/reopened/resolved (not closed) cases sorted by creation
# date.
query_params = {
' filtering ' : { ' status__in ' : [ 1 , 2 , 3 ] } ,
' sorting ' : ' created ' ,
}
2008-08-28 11:06:24 +02:00
else :
queues = request . GET . getlist ( ' queue ' )
if queues :
queues = [ int ( q ) for q in queues ]
query_params [ ' filtering ' ] [ ' queue__id__in ' ] = queues
owners = request . GET . getlist ( ' assigned_to ' )
if owners :
owners = [ int ( u ) for u in owners ]
query_params [ ' filtering ' ] [ ' assigned_to__id__in ' ] = owners
statuses = request . GET . getlist ( ' status ' )
if statuses :
statuses = [ int ( s ) for s in statuses ]
query_params [ ' filtering ' ] [ ' status__in ' ] = statuses
2011-05-13 00:02:59 +02:00
date_from = request . GET . get ( ' date_from ' )
if date_from :
query_params [ ' filtering ' ] [ ' created__gte ' ] = date_from
date_to = request . GET . get ( ' date_to ' )
if date_to :
query_params [ ' filtering ' ] [ ' created__lte ' ] = date_to
2008-08-28 11:06:24 +02:00
### KEYWORD SEARCHING
q = request . GET . get ( ' q ' , None )
if q :
qset = (
Q ( title__icontains = q ) |
Q ( description__icontains = q ) |
Q ( resolution__icontains = q ) |
Q ( submitter_email__icontains = q )
)
context = dict ( context , query = q )
2009-03-08 07:03:55 +01:00
2008-08-28 11:06:24 +02:00
query_params [ ' other_filter ' ] = qset
### SORTING
sort = request . GET . get ( ' sort ' , None )
if sort not in ( ' status ' , ' assigned_to ' , ' created ' , ' title ' , ' queue ' , ' priority ' ) :
sort = ' created '
query_params [ ' sorting ' ] = sort
2009-03-08 07:03:55 +01:00
2008-10-25 00:52:34 +02:00
sortreverse = request . GET . get ( ' sortreverse ' , None )
query_params [ ' sortreverse ' ] = sortreverse
2008-08-28 11:06:24 +02:00
2009-07-21 12:29:23 +02:00
ticket_qs = apply_query ( Ticket . objects . select_related ( ) , query_params )
2011-09-01 13:01:03 +02:00
print >> sys . stderr , str ( ticket_qs . query )
2009-09-09 11:11:05 +02:00
## TAG MATCHING
if HAS_TAG_SUPPORT :
tags = request . GET . getlist ( ' tags ' )
if tags :
ticket_qs = TaggedItem . objects . get_by_model ( ticket_qs , tags )
query_params [ ' tags ' ] = tags
2009-08-22 08:29:30 +02:00
ticket_paginator = paginator . Paginator ( ticket_qs , request . user . usersettings . settings . get ( ' tickets_per_page ' ) or 20 )
2009-07-21 12:29:23 +02:00
try :
page = int ( request . GET . get ( ' page ' , ' 1 ' ) )
except ValueError :
page = 1
try :
2009-08-18 14:12:35 +02:00
tickets = ticket_paginator . page ( page )
except ( paginator . EmptyPage , paginator . InvalidPage ) :
tickets = ticket_paginator . page ( ticket_paginator . num_pages )
2008-08-28 11:06:24 +02:00
2009-03-08 06:49:08 +01:00
search_message = ' '
if context . has_key ( ' query ' ) and settings . DATABASE_ENGINE . startswith ( ' sqlite ' ) :
search_message = _ ( ' <p><strong>Note:</strong> Your keyword search is case sensitive because of your database. This means the search will <strong>not</strong> be accurate. By switching to a different database system you will gain better searching! For more information, read the <a href= " http://docs.djangoproject.com/en/dev/ref/databases/#sqlite-string-matching " >Django Documentation on string matching in SQLite</a>. ' )
2009-03-08 07:03:55 +01:00
2008-11-18 01:14:36 +01:00
import cPickle
from helpdesk . lib import b64encode
urlsafe_query = b64encode ( cPickle . dumps ( query_params ) )
2008-08-19 10:50:38 +02:00
2008-08-28 11:06:24 +02:00
user_saved_queries = SavedSearch . objects . filter ( Q ( user = request . user ) | Q ( shared__exact = True ) )
2007-12-27 01:29:17 +01:00
2009-07-21 12:29:23 +02:00
query_string = [ ]
for get_key , get_value in request . GET . iteritems ( ) :
if get_key != " page " :
query_string . append ( " %s = %s " % ( get_key , get_value ) )
2009-09-09 11:11:05 +02:00
tag_choices = [ ]
if HAS_TAG_SUPPORT :
# FIXME: restrict this to tags that are actually in use
tag_choices = Tag . objects . all ( )
2007-12-27 01:29:17 +01:00
return render_to_response ( ' helpdesk/ticket_list.html ' ,
RequestContext ( request , dict (
context ,
2009-07-21 12:29:23 +02:00
query_string = " & " . join ( query_string ) ,
2007-12-27 01:29:17 +01:00
tickets = tickets ,
user_choices = User . objects . filter ( is_active = True ) ,
queue_choices = Queue . objects . all ( ) ,
status_choices = Ticket . STATUS_CHOICES ,
2009-09-09 11:11:05 +02:00
tag_choices = tag_choices ,
2008-08-28 11:06:24 +02:00
urlsafe_query = urlsafe_query ,
user_saved_queries = user_saved_queries ,
query_params = query_params ,
from_saved_query = from_saved_query ,
2011-05-06 08:55:52 +02:00
saved_query = saved_query ,
2009-03-08 06:49:08 +01:00
search_message = search_message ,
2009-09-09 11:11:05 +02:00
tags_enabled = HAS_TAG_SUPPORT
2007-12-27 01:29:17 +01:00
) ) )
2009-01-11 01:26:00 +01:00
ticket_list = staff_member_required ( ticket_list )
2007-12-27 01:29:17 +01:00
2008-08-19 10:50:38 +02:00
2009-06-03 13:43:46 +02:00
def edit_ticket ( request , ticket_id ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
if request . method == ' POST ' :
form = EditTicketForm ( request . POST , instance = ticket )
if form . is_valid ( ) :
ticket = form . save ( )
return HttpResponseRedirect ( ticket . get_absolute_url ( ) )
else :
form = EditTicketForm ( instance = ticket )
return render_to_response ( ' helpdesk/edit_ticket.html ' ,
RequestContext ( request , {
' form ' : form ,
2009-09-09 11:11:05 +02:00
' tags_enabled ' : HAS_TAG_SUPPORT ,
2009-06-03 13:43:46 +02:00
} ) )
2009-09-09 10:47:48 +02:00
edit_ticket = staff_member_required ( edit_ticket )
2009-06-03 13:43:46 +02:00
2007-12-27 01:29:17 +01:00
def create_ticket ( request ) :
if request . method == ' POST ' :
2009-01-22 09:08:22 +01:00
form = TicketForm ( request . POST , request . FILES )
2007-12-27 01:29:17 +01:00
form . fields [ ' queue ' ] . choices = [ ( ' ' , ' -------- ' ) ] + [ [ q . id , q . title ] for q in Queue . objects . all ( ) ]
2011-02-03 12:21:01 +01:00
form . fields [ ' assigned_to ' ] . choices = [ ( ' ' , ' -------- ' ) ] + [ [ u . id , u . username ] for u in User . objects . filter ( is_active = True ) . order_by ( ' username ' ) ]
2007-12-27 01:29:17 +01:00
if form . is_valid ( ) :
2007-12-28 04:29:45 +01:00
ticket = form . save ( user = request . user )
2007-12-27 01:29:17 +01:00
return HttpResponseRedirect ( ticket . get_absolute_url ( ) )
else :
2009-08-06 10:56:02 +02:00
initial_data = { }
if request . user . usersettings . settings . get ( ' use_email_as_submitter ' , False ) and request . user . email :
initial_data [ ' submitter_email ' ] = request . user . email
2011-02-06 19:17:55 +01:00
if request . GET . has_key ( ' queue ' ) :
initial_data [ ' queue ' ] = request . GET [ ' queue ' ]
2009-08-06 10:56:02 +02:00
form = TicketForm ( initial = initial_data )
2007-12-27 01:29:17 +01:00
form . fields [ ' queue ' ] . choices = [ ( ' ' , ' -------- ' ) ] + [ [ q . id , q . title ] for q in Queue . objects . all ( ) ]
2011-02-03 12:21:01 +01:00
form . fields [ ' assigned_to ' ] . choices = [ ( ' ' , ' -------- ' ) ] + [ [ u . id , u . username ] for u in User . objects . filter ( is_active = True ) . order_by ( ' username ' ) ]
2011-11-28 15:17:54 +01:00
if helpdesk_settings . HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO :
form . fields [ ' assigned_to ' ] . widget = forms . HiddenInput ( )
2007-12-27 01:29:17 +01:00
2008-08-19 10:50:38 +02:00
return render_to_response ( ' helpdesk/create_ticket.html ' ,
2007-12-27 01:29:17 +01:00
RequestContext ( request , {
' form ' : form ,
2009-09-09 11:11:05 +02:00
' tags_enabled ' : HAS_TAG_SUPPORT ,
2007-12-27 01:29:17 +01:00
} ) )
2009-01-11 01:26:00 +01:00
create_ticket = staff_member_required ( create_ticket )
2008-01-11 02:00:01 +01:00
2008-08-19 10:50:38 +02:00
2008-01-11 02:00:01 +01:00
def raw_details ( request , type ) :
2008-08-19 10:50:38 +02:00
# TODO: This currently only supports spewing out 'PreSetReply' objects,
# in the future it needs to be expanded to include other items. All it
# does is return a plain-text representation of an object.
2008-01-11 02:00:01 +01:00
if not type in ( ' preset ' , ) :
raise Http404
2008-08-19 10:50:38 +02:00
2008-01-11 02:00:01 +01:00
if type == ' preset ' and request . GET . get ( ' id ' , False ) :
try :
preset = PreSetReply . objects . get ( id = request . GET . get ( ' id ' ) )
return HttpResponse ( preset . body )
except PreSetReply . DoesNotExist :
raise Http404
2008-08-19 10:50:38 +02:00
2008-01-11 02:00:01 +01:00
raise Http404
2009-01-11 01:26:00 +01:00
raw_details = staff_member_required ( raw_details )
2008-01-16 01:26:24 +01:00
2008-08-19 10:50:38 +02:00
2008-01-16 05:52:30 +01:00
def hold_ticket ( request , ticket_id , unhold = False ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
if unhold :
ticket . on_hold = False
2008-05-07 11:04:18 +02:00
title = _ ( ' Ticket taken off hold ' )
2008-01-16 05:52:30 +01:00
else :
ticket . on_hold = True
2008-05-07 11:04:18 +02:00
title = _ ( ' Ticket placed on hold ' )
2008-08-19 10:50:38 +02:00
2008-01-16 05:52:30 +01:00
f = FollowUp (
ticket = ticket ,
user = request . user ,
title = title ,
date = datetime . now ( ) ,
2008-01-21 00:31:27 +01:00
public = True ,
2008-01-16 05:52:30 +01:00
)
f . save ( )
2008-08-19 10:50:38 +02:00
2008-01-16 05:52:30 +01:00
ticket . save ( )
2008-08-19 10:50:38 +02:00
2008-01-16 05:52:30 +01:00
return HttpResponseRedirect ( ticket . get_absolute_url ( ) )
2009-01-11 01:26:00 +01:00
hold_ticket = staff_member_required ( hold_ticket )
2008-01-16 05:52:30 +01:00
2008-08-19 10:50:38 +02:00
2008-01-16 05:52:30 +01:00
def unhold_ticket ( request , ticket_id ) :
return hold_ticket ( request , ticket_id , unhold = True )
2009-01-11 01:26:00 +01:00
unhold_ticket = staff_member_required ( unhold_ticket )
2008-01-16 05:52:30 +01:00
2008-08-19 10:50:38 +02:00
2008-02-08 06:29:51 +01:00
def rss_list ( request ) :
2008-08-19 10:50:38 +02:00
return render_to_response ( ' helpdesk/rss_list.html ' ,
2008-02-08 06:29:51 +01:00
RequestContext ( request , {
' queues ' : Queue . objects . all ( ) ,
} ) )
2009-01-11 01:26:00 +01:00
rss_list = staff_member_required ( rss_list )
2008-04-02 01:26:12 +02:00
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
def report_index ( request ) :
2009-12-23 12:47:50 +01:00
number_tickets = Ticket . objects . all ( ) . count ( )
2011-05-12 01:01:35 +02:00
saved_query = request . GET . get ( ' saved_query ' , None )
2008-04-02 01:26:12 +02:00
return render_to_response ( ' helpdesk/report_index.html ' ,
2009-12-23 12:47:50 +01:00
RequestContext ( request , {
' number_tickets ' : number_tickets ,
2011-05-11 12:07:46 +02:00
' saved_query ' : saved_query ,
2009-12-23 12:47:50 +01:00
} ) )
2009-01-11 01:26:00 +01:00
report_index = staff_member_required ( report_index )
2008-04-02 01:26:12 +02:00
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
def run_report ( request , report ) :
2011-05-11 12:07:46 +02:00
if Ticket . objects . all ( ) . count ( ) == 0 or report not in ( ' queuemonth ' , ' usermonth ' , ' queuestatus ' , ' queuepriority ' , ' userstatus ' , ' userpriority ' , ' userqueue ' ) :
2011-04-19 23:36:20 +02:00
return HttpResponseRedirect ( reverse ( " helpdesk_report_index " ) )
2011-05-11 12:07:46 +02:00
report_queryset = Ticket . objects . all ( ) . select_related ( )
from_saved_query = False
saved_query = None
if request . GET . get ( ' saved_query ' , None ) :
from_saved_query = True
try :
saved_query = SavedSearch . objects . get ( pk = request . GET . get ( ' saved_query ' ) )
except SavedSearch . DoesNotExist :
return HttpResponseRedirect ( reverse ( ' helpdesk_report_index ' ) )
if not ( saved_query . shared or saved_query . user == request . user ) :
return HttpResponseRedirect ( reverse ( ' helpdesk_report_index ' ) )
import cPickle
from helpdesk . lib import b64decode
query_params = cPickle . loads ( b64decode ( str ( saved_query . query ) ) )
report_queryset = apply_query ( report_queryset , query_params )
from collections import defaultdict
summarytable = defaultdict ( int )
2008-04-02 01:26:12 +02:00
months = (
2011-05-11 12:07:46 +02:00
_ ( ' Jan ' ) ,
_ ( ' Feb ' ) ,
_ ( ' Mar ' ) ,
_ ( ' Apr ' ) ,
_ ( ' May ' ) ,
_ ( ' Jun ' ) ,
_ ( ' Jul ' ) ,
_ ( ' Aug ' ) ,
_ ( ' Sep ' ) ,
_ ( ' Oct ' ) ,
_ ( ' Nov ' ) ,
_ ( ' Dec ' ) ,
2008-04-02 01:26:12 +02:00
)
2011-05-11 12:07:46 +02:00
2008-04-02 01:26:12 +02:00
first_ticket = Ticket . objects . all ( ) . order_by ( ' created ' ) [ 0 ]
first_month = first_ticket . created . month
first_year = first_ticket . created . year
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
last_ticket = Ticket . objects . all ( ) . order_by ( ' -created ' ) [ 0 ]
last_month = last_ticket . created . month
last_year = last_ticket . created . year
periods = [ ]
year , month = first_year , first_month
working = True
2011-05-11 12:07:46 +02:00
periods . append ( " %s %s " % ( months [ month ] , year ) )
2008-04-02 01:26:12 +02:00
while working :
month + = 1
if month > 12 :
year + = 1
month = 1
2009-12-16 09:30:50 +01:00
if ( year > last_year ) or ( month > last_month and year > = last_year ) :
2008-04-02 01:26:12 +02:00
working = False
2011-11-19 09:34:07 +01:00
periods . append ( " %s %s " % ( months [ month - 1 ] , year ) )
2008-04-02 01:26:12 +02:00
if report == ' userpriority ' :
2011-05-11 12:07:46 +02:00
title = _ ( ' User by Priority ' )
col1heading = _ ( ' User ' )
possible_options = [ t [ 1 ] . __unicode__ ( ) for t in Ticket . PRIORITY_CHOICES ]
charttype = ' bar '
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
elif report == ' userqueue ' :
2011-05-11 12:07:46 +02:00
title = _ ( ' User by Queue ' )
col1heading = _ ( ' User ' )
possible_options = [ q . title . encode ( ' utf-8 ' ) for q in Queue . objects . all ( ) ]
charttype = ' bar '
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
elif report == ' userstatus ' :
2011-05-11 12:07:46 +02:00
title = _ ( ' User by Status ' )
col1heading = _ ( ' User ' )
possible_options = [ s [ 1 ] . __unicode__ ( ) for s in Ticket . STATUS_CHOICES ]
charttype = ' bar '
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
elif report == ' usermonth ' :
2011-05-11 12:07:46 +02:00
title = _ ( ' User by Month ' )
col1heading = _ ( ' User ' )
possible_options = periods
charttype = ' date '
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
elif report == ' queuepriority ' :
2011-05-11 12:07:46 +02:00
title = _ ( ' Queue by Priority ' )
col1heading = _ ( ' Queue ' )
possible_options = [ t [ 1 ] . __unicode__ ( ) for t in Ticket . PRIORITY_CHOICES ]
charttype = ' bar '
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
elif report == ' queuestatus ' :
2011-05-11 12:07:46 +02:00
title = _ ( ' Queue by Status ' )
col1heading = _ ( ' Queue ' )
possible_options = [ s [ 1 ] . __unicode__ ( ) for s in Ticket . STATUS_CHOICES ]
charttype = ' bar '
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
elif report == ' queuemonth ' :
2011-05-11 12:07:46 +02:00
title = _ ( ' Queue by Month ' )
col1heading = _ ( ' Queue ' )
possible_options = periods
charttype = ' date '
2008-04-02 01:26:12 +02:00
2011-05-11 12:07:46 +02:00
for ticket in report_queryset :
if report == ' userpriority ' :
metric1 = u ' %s ' % ticket . get_assigned_to
metric2 = u ' %s ' % ticket . get_priority_display ( )
2008-04-02 01:26:12 +02:00
2011-05-11 12:07:46 +02:00
elif report == ' userqueue ' :
metric1 = u ' %s ' % ticket . get_assigned_to
metric2 = u ' %s ' % ticket . queue . title
2008-04-02 01:26:12 +02:00
2011-05-11 12:07:46 +02:00
elif report == ' userstatus ' :
metric1 = u ' %s ' % ticket . get_assigned_to
metric2 = u ' %s ' % ticket . get_status_display ( )
elif report == ' usermonth ' :
metric1 = u ' %s ' % ticket . get_assigned_to
metric2 = u ' %s %s ' % ( months [ ticket . created . month ] , ticket . created . year )
elif report == ' queuepriority ' :
metric1 = u ' %s ' % ticket . queue . title
metric2 = u ' %s ' % ticket . get_priority_display ( )
elif report == ' queuestatus ' :
metric1 = u ' %s ' % ticket . queue . title
metric2 = u ' %s ' % ticket . get_status_display ( )
elif report == ' queuemonth ' :
metric1 = u ' %s ' % ticket . queue . title
metric2 = u ' %s %s ' % ( months [ ticket . created . month ] , ticket . created . year )
summarytable [ metric1 , metric2 ] + = 1
table = [ ]
header1 = sorted ( set ( list ( i . encode ( ' utf-8 ' ) for i , _ in summarytable . keys ( ) ) ) )
column_headings = [ col1heading ] + possible_options
# Pivot the data so that 'header1' fields are always first column
# in the row, and 'possible_options' are always the 2nd - nth columns.
for item in header1 :
data = [ ]
for hdr in possible_options :
data . append ( summarytable [ item , hdr ] )
table . append ( [ item ] + data )
2008-08-19 10:50:38 +02:00
2008-04-02 01:26:12 +02:00
return render_to_response ( ' helpdesk/report_output.html ' ,
RequestContext ( request , {
2008-10-25 00:52:34 +02:00
' title ' : title ,
2011-05-03 00:32:51 +02:00
' charttype ' : charttype ,
2011-05-11 12:07:46 +02:00
' data ' : table ,
' headings ' : column_headings ,
' from_saved_query ' : from_saved_query ,
' saved_query ' : saved_query ,
2008-04-02 01:26:12 +02:00
} ) )
2009-01-11 01:26:00 +01:00
run_report = staff_member_required ( run_report )
2008-08-19 10:50:38 +02:00
2008-08-28 11:06:24 +02:00
def save_query ( request ) :
title = request . POST . get ( ' title ' , None )
shared = request . POST . get ( ' shared ' , False )
query_encoded = request . POST . get ( ' query_encoded ' , None )
2009-03-08 07:03:55 +01:00
2008-08-28 11:06:24 +02:00
if not title or not query_encoded :
return HttpResponseRedirect ( reverse ( ' helpdesk_list ' ) )
2009-03-08 07:03:55 +01:00
2008-08-28 11:06:24 +02:00
query = SavedSearch ( title = title , shared = shared , query = query_encoded , user = request . user )
query . save ( )
2009-03-08 07:03:55 +01:00
2008-08-28 11:06:24 +02:00
return HttpResponseRedirect ( ' %s ?saved_query= %s ' % ( reverse ( ' helpdesk_list ' ) , query . id ) )
2009-01-11 01:26:00 +01:00
save_query = staff_member_required ( save_query )
2008-08-28 11:06:24 +02:00
def delete_saved_query ( request , id ) :
query = get_object_or_404 ( SavedSearch , id = id , user = request . user )
if request . method == ' POST ' :
query . delete ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_list ' ) )
else :
return render_to_response ( ' helpdesk/confirm_delete_saved_query.html ' ,
RequestContext ( request , {
' query ' : query ,
} ) )
2009-01-11 01:26:00 +01:00
delete_saved_query = staff_member_required ( delete_saved_query )
2008-09-09 10:32:01 +02:00
2008-10-25 00:52:34 +02:00
2008-09-09 10:32:01 +02:00
def user_settings ( request ) :
s = request . user . usersettings
if request . POST :
form = UserSettingsForm ( request . POST )
if form . is_valid ( ) :
s . settings = form . cleaned_data
s . save ( )
else :
form = UserSettingsForm ( s . settings )
2011-11-24 13:30:45 +01:00
user = User . objects . get ( id = request . user . id )
show_password_change_link = 0
# we don't want non-local users to see the 'change password' link.
if helpdesk_settings . HELPDESK_SHOW_CHANGE_PASSWORD and user . has_usable_password ( ) :
show_password_change_link = 1
2008-09-09 10:32:01 +02:00
return render_to_response ( ' helpdesk/user_settings.html ' ,
RequestContext ( request , {
' form ' : form ,
2011-11-24 13:30:45 +01:00
' show_password_change_link ' : show_password_change_link ,
2008-09-09 10:32:01 +02:00
} ) )
2009-01-11 01:26:00 +01:00
user_settings = staff_member_required ( user_settings )
2008-10-25 00:52:34 +02:00
def email_ignore ( request ) :
return render_to_response ( ' helpdesk/email_ignore_list.html ' ,
RequestContext ( request , {
' ignore_list ' : IgnoreEmail . objects . all ( ) ,
} ) )
email_ignore = superuser_required ( email_ignore )
def email_ignore_add ( request ) :
if request . method == ' POST ' :
form = EmailIgnoreForm ( request . POST )
if form . is_valid ( ) :
ignore = form . save ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_email_ignore ' ) )
else :
form = EmailIgnoreForm ( request . GET )
return render_to_response ( ' helpdesk/email_ignore_add.html ' ,
RequestContext ( request , {
' form ' : form ,
} ) )
email_ignore_add = superuser_required ( email_ignore_add )
def email_ignore_del ( request , id ) :
ignore = get_object_or_404 ( IgnoreEmail , id = id )
if request . method == ' POST ' :
ignore . delete ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_email_ignore ' ) )
else :
return render_to_response ( ' helpdesk/email_ignore_del.html ' ,
RequestContext ( request , {
' ignore ' : ignore ,
} ) )
email_ignore_del = superuser_required ( email_ignore_del )
2009-09-09 10:47:48 +02:00
def ticket_cc ( request , ticket_id ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
copies_to = ticket . ticketcc_set . all ( )
return render_to_response ( ' helpdesk/ticket_cc_list.html ' ,
RequestContext ( request , {
' copies_to ' : copies_to ,
' ticket ' : ticket ,
} ) )
ticket_cc = staff_member_required ( ticket_cc )
def ticket_cc_add ( request , ticket_id ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
if request . method == ' POST ' :
form = TicketCCForm ( request . POST )
if form . is_valid ( ) :
ticketcc = form . save ( commit = False )
ticketcc . ticket = ticket
ticketcc . save ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_ticket_cc ' , kwargs = { ' ticket_id ' : ticket . id } ) )
else :
form = TicketCCForm ( )
return render_to_response ( ' helpdesk/ticket_cc_add.html ' ,
RequestContext ( request , {
' ticket ' : ticket ,
' form ' : form ,
} ) )
ticket_cc_add = staff_member_required ( ticket_cc_add )
def ticket_cc_del ( request , ticket_id , cc_id ) :
cc = get_object_or_404 ( TicketCC , ticket__id = ticket_id , id = cc_id )
2010-01-26 01:01:22 +01:00
if request . method == ' POST ' :
2009-09-09 10:47:48 +02:00
cc . delete ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_ticket_cc ' , kwargs = { ' ticket_id ' : cc . ticket . id } ) )
return render_to_response ( ' helpdesk/ticket_cc_del.html ' ,
RequestContext ( request , {
' cc ' : cc ,
} ) )
ticket_cc_del = staff_member_required ( ticket_cc_del )
2011-05-10 11:27:11 +02:00
def ticket_dependency_add ( request , ticket_id ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
if request . method == ' POST ' :
form = TicketDependencyForm ( request . POST )
if form . is_valid ( ) :
ticketdependency = form . save ( commit = False )
ticketdependency . ticket = ticket
if ticketdependency . ticket < > ticketdependency . depends_on :
ticketdependency . save ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_view ' , args = [ ticket . id ] ) )
else :
form = TicketDependencyForm ( )
return render_to_response ( ' helpdesk/ticket_dependency_add.html ' ,
RequestContext ( request , {
' ticket ' : ticket ,
' form ' : form ,
} ) )
ticket_dependency_add = staff_member_required ( ticket_dependency_add )
def ticket_dependency_del ( request , ticket_id , dependency_id ) :
dependency = get_object_or_404 ( TicketDependency , ticket__id = ticket_id , id = dependency_id )
if request . method == ' POST ' :
dependency . delete ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_view ' , args = [ ticket_id ] ) )
return render_to_response ( ' helpdesk/ticket_dependency_del.html ' ,
RequestContext ( request , {
' dependency ' : dependency ,
} ) )
ticket_dependency_del = staff_member_required ( ticket_dependency_del )
2011-11-19 09:34:07 +01:00
def attachment_del ( request , ticket_id , attachment_id ) :
ticket = get_object_or_404 ( Ticket , id = ticket_id )
attachment = get_object_or_404 ( Attachment , id = attachment_id )
attachment . delete ( )
return HttpResponseRedirect ( reverse ( ' helpdesk_view ' , args = [ ticket_id ] ) )
attachment_del = staff_member_required ( attachment_del )