Merge pull request #106 from yekibud/master

adding global queue email settings for get_mail and HELPDESK_KB_ENABLED_STAFF; added ticket due date
This commit is contained in:
Ross Poulton 2012-01-23 15:15:44 -08:00
commit 7e72f3d8ea
10 changed files with 482 additions and 1373 deletions

View File

@ -19,6 +19,7 @@ from django.utils.translation import ugettext as _
from helpdesk.lib import send_templated_mail, safe_template_context from helpdesk.lib import send_templated_mail, safe_template_context
from helpdesk.models import Ticket, Queue, FollowUp, Attachment, IgnoreEmail, TicketCC, CustomField, TicketCustomFieldValue, TicketDependency from helpdesk.models import Ticket, Queue, FollowUp, Attachment, IgnoreEmail, TicketCC, CustomField, TicketCustomFieldValue, TicketDependency
from helpdesk.settings import HAS_TAG_SUPPORT from helpdesk.settings import HAS_TAG_SUPPORT
from helpdesk import settings as helpdesk_settings
class EditTicketForm(forms.ModelForm): class EditTicketForm(forms.ModelForm):
class Meta: class Meta:
@ -58,8 +59,8 @@ class EditTicketForm(forms.ModelForm):
instanceargs['max_digits'] = field.max_length instanceargs['max_digits'] = field.max_length
elif field.data_type == 'list': elif field.data_type == 'list':
fieldclass = forms.ChoiceField fieldclass = forms.ChoiceField
if field.empty_selection_list:
choices = field.choices_as_array choices = field.choices_as_array
if field.empty_selection_list:
choices.insert(0, ('','---------' ) ) choices.insert(0, ('','---------' ) )
instanceargs['choices'] = choices instanceargs['choices'] = choices
elif field.data_type == 'boolean': elif field.data_type == 'boolean':
@ -152,6 +153,19 @@ class TicketForm(forms.Form):
'as \'3\'.'), 'as \'3\'.'),
) )
due_date = forms.DateTimeField(
widget=extras.SelectDateWidget,
required=False,
label=_('Due on'),
)
def clean_due_date(self):
data = self.cleaned_data['due_date']
#TODO: add Google calendar update hook
#if not hasattr(self, 'instance') or self.instance.due_date != new_data:
# print "you changed!"
return data
attachment = forms.FileField( attachment = forms.FileField(
required=False, required=False,
label=_('Attach File'), label=_('Attach File'),
@ -195,8 +209,8 @@ class TicketForm(forms.Form):
instanceargs['max_digits'] = field.max_length instanceargs['max_digits'] = field.max_length
elif field.data_type == 'list': elif field.data_type == 'list':
fieldclass = forms.ChoiceField fieldclass = forms.ChoiceField
if field.empty_selection_list:
choices = field.choices_as_array choices = field.choices_as_array
if field.empty_selection_list:
choices.insert(0, ('','---------' ) ) choices.insert(0, ('','---------' ) )
instanceargs['choices'] = choices instanceargs['choices'] = choices
elif field.data_type == 'boolean': elif field.data_type == 'boolean':
@ -234,6 +248,7 @@ class TicketForm(forms.Form):
queue = q, queue = q,
description = self.cleaned_data['body'], description = self.cleaned_data['body'],
priority = self.cleaned_data['priority'], priority = self.cleaned_data['priority'],
due_date = self.cleaned_data['due_date'],
) )
if HAS_TAG_SUPPORT: if HAS_TAG_SUPPORT:
@ -376,6 +391,12 @@ class PublicTicketForm(forms.Form):
help_text=_('Please select a priority carefully.'), help_text=_('Please select a priority carefully.'),
) )
due_date = forms.DateTimeField(
widget=extras.SelectDateWidget,
required=False,
label=_('Due on'),
)
attachment = forms.FileField( attachment = forms.FileField(
required=False, required=False,
label=_('Attach File'), label=_('Attach File'),
@ -408,8 +429,8 @@ class PublicTicketForm(forms.Form):
instanceargs['max_digits'] = field.max_length instanceargs['max_digits'] = field.max_length
elif field.data_type == 'list': elif field.data_type == 'list':
fieldclass = forms.ChoiceField fieldclass = forms.ChoiceField
if field.empty_selection_list:
choices = field.choices_as_array choices = field.choices_as_array
if field.empty_selection_list:
choices.insert(0, ('','---------' ) ) choices.insert(0, ('','---------' ) )
instanceargs['choices'] = choices instanceargs['choices'] = choices
elif field.data_type == 'boolean': elif field.data_type == 'boolean':
@ -446,6 +467,7 @@ class PublicTicketForm(forms.Form):
queue = q, queue = q,
description = self.cleaned_data['body'], description = self.cleaned_data['body'],
priority = self.cleaned_data['priority'], priority = self.cleaned_data['priority'],
due_date = self.cleaned_data['due_date'],
) )
t.save() t.save()
@ -572,7 +594,11 @@ class EmailIgnoreForm(forms.ModelForm):
class TicketCCForm(forms.ModelForm): class TicketCCForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(TicketCCForm, self).__init__(*args, **kwargs) super(TicketCCForm, self).__init__(*args, **kwargs)
self.fields['user'].queryset = User.objects.filter(is_active=True).order_by('username') if helpdesk_settings.HELPDESK_STAFF_ONLY_TICKET_CC:
users = User.objects.filter(is_active=True, is_staff=True).order_by('username')
else:
users = User.objects.filter(is_active=True).order_by('username')
self.fields['user'].queryset = users
class Meta: class Meta:
model = TicketCC model = TicketCC
exclude = ('ticket',) exclude = ('ticket',)

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@ from django.core.files.base import ContentFile
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db.models import Q from django.db.models import Q
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings
from helpdesk.lib import send_templated_mail, safe_template_context from helpdesk.lib import send_templated_mail, safe_template_context
from helpdesk.models import Queue, Ticket, FollowUp, Attachment, IgnoreEmail from helpdesk.models import Queue, Ticket, FollowUp, Attachment, IgnoreEmail
@ -75,18 +76,22 @@ def process_email(quiet=False):
def process_queue(q, quiet=False): def process_queue(q, quiet=False):
if not quiet: if not quiet:
print "Processing: %s" % q print "Processing: %s" % q
if q.email_box_type == 'pop3':
if q.email_box_ssl: email_box_type = settings.QUEUE_EMAIL_BOX_TYPE if settings.QUEUE_EMAIL_BOX_TYPE else q.email_box_type
if email_box_type == 'pop3':
if q.email_box_ssl or settings.QUEUE_EMAIL_BOX_SSL:
if not q.email_box_port: q.email_box_port = 995 if not q.email_box_port: q.email_box_port = 995
server = poplib.POP3_SSL(q.email_box_host, int(q.email_box_port)) server = poplib.POP3_SSL(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
else: else:
if not q.email_box_port: q.email_box_port = 110 if not q.email_box_port: q.email_box_port = 110
server = poplib.POP3(q.email_box_host, int(q.email_box_port)) server = poplib.POP3(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
server.getwelcome() server.getwelcome()
server.user(q.email_box_user) server.user(q.email_box_user or settings.QUEUE_EMAIL_BOX_USER)
server.pass_(q.email_box_pass) server.pass_(q.email_box_pass or settings.QUEUE_EMAIL_BOX_PASSWORD)
messagesInfo = server.list()[1] messagesInfo = server.list()[1]
@ -102,15 +107,15 @@ def process_queue(q, quiet=False):
server.quit() server.quit()
elif q.email_box_type == 'imap': elif email_box_type == 'imap':
if q.email_box_ssl: if q.email_box_ssl or settings.QUEUE_EMAIL_BOX_SSL:
if not q.email_box_port: q.email_box_port = 993 if not q.email_box_port: q.email_box_port = 993
server = imaplib.IMAP4_SSL(q.email_box_host, int(q.email_box_port)) server = imaplib.IMAP4_SSL(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
else: else:
if not q.email_box_port: q.email_box_port = 143 if not q.email_box_port: q.email_box_port = 143
server = imaplib.IMAP4(q.email_box_host, int(q.email_box_port)) server = imaplib.IMAP4(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
server.login(q.email_box_user, q.email_box_pass) server.login(q.email_box_user or settings.QUEUE_EMAIL_BOX_USER, q.email_box_pass or settings.QUEUE_EMAIL_BOX_PASSWORD)
server.select(q.email_box_imap_folder) server.select(q.email_box_imap_folder)
status, data = server.search(None, 'NOT', 'DELETED') status, data = server.search(None, 'NOT', 'DELETED')

View File

@ -0,0 +1,228 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Ticket.due_date'
db.add_column('helpdesk_ticket', 'due_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)
def backwards(self, orm):
# Deleting field 'Ticket.due_date'
db.delete_column('helpdesk_ticket', 'due_date')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'helpdesk.attachment': {
'Meta': {'ordering': "['filename']", 'object_name': 'Attachment'},
'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'filename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'followup': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.FollowUp']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'size': ('django.db.models.fields.IntegerField', [], {})
},
'helpdesk.customfield': {
'Meta': {'object_name': 'CustomField'},
'data_type': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'decimal_places': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'empty_selection_list': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'help_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': "'30'"}),
'list_values': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'max_length': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}),
'ordering': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'staff_only': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'helpdesk.emailtemplate': {
'Meta': {'ordering': "['template_name', 'locale']", 'object_name': 'EmailTemplate'},
'heading': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'html': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'locale': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'plain_text': ('django.db.models.fields.TextField', [], {}),
'subject': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'template_name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'helpdesk.escalationexclusion': {
'Meta': {'object_name': 'EscalationExclusion'},
'date': ('django.db.models.fields.DateField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'queues': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['helpdesk.Queue']", 'null': 'True', 'blank': 'True'})
},
'helpdesk.followup': {
'Meta': {'ordering': "['date']", 'object_name': 'FollowUp'},
'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 1, 20, 12, 19, 46, 778593)'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_status': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'ticket': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.Ticket']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
'helpdesk.ignoreemail': {
'Meta': {'object_name': 'IgnoreEmail'},
'date': ('django.db.models.fields.DateField', [], {'blank': 'True'}),
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'keep_in_mailbox': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'queues': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['helpdesk.Queue']", 'null': 'True', 'blank': 'True'})
},
'helpdesk.kbcategory': {
'Meta': {'ordering': "['title']", 'object_name': 'KBCategory'},
'description': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'helpdesk.kbitem': {
'Meta': {'ordering': "['title']", 'object_name': 'KBItem'},
'answer': ('django.db.models.fields.TextField', [], {}),
'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.KBCategory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_updated': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
'question': ('django.db.models.fields.TextField', [], {}),
'recommendations': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'votes': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'helpdesk.presetreply': {
'Meta': {'ordering': "['name']", 'object_name': 'PreSetReply'},
'body': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'queues': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['helpdesk.Queue']", 'null': 'True', 'blank': 'True'})
},
'helpdesk.queue': {
'Meta': {'ordering': "('title',)", 'object_name': 'Queue'},
'allow_email_submission': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'allow_public_submission': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
'email_box_host': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'email_box_imap_folder': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'email_box_interval': ('django.db.models.fields.IntegerField', [], {'default': "'5'", 'null': 'True', 'blank': 'True'}),
'email_box_last_check': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'email_box_pass': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'email_box_port': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'email_box_ssl': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'email_box_type': ('django.db.models.fields.CharField', [], {'max_length': '5', 'null': 'True', 'blank': 'True'}),
'email_box_user': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'escalate_days': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'locale': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'new_ticket_cc': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'updated_ticket_cc': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
},
'helpdesk.savedsearch': {
'Meta': {'object_name': 'SavedSearch'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'query': ('django.db.models.fields.TextField', [], {}),
'shared': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'helpdesk.ticket': {
'Meta': {'object_name': 'Ticket'},
'assigned_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'assigned_to'", 'null': 'True', 'to': "orm['auth.User']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'due_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_escalation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
'on_hold': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'priority': ('django.db.models.fields.IntegerField', [], {'default': '3', 'blank': '3'}),
'queue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.Queue']"}),
'resolution': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
'submitter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
},
'helpdesk.ticketcc': {
'Meta': {'object_name': 'TicketCC'},
'can_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'can_view': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ticket': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.Ticket']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
'helpdesk.ticketchange': {
'Meta': {'object_name': 'TicketChange'},
'field': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'followup': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.FollowUp']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'old_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'helpdesk.ticketcustomfieldvalue': {
'Meta': {'unique_together': "(('ticket', 'field'),)", 'object_name': 'TicketCustomFieldValue'},
'field': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.CustomField']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ticket': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['helpdesk.Ticket']"}),
'value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
},
'helpdesk.ticketdependency': {
'Meta': {'unique_together': "(('ticket', 'depends_on'),)", 'object_name': 'TicketDependency'},
'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'depends_on'", 'to': "orm['helpdesk.Ticket']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticketdependency'", 'to': "orm['helpdesk.Ticket']"})
},
'helpdesk.usersettings': {
'Meta': {'object_name': 'UserSettings'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'settings_pickled': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
}
}
complete_apps = ['helpdesk']

View File

@ -326,6 +326,12 @@ class Ticket(models.Model):
help_text=_('1 = Highest Priority, 5 = Low Priority'), help_text=_('1 = Highest Priority, 5 = Low Priority'),
) )
due_date = models.DateTimeField(
_('Due on'),
blank=True,
null=True,
)
last_escalation = models.DateTimeField( last_escalation = models.DateTimeField(
blank=True, blank=True,
null=True, null=True,

View File

@ -40,6 +40,9 @@ HELPDESK_PREPEND_ORG_NAME = getattr(settings, 'HELPDESK_PREPEND_ORG_NAME', False
# show knowledgebase links? # show knowledgebase links?
HELPDESK_KB_ENABLED = getattr(settings, 'HELPDESK_KB_ENABLED', True) HELPDESK_KB_ENABLED = getattr(settings, 'HELPDESK_KB_ENABLED', True)
# show knowledgebase links on staff view?
HELPDESK_KB_ENABLED_STAFF = getattr(settings, 'HELPDESK_KB_ENABLED_STAFF', False)
# show extended navigation by default, to all users, irrespective of staff status? # show extended navigation by default, to all users, irrespective of staff status?
HELPDESK_NAVIGATION_ENABLED = getattr(settings, 'HELPDESK_NAVIGATION_ENABLED', False) HELPDESK_NAVIGATION_ENABLED = getattr(settings, 'HELPDESK_NAVIGATION_ENABLED', False)
@ -97,6 +100,12 @@ HELPDESK_SHOW_HOLD_BUTTON_TICKET_TOP = getattr(settings, 'HELPDESK_SHOW_HOLD_BUT
# make all updates public by default? this will hide the 'is this update public' checkbox # make all updates public by default? this will hide the 'is this update public' checkbox
HELPDESK_UPDATE_PUBLIC_DEFAULT = getattr(settings, 'HELPDESK_UPDATE_PUBLIC_DEFAULT', True) HELPDESK_UPDATE_PUBLIC_DEFAULT = getattr(settings, 'HELPDESK_UPDATE_PUBLIC_DEFAULT', True)
# only show staff users in ticket owner drop-downs
HELPDESK_STAFF_ONLY_TICKET_OWNERS = getattr(settings, 'HELPDESK_STAFF_ONLY_TICKET_OWNERS', False)
# only show staff users in ticket cc drop-down
HELPDESK_STAFF_ONLY_TICKET_CC = getattr(settings, 'HELPDESK_STAFF_ONLY_TICKET_CC', False)
''' options for staff.create_ticket view ''' ''' options for staff.create_ticket view '''
@ -121,3 +130,10 @@ HELPDESK_FOOTER_SHOW_API_LINK = getattr(settings, 'HELPDESK_FOOTER_SHOW_API_LINK
# show / hide 'change language' link at bottom of page # show / hide 'change language' link at bottom of page
HELPDESK_FOOTER_SHOW_CHANGE_LANGUAGE_LINK = getattr(settings, 'HELPDESK_FOOTER_SHOW_CHANGE_LANGUAGE_LINK', False) HELPDESK_FOOTER_SHOW_CHANGE_LANGUAGE_LINK = getattr(settings, 'HELPDESK_FOOTER_SHOW_CHANGE_LANGUAGE_LINK', False)
''' email options '''
# default Queue email submission settings
QUEUE_EMAIL_BOX_TYPE = getattr(settings, 'QUEUE_EMAIL_BOX_TYPE', None)
QUEUE_EMAIL_BOX_SSL = getattr(settings, 'QUEUE_EMAIL_BOX_SSL', None)
QUEUE_EMAIL_BOX_HOST = getattr(settings, 'QUEUE_EMAIL_BOX_HOST', None)
QUEUE_EMAIL_BOX_USER = getattr(settings, 'QUEUE_EMAIL_BOX_USER', None)
QUEUE_EMAIL_BOX_PASSWORD = getattr(settings, 'QUEUE_EMAIL_BOX_PASSWORD', None)

View File

@ -7,6 +7,9 @@
{% if helpdesk_settings.HELPDESK_NAVIGATION_STATS_ENABLED %} {% if helpdesk_settings.HELPDESK_NAVIGATION_STATS_ENABLED %}
<li><a href='{% url helpdesk_report_index %}'>{% trans "Stats" %}</a></li> <li><a href='{% url helpdesk_report_index %}'>{% trans "Stats" %}</a></li>
{% endif %} {% endif %}
{% if helpdesk_settings.HELPDESK_KB_ENABLED_STAFF %}
<li><a href='{% url helpdesk_kb_index %}'>{% trans "Knowledgebase" %}</a></li>
{% endif %}
{% if user_saved_queries_ %} {% if user_saved_queries_ %}
<li class="headerlink"><a>{% trans "Load Saved Query" %}</a> <li class="headerlink"><a>{% trans "Load Saved Query" %}</a>
<ul> <ul>

View File

@ -175,6 +175,9 @@ function googleTranslateElementInit() {
<dt><label for='id_priority'>{% trans "Priority" %}</label></dt> <dt><label for='id_priority'>{% trans "Priority" %}</label></dt>
<dd><select id='id_priority' name='priority'>{% for p in priorities %}<option value='{{ p.0 }}'{% ifequal p.0 ticket.priority %} selected='selected'{% endifequal %}>{{ p.1 }}</option>{% endfor %}</select></dd> <dd><select id='id_priority' name='priority'>{% for p in priorities %}<option value='{{ p.0 }}'{% ifequal p.0 ticket.priority %} selected='selected'{% endifequal %}>{{ p.1 }}</option>{% endfor %}</select></dd>
<dt><label for='id_due_date'>{% trans "Due on" %}</label></dt>
<dd>{{ form.due_date }}</dd>
{% if tags_enabled %} {% if tags_enabled %}
<dt><label for='id_tags'>{% trans "Tags" %}</label></dt> <dt><label for='id_tags'>{% trans "Tags" %}</label></dt>
<dd><input type='text' id='id_tags' name='tags' value='{{ ticket.tags }}'/></dd> <dd><input type='text' id='id_tags' name='tags' value='{{ ticket.tags }}'/></dd>

View File

@ -216,10 +216,20 @@ def view_ticket(request, ticket_id):
return update_ticket(request, ticket_id) return update_ticket(request, ticket_id)
if helpdesk_settings.HELPDESK_STAFF_ONLY_TICKET_OWNERS:
users = User.objects.filter(is_active=True, is_staff=True).order_by('username')
else:
users = User.objects.filter(is_active=True).order_by('username')
# TODO: shouldn't this template get a form to begin with?
form = TicketForm(initial={'due_date':ticket.due_date})
return render_to_response('helpdesk/ticket.html', return render_to_response('helpdesk/ticket.html',
RequestContext(request, { RequestContext(request, {
'ticket': ticket, 'ticket': ticket,
'active_users': User.objects.filter(is_active=True).order_by('username'), 'form': form,
'active_users': users,
'priorities': Ticket.PRIORITY_CHOICES, 'priorities': Ticket.PRIORITY_CHOICES,
'preset_replies': PreSetReply.objects.filter(Q(queues=ticket.queue) | Q(queues__isnull=True)), 'preset_replies': PreSetReply.objects.filter(Q(queues=ticket.queue) | Q(queues__isnull=True)),
'tags_enabled': HAS_TAG_SUPPORT, 'tags_enabled': HAS_TAG_SUPPORT,
@ -239,6 +249,10 @@ def update_ticket(request, ticket_id, public=False):
public = request.POST.get('public', False) public = request.POST.get('public', False)
owner = int(request.POST.get('owner', None)) owner = int(request.POST.get('owner', None))
priority = int(request.POST.get('priority', ticket.priority)) priority = int(request.POST.get('priority', ticket.priority))
due_date = datetime(
int(request.POST.get('due_date_year')),
int(request.POST.get('due_date_month')),
int(request.POST.get('due_date_day')))
tags = request.POST.get('tags', '') tags = request.POST.get('tags', '')
# We need to allow the 'ticket' and 'queue' contexts to be applied to the # We need to allow the 'ticket' and 'queue' contexts to be applied to the
@ -333,6 +347,16 @@ def update_ticket(request, ticket_id, public=False):
c.save() c.save()
ticket.priority = priority ticket.priority = priority
if due_date != ticket.due_date:
c = TicketChange(
followup=f,
field=_('Due on'),
old_value=ticket.due_date,
new_value=due_date,
)
c.save()
ticket.due_date = due_date
if HAS_TAG_SUPPORT: if HAS_TAG_SUPPORT:
if tags != ticket.tags: if tags != ticket.tags:
c = TicketChange( c = TicketChange(
@ -749,7 +773,11 @@ def create_ticket(request):
form = TicketForm(initial=initial_data) form = TicketForm(initial=initial_data)
form.fields['queue'].choices = [('', '--------')] + [[q.id, q.title] for q in Queue.objects.all()] form.fields['queue'].choices = [('', '--------')] + [[q.id, q.title] for q in Queue.objects.all()]
form.fields['assigned_to'].choices = [('', '--------')] + [[u.id, u.username] for u in User.objects.filter(is_active=True).order_by('username')] if helpdesk_settings.HELPDESK_STAFF_ONLY_TICKET_OWNERS:
users = User.objects.filter(is_active=True, is_staff=True).order_by('username')
else:
users = User.objects.filter(is_active=True).order_by('username')
form.fields['assigned_to'].choices = [('', '--------')] + [[u.id, u.username] for u in users]
if helpdesk_settings.HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO: if helpdesk_settings.HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO:
form.fields['assigned_to'].widget = forms.HiddenInput() form.fields['assigned_to'].widget = forms.HiddenInput()