From 30e3aa55aaea95c460a5430b9a515936baf5a7e8 Mon Sep 17 00:00:00 2001 From: Alex Barcelo Date: Sun, 23 Oct 2016 22:09:17 +0200 Subject: [PATCH] almost auto-fix on misc files --- helpdesk/forms.py | 104 +++---- helpdesk/lib.py | 6 +- .../commands/create_escalation_exclusions.py | 3 +- .../commands/create_queue_permissions.py | 4 +- .../commands/create_usersettings.py | 2 +- .../management/commands/escalate_tickets.py | 35 +-- helpdesk/management/commands/get_email.py | 27 +- helpdesk/models.py | 260 +++++++++--------- .../templatetags/load_helpdesk_settings.py | 2 +- helpdesk/templatetags/saved_queries.py | 6 +- 10 files changed, 230 insertions(+), 219 deletions(-) diff --git a/helpdesk/forms.py b/helpdesk/forms.py index 44d3be8f..090d5455 100644 --- a/helpdesk/forms.py +++ b/helpdesk/forms.py @@ -35,6 +35,7 @@ class CustomFieldMixin(object): """ Mixin that provides a method to turn CustomFields into an actual field """ + def customfield_to_field(self, field, instanceargs): if field.data_type == 'varchar': fieldclass = forms.CharField @@ -76,6 +77,7 @@ class CustomFieldMixin(object): class EditTicketForm(CustomFieldMixin, forms.ModelForm): + class Meta: model = Ticket exclude = ('created', 'modified', 'status', 'on_hold', 'resolution', 'last_escalation', 'assigned_to') @@ -93,11 +95,11 @@ class EditTicketForm(CustomFieldMixin, forms.ModelForm): except TicketCustomFieldValue.DoesNotExist: initial_value = None instanceargs = { - 'label': field.label, - 'help_text': field.help_text, - 'required': field.required, - 'initial': initial_value, - } + 'label': field.label, + 'help_text': field.help_text, + 'required': field.required, + 'initial': initial_value, + } self.customfield_to_field(field, instanceargs) @@ -118,6 +120,7 @@ class EditTicketForm(CustomFieldMixin, forms.ModelForm): class EditFollowUpForm(forms.ModelForm): + class Meta: model = FollowUp exclude = ('date', 'user',) @@ -133,28 +136,28 @@ class TicketForm(CustomFieldMixin, forms.Form): label=_('Queue'), required=True, choices=() - ) + ) title = forms.CharField( max_length=100, required=True, - widget=forms.TextInput(attrs={'size':'60'}), + widget=forms.TextInput(attrs={'size': '60'}), label=_('Summary of the problem'), - ) + ) submitter_email = forms.EmailField( required=False, label=_('Submitter E-Mail Address'), - widget=forms.TextInput(attrs={'size':'60'}), + widget=forms.TextInput(attrs={'size': '60'}), help_text=_('This e-mail address will receive copies of all public ' - 'updates to this ticket.'), - ) + 'updates to this ticket.'), + ) body = forms.CharField( widget=forms.Textarea(attrs={'cols': 47, 'rows': 15}), label=_('Description of Issue'), required=True, - ) + ) assigned_to = forms.ChoiceField( choices=(), @@ -162,7 +165,7 @@ class TicketForm(CustomFieldMixin, forms.Form): label=_('Case owner'), help_text=_('If you select an owner other than yourself, they\'ll be ' 'e-mailed details of this ticket immediately.'), - ) + ) priority = forms.ChoiceField( choices=Ticket.PRIORITY_CHOICES, @@ -170,13 +173,13 @@ class TicketForm(CustomFieldMixin, forms.Form): initial='3', label=_('Priority'), help_text=_('Please select a priority carefully. If unsure, leave it 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'] @@ -189,7 +192,7 @@ class TicketForm(CustomFieldMixin, forms.Form): required=False, label=_('Attach File'), help_text=_('You can attach a file such as a document or screenshot to this ticket.'), - ) + ) def __init__(self, *args, **kwargs): """ @@ -198,10 +201,10 @@ class TicketForm(CustomFieldMixin, forms.Form): super(TicketForm, self).__init__(*args, **kwargs) for field in CustomField.objects.all(): instanceargs = { - 'label': field.label, - 'help_text': field.help_text, - 'required': field.required, - } + 'label': field.label, + 'help_text': field.help_text, + 'required': field.required, + } self.customfield_to_field(field, instanceargs) @@ -263,7 +266,7 @@ class TicketForm(CustomFieldMixin, forms.Form): 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() @@ -288,7 +291,7 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.submitter_email) if t.assigned_to and \ @@ -303,7 +306,7 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.assigned_to.email) if q.new_ticket_cc and q.new_ticket_cc not in messages_sent_to: @@ -314,7 +317,7 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(q.new_ticket_cc) if q.updated_ticket_cc and \ @@ -327,7 +330,7 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) return t @@ -337,20 +340,20 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): label=_('Queue'), required=True, choices=() - ) + ) title = forms.CharField( max_length=100, required=True, widget=forms.TextInput(), label=_('Summary of your query'), - ) + ) submitter_email = forms.EmailField( required=True, label=_('Your E-Mail Address'), help_text=_('We will e-mail you when your ticket is updated.'), - ) + ) body = forms.CharField( widget=forms.Textarea(), @@ -358,7 +361,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): required=True, help_text=_('Please be as descriptive as possible, including any ' 'details we may need to address your query.'), - ) + ) priority = forms.ChoiceField( choices=Ticket.PRIORITY_CHOICES, @@ -366,20 +369,20 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): initial='3', label=_('Urgency'), help_text=_('Please select a priority carefully.'), - ) + ) due_date = forms.DateTimeField( widget=extras.SelectDateWidget, required=False, label=_('Due on'), - ) + ) attachment = forms.FileField( required=False, label=_('Attach File'), help_text=_('You can attach a file such as a document or screenshot to this ticket.'), max_length=1000, - ) + ) def __init__(self, *args, **kwargs): """ @@ -388,10 +391,10 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): super(PublicTicketForm, self).__init__(*args, **kwargs) for field in CustomField.objects.filter(staff_only=False): instanceargs = { - 'label': field.label, - 'help_text': field.help_text, - 'required': field.required, - } + 'label': field.label, + 'help_text': field.help_text, + 'required': field.required, + } self.customfield_to_field(field, instanceargs) @@ -411,7 +414,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): description=self.cleaned_data['body'], priority=self.cleaned_data['priority'], due_date=self.cleaned_data['due_date'], - ) + ) if q.default_owner and not t.assigned_to: t.assigned_to = q.default_owner @@ -433,7 +436,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): date=timezone.now(), public=True, comment=self.cleaned_data['body'], - ) + ) f.save() @@ -447,7 +450,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): 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() @@ -467,7 +470,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.submitter_email) if t.assigned_to and \ @@ -481,7 +484,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.assigned_to.email) if q.new_ticket_cc and q.new_ticket_cc not in messages_sent_to: @@ -492,7 +495,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(q.new_ticket_cc) if q.updated_ticket_cc and \ @@ -505,7 +508,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) return t @@ -515,25 +518,25 @@ class UserSettingsForm(forms.Form): label=_('Show Ticket List on Login?'), help_text=_('Display the ticket list upon login? Otherwise, the dashboard is shown.'), required=False, - ) + ) email_on_ticket_change = forms.BooleanField( label=_('E-mail me on ticket change?'), help_text=_('If you\'re the ticket owner and the ticket is changed via the web by somebody else, do you want to receive an e-mail?'), required=False, - ) + ) email_on_ticket_assign = forms.BooleanField( label=_('E-mail me when assigned a ticket?'), help_text=_('If you are assigned a ticket via the web, do you want to receive an e-mail?'), required=False, - ) + ) email_on_ticket_apichange = forms.BooleanField( label=_('E-mail me when a ticket is changed via the API?'), help_text=_('If a ticket is altered by the API, do you want to receive an e-mail?'), required=False, - ) + ) tickets_per_page = forms.IntegerField( label=_('Number of tickets to show per page'), @@ -541,22 +544,24 @@ class UserSettingsForm(forms.Form): required=False, min_value=1, max_value=1000, - ) + ) use_email_as_submitter = forms.BooleanField( label=_('Use my e-mail address when submitting tickets?'), help_text=_('When you submit a ticket, do you want to automatically use your e-mail address as the submitter address? You can type a different e-mail address when entering the ticket if needed, this option only changes the default.'), required=False, - ) + ) class EmailIgnoreForm(forms.ModelForm): + class Meta: model = IgnoreEmail exclude = [] class TicketCCForm(forms.ModelForm): + class Meta: model = TicketCC exclude = ('ticket',) @@ -571,6 +576,7 @@ class TicketCCForm(forms.ModelForm): class TicketDependencyForm(forms.ModelForm): + class Meta: model = TicketDependency exclude = ('ticket',) diff --git a/helpdesk/lib.py b/helpdesk/lib.py index 84a60b2f..364abc1e 100644 --- a/helpdesk/lib.py +++ b/helpdesk/lib.py @@ -109,7 +109,7 @@ def send_templated_mail(template_name, text_part = template_func( "%s{%% include '%s' %%}" % (t.plain_text, footer_file) - ).render(context) + ).render(context) email_html_base_file = os.path.join('helpdesk', locale, 'email_html_base.html') @@ -233,8 +233,8 @@ def safe_template_context(ticket): context = { 'queue': {}, - 'ticket': {}, - } + 'ticket': {} + } queue = ticket.queue for field in ('title', 'slug', 'email_address', 'from_address', 'locale'): diff --git a/helpdesk/management/commands/create_escalation_exclusions.py b/helpdesk/management/commands/create_escalation_exclusions.py index 6c011f1b..fcda257d 100644 --- a/helpdesk/management/commands/create_escalation_exclusions.py +++ b/helpdesk/management/commands/create_escalation_exclusions.py @@ -21,6 +21,7 @@ from helpdesk.models import EscalationExclusion, Queue class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) @@ -42,7 +43,7 @@ class Command(BaseCommand): default=False, dest='escalate-verbosely', help='Display a list of dates excluded'), - ) + ) def handle(self, *args, **options): days = options['days'] diff --git a/helpdesk/management/commands/create_queue_permissions.py b/helpdesk/management/commands/create_queue_permissions.py index 66118e75..50e980c3 100644 --- a/helpdesk/management/commands/create_queue_permissions.py +++ b/helpdesk/management/commands/create_queue_permissions.py @@ -25,6 +25,7 @@ from helpdesk.models import Queue class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) @@ -32,7 +33,7 @@ class Command(BaseCommand): make_option( '--queues', '-q', help='Queues to include (default: all). Use queue slugs'), - ) + ) def handle(self, *args, **options): queue_slugs = options['queues'] @@ -71,4 +72,3 @@ class Command(BaseCommand): ) except IntegrityError: self.stdout.write(" .. permission already existed, skipping") - diff --git a/helpdesk/management/commands/create_usersettings.py b/helpdesk/management/commands/create_usersettings.py index 965d347f..46280159 100644 --- a/helpdesk/management/commands/create_usersettings.py +++ b/helpdesk/management/commands/create_usersettings.py @@ -4,7 +4,7 @@ django-helpdesk - A Django powered ticket tracker for small enterprise. See LICENSE for details. -create_usersettings.py - Easy way to create helpdesk-specific settings for +create_usersettings.py - Easy way to create helpdesk-specific settings for users who don't yet have them. """ diff --git a/helpdesk/management/commands/escalate_tickets.py b/helpdesk/management/commands/escalate_tickets.py index a3df890a..b2788762 100644 --- a/helpdesk/management/commands/escalate_tickets.py +++ b/helpdesk/management/commands/escalate_tickets.py @@ -28,6 +28,7 @@ from helpdesk.lib import send_templated_mail, safe_template_context class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) @@ -40,7 +41,7 @@ class Command(BaseCommand): action='store_true', default=False, help='Display a list of dates excluded'), - ) + ) def handle(self, *args, **options): verbose = False @@ -88,17 +89,17 @@ def escalate_tickets(queues, verbose): print("Processing: %s" % q) for t in q.ticket_set.filter( - Q(status=Ticket.OPEN_STATUS) - | Q(status=Ticket.REOPENED_STATUS) - ).exclude( - priority=1 - ).filter( - Q(on_hold__isnull=True) - | Q(on_hold=False) - ).filter( - Q(last_escalation__lte=req_last_escl_date) - | Q(last_escalation__isnull=True, created__lte=req_last_escl_date) - ): + Q(status=Ticket.OPEN_STATUS) | + Q(status=Ticket.REOPENED_STATUS) + ).exclude( + priority=1 + ).filter( + Q(on_hold__isnull=True) | + Q(on_hold=False) + ).filter( + Q(last_escalation__lte=req_last_escl_date) | + Q(last_escalation__isnull=True, created__lte=req_last_escl_date) + ): t.last_escalation = timezone.now() t.priority -= 1 @@ -113,7 +114,7 @@ def escalate_tickets(queues, verbose): recipients=t.submitter_email, sender=t.queue.from_address, fail_silently=True, - ) + ) if t.queue.updated_ticket_cc: send_templated_mail( @@ -122,7 +123,7 @@ def escalate_tickets(queues, verbose): recipients=t.queue.updated_ticket_cc, sender=t.queue.from_address, fail_silently=True, - ) + ) if t.assigned_to: send_templated_mail( @@ -131,14 +132,14 @@ def escalate_tickets(queues, verbose): recipients=t.assigned_to.email, sender=t.queue.from_address, fail_silently=True, - ) + ) if verbose: print(" - Esclating %s from %s>%s" % ( t.ticket, - t.priority+1, + t.priority + 1, t.priority - ) + ) ) f = FollowUp( diff --git a/helpdesk/management/commands/get_email.py b/helpdesk/management/commands/get_email.py index 287cff0f..d40a7958 100644 --- a/helpdesk/management/commands/get_email.py +++ b/helpdesk/management/commands/get_email.py @@ -48,7 +48,9 @@ STRIPPED_SUBJECT_STRINGS = [ "Automatic reply: ", ] + class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) @@ -58,7 +60,7 @@ class Command(BaseCommand): default=False, action='store_true', help='Hide details about each queue/message as they are processed'), - ) + ) help = 'Process Jutda Helpdesk queues and process e-mails via ' \ 'POP3/IMAP as required, feeding them into the helpdesk.' @@ -74,7 +76,7 @@ def process_email(quiet=False): allow_email_submission=True): if not q.email_box_last_check: - q.email_box_last_check = timezone.now()-timedelta(minutes=30) + q.email_box_last_check = timezone.now() - timedelta(minutes=30) if not q.email_box_interval: q.email_box_interval = 0 @@ -176,7 +178,7 @@ def process_queue(q, quiet=False): ticket = ticket_from_message(message=data[0][1], queue=q, quiet=quiet) if ticket: server.store(num, '+FLAGS', '\\Deleted') - + server.expunge() server.close() server.logout() @@ -221,7 +223,7 @@ def ticket_from_message(message, queue, quiet): return False return True - matchobj = re.match(r".*\["+queue.slug+"-(?P\d+)\]", subject) + matchobj = re.match(r".*\[" + queue.slug + "-(?P\d+)\]", subject) if matchobj: # This is a reply or forward. ticket = matchobj.group('id') @@ -254,7 +256,7 @@ def ticket_from_message(message, queue, quiet): 'filename': name, 'content': part.get_payload(decode=True), 'type': part.get_content_type()}, - ) + ) counter += 1 @@ -317,7 +319,7 @@ def ticket_from_message(message, queue, quiet): if t.status == Ticket.REOPENED_STATUS: f.new_status = Ticket.REOPENED_STATUS f.title = _('Ticket Re-Opened by E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}) - + f.save() if not quiet: @@ -332,7 +334,7 @@ def ticket_from_message(message, queue, quiet): filename=filename, mime_type=file['type'], size=len(file['content']), - ) + ) a.file.save(filename, ContentFile(file['content']), save=False) a.save() if not quiet: @@ -349,7 +351,7 @@ def ticket_from_message(message, queue, quiet): recipients=sender_email, sender=queue.from_address, fail_silently=True, - ) + ) if queue.new_ticket_cc: send_templated_mail( @@ -358,7 +360,7 @@ def ticket_from_message(message, queue, quiet): recipients=queue.new_ticket_cc, sender=queue.from_address, fail_silently=True, - ) + ) if queue.updated_ticket_cc and queue.updated_ticket_cc != queue.new_ticket_cc: send_templated_mail( @@ -367,7 +369,7 @@ def ticket_from_message(message, queue, quiet): recipients=queue.updated_ticket_cc, sender=queue.from_address, fail_silently=True, - ) + ) else: context.update(comment=f.comment) @@ -384,7 +386,7 @@ def ticket_from_message(message, queue, quiet): recipients=t.assigned_to.email, sender=queue.from_address, fail_silently=True, - ) + ) if queue.updated_ticket_cc: send_templated_mail( @@ -393,11 +395,10 @@ def ticket_from_message(message, queue, quiet): recipients=queue.updated_ticket_cc, sender=queue.from_address, fail_silently=True, - ) + ) return t if __name__ == '__main__': process_email() - diff --git a/helpdesk/models.py b/helpdesk/models.py index 4ee9ab08..dec02ea7 100644 --- a/helpdesk/models.py +++ b/helpdesk/models.py @@ -36,7 +36,7 @@ class Queue(models.Model): title = models.CharField( _('Title'), max_length=100, - ) + ) slug = models.SlugField( _('Slug'), @@ -44,7 +44,7 @@ class Queue(models.Model): unique=True, help_text=_('This slug is used when building ticket ID\'s. Once set, ' 'try not to change it or e-mailing may get messy.'), - ) + ) email_address = models.EmailField( _('E-Mail Address'), @@ -53,7 +53,7 @@ class Queue(models.Model): help_text=_('All outgoing e-mails for this queue will use this e-mail ' 'address. If you use IMAP or POP3, this should be the e-mail ' 'address for that mailbox.'), - ) + ) locale = models.CharField( _('Locale'), @@ -62,14 +62,14 @@ class Queue(models.Model): null=True, help_text=_('Locale of this queue. All correspondence in this ' 'queue will be in this language.'), - ) + ) allow_public_submission = models.BooleanField( _('Allow Public Submission?'), blank=True, default=False, help_text=_('Should this queue be listed on the public submission form?'), - ) + ) allow_email_submission = models.BooleanField( _('Allow E-Mail Submission?'), @@ -77,7 +77,7 @@ class Queue(models.Model): default=False, help_text=_('Do you want to poll the e-mail box below for new ' 'tickets?'), - ) + ) escalate_days = models.IntegerField( _('Escalation Days'), @@ -85,7 +85,7 @@ class Queue(models.Model): null=True, help_text=_('For tickets which are not held, how often do you wish to ' 'increase their priority? Set to 0 for no escalation.'), - ) + ) new_ticket_cc = models.CharField( _('New Ticket CC Address'), @@ -95,7 +95,7 @@ class Queue(models.Model): help_text=_('If an e-mail address is entered here, then it will ' 'receive notification of all new tickets created for this queue. ' 'Enter a comma between multiple e-mail addresses.'), - ) + ) updated_ticket_cc = models.CharField( _('Updated Ticket CC Address'), @@ -106,7 +106,7 @@ class Queue(models.Model): 'receive notification of all activity (new tickets, closed ' 'tickets, updates, reassignments, etc) for this queue. Separate ' 'multiple addresses with a comma.'), - ) + ) email_box_type = models.CharField( _('E-Mail Box Type'), @@ -116,7 +116,7 @@ class Queue(models.Model): null=True, help_text=_('E-Mail server type for creating tickets automatically ' 'from a mailbox - both POP3 and IMAP are supported.'), - ) + ) email_box_host = models.CharField( _('E-Mail Hostname'), @@ -125,7 +125,7 @@ class Queue(models.Model): null=True, help_text=_('Your e-mail server address - either the domain name or ' 'IP address. May be "localhost".'), - ) + ) email_box_port = models.IntegerField( _('E-Mail Port'), @@ -134,7 +134,7 @@ class Queue(models.Model): help_text=_('Port number to use for accessing e-mail. Default for ' 'POP3 is "110", and for IMAP is "143". This may differ on some ' 'servers. Leave it blank to use the defaults.'), - ) + ) email_box_ssl = models.BooleanField( _('Use SSL for E-Mail?'), @@ -142,7 +142,7 @@ class Queue(models.Model): default=False, 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'), @@ -150,7 +150,7 @@ class Queue(models.Model): blank=True, null=True, help_text=_('Username for accessing this mailbox.'), - ) + ) email_box_pass = models.CharField( _('E-Mail Password'), @@ -158,7 +158,7 @@ class Queue(models.Model): blank=True, null=True, help_text=_('Password for the above username'), - ) + ) email_box_imap_folder = models.CharField( _('IMAP Folder'), @@ -169,7 +169,7 @@ class Queue(models.Model): 'from? This allows you to use one IMAP account for multiple ' 'queues, by filtering messages on your IMAP server into separate ' 'folders. Default: INBOX.'), - ) + ) permission_name = models.CharField( _('Django auth permission name'), @@ -178,8 +178,7 @@ class Queue(models.Model): null=True, editable=False, help_text=_('Name used in the django.contrib.auth permission system'), - ) - + ) email_box_interval = models.IntegerField( _('E-Mail Check Interval'), @@ -187,14 +186,14 @@ class Queue(models.Model): blank=True, null=True, default='5', - ) + ) email_box_last_check = models.DateTimeField( blank=True, null=True, editable=False, # This is updated by management/commands/get_mail.py. - ) + ) socks_proxy_type = models.CharField( _('Socks Proxy Type'), @@ -347,24 +346,24 @@ class Ticket(models.Model): title = models.CharField( _('Title'), max_length=200, - ) + ) queue = models.ForeignKey( Queue, verbose_name=_('Queue'), - ) + ) created = models.DateTimeField( _('Created'), blank=True, help_text=_('Date this ticket was first created'), - ) + ) modified = models.DateTimeField( _('Modified'), blank=True, help_text=_('Date this ticket was most recently changed.'), - ) + ) submitter_email = models.EmailField( _('Submitter E-Mail'), @@ -372,7 +371,7 @@ class Ticket(models.Model): null=True, help_text=_('The submitter will receive an email for all public ' 'follow-ups left for this task.'), - ) + ) assigned_to = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -380,34 +379,34 @@ class Ticket(models.Model): blank=True, null=True, verbose_name=_('Assigned to'), - ) + ) status = models.IntegerField( _('Status'), choices=STATUS_CHOICES, default=OPEN_STATUS, - ) + ) on_hold = models.BooleanField( _('On Hold'), blank=True, default=False, help_text=_('If a ticket is on hold, it will not automatically be escalated.'), - ) + ) description = models.TextField( _('Description'), blank=True, null=True, help_text=_('The content of the customers query.'), - ) + ) resolution = models.TextField( _('Resolution'), blank=True, null=True, help_text=_('The resolution provided to the customer by our staff.'), - ) + ) priority = models.IntegerField( _('Priority'), @@ -415,13 +414,13 @@ class Ticket(models.Model): default=3, blank=3, help_text=_('1 = Highest Priority, 5 = Low Priority'), - ) + ) due_date = models.DateTimeField( _('Due on'), blank=True, null=True, - ) + ) last_escalation = models.DateTimeField( blank=True, @@ -429,7 +428,7 @@ class Ticket(models.Model): editable=False, help_text=_('The date this ticket was last escalated - updated ' 'automatically by management/commands/escalate_tickets.py.'), - ) + ) def _get_assigned_to(self): """ Custom property to allow us to easily print 'Unassigned' if a @@ -479,7 +478,8 @@ class Ticket(models.Model): Displays the ticket status, with an "On Hold" message if needed. """ held_msg = '' - if self.on_hold: held_msg = _(' - On Hold') + if self.on_hold: + held_msg = _(' - On Hold') dep_msg = '' if not self.can_be_resolved: dep_msg = _(' - Open dependencies') @@ -502,7 +502,7 @@ class Ticket(models.Model): reverse('helpdesk_public_view'), self.ticket_for_url, self.submitter_email - ) + ) ticket_url = property(_get_ticket_url) def _get_staff_url(self): @@ -519,8 +519,8 @@ class Ticket(models.Model): return u"http://%s%s" % ( site.domain, reverse('helpdesk_view', - args=[self.id]) - ) + args=[self.id]) + ) staff_url = property(_get_staff_url) def _can_be_resolved(self): @@ -569,6 +569,7 @@ class Ticket(models.Model): class FollowUpManager(models.Manager): + def private_followups(self): return self.filter(public=False) @@ -593,25 +594,25 @@ class FollowUp(models.Model): ticket = models.ForeignKey( Ticket, verbose_name=_('Ticket'), - ) + ) date = models.DateTimeField( _('Date'), - default = timezone.now - ) + default=timezone.now + ) title = models.CharField( _('Title'), max_length=200, blank=True, null=True, - ) + ) comment = models.TextField( _('Comment'), blank=True, null=True, - ) + ) public = models.BooleanField( _('Public'), @@ -619,14 +620,14 @@ class FollowUp(models.Model): default=False, help_text=_('Public tickets are viewable by the submitter and all ' 'staff, but non-public tickets can only be seen by staff.'), - ) + ) user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name=_('User'), - ) + ) new_status = models.IntegerField( _('New Status'), @@ -634,12 +635,12 @@ class FollowUp(models.Model): blank=True, null=True, help_text=_('If the status was changed, what was it changed to?'), - ) + ) objects = FollowUpManager() class Meta: - ordering = ['date'] + ordering = ('date',) verbose_name = _('Follow-up') verbose_name_plural = _('Follow-ups') @@ -666,24 +667,24 @@ class TicketChange(models.Model): followup = models.ForeignKey( FollowUp, verbose_name=_('Follow-up'), - ) + ) field = models.CharField( _('Field'), max_length=100, - ) + ) old_value = models.TextField( _('Old Value'), blank=True, null=True, - ) + ) new_value = models.TextField( _('New Value'), blank=True, null=True, - ) + ) def __str__(self): out = '%s ' % self.field @@ -695,7 +696,7 @@ class TicketChange(models.Model): out += ugettext('changed from "%(old_value)s" to "%(new_value)s"') % { 'old_value': self.old_value, 'new_value': self.new_value - } + } return out class Meta: @@ -711,7 +712,7 @@ def attachment_path(instance, filename): import os from django.conf import settings os.umask(0) - path = 'helpdesk/attachments/%s/%s' % (instance.followup.ticket.ticket_for_url, instance.followup.id ) + path = 'helpdesk/attachments/%s/%s' % (instance.followup.ticket.ticket_for_url, instance.followup.id) att_path = os.path.join(settings.MEDIA_ROOT, path) if settings.DEFAULT_FILE_STORAGE == "django.core.files.storage.FileSystemStorage": if not os.path.exists(att_path): @@ -729,28 +730,28 @@ class Attachment(models.Model): followup = models.ForeignKey( FollowUp, verbose_name=_('Follow-up'), - ) + ) file = models.FileField( _('File'), upload_to=attachment_path, max_length=1000, - ) + ) filename = models.CharField( _('Filename'), max_length=1000, - ) + ) mime_type = models.CharField( _('MIME Type'), max_length=255, - ) + ) size = models.IntegerField( _('Size'), help_text=_('Size of this file in bytes'), - ) + ) def get_upload_to(self, field_attname): """ Get upload_to path specific to this item """ @@ -759,13 +760,13 @@ class Attachment(models.Model): return u'helpdesk/attachments/%s/%s' % ( self.followup.ticket.ticket_for_url, self.followup.id - ) + ) def __str__(self): return '%s' % self.filename class Meta: - ordering = ['filename',] + ordering = ('filename',) verbose_name = _('Attachment') verbose_name_plural = _('Attachments') @@ -783,7 +784,7 @@ class PreSetReply(models.Model): queue, and the body text is fetched via AJAX. """ class Meta: - ordering = ['name', ] + ordering = ('name',) verbose_name = _('Pre-set reply') verbose_name_plural = _('Pre-set replies') @@ -792,21 +793,21 @@ class PreSetReply(models.Model): blank=True, help_text=_('Leave blank to allow this reply to be used for all ' 'queues, or select those queues you wish to limit this reply to.'), - ) + ) name = models.CharField( _('Name'), max_length=100, help_text=_('Only used to assist users with selecting a reply - not ' 'shown to the user.'), - ) + ) body = models.TextField( _('Body'), help_text=_('Context available: {{ ticket }} - ticket object (eg ' '{{ ticket.title }}); {{ queue }} - The queue; and {{ user }} ' '- the current user.'), - ) + ) def __str__(self): return '%s' % self.name @@ -829,17 +830,17 @@ class EscalationExclusion(models.Model): blank=True, help_text=_('Leave blank for this exclusion to be applied to all queues, ' 'or select those queues you wish to exclude with this entry.'), - ) + ) name = models.CharField( _('Name'), max_length=100, - ) + ) date = models.DateField( _('Date'), help_text=_('Date on which escalation should not happen'), - ) + ) def __str__(self): return '%s' % self.name @@ -862,7 +863,7 @@ class EmailTemplate(models.Model): template_name = models.CharField( _('Template Name'), max_length=100, - ) + ) subject = models.CharField( _('Subject'), @@ -870,7 +871,7 @@ class EmailTemplate(models.Model): help_text=_('This will be prefixed with "[ticket.ticket] ticket.title"' '. We recommend something simple such as "(Updated") or "(Closed)"' ' - the same context is available as in plain_text, below.'), - ) + ) heading = models.CharField( _('Heading'), @@ -878,19 +879,19 @@ class EmailTemplate(models.Model): help_text=_('In HTML e-mails, this will be the heading at the top of ' 'the email - the same context is available as in plain_text, ' 'below.'), - ) + ) plain_text = models.TextField( _('Plain Text'), help_text=_('The context available to you includes {{ ticket }}, ' '{{ queue }}, and depending on the time of the call: ' '{{ resolution }} or {{ comment }}.'), - ) + ) html = models.TextField( _('HTML'), help_text=_('The same context is available here as in plain_text, above.'), - ) + ) locale = models.CharField( _('Locale'), @@ -898,13 +899,13 @@ class EmailTemplate(models.Model): blank=True, null=True, help_text=_('Locale of this template.'), - ) + ) def __str__(self): return '%s' % self.template_name class Meta: - ordering = ['template_name', 'locale'] + ordering = ('template_name', 'locale') verbose_name = _('e-mail template') verbose_name_plural = _('e-mail templates') @@ -919,21 +920,21 @@ class KBCategory(models.Model): title = models.CharField( _('Title'), max_length=100, - ) + ) slug = models.SlugField( _('Slug'), - ) + ) description = models.TextField( _('Description'), - ) + ) def __str__(self): return '%s' % self.title class Meta: - ordering = ['title',] + ordering = ('title',) verbose_name = _('Knowledge base category') verbose_name_plural = _('Knowledge base categories') @@ -951,38 +952,38 @@ class KBItem(models.Model): category = models.ForeignKey( KBCategory, verbose_name=_('Category'), - ) + ) title = models.CharField( _('Title'), max_length=100, - ) + ) question = models.TextField( _('Question'), - ) + ) answer = models.TextField( _('Answer'), - ) + ) votes = models.IntegerField( _('Votes'), help_text=_('Total number of votes cast for this item'), default=0, - ) + ) recommendations = models.IntegerField( _('Positive Votes'), help_text=_('Number of votes for this item which were POSITIVE.'), default=0, - ) + ) last_updated = models.DateTimeField( _('Last Updated'), help_text=_('The date on which this question was most recently changed.'), blank=True, - ) + ) def save(self, *args, **kwargs): if not self.last_updated: @@ -1000,7 +1001,7 @@ class KBItem(models.Model): return '%s' % self.title class Meta: - ordering = ['title',] + ordering = ('title',) verbose_name = _('Knowledge base item') verbose_name_plural = _('Knowledge base items') @@ -1024,25 +1025,25 @@ class SavedSearch(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, verbose_name=_('User'), - ) + ) title = models.CharField( _('Query Name'), max_length=100, help_text=_('User-provided name for this query'), - ) + ) shared = models.BooleanField( _('Shared With Other Users?'), blank=True, default=False, help_text=_('Should other users see this query?'), - ) + ) query = models.TextField( _('Search Query'), help_text=_('Pickled query object. Be wary changing this.'), - ) + ) def __str__(self): if self.shared: @@ -1073,7 +1074,7 @@ class UserSettings(models.Model): 'Do not change this field via the admin.'), blank=True, null=True, - ) + ) def _set_settings(self, data): # data should always be a Python dictionary. @@ -1138,26 +1139,26 @@ class IgnoreEmail(models.Model): blank=True, help_text=_('Leave blank for this e-mail to be ignored on all queues, ' 'or select those queues you wish to ignore this e-mail for.'), - ) + ) name = models.CharField( _('Name'), max_length=100, - ) + ) date = models.DateField( _('Date'), help_text=_('Date on which this e-mail address was added'), blank=True, editable=False - ) + ) email_address = models.CharField( _('E-Mail Address'), max_length=150, help_text=_('Enter a full e-mail address, or portions with ' 'wildcards, eg *@domain.com or postmaster@*.'), - ) + ) keep_in_mailbox = models.BooleanField( _('Save Emails in Mailbox?'), @@ -1165,7 +1166,7 @@ class IgnoreEmail(models.Model): default=False, help_text=_('Do you want to save emails from this address in the mailbox? ' 'If this is unticked, emails from this address will be deleted.'), - ) + ) def __str__(self): return '%s' % self.name @@ -1213,7 +1214,7 @@ class TicketCC(models.Model): ticket = models.ForeignKey( Ticket, verbose_name=_('Ticket'), - ) + ) user = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -1221,28 +1222,28 @@ class TicketCC(models.Model): null=True, help_text=_('User who wishes to receive updates for this ticket.'), verbose_name=_('User'), - ) + ) 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, default=False, help_text=_('Can this CC login to view the ticket details?'), - ) + ) can_update = models.BooleanField( _('Can Update Ticket?'), blank=True, default=False, help_text=_('Can this CC login and update the ticket?'), - ) + ) def _email_address(self): if self.user and self.user.email is not None: @@ -1263,6 +1264,7 @@ class TicketCC(models.Model): class CustomFieldManager(models.Manager): + def get_queryset(self): return super(CustomFieldManager, self).get_queryset().order_by('ordering') @@ -1278,77 +1280,77 @@ class CustomField(models.Model): help_text=_('As used in the database and behind the scenes. ' 'Must be unique and consist of only lowercase letters with no punctuation.'), unique=True, - ) + ) label = models.CharField( _('Label'), max_length=30, help_text=_('The display label for this field'), - ) + ) help_text = models.TextField( _('Help Text'), help_text=_('Shown to the user when editing the ticket'), blank=True, null=True - ) + ) DATA_TYPE_CHOICES = ( - ('varchar', _('Character (single line)')), - ('text', _('Text (multi-line)')), - ('integer', _('Integer')), - ('decimal', _('Decimal')), - ('list', _('List')), - ('boolean', _('Boolean (checkbox yes/no)')), - ('date', _('Date')), - ('time', _('Time')), - ('datetime', _('Date & Time')), - ('email', _('E-Mail Address')), - ('url', _('URL')), - ('ipaddress', _('IP Address')), - ('slug', _('Slug')), - ) + ('varchar', _('Character (single line)')), + ('text', _('Text (multi-line)')), + ('integer', _('Integer')), + ('decimal', _('Decimal')), + ('list', _('List')), + ('boolean', _('Boolean (checkbox yes/no)')), + ('date', _('Date')), + ('time', _('Time')), + ('datetime', _('Date & Time')), + ('email', _('E-Mail Address')), + ('url', _('URL')), + ('ipaddress', _('IP Address')), + ('slug', _('Slug')), + ) data_type = models.CharField( _('Data Type'), max_length=100, help_text=_('Allows you to restrict the data entered into this field'), choices=DATA_TYPE_CHOICES, - ) + ) max_length = models.IntegerField( _('Maximum Length (characters)'), blank=True, null=True, - ) + ) decimal_places = models.IntegerField( _('Decimal Places'), help_text=_('Only used for decimal fields'), blank=True, null=True, - ) + ) empty_selection_list = models.BooleanField( _('Add empty first choice to List?'), default=False, help_text=_('Only for List: adds an empty first entry to the choices list, ' 'which enforces that the user makes an active choice.'), - ) + ) list_values = models.TextField( _('List Values'), help_text=_('For list fields only. Enter one option per line.'), blank=True, null=True, - ) + ) ordering = models.IntegerField( _('Ordering'), help_text=_('Lower numbers are displayed first; higher numbers are listed later'), blank=True, null=True, - ) + ) def _choices_as_array(self): from StringIO import StringIO @@ -1362,14 +1364,14 @@ class CustomField(models.Model): _('Required?'), help_text=_('Does the user have to enter a value for this field?'), default=False, - ) + ) staff_only = models.BooleanField( _('Staff Only?'), help_text=_('If this is ticked, then the public submission form ' 'will NOT show this field'), default=False, - ) + ) objects = CustomFieldManager() @@ -1386,12 +1388,12 @@ class TicketCustomFieldValue(models.Model): ticket = models.ForeignKey( Ticket, verbose_name=_('Ticket'), - ) + ) field = models.ForeignKey( CustomField, verbose_name=_('Field'), - ) + ) value = models.TextField(blank=True, null=True) @@ -1420,13 +1422,13 @@ class TicketDependency(models.Model): Ticket, verbose_name=_('Ticket'), related_name='ticketdependency', - ) + ) depends_on = models.ForeignKey( Ticket, verbose_name=_('Depends On Ticket'), related_name='depends_on', - ) + ) def __str__(self): return '%s / %s' % (self.ticket, self.depends_on) diff --git a/helpdesk/templatetags/load_helpdesk_settings.py b/helpdesk/templatetags/load_helpdesk_settings.py index 835efe81..4b1afcf4 100644 --- a/helpdesk/templatetags/load_helpdesk_settings.py +++ b/helpdesk/templatetags/load_helpdesk_settings.py @@ -1,7 +1,7 @@ """ django-helpdesk - A Django powered ticket tracker for small enterprise. -templatetags/load_helpdesk_settings.py - returns the settings as defined in +templatetags/load_helpdesk_settings.py - returns the settings as defined in django-helpdesk/helpdesk/settings.py """ from __future__ import print_function diff --git a/helpdesk/templatetags/saved_queries.py b/helpdesk/templatetags/saved_queries.py index ebedf9bb..e3f9a954 100644 --- a/helpdesk/templatetags/saved_queries.py +++ b/helpdesk/templatetags/saved_queries.py @@ -1,7 +1,7 @@ """ django-helpdesk - A Django powered ticket tracker for small enterprise. -templatetags/saved_queries.py - This template tag returns previously saved +templatetags/saved_queries.py - This template tag returns previously saved queries. Therefore you don't need to modify any views. """ @@ -17,8 +17,8 @@ def saved_queries(user): return user_saved_queries except Exception as e: import sys - print >> sys.stderr, "'saved_queries' template tag (django-helpdesk) crashed with following error:" - print >> sys.stderr, e + print >> sys.stderr, "'saved_queries' template tag (django-helpdesk) crashed with following error:" + print >> sys.stderr, e return '' register = Library()