From 9e9ebd45a76427738e8caa5123eb9ed3a969e5fd Mon Sep 17 00:00:00 2001 From: Benbb96 Date: Sat, 22 Apr 2023 22:55:41 +0200 Subject: [PATCH] Create models and admin for Checklist --- helpdesk/admin.py | 22 +++++- ...ecklist_checklisttemplate_checklisttask.py | 52 ++++++++++++++ helpdesk/models.py | 70 +++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 helpdesk/migrations/0038_checklist_checklisttemplate_checklisttask.py diff --git a/helpdesk/admin.py b/helpdesk/admin.py index d51cf209..c3b97cd5 100644 --- a/helpdesk/admin.py +++ b/helpdesk/admin.py @@ -13,7 +13,7 @@ from helpdesk.models import ( PreSetReply, Queue, Ticket, - TicketChange + TicketChange, Checklist, ChecklistTemplate, ChecklistTask ) @@ -41,6 +41,7 @@ class TicketAdmin(admin.ModelAdmin): 'hidden_submitter_email', 'time_spent') date_hierarchy = 'created' list_filter = ('queue', 'assigned_to', 'status') + search_fields = ('id', 'title') def hidden_submitter_email(self, ticket): if ticket.submitter_email: @@ -115,5 +116,24 @@ class IgnoreEmailAdmin(admin.ModelAdmin): list_display = ('name', 'queue_list', 'email_address', 'keep_in_mailbox') +@admin.register(ChecklistTemplate) +class ChecklistTemplateAdmin(admin.ModelAdmin): + list_display = ('name', 'task_list') + search_fields = ('name', 'task_list') + + +class ChecklistTaskInline(admin.TabularInline): + model = ChecklistTask + + +@admin.register(Checklist) +class ChecklistAdmin(admin.ModelAdmin): + list_display = ('name', 'ticket') + search_fields = ('name', 'ticket__id', 'ticket__title') + autocomplete_fields = ('ticket',) + list_select_related = ('ticket',) + inlines = (ChecklistTaskInline,) + + admin.site.register(PreSetReply) admin.site.register(EscalationExclusion) diff --git a/helpdesk/migrations/0038_checklist_checklisttemplate_checklisttask.py b/helpdesk/migrations/0038_checklist_checklisttemplate_checklisttask.py new file mode 100644 index 00000000..3bfd0156 --- /dev/null +++ b/helpdesk/migrations/0038_checklist_checklisttemplate_checklisttask.py @@ -0,0 +1,52 @@ +# Generated by Django 4.2 on 2023-04-22 20:50 + +from django.db import migrations, models +import django.db.models.deletion +import helpdesk.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('helpdesk', '0037_alter_queue_email_box_type'), + ] + + operations = [ + migrations.CreateModel( + name='Checklist', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, verbose_name='Name')), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='checklists', to='helpdesk.ticket', verbose_name='Ticket')), + ], + options={ + 'verbose_name': 'Checklist', + 'verbose_name_plural': 'Checklists', + }, + ), + migrations.CreateModel( + name='ChecklistTemplate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, verbose_name='Name')), + ('task_list', models.JSONField(validators=[helpdesk.models.is_a_list_without_empty_element], verbose_name='Task List')), + ], + options={ + 'verbose_name': 'Checklist Template', + 'verbose_name_plural': 'Checklist Templates', + }, + ), + migrations.CreateModel( + name='ChecklistTask', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.CharField(max_length=250, verbose_name='Description')), + ('completion_date', models.DateTimeField(blank=True, null=True, verbose_name='Completion Date')), + ('checklist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='helpdesk.checklist', verbose_name='Checklist')), + ], + options={ + 'verbose_name': 'Checklist Task', + 'verbose_name_plural': 'Checklist Tasks', + }, + ), + ] diff --git a/helpdesk/models.py b/helpdesk/models.py index 27151171..d72e62ca 100644 --- a/helpdesk/models.py +++ b/helpdesk/models.py @@ -2002,3 +2002,73 @@ class TicketDependency(models.Model): def __str__(self): return '%s / %s' % (self.ticket, self.depends_on) + + +def is_a_list_without_empty_element(task_list): + if not isinstance(task_list, list): + raise ValidationError(f'{task_list} is not a list') + for task in task_list: + if not isinstance(task, str): + raise ValidationError(f'{task} is not a string') + if task == '': + raise ValidationError('A task cannot be an empty string') + + +class ChecklistTemplate(models.Model): + name = models.CharField( + verbose_name=_('Name'), + max_length=100 + ) + task_list = models.JSONField(verbose_name=_('Task List'), validators=[is_a_list_without_empty_element]) + + class Meta: + verbose_name = _('Checklist Template') + verbose_name_plural = _('Checklist Templates') + + def __str__(self): + return self.name + + +class Checklist(models.Model): + ticket = models.ForeignKey( + Ticket, + on_delete=models.CASCADE, + verbose_name=_('Ticket'), + related_name='checklists', + ) + name = models.CharField( + verbose_name=_('Name'), + max_length=100 + ) + + class Meta: + verbose_name = _('Checklist') + verbose_name_plural = _('Checklists') + + def __str__(self): + return self.name + + +class ChecklistTask(models.Model): + checklist = models.ForeignKey( + Checklist, + on_delete=models.CASCADE, + verbose_name=_('Checklist'), + related_name='tasks', + ) + description = models.CharField( + verbose_name=_('Description'), + max_length=250 + ) + completion_date = models.DateTimeField( + verbose_name=_('Completion Date'), + null=True, + blank=True + ) + + class Meta: + verbose_name = _('Checklist Task') + verbose_name_plural = _('Checklist Tasks') + + def __str__(self): + return self.description