Skip to content
Snippets Groups Projects
model_extensions.py 4.91 KiB
Newer Older
Jonathan Weth's avatar
Jonathan Weth committed
from datetime import date
from django.utils.translation import gettext_lazy as _
from aleksis.core.models import Announcement, Group, Person
from aleksis.core.util.core_helpers import get_site_preferences
from .managers import TimetableType
from .models import Lesson, LessonPeriod
from .util.change_tracker import timetable_data_changed
from .util.notifications import send_notifications_for_object
Jonathan Weth's avatar
Jonathan Weth committed
@Person.property_
Tom Teichler's avatar
Tom Teichler committed
    """Check if the user has lessons as a teacher."""
    return self.lesson_periods_as_teacher.exists()
Jonathan Weth's avatar
Jonathan Weth committed
@Person.property_
def timetable_type(self) -> Optional[TimetableType]:
Tom Teichler's avatar
Tom Teichler committed
    """Return which type of timetable this user has."""
        return TimetableType.TEACHER
        return TimetableType.GROUP
Jonathan Weth's avatar
Jonathan Weth committed
@Person.property_
def timetable_object(self) -> Optional[Union[Group, Person]]:
Tom Teichler's avatar
Tom Teichler committed
    """Return the object which has the user's timetable."""
    if type_ == TimetableType.TEACHER:
    elif type_ == TimetableType.GROUP:
Jonathan Weth's avatar
Jonathan Weth committed
@Person.property_
    """Return a `QuerySet` containing all `Lesson`s this person participates in (as student).
    .. note:: Only available when AlekSIS-App-Chronos is installed.

    :Date: 2019-11-07
    :Authors:
        - Dominik George <dominik.george@teckids.org>
    """
Nik | Klampfradler's avatar
Nik | Klampfradler committed
    return Lesson.objects.filter(groups__members=self)
Jonathan Weth's avatar
Jonathan Weth committed
@Person.property_
def lesson_periods_as_participant(self):
    """Return a `QuerySet` containing all `LessonPeriod`s this person participates in (as student).
    .. note:: Only available when AlekSIS-App-Chronos is installed.

    :Date: 2019-11-07
    :Authors:
        - Dominik George <dominik.george@teckids.org>
    """
    return LessonPeriod.objects.filter(lesson__groups__members=self)


Jonathan Weth's avatar
Jonathan Weth committed
@Person.property_
def lesson_periods_as_teacher(self):
    """Return a `QuerySet` containing all `Lesson`s this person gives (as teacher).
    .. note:: Only available when AlekSIS-App-Chronos is installed.

    :Date: 2019-11-07
    :Authors:
        - Dominik George <dominik.george@teckids.org>
    """
    return LessonPeriod.objects.filter(lesson__teachers=self)
def lessons_on_day(self, day: date):
    """Get all lessons of this person (either as participant or teacher) on the given day."""
    qs = LessonPeriod.objects.on_day(day).filter_from_person(self)
    if qs:
        # This is a union queryset, so order by must be after the union.
        return qs.order_by("period__period")
    return None
def _adjacent_lesson(
    self, lesson_period: "LessonPeriod", day: date, offset: int = 1
) -> Union["LessonPeriod", None]:
    """Get next/previous lesson of the person (either as participant or teacher) on the same day."""
    daily_lessons = self.lessons_on_day(day)

    if not daily_lessons:
        return None

    ids = list(daily_lessons.values_list("id", flat=True))

    # Check if the lesson period is one of the person's lesson periods on this day
    # and return None if it's not so
    if lesson_period.pk not in ids:
        return None

    if (offset > 0 and index + offset < len(ids)) or (offset < 0 and index >= -offset):
        return daily_lessons[index + offset]
Tom Teichler's avatar
Tom Teichler committed
def next_lesson(self, lesson_period: "LessonPeriod", day: date) -> Union["LessonPeriod", None]:
    """Get next lesson of the person (either as participant or teacher) on the same day."""
    return self._adjacent_lesson(lesson_period, day)
Tom Teichler's avatar
Tom Teichler committed
def previous_lesson(self, lesson_period: "LessonPeriod", day: date) -> Union["LessonPeriod", None]:
    """Get previous lesson of the person (either as participant or teacher) on the same day."""
    return self._adjacent_lesson(lesson_period, day, offset=-1)
Jonathan Weth's avatar
Jonathan Weth committed
    """Return all announcements that should be shown in timetable views."""
    return cls.objects.all()


Announcement.class_method(for_timetables)

# Dynamically add extra permissions to Group and Person models in core
# Note: requires migrate afterwards
Group.add_permission(
    "view_group_timetable",
    _("Can view group timetable"),
Group.add_permission(
    "manage_group_substitutions",
    _("Can manage group substitutions"),
)
    "view_person_timetable",
    _("Can view person timetable"),


@receiver(timetable_data_changed)
def send_notifications(sender: Revision, **kwargs):
    """Send notifications to users about the changes."""
    if not get_site_preferences()["chronos__send_notifications_site"]:
    for change in sender.changes.values():
        if change.deleted:
            continue

        send_notifications_for_object(change.instance)