From bcc7f3023b7a6602f8c3313702d98507a1aa5cf2 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Sun, 5 Apr 2020 12:47:44 +0200
Subject: [PATCH] Add basic import for substitutions

---
 aleksis/apps/untis/model_extensions.py        |   6 +
 .../util/mysql/importers/substitutions.py     | 158 ++++++++++++++++++
 aleksis/apps/untis/util/mysql/main.py         |   4 +
 3 files changed, 168 insertions(+)
 create mode 100644 aleksis/apps/untis/util/mysql/importers/substitutions.py

diff --git a/aleksis/apps/untis/model_extensions.py b/aleksis/apps/untis/model_extensions.py
index 0ea5b93..52e9d0f 100644
--- a/aleksis/apps/untis/model_extensions.py
+++ b/aleksis/apps/untis/model_extensions.py
@@ -62,3 +62,9 @@ chronos_models.LessonPeriod.field(
         verbose_name=_("Number of lesson element in UNTIS"), null=True, blank=True
     )
 )
+chronos_models.LessonSubstitution.field(
+    import_ref_untis=IntegerField(
+        verbose_name=_("UNTIS import reference"), null=True, blank=True
+    )
+)
+
diff --git a/aleksis/apps/untis/util/mysql/importers/substitutions.py b/aleksis/apps/untis/util/mysql/importers/substitutions.py
new file mode 100644
index 0000000..90f6c07
--- /dev/null
+++ b/aleksis/apps/untis/util/mysql/importers/substitutions.py
@@ -0,0 +1,158 @@
+import logging
+
+from calendarweek import CalendarWeek
+from django.db.models import Q
+
+from aleksis.apps.chronos import models as chronos_models
+from ..util import run_default_filter, untis_split_first, untis_date_to_date, sync_m2m
+from .... import models as mysql_models
+
+logger = logging.getLogger(__name__)
+
+
+def import_substitutions(teachers_ref, subjects_ref, rooms_ref, classes_ref):
+    """ Import substitutions """
+
+    subs = (
+        run_default_filter(mysql_models.Substitution.objects, filter_term=False)
+        .exclude(
+            Q(flags__contains="N")
+            | Q(flags__contains="b")
+            | Q(flags__contains="F")
+            | Q(flags__exact="g")
+        )
+        .order_by("classids", "lesson")
+    )
+
+    existing_subs = []
+    for sub in subs:
+        # IDs
+        sub_id = sub.lesson_idsubst
+        existing_subs.append(sub_id)
+
+        lesson_id = sub.lesson_idsubst
+
+        logger.info("Import substitution {}".format(sub_id))
+
+        # Time
+        date = untis_date_to_date(sub.date)
+        weekday = date.weekday()
+        week = CalendarWeek.from_date(date)
+        period = sub.lesson
+
+        # Supervision substitution?
+        is_supervision_substitution = sub.corridor_id != 0
+
+        # Cancellation?
+        cancelled, cancelled_for_teachers = False, False
+        if "E" in sub.flags:
+            cancelled = True
+        elif "F" in sub.flags:
+            cancelled_for_teachers = True
+
+        # Comment
+        comment = sub.text
+
+        # Teacher
+        if sub.teacher_idlessn != 0:
+            teacher_old = teachers_ref[sub.teacher_idlessn]
+        else:
+            teacher_old = None
+
+        teachers = []
+        if sub.teacher_idsubst != 0:
+            teacher_new = teachers_ref[sub.teacher_idsubst]
+            teachers = [teacher_new]
+
+            if teacher_old is not None and teacher_new.id == teacher_old.id:
+                teachers = []
+
+        if not is_supervision_substitution:
+            lesson_periods = chronos_models.LessonPeriod.objects.filter(
+                lesson__lesson_id_untis=lesson_id,
+                lesson__teachers=teacher_old,
+                period__period=period,
+                period__weekday=weekday,
+            ).on_day(date)
+            if lesson_periods.exists():
+                lesson_period = lesson_periods[0]
+                logger.info("  Matching lesson period found ({})".format(lesson_period))
+            else:
+                lesson_period = None
+
+            # Subject
+            subject_old = lesson_period.lesson.subject if lesson_period else None
+            subject_new = None
+            if sub.subject_idsubst != 0:
+                subject_new = subjects_ref[sub.subject_idsubst]
+
+                if subject_old and subject_old.id == subject_new.id:
+                    subject_new = None
+
+            # # Room
+            room_old = lesson_period.room if lesson_period else None
+            room_new = None
+            if sub.room_idsubst != 0:
+                room_new = rooms_ref[sub.room_idsubst]
+
+                if room_old is not None and room_old.id == room_new.id:
+                    room_new = None
+
+            # # Classes
+            classes = []
+            class_ids = untis_split_first(sub.classids, conv=int)
+
+            for id in class_ids:
+                classes.append(classes_ref[id])
+
+            if lesson_period:
+                (
+                    substitution,
+                    created,
+                ) = chronos_models.LessonSubstitution.objects.get_or_create(
+                    lesson_period=lesson_period, week=week.week
+                )
+
+                if created:
+                    logger.info("  Substitution created")
+
+                # Sync teachers
+                sync_m2m(teachers, substitution.teachers)
+
+                # Update values
+                if (
+                    substitution.subject != subject_new
+                    or substitution.room != room_new
+                    or substitution.cancelled != cancelled
+                    or substitution.cancelled_for_teachers != cancelled_for_teachers
+                    or substitution.comment != comment
+                    or substitution.import_ref_untis != sub_id
+                ):
+                    substitution.subject = subject_new
+                    substitution.room = room_new
+                    substitution.cancelled = cancelled
+                    substitution.cancelled_for_teachers = cancelled_for_teachers
+                    substitution.comment = comment
+                    substitution.import_ref_untis = sub_id
+                    substitution.save()
+                    logger.info("  Substitution updated")
+
+            else:
+                pass
+                # TODO: Special assignment, no existing lesson period for that substitution
+        else:
+            pass
+            # TODO: Supervision substitution
+            # # Supervisement
+            # if sub.corridor_id != 0:
+            #     corridor = drive["corridors"][sub.corridor_id]
+            #     type = TYPE_CORRIDOR
+            #
+
+    # Delete all no longer existing substitutions
+    for s in chronos_models.LessonSubstitution.objects.all():
+        if s.import_ref_untis and s.import_ref_untis not in existing_subs:
+            logger.info("Substitution {} deleted".format(s.id))
+            s.delete()
+
+    # TODO: Do that for supervision substitutions, too
diff --git a/aleksis/apps/untis/util/mysql/main.py b/aleksis/apps/untis/util/mysql/main.py
index 1d3d9d1..26aaa4e 100644
--- a/aleksis/apps/untis/util/mysql/main.py
+++ b/aleksis/apps/untis/util/mysql/main.py
@@ -7,6 +7,7 @@ from .importers.common_data import (
     import_time_periods,
     import_breaks)
 from .importers.lessons import import_lessons
+from .importers.substitutions import import_substitutions
 
 
 def untis_import_mysql():
@@ -27,3 +28,6 @@ def untis_import_mysql():
 
     # Lessons
     import_lessons(time_periods_ref, rooms_ref, subjects_ref, teachers_ref, classes_ref)
+
+    # Substitutions
+    import_substitutions(teachers_ref, subjects_ref, rooms_ref, classes_ref)
-- 
GitLab