Skip to content

Commit

Permalink
Issue #102
Browse files Browse the repository at this point in the history
Add rudimentary CC: functionality on tickets, controlled by staff users. CC's 
can be e-mail addresses or users, who will receive copies of all emails sent 
to the Submitter. This is a work in progress.
  • Loading branch information
rossp committed Sep 9, 2009
1 parent a9d5bb6 commit f419d8e
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
2009-09-09 r138 Issue #104 Add a CHANGELOG file

2009-09-09 r139 Issue #102 Add Ticket CC's
Add rudimentary CC: functionality on tickets, controlled by staff users. CC's
can be e-mail addresses or users, who will receive copies of all emails sent
to the Submitter. This is a work in progress.
7 changes: 6 additions & 1 deletion forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from django.utils.translation import ugettext as _

from helpdesk.lib import send_templated_mail
from helpdesk.models import Ticket, Queue, FollowUp, Attachment, IgnoreEmail
from helpdesk.models import Ticket, Queue, FollowUp, Attachment, IgnoreEmail, TicketCC

class EditTicketForm(forms.ModelForm):
class Meta:
Expand Down Expand Up @@ -356,3 +356,8 @@ class UserSettingsForm(forms.Form):
class EmailIgnoreForm(forms.ModelForm):
class Meta:
model = IgnoreEmail

class TicketCCForm(forms.ModelForm):
class Meta:
model = TicketCC
exclude = ('ticket',)
57 changes: 56 additions & 1 deletion models.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class Queue(models.Model):
help_text=_('Whether to use SSL for IMAP or POP3 - the default ports '
'when using SSL are 993 for IMAP and 995 for POP3.'),
)

email_box_user = models.CharField(
_('E-Mail Username'),
max_length=200,
Expand Down Expand Up @@ -999,3 +999,58 @@ def test(self, email):
return True
else:
return False

class TicketCC(models.Model):
"""
Often, there are people who wish to follow a ticket who aren't the
person who originally submitted it. This model provides a way for those
people to follow a ticket.
In this circumstance, a 'person' could be either an e-mail address or
an existing system user.
"""

ticket = models.ForeignKey(Ticket)

user = models.ForeignKey(
User,
blank=True,
null=True,
help_text=_('User who wishes to receive updates for this ticket.'),
)

email = models.EmailField(
_('E-Mail Address'),
blank=True,
null=True,
help_text=_('For non-user followers, enter their e-mail address'),
)

can_view = models.BooleanField(
_('Can View Ticket?'),
blank=True,
help_text=_('Can this CC login to view the ticket details?'),
)

can_update = models.BooleanField(
_('Can Update Ticket?'),
blank=True,
help_text=_('Can this CC login and update the ticket?'),
)

def _email_address(self):
if self.user and self.user.email is not None:
return self.user.email
else:
return self.email
email_address = property(_email_address)

def _display(self):
if self.user:
return self.user
else:
return self.email
display = property(_display)

def __unicode__(self):
return u'%s for %s' % (self.display, self.ticket.title)
2 changes: 1 addition & 1 deletion templates/helpdesk/email_ignore_del.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{% block helpdesk_body %}{% blocktrans with ignore.email_address as email_address %}
<h2>Un-Ignore E-Mail Address</h2>

<p>Are you sure you wish to stop removing this email address (<em>{{ email_address }}</em>) and allow their e-mails to automatically create tickets in your system? You can re-add this e-mail address at any time.<?p>
<p>Are you sure you wish to stop removing this email address (<em>{{ email_address }}</em>) and allow their e-mails to automatically create tickets in your system? You can re-add this e-mail address at any time.</p>
{% endblocktrans %}

{% blocktrans %}<p><a href='../../'>Keep Ignoring It</a></p>
Expand Down
11 changes: 8 additions & 3 deletions templates/helpdesk/ticket.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,21 @@
</tr>

<tr class='row_odd'>
<th colspan='2'>{% trans "Description" %}</th>
<th>{% trans "Copies To" %}</th>
<td>{% for ticketcc in ticket.ticketcc_set.all %}{{ ticketcc.display }}{% if not forloop.last %}, {% endif %}{% endfor %} <strong><a href='{% url helpdesk_ticket_cc ticket.id %}'>{% trans "Manage" %}</a></strong></td>
</tr>

<tr class='row_even'>
<th colspan='2'>{% trans "Description" %}</th>
</tr>
<tr class='row_odd'>
<td colspan='2'>{{ ticket.description|force_escape|linebreaksbr }}</td>
</tr>

{% if ticket.resolution %}<tr class='row_odd'>
{% if ticket.resolution %}<tr class='row_even'>
<th colspan='2'>{% trans "Resolution" %}{% ifequal ticket.get_status_display "Resolved" %} <a href='?close'><img src='{{ MEDIA_URL }}helpdesk/buttons/accept.png' alt='{% trans "Accept" %}' title='{% trans "Accept and Close" %}' width='60' height='15' /></a>{% endifequal %}</th>
</tr>
<tr class='row_even'>
<tr class='row_odd'>
<td colspan='2'>{{ ticket.resolution|force_escape }}</td>
</tr>{% endif %}

Expand Down
25 changes: 25 additions & 0 deletions templates/helpdesk/ticket_cc_add.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{% extends "helpdesk/base.html" %}{% load i18n %}

{% block helpdesk_title %}{% trans "Add Ticket CC" %}{% endblock %}

{% block helpdesk_body %}{% blocktrans %}
<h2>Add Ticket CC</h2>

<p>To automatically send an email to a user or e-mail address when this ticket is updated, select the user or enter an e-mail address below.</p>{% endblocktrans %}

<form method='post' action='./'>

<fieldset>
<dl>{% for field in form %}
<dt><label for='id_{{ field.name }}'>{{ field.label }}</label></dt>
<dd>{{ field }}</dd>
{% if field.errors %}<dd class='error'>{{ field.errors }}</dd>{% endif %}
{% if field.help_text %}<dd class='form_help_text'>{{ field.help_text }}</dd>{% endif %}
{% endfor %}</dl>
</fieldset>

<input type='submit' value='{% trans "Save Ticket CC" %}' />

</form>

{% endblock %}
14 changes: 14 additions & 0 deletions templates/helpdesk/ticket_cc_del.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends "helpdesk/base.html" %}{% load i18n %}

