From 94ef78b7decf6f3b600c7ea7eb4e021cb9e3239f Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Thu, 5 Aug 2021 17:01:12 +0200
Subject: [PATCH] Move get_substitutions_context_data to util namespace

---
 aleksis/apps/chronos/models.py               |  2 +-
 aleksis/apps/chronos/util/chronos_helpers.py | 88 ++++++++++++++++++-
 aleksis/apps/chronos/views.py                | 91 ++------------------
 3 files changed, 93 insertions(+), 88 deletions(-)

diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index f31f75c6..1f95bc54 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -1157,7 +1157,7 @@ class AutomaticPlan(LiveDocument):
 
     def get_context_data(self) -> Dict[str, Any]:
         """Get context data for generating the substitutions PDF."""
-        from aleksis.apps.chronos.views import get_substitutions_context_data  # noqa
+        from aleksis.apps.chronos.util.chronos_helpers import get_substitutions_context_data  # noqa
 
         context = get_substitutions_context_data(
             request=None,
diff --git a/aleksis/apps/chronos/util/chronos_helpers.py b/aleksis/apps/chronos/util/chronos_helpers.py
index f4bb7d2d..69d48627 100644
--- a/aleksis/apps/chronos/util/chronos_helpers.py
+++ b/aleksis/apps/chronos/util/chronos_helpers.py
@@ -3,14 +3,19 @@ from typing import TYPE_CHECKING, Optional
 from django.db.models import Count, Q
 from django.http import HttpRequest, HttpResponseNotFound
 from django.shortcuts import get_object_or_404
+from django.urls import reverse
+from django.utils import timezone
 
 from guardian.core import ObjectPermissionChecker
 
-from aleksis.core.models import Group, Person
+from aleksis.core.models import Announcement, Group, Person
+from aleksis.core.util.core_helpers import get_site_preferences
 from aleksis.core.util.predicates import check_global_permission
 
 from ..managers import TimetableType
-from ..models import LessonPeriod, LessonSubstitution, Room
+from ..models import Absence, LessonPeriod, LessonSubstitution, Room, TimePeriod
+from .build import build_substitutions_list
+from .js import date_unix
 
 if TYPE_CHECKING:
     from django.contrib.auth import get_user_model
@@ -130,3 +135,82 @@ def get_rooms(user: "User"):
         rooms = rooms.filter(Q(pk__in=wanted_rooms))
 
     return rooms
+
+
+def get_substitutions_context_data(
+    request: Optional[HttpRequest] = None,
+    year: Optional[int] = None,
+    month: Optional[int] = None,
+    day: Optional[int] = None,
+    is_print: bool = False,
+    number_of_days: Optional[int] = None,
+    show_header_box: Optional[bool] = None,
+):
+    """Get context data for the substitutions table."""
+    context = {}
+
+    if day:
+        wanted_day = timezone.datetime(year=year, month=month, day=day).date()
+        wanted_day = TimePeriod.get_next_relevant_day(wanted_day)
+    else:
+        wanted_day = TimePeriod.get_next_relevant_day(timezone.now().date(), timezone.now().time())
+
+    day_number = (
+        number_of_days or get_site_preferences()["chronos__substitutions_print_number_of_days"]
+    )
+    show_header_box = (
+        show_header_box
+        if show_header_box is not None
+        else get_site_preferences()["chronos__substitutions_show_header_box"]
+    )
+    day_contexts = {}
+
+    if is_print:
+        next_day = wanted_day
+        for i in range(day_number):
+            day_contexts[next_day] = {"day": next_day}
+            next_day = TimePeriod.get_next_relevant_day(next_day + timedelta(days=1))
+    else:
+        day_contexts = {wanted_day: {"day": wanted_day}}
+
+    for day in day_contexts:
+        subs = build_substitutions_list(day)
+        day_contexts[day]["substitutions"] = subs
+
+        day_contexts[day]["announcements"] = (
+            Announcement.for_timetables().on_date(day).filter(show_in_timetables=True)
+        )
+
+        if show_header_box:
+            subs = LessonSubstitution.objects.on_day(day).order_by(
+                "lesson_period__lesson__groups", "lesson_period__period"
+            )
+            absences = Absence.objects.on_day(day)
+            day_contexts[day]["absent_teachers"] = absences.absent_teachers()
+            day_contexts[day]["absent_groups"] = absences.absent_groups()
+            day_contexts[day]["affected_teachers"] = subs.affected_teachers()
+            affected_groups = subs.affected_groups()
+            if get_site_preferences()["chronos__affected_groups_parent_groups"]:
+                groups_with_parent_groups = affected_groups.filter(parent_groups__isnull=False)
+                groups_without_parent_groups = affected_groups.filter(parent_groups__isnull=True)
+                affected_groups = Group.objects.filter(
+                    Q(child_groups__pk__in=groups_with_parent_groups.values_list("pk", flat=True))
+                    | Q(pk__in=groups_without_parent_groups.values_list("pk", flat=True))
+                ).distinct()
+            day_contexts[day]["affected_groups"] = affected_groups
+
+    if not is_print:
+        context = day_contexts[wanted_day]
+        context["datepicker"] = {
+            "date": date_unix(wanted_day),
+            "dest": reverse("substitutions"),
+        }
+
+        context["url_prev"], context["url_next"] = TimePeriod.get_prev_next_by_day(
+            wanted_day, "substitutions_by_date"
+        )
+
+    else:
+        context["days"] = day_contexts
+
+    return context
diff --git a/aleksis/apps/chronos/views.py b/aleksis/apps/chronos/views.py
index 5c2dab29..158bc5b9 100644
--- a/aleksis/apps/chronos/views.py
+++ b/aleksis/apps/chronos/views.py
@@ -1,7 +1,6 @@
-from datetime import datetime, timedelta
+from datetime import datetime
 from typing import Optional
 
-from django.db.models import Q
 from django.http import HttpRequest, HttpResponse, HttpResponseNotFound
 from django.shortcuts import get_object_or_404, redirect, render
 from django.urls import reverse
@@ -12,21 +11,22 @@ from django.views.decorators.cache import never_cache
 from django_tables2 import RequestConfig
 from rules.contrib.views import permission_required
 
-from aleksis.core.models import Announcement, Group
+from aleksis.core.models import Announcement
 from aleksis.core.util import messages
-from aleksis.core.util.core_helpers import get_site_preferences, has_person
+from aleksis.core.util.core_helpers import has_person
 from aleksis.core.util.pdf import render_pdf
 
 from .forms import LessonSubstitutionForm
 from .managers import TimetableType
-from .models import Absence, Holiday, LessonPeriod, LessonSubstitution, TimePeriod
+from .models import Holiday, LessonPeriod, TimePeriod
 from .tables import LessonsTable
-from .util.build import build_substitutions_list, build_timetable, build_weekdays
+from .util.build import build_timetable, build_weekdays
 from .util.chronos_helpers import (
     get_classes,
     get_el_by_pk,
     get_rooms,
     get_substitution_by_id,
+    get_substitutions_context_data,
     get_teachers,
 )
 from .util.date import CalendarWeek, get_weeks_for_year
@@ -288,85 +288,6 @@ def delete_substitution(request: HttpRequest, id_: int, week: int) -> HttpRespon
     return redirect("lessons_day_by_date", year=date.year, month=date.month, day=date.day)
 
 
-def get_substitutions_context_data(
-    request: Optional[HttpRequest] = None,
-    year: Optional[int] = None,
-    month: Optional[int] = None,
-    day: Optional[int] = None,
-    is_print: bool = False,
-    number_of_days: Optional[int] = None,
-    show_header_box: Optional[bool] = None,
-):
-    """Get context data for the substitutions table."""
-    context = {}
-
-    if day:
-        wanted_day = timezone.datetime(year=year, month=month, day=day).date()
-        wanted_day = TimePeriod.get_next_relevant_day(wanted_day)
-    else:
-        wanted_day = TimePeriod.get_next_relevant_day(timezone.now().date(), datetime.now().time())
-
-    day_number = (
-        number_of_days or get_site_preferences()["chronos__substitutions_print_number_of_days"]
-    )
-    show_header_box = (
-        show_header_box
-        if show_header_box is not None
-        else get_site_preferences()["chronos__substitutions_show_header_box"]
-    )
-    day_contexts = {}
-
-    if is_print:
-        next_day = wanted_day
-        for i in range(day_number):
-            day_contexts[next_day] = {"day": next_day}
-            next_day = TimePeriod.get_next_relevant_day(next_day + timedelta(days=1))
-    else:
-        day_contexts = {wanted_day: {"day": wanted_day}}
-
-    for day in day_contexts:
-        subs = build_substitutions_list(day)
-        day_contexts[day]["substitutions"] = subs
-
-        day_contexts[day]["announcements"] = (
-            Announcement.for_timetables().on_date(day).filter(show_in_timetables=True)
-        )
-
-        if show_header_box:
-            subs = LessonSubstitution.objects.on_day(day).order_by(
-                "lesson_period__lesson__groups", "lesson_period__period"
-            )
-            absences = Absence.objects.on_day(day)
-            day_contexts[day]["absent_teachers"] = absences.absent_teachers()
-            day_contexts[day]["absent_groups"] = absences.absent_groups()
-            day_contexts[day]["affected_teachers"] = subs.affected_teachers()
-            affected_groups = subs.affected_groups()
-            if get_site_preferences()["chronos__affected_groups_parent_groups"]:
-                groups_with_parent_groups = affected_groups.filter(parent_groups__isnull=False)
-                groups_without_parent_groups = affected_groups.filter(parent_groups__isnull=True)
-                affected_groups = Group.objects.filter(
-                    Q(child_groups__pk__in=groups_with_parent_groups.values_list("pk", flat=True))
-                    | Q(pk__in=groups_without_parent_groups.values_list("pk", flat=True))
-                ).distinct()
-            day_contexts[day]["affected_groups"] = affected_groups
-
-    if not is_print:
-        context = day_contexts[wanted_day]
-        context["datepicker"] = {
-            "date": date_unix(wanted_day),
-            "dest": reverse("substitutions"),
-        }
-
-        context["url_prev"], context["url_next"] = TimePeriod.get_prev_next_by_day(
-            wanted_day, "substitutions_by_date"
-        )
-
-    else:
-        context["days"] = day_contexts
-
-    return context
-
-
 @permission_required("chronos.view_substitutions_rule")
 def substitutions(
     request: HttpRequest,
-- 
GitLab