Skip to content
Snippets Groups Projects
chronos_helpers.py 3.98 KiB
Newer Older
from datetime import date, datetime, timedelta
Hangzhi Yu's avatar
Hangzhi Yu committed
from typing import TYPE_CHECKING, Optional
Hangzhi Yu's avatar
Hangzhi Yu committed

from django.db.models import Q
Hangzhi Yu's avatar
Hangzhi Yu committed

from guardian.shortcuts import get_objects_for_user
from aleksis.core.models import Announcement, Group, Person, Room
from aleksis.core.util.core_helpers import get_site_preferences
from aleksis.core.util.predicates import check_global_permission
Tom Teichler's avatar
Tom Teichler committed

from .build import build_substitutions_list
Hangzhi Yu's avatar
Hangzhi Yu committed

if TYPE_CHECKING:
    from django.contrib.auth import get_user_model

    User = get_user_model()  # noqa

Hangzhi Yu's avatar
Hangzhi Yu committed

def get_teachers(user: "User"):
Hangzhi Yu's avatar
Hangzhi Yu committed
    """Get the teachers whose timetables are allowed to be seen by current user."""
    teachers = Person.objects.all().order_by("short_name", "last_name")

    if not check_global_permission(user, "chronos.view_all_person_timetables"):
        teachers.filter(
            Q(pk=user.person.pk)
            | Q(pk__in=get_objects_for_user(user, "core.view_person_timetable", teachers))
        )
    teachers = teachers.distinct()

def get_groups(user: "User"):
    """Get the groups whose timetables are allowed to be seen by current user."""
    groups = Group.objects.for_current_school_term_or_all()
    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"):
        if user.person.primary_group:
            return groups.filter(pk=user.person.primary_group.pk)
        wanted_groups = get_objects_for_user(user, "core.view_group_timetable", groups)
            Q(pk__in=wanted_groups) | Q(members=user.person) | Q(owners=user.person)
def get_rooms(user: "User"):
Hangzhi Yu's avatar
Hangzhi Yu committed
    """Get the rooms whose timetables are allowed to be seen by current user."""
    rooms = Room.objects.all().order_by("short_name", "name")

    if not check_global_permission(user, "chronos.view_all_room_timetables"):
        rooms = get_objects_for_user(user, "core.view_room_timetable", rooms)
    rooms = rooms.distinct()



def get_substitutions_context_data(
    wanted_day: date,
    number_of_days: Optional[int] = None,
    show_header_box: Optional[bool] = None,
):
    """Get context data for the substitutions table."""
    context = {}

    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 = {}

    day = get_next_relevant_day(wanted_day)
    for _i in range(day_number):
        day_contexts[day] = {"day": day}
        subs, affected_teachers, affected_groups = build_substitutions_list(day)
        day_contexts[day]["substitutions"] = subs

        day_contexts[day]["announcements"] = Announcement.objects.on_date(day)
            day_contexts[day]["affected_teachers"] = sorted(
                affected_teachers, key=lambda t: t.short_name or t.full_name
            )
            day_contexts[day]["affected_groups"] = affected_groups
        day = get_next_relevant_day(day + timedelta(days=1))
    context["days"] = day_contexts


def get_next_relevant_day(current: datetime | date) -> date:
    """Get next relevant day for substitution plans."""
    relevant_days = get_site_preferences()["chronos__substitutions_relevant_days"]
    change_time = get_site_preferences()["chronos__substitutions_day_change_time"]

    if isinstance(current, datetime):
        current_day = current.date()
        if current.time() > change_time:
            current_day += timedelta(days=1)
    else:
        current_day = current

    while str(current_day.weekday()) not in relevant_days:
        current_day += timedelta(days=1)

    return current_day