From ee024f0537dd4069bfe5b50e8ae421c7f4feba9f Mon Sep 17 00:00:00 2001 From: Dominik George <nik@naturalnet.de> Date: Thu, 20 May 2021 12:31:46 +0200 Subject: [PATCH] Remove XML importer for now This can be reverted completely when working on #7 outside of the release cycle. --- aleksis/apps/untis/forms.py | 6 - .../management/commands/untis_import_xml.py | 14 -- aleksis/apps/untis/menus.py | 7 - aleksis/apps/untis/migrations/0001_initial.py | 1 - .../migrations/0002_auto_20200820_1542.py | 2 +- aleksis/apps/untis/models.py | 5 +- aleksis/apps/untis/rules.py | 6 - .../untis/templates/untis/xml_import.html | 43 ----- aleksis/apps/untis/urls.py | 7 - aleksis/apps/untis/util/xml/xml.py | 173 ------------------ aleksis/apps/untis/views.py | 24 --- 11 files changed, 2 insertions(+), 286 deletions(-) delete mode 100644 aleksis/apps/untis/forms.py delete mode 100644 aleksis/apps/untis/management/commands/untis_import_xml.py delete mode 100644 aleksis/apps/untis/templates/untis/xml_import.html delete mode 100644 aleksis/apps/untis/urls.py delete mode 100644 aleksis/apps/untis/util/xml/xml.py delete mode 100644 aleksis/apps/untis/views.py diff --git a/aleksis/apps/untis/forms.py b/aleksis/apps/untis/forms.py deleted file mode 100644 index 66a2f9d..0000000 --- a/aleksis/apps/untis/forms.py +++ /dev/null @@ -1,6 +0,0 @@ -from django import forms -from django.utils.translation import gettext_lazy as _ - - -class UntisUploadForm(forms.Form): - untis_xml = forms.FileField(label=_("Untis XML export")) diff --git a/aleksis/apps/untis/management/commands/untis_import_xml.py b/aleksis/apps/untis/management/commands/untis_import_xml.py deleted file mode 100644 index efbaa67..0000000 --- a/aleksis/apps/untis/management/commands/untis_import_xml.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.core.management.base import BaseCommand -from django.utils.translation import ugettext as _ - -from ...util.xml.xml import untis_import_xml - - -class Command(BaseCommand): - def add_arguments(self, parser): - parser.add_argument("untis_xml_path", help=_("Path to Untis XML export file")) - - def handle(self, *args, **options): - untis_xml = open(options["untis_xml_path"], "rb") - - untis_import_xml(None, untis_xml) diff --git a/aleksis/apps/untis/menus.py b/aleksis/apps/untis/menus.py index f05d52f..d9f723f 100644 --- a/aleksis/apps/untis/menus.py +++ b/aleksis/apps/untis/menus.py @@ -2,13 +2,6 @@ from django.utils.translation import gettext_lazy as _ MENUS = { "DATA_MANAGEMENT_MENU": [ - { - "name": _("Untis XML import"), - "url": "untis_xml_import", - "validators": [ - ("aleksis.core.util.predicates.permission_validator", "untis.do_xml_import_rule",), - ], - }, { "name": _("Link subjects to groups (for UNTIS MySQL import)"), "url": "untis_groups_subjects", diff --git a/aleksis/apps/untis/migrations/0001_initial.py b/aleksis/apps/untis/migrations/0001_initial.py index dcdd6f4..befeb5e 100644 --- a/aleksis/apps/untis/migrations/0001_initial.py +++ b/aleksis/apps/untis/migrations/0001_initial.py @@ -2272,7 +2272,6 @@ class Migration(migrations.Migration): ], options={ "permissions": ( - ("do_xml_import", "Can do XML import"), ("assign_subjects_to_groups", "Can assign subjects to groups"), ), "managed": False, diff --git a/aleksis/apps/untis/migrations/0002_auto_20200820_1542.py b/aleksis/apps/untis/migrations/0002_auto_20200820_1542.py index a3d7948..eef0e28 100644 --- a/aleksis/apps/untis/migrations/0002_auto_20200820_1542.py +++ b/aleksis/apps/untis/migrations/0002_auto_20200820_1542.py @@ -12,6 +12,6 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='globalpermissions', - options={'managed': False, 'permissions': (('do_xml_import', 'Kann XML-Import durchführen'), ('assign_subjects_to_groups', 'Kann Fächer zu Gruppen zuzuordnen'))}, + options={'managed': False, 'permissions': (('assign_subjects_to_groups', 'Kann Fächer zu Gruppen zuzuordnen'),)}, ), ] diff --git a/aleksis/apps/untis/models.py b/aleksis/apps/untis/models.py index d141979..4d1d23a 100644 --- a/aleksis/apps/untis/models.py +++ b/aleksis/apps/untis/models.py @@ -4218,7 +4218,4 @@ class Views(models.Model, PureDjangoModel): class GlobalPermissions(models.Model, PureDjangoModel): class Meta: managed = False - permissions = ( - ("do_xml_import", _("Can do XML import")), - ("assign_subjects_to_groups", _("Can assign subjects to groups")), - ) + permissions = (("assign_subjects_to_groups", _("Can assign subjects to groups")),) diff --git a/aleksis/apps/untis/rules.py b/aleksis/apps/untis/rules.py index fc420c3..cf7b59c 100644 --- a/aleksis/apps/untis/rules.py +++ b/aleksis/apps/untis/rules.py @@ -2,12 +2,6 @@ from rules import add_perm from aleksis.core.util.predicates import has_global_perm, has_person -# Do XML import -do_xml_import_predicate = has_person & has_global_perm("untis.do_xml_import") -add_perm("untis.do_xml_import_rule", do_xml_import_predicate) - - -# Do XML import assign_subjects_to_groups_predicate = has_person & has_global_perm( "untis.assign_subjects_to_groups" ) diff --git a/aleksis/apps/untis/templates/untis/xml_import.html b/aleksis/apps/untis/templates/untis/xml_import.html deleted file mode 100644 index 48af24b..0000000 --- a/aleksis/apps/untis/templates/untis/xml_import.html +++ /dev/null @@ -1,43 +0,0 @@ -{# -*- engine:django -*- #} - -{% extends "core/base.html" %} - -{% load material_form i18n %} - -{% block browser_title %}{% blocktrans %}Import Untis data via XML{% endblocktrans %}{% endblock %} -{% block page_title %}{% blocktrans %}Import Untis data via XML{% endblocktrans %}{% endblock %} - -{% block content %} - - <p class="flow-text"> - {% blocktrans %} - Untis provides a function for exporting all data as an XML file. - {% endblocktrans %} - </p> - <div class="alert warning"> - <p> - <i class="material-icons left">warning</i> - {% blocktrans %} - Newly imported data will be valid as of tomorrow. - {% endblocktrans %} - {% blocktrans %} - The effective dates of all existing lessons will be set to end - today. - {% endblocktrans %} - {% blocktrans %} - The effective dates of all newly imported lessons will be set to - start tomorrow. - {% endblocktrans %} - {% blocktrans %} - Teachers, rooms, subjects and classes and periods will be updated in place. - {% endblocktrans %} - </p> - </div> - - <form method="post" enctype="multipart/form-data"> - {% csrf_token %} - {% form form=upload_form %}{% endform %} - {% include "core/partials/save_button.html" with icon="import_export" caption=_("Import data") %} - </form> - -{% endblock %} diff --git a/aleksis/apps/untis/urls.py b/aleksis/apps/untis/urls.py deleted file mode 100644 index 1a5119e..0000000 --- a/aleksis/apps/untis/urls.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.urls import path - -from . import views - -urlpatterns = [ - path("import/xml/", views.xml_import, name="untis_xml_import"), -] diff --git a/aleksis/apps/untis/util/xml/xml.py b/aleksis/apps/untis/util/xml/xml.py deleted file mode 100644 index 076719b..0000000 --- a/aleksis/apps/untis/util/xml/xml.py +++ /dev/null @@ -1,173 +0,0 @@ -from datetime import date, time, timedelta -from typing import BinaryIO, Optional, Union -from xml.dom import Node - -from django.http import HttpRequest -from django.utils.translation import ugettext as _ - -import defusedxml - -from aleksis.apps.chronos.models import Lesson, Room, Subject, TimePeriod -from aleksis.core.models import Group, Person -from aleksis.core.util import messages - - -def get_child_node_text(node: Node, tag: str) -> Optional[str]: - tag_nodes = node.getElementsByTagName(tag) - - if len(tag_nodes) == 1: - return tag_nodes[0].firstChild.nodeValue - else: - return None - - -def get_child_node_id(node: Node, tag: str) -> Optional[str]: - tag_nodes = node.getElementsByTagName(tag) - - if len(tag_nodes) == 1: - return tag_nodes[0].attributes["id"].value - else: - return None - - -def untis_import_xml(request: HttpRequest, untis_xml: Union[BinaryIO, str]) -> None: - dom = defusedxml.parse(untis_xml) - - subjects = dom.getElementsByTagName("subject") - for subject_node in subjects: - short_name = subject_node.attributes["id"].value[3:] - name = get_child_node_text(subject_node, "longname") - colour_fg = get_child_node_text(subject_node, "forecolor") - colour_bg = get_child_node_text(subject_node, "backcolor") - - Subject.objects.select_related(None).prefetch_related(None).update_or_create( - short_name=short_name, - defaults={"name": name, "colour_fg": colour_fg, "colour_bg": colour_bg}, - ) - - periods = dom.getElementsByTagName("timeperiod") - for period_node in periods: - weekday = int(get_child_node_text(period_node, "day")) - period = int(get_child_node_text(period_node, "period")) - starttime = get_child_node_text(period_node, "starttime") - endtime = get_child_node_text(period_node, "endtime") - - time_start = time(int(starttime[:2]), int(starttime[2:])) - time_end = time(int(endtime[:2]), int(endtime[2:])) - - TimePeriod.objects.select_related(None).prefetch_related(None).update_or_create( - weekday=weekday, - period=period, - defaults={"time_start": time_start, "time_end": time_end}, - ) - - rooms = dom.getElementsByTagName("room") - for room_node in rooms: - short_name = room_node.attributes["id"].value[3:] - name = get_child_node_text(room_node, "longname") - - Room.objects.select_related(None).prefetch_related(None).update_or_create( - short_name=short_name, defaults={"name": name} - ) - - classes = dom.getElementsByTagName("class") - for class_node in classes: - short_name = class_node.attributes["id"].value[3:] - name = _("Class %s") % short_name - class_teacher_short_name = get_child_node_id(class_node, "class_teacher")[3:] - - class_, created = ( - Group.objects.select_related(None) - .prefetch_related(None) - .update_or_create(short_name=short_name, defaults={"name": name}) - ) - - try: - # Teachers need to come from another source, e.g. SchILD-NRW - class_.owners.set([Person.objects.get(short_name=class_teacher_short_name)]) - class_.save() - except Person.DoesNotExist: - messages.warning( - request, - _("Could not set class teacher of %(class)s to %(teacher)s.") - % {"class": short_name, "teacher": class_teacher_short_name}, - ) - - # Set all existing lessons that overlap to end today - today = date.today() - Lesson.objects.filter(date_end__gt=today).update(date_end=today) - - lessons = dom.getElementsByTagName("lesson") - for lesson_node in lessons: - subject_short_name = get_child_node_id(lesson_node, "lesson_subject")[3:] - teacher_short_name = get_child_node_id(lesson_node, "lesson_teacher")[3:] - group_short_names = [ - v.strip() - for v in get_child_node_id(lesson_node, "lesson_classes").split("CL_") - if v.strip() - ] - effectivebegindate = get_child_node_text(lesson_node, "effectivebegindate") - effectiveenddate = get_child_node_text(lesson_node, "effectiveenddate") - - times = lesson_node.getElementsByTagName("time") - time_periods = [] - for time_node in times: - day = int(get_child_node_text(time_node, "assigned_day")) - period = int(get_child_node_text(time_node, "assigned_period")) - - room_id = get_child_node_id(time_node, "assigned_room") - room = room_id[3:] if room_id else None - - time_periods.append((day, period, room)) - - subject = Subject.objects.get(short_name=subject_short_name) - periods = [ - ( - TimePeriod.objects.get(weekday=v[0], period=v[1]), - Room.objects.get(short_name=v[2]) if v[2] else None, - ) - for v in time_periods - ] - date_start = ( - date( - int(effectivebegindate[:4]), - int(effectivebegindate[4:6]), - int(effectivebegindate[6:]), - ) - if effectivebegindate - else None - ) - date_end = ( - date(int(effectiveenddate[:4]), int(effectiveenddate[4:6]), int(effectiveenddate[6:]),) - if effectiveenddate - else None - ) - - # Coerce effective start date to not be before tomorrow - if date_start and date_start <= today: - date_start = today + timedelta(days=1) - - try: - groups = [Group.objects.get(short_name=v) for v in group_short_names] - except Group.DoesNotExist: - messages.error(request, _("Invalid list of classes: %s") % ", ".join(group_short_names)) - continue - - try: - teachers = [Person.objects.get(short_name=teacher_short_name)] - except Person.DoesNotExist: - messages.error( - request, - _("Failed to import lesson: Teacher %s does not exist.") % teacher_short_name, - ) - continue - - lesson = Lesson.objects.create(subject=subject, date_start=date_start, date_end=date_end) - - lesson.groups.set(groups) - lesson.teachers.set(teachers) - - for period in periods: - lesson.periods.add(period[0], through_defaults={"room": period[1]}) - - lesson.save() diff --git a/aleksis/apps/untis/views.py b/aleksis/apps/untis/views.py deleted file mode 100644 index 84b2a2d..0000000 --- a/aleksis/apps/untis/views.py +++ /dev/null @@ -1,24 +0,0 @@ -from django.http import HttpRequest, HttpResponse -from django.shortcuts import render - -from rules.contrib.views import permission_required - -from .forms import UntisUploadForm -from .util.xml.xml import untis_import_xml - - -@permission_required("untis.do_xml_import_rule") -def xml_import(request: HttpRequest) -> HttpResponse: - context = {} - - upload_form = UntisUploadForm() - - if request.method == "POST": - upload_form = UntisUploadForm(request.POST, request.FILES) - - if upload_form.is_valid(): - untis_import_xml(request, request.FILES["untis_xml"]) - - context["upload_form"] = upload_form - - return render(request, "untis/xml_import.html", context) -- GitLab