diff --git a/README.rst b/README.rst index 895b6e5077d8d37a557edf01bae80182f41077bf..46a0bb8b6be07cc3e36c553b3c11211635892aa1 100644 --- a/README.rst +++ b/README.rst @@ -9,7 +9,19 @@ This is an application for use with the `AlekSIS`_ platform. Features -------- -The Alsijil app provides functionality for digital class registers. +This AlekSIS app currently provides the following features for managing digital class registers: + +* For users: + + * Manage and assign group roles + * Manage custom excuse types + * Manage extra marks (e. g. forgotten homework) + * Manage group notes for every lesson + * Manage lesson documentations for every lesson + * Manage personal notes for every lesson + * Show all owned groups of the current person + * Show all students of the current person + * Show filterable (week) overview for lesson documentations and personal/group notes Licence ------- diff --git a/aleksis/apps/alsijil/migrations/0013_fix_uniqueness_per_site.py b/aleksis/apps/alsijil/migrations/0013_fix_uniqueness_per_site.py new file mode 100644 index 0000000000000000000000000000000000000000..ed4edc714dc1c9f7c5c82ca58d3edd6f1628891c --- /dev/null +++ b/aleksis/apps/alsijil/migrations/0013_fix_uniqueness_per_site.py @@ -0,0 +1,49 @@ +# Generated by Django 3.2.3 on 2021-05-23 12:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('alsijil', '0012_unique_relation'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='lessondocumentation', + unique_together=set(), + ), + migrations.AlterUniqueTogether( + name='personalnote', + unique_together=set(), + ), + migrations.AddConstraint( + model_name='excusetype', + constraint=models.UniqueConstraint(fields=('site_id', 'short_name'), name='unique_excuse_short_name'), + ), + migrations.AddConstraint( + model_name='excusetype', + constraint=models.UniqueConstraint(fields=('site_id', 'name'), name='unique_excuse_name'), + ), + migrations.AddConstraint( + model_name='extramark', + constraint=models.UniqueConstraint(fields=('site_id', 'short_name'), name='unique_mark_short_name'), + ), + migrations.AddConstraint( + model_name='extramark', + constraint=models.UniqueConstraint(fields=('site_id', 'name'), name='unique_mark_name'), + ), + migrations.AddConstraint( + model_name='grouprole', + constraint=models.UniqueConstraint(fields=('site_id', 'name'), name='unique_role_per_site'), + ), + migrations.AddConstraint( + model_name='lessondocumentation', + constraint=models.UniqueConstraint(fields=('lesson_period', 'week', 'year', 'event', 'extra_lesson'), name='unique_documentation_per_object'), + ), + migrations.AddConstraint( + model_name='personalnote', + constraint=models.UniqueConstraint(fields=('lesson_period', 'week', 'year', 'event', 'extra_lesson'), name='unique_personal_note_per_object'), + ), + ] diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py index 94044b74a3f3c859cd95ae19290e375baf9ee595..51857750b434dc03b36c23b7c10f6fcca69ed013 100644 --- a/aleksis/apps/alsijil/models.py +++ b/aleksis/apps/alsijil/models.py @@ -61,6 +61,12 @@ class ExcuseType(ExtensibleModel): ordering = ["name"] verbose_name = _("Excuse type") verbose_name_plural = _("Excuse types") + constraints = [ + models.UniqueConstraint( + fields=("site_id", "short_name"), name="unique_excuse_short_name" + ), + models.UniqueConstraint(fields=("site_id", "name"), name="unique_excuse_name"), + ] lesson_related_constraint_q = ( @@ -275,9 +281,12 @@ class PersonalNote(RegisterObjectRelatedMixin, ExtensibleModel): constraints = [ CheckConstraint( check=lesson_related_constraint_q, name="one_relation_only_personal_note" - ) + ), + models.UniqueConstraint( + fields=("lesson_period", "week", "year", "event", "extra_lesson"), + name="unique_personal_note_per_object", + ), ] - unique_together = ["lesson_period", "week", "year", "event", "extra_lesson"] class LessonDocumentation(RegisterObjectRelatedMixin, ExtensibleModel): @@ -362,9 +371,12 @@ class LessonDocumentation(RegisterObjectRelatedMixin, ExtensibleModel): constraints = [ CheckConstraint( check=lesson_related_constraint_q, name="one_relation_only_lesson_documentation", - ) + ), + models.UniqueConstraint( + fields=("lesson_period", "week", "year", "event", "extra_lesson"), + name="unique_documentation_per_object", + ), ] - unique_together = ["lesson_period", "week", "year", "event", "extra_lesson"] class ExtraMark(ExtensibleModel): @@ -387,6 +399,12 @@ class ExtraMark(ExtensibleModel): ordering = ["short_name"] verbose_name = _("Extra mark") verbose_name_plural = _("Extra marks") + constraints = [ + models.UniqueConstraint( + fields=("site_id", "short_name"), name="unique_mark_short_name" + ), + models.UniqueConstraint(fields=("site_id", "name"), name="unique_mark_name"), + ] class GroupRole(ExtensibleModel): @@ -402,6 +420,9 @@ class GroupRole(ExtensibleModel): class Meta: verbose_name = _("Group role") verbose_name_plural = _("Group roles") + constraints = [ + models.UniqueConstraint(fields=("site_id", "name"), name="unique_role_per_site"), + ] class GroupRoleAssignment(GroupPropertiesMixin, ExtensibleModel): diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py index bb7014100da62cdce1d7cd2255fe439f46883c59..0b418af8cb20cb96a109a4b8e55a16a707e38b6d 100644 --- a/aleksis/apps/alsijil/rules.py +++ b/aleksis/apps/alsijil/rules.py @@ -261,7 +261,7 @@ add_perm("alsijil.delete_grouprole_rule", delete_group_role_predicate) view_assigned_group_roles_predicate = has_person & ( is_group_owner - | has_global_perm("alsjil.assign_grouprole") + | has_global_perm("alsijil.assign_grouprole") | has_object_perm("core.assign_grouprole") ) add_perm("alsijil.view_assigned_grouproles_rule", view_assigned_group_roles_predicate) @@ -270,7 +270,7 @@ view_assigned_group_roles_register_object_predicate = has_person & ( is_lesson_teacher | is_lesson_original_teacher | is_lesson_parent_group_owner - | has_global_perm("alsjil.assign_grouprole") + | has_global_perm("alsijil.assign_grouprole") ) add_perm( "alsijil.view_assigned_grouproles_for_register_object", @@ -278,12 +278,12 @@ add_perm( ) assign_group_role_person_predicate = has_person & ( - is_person_group_owner | has_global_perm("alsjil.assign_grouprole") + is_person_group_owner | has_global_perm("alsijil.assign_grouprole") ) add_perm("alsijil.assign_grouprole_to_person_rule", assign_group_role_person_predicate) assign_group_role_for_multiple_predicate = has_person & ( - is_owner_of_any_group | has_global_perm("alsjil.assign_grouprole") + is_owner_of_any_group | has_global_perm("alsijil.assign_grouprole") ) add_perm("alsijil.assign_grouprole_for_multiple_rule", assign_group_role_for_multiple_predicate) @@ -291,7 +291,7 @@ assign_group_role_group_predicate = view_assigned_group_roles_predicate add_perm("alsijil.assign_grouprole_for_group_rule", assign_group_role_group_predicate) edit_group_role_assignment_predicate = has_person & ( - has_global_perm("alsjil.assign_grouprole") | is_group_role_assignment_group_owner + has_global_perm("alsijil.assign_grouprole") | is_group_role_assignment_group_owner ) add_perm("alsijil.edit_grouproleassignment_rule", edit_group_role_assignment_predicate) @@ -299,7 +299,7 @@ stop_group_role_assignment_predicate = edit_group_role_assignment_predicate add_perm("alsijil.stop_grouproleassignment_rule", stop_group_role_assignment_predicate) delete_group_role_assignment_predicate = has_person & ( - has_global_perm("alsjil.assign_grouprole") | is_group_role_assignment_group_owner + has_global_perm("alsijil.assign_grouprole") | is_group_role_assignment_group_owner ) add_perm("alsijil.delete_grouproleassignment_rule", delete_group_role_assignment_predicate) diff --git a/aleksis/apps/alsijil/tables.py b/aleksis/apps/alsijil/tables.py index b0337d749297affafcf487b3936aec0efa4c0789..bf841edc5565159fdc3cb54e6f5f424e6f2c072c 100644 --- a/aleksis/apps/alsijil/tables.py +++ b/aleksis/apps/alsijil/tables.py @@ -51,9 +51,9 @@ class ExcuseTypeTable(tables.Table): ) def before_render(self, request): - if not request.user.has_perm("alsijil.edit_excusetype"): + if not request.user.has_perm("alsijil.edit_excusetype_rule"): self.columns.hide("edit") - if not request.user.has_perm("alsijil.delete_excusetype"): + if not request.user.has_perm("alsijil.delete_excusetype_rule"): self.columns.hide("delete") @@ -80,9 +80,9 @@ class GroupRoleTable(tables.Table): return render_to_string("alsijil/group_role/chip.html", context) def before_render(self, request): - if not request.user.has_perm("alsijil.edit_grouprole"): + if not request.user.has_perm("alsijil.edit_grouprole_rule"): self.columns.hide("edit") - if not request.user.has_perm("alsijil.delete_grouprole"): + if not request.user.has_perm("alsijil.delete_grouprole_rule"): self.columns.hide("delete") diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/groups.html b/aleksis/apps/alsijil/templates/alsijil/class_register/groups.html index f300f3b8457eed468cb3bad31821eb8d94033cf8..8c6254cdbd54ea045ec16df9684b6e65171a9d33 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/groups.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/groups.html @@ -38,7 +38,7 @@ <i class="material-icons left">view_week</i> {% trans "Week view" %} </a> - {% has_perm "alsijil.view_assigned_grouproles" user group as can_view_assigned_group_roles %} + {% has_perm "alsijil.view_assigned_grouproles_rule" user group as can_view_assigned_group_roles %} {% if can_view_assigned_group_roles %} <a class="btn primary waves-effect waves-light" href="{% url 'assigned_group_roles' group.pk %}"> <i class="material-icons left">assignment_ind</i> @@ -82,7 +82,7 @@ {% trans "Week view" %} </a> </p> - {% has_perm "alsijil.view_assigned_grouproles" user group as can_view_assigned_group_roles %} + {% has_perm "alsijil.view_assigned_grouproles_rule" user group as can_view_assigned_group_roles %} {% if can_view_assigned_group_roles %} <p> <a class="btn primary waves-effect waves-light" href="{% url 'assigned_group_roles' group.pk %}"> diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html b/aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html index 94b8b8118d77afe98d53283b8375509a86d2c986..7092d63fca12c762273a1590427349efb7ffd216 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/lesson.html @@ -66,9 +66,9 @@ </h4> <br/> - {% has_perm "alsijil.view_lessondocumentation" user register_object as can_view_lesson_documentation %} - {% has_perm "alsijil.edit_lessondocumentation" user register_object as can_edit_lesson_documentation %} - {% has_perm "alsijil.edit_register_object_personalnote" user register_object as can_edit_register_object_personalnote %} + {% has_perm "alsijil.view_lessondocumentation_rule" user register_object as can_view_lesson_documentation %} + {% has_perm "alsijil.edit_lessondocumentation_rule" user register_object as can_edit_lesson_documentation %} + {% has_perm "alsijil.edit_register_object_personalnote_rule" user register_object as can_edit_register_object_personalnote %} <form method="post" class="row"> <p> @@ -115,7 +115,7 @@ </li> {% endif %} {% if prev_lesson %} - {% has_perm "alsijil.view_lessondocumentation" user prev_lesson as can_view_prev_lesson_documentation %} + {% has_perm "alsijil.view_lessondocumentation_rule" user prev_lesson as can_view_prev_lesson_documentation %} {% if prev_lesson.get_lesson_documentation and can_view_prev_lesson_documentation %} <li class="tab"> <a href="#previous-lesson">{% trans "Previous lesson" %}</a> @@ -176,7 +176,7 @@ {% with prev_doc=prev_lesson.get_lesson_documentation %} {% with absences=prev_lesson.get_absences tardinesses=prev_lesson.get_tardinesses extra_marks=prev_lesson.get_extra_marks %} - {% has_perm "alsijil.view_lessondocumentation" user prev_lesson as can_view_prev_lesson_documentation %} + {% has_perm "alsijil.view_lessondocumentation_rule" user prev_lesson as can_view_prev_lesson_documentation %} {% if prev_doc and can_view_prev_lesson_documentation %} {% weekday_to_date prev_lesson.week prev_lesson.period.weekday as prev_date %} <div class="col s12" id="previous-lesson"> @@ -228,7 +228,7 @@ <th>{{ extra_mark.name }}</th> <td> {% for note in notes %} - {% has_perm "alsijil.view_personalnote" user note as can_view_personalnote %} + {% has_perm "alsijil.view_personalnote_rule" user note as can_view_personalnote %} {% if can_view_personalnote %} <span>{{ note.person }}{% if not forloop.last %},{% endif %}</span> {% endif %} diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html index 4d063d3ddaf1dc67da0ae29a5d0ac2e0b4c67911..e73e48dcafc3cd1bba617e2cc9cd30e6799c439a 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html @@ -11,7 +11,7 @@ {% block page_title %} - {% has_perm "alsijil.view_my_students" user as has_students %} + {% has_perm "alsijil.view_my_students_rule" user as has_students %} {% if has_students %} <a href="{% url "my_students" %}" class="btn-flat primary-color-text waves-light waves-effect"> @@ -23,7 +23,7 @@ Class register overview for {{ person }} {% endblocktrans %} </span> - {% has_perm "alsijil.register_absence" user person as can_register_absence %} + {% has_perm "alsijil.register_absence_rule" user person as can_register_absence %} {% if can_register_absence %} <a class="btn primary-color waves-effect waves-light right" href="{% url "register_absence" person.pk %}"> <i class="material-icons left">rate_review</i> @@ -80,7 +80,7 @@ </button> </div> </form> - {% has_perm "alsijil.edit_person_overview_personalnote" user person as can_mark_all_as_excused %} + {% has_perm "alsijil.edit_person_overview_personalnote_rule" user person as can_mark_all_as_excused %} <div class="row"> <div class="col s12 m3 l5 push-m9 push-l7"> <button diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html b/aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html index 970a07558aa6b2d4308e2fc57d74f633723cd53f..82d9fb4b987e8c920cf5768a69bd0d6acd07e83a 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html @@ -112,7 +112,7 @@ </thead> <tbody> {% for register_object in objects %} - {% has_perm "alsijil.view_lessondocumentation" user register_object as can_view_lesson_documentation %} + {% has_perm "alsijil.view_lessondocumentation_rule" user register_object as can_view_lesson_documentation %} {% if can_view_lesson_documentation %} <tr> <td class="center-align"> @@ -192,7 +192,7 @@ <div class="collapsible-body"> <div class="collection"> {% for register_object in objects %} - {% has_perm "alsijil.view_lessondocumentation" user register_object as can_view_lesson_documentation %} + {% has_perm "alsijil.view_lessondocumentation_rule" user register_object as can_view_lesson_documentation %} {% if can_view_lesson_documentation %} <a class="collection-item avatar" href="{{ register_object.alsijil_url }}?back={{ back_url }}"> @@ -319,7 +319,7 @@ {% for person in persons %} <h5 class="card-title"> <a href="{% url "overview_person" person.person.pk %}">{{ person.person.full_name }}</a> - {% has_perm "alsijil.register_absence" user person.person as can_register_absence %} + {% has_perm "alsijil.register_absence_rule" user person.person as can_register_absence %} {% if can_register_absence %} <a class="btn primary-color waves-effect waves-light right" href="{% url "register_absence" person.person.pk %}"> diff --git a/aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html b/aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html index 9c74d62e127f6a03b1ad7637114badfc2f4d9de2..c394784f0a9bfbb681a33c5f6875206f8d94b42a 100644 --- a/aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html +++ b/aleksis/apps/alsijil/templates/alsijil/excuse_type/list.html @@ -11,7 +11,7 @@ {% block content %} {% include "alsijil/excuse_type/warning.html" %} - {% has_perm "alsijil.add_excusetype" user as add_excusetype %} + {% has_perm "alsijil.add_excusetype_rule" user as add_excusetype %} {% if add_excusetype %} <a class="btn green waves-effect waves-light" href="{% url 'create_excuse_type' %}"> <i class="material-icons left">add</i> diff --git a/aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html b/aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html index 087dffaaf7151272b97c71e60ca178bc994547a3..a5533b444615836ccddefed3b45f009ced5b987c 100644 --- a/aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html +++ b/aleksis/apps/alsijil/templates/alsijil/group_role/assigned_list.html @@ -21,7 +21,7 @@ {% url "assigned_group_roles" object.pk as back_url %} <p> - {% has_perm "alsijil.view_my_groups" user as can_view_group_overview %} + {% has_perm "alsijil.view_my_groups_rule" user as can_view_group_overview %} {% if can_view_group_overview %} <a class="btn waves-effect waves-light" href="{% url "my_groups" %}"> <i class="material-icons left">arrow_back</i> @@ -29,7 +29,7 @@ </a> {% endif %} - {% has_perm "alsijil.assign_grouprole_for_group" user object as can_assign_group_role %} + {% has_perm "alsijil.assign_grouprole_for_group_rule" user object as can_assign_group_role %} {% if can_assign_group_role %} <a class="btn green waves-effect waves-light" href="{% url "assign_group_role" object.pk %}"> <i class="material-icons left">assignment_ind</i> diff --git a/aleksis/apps/alsijil/templates/alsijil/group_role/list.html b/aleksis/apps/alsijil/templates/alsijil/group_role/list.html index f3e4a487edfcec8761f978f89b25640b7580da40..73606d95b0f2cef8b24939dc7ab55a80d0a8721a 100644 --- a/aleksis/apps/alsijil/templates/alsijil/group_role/list.html +++ b/aleksis/apps/alsijil/templates/alsijil/group_role/list.html @@ -9,7 +9,7 @@ {% block page_title %}{% blocktrans %}Group roles{% endblocktrans %}{% endblock %} {% block content %} - {% has_perm "alsijil.add_grouprole" user as add_group_role %} + {% has_perm "alsijil.add_grouprole_rule" user as add_group_role %} {% if add_group_role %} <a class="btn green waves-effect waves-light" href="{% url 'create_group_role' %}"> <i class="material-icons left">add</i> diff --git a/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assigned_roles.html b/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assigned_roles.html index bc8c16f022b528cd666b3056d61317ad7fd297d8..349cd940cacbb9a8cc0ed19c277a1e08220877ce 100644 --- a/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assigned_roles.html +++ b/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assigned_roles.html @@ -1,5 +1,5 @@ {% load i18n rules %} -{% has_perm "alsijil.assign_grouprole_for_group" user group as can_assign_group_role %} +{% has_perm "alsijil.assign_grouprole_for_group_rule" user group as can_assign_group_role %} <div class="collection"> {% for role in roles %} <div class="collection-item"> diff --git a/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html b/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html index ff50720db9dacd5437fb4b43ecf19e9719138de3..6c6928934229e4b1f721fa98a7df49683d77d556 100644 --- a/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html +++ b/aleksis/apps/alsijil/templates/alsijil/group_role/partials/assignment_options.html @@ -2,9 +2,9 @@ {% load i18n rules %} -{% has_perm "alsijil.edit_grouproleassignment" user assignment as can_edit %} -{% has_perm "alsijil.stop_grouproleassignment" user assignment as can_stop %} -{% has_perm "alsijil.delete_grouproleassignment" user assignment as can_delete %} +{% has_perm "alsijil.edit_grouproleassignment_rule" user assignment as can_edit %} +{% has_perm "alsijil.stop_grouproleassignment_rule" user assignment as can_stop %} +{% has_perm "alsijil.delete_grouproleassignment_rule" user assignment as can_delete %} <ul id="dropdown-{{ assignment.pk }}{{ suffix }}" class="dropdown-content"> {% if can_edit %} diff --git a/aleksis/apps/alsijil/templates/alsijil/partials/absences.html b/aleksis/apps/alsijil/templates/alsijil/partials/absences.html index c72204c556efee0c5308d607947b5cd9670d85c3..d1faaadd474111453bc07e608ddb63aee11efedc 100644 --- a/aleksis/apps/alsijil/templates/alsijil/partials/absences.html +++ b/aleksis/apps/alsijil/templates/alsijil/partials/absences.html @@ -1,6 +1,6 @@ {% load i18n rules %} {% for note in notes %} - {% has_perm "alsijil.view_personalnote" user note as can_view_personalnote %} + {% has_perm "alsijil.view_personalnote_rule" user note as can_view_personalnote %} {% if can_view_personalnote %} <span class="{% if note.excused %}green-text{% else %}red-text{% endif %}">{{ note.person }} {% 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 %} diff --git a/aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html b/aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html index 25341b1a6deb1ae867000ad1b20f7ad5a46d7d1a..ea78cc7eb904c07cc151e7e23584120941d04704 100644 --- a/aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html +++ b/aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html @@ -108,7 +108,7 @@ <span class="hide-on-large-only">{% trans "Details" %}</span> </a> - {% has_perm "alsijil.register_absence" user person as can_register_absence %} + {% has_perm "alsijil.register_absence_rule" user person as can_register_absence %} {% if can_register_absence %} <a class="btn primary-color waves-effect waves-light" href="{% url "register_absence" person.pk %}"> <i class="material-icons left">rate_review</i> diff --git a/aleksis/apps/alsijil/templates/alsijil/partials/tardinesses.html b/aleksis/apps/alsijil/templates/alsijil/partials/tardinesses.html index 3bb86191612f2bdface729be8d048a6fb05edcd5..d11a94ea16f4ebd23a41dce65aca7980e1893172 100644 --- a/aleksis/apps/alsijil/templates/alsijil/partials/tardinesses.html +++ b/aleksis/apps/alsijil/templates/alsijil/partials/tardinesses.html @@ -1,6 +1,6 @@ {% load rules %} {% for note in notes %} - {% has_perm "alsijil.view_personalnote" user note as can_view_personalnote %} + {% has_perm "alsijil.view_personalnote_rule" user note as can_view_personalnote %} {% if can_view_personalnote %} <span>{{ note.person }} ({{ note.late }}'){% if not forloop.last %},{% endif %}</span> {% endif %}