from enum import Enum from typing import Optional, Union from django.db.models import Q from aleksis.apps.cursus.models import Course from aleksis.core.managers import ( CalendarEventQuerySet, ) from aleksis.core.models import Group, Person, Room class TimetableType(Enum): """Enum for different types of timetables.""" GROUP = "group" TEACHER = "teacher" PARTICIPANT = "participant" ROOM = "room" COURSE = "course" @classmethod def from_string(cls, s: Optional[str]): return cls.__members__.get(s.upper()) class LessonEventQuerySet(CalendarEventQuerySet): """Queryset with special query methods for lesson events.""" @staticmethod def for_teacher_q(teacher: Union[int, Person]) -> Q: """Get all lesson events for a certain person as teacher (including amends).""" from .models import LessonEvent amended = ( LessonEvent.objects.filter(amended_by__isnull=False, teachers=teacher) .values_list("amended_by__pk", flat=True) .union(LessonEvent.objects.filter(teachers=teacher).values_list("pk", flat=True)) ) return Q(pk__in=amended) def for_teacher(self, teacher: Union[int, Person]) -> "LessonEventQuerySet": """Get all lesson events for a certain person as teacher (including amends).""" return self.filter(self.for_teacher_q(teacher)).distinct() @staticmethod def for_participant_q(person: Union[int, Person]) -> Q: """Get all lesson events the person participates in (including amends).""" from .models import LessonEvent amended = ( LessonEvent.objects.filter(amended_by__isnull=False, groups__members=person) .values_list("amended_by__pk", flat=True) .union(LessonEvent.objects.filter(groups__members=person).values_list("pk", flat=True)) ) return Q(pk__in=amended) def for_teachers(self, teachers: list[Union[int, Person]]) -> "LessonEventQuerySet": """Get all lesson events for a list of persons as teacher (including amends).""" amended = self.filter(Q(amended_by__isnull=False) & (Q(teachers__in=teachers))).values_list( "amended_by__pk", flat=True ) return self.filter(Q(teachers__in=teachers) | Q(pk__in=amended)).distinct() def for_participant(self, person: Union[int, Person]) -> "LessonEventQuerySet": """Get all lesson events the person participates in (including amends).""" return self.filter(self.for_participant_q(person)).distinct() @staticmethod def for_group_q(group: Union[int, Group]) -> Q: """Get all lesson events for a certain group (including amends/as parent group).""" from .models import LessonEvent amended = ( LessonEvent.objects.filter(amended_by__isnull=False, groups=group) .values_list("amended_by__pk", flat=True) .union( LessonEvent.objects.filter( amended_by__isnull=False, groups__parent_groups=group ).values_list("amended_by__pk", flat=True) ) .union(LessonEvent.objects.filter(groups=group).values_list("pk", flat=True)) .union( LessonEvent.objects.filter(groups__parent_groups=group).values_list("pk", flat=True) ) ) return Q(pk__in=amended) def for_owner_q(self, person: Union[int, Person]) -> Q: """Get all lesson events the person owns any group of (including amends).""" amended = self.filter(Q(amended_by__isnull=False) & Q(groups__owners=person)).values_list( "amended_by__pk", flat=True ) return Q(groups__owners=person) | Q(pk__in=amended) def for_owner(self, person: Union[int, Person]) -> "LessonEventQuerySet": """Get all lesson events the person owns any group of (including amends).""" return self.filter(self.for_owner_q(person)).distinct() def for_group(self, group: Union[int, Group]) -> "LessonEventQuerySet": """Get all lesson events for a certain group (including amends/as parent group).""" return self.filter(self.for_group_q(group)).distinct() @staticmethod def for_room_q(room: Union[int, Room]) -> Q: """Get all lesson events for a certain room (including amends).""" from .models import LessonEvent amended = ( LessonEvent.objects.filter(amended_by__isnull=False, rooms=room) .values_list("amended_by__pk", flat=True) .union(LessonEvent.objects.filter(rooms=room).values_list("pk", flat=True)) ) return Q(pk__in=amended) def for_room(self, room: Union[int, Room]) -> "LessonEventQuerySet": """Get all lesson events for a certain room (including amends).""" return self.filter(self.for_room_q(room)).distinct() @staticmethod def for_course_q(course: Union[int, Course]) -> Q: """Get all lesson events for a certain course (including amends).""" from .models import LessonEvent amended = ( LessonEvent.objects.filter(amended_by__isnull=False, course=course) .values_list("amended_by__pk", flat=True) .union(LessonEvent.objects.filter(course=course).values_list("pk", flat=True)) ) return Q(pk__in=amended) def for_course(self, course: Union[int, Course]) -> "LessonEventQuerySet": """Get all lesson events for a certain course (including amends).""" return self.filter(self.for_course_q(course)).distinct() @staticmethod def for_person_q(person: Union[int, Person]) -> Q: """Get all lesson events for a certain person (as teacher/participant, including amends).""" from .models import LessonEvent amended = ( LessonEvent.objects.filter(amended_by__isnull=False, teachers=person) .values_list("amended_by__pk", flat=True) .union( LessonEvent.objects.filter( amended_by__isnull=False, groups__members=person ).values_list("amended_by__pk", flat=True) ) .union(LessonEvent.objects.filter(teachers=person).values_list("pk", flat=True)) .union(LessonEvent.objects.filter(groups__members=person).values_list("pk", flat=True)) ) return Q(pk__in=amended) def for_person(self, person: Union[int, Person]) -> "LessonEventQuerySet": """Get all lesson events for a certain person (as teacher/participant, including amends).""" return self.filter(self.for_person_q(person)).distinct() @staticmethod def related_to_person_q(person: Union[int, Person]) -> Q: """Get all lesson events a certain person is allowed to see. This includes all lesson events the person is assigned to as teacher/participant/group owner/parent group owner, including those amended. """ from .models import LessonEvent amended = ( LessonEvent.objects.filter(amended_by__isnull=False, teachers=person) .values_list("amended_by__pk", flat=True) .union( LessonEvent.objects.filter( amended_by__isnull=False, groups__members=person ).values_list("amended_by__pk", flat=True) ) .union( LessonEvent.objects.filter( amended_by__isnull=False, groups__owners=person ).values_list("amended_by__pk", flat=True) ) .union( LessonEvent.objects.filter( amended_by__isnull=False, groups__parent_groups__owners=person ).values_list("amended_by__pk", flat=True) ) .union(LessonEvent.objects.filter(teachers=person).values_list("pk", flat=True)) .union(LessonEvent.objects.filter(groups__members=person).values_list("pk", flat=True)) .union(LessonEvent.objects.filter(groups__owners=person).values_list("pk", flat=True)) .union( LessonEvent.objects.filter(groups__parent_groups__owners=person).values_list( "pk", flat=True ) ) ) return Q(pk__in=amended) def related_to_person(self, person: Union[int, Person]) -> "LessonEventQuerySet": """Get all lesson events a certain person is allowed to see. This includes all lesson events the person is assigned to as teacher/participant/group owner/parent group owner, including those amended. """ return self.filter(self.related_to_person_q(person)).distinct() @staticmethod def not_amended_q() -> Q: """Get all lesson events that are not amended.""" return Q(amended_by__isnull=True) def not_amended(self) -> "LessonEventQuerySet": """Get all lesson events that are not amended.""" return self.filter(self.not_amended_q()) @staticmethod def not_amending_q() -> Q: """Get all lesson events that are not amending other events.""" return Q(amends__isnull=True) def not_amending(self) -> "LessonEventQuerySet": """Get all lesson events that are not amending other events.""" return self.filter(self.not_amending_q()) @staticmethod def amending_q() -> Q: """Get all lesson events that are amending other events.""" return Q(amends__isnull=False) def amending(self) -> "LessonEventQuerySet": """Get all lesson events that are amending other events.""" return self.filter(self.amending_q()) @staticmethod def current_changes_q() -> Q: """Get all lesson events that are current changes.""" return Q(amends__isnull=False) | Q(current_change=True) def current_changes(self) -> "LessonEventQuerySet": """Get all lesson events that are current changes.""" return self.filter(self.current_changes_q()) class SupervisionEventQuerySet(LessonEventQuerySet): pass