From df893f6f46c6d4d983b5eeea022dfecdfb797d98 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Thu, 24 Sep 2020 16:22:09 +0200
Subject: [PATCH] Show also groups which have child groups with lessons in my
 groups and select form

In order to do that, refactor the queries to model extensions
---
 aleksis/apps/alsijil/forms.py            |  6 +----
 aleksis/apps/alsijil/model_extensions.py | 28 +++++++++++++++++++++++-
 aleksis/apps/alsijil/views.py            | 13 ++---------
 3 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/aleksis/apps/alsijil/forms.py b/aleksis/apps/alsijil/forms.py
index 7b74944b1..3632661e3 100644
--- a/aleksis/apps/alsijil/forms.py
+++ b/aleksis/apps/alsijil/forms.py
@@ -79,11 +79,7 @@ class SelectForm(forms.Form):
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        self.fields["group"].queryset = (
-            Group.objects.for_current_school_term_or_all()
-            .annotate(lessons_count=Count("lessons"))
-            .filter(lessons_count__gt=0)
-        )
+        self.fields["group"].queryset = Group.get_groups_with_lessons()
 
 
 PersonalNoteFormSet = forms.modelformset_factory(
diff --git a/aleksis/apps/alsijil/model_extensions.py b/aleksis/apps/alsijil/model_extensions.py
index 0fbfd9575..847d815c7 100644
--- a/aleksis/apps/alsijil/model_extensions.py
+++ b/aleksis/apps/alsijil/model_extensions.py
@@ -1,7 +1,8 @@
 from datetime import date
 from typing import Dict, Optional, Union
 
-from django.db.models import Exists, OuterRef, QuerySet
+from django.db.models import Exists, OuterRef, Q, QuerySet
+from django.db.models.aggregates import Count
 
 import reversion
 from calendarweek import CalendarWeek
@@ -204,3 +205,28 @@ def get_extra_marks(
             stats[extra_mark] = qs
 
     return stats
+
+
+@Group.class_method
+def get_groups_with_lessons(cls: Group):
+    """Get all groups which have related lessons or child groups with related lessons."""
+    group_pks = (
+        cls.objects.for_current_school_term_or_all()
+        .annotate(lessons_count=Count("lessons"))
+        .filter(lessons_count__gt=0)
+        .values_list("pk", flat=True)
+    )
+    groups = cls.objects.filter(
+        Q(child_groups__pk__in=group_pks) | Q(pk__in=group_pks)
+    ).distinct()
+
+    return groups
+
+
+@Person.method
+def get_owner_groups_with_lessons(self: Person):
+    """Get all groups the person is an owner of and which have related lessons.
+
+    Groups which have child groups with related lessons are also included.
+    """
+    return Group.get_groups_with_lessons().filter(owners=self)
diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py
index b6b76985e..0919d0ed4 100644
--- a/aleksis/apps/alsijil/views.py
+++ b/aleksis/apps/alsijil/views.py
@@ -463,11 +463,7 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse:
 
 def my_students(request: HttpRequest) -> HttpResponse:
     context = {}
-    relevant_groups = (
-        Group.objects.for_current_school_term_or_all()
-        .annotate(lessons_count=Count("lessons"))
-        .filter(lessons_count__gt=0, owners=request.user.person)
-    )
+    relevant_groups = request.user.person.get_owner_groups_with_lessons()
     persons = Person.objects.filter(member_of__in=relevant_groups)
     context["persons"] = persons
     return render(request, "alsijil/class_register/persons.html", context)
@@ -475,12 +471,7 @@ def my_students(request: HttpRequest) -> HttpResponse:
 
 def my_groups(request: HttpRequest) -> HttpResponse:
     context = {}
-    groups = (
-        Group.objects.for_current_school_term_or_all()
-        .annotate(lessons_count=Count("lessons"))
-        .filter(lessons_count__gt=0, owners=request.user.person)
-    )
-    context["groups"] = groups
+    context["groups"] = request.user.person.get_owner_groups_with_lessons()
     return render(request, "alsijil/class_register/groups.html", context)
 
 
-- 
GitLab