diff --git a/biscuit/apps/alsijil/forms.py b/biscuit/apps/alsijil/forms.py index be77cd06cae20c11b602af70b6716bd2bd33bfe7..dd64517d6aa575f3d2b540b460691a24a15afcfd 100644 --- a/biscuit/apps/alsijil/forms.py +++ b/biscuit/apps/alsijil/forms.py @@ -36,7 +36,7 @@ class SelectForm(forms.Form): label=_('Group'), required=False) teacher = forms.ModelChoiceField( queryset=Person.objects.annotate(lessons_count=Count( - 'lessons')).filter(lessons_count__gt=0), + 'lessons_as_teacher')).filter(lessons_count__gt=0), label=_('Teacher'), required=False) room = forms.ModelChoiceField( queryset=Room.objects.annotate(lessons_count=Count( diff --git a/biscuit/apps/alsijil/model_extensions.py b/biscuit/apps/alsijil/model_extensions.py new file mode 100644 index 0000000000000000000000000000000000000000..2b78cead0be4024b1a037cbcda6d1aebfd3caea7 --- /dev/null +++ b/biscuit/apps/alsijil/model_extensions.py @@ -0,0 +1,59 @@ +from datetime import date +from typing import Optional + +from django.db.models import Exists, OuterRef + +from biscuit.apps.chronos.models import LessonPeriod +from biscuit.apps.chronos.util import CalendarWeek +from biscuit.core.models import Group, Person + +from .models import PersonalNote + + +@Person.method +def mark_absent(self, day: date, starting_period: Optional[int] = 0, absent=True, excused=False): + wanted_week = CalendarWeek.from_date(day) + + # Get all lessons of this person on the specified day + lesson_periods = self.lesson_periods_as_participant.on_day( + day + ).filter( + period__period__gte=starting_period + ) + + # Create and update all personal notes for the discovered lesson periods + for lesson_period in lesson_periods: + PersonalNote.objects.update_or_create( + person=self, + lesson_period=lesson_period, + week=wanted_week.week, + defaults={ + 'absent': absent, + 'excused': excused + } + ) + + +@LessonPeriod.method +def get_personal_notes(self, wanted_week: CalendarWeek): + # Find all persons in the associated groups that do not yet have a personal note for this lesson + missing_persons = Person.objects.annotate( + no_personal_notes=~Exists(PersonalNote.objects.filter( + week=wanted_week.week, + lesson_period=self, + person__pk=OuterRef('pk') + )) + ).filter( + member_of__in=Group.objects.filter(pk__in=self.lesson.groups.all()), + is_active=True, + no_personal_notes=True + ) + + # Create all missing personal notes + PersonalNote.objects.bulk_create([ + PersonalNote(person=person, lesson_period=self, + week=wanted_week.week) for person in missing_persons + ]) + + return PersonalNote.objects.select_related('person').filter( + lesson_period=self, week=wanted_week.week) diff --git a/biscuit/apps/alsijil/views.py b/biscuit/apps/alsijil/views.py index af7a60e62a9c776fad8341df304ec2ad00daadff..75854dd771b22eeb699be1d9edaf580116fb15ab 100644 --- a/biscuit/apps/alsijil/views.py +++ b/biscuit/apps/alsijil/views.py @@ -14,7 +14,7 @@ from biscuit.apps.chronos.util import CalendarWeek from biscuit.core.models import Group, Person from .forms import LessonDocumentationForm, PersonalNoteFormSet, SelectForm -from .models import LessonDocumentation, PersonalNote +from .models import LessonDocumentation @login_required @@ -48,36 +48,27 @@ def lesson(request: HttpRequest, year: Optional[int] = None, week: Optional[int] lesson_documentation_form = LessonDocumentationForm( request.POST or None, instance=lesson_documentation, prefix='leson_documentation') - # Find all persons in the associated groups that do not yet have a personal note for this lesson - missing_persons = Person.objects.annotate( - no_personal_notes=~Exists(PersonalNote.objects.filter( - week=wanted_week.week, - lesson_period=lesson_period, - person__pk=OuterRef('pk') - )) - ).filter( - member_of__in=Group.objects.filter(pk__in=lesson_period.lesson.groups.all()), - is_active=True, - no_personal_notes=True - ) - - # Create all missing personal notes - PersonalNote.objects.bulk_create([ - PersonalNote(person=person, lesson_period=lesson_period, - week=wanted_week.week) for person in missing_persons # FIXME Respect year as well - ]) # Create a formset that holds all personal notes for all persons in this lesson - persons_qs = PersonalNote.objects.select_related('person').filter( - lesson_period=lesson_period, week=wanted_week.week) # FIXME Respect year as well + persons_qs = lesson_period.get_personal_notes(wanted_week) personal_note_formset = PersonalNoteFormSet( request.POST or None, queryset=persons_qs, prefix='personal_notes') if request.method == 'POST': if lesson_documentation_form.is_valid(): lesson_documentation_form.save() + if personal_note_formset.is_valid(): - personal_note_formset.save() + instances = personal_note_formset.save() + + # Iterate over personal notes and carry changed absences to following lessons + for instance in instances: + instance.person.mark_absent( + wanted_week[lesson_period.period.weekday-1], + lesson_period.period.period+1, + instance.absent, + instance.excused + ) context['lesson_documentation'] = lesson_documentation context['lesson_documentation_form'] = lesson_documentation_form