diff --git a/client/src/locales/de/translation.json b/client/src/locales/de/translation.json
index 55a8ebec..dd5b1340 100644
--- a/client/src/locales/de/translation.json
+++ b/client/src/locales/de/translation.json
@@ -269,7 +269,7 @@
"selfEvaluationNo": "@:selfEvaluation: Muss ich nochmals anschauen.",
"selfEvaluationYes": "@:selfEvaluation: Ich kann das.",
"steps": "Schritt {{current}} von {{max}}",
- "title": "@:selfEvaluation.selfEvaluation {{title}}",
+ "title": "Selbsteinschätzung {{title}}",
"yes": "Ja, ich kann das"
},
"settings": {
diff --git a/client/src/pages/DashboardPage.vue b/client/src/pages/DashboardPage.vue
index f7ca56d5..bd246037 100644
--- a/client/src/pages/DashboardPage.vue
+++ b/client/src/pages/DashboardPage.vue
@@ -91,7 +91,9 @@ const getNextStepLink = (courseSession: CourseSession) => {
{{ $t("uk.contact.address") }}
- uk.contact.email
+
+ uek-support@vbv-afa.ch
+
diff --git a/server/config/urls.py b/server/config/urls.py
index 4268109e..0c60936a 100644
--- a/server/config/urls.py
+++ b/server/config/urls.py
@@ -37,7 +37,11 @@ from vbv_lernwelt.course.views import (
request_course_completion,
request_course_completion_for_user,
)
-from vbv_lernwelt.edoniq_test.views import export_students, export_trainers
+from vbv_lernwelt.edoniq_test.views import (
+ export_students,
+ export_students_and_trainers,
+ export_trainers,
+)
from vbv_lernwelt.feedback.views import (
get_expert_feedbacks_for_course,
get_feedback_for_circle,
@@ -148,6 +152,8 @@ urlpatterns = [
# edoniq test
path(r'api/core/edoniq-test/export-users/', export_students, name='edoniq_export_students'),
path(r'api/core/edoniq-test/export-trainers/', export_trainers, name='edoniq_export_trainers'),
+ path(r'api/core/edoniq-test/export-users-trainers/', export_students_and_trainers,
+ name='edoniq_export_students_and_trainers'),
# importer
path(
diff --git a/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py b/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py
index fae09e0e..893ca698 100644
--- a/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py
+++ b/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py
@@ -6,7 +6,9 @@ from vbv_lernwelt.core.admin import User
from vbv_lernwelt.core.create_default_users import create_default_users
from vbv_lernwelt.course.consts import COURSE_TEST_ID
from vbv_lernwelt.course.creators.test_course import create_test_course
+from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
from vbv_lernwelt.edoniq_test.views import (
+ fetch_course_session_all_users,
fetch_course_session_users,
generate_export_response,
)
@@ -36,6 +38,37 @@ class EdoniqUserExportTestCase(TestCase):
users = fetch_course_session_users([COURSE_TEST_ID])
self.assertEqual(len(users), 2)
+ def test_fetch_course_session_trainers(self):
+ users = fetch_course_session_users(
+ [COURSE_TEST_ID], role=CourseSessionUser.Role.EXPERT
+ )
+ self.assertEqual(len(users), 1)
+
+ def test_remove_eiger_versicherungen(self):
+ user1 = User.objects.get(email="test-student1@example.com")
+ user1.email = "some@eiger-versicherungen.ch"
+ user1.save()
+ users = fetch_course_session_users([COURSE_TEST_ID])
+ self.assertEqual(len(users), 1)
+
+ def test_export_students_and_trainers(self):
+ users = fetch_course_session_all_users([COURSE_TEST_ID])
+ self.assertEqual(len(users), 3)
+
+ def test_deduplicates_users(self):
+ trainer1 = User.objects.get(email="test-trainer1@example.com")
+ cs_zrh = CourseSession.objects.get(
+ title="Test Zürich 2022 a",
+ )
+ _csu = CourseSessionUser.objects.create(
+ course_session=cs_zrh,
+ user=trainer1,
+ )
+ users = fetch_course_session_all_users([COURSE_TEST_ID])
+ for u in users:
+ print(u.edoniq_role, u.email)
+ self.assertEqual(len(users), 3)
+
def test_response_csv(self):
users = fetch_course_session_users([COURSE_TEST_ID])
response = generate_export_response(users)
diff --git a/server/vbv_lernwelt/edoniq_test/views.py b/server/vbv_lernwelt/edoniq_test/views.py
index 1fe5cf44..30f65398 100644
--- a/server/vbv_lernwelt/edoniq_test/views.py
+++ b/server/vbv_lernwelt/edoniq_test/views.py
@@ -1,8 +1,10 @@
import csv
from datetime import date
+from itertools import chain
from typing import List
from django.contrib.admin.views.decorators import staff_member_required
+from django.db.models import CharField, Value
from django.http import HttpResponse
from vbv_lernwelt.core.models import User
@@ -18,26 +20,53 @@ def export_students(request):
return generate_export_response(course_session_users)
+@staff_member_required
def export_trainers(request):
course_session_users = fetch_course_session_users(
UK_COURSE_IDS, role=CourseSessionUser.Role.EXPERT
)
- return generate_export_response(course_session_users, role="Trainer")
+ return generate_export_response(course_session_users)
+
+
+@staff_member_required
+def export_students_and_trainers(request):
+ course_session_users = fetch_course_session_all_users(UK_COURSE_IDS)
+ return generate_export_response(course_session_users)
def fetch_course_session_users(courses: List[int], role=CourseSessionUser.Role.MEMBER):
+ if role == CourseSessionUser.Role.EXPERT:
+ edoniq_role = "Trainer"
+ else:
+ edoniq_role = "Lernende"
+
# if users should be exported per course session, remove the distinct() call
return (
User.objects.filter(
coursesessionuser__course_session__course__id__in=courses,
coursesessionuser__role=role,
)
+ .exclude(email__contains="eiger-versicherungen.ch") # exclude test users
+ .exclude(email__contains="assurance.ch")
.order_by("email")
+ .annotate(edoniq_role=Value(edoniq_role, output_field=CharField()))
.distinct()
)
-def generate_export_response(cs_users: List[User], role="Lernende") -> HttpResponse:
+def fetch_course_session_all_users(courses: List[int]):
+ course_session_users = fetch_course_session_users(courses)
+ course_session_trainers = fetch_course_session_users(
+ courses, role=CourseSessionUser.Role.EXPERT
+ )
+ combined_queryset = chain(course_session_users, course_session_trainers)
+
+ # use email as key to remove duplicates. Maybe we can use the sso id in the future, but it is not set for all users
+ unique_dict = {obj.email: obj for obj in combined_queryset}
+ return list(unique_dict.values())
+
+
+def generate_export_response(cs_users: List[User]) -> HttpResponse:
response = HttpResponse(content_type="text/csv")
response[
"Content-Disposition"
@@ -71,7 +100,7 @@ def generate_export_response(cs_users: List[User], role="Lernende") -> HttpRespo
cs_user.language,
cs_user.email,
cs_user.additional_json_data.get("Geburtsdatum", ""),
- role,
+ cs_user.edoniq_role,
cs_user.additional_json_data.get("Firmenname", ""),
cs_user.additional_json_data.get("Lehrvertragsnummer", ""),
cs_user.coursesessionuser_set.first().course_session.import_id,
diff --git a/server/vbv_lernwelt/importer/services.py b/server/vbv_lernwelt/importer/services.py
index 30b35e9a..2cd64419 100644
--- a/server/vbv_lernwelt/importer/services.py
+++ b/server/vbv_lernwelt/importer/services.py
@@ -185,6 +185,7 @@ def create_or_update_user(
last_name: str = "",
sso_id: str = None,
contract_number: str = "",
+ date_of_birth: str = "",
):
logger.debug(
"create_or_update_user",
@@ -200,9 +201,13 @@ def create_or_update_user(
if user_qs.exists():
user = user_qs.first()
+ # use the ID from DBPLAP2 (Lehrvertragsnummer, firstname, lastname, date of birth)
if not user and contract_number:
user_qs = User.objects.filter(
- additional_json_data__Lehrvertragsnummer=contract_number
+ first_name=first_name,
+ last_name=last_name,
+ additional_json_data__Lehrvertragsnummer=contract_number,
+ additional_json_data__Geburtsdatum=date_of_birth,
)
if user_qs.exists():
user = user_qs.first()
@@ -502,6 +507,8 @@ def import_students_from_excel(filename: str):
"Name",
"Sprache",
"Durchführungen",
+ "Lehrvertragsnummer",
+ "Geburtsdatum",
],
)
create_or_update_student(data)
@@ -514,11 +521,14 @@ def create_or_update_student(data: Dict[str, Any]):
label="import",
)
+ date_of_birth = _get_date_of_birth(data)
+
user = create_or_update_user(
email=data["Email"].lower(),
first_name=data["Vorname"],
last_name=data["Name"],
contract_number=data.get("Lehrvertragsnummer", ""),
+ date_of_birth=date_of_birth,
)
user.language = data["Sprache"]
@@ -535,6 +545,16 @@ def create_or_update_student(data: Dict[str, Any]):
csu.save()
+def _get_date_of_birth(data: Dict[str, Any]) -> str:
+ date_of_birth = data.get("Geburtsdatum", None)
+ if date_of_birth is None:
+ return ""
+ elif date_of_birth is date or date_of_birth is datetime:
+ return date_of_birth.strftime("%d.%m.%Y")
+ elif type(date_of_birth) is str:
+ return date_of_birth
+
+
def sync_students_from_t2l_excel(filename: str):
workbook = load_workbook(filename=filename)
sheet = workbook.active
@@ -546,10 +566,13 @@ def sync_students_from_t2l_excel(filename: str):
def sync_students_from_t2l(data):
- # ignore errors
+ date_of_birth = _get_date_of_birth(data)
try:
user = User.objects.get(
- additional_json_data__Lehrvertragsnummer=data["Lehrvertragsnummer"]
+ first_name=data["Vorname"],
+ last_name=data["Name"],
+ additional_json_data__Lehrvertragsnummer=data["Lehrvertragsnummer"],
+ additional_json_data__Geburtsdatum=date_of_birth,
)
except User.DoesNotExist:
return
diff --git a/server/vbv_lernwelt/importer/tests/Schulungen_Teilnehmende.xlsx b/server/vbv_lernwelt/importer/tests/Schulungen_Teilnehmende.xlsx
index 743518fa..b79f00e0 100644
Binary files a/server/vbv_lernwelt/importer/tests/Schulungen_Teilnehmende.xlsx and b/server/vbv_lernwelt/importer/tests/Schulungen_Teilnehmende.xlsx differ
diff --git a/server/vbv_lernwelt/importer/tests/__init__.py b/server/vbv_lernwelt/importer/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/server/vbv_lernwelt/importer/tests/test_import_students.py b/server/vbv_lernwelt/importer/tests/test_import_students.py
index e9597c25..d771d89d 100644
--- a/server/vbv_lernwelt/importer/tests/test_import_students.py
+++ b/server/vbv_lernwelt/importer/tests/test_import_students.py
@@ -51,6 +51,7 @@ class CreateOrUpdateStudentTestCase(TestCase):
"Durchführungen": "DE 2023 A",
"Lehrvertragsnummer": "1234",
"Tel. Privat": "079 593 83 43",
+ "Geburtsdatum": "01.01.2000",
}
def test_create_student(self):
diff --git a/server/vbv_lernwelt/importer/tests/test_t2l_sync.py b/server/vbv_lernwelt/importer/tests/test_t2l_sync.py
index cc889a80..c800a52e 100644
--- a/server/vbv_lernwelt/importer/tests/test_t2l_sync.py
+++ b/server/vbv_lernwelt/importer/tests/test_t2l_sync.py
@@ -32,6 +32,7 @@ class SyncT2lTestCase(TestCase):
"Durchführungen": "DE 2023 A",
"Lehrvertragsnummer": "1234",
"Tel. Privat": "079 593 83 43",
+ "Geburtsdatum": "01.01.2000",
}
create_or_update_student(self.user_dict)
@@ -44,6 +45,7 @@ class SyncT2lTestCase(TestCase):
"Durchführungen": "DE 2023 A",
"Lehrvertragsnummer": "1234",
"Tel. Privat": "079 593 83 65",
+ "Geburtsdatum": "01.01.2000",
}
sync_students_from_t2l(user_dict)
@@ -65,6 +67,7 @@ class SyncT2lTestCase(TestCase):
"Lehrvertragsnummer": "1234",
"Tel. Privat": "079 593 83 43",
"Firma": "VBV",
+ "Geburtsdatum": "01.01.2000",
}
sync_students_from_t2l(user_dict)
@@ -84,6 +87,7 @@ class SyncT2lTestCase(TestCase):
"Durchführungen": "DE 2023 B",
"Lehrvertragsnummer": "1234",
"Tel. Privat": "079 593 83 43",
+ "Geburtsdatum": "01.01.2000",
}
sync_students_from_t2l(user_dict)
diff --git a/server/vbv_lernwelt/templates/admin/index.html b/server/vbv_lernwelt/templates/admin/index.html
index ffdf0dc3..564c0c92 100644
--- a/server/vbv_lernwelt/templates/admin/index.html
+++ b/server/vbv_lernwelt/templates/admin/index.html
@@ -31,9 +31,13 @@
Export Edoniq Teilnehmer
Teilnehmer exportieren
- Export Edoniq Trainer
+ Export Edoniq Trainer
Trainer exportieren
+ Export Edoniq Teilnehmer und Trainer
+ Teilnehmer und Trainer exportieren
+
+
Reset