Skip to content
Snippets Groups Projects
build.py 9.03 KiB
Newer Older
from collections import OrderedDict

from calendarweek import CalendarWeek
LessonPeriod = apps.get_model("chronos", "LessonPeriod")
TimePeriod = apps.get_model("chronos", "TimePeriod")
Break = apps.get_model("chronos", "Break")
Supervision = apps.get_model("chronos", "Supervision")
LessonSubstitution = apps.get_model("chronos", "LessonSubstitution")
SupervisionSubstitution = apps.get_model("chronos", "SupervisionSubstitution")
Event = apps.get_model("chronos", "Event")

def build_timetable(
    type_: str, obj: Union[int, Person], date_ref: Union[CalendarWeek, date]
):
    if not isinstance(obj, int):
        pk = obj.pk
    else:
        pk = obj

    is_person = False
    if type_ == "person":
        is_person = True
        type_ = obj.timetable_type

    if is_person:
        lesson_periods = LessonPeriod.objects.daily_lessons_for_person(obj, date_ref)
    else:
        lesson_periods = LessonPeriod.objects.in_week(date_ref).filter_from_type(
            type_, obj
        )

    # Sort lesson periods in a dict
    lesson_periods_per_period = {}
    for lesson_period in lesson_periods:
        period = lesson_period.period.period
        weekday = lesson_period.period.weekday

        if period not in lesson_periods_per_period:
            lesson_periods_per_period[period] = [] if is_person else {}
        if not is_person and weekday not in lesson_periods_per_period[period]:
            lesson_periods_per_period[period][weekday] = []

        if is_person:
            lesson_periods_per_period[period].append(lesson_period)
        else:
            lesson_periods_per_period[period][weekday].append(lesson_period)
    # Get events
    if is_person:
        events = Event.objects.on_day(date_ref).filter_from_person(obj)
    else:
        events = Event.objects.in_week(date_ref).filter_from_type(type_, obj)

    # Sort events in a dict
    events_per_period = {}
    for event in events:
        if not is_person and event.date_start < date_ref[TimePeriod.weekday_min]:
            # If start date not in current week, set weekday and period to min
            weekday_from = TimePeriod.weekday_min
            period_from_first_weekday = TimePeriod.period_min
        else:
            weekday_from = event.date_start.weekday()
            period_from_first_weekday = event.period_from.period

        if not is_person and event.date_end > date_ref[TimePeriod.weekday_max]:
            # If end date not in current week, set weekday and period to max
            weekday_to = TimePeriod.weekday_max
            period_to_last_weekday = TimePeriod.period_max
        else:
            weekday_to = event.date_end.weekday()
            period_to_last_weekday = event.period_to.period

        for weekday in range(weekday_from, weekday_to + 1):
            if is_person and weekday != date_ref.weekday():
                # If daily timetable for person, skip other weekdays
                continue

            if weekday == weekday_from:
                # If start day, use start period
                period_from = period_from_first_weekday
            else:
                # If not start day, use min period
                period_from = TimePeriod.period_min

            if weekday == weekday_to:
                # If end day, use end period
                period_to = period_to_last_weekday
            else:
                # If not end day, use max period
                period_to = TimePeriod.period_max

            for period in range(period_from, period_to +1):
                if period not in events_per_period:
                    events_per_period[period] = [] if is_person else {}

                if not is_person and weekday not in events_per_period[period]:
                    events_per_period[period][weekday] = []

                if is_person:
                    events_per_period[period].append(event)
                else:
                    events_per_period[period][weekday].append(event)

    if type_ == "teacher":
        # Get matching supervisions
        if is_person:
            week = CalendarWeek.from_date(date_ref)
        else:
            week = date_ref
        supervisions = Supervision.objects.all().annotate_week(week).filter_by_teacher(obj)

        if is_person:
            supervisions.filter_by_weekday(date_ref.weekday())

        supervisions_per_period_after = {}
        for supervision in supervisions:
            weekday = supervision.break_item.weekday
            period_after_break = supervision.break_item.before_period_number
            print(supervision, weekday, period_after_break)

            if period_after_break not in needed_breaks:
                needed_breaks.append(period_after_break)

            if (
                not is_person
                and period_after_break not in supervisions_per_period_after
            ):
                supervisions_per_period_after[period_after_break] = {}

            if is_person:
                supervisions_per_period_after[period_after_break] = supervision
            else:
                supervisions_per_period_after[period_after_break][weekday] = supervision
    # Get ordered breaks
    breaks = OrderedDict(sorted(Break.get_breaks_dict().items()))

    rows = []
    for period, break_ in breaks.items():  # period is period after break
        # Break
        if type_ == "teacher" and period in needed_breaks:
            row = {
                "type": "break",
                "after_period": break_.after_period_number,
                "before_period": break_.before_period_number,
                "time_start": break_.time_start,
                "time_end": break_.time_end,
            }

            if not is_person:
                cols = []

                for weekday in range(
                    TimePeriod.weekday_min, TimePeriod.weekday_max + 1
                ):
                    col = None
                    if period in supervisions_per_period_after:
                        if weekday in supervisions_per_period_after[period]:
                            col = supervisions_per_period_after[period][weekday]
                    cols.append(col)
                col = None
                if period in supervisions_per_period_after:
                    col = supervisions_per_period_after[period]
                row["col"] = col
        if period <= TimePeriod.period_max:
            row = {
                "type": "period",
                "period": period,
                "time_start": break_.before_period.time_start,
                "time_end": break_.before_period.time_end,
            }

            if not is_person:
                cols = []
                for weekday in range(
                    TimePeriod.weekday_min, TimePeriod.weekday_max + 1
                ):
                    col = []

                    # Add lesson periods
                    if period in lesson_periods_per_period:
                        if weekday in lesson_periods_per_period[period]:
                            col += lesson_periods_per_period[period][weekday]

                    # Add events
                    if period in events_per_period:
                        if weekday in events_per_period[period]:
                            col += events_per_period[period][weekday]

                # Add lesson periods
                if period in lesson_periods_per_period:
                # Add events
                if period in events_per_period:
                    col += events_per_period[period]



def build_substitutions_list(wanted_day: date) -> List[dict]:
    rows = []

    subs = LessonSubstitution.objects.on_day(wanted_day).order_by(
        "lesson_period__lesson__groups", "lesson_period__period"
    )

    for sub in subs:
        if not sub.cancelled_for_teachers:
            sort_a = sub.lesson_period.lesson.group_names
        else:
            sort_a = "Z.{}".format(sub.lesson_period.lesson.teacher_names)

        row = {
            "type": "substitution",
            "sort_a": sort_a,
            "sort_b": "{}".format(sub.lesson_period.period.period),
            "el": sub,
        }

        rows.append(row)

    # Get supervision substitutions
    super_subs = SupervisionSubstitution.objects.filter(date=wanted_day)

    for super_sub in super_subs:
        row = {
            "type": "supervision_substitution",
            "sort_a": "Z.{}".format(super_sub.teacher),
            "sort_b": "{}".format(super_sub.supervision.break_item.after_period_number),
            "el": super_sub
        }
        rows.append(row)

    # Sort all items
    def sorter(row: dict):
        return row["sort_a"] + row["sort_b"]

    rows.sort(key=sorter)