From 0bb8946b3d5205cc2772069c528653faebf8d655 Mon Sep 17 00:00:00 2001 From: Jan Gaura Date: Tue, 13 Feb 2024 15:39:03 +0100 Subject: [PATCH] Enable importing of classes with multiple teachers This implements importing of classes that are taught by multiple teachers. Since we support only one teacher per class, the teacher is taken from the current "user/teacher" who's importing the class. --- api/views.py | 4 ++-- common/bulk_import.py | 19 ++++++++++++------- common/inbus/inbus.py | 2 +- common/utils.py | 4 +++- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/api/views.py b/api/views.py index e8f12a33..25fa44a1 100644 --- a/api/views.py +++ b/api/views.py @@ -618,10 +618,10 @@ def import_activities(request): semester = Semester.objects.get(pk=semester_id) try: - res['users'] = list(common.bulk_import.run(activities, subject, semester)) + res['users'] = list(common.bulk_import.run(activities, subject, semester, request.user)) res['count'] = len(res['users']) except (ImportException, UnicodeDecodeError) as e: - res['error'] = e + res['error'] = ''.join(traceback.TracebackException.from_exception(e).format()) except: res['error'] = traceback.format_exc() diff --git a/common/bulk_import.py b/common/bulk_import.py index 00762fad..85032266 100644 --- a/common/bulk_import.py +++ b/common/bulk_import.py @@ -8,10 +8,12 @@ from common.models import Class, Semester, Subject from io import StringIO from lxml.html import parse -from typing import List, Dict +from typing import List, Dict, Generator +import traceback from .inbus.dto import ConcreteActivity + class ImportException(Exception): pass @@ -25,10 +27,10 @@ class ImportResult: created: bool -def run(concrete_activities: List[ConcreteActivity], subj: Dict[str, str], semester: Semester): - ''' +def run(concrete_activities: List[ConcreteActivity], subj: Dict[str, str], semester: Semester, user: User) -> Generator[ImportResult, None, None]: + """ `subj`: subject from selected subject in UI as dictionary with k:abbr, v: name - ''' + """ subject_abbr = subj['abbr'] try: @@ -58,12 +60,16 @@ def run(concrete_activities: List[ConcreteActivity], subj: Dict[str, str], semes # Teacher # TODO: There may be more teachers for a class - if ca.teacherLogins.strip() != '': + if len(ca.teacherIds) > 1: + # if there are more than 1 teacher, assign class to the one, who's importing + teacher = User.objects.get(username=user.username.upper()) + elif len(ca.teacherIds) == 1: try: teacher = User.objects.get(username=ca.teacherLogins.upper()) except User.DoesNotExist: teacher = user_from_login(ca.teacherLogins.upper()) - + if not teacher: + raise ImportException(f"Cannot create user {ca.teacherLogins.upper()}.\n\nTraceback\n\n{traceback.format_exc()}") else: # TODO: We assign all activities without teacher to one special user :-) teacher = User.objects.get(username='GAU01') @@ -72,7 +78,6 @@ def run(concrete_activities: List[ConcreteActivity], subj: Dict[str, str], semes class_in_db[c].save() - # Students students_in_class = inbus.inbus.students_in_concrete_activity(ca.concreteActivityId) diff --git a/common/inbus/inbus.py b/common/inbus/inbus.py index b1783e29..31660f42 100644 --- a/common/inbus/inbus.py +++ b/common/inbus/inbus.py @@ -68,7 +68,7 @@ def schedule_subject_by_version_id(subject_version_id: dto.SubjectVersionId) -> Complete schedule for given subject version for current semester. """ url = urllib.parse.urljoin(config.INBUS_SERVICE_EDISON_URL, 'schedule') - concrete_activities_resp = utils.inbus_request(url, {'subjectVersionId': subject_version_id}) + concrete_activities_resp = utils.inbus_request(url, {'subjectVersionId': subject_version_id, 'semesterId': 129}) concrete_activities_json = concrete_activities_resp.json() diff --git a/common/utils.py b/common/utils.py index d2f7567a..8d3668a2 100644 --- a/common/utils.py +++ b/common/utils.py @@ -47,12 +47,14 @@ def user_from_inbus_person(person: inbus.dto.PersonSimple) -> django.contrib.aut return user -def user_from_login(login: str) -> django.contrib.auth.models.User: +def user_from_login(login: str) -> Optional[django.contrib.auth.models.User]: """ A shotcut to calling `inbus_search_user` and `user_from_inbus_person`. No need to further set anything. """ person = inbus_search_user(login) + if not person: + return None user = user_from_inbus_person(person) user.username = login.upper() user.save()