+
diff --git a/client/src/services/circle.ts b/client/src/services/circle.ts
index 2ee177aa..ddb4962e 100644
--- a/client/src/services/circle.ts
+++ b/client/src/services/circle.ts
@@ -43,10 +43,24 @@ export function someFinishedInLearningSequence(ls: LearningSequence) {
});
}
+/**
+ * Completed is defined as having completed all learning contents, ranked at
+ * least one performance criteria (but not necessarily all) as success or fail.
+ */
export function allFinishedInLearningSequence(ls: LearningSequence) {
- return learningSequenceFlatChildren(ls).every((lc) => {
- return lc.completion_status === "SUCCESS";
- });
+ const allLearningContentsCompleted = ls.learning_units
+ .flatMap((lu) => lu.learning_contents)
+ .every((lc) => lc.completion_status === "SUCCESS");
+
+ const performanceCriteria = ls.learning_units.flatMap(
+ (lu) => lu.performance_criteria
+ );
+
+ const somePerformanceCriteriaRanked =
+ performanceCriteriaHasStatus(performanceCriteria) ||
+ performanceCriteria.length === 0; // -> treat as completed
+
+ return allLearningContentsCompleted && somePerformanceCriteriaRanked;
}
export function performanceCriteriaStatusCount(
diff --git a/env_secrets/local_chrigu.env b/env_secrets/local_chrigu.env
index ddbca2d5..431043ff 100644
Binary files a/env_secrets/local_chrigu.env and b/env_secrets/local_chrigu.env differ
diff --git a/server/vbv_lernwelt/assignment/services.py b/server/vbv_lernwelt/assignment/services.py
index 7460624d..94a00b49 100644
--- a/server/vbv_lernwelt/assignment/services.py
+++ b/server/vbv_lernwelt/assignment/services.py
@@ -9,6 +9,7 @@ from vbv_lernwelt.assignment.models import (
AssignmentCompletion,
AssignmentCompletionAuditLog,
AssignmentCompletionStatus,
+ AssignmentType,
is_valid_assignment_completion_status,
)
from vbv_lernwelt.core.models import User
@@ -208,10 +209,14 @@ def update_assignment_completion(
ac.save()
- if completion_status in [
- AssignmentCompletionStatus.EVALUATION_SUBMITTED,
- AssignmentCompletionStatus.SUBMITTED,
- ]:
+ if (
+ completion_status
+ in [
+ AssignmentCompletionStatus.EVALUATION_SUBMITTED,
+ AssignmentCompletionStatus.SUBMITTED,
+ ]
+ and assignment.assignment_type != AssignmentType.EDONIQ_TEST.value
+ ):
acl = AssignmentCompletionAuditLog.objects.create(
assignment_user=assignment_user,
assignment=assignment,
diff --git a/server/vbv_lernwelt/course/consts.py b/server/vbv_lernwelt/course/consts.py
index 831d5987..a0dd7b27 100644
--- a/server/vbv_lernwelt/course/consts.py
+++ b/server/vbv_lernwelt/course/consts.py
@@ -1,3 +1,4 @@
+# Course IDs
COURSE_TEST_ID = -1
COURSE_UK = -3
COURSE_VERSICHERUNGSVERMITTLERIN_ID = -4
diff --git a/server/vbv_lernwelt/course/creators/test_utils.py b/server/vbv_lernwelt/course/creators/test_utils.py
index fe61b8fb..d5c65682 100644
--- a/server/vbv_lernwelt/course/creators/test_utils.py
+++ b/server/vbv_lernwelt/course/creators/test_utils.py
@@ -88,9 +88,10 @@ def create_user(username: str) -> User:
def create_course_session(
- course: Course, title: str, generation: str = "2023"
+ course: Course, title: str, generation: str = "2023", _id=None
) -> CourseSession:
return CourseSession.objects.create(
+ id=_id,
course=course,
title=title,
import_id=title,
diff --git a/server/vbv_lernwelt/feedback/services.py b/server/vbv_lernwelt/feedback/services.py
index cd597e4e..b593992a 100644
--- a/server/vbv_lernwelt/feedback/services.py
+++ b/server/vbv_lernwelt/feedback/services.py
@@ -185,7 +185,7 @@ def export_feedback(course_session_ids: list[str], save_as_file: bool):
def _create_sheet(wb: Workbook, title: str, data: list[FeedbackResponse]):
- sheet = wb.create_sheet(title=title)
+ sheet = wb.create_sheet(title=_sanitize_sheet_name(title))
if len(data) == 0:
return sheet
@@ -208,6 +208,24 @@ def _create_sheet(wb: Workbook, title: str, data: list[FeedbackResponse]):
return sheet
+def _sanitize_sheet_name(text, default_name="DefaultSheet"):
+ if text is None:
+ return default_name
+
+ prohibited_chars = ["\\", "/", "*", "?", ":", "[", "]"]
+ for char in prohibited_chars:
+ text = text.replace(char, "")
+
+ text = text.strip("'")
+
+ text = text[:31]
+
+ if len(text) == 0:
+ return default_name
+
+ return text
+
+
def _add_rows(sheet, data, question_data):
for row_idx, feedback in enumerate(data, start=2):
sheet.cell(row=row_idx, column=1, value=feedback.course_session.title)
diff --git a/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py b/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py
index 5850ea11..c18f7e6c 100644
--- a/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py
+++ b/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py
@@ -35,7 +35,13 @@ class DatatransWebhookTestCase(APITestCase):
_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
)
- create_course_session(course=course, title="Versicherungsvermittler/-in DE")
+ create_course_session(
+ course=course,
+ title="Versicherungsvermittler/-in DE",
+ # MUST be 1 -> this is the correct
+ # VV DE course session ID in production
+ _id=1,
+ )
self.user = User.objects.create_user(
username="testuser",
@@ -145,14 +151,21 @@ class DatatransWebhookTestCase(APITestCase):
CourseSessionUser.objects.count(),
)
+ csu = CourseSessionUser.objects.first()
+
self.assertEqual(
self.user,
- CourseSessionUser.objects.first().user,
+ csu.user,
+ )
+
+ self.assertEqual(
+ 1,
+ csu.course_session.id,
)
self.assertEqual(
COURSE_VERSICHERUNGSVERMITTLERIN_ID,
- CourseSessionUser.objects.first().course_session.course.id,
+ csu.course_session.course.id,
)
self.assertEqual(
diff --git a/server/vbv_lernwelt/shop/views.py b/server/vbv_lernwelt/shop/views.py
index 3f5e4a97..06672826 100644
--- a/server/vbv_lernwelt/shop/views.py
+++ b/server/vbv_lernwelt/shop/views.py
@@ -8,11 +8,6 @@ from rest_framework.response import Response
from sentry_sdk import capture_exception
from vbv_lernwelt.core.models import Country, User
-from vbv_lernwelt.course.consts import (
- COURSE_VERSICHERUNGSVERMITTLERIN_FR_ID,
- COURSE_VERSICHERUNGSVERMITTLERIN_ID,
- COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID,
-)
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email
from vbv_lernwelt.shop.const import (
@@ -37,10 +32,11 @@ from vbv_lernwelt.shop.services import (
logger = structlog.get_logger(__name__)
-PRODUCT_SKU_TO_COURSE = {
- VV_DE_PRODUCT_SKU: COURSE_VERSICHERUNGSVERMITTLERIN_ID,
- VV_FR_PRODUCT_SKU: COURSE_VERSICHERUNGSVERMITTLERIN_FR_ID,
- VV_IT_PRODUCT_SKU: COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID,
+PRODUCT_SKU_TO_COURSE_SESSION_ID = {
+ # CourseSession IDs PROD/STAGING
+ VV_DE_PRODUCT_SKU: 1, # vv-de
+ VV_FR_PRODUCT_SKU: 2, # vv-fr
+ VV_IT_PRODUCT_SKU: 3, # vv-it
}
@@ -229,9 +225,9 @@ def create_vv_course_session_user(checkout_info: CheckoutInformation):
_, created = CourseSessionUser.objects.get_or_create(
user=checkout_info.user,
role=CourseSessionUser.Role.MEMBER,
- course_session=CourseSession.objects.filter(
- course_id=PRODUCT_SKU_TO_COURSE[checkout_info.product_sku]
- ).first(),
+ course_session=CourseSession.objects.get(
+ id=PRODUCT_SKU_TO_COURSE_SESSION_ID[checkout_info.product_sku]
+ ),
)
if created: