From 2e7a069d0ab37c3fab6e2c759f2748985ffd7ca2 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Wed, 31 May 2023 18:52:01 +0200 Subject: [PATCH] Add trainer import code --- server/vbv_lernwelt/importer/services.py | 57 ++++++++++++- .../Schulungen_Durchfuehrung_Trainer.xlsx | Bin 15523 -> 15535 bytes .../importer/tests/test_import_trainers.py | 76 ++++++++++++++++++ .../importer/tests/test_services.py | 1 - .../vbv_lernwelt/importer/tests/test_utils.py | 10 +++ server/vbv_lernwelt/importer/utils.py | 10 ++- 6 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 server/vbv_lernwelt/importer/tests/test_import_trainers.py diff --git a/server/vbv_lernwelt/importer/services.py b/server/vbv_lernwelt/importer/services.py index a7ac207f..e9033e56 100644 --- a/server/vbv_lernwelt/importer/services.py +++ b/server/vbv_lernwelt/importer/services.py @@ -3,9 +3,9 @@ from typing import Dict, Any from openpyxl.reader.excel import load_workbook from vbv_lernwelt.core.models import User -from vbv_lernwelt.course.models import Course, CourseSession -from vbv_lernwelt.importer.utils import try_parse_datetime -from vbv_lernwelt.learnpath.models import LearningContentAttendanceCourse +from vbv_lernwelt.course.models import Course, CourseSession, CourseSessionUser +from vbv_lernwelt.importer.utils import try_parse_datetime, parse_circle_group_string +from vbv_lernwelt.learnpath.models import LearningContentAttendanceCourse, Circle def create_or_update_user( @@ -27,7 +27,7 @@ def create_or_update_user( user = User(sso_id=sso_id, email=email, username=email) user.email = email - user.sso_id = sso_id + user.sso_id = user.sso_id or sso_id user.username = email user.first_name = first_name user.last_name = last_name @@ -100,3 +100,52 @@ def create_or_update_course_session(course: Course, data: Dict[str, Any], circle cs.save() return cs + + +def create_or_update_trainer(course: Course, data: Dict[str, Any]): + user = create_or_update_user( + email=data["Email"], + first_name=data["Vorname"], + last_name=data["Name"], + ) + + # TODO: handle language + + import_id = data["Generation"].strip() + groups = [g.strip() for g in data["Klasse"].strip().split(",")] + + # general expert handling + for group in groups: + course_session = CourseSession.objects.filter( + import_id=import_id, group=group, course=course + ).first() + if course_session: + csu, _created = CourseSessionUser.objects.get_or_create( + course_session_id=course_session.id, user_id=user.id + ) + csu.role = CourseSessionUser.Role.EXPERT + csu.save() + + # circle expert handling + circle_data = parse_circle_group_string(data["Circles"]) + for circle_string in circle_data: + parts = circle_string.split("(", 1) + circle_name = parts[0].strip() + groups = [g.strip() for g in parts[1].rstrip(")").strip().split(",")] + + # print(circle_name, groups) + for group in groups: + course_session = CourseSession.objects.filter( + import_id=import_id, group=group, course=course + ).first() + circle = Circle.objects.filter( + slug=f"{course.slug}-lp-circle-{circle_name.lower()}" + ).first() + + if course_session and circle: + csu = CourseSessionUser.objects.filter( + course_session_id=course_session.id, user_id=user.id + ).first() + if csu: + csu.expert.add(circle) + csu.save() diff --git a/server/vbv_lernwelt/importer/tests/Schulungen_Durchfuehrung_Trainer.xlsx b/server/vbv_lernwelt/importer/tests/Schulungen_Durchfuehrung_Trainer.xlsx index 9df30a5ff87fbaa9b5ed42b2b9103243cdf6fc93..d40126c789472b43c0a2114142433fe0ba92dac9 100644 GIT binary patch delta 6118 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 List[str]: + # This regex pattern matches any comma that is not inside parentheses + pattern = r",(?![^()]*\))" + + # re.split() splits the string based on the pattern + return [x.strip() for x in re.split(pattern, value)]