From d924fb55b19d7c673deeec308e58b4e8f6515f6d Mon Sep 17 00:00:00 2001
From: Dominik George <nik@naturalnet.de>
Date: Sun, 26 Jan 2020 17:16:41 +0100
Subject: [PATCH] Move min_max helpers to TimePeriod as properties

Closes #59.
---
 aleksis/apps/chronos/models.py         | 29 ++++++++++++++++++++++++--
 aleksis/apps/chronos/util/min_max.py   | 19 -----------------
 aleksis/apps/chronos/util/prev_next.py | 16 +++++++-------
 aleksis/apps/chronos/views.py          | 14 ++++---------
 4 files changed, 39 insertions(+), 39 deletions(-)
 delete mode 100644 aleksis/apps/chronos/util/min_max.py

diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index 293b62ba..461a8ad2 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -1,13 +1,14 @@
 from __future__ import annotations
 
-from datetime import date, datetime, timedelta
+from datetime import date, datetime, timedelta, time
 from typing import Dict, Optional, Tuple, Union
 
 from django.core import validators
 from django.core.exceptions import ValidationError
 from django.db import models
-from django.db.models import F, Q
+from django.db.models import F, Max, Min, Q
 from django.http.request import QueryDict
+from django.utils.decorators import classproperty
 from django.utils.translation import ugettext_lazy as _
 
 from calendarweek.django import CalendarWeek, i18n_day_names_lazy, i18n_day_abbrs_lazy
@@ -244,6 +245,30 @@ class TimePeriod(models.Model):
 
         return wanted_week[self.weekday]
 
+    @classproperty
+    def period_min(cls) -> int:
+        return cls.objects.aggregate(Min("period")).get("period__min", 1)
+
+    @classproperty
+    def period_max(cls) -> int:
+        return cls.objects.aggregate(Max("period")).get("period__max", 7)
+
+    @classproperty
+    def time_min(cls) -> Optional[time]:
+        return cls.objects.aggregate(Min("time_start")).get("time_start__min", None)
+
+    @classproperty
+    def time_max(cls) -> Optional[time]:
+        return cls.objects.aggregate(Max("time_start")).get("time_start__max", None)
+
+    @classproperty
+    def weekday_min(cls) -> int:
+        return cls.objects.aggregate(Min("weekday")).get("weekday__min", 0)
+
+    @classproperty
+    def weekday_max(cls) -> int:
+        return cls.objects.aggregate(Max("weekday")).get("weekday__max", 6)
+
     class Meta:
         unique_together = [["weekday", "period"]]
         ordering = ["weekday", "period"]
diff --git a/aleksis/apps/chronos/util/min_max.py b/aleksis/apps/chronos/util/min_max.py
deleted file mode 100644
index 4d5dd421..00000000
--- a/aleksis/apps/chronos/util/min_max.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.db.models import Min, Max
-
-from aleksis.apps.chronos.models import TimePeriod
-
-# Determine overall first and last day and period
-min_max = TimePeriod.objects.aggregate(
-    Min("period"), Max("period"), Min("weekday"), Max("weekday"), Min("time_start"), Max("time_end")
-)
-
-period_min = min_max.get("period__min", 1)
-period_max = min_max.get("period__max", 7)
-
-time_min = min_max.get("time_start__min", None)
-time_max = min_max.get("time_end__max", None)
-
-weekday_min_ = min_max.get("weekday__min", 0)
-weekday_max = min_max.get("weekday__max", 6)
-
-
diff --git a/aleksis/apps/chronos/util/prev_next.py b/aleksis/apps/chronos/util/prev_next.py
index c0a844dc..4f954c30 100644
--- a/aleksis/apps/chronos/util/prev_next.py
+++ b/aleksis/apps/chronos/util/prev_next.py
@@ -5,7 +5,7 @@ from calendarweek import CalendarWeek
 from django.urls import reverse
 from django.utils import timezone
 
-from aleksis.apps.chronos.util.min_max import weekday_min_, weekday_max, time_max
+from ..models import TimePeriod
 
 
 def get_next_relevant_day(day: Optional[date] = None, time: Optional[time] = None, prev: bool = False) -> date:
@@ -15,23 +15,23 @@ def get_next_relevant_day(day: Optional[date] = None, time: Optional[time] = Non
         day = timezone.now().date()
 
     if time is not None and not prev:
-        if time > time_max:
+        if time > TimePeriod.time_max:
             day += timedelta(days=1)
 
     cw = CalendarWeek.from_date(day)
 
-    if day.weekday() > weekday_max:
+    if day.weekday() > TimePeriod.weekday_max:
         if prev:
-            day = cw[weekday_max]
+            day = cw[TimePeriod.weekday_max]
         else:
             cw += 1
-            day = cw[weekday_min_]
-    elif day.weekday() < weekday_min_:
+            day = cw[TimePeriod.weekday_min]
+    elif day.weekday() < TimePeriod.weekday_min:
         if prev:
             cw -= 1
-            day = cw[weekday_max]
+            day = cw[TimePeriod.weekday_max]
         else:
-            day = cw[weekday_min_]
+            day = cw[TimePeriod.weekday_min]
 
     return day
 
diff --git a/aleksis/apps/chronos/views.py b/aleksis/apps/chronos/views.py
index 90cac912..66ddde4a 100644
--- a/aleksis/apps/chronos/views.py
+++ b/aleksis/apps/chronos/views.py
@@ -18,12 +18,6 @@ from .forms import LessonSubstitutionForm
 from .models import LessonPeriod, LessonSubstitution, TimePeriod, Room
 from .tables import LessonsTable
 from .util.js import date_unix
-from .util.min_max import (
-    period_min,
-    period_max,
-    weekday_min_,
-    weekday_max
-)
 from .util.prev_next import get_next_relevant_day, get_prev_next_by_day
 from .util.weeks import CalendarWeek, get_weeks_for_year
 from aleksis.core.util.core_helpers import has_person
@@ -158,13 +152,13 @@ def timetable(
             ] = [lesson_period]
 
     # Fill in empty lessons
-    for period_num in range(period_min, period_max + 1):
+    for period_num in range(TimePeriod.period_min, TimePeriod.period_max + 1):
         # Fill in empty weekdays
         if period_num not in per_period.keys():
             per_period[period_num] = {}
 
         # Fill in empty lessons on this workday
-        for weekday_num in range(weekday_min_, weekday_max + 1):
+        for weekday_num in range(TimePeriod.weekday_min, TimePeriod.weekday_max + 1):
             if weekday_num not in per_period[period_num].keys():
                 per_period[period_num][weekday_num] = []
 
@@ -174,10 +168,10 @@ def timetable(
     context["lesson_periods"] = OrderedDict(sorted(per_period.items()))
     context["periods"] = TimePeriod.get_times_dict()
     context["weekdays"] = dict(
-        TimePeriod.WEEKDAY_CHOICES[weekday_min_ : weekday_max + 1]
+        TimePeriod.WEEKDAY_CHOICES[TimePeriod.weekday_min : TimePeriod.weekday_max + 1]
     )
     context["weekdays_short"] = dict(
-        TimePeriod.WEEKDAY_CHOICES_SHORT[weekday_min_ : weekday_max + 1]
+        TimePeriod.WEEKDAY_CHOICES_SHORT[TimePeriod.weekday_min : TimePeriod.weekday_max + 1]
     )
     context["weeks"] = get_weeks_for_year(year=wanted_week.year)
     context["week"] = wanted_week
-- 
GitLab