{% block helpdesk_title %}{% trans "Delete Ticket CC" %}{% endblock %}

{% block helpdesk_body %}{% blocktrans with cc.email_address as email_address %}
<h2>Delete Ticket CC</h2>

<p>Are you sure you wish to delete this email address (<em>{{ email_address }}</em>) from the CC list for this ticket? They will stop receiving updates.</p>
{% endblocktrans %}

{% blocktrans %}<p><a href='../../'>Don't Delete</a></p>

<form method='post' action='./'><input type='submit' value='Yes, Delete' /></form>
{% endblocktrans %}{% endblock %}
31 changes: 31 additions & 0 deletions templates/helpdesk/ticket_cc_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{% extends "helpdesk/base.html" %}{% load i18n %}

{% block helpdesk_title %}{% trans "Ticket CC Settings" %}{% endblock %}

{% block helpdesk_body %}{% blocktrans with ticket.title as ticket_title and ticket.id as ticket_id %}
<h2>Ticket CC Settings</h2>

<p>The following people will receive an e-mail whenever <em><a href='../'>{{ ticket_title }}</a></em> is updated. Some people can also view or edit the ticket via the public ticket views.</p>

<p>You can <a href='add/'>add a new e-mail address to the list</a> or delete any of the items below as required.</p>{% endblocktrans %}

<table width='100%'>
<thead>
<tr class='row_tablehead'><td colspan='4'>{% trans "Ticket CC List" %}</td></tr>
<tr class='row_columnheads'><th>{% trans "E-Mail Address" %}</th><th>{% trans "View?" %}</th><th>{% trans "Update?" %}</th><th>{% trans "Delete" %}</th></tr>
</thead>
<tbody>
{% for person in copies_to %}
<tr class='row_{% cycle odd,even %}'>
<td>{{ person.display }}</td>
<td>{{ person.can_view }}</td>
<td>{{ person.can_update }}</td>
<td><a href='{% url helpdesk_ticket_cc_del ticket.id person.id %}'>{% trans "Delete" %}</a></td>
</tr>
{% endfor %}
</tbody>
</table>

<p><a href='{% url helpdesk_view ticket.id %}'>{% blocktrans with ticket.title as ticket_title %}Return to <em>{{ ticket_title }}</em>{% endblocktrans %}</a></p>

{% endblock %}
12 changes: 12 additions & 0 deletions urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@
'unhold_ticket',
name='helpdesk_unhold'),

url(r'^tickets/(?P<ticket_id>[0-9]+)/cc/$',
'ticket_cc',
name='helpdesk_ticket_cc'),

url(r'^tickets/(?P<ticket_id>[0-9]+)/cc/add/$',
'ticket_cc_add',
name='helpdesk_ticket_cc_add'),

url(r'^tickets/(?P<ticket_id>[0-9]+)/cc/delete/(?P<cc_id>[0-9]+)/$',
'ticket_cc_del',
name='helpdesk_ticket_cc_del'),

url(r'^raw/(?P<type>\w+)/$',
'raw_details',
name='helpdesk_raw'),
Expand Down
23 changes: 23 additions & 0 deletions views/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,18 @@ def api_public_add_followup(self):
)
messages_sent_to.append(ticket.submitter_email)

if public:
for cc in ticket.ticketcc_set.all():
if cc.email_address not in messages_sent_to:
send_templated_mail(
'updated_submitter',
context,
recipients=cc.email_address,
sender=ticket.queue.from_address,
fail_silently=True,
)
messages_sent_to.append(cc.email_address)

if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to:
send_templated_mail(
'updated_cc',
Expand Down Expand Up @@ -274,6 +286,17 @@ def api_public_resolve(self):
)
messages_sent_to.append(ticket.submitter_email)

for cc in ticket.ticketcc_set.all():
if cc.email_address not in messages_sent_to:
send_templated_mail(
'resolved_submitter',
context,
recipients=cc.email_address,
sender=ticket.queue.from_address,
fail_silently=True,
)
messages_sent_to.append(cc.email_address)

if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to:
send_templated_mail(
'resolved_cc',
Expand Down
66 changes: 64 additions & 2 deletions views/staff.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
from django.template import loader, Context, RequestContext
from django.utils.translation import ugettext as _

from helpdesk.forms import TicketForm, UserSettingsForm, EmailIgnoreForm, EditTicketForm
from helpdesk.forms import TicketForm, UserSettingsForm, EmailIgnoreForm, EditTicketForm, TicketCCForm
from helpdesk.lib import send_templated_mail, line_chart, bar_chart, query_to_dict, apply_query, safe_template_context
from helpdesk.models import Ticket, Queue, FollowUp, TicketChange, PreSetReply, Attachment, SavedSearch, IgnoreEmail
from helpdesk.models import Ticket, Queue, FollowUp, TicketChange, PreSetReply, Attachment, SavedSearch, IgnoreEmail, TicketCC


staff_member_required = user_passes_test(lambda u: u.is_authenticated() and u.is_active and u.is_staff)
Expand Down Expand Up @@ -259,6 +259,17 @@ def update_ticket(request, ticket_id, public=False):
)
messages_sent_to.append(ticket.submitter_email)

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)

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:
# We only send e-mails to staff members if the ticket is updated by
# another user. The actual template varies, depending on what has been
Expand Down Expand Up @@ -364,6 +375,17 @@ def mass_update(request):
)
messages_sent_to.append(t.submitter_email)

for cc in ticket.ticketcc_set.all():
if cc.email_address not in messages_sent_to:
send_templated_mail(
'closed_submitter',
context,
recipients=cc.email_address,
sender=ticket.queue.from_address,
fail_silently=True,
)
messages_sent_to.append(cc.email_address)

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:
send_templated_mail(
'closed_owner',
Expand Down Expand Up @@ -563,6 +585,7 @@ def edit_ticket(request, ticket_id):
RequestContext(request, {
'form': form,
}))
edit_ticket = staff_member_required(edit_ticket)

def create_ticket(request):
if request.method == 'POST':
Expand Down Expand Up @@ -890,3 +913,42 @@ def email_ignore_del(request, id):
'ignore': ignore,
}))
email_ignore_del = superuser_required(email_ignore_del)

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)
if request.POST:
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)

0 comments on commit f419d8e

Please sign in to comment.