Skip to content
Snippets Groups Projects
Commit 6ec576a4 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Merge branch '5-import-exams-announcement-from-calendar-via-mysql' into 'master'

Resolve "Import exams/announcement from calendar via MySQL"

Closes #5

See merge request AlekSIS/official/AlekSIS-App-Untis!146
parents fd898f89 fd0d8b61
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ Added ...@@ -14,6 +14,7 @@ Added
* Support for configuring the Untis school ID * Support for configuring the Untis school ID
* Add Ukrainian locale (contributed by Sergiy Gorichenko from Fre(i)e Software GmbH). * Add Ukrainian locale (contributed by Sergiy Gorichenko from Fre(i)e Software GmbH).
* Import exams from Untis.
Fixed Fixed
~~~~~ ~~~~~
......
...@@ -14,6 +14,7 @@ Features ...@@ -14,6 +14,7 @@ Features
* Import breaks * Import breaks
* Import classes * Import classes
* Import events * Import events
* Import exams
* Import exported Untis database via MySQL import * Import exported Untis database via MySQL import
* Import exported Untis XML files * Import exported Untis XML files
* Import holidays * Import holidays
......
...@@ -74,3 +74,6 @@ chronos_models.Holiday.field( ...@@ -74,3 +74,6 @@ chronos_models.Holiday.field(
chronos_models.ExtraLesson.field( chronos_models.ExtraLesson.field(
import_ref_untis=IntegerField(verbose_name=_("UNTIS import reference"), null=True, blank=True) import_ref_untis=IntegerField(verbose_name=_("UNTIS import reference"), null=True, blank=True)
) )
chronos_models.Exam.field(
import_ref_untis=IntegerField(verbose_name=_("UNTIS import reference"), null=True, blank=True)
)
import logging
from django.utils.translation import gettext as _
from calendarweek import CalendarWeek
from tqdm import tqdm
from aleksis.apps.chronos import models as chronos_models
from aleksis.apps.chronos.models import ExtraLesson, Lesson, ValidityRange
from .... import models as mysql_models
from ..util import (
TQDM_DEFAULTS,
connect_untis_fields,
date_to_untis_date,
get_first_period,
get_last_period,
move_weekday_to_range,
run_default_filter,
untis_date_to_date,
untis_split_second,
)
logger = logging.getLogger(__name__)
def import_exams(
validity_range: ValidityRange,
time_periods_ref,
subjects_ref,
teachers_ref,
rooms_ref,
):
ref = {}
# Get absences
exams = (
run_default_filter(validity_range, mysql_models.Exam.objects, filter_term=False)
.filter(
date__lte=date_to_untis_date(validity_range.date_end),
date__gte=date_to_untis_date(validity_range.date_start),
)
.order_by("exam_id")
)
existing_exams = []
for exam in tqdm(exams, desc="Import exams", **TQDM_DEFAULTS):
import_ref = exam.exam_id
logger.info("Import exam {}".format(import_ref))
# Build values
title = exam.name
comment = exam.text
day = untis_date_to_date(exam.date)
period_from = exam.lessonfrom
period_to = exam.lessonto
weekday = day.weekday()
week = CalendarWeek.from_date(day)
# Check min/max weekdays
weekday = move_weekday_to_range(time_periods_ref, weekday)
# Check min/max periods
first_period = get_first_period(time_periods_ref, weekday)
last_period = get_last_period(time_periods_ref, weekday)
if period_from == 0:
period_from = first_period
if period_to == 0:
period_to = last_period
time_period_from = time_periods_ref[weekday][period_from]
time_period_to = time_periods_ref[weekday][period_to]
# Get groups, teachers and rooms
raw_exams = connect_untis_fields(exam, "examelement", 10)
first = True
lesson = None
subject = None
exams = []
for raw_exam in raw_exams:
el = untis_split_second(raw_exam, remove_empty=False)
if first:
lesson_id = int(el[0])
subject_id = int(el[1])
lesson = Lesson.objects.get(validity=validity_range, lesson_id_untis=lesson_id)
subject = subjects_ref[subject_id]
first = False
period = int(el[4])
period = time_periods_ref[weekday][period]
teacher_id = int(el[5])
room_id = int(el[6])
teacher = teachers_ref[teacher_id]
room = rooms_ref[room_id]
exams.append((period, teacher, room))
if not lesson or not subject:
logger.warning(f"Skip exam {import_ref} due to missing data.")
continue
new_exam, created = chronos_models.Exam.objects.update_or_create(
import_ref_untis=import_ref,
defaults={
"date": day,
"lesson": lesson,
"period_from": time_period_from,
"period_to": time_period_to,
"title": title,
"comment": comment,
"school_term": validity_range.school_term,
},
)
if created:
logger.info(" New exam created")
extra_lesson_pks = []
for exam in exams:
period, teacher, room = exam
comment = new_exam.title or _("Exam")
extra_lesson, __ = ExtraLesson.objects.get_or_create(
exam=new_exam,
period=period,
defaults={
"room": room,
"week": week.week,
"year": week.year,
"comment": comment,
"subject": subject,
},
)
if (
extra_lesson.room != room
or extra_lesson.week != week.week
or extra_lesson.year != week.year
or extra_lesson.comment != comment
or extra_lesson.subject != subject
):
extra_lesson.room = room
extra_lesson.week = week.week
extra_lesson.year = week.year
extra_lesson.comment = comment
extra_lesson.subject = subject
extra_lesson.save()
extra_lesson.groups.set(lesson.groups.all())
extra_lesson.teachers.set([teacher])
extra_lesson_pks.append(extra_lesson.pk)
# Delete no-longer necessary extra lessons
ExtraLesson.objects.filter(exam=new_exam).exclude(pk__in=extra_lesson_pks).delete()
existing_exams.append(import_ref)
ref[import_ref] = new_exam
# Delete all no longer existing exams
for e in chronos_models.Exam.objects.within_dates(
validity_range.date_start, validity_range.date_end
):
if e.import_ref_untis and e.import_ref_untis not in existing_exams:
logger.info("exam {} deleted".format(e.id))
e.delete()
...@@ -21,6 +21,7 @@ from .importers.common_data import ( ...@@ -21,6 +21,7 @@ from .importers.common_data import (
import_time_periods, import_time_periods,
) )
from .importers.events import import_events from .importers.events import import_events
from .importers.exams import import_exams
from .importers.holidays import import_holidays from .importers.holidays import import_holidays
from .importers.lessons import import_lessons from .importers.lessons import import_lessons
from .importers.substitutions import import_substitutions from .importers.substitutions import import_substitutions
...@@ -93,3 +94,6 @@ def untis_import_mysql( ...@@ -93,3 +94,6 @@ def untis_import_mysql(
# Events # Events
import_events(validity_range, time_periods_ref, teachers_ref, classes_ref, rooms_ref) import_events(validity_range, time_periods_ref, teachers_ref, classes_ref, rooms_ref)
# Exams
import_exams(validity_range, time_periods_ref, subjects_ref, teachers_ref, rooms_ref)
...@@ -25,6 +25,7 @@ information from Untis can be imported into AlekSIS: ...@@ -25,6 +25,7 @@ information from Untis can be imported into AlekSIS:
* Absences, absence reasons * Absences, absence reasons
* Substitutions, extra lessons, cancellations * Substitutions, extra lessons, cancellations
* Events * Events
* Exams
The Untis integration supports the versioning features of Untis. By default, The Untis integration supports the versioning features of Untis. By default,
the most recent version of each object is imported. the most recent version of each object is imported.
...@@ -32,10 +33,10 @@ the most recent version of each object is imported. ...@@ -32,10 +33,10 @@ the most recent version of each object is imported.
Currently, the following features are known not to be supported: Currently, the following features are known not to be supported:
* Students, student groups, student choices * Students, student groups, student choices
* Exams
* Calendars
* Prebookings * Prebookings
* Statistical data * Statistical data
* Special rooms (subject and group rooms) * Special rooms (subject and group rooms)
AlekSIS does not support so-called "day texts" from Untis. These are incompatible with AlekSIS' announcement feature, which can be used as a replacement.
.. _Untis MultiUser: https://www.untis.at/produkte/untis-das-grundpaket/multiuser .. _Untis MultiUser: https://www.untis.at/produkte/untis-das-grundpaket/multiuser
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment