From f717a83a0488a77e911233de8fa30c6e01cd92b1 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Sun, 31 May 2020 12:32:33 +0200 Subject: [PATCH] Fix week view code - Fix select form - Fix names - Fix URLs --- aleksis/apps/alsijil/forms.py | 27 +++++++++---- aleksis/apps/alsijil/urls.py | 2 + aleksis/apps/alsijil/views.py | 71 ++++++++++++++++++++++------------- 3 files changed, 66 insertions(+), 34 deletions(-) diff --git a/aleksis/apps/alsijil/forms.py b/aleksis/apps/alsijil/forms.py index 350bf018d..48c809cde 100644 --- a/aleksis/apps/alsijil/forms.py +++ b/aleksis/apps/alsijil/forms.py @@ -1,6 +1,8 @@ from datetime import datetime +from aleksis.apps.chronos.managers import TimetableType from django import forms +from django.core.exceptions import ValidationError from django.db.models import Count from django.utils.translation import gettext_lazy as _ @@ -50,15 +52,24 @@ class SelectForm(forms.Form): required=False, widget=Select2Widget, ) - room = forms.ModelChoiceField( - queryset=Room.objects.annotate(lessons_count=Count("lesson_periods")).filter( - lessons_count__gt=0 - ), - label=_("Room"), - required=False, - widget=Select2Widget, - ) + def clean(self) -> dict: + data = super().clean() + + if data.get("group") and not data.get("teacher") : + type_ = TimetableType.GROUP + instance = data["group"] + elif data.get("teacher") and not data.get("group"): + type_ = TimetableType.TEACHER + instance = data["teacher"] + elif not data.get("teacher") and not data.get("group"): + return data + else: + raise ValidationError(_("You can't select a group and a teacher both.")) + + data["type_"] = type_ + data["instance"] = instance + return data PersonalNoteFormSet = forms.modelformset_factory( PersonalNote, form=PersonalNoteForm, max_num=0, extra=0 diff --git a/aleksis/apps/alsijil/urls.py b/aleksis/apps/alsijil/urls.py index 20519ad4d..fe40f18ee 100644 --- a/aleksis/apps/alsijil/urls.py +++ b/aleksis/apps/alsijil/urls.py @@ -11,6 +11,8 @@ urlpatterns = [ ), path("week", views.week_view, name="week_view"), path("week/<int:year>/<int:week>", views.week_view, name="week_view_by_week"), + path("week/<str:type_>/<int:id_>/", views.week_view, name="week_view"), + path("week/<int:year>/<int:week>/<str:type_>/<int:id_>/", views.week_view, name="week_view_by_week"), path("print/group/<int:id_>", views.full_register_group, name="full_register_group"), path("absence/new", views.register_absence, name="register_absence"), path("filters/list", views.list_personal_note_filters, name="list_personal_note_filters",), diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py index b1e9f40bd..ee7c8d7e9 100644 --- a/aleksis/apps/alsijil/views.py +++ b/aleksis/apps/alsijil/views.py @@ -1,9 +1,11 @@ from datetime import date, datetime, timedelta from typing import Optional +from aleksis.apps.chronos.managers import TimetableType +from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk from django.core.exceptions import PermissionDenied from django.db.models import Count, Exists, OuterRef, Q, Sum -from django.http import Http404, HttpRequest, HttpResponse +from django.http import Http404, HttpRequest, HttpResponse, HttpResponseNotFound from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.translation import ugettext as _ @@ -74,7 +76,7 @@ def lesson( lesson_period=lesson_period, week=wanted_week.week ) lesson_documentation_form = LessonDocumentationForm( - request.POST or None, instance=lesson_documentation, prefix="leson_documentation", + request.POST or None, instance=lesson_documentation, prefix="lesson_documentation", ) # Create a formset that holds all personal notes for all persons in this lesson @@ -107,7 +109,7 @@ def lesson( def week_view( - request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None + request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None, type_: Optional[str] = None, id_: Optional[int] = None ) -> HttpResponse: context = {} @@ -124,45 +126,62 @@ def week_view( ) ).in_week(wanted_week) - group = None # FIXME workaround for #38 - if ( - request.GET.get("group", None) - or request.GET.get("teacher", None) - or request.GET.get("room", None) - ): - lesson_periods = lesson_periods.filter_from_query(request.GET) - if "group" in request.GET and request.GET["group"]: - group = Group.objects.get(pk=request.GET["group"]) - else: - group = None + group = None + if type_ and id_: + instance = get_el_by_pk(request, type_, id_) + + if isinstance(instance, HttpResponseNotFound): + return HttpResponseNotFound() + + type_ = TimetableType.from_string(type_) + + if type_ == TimetableType.GROUP: + group = instance + + lesson_periods = lesson_periods.filter_from_type(type_, instance) elif hasattr(request, "user") and hasattr(request.user, "person"): - group = request.user.person.owner_of.first() - if group: - lesson_periods = lesson_periods.filter_group(group) - elif request.user.person.lessons_as_teacher.exists(): + instance = request.user.person + if request.user.person.lessons_as_teacher.exists(): lesson_periods = lesson_periods.filter_teacher(request.user.person) + type_ = TimetableType.TEACHER else: lesson_periods = lesson_periods.filter_participant(request.user.person) else: lesson_periods = None + # Add a form to filter the view + if type_: + initial = {type_.value: instance} + else: + initial = {} + select_form = SelectForm(request.POST or None, initial=initial) + + if request.method == "POST": + if select_form.is_valid(): + if "type_" not in select_form.cleaned_data: + return redirect("week_view_by_week", wanted_week.year, wanted_week.week) + else: + return redirect("week_view_by_week", wanted_week.year, wanted_week.week, + select_form.cleaned_data["type_"].value, select_form.cleaned_data["instance"].pk) + if lesson_periods: # Aggregate all personal notes for this group and week + lesson_periods_pk = lesson_periods.values_list("pk", flat=True) persons = ( Person.objects.filter(is_active=True) - .filter(member_of__lessons__lesson_periods__in=lesson_periods) + .filter(member_of__lessons__lesson_periods__in=lesson_periods_pk) .distinct() .prefetch_related("personal_notes") .annotate( - absences=Count( + absences_count=Count( "personal_notes__absent", 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, ), ), - unexcused=Count( + unexcused_count=Count( "personal_notes__absent", filter=Q( personal_notes__lesson_period__in=lesson_periods, @@ -171,7 +190,7 @@ def week_view( personal_notes__excused=False, ), ), - tardiness=Sum( + tardiness_sum=Sum( "personal_notes__late", filter=Q( personal_notes__lesson_period__in=lesson_periods, @@ -183,15 +202,15 @@ def week_view( else: persons = None - # Add a form to filter the view - select_form = SelectForm(request.GET or None) + # Resort lesson periods manually because an union queryset doesn't support order_by + lesson_periods = sorted(lesson_periods, key=lambda x: (x.period.weekday, x.period.period)) - context["current_head"] = str(wanted_week) context["week"] = wanted_week context["lesson_periods"] = lesson_periods context["persons"] = persons context["group"] = group context["select_form"] = select_form + context["instance"] = instance week_prev = wanted_week - 1 week_next = wanted_week + 1 -- GitLab