diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py index 2449efb3176ed973fbc11368b562bc891ff23f2e..95360559b0cbe707ee5288375637b5ff1cb0dd0e 100644 --- a/aleksis/apps/alsijil/models.py +++ b/aleksis/apps/alsijil/models.py @@ -42,7 +42,7 @@ from aleksis.apps.kolego.models import Absence as KolegoAbsence from aleksis.apps.kolego.models import AbsenceReason from aleksis.core.data_checks import field_validation_data_check_factory from aleksis.core.mixins import ExtensibleModel, GlobalPermissionModel -from aleksis.core.models import CalendarEvent, Group, SchoolTerm +from aleksis.core.models import CalendarEvent, Group, Person, SchoolTerm from aleksis.core.util.core_helpers import get_site_preferences from aleksis.core.util.model_helpers import ICONS @@ -660,29 +660,12 @@ class Documentation(CalendarEvent): amends=lesson_event, course=course, subject=subject, - topic="", - homework="", - group_note="", ) obj.teachers.set(teachers.all()) obj.save() # Create Participation Statuses - # Cannot use djangos bulk_create method, as then the save method of the - # superclass wouldn't be called - - for member in lesson_event.all_members: - # TODO: Check for preexisting absences in kolego - # TODO: maybe only create if the lesson start is in the past - status = ParticipationStatus.objects.create( - person=member, - related_documentation=obj, - datetime_start=datetime_start, - datetime_end=datetime_end, - timezone=lesson_event.timezone, - ) - status.groups_of_person.set(member.member_of.all()) - status.save() + obj.touch() return obj @@ -692,15 +675,47 @@ class Documentation(CalendarEvent): return cls.create_from_lesson_event( user, *cls.parse_dummy(_id), - ) - - return cls.objects.get(id=_id) + ), True + + return cls.objects.get(id=_id), False + + def build_participation_status(self, person: Person) -> "ParticipationStatus": + """Build participation status object for this documentation and a person.""" + return ParticipationStatus( + person=person, + related_documentation=self, + datetime_start=self.datetime_start, + datetime_end=self.datetime_end, + # Set timezone directly as save of ParticipationStatus won't be called in bulk_create + timezone=self.timezone, + ) def touch(self): - # TODO: check if participation statuses etc. are created correctly. - # might require some extra work, as the object may have been created - # recently, so checking again would be overkill. - pass + # TODO: Check for preexisting absences in kolego + # TODO: maybe only create if the lesson start is in the past + + if not self.amends: + # There is no source to update from + return + + lesson_event: LessonEvent = self.amends + all_members = lesson_event.all_members + + existing_participations = ParticipationStatus.objects.filter( + person__in=all_members, related_documentation=self + ) + new_persons = Person.objects.filter( + Q(pk__in=[p.pk for p in all_members]) + & ~Q(pk__in=existing_participations.values_list("person", flat=True)) + ).prefetch_related("member_of") + new_participations = [] + for person in new_persons: + participation_status = self.build_participation_status(person) + participation_status.save() + participation_status.groups_of_person.set(person.member_of.all()) + new_participations.append(participation_status) + + return new_participations class ParticipationStatus(CalendarEvent): diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py index a994457550ff91d94897b2c7c1f7e373532577ee..433cde4e7c16508451f404765b72010e5d275929 100644 --- a/aleksis/apps/alsijil/schema/documentation.py +++ b/aleksis/apps/alsijil/schema/documentation.py @@ -109,7 +109,7 @@ class DocumentationBatchCreateOrUpdateMutation(graphene.Mutation): # Sadly, we can't use the update_or_create method since create_defaults # is only introduced in Django 5.0 - obj = Documentation.get_or_create_by_id(_id, info.context.user) + obj, __ = Documentation.get_or_create_by_id(_id, info.context.user) if not info.context.user.has_perm("alsijil.edit_documentation_rule", obj): raise PermissionDenied() @@ -146,6 +146,15 @@ class TouchDocumentationMutation(graphene.Mutation): documentation = graphene.Field(DocumentationType) def mutate(root, info, documentation_id): - documentation = Documentation.get_or_create_by_id(documentation_id, info.context.user) - documentation.touch() + documentation, created = Documentation.get_or_create_by_id( + documentation_id, info.context.user + ) + + if not info.context.user.has_perm( + "alsijil.edit_participation_status_for_documentation_rule", documentation + ): + raise PermissionDenied() + # FIXME Should not be effective in past + if not created: + documentation.touch() return TouchDocumentationMutation(documentation=documentation)