Skip to content
Snippets Groups Projects
Verified Commit 4079c21f authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Merge branch 'master' into 85-add-option-to-configure-extra-marks-for-personal-notes

parents 49718f69 4a5b813e
No related branches found
No related tags found
1 merge request!68Resolve "Add option to configure extra marks for personal notes"
Showing
with 451 additions and 55 deletions
......@@ -11,7 +11,13 @@ from material import Layout, Row
from aleksis.apps.chronos.managers import TimetableType
from aleksis.core.models import Group, Person
from .models import ExtraMark, LessonDocumentation, PersonalNote, PersonalNoteFilter
from .models import (
ExcuseType,
ExtraMark,
LessonDocumentation,
PersonalNote,
PersonalNoteFilter,
)
class LessonDocumentationForm(forms.ModelForm):
......@@ -28,7 +34,7 @@ class LessonDocumentationForm(forms.ModelForm):
class PersonalNoteForm(forms.ModelForm):
class Meta:
model = PersonalNote
fields = ["absent", "late", "excused", "extra_marks", "remarks"]
fields = ["absent", "late", "excused", "excuse_type", "extra_marks", "remarks"]
person_name = forms.CharField(disabled=True)
......@@ -47,10 +53,7 @@ class SelectForm(forms.Form):
layout = Layout(Row("group", "teacher"))
group = forms.ModelChoiceField(
queryset=None,
label=_("Group"),
required=False,
widget=Select2Widget,
queryset=None, label=_("Group"), required=False, widget=Select2Widget,
)
teacher = forms.ModelChoiceField(
queryset=Person.objects.annotate(
......@@ -81,8 +84,10 @@ class SelectForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["group"].queryset = Group.objects.for_current_school_term_or_all().annotate(lessons_count=Count("lessons")).filter(
lessons_count__gt=0
self.fields["group"].queryset = (
Group.objects.for_current_school_term_or_all()
.annotate(lessons_count=Count("lessons"))
.filter(lessons_count__gt=0)
)
......@@ -124,3 +129,11 @@ class ExtraMarkForm(forms.ModelForm):
class Meta:
model = ExtraMark
fields = ["short_name", "name"]
class ExcuseTypeForm(forms.ModelForm):
layout = Layout("short_name", "name")
class Meta:
model = ExcuseType
fields = ["short_name", "name"]
......@@ -36,6 +36,12 @@ MENUS = {
"icon": "filter_list",
"validators": ["menu_generator.validators.is_superuser"],
},
{
"name": _("Excuse types"),
"url": "excuse_types",
"icon": "label",
"validators": ["menu_generator.validators.is_superuser"],
},
{
"name": _("Extra marks"),
"url": "extra_marks",
......
# Generated by Django 3.0.8 on 2020-07-10 10:46
import django.contrib.postgres.fields.jsonb
import django.contrib.sites.managers
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("sites", "0002_alter_domain_unique"),
("alsijil", "0001_initial"),
]
operations = [
migrations.CreateModel(
name="ExcuseType",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"extended_data",
django.contrib.postgres.fields.jsonb.JSONField(
default=dict, editable=False
),
),
(
"short_name",
models.CharField(
max_length=255, unique=True, verbose_name="Short name"
),
),
(
"name",
models.CharField(max_length=255, unique=True, verbose_name="Name"),
),
(
"site",
models.ForeignKey(
default=1,
editable=False,
on_delete=django.db.models.deletion.CASCADE,
to="sites.Site",
),
),
],
options={
"verbose_name": "Excuse type",
"verbose_name_plural": "Excuse types",
"ordering": ["name"],
},
managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
),
migrations.AddField(
model_name="personalnote",
name="excuse_type",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="alsijil.ExcuseType",
verbose_name="Excuse type",
),
),
]
......@@ -8,7 +8,7 @@ from calendarweek import CalendarWeek
from aleksis.apps.chronos.models import LessonPeriod
from aleksis.core.models import Group, Person
from .models import ExtraMark, LessonDocumentation, PersonalNote
from .models import ExcuseType, ExtraMark, LessonDocumentation, PersonalNote
@Person.method
......@@ -18,6 +18,7 @@ def mark_absent(
from_period: int = 0,
absent: bool = True,
excused: bool = False,
excuse_type: Optional[ExcuseType] = None,
remarks: str = "",
):
"""Mark a person absent for all lessons in a day, optionally starting with a selected period number.
......@@ -44,7 +45,7 @@ def mark_absent(
person=self,
lesson_period=lesson_period,
week=wanted_week.week,
defaults={"absent": absent, "excused": excused},
defaults={"absent": absent, "excused": excused, "excuse_type": excuse_type},
)
if remarks:
......
......@@ -8,6 +8,30 @@ def isidentifier(value: str) -> bool:
return value.isidentifier()
class ExcuseType(ExtensibleModel):
"""An type of excuse.
Can be used to count different types of absences separately.
"""
short_name = models.CharField(
max_length=255, unique=True, verbose_name=_("Short name")
)
name = models.CharField(max_length=255, unique=True, verbose_name=_("Name"))
def __str__(self):
return f"{self.name} ({self.short_name})"
@property
def count_label(self):
return f"{self.short_name}_count"
class Meta:
ordering = ["name"]
verbose_name = _("Excuse type")
verbose_name_plural = _("Excuse types")
class PersonalNote(ExtensibleModel):
"""A personal note about a single person.
......@@ -27,6 +51,13 @@ class PersonalNote(ExtensibleModel):
absent = models.BooleanField(default=False)
late = models.IntegerField(default=0)
excused = models.BooleanField(default=False)
excuse_type = models.ForeignKey(
ExcuseType,
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name=_("Excuse type"),
)
remarks = models.CharField(max_length=200, blank=True)
......@@ -34,6 +65,11 @@ class PersonalNote(ExtensibleModel):
"ExtraMark", null=True, blank=True, verbose_name=_("Extra marks")
)
def save(self, *args, **kwargs):
if self.excuse_type:
self.excused = True
super().save(*args, **kwargs)
class Meta:
verbose_name = _("Personal note")
verbose_name_plural = _("Personal notes")
......
table.small-print {
table.small-print, td.small-print, th.small-print {
font-size: 10pt;
}
......@@ -25,7 +25,7 @@ tr.lessons-day-first {
border-top: 3px solid rgba(0, 0, 0, 0.3);
}
th.lessons-day-head {
th.lessons-day-head, td.rotate, th.rotate {
text-align: center;
transform: rotate(-90deg);
}
......
......@@ -37,3 +37,23 @@ class ExtraMarkTable(tables.Table):
text=_("Delete"),
attrs={"a": {"class": "btn-flat waves-effect waves-red red-text"}},
)
class ExcuseTypeTable(tables.Table):
class Meta:
attrs = {"class": "highlight"}
name = tables.LinkColumn("edit_excuse_type", args=[A("id")])
short_name = tables.Column()
edit = tables.LinkColumn(
"edit_excuse_type",
args=[A("id")],
text=_("Edit"),
attrs={"a": {"class": "btn-flat waves-effect waves-orange orange-text"}},
)
delete = tables.LinkColumn(
"delete_excuse_type",
args=[A("id")],
text=_("Delete"),
attrs={"a": {"class": "btn-flat waves-effect waves-red red-text"}},
)
......@@ -156,6 +156,7 @@
<th>{% blocktrans %}Absent{% endblocktrans %}</th>
<th>{% blocktrans %}Tardiness{% endblocktrans %}</th>
<th>{% blocktrans %}Excused{% endblocktrans %}</th>
<th>{% blocktrans %}Excuse type{% endblocktrans %}</th>
<th>{% blocktrans %}Extra marks{% endblocktrans %}</th>
<th>{% blocktrans %}Remarks{% endblocktrans %}</th>
</tr>
......@@ -185,6 +186,14 @@
<span></span>
</label>
</td>
<td>
<div class="input-field">
{{ form.excuse_type }}
<label for="{{ form.excuse_type.id_for_label }}">
{% trans "Excuse type" %}
</label>
</div>
</td>
<td>
{% for group, items in form.extra_marks|select_options %}
{% for choice, value, selected in items %}
......
......@@ -88,20 +88,20 @@
{% blocktrans %}Personal notes{% endblocktrans %}
</span>
{% for person in persons %}
<h5 class="card-title">{{ person.full_name }}</h5>
<h5 class="card-title">{{ person.person.full_name }}</h5>
<p class="card-text">
{% trans "Absent" %}: {{ person.absences_count }}
({{ person.unexcused_count }} {% trans "unexcused" %})
{% trans "Absent" %}: {{ person.person.absences_count }}
({{ person.person.unexcused_count }} {% trans "unexcused" %})
</p>
<p class="card-text">
{% trans "Summed up tardiness" %}: {{ person.tardiness_sum }}'
{% trans "Summed up tardiness" %}: {{ person.person.tardiness_sum }}'
</p>
{% for extra_mark in extra_marks %}
<p class="card-text">
{{ extra_mark.name }}: {{ person|get_dict:extra_mark.count_label }}
{{ extra_mark.name }}: {{ person.person|get_dict:extra_mark.count_label }}
</p>
{% endfor %}
{% for note in person.personal_notes|only_week:week %}
{% for note in person.personal_notes %}
{% if note.remarks %}
<blockquote>
{{ note.remarks }}
......@@ -123,11 +123,11 @@
<div class="card red darken-1">
<div class="card-content white-text">
<span class="card-title">
{% blocktrans %}No group selected{% endblocktrans %}
{% blocktrans %}No lessons available{% endblocktrans %}
</span>
<p>
{% blocktrans %}
There are no lessons for the selected group, teacher or time.
There are no lessons for the selected group or teacher in this week.
{% endblocktrans %}
</p>
</div>
......
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load material_form i18n %}
{% block browser_title %}{% blocktrans %}Create excuse type{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Create excuse type{% endblocktrans %}{% endblock %}
{% block content %}
{% include "alsijil/excuse_type/warning.html" %}
<form method="post">
{% csrf_token %}
{% form form=form %}{% endform %}
{% include "core/partials/save_button.html" %}
</form>
{% endblock %}
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load material_form i18n %}
{% block browser_title %}{% blocktrans %}Edit excuse type{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Edit excuse type{% endblocktrans %}{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{% form form=form %}{% endform %}
{% include "core/partials/save_button.html" %}
</form>
{% endblock %}
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% block browser_title %}{% blocktrans %}Excuse types{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Excuse types{% endblocktrans %}{% endblock %}
{% block content %}
{% include "alsijil/excuse_type/warning.html" %}
<a class="btn green waves-effect waves-light" href="{% url 'create_excuse_type' %}">
<i class="material-icons left">add</i>
{% trans "Create excuse type" %}
</a>
{% render_table table %}
{% endblock %}
{% load i18n %}
<div class="alert warning">
<p>
<i class="material-icons left">warning</i>
{% blocktrans %}
This function should only be used to define alternatives to the default excuse which also will be counted extra.
Don't use this to create a default excuse or if you don't divide between different types of excuse.
{% endblocktrans %}
</p>
</div>
{% load i18n %}
{% for note in notes %}
<span class="{% if note.excused %}green-text{% else %}red-text{% endif %}">{{ note.person }}
{% if note.excused %}{% trans "(e)" %}{% else %}{% trans "(u)" %}{% endif %}{% if not forloop.last %},{% endif %}
{% if note.excused %}{% if note.excuse_type %}({{ note.excuse_type.short_name }}){% else %}{% trans "(e)" %}{% endif %}{% else %}{% trans "(u)" %}{% endif %}{% if not forloop.last %},{% endif %}
</span>
{% endfor %}
......@@ -14,6 +14,8 @@
<div class="center-align">
<h1>{% trans 'Class register' %}</h1>
<h5>{{ school_term }}</h5>
<p>({{ school_term.date_start }}–{{ school_term.date_end }})</p>
{% static "img/aleksis-banner.svg" as aleksis_banner %}
<img src="{% firstof request.site.preferences.theme__logo.url aleksis_banner %}"
alt="{{ request.site.preferences.general__title }} – Logo" class="max-size-600 center">
......@@ -64,6 +66,40 @@
<div class="page-break">&nbsp;</div>
<h4>{% trans "Abbreviations" %}</h4>
<h5>{% trans "General" %}</h5>
<ul class="collection">
<li class="collection-item">
<strong>(a)</strong> {% trans "Absent" %}
</li>
<li class="collection-item">
<strong>(b)</strong> {% trans "Late" %}
</li>
<li class="collection-item">
<strong>(u)</strong> {% trans "Unexcused" %}
</li>
<li class="collection-item">
<strong>(e)</strong> {% trans "Excused" %}
</li>
</ul>
{% if excuse_types %}
<h5>{% trans "Custom excuse types" %}</h5>
<ul class="collection">
{% for excuse_type in excuse_types %}
<li class="collection-item">
<strong>({{ excuse_type.short_name }})</strong> {{ excuse_type.name }}
</li>
{% endfor %}
</ul>
{% endif %}
<div class="page-break">&nbsp;</div>
<h4>{% trans 'Persons in group' %} {{ group.name }}</h4>
<table id="persons">
......@@ -74,9 +110,13 @@
<th>{% trans 'First name' %}</th>
<th>{% trans 'Sex' %}</th>
<th>{% trans 'Date of birth' %}</th>
<th>{% trans 'Absences' %}</th>
<th>{% trans 'Unexcused' %}</th>
<th>{% trans 'Tard.' %}</th>
<th>{% trans '(a)' %}</th>
<th>{% trans "(e)" %}</th>
{% for excuse_type in excuse_types %}
<th>({{ excuse_type.short_name }})</th>
{% endfor %}
<th>{% trans '(u)' %}</th>
<th>{% trans '(b)' %}</th>
{% for extra_mark in extra_marks %}
<th>{{ extra_mark.short_name }}</th>
{% endfor %}
......@@ -92,6 +132,10 @@
<td>{{ person.get_sex_display }}</td>
<td>{{ person.date_of_birth }}</td>
<td>{{ person.absences_count }}</td>
<td>{{ person.excused }}</td>
{% for excuse_type in excuse_types %}
<td>{{ person|get_dict:excuse_type.count_label }}</td>
{% endfor %}
<td>{{ person.unexcused }}</td>
<td>{{ person.tardiness }}'</td>
{% for extra_mark in extra_marks %}
......@@ -123,8 +167,8 @@
<tr>
<td>{{ lesson.subject.name }}</td>
<td>{{ lesson.teachers.all|join:', ' }}</td>
<td>{{ lesson.date_start }}</td>
<td>{{ lesson.date_end }}</td>
<td>{{ lesson.validity.date_start }}</td>
<td>{{ lesson.validity.date_end }}</td>
<td>{{ lesson.lesson_periods.count }}</td>
</tr>
{% endfor %}
......@@ -156,8 +200,8 @@
<td>{{ child_group.name }}</td>
<td>{{ lesson.subject.name }}</td>
<td>{{ lesson.teachers.all|join:', ' }}</td>
<td>{{ lesson.date_start }}</td>
<td>{{ lesson.date_end }}</td>
<td>{{ lesson.validity.date_start }}</td>
<td>{{ lesson.validity.date_end }}</td>
<td>{{ lesson.lesson_periods.count }}</td>
</tr>
{% endfor %}
......@@ -232,21 +276,28 @@
<h5>{% trans 'Absences and tardiness' %}</h5>
<table>
<thead>
<tr>
<th>{% trans 'Absences' %}</th>
<th>{% trans 'Unexcused' %}</th>
<th>{% trans 'Tardiness' %}</th>
<th colspan="2">{% trans 'Absences' %}</th>
<td>{{ person.absences_count }}</td>
</tr>
</thead>
<tbody>
<tr>
<td>{{ person.absences_count }}</td>
<td rowspan="{{ excuse_types.count|add:2 }}" style="width: 16mm;"
class="rotate small-print">{% trans "thereof" %}</td>
<th>{% trans 'Excused' %}</th>
<td>{{ person.excused }}</td>
</tr>
{% for excuse_type in excuse_types %}
<th>{{ excuse_type.name }}</th>
<td>{{ person|get_dict:excuse_type.count_label }}</td>
{% endfor %}
<tr>
<th>{% trans 'Unexcused' %}</th>
<td>{{ person.unexcused }}</td>
</tr>
<tr>
<th colspan="2">{% trans 'Tardiness' %}</th>
<td>{{ person.tardiness }}'</td>
</tr>
</tbody>
</table>
{% if extra_marks %}
......@@ -287,8 +338,12 @@
<td>
{% if note.absent %}
{% trans 'Yes' %}
{% if note.escused %}
({% trans 'e' %})
{% if note.excused %}
{% if note.excuse_type %}
({{ note.excuse_type.short_name }})
{% else %}
({% trans 'e' %})
{% endif %}
{% endif %}
{% endif %}
</td>
......@@ -370,8 +425,12 @@
{{ note.person.last_name }}, {{ note.person.first_name|slice:"0:1" }}.
{% if note.excused %}
<span class="lesson-note-excused">
({% trans 'e' %})
</span>
{% if note.excuse_type %}
({{ note.excuse_type.short_name }})
{% else %}
({% trans 'e' %})
{% endif %}
</span>
{% endif %}
</span>
{% endif %}
......@@ -381,8 +440,12 @@
({{ note.late }}′)
{% if note.excused %}
<span class="lesson-note-excused">
({% trans 'e' %})
</span>
{% if note.excuse_type %}
({{ note.excuse_type.short_name }})
{% else %}
({% trans 'e' %})
{% endif %}
</span>
{% endif %}
</span>
{% endif %}
......
......@@ -57,4 +57,20 @@ urlpatterns = [
views.ExtraMarkDeleteView.as_view(),
name="delete_extra_mark",
),
path("excuse_types/", views.ExcuseTypeListView.as_view(), name="excuse_types"),
path(
"excuse_types/create/",
views.ExcuseTypeCreateView.as_view(),
name="create_excuse_type",
),
path(
"excuse_types/<int:pk>/edit/",
views.ExcuseTypeEditView.as_view(),
name="edit_excuse_type",
),
path(
"excuse_types/<int:pk>/delete/",
views.ExcuseTypeDeleteView.as_view(),
name="delete_excuse_type",
),
]
......@@ -21,6 +21,7 @@ from aleksis.core.models import Group, Person, SchoolTerm
from aleksis.core.util import messages
from .forms import (
ExcuseTypeForm,
ExtraMarkForm,
LessonDocumentationForm,
PersonalNoteFilterForm,
......@@ -28,8 +29,8 @@ from .forms import (
RegisterAbsenceForm,
SelectForm,
)
from .models import ExtraMark, LessonDocumentation, PersonalNoteFilter
from .tables import ExtraMarkTable, PersonalNoteFilterTable
from .models import ExcuseType, ExtraMark, LessonDocumentation, PersonalNoteFilter
from .tables import ExcuseTypeTable, ExtraMarkTable, PersonalNoteFilterTable
def lesson(
......@@ -103,6 +104,8 @@ def lesson(
if lesson_documentation_form.is_valid():
lesson_documentation_form.save()
messages.success(request, _("The lesson documentation has been saved."))
if personal_note_formset.is_valid():
instances = personal_note_formset.save()
......@@ -113,8 +116,16 @@ def lesson(
lesson_period.period.period + 1,
instance.absent,
instance.excused,
instance.excuse_type,
)
messages.success(request, _("The personal notes have been saved."))
# Regenerate form here to ensure that programmatically changed data will be shown correctly
personal_note_formset = PersonalNoteFormSet(
None, queryset=persons_qs, prefix="personal_notes"
)
context["lesson_documentation"] = lesson_documentation
context["lesson_documentation_form"] = lesson_documentation_form
context["personal_note_formset"] = personal_note_formset
......@@ -189,16 +200,25 @@ def week_view(
if lesson_periods:
# Aggregate all personal notes for this group and week
persons = (
Person.objects.filter(is_active=True)
.filter(member_of__lessons__lesson_periods__in=lesson_periods)
.distinct()
lesson_periods_pk = list(lesson_periods.values_list("pk", flat=True))
persons_qs = Person.objects.filter(is_active=True)
if group:
persons_qs = persons_qs.filter(member_of=group)
else:
persons_qs = persons_qs.filter(
member_of__lessons__lesson_periods__in=lesson_periods_pk
)
persons_qs = (
persons_qs.distinct()
.prefetch_related("personal_notes")
.annotate(
absences_count=Count(
"personal_notes",
filter=Q(
personal_notes__lesson_period__in=lesson_periods,
personal_notes__lesson_period__in=lesson_periods_pk,
personal_notes__week=wanted_week.week,
personal_notes__absent=True,
),
......@@ -207,7 +227,7 @@ def week_view(
unexcused_count=Count(
"personal_notes",
filter=Q(
personal_notes__lesson_period__in=lesson_periods,
personal_notes__lesson_period__in=lesson_periods_pk,
personal_notes__week=wanted_week.week,
personal_notes__absent=True,
personal_notes__excused=False,
......@@ -217,7 +237,7 @@ def week_view(
tardiness_sum=Subquery(
Person.objects.filter(
pk=OuterRef("pk"),
personal_notes__lesson_period__in=lesson_periods,
personal_notes__lesson_period__in=lesson_periods_pk,
personal_notes__week=wanted_week.week,
)
.distinct()
......@@ -228,12 +248,12 @@ def week_view(
)
for extra_mark in ExtraMark.objects.all():
persons = persons.annotate(
persons_qs = persons_qs.annotate(
**{
extra_mark.count_label: Count(
"personal_notes",
filter=Q(
personal_notes__lesson_period__in=lesson_periods,
personal_notes__lesson_period__in=lesson_periods_pk,
personal_notes__week=wanted_week.week,
personal_notes__extra_marks=extra_mark,
),
......@@ -242,6 +262,16 @@ def week_view(
}
)
persons = []
for person in persons_qs:
persons.append(
{
"person": person,
"personal_notes": person.personal_notes.filter(
week=wanted_week.week, lesson_period__in=lesson_periods_pk
),
}
)
else:
persons = None
......@@ -325,6 +355,14 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse:
absences_count=Count(
"personal_notes__absent", filter=Q(personal_notes__absent=True)
),
excused=Count(
"personal_notes__absent",
filter=Q(
personal_notes__absent=True,
personal_notes__excused=True,
personal_notes__excuse_type__isnull=True,
),
),
unexcused=Count(
"personal_notes__absent",
filter=Q(personal_notes__absent=True, personal_notes__excused=False),
......@@ -341,6 +379,19 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse:
}
)
for excuse_type in ExcuseType.objects.all():
persons = persons.annotate(
**{
excuse_type.count_label: Count(
"personal_notes__absent",
filter=Q(
personal_notes__absent=True,
personal_notes__excuse_type=excuse_type,
),
)
}
)
# FIXME Move to manager
personal_note_filters = PersonalNoteFilter.objects.all()
for personal_note_filter in personal_note_filters:
......@@ -356,9 +407,11 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse:
}
)
context["extra_marks"] = ExtraMark.objects.all()
context["school_term"] = current_school_term
context["persons"] = persons
context["personal_note_filters"] = personal_note_filters
context["excuse_types"] = ExcuseType.objects.all()
context["extra_marks"] = ExtraMark.objects.all()
context["group"] = group
context["weeks"] = weeks
context["periods_by_day"] = periods_by_day
......@@ -490,3 +543,44 @@ class ExtraMarkDeleteView(AdvancedDeleteView, PermissionRequiredMixin, RevisionM
template_name = "core/pages/delete.html"
success_url = reverse_lazy("extra_marks")
success_message = _("The extra mark has been deleted.")
class ExcuseTypeListView(SingleTableView, PermissionRequiredMixin):
"""Table of all excuse types."""
model = ExcuseType
table_class = ExcuseTypeTable
permission_required = "core.view_excusetype"
template_name = "alsijil/excuse_type/list.html"
class ExcuseTypeCreateView(AdvancedCreateView, PermissionRequiredMixin):
"""Create view for excuse types."""
model = ExcuseType
form_class = ExcuseTypeForm
permission_required = "core.create_excusetype"
template_name = "alsijil/excuse_type/create.html"
success_url = reverse_lazy("excuse_types")
success_message = _("The excuse type has been created.")
class ExcuseTypeEditView(AdvancedEditView, PermissionRequiredMixin):
"""Edit view for excuse types."""
model = ExcuseType
form_class = ExcuseTypeForm
permission_required = "core.edit_excusetype"
template_name = "alsijil/excuse_type/edit.html"
success_url = reverse_lazy("excuse_types")
success_message = _("The excuse type has been saved.")
class ExcuseTypeDeleteView(AdvancedDeleteView, PermissionRequiredMixin, RevisionMixin):
"""Delete view for excuse types"""
model = ExcuseType
permission_required = "core.delete_excusetype"
template_name = "core/pages/delete.html"
success_url = reverse_lazy("excuse_types")
success_message = _("The excuse type has been deleted.")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment