Merged develop into feature/VBV-650-dont-log-duplicates
This commit is contained in:
commit
a723b88277
|
|
@ -41,7 +41,6 @@ const someFinished = computed(() => {
|
||||||
if (props.learningSequence) {
|
if (props.learningSequence) {
|
||||||
return someFinishedInLearningSequence(props.learningSequence);
|
return someFinishedInLearningSequence(props.learningSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -235,7 +234,11 @@ type LearninContentWithCompetenceCertificate =
|
||||||
: 'no-status'
|
: 'no-status'
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<CompletionStatus />
|
<CompletionStatus
|
||||||
|
:completed="
|
||||||
|
performanceCriteriaHasStatus(learningUnit.performance_criteria)
|
||||||
|
"
|
||||||
|
/>
|
||||||
{{ $t("a.Selbsteinschätzung") }}
|
{{ $t("a.Selbsteinschätzung") }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@ const props = defineProps<{
|
||||||
content: LearningContent;
|
content: LearningContent;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LearningContentSimpleLayout :learning-content="props.content">
|
<LearningContentSimpleLayout :learning-content="props.content">
|
||||||
<div class="h-screen">
|
<div class="h-[calc(100vh-222px)] md:h-[calc(100vh-238px)]">
|
||||||
<iframe width="100%" height="100%" :src="props.content.content_url" />
|
<iframe width="100%" height="100%" :src="props.content.content_url" />
|
||||||
</div>
|
</div>
|
||||||
</LearningContentSimpleLayout>
|
</LearningContentSimpleLayout>
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
export function allFinishedInLearningSequence(ls: LearningSequence) {
|
||||||
return learningSequenceFlatChildren(ls).every((lc) => {
|
const allLearningContentsCompleted = ls.learning_units
|
||||||
return lc.completion_status === "SUCCESS";
|
.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(
|
export function performanceCriteriaStatusCount(
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# Course IDs
|
||||||
COURSE_TEST_ID = -1
|
COURSE_TEST_ID = -1
|
||||||
COURSE_UK = -3
|
COURSE_UK = -3
|
||||||
COURSE_VERSICHERUNGSVERMITTLERIN_ID = -4
|
COURSE_VERSICHERUNGSVERMITTLERIN_ID = -4
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,10 @@ def create_user(username: str) -> User:
|
||||||
|
|
||||||
|
|
||||||
def create_course_session(
|
def create_course_session(
|
||||||
course: Course, title: str, generation: str = "2023"
|
course: Course, title: str, generation: str = "2023", _id=None
|
||||||
) -> CourseSession:
|
) -> CourseSession:
|
||||||
return CourseSession.objects.create(
|
return CourseSession.objects.create(
|
||||||
|
id=_id,
|
||||||
course=course,
|
course=course,
|
||||||
title=title,
|
title=title,
|
||||||
import_id=title,
|
import_id=title,
|
||||||
|
|
|
||||||
|
|
@ -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]):
|
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:
|
if len(data) == 0:
|
||||||
return sheet
|
return sheet
|
||||||
|
|
@ -208,6 +208,24 @@ def _create_sheet(wb: Workbook, title: str, data: list[FeedbackResponse]):
|
||||||
return sheet
|
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):
|
def _add_rows(sheet, data, question_data):
|
||||||
for row_idx, feedback in enumerate(data, start=2):
|
for row_idx, feedback in enumerate(data, start=2):
|
||||||
sheet.cell(row=row_idx, column=1, value=feedback.course_session.title)
|
sheet.cell(row=row_idx, column=1, value=feedback.course_session.title)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,13 @@ class DatatransWebhookTestCase(APITestCase):
|
||||||
_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
_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(
|
self.user = User.objects.create_user(
|
||||||
username="testuser",
|
username="testuser",
|
||||||
|
|
@ -145,14 +151,21 @@ class DatatransWebhookTestCase(APITestCase):
|
||||||
CourseSessionUser.objects.count(),
|
CourseSessionUser.objects.count(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
csu = CourseSessionUser.objects.first()
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.user,
|
self.user,
|
||||||
CourseSessionUser.objects.first().user,
|
csu.user,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
1,
|
||||||
|
csu.course_session.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
||||||
CourseSessionUser.objects.first().course_session.course.id,
|
csu.course_session.course.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,6 @@ from rest_framework.response import Response
|
||||||
from sentry_sdk import capture_exception
|
from sentry_sdk import capture_exception
|
||||||
|
|
||||||
from vbv_lernwelt.core.models import Country, User
|
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.course.models import CourseSession, CourseSessionUser
|
||||||
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email
|
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email
|
||||||
from vbv_lernwelt.shop.const import (
|
from vbv_lernwelt.shop.const import (
|
||||||
|
|
@ -37,10 +32,11 @@ from vbv_lernwelt.shop.services import (
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
PRODUCT_SKU_TO_COURSE = {
|
PRODUCT_SKU_TO_COURSE_SESSION_ID = {
|
||||||
VV_DE_PRODUCT_SKU: COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
# CourseSession IDs PROD/STAGING
|
||||||
VV_FR_PRODUCT_SKU: COURSE_VERSICHERUNGSVERMITTLERIN_FR_ID,
|
VV_DE_PRODUCT_SKU: 1, # vv-de
|
||||||
VV_IT_PRODUCT_SKU: COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID,
|
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(
|
_, created = CourseSessionUser.objects.get_or_create(
|
||||||
user=checkout_info.user,
|
user=checkout_info.user,
|
||||||
role=CourseSessionUser.Role.MEMBER,
|
role=CourseSessionUser.Role.MEMBER,
|
||||||
course_session=CourseSession.objects.filter(
|
course_session=CourseSession.objects.get(
|
||||||
course_id=PRODUCT_SKU_TO_COURSE[checkout_info.product_sku]
|
id=PRODUCT_SKU_TO_COURSE_SESSION_ID[checkout_info.product_sku]
|
||||||
).first(),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue