diff --git a/server/vbv_lernwelt/course/management/commands/create_default_courses.py b/server/vbv_lernwelt/course/management/commands/create_default_courses.py index 12363a7e..8b16eaf8 100644 --- a/server/vbv_lernwelt/course/management/commands/create_default_courses.py +++ b/server/vbv_lernwelt/course/management/commands/create_default_courses.py @@ -52,7 +52,10 @@ from vbv_lernwelt.course.models import ( ) from vbv_lernwelt.course.services import mark_course_completion from vbv_lernwelt.feedback.creators.create_demo_feedback import create_feedback -from vbv_lernwelt.importer.services import import_course_sessions_from_excel +from vbv_lernwelt.importer.services import ( + import_course_sessions_from_excel, + import_trainers_from_excel, +) from vbv_lernwelt.learnpath.create_vv_new_learning_path import ( create_vv_new_learning_path, ) @@ -453,6 +456,10 @@ def create_course_training_de(): course, f"{current_dir}/../../../importer/tests/Schulungen_Durchfuehrung_Trainer.xlsx", ) + import_trainers_from_excel( + course, + f"{current_dir}/../../../importer/tests/Schulungen_Durchfuehrung_Trainer.xlsx", + ) for cs in CourseSession.objects.filter(course_id=COURSE_UK_TRAINING): cs.assignment_details_list = [ diff --git a/server/vbv_lernwelt/importer/services.py b/server/vbv_lernwelt/importer/services.py index e9033e56..9c66fe85 100644 --- a/server/vbv_lernwelt/importer/services.py +++ b/server/vbv_lernwelt/importer/services.py @@ -1,5 +1,6 @@ from typing import Dict, Any +import structlog from openpyxl.reader.excel import load_workbook from vbv_lernwelt.core.models import User @@ -7,10 +8,20 @@ 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 +logger = structlog.get_logger(__name__) + def create_or_update_user( email: str, first_name: str = "", last_name: str = "", sso_id: str = None ): + logger.debug( + "create_or_update_user", + email=email, + first_name=first_name, + last_name=last_name, + sso_id=sso_id, + label="import", + ) user = None if sso_id: user_qs = User.objects.filter(sso_id=sso_id) @@ -56,6 +67,13 @@ def create_or_update_course_session(course: Course, data: Dict[str, Any], circle :return: """ + logger.debug( + "create_or_update_course_session", + course=course.title, + data=data, + label="import", + ) + if circles is None: circles = [] @@ -102,7 +120,25 @@ def create_or_update_course_session(course: Course, data: Dict[str, Any], circle return cs +def import_trainers_from_excel(course: Course, filename: str): + workbook = load_workbook(filename=filename) + sheet = workbook["Schulungen Trainer"] + + header = [cell.value for cell in sheet[1]] + + for row in sheet.iter_rows(min_row=2, values_only=True): + row_with_header = list(zip(header, row)) + create_or_update_trainer(course, dict(row_with_header)) + + def create_or_update_trainer(course: Course, data: Dict[str, Any]): + logger.debug( + "create_or_update_trainer", + course=course.title, + data=data, + label="import", + ) + user = create_or_update_user( email=data["Email"], first_name=data["Vorname"], diff --git a/server/vbv_lernwelt/importer/tests/test_import_trainers.py b/server/vbv_lernwelt/importer/tests/test_import_trainers.py index f02c8b15..9f47838c 100644 --- a/server/vbv_lernwelt/importer/tests/test_import_trainers.py +++ b/server/vbv_lernwelt/importer/tests/test_import_trainers.py @@ -26,6 +26,7 @@ class ImportTrainerTestCase(TestCase): for row in sheet.iter_rows(min_row=2, values_only=True): row_with_header = list(zip(header, row)) print(row_with_header) + create_or_update_trainer(self.course, dict(row_with_header)) class CreateOrUpdateCourseSessionTestCase(TestCase): diff --git a/server/vbv_lernwelt/notify/service.py b/server/vbv_lernwelt/notify/service.py index e14decd9..ec384814 100644 --- a/server/vbv_lernwelt/notify/service.py +++ b/server/vbv_lernwelt/notify/service.py @@ -1,6 +1,6 @@ -import logging from typing import Optional +import structlog from notifications.signals import notify from sendgrid import Mail, SendGridAPIClient from storages.utils import setting @@ -8,7 +8,7 @@ from storages.utils import setting from vbv_lernwelt.core.models import User from vbv_lernwelt.notify.models import Notification, NotificationType -logger = logging.getLogger(__name__) +logger = structlog.get_logger(__name__) class EmailService: @@ -25,10 +25,14 @@ class EmailService: ) try: cls._sendgrid_client.send(message) - logger.info(f"Successfully sent email to {recipient}") + logger.info(f"Successfully sent email to {recipient}", label="email") return True except Exception as e: - logger.error(f"Failed to send email to {recipient}: {e}") + logger.error( + f"Failed to send email to {recipient}: {e}", + exc_info=True, + label="email", + ) return False diff --git a/server/vbv_lernwelt/sso/jwt.py b/server/vbv_lernwelt/sso/jwt.py index c31462a6..dee3c02a 100644 --- a/server/vbv_lernwelt/sso/jwt.py +++ b/server/vbv_lernwelt/sso/jwt.py @@ -1,8 +1,9 @@ import base64 import json -import logging -logger = logging.getLogger(__name__) +import structlog + +logger = structlog.get_logger(__name__) def decode_jwt(jwt: str): @@ -11,7 +12,9 @@ def decode_jwt(jwt: str): payload_bytes = base64.urlsafe_b64decode(_correct_padding(jwt_parts[1])) payload = json.loads(payload_bytes.decode("UTF-8")) except Exception as e: - logger.warning(f"OAuthToken error: Could not decode jwt: {e}") + logger.warning( + f"OAuthToken error: Could not decode jwt: {e}", exc_info=True, label="sso" + ) return None return payload