From 8b0fbc1675f0915f52255097222e212aeaf91eec Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Tue, 9 Apr 2024 17:58:08 +0200
Subject: [PATCH] Add preference for selecting group types to be shown in
 timetables

---
 aleksis/apps/chronos/preferences.py          | 16 ++++++++++++
 aleksis/apps/chronos/schema/__init__.py      |  7 +++---
 aleksis/apps/chronos/util/chronos_helpers.py | 26 ++++++++++++--------
 aleksis/apps/chronos/util/predicates.py      |  4 +--
 4 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/aleksis/apps/chronos/preferences.py b/aleksis/apps/chronos/preferences.py
index d319001c..e75062cc 100644
--- a/aleksis/apps/chronos/preferences.py
+++ b/aleksis/apps/chronos/preferences.py
@@ -7,10 +7,12 @@ from dynamic_preferences.preferences import Section
 from dynamic_preferences.types import (
     BooleanPreference,
     IntegerPreference,
+    ModelMultipleChoicePreference,
     StringPreference,
     TimePreference,
 )
 
+from aleksis.core.models import GroupType
 from aleksis.core.registries import person_preferences_registry, site_preferences_registry
 
 chronos = Section("chronos", verbose_name=_("Timetables"))
@@ -115,6 +117,20 @@ class SendNotificationsPerson(BooleanPreference):
     verbose_name = _("Send notifications for current timetable changes")
 
 
+@site_preferences_registry.register
+class GroupTypesTimetables(ModelMultipleChoicePreference):
+    section = chronos
+    name = "group_types_timetables"
+    required = False
+    default = []
+    model = GroupType
+    verbose_name = _("Group types to show in timetables")
+    help_text = _("If you leave it empty, all groups will be shown.")
+
+    def get_queryset(self):
+        return GroupType.objects.managed_and_unmanaged()
+
+
 @site_preferences_registry.register
 class LessonEventFeedColor(StringPreference):
     """Color for the lesson calendar feed."""
diff --git a/aleksis/apps/chronos/schema/__init__.py b/aleksis/apps/chronos/schema/__init__.py
index a0682ef5..7ce24c5f 100644
--- a/aleksis/apps/chronos/schema/__init__.py
+++ b/aleksis/apps/chronos/schema/__init__.py
@@ -11,7 +11,7 @@ from graphene_django_cud.mutations import (
 from aleksis.core.models import Group, Person, Room
 
 from ..models import LessonEvent
-from ..util.chronos_helpers import get_classes, get_rooms, get_teachers
+from ..util.chronos_helpers import get_groups, get_rooms, get_teachers
 
 
 class TimetablePersonType(DjangoObjectType):
@@ -149,14 +149,14 @@ class Query(graphene.ObjectType):
         return get_teachers(info.context.user)
 
     def resolve_timetable_groups(self, info, **kwargs):
-        return get_classes(info.context.user)
+        return get_groups(info.context.user)
 
     def resolve_timetable_rooms(self, info, **kwargs):
         return get_rooms(info.context.user)
 
     def resolve_available_timetables(self, info, **kwargs):
         all_timetables = []
-        for group in get_classes(info.context.user):
+        for group in get_groups(info.context.user):
             all_timetables.append(
                 TimetableObjectType(
                     id=group.id,
@@ -167,7 +167,6 @@ class Query(graphene.ObjectType):
             )
 
         for teacher in get_teachers(info.context.user):
-            print(teacher.full_name)
             all_timetables.append(
                 TimetableObjectType(
                     id=teacher.id,
diff --git a/aleksis/apps/chronos/util/chronos_helpers.py b/aleksis/apps/chronos/util/chronos_helpers.py
index 1f299424..e5d5fe9c 100644
--- a/aleksis/apps/chronos/util/chronos_helpers.py
+++ b/aleksis/apps/chronos/util/chronos_helpers.py
@@ -96,38 +96,44 @@ def get_teachers(user: "User"):
     return teachers
 
 
-def get_classes(user: "User"):
-    """Get the classes whose timetables are allowed to be seen by current user."""
+def get_groups(user: "User"):
+    """Get the groups whose timetables are allowed to be seen by current user."""
     checker = ObjectPermissionChecker(user)
 
-    classes = (
+    groups = (
         Group.objects.for_current_school_term_or_all()
         .annotate(
             lessons_count=Count("lesson_events"),
             child_lessons_count=Count("child_groups__lesson_events"),
         )
         .filter(Q(lessons_count__gt=0) | Q(child_lessons_count__gt=0))
-        .order_by("short_name", "name")
     )
 
+    group_types = get_site_preferences()["chronos__group_types_timetables"]
+
+    if group_types:
+        groups = groups.filter(group_type__in=group_types)
+
+    groups = groups.order_by("short_name", "name")
+
     if not check_global_permission(user, "chronos.view_all_group_timetables"):
-        checker.prefetch_perms(classes)
+        checker.prefetch_perms(groups)
 
         wanted_classes = set()
 
-        for _class in classes:
+        for _class in groups:
             if checker.has_perm("core.view_group_timetable", _class):
                 wanted_classes.add(_class.pk)
 
-        classes = classes.filter(
+        groups = groups.filter(
             Q(pk__in=wanted_classes) | Q(members=user.person) | Q(owners=user.person)
         )
         if user.person.primary_group:
-            classes = classes.filter(Q(pk=user.person.primary_group.pk))
+            groups = groups.filter(Q(pk=user.person.primary_group.pk))
 
-    classes = classes.distinct()
+    groups = groups.distinct()
 
-    return classes
+    return groups
 
 
 def get_rooms(user: "User"):
diff --git a/aleksis/apps/chronos/util/predicates.py b/aleksis/apps/chronos/util/predicates.py
index d99ac20a..7657ea96 100644
--- a/aleksis/apps/chronos/util/predicates.py
+++ b/aleksis/apps/chronos/util/predicates.py
@@ -6,7 +6,7 @@ from rules import predicate
 from aleksis.core.models import Group, Person, Room
 from aleksis.core.util.predicates import has_global_perm, has_object_perm
 
-from .chronos_helpers import get_classes, get_rooms, get_teachers
+from .chronos_helpers import get_groups, get_rooms, get_teachers
 
 
 @predicate
@@ -75,4 +75,4 @@ def has_room_timetable_perm(user: User, obj: Room) -> bool:
 @predicate
 def has_any_timetable_object(user: User) -> bool:
     """Predicate which checks whether there are any timetables the user is allowed to access."""
-    return get_classes(user).exists() or get_rooms(user).exists() or get_teachers(user).exists()
+    return get_groups(user).exists() or get_rooms(user).exists() or get_teachers(user).exists()
-- 
GitLab