diff --git a/aleksis/apps/alsijil/forms.py b/aleksis/apps/alsijil/forms.py index c39709aa2b1d0161fff0ad4d13d4839b43d7ba06..6024b8581642073064c9c20e965f4ae5d9269638 100644 --- a/aleksis/apps/alsijil/forms.py +++ b/aleksis/apps/alsijil/forms.py @@ -119,15 +119,11 @@ PersonalNoteFormSet = forms.modelformset_factory( class RegisterAbsenceForm(forms.Form): layout = Layout( - Fieldset("", "person"), Fieldset("", Row("date_start", "date_end"), Row("from_period", "to_period")), Fieldset("", Row("absent", "excused"), Row("excuse_type"), Row("remarks")), ) date_start = forms.DateField(label=_("Start date"), initial=datetime.today) date_end = forms.DateField(label=_("End date"), initial=datetime.today) - person = forms.ModelChoiceField( - label=_("Person"), queryset=None, widget=Select2Widget - ) from_period = forms.ChoiceField(label=_("Start period")) to_period = forms.ChoiceField(label=_("End period")) absent = forms.BooleanField(label=_("Absent"), initial=True, required=False) @@ -145,37 +141,6 @@ class RegisterAbsenceForm(forms.Form): super().__init__(*args, **kwargs) period_choices = TimePeriod.period_choices - # Filter selectable persons by permissions - if check_global_permission(self.request.user, "alsijil.register_absence"): - # Global permission, user can register absences for all persons - self.fields["person"].queryset = Person.objects.all() - else: - # 1) All persons the user is allowed to register an absence for by object permissions - # 2) All persons the user is the primary group owner - # 3) All persons the user is allowed to register an absence for by object permissions of the person's group - persons_qs = ( - get_objects_for_user( - self.request.user, "core.register_absence_person", Person - ) - .union( - Person.objects.filter( - primary_group__owners=self.request.user.person - ) - ) - .union( - Person.objects.filter( - member_of__in=get_objects_for_user( - self.request.user, "core.register_absence_group", Group - ) - ) - ) - ) - - # Flatten query by getting all pks and filter persons - self.fields["person"].queryset = Person.objects.filter( - pk__in=list(persons_qs.values_list("pk", flat=True)) - ) - self.fields["from_period"].choices = period_choices self.fields["to_period"].choices = period_choices self.fields["from_period"].initial = TimePeriod.period_min diff --git a/aleksis/apps/alsijil/menus.py b/aleksis/apps/alsijil/menus.py index 87a1daa3c93fb4985d9ccbf5f6a8afb3e956503a..f90052a765147b8555840d84f24203b12f09b248 100644 --- a/aleksis/apps/alsijil/menus.py +++ b/aleksis/apps/alsijil/menus.py @@ -67,17 +67,6 @@ MENUS = { ), ], }, - { - "name": _("Register absence"), - "url": "register_absence", - "icon": "rate_review", - "validators": [ - ( - "aleksis.core.util.predicates.permission_validator", - "alsijil.view_register_absence", - ), - ], - }, { "name": _("Excuse types"), "url": "excuse_types", diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py index 7959099b1f1b88f64363ae946c79ea4ac3039ad0..23c22cbe340d1f27af1be11378623817eb360a8b 100644 --- a/aleksis/apps/alsijil/rules.py +++ b/aleksis/apps/alsijil/rules.py @@ -113,12 +113,6 @@ view_week_personal_notes_predicate = has_person & ( ) add_perm("alsijil.view_week_personalnote", view_week_personal_notes_predicate) -# View register absence page -view_register_absence_predicate = has_person & ( - has_global_perm("alsijil.register_absence") | has_any_object_absence -) -add_perm("alsijil.view_register_absence", view_register_absence_predicate) - # Register absence register_absence_predicate = has_person & ( ( diff --git a/aleksis/apps/alsijil/templates/alsijil/absences/register.html b/aleksis/apps/alsijil/templates/alsijil/absences/register.html index 4074c947fb5016b912bdfaf6d793bdf1a1b263b1..5452de10e44ca52dd75de373dcb43fe11c29bbf8 100644 --- a/aleksis/apps/alsijil/templates/alsijil/absences/register.html +++ b/aleksis/apps/alsijil/templates/alsijil/absences/register.html @@ -6,6 +6,7 @@ {% block page_title %}{% blocktrans %}Register absence{% endblocktrans %}{% endblock %} {% block content %} + <h6>{% trans "Person" %}: {{ person }}</h6> <form method="post"> {% csrf_token %} diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html index be40b8e2376da7409c7697a4d3bb901aa5c27fc7..e4cf09b92381b447036dc7325cac00eb4a998cda 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html @@ -23,6 +23,13 @@ {% block content %} {% has_perm "alsijil.edit_person_overview_personalnote" user person as can_mark_all_as_excused %} + {% has_perm "alsijil.register_absence" 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> + {% trans "Register absence" %} + </a> + {% endif %} <div class="row"> <div class="col s12 m12 l6"> 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 c9278671b55c085b3a379999fdb2ba1a25ae1f5a..49421615169bd68233ca347af4f4dc86f1747fb5 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/week_view.html @@ -249,6 +249,13 @@ {% else %} {{ person.person.full_name }} {% endif %} + {% has_perm "alsijil.register_absence" 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 %}"> + <i class="material-icons left">rate_review</i> + {% trans "Register absence" %} + </a> + {% endif %} </h5> <p class="card-text"> {% trans "Absent" %}: {{ person.person.absences_count }} 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 7da999cff243026df3e51b3f9d8ff7744fcfd932..25341b1a6deb1ae867000ad1b20f7ad5a46d7d1a 100644 --- a/aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html +++ b/aleksis/apps/alsijil/templates/alsijil/partials/persons_with_stats.html @@ -1,4 +1,4 @@ -{% load data_helpers time_helpers i18n %} +{% load data_helpers time_helpers i18n rules %} {% if not persons %} <div class="alert primary"> @@ -107,6 +107,14 @@ <span class="hide-on-med-and-down"> {% trans "Show more details" %}</span> <span class="hide-on-large-only">{% trans "Details" %}</span> </a> + + {% has_perm "alsijil.register_absence" 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> + {% trans "Register absence" %} + </a> + {% endif %} </td> </tr> {% endfor %} diff --git a/aleksis/apps/alsijil/urls.py b/aleksis/apps/alsijil/urls.py index 4d4c490a20ae82e1e04699f7d3b6b000cfe65e0b..38f7a41a36b701a9499dc12697ea70d32d46e54a 100644 --- a/aleksis/apps/alsijil/urls.py +++ b/aleksis/apps/alsijil/urls.py @@ -36,7 +36,7 @@ urlpatterns = [ views.DeletePersonalNoteView.as_view(), name="delete_personal_note", ), - path("absence/new", views.register_absence, name="register_absence"), + path("absence/new/<int:id_>/", views.register_absence, name="register_absence"), path("extra_marks/", views.ExtraMarkListView.as_view(), name="extra_marks"), path( "extra_marks/create/", diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py index b059ebf8da0bcd07bf699910907b5b95004ddbed..c93526317efd15abf07a730486895fa0fd1dba17 100644 --- a/aleksis/apps/alsijil/views.py +++ b/aleksis/apps/alsijil/views.py @@ -680,49 +680,47 @@ def overview_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResp return render(request, "alsijil/class_register/person.html", context) -@permission_required("alsijil.view_register_absence") -def register_absence(request: HttpRequest) -> HttpResponse: +@permission_required("alsijil.register_absence", fn=objectgetter_optional(Person)) +def register_absence(request: HttpRequest, id_: int) -> HttpResponse: context = {} + person = get_object_or_404(Person, pk=id_) + register_absence_form = RegisterAbsenceForm(request.POST or None) - if request.method == "POST": - if register_absence_form.is_valid() and request.user.has_perm( - "alsijil.register_absence", register_absence_form.cleaned_data["person"] - ): - # Get data from form - person = register_absence_form.cleaned_data["person"] - start_date = register_absence_form.cleaned_data["date_start"] - end_date = register_absence_form.cleaned_data["date_end"] - from_period = register_absence_form.cleaned_data["from_period"] - to_period = register_absence_form.cleaned_data["to_period"] - absent = register_absence_form.cleaned_data["absent"] - excused = register_absence_form.cleaned_data["excused"] - excuse_type = register_absence_form.cleaned_data["excuse_type"] - remarks = register_absence_form.cleaned_data["remarks"] - - # Mark person as absent - delta = end_date - start_date - for i in range(delta.days + 1): - from_period_on_day = from_period if i == 0 else TimePeriod.period_min - to_period_on_day = ( - to_period if i == delta.days else TimePeriod.period_max - ) - day = start_date + timedelta(days=i) - - person.mark_absent( - day, - from_period_on_day, - absent, - excused, - excuse_type, - remarks, - to_period_on_day, - ) + if request.method == "POST" and register_absence_form.is_valid(): + # Get data from form + # person = register_absence_form.cleaned_data["person"] + start_date = register_absence_form.cleaned_data["date_start"] + end_date = register_absence_form.cleaned_data["date_end"] + from_period = register_absence_form.cleaned_data["from_period"] + to_period = register_absence_form.cleaned_data["to_period"] + absent = register_absence_form.cleaned_data["absent"] + excused = register_absence_form.cleaned_data["excused"] + excuse_type = register_absence_form.cleaned_data["excuse_type"] + remarks = register_absence_form.cleaned_data["remarks"] + + # Mark person as absent + delta = end_date - start_date + for i in range(delta.days + 1): + from_period_on_day = from_period if i == 0 else TimePeriod.period_min + to_period_on_day = to_period if i == delta.days else TimePeriod.period_max + day = start_date + timedelta(days=i) + + person.mark_absent( + day, + from_period_on_day, + absent, + excused, + excuse_type, + remarks, + to_period_on_day, + ) - messages.success(request, _("The absence has been saved.")) - return redirect("register_absence") + messages.success(request, _("The absence has been saved.")) + return redirect("overview_person", person.pk) + context["person"] = person context["register_absence_form"] = register_absence_form return render(request, "alsijil/absences/register.html", context)