Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AlekSIS/official/AlekSIS-App-Untis
  • sunweaver/AlekSIS-App-Untis
  • cocguPpenda/AlekSIS-App-Untis
  • 0inraMfauri/AlekSIS-App-Untis
4 results
Show changes
Commits on Source (1)
import pkg_resources import pkg_resources
try: try:
__version__ = pkg_resources.get_distribution('BiscuIT-App-Untis').version __version__ = pkg_resources.get_distribution("BiscuIT-App-Untis").version
except Exception: except Exception:
__version__ = 'unknown' __version__ = "unknown"
default_app_config = 'biscuit.apps.untis.apps.UntisConfig' default_app_config = "biscuit.apps.untis.apps.UntisConfig"
...@@ -2,5 +2,5 @@ from biscuit.core.util.apps import AppConfig ...@@ -2,5 +2,5 @@ from biscuit.core.util.apps import AppConfig
class UntisConfig(AppConfig): class UntisConfig(AppConfig):
name = 'biscuit.apps.untis' name = "biscuit.apps.untis"
verbose_name = 'BiscuIT - Untis interface' verbose_name = "BiscuIT - Untis interface"
...@@ -3,4 +3,4 @@ from django.utils.translation import ugettext_lazy as _ ...@@ -3,4 +3,4 @@ from django.utils.translation import ugettext_lazy as _
class UntisUploadForm(forms.Form): class UntisUploadForm(forms.Form):
untis_xml = forms.FileField(label=_('Untis XML export')) untis_xml = forms.FileField(label=_("Untis XML export"))
...@@ -6,10 +6,9 @@ from ...util import untis_import_xml ...@@ -6,10 +6,9 @@ from ...util import untis_import_xml
class Command(BaseCommand): class Command(BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('untis_xml_path', help=_( parser.add_argument("untis_xml_path", help=_("Path to Untis XML export file"))
'Path to Untis XML export file'))
def handle(self, *args, **options): def handle(self, *args, **options):
untis_xml = open(options['untis_xml_path'], 'rb') untis_xml = open(options["untis_xml_path"], "rb")
untis_import_xml(None, untis_xml) untis_import_xml(None, untis_xml)
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
MENUS = { MENUS = {
'DATA_MANAGEMENT_MENU': [ "DATA_MANAGEMENT_MENU": [
{ {
'name': _('Units import'), "name": _("Units import"),
'url': 'untis_import', "url": "untis_import",
'validators': ['menu_generator.validators.is_authenticated', 'menu_generator.validators.is_superuser', 'biscuit.core.util.core_helpers.has_person'], "validators": [
"menu_generator.validators.is_authenticated",
"menu_generator.validators.is_superuser",
"biscuit.core.util.core_helpers.has_person",
],
} }
] ]
} }
...@@ -2,7 +2,6 @@ from django.urls import path ...@@ -2,7 +2,6 @@ from django.urls import path
from . import views from . import views
urlpatterns = [ urlpatterns = [
path('import', views.untis_import, name='untis_import'), path("import", views.untis_import, name="untis_import"),
] ]
from datetime import date, time, timedelta from datetime import date, time, timedelta
from typing import BinaryIO, Optional, Union from typing import BinaryIO, Optional, Union
from xml.dom import minidom, Node from xml.dom import Node, minidom
from django.http import HttpRequest from django.http import HttpRequest
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from biscuit.apps.chronos.models import Subject, TimePeriod, Room, Lesson from biscuit.apps.chronos.models import Lesson, Room, Subject, TimePeriod
from biscuit.core.models import Group, Person from biscuit.core.models import Group, Person
from biscuit.core.util import messages from biscuit.core.util import messages
...@@ -23,7 +23,7 @@ def get_child_node_id(node: Node, tag: str) -> Optional[str]: ...@@ -23,7 +23,7 @@ def get_child_node_id(node: Node, tag: str) -> Optional[str]:
tag_nodes = node.getElementsByTagName(tag) tag_nodes = node.getElementsByTagName(tag)
if len(tag_nodes) == 1: if len(tag_nodes) == 1:
return tag_nodes[0].attributes['id'].value return tag_nodes[0].attributes["id"].value
else: else:
return None return None
...@@ -31,120 +31,146 @@ def get_child_node_id(node: Node, tag: str) -> Optional[str]: ...@@ -31,120 +31,146 @@ def get_child_node_id(node: Node, tag: str) -> Optional[str]:
def untis_import_xml(request: HttpRequest, untis_xml: Union[BinaryIO, str]) -> None: def untis_import_xml(request: HttpRequest, untis_xml: Union[BinaryIO, str]) -> None:
dom = minidom.parse(untis_xml) dom = minidom.parse(untis_xml)
subjects = dom.getElementsByTagName('subject') subjects = dom.getElementsByTagName("subject")
for subject_node in subjects: for subject_node in subjects:
abbrev = subject_node.attributes['id'].value[3:] abbrev = subject_node.attributes["id"].value[3:]
name = get_child_node_text(subject_node, 'longname') name = get_child_node_text(subject_node, "longname")
colour_fg = get_child_node_text(subject_node, 'forecolor') colour_fg = get_child_node_text(subject_node, "forecolor")
colour_bg = get_child_node_text(subject_node, 'backcolor') colour_bg = get_child_node_text(subject_node, "backcolor")
Subject.objects.update_or_create(abbrev=abbrev, defaults={ Subject.objects.update_or_create(
'name': name, 'colour_fg': colour_fg, 'colour_bg': colour_bg}) abbrev=abbrev,
defaults={"name": name, "colour_fg": colour_fg, "colour_bg": colour_bg},
)
periods = dom.getElementsByTagName('timeperiod') periods = dom.getElementsByTagName("timeperiod")
for period_node in periods: for period_node in periods:
weekday = int(get_child_node_text(period_node, 'day')) weekday = int(get_child_node_text(period_node, "day"))
period = int(get_child_node_text(period_node, 'period')) period = int(get_child_node_text(period_node, "period"))
starttime = get_child_node_text(period_node, 'starttime') starttime = get_child_node_text(period_node, "starttime")
endtime = get_child_node_text(period_node, 'endtime') endtime = get_child_node_text(period_node, "endtime")
time_start = time(int(starttime[:2]), int(starttime[2:])) time_start = time(int(starttime[:2]), int(starttime[2:]))
time_end = time(int(endtime[:2]), int(endtime[2:])) time_end = time(int(endtime[:2]), int(endtime[2:]))
TimePeriod.objects.update_or_create(weekday=weekday, period=period, defaults={ TimePeriod.objects.update_or_create(
'time_start': time_start, 'time_end': time_end}) weekday=weekday,
period=period,
defaults={"time_start": time_start, "time_end": time_end},
)
rooms = dom.getElementsByTagName('room') rooms = dom.getElementsByTagName("room")
for room_node in rooms: for room_node in rooms:
short_name = room_node.attributes['id'].value[3:] short_name = room_node.attributes["id"].value[3:]
name = get_child_node_text(room_node, 'longname') name = get_child_node_text(room_node, "longname")
Room.objects.update_or_create(short_name=short_name, defaults={ Room.objects.update_or_create(short_name=short_name, defaults={"name": name})
'name': name})
classes = dom.getElementsByTagName('class') classes = dom.getElementsByTagName("class")
for class_node in classes: for class_node in classes:
short_name = class_node.attributes['id'].value[3:] short_name = class_node.attributes["id"].value[3:]
name = _('Class %s') % short_name name = _("Class %s") % short_name
class_teacher_short_name = get_child_node_id( class_teacher_short_name = get_child_node_id(class_node, "class_teacher")[3:]
class_node, 'class_teacher')[3:]
class_, created = Group.objects.update_or_create(short_name=short_name, defaults={ class_, created = Group.objects.update_or_create(
'name': name}) short_name=short_name, defaults={"name": name}
)
try: try:
# Teachers need to come from another source, e.g. SchILD-NRW # Teachers need to come from another source, e.g. SchILD-NRW
class_.owners.set([Person.objects.get( class_.owners.set([Person.objects.get(short_name=class_teacher_short_name)])
short_name=class_teacher_short_name)])
class_.save() class_.save()
except Person.DoesNotExist: except Person.DoesNotExist:
messages.warning(request, _('Could not set class teacher of %(class)s to %(teacher)s.') % { messages.warning(
'class': short_name, 'teacher': class_teacher_short_name}) 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 # Set all existing lessons that overlap to end today
today = date.today() today = date.today()
Lesson.objects.filter( Lesson.objects.filter(date_end__gt=today).update(date_end=today)
date_end__gt=today
).update(
date_end=today
)
lessons = dom.getElementsByTagName('lesson') lessons = dom.getElementsByTagName("lesson")
for lesson_node in lessons: for lesson_node in lessons:
subject_abbrev = get_child_node_id(lesson_node, 'lesson_subject')[3:] subject_abbrev = get_child_node_id(lesson_node, "lesson_subject")[3:]
teacher_short_name = get_child_node_id( teacher_short_name = get_child_node_id(lesson_node, "lesson_teacher")[3:]
lesson_node, 'lesson_teacher')[3:] group_short_names = [
group_short_names = [v.strip() for v in get_child_node_id( v.strip()
lesson_node, 'lesson_classes').split('CL_') if v.strip()] for v in get_child_node_id(lesson_node, "lesson_classes").split("CL_")
effectivebegindate = get_child_node_text( if v.strip()
lesson_node, 'effectivebegindate') ]
effectiveenddate = get_child_node_text(lesson_node, 'effectiveenddate') effectivebegindate = get_child_node_text(lesson_node, "effectivebegindate")
effectiveenddate = get_child_node_text(lesson_node, "effectiveenddate")
times = lesson_node.getElementsByTagName('time')
times = lesson_node.getElementsByTagName("time")
time_periods = [] time_periods = []
for time_node in times: for time_node in times:
day = int(get_child_node_text(time_node, 'assigned_day')) day = int(get_child_node_text(time_node, "assigned_day"))
period = int(get_child_node_text(time_node, 'assigned_period')) period = int(get_child_node_text(time_node, "assigned_period"))
room_id = get_child_node_id(time_node, 'assigned_room') room_id = get_child_node_id(time_node, "assigned_room")
room = room_id[3:] if room_id else None room = room_id[3:] if room_id else None
time_periods.append((day, period, room)) time_periods.append((day, period, room))
subject = Subject.objects.get(abbrev=subject_abbrev) subject = Subject.objects.get(abbrev=subject_abbrev)
periods = [(TimePeriod.objects.get( periods = [
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( TimePeriod.objects.get(weekday=v[0], period=v[1]),
effectivebegindate[6:])) if effectivebegindate else None Room.objects.get(short_name=v[2]) if v[2] else None,
date_end = date(int(effectiveenddate[:4]), int(effectiveenddate[4:6]), int( )
effectiveenddate[6:])) if effectiveenddate 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 # Coerce effective start date to not be before tomorrow
if date_start and date_start <= today: if date_start and date_start <= today:
date_start = today + timedelta(days=1) date_start = today + timedelta(days=1)
try: try:
groups = [Group.objects.get(short_name=v) groups = [Group.objects.get(short_name=v) for v in group_short_names]
for v in group_short_names]
except Group.DoesNotExist: except Group.DoesNotExist:
messages.error(request, _('Invalid list of classes: %s') % messages.error(
', '.join(group_short_names)) request, _("Invalid list of classes: %s") % ", ".join(group_short_names)
)
continue continue
try: try:
teachers = [Person.objects.get(short_name=teacher_short_name)] teachers = [Person.objects.get(short_name=teacher_short_name)]
except Person.DoesNotExist: except Person.DoesNotExist:
messages.error(request, _( messages.error(
'Failed to import lesson: Teacher %s does not exist.') % teacher_short_name) request,
_("Failed to import lesson: Teacher %s does not exist.")
% teacher_short_name,
)
continue continue
lesson = Lesson.objects.create( lesson = Lesson.objects.create(
subject=subject, date_start=date_start, date_end=date_end) subject=subject, date_start=date_start, date_end=date_end
)
lesson.groups.set(groups) lesson.groups.set(groups)
lesson.teachers.set(teachers) lesson.teachers.set(teachers)
for period in periods: for period in periods:
lesson.periods.add(period[0], through_defaults={'room': period[1]}) lesson.periods.add(period[0], through_defaults={"room": period[1]})
lesson.save() lesson.save()
...@@ -2,11 +2,11 @@ from django.contrib.auth.decorators import login_required ...@@ -2,11 +2,11 @@ from django.contrib.auth.decorators import login_required
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from biscuit.core.decorators import admin_required
from .forms import UntisUploadForm from .forms import UntisUploadForm
from .util import untis_import_xml from .util import untis_import_xml
from biscuit.core.decorators import admin_required
@login_required @login_required
@admin_required @admin_required
...@@ -15,12 +15,12 @@ def untis_import(request: HttpRequest) -> HttpResponse: ...@@ -15,12 +15,12 @@ def untis_import(request: HttpRequest) -> HttpResponse:
upload_form = UntisUploadForm() upload_form = UntisUploadForm()
if request.method == 'POST': if request.method == "POST":
upload_form = UntisUploadForm(request.POST, request.FILES) upload_form = UntisUploadForm(request.POST, request.FILES)
if upload_form.is_valid(): if upload_form.is_valid():
untis_import_xml(request, request.FILES['untis_xml']) untis_import_xml(request, request.FILES["untis_xml"])
context['upload_form'] = upload_form context["upload_form"] = upload_form
return render(request, 'untis/untis_import.html', context) return render(request, "untis/untis_import.html", context)