Merged in bugfix/VBV-752-ausbildungsverantwortlicher-export-fixen (pull request #396)

VBV-752: Ausbildungsverantwortlicher: Export von Personen

Approved-by: Christian Cueni
This commit is contained in:
Elia Bieri 2024-10-09 06:36:23 +00:00 committed by Christian Cueni
commit 090082efba
9 changed files with 268 additions and 136 deletions

View File

@ -7,9 +7,10 @@ import {
type DashboardPersonCourseSessionType, type DashboardPersonCourseSessionType,
exportPersons, exportPersons,
} from "@/services/dashboard"; } from "@/services/dashboard";
import { useCourseSessionsStore } from "@/stores/courseSessions";
import { useUserStore } from "@/stores/user"; import { useUserStore } from "@/stores/user";
import type { DashboardPersonsPageMode, StatisticsFilterItem } from "@/types"; import type { DashboardPersonsPageMode } from "@/types";
import { exportDataAsXls } from "@/utils/export"; import { openDataAsXls } from "@/utils/export";
import { useRouteQuery } from "@vueuse/router"; import { useRouteQuery } from "@vueuse/router";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { useTranslation } from "i18next-vue"; import { useTranslation } from "i18next-vue";
@ -39,6 +40,7 @@ const userStore = useUserStore();
const { loading, dashboardPersons } = useDashboardPersonsDueDates(props.mode); const { loading, dashboardPersons } = useDashboardPersonsDueDates(props.mode);
const { CHOSEN_PROFILE_TO_NAME } = useChosenProfileMapping(); const { CHOSEN_PROFILE_TO_NAME } = useChosenProfileMapping();
const { allCourseSessionActions } = useCourseSessionsStore();
const courses = computed(() => { const courses = computed(() => {
return [ return [
@ -300,9 +302,34 @@ const filtersVisible = computed(() => {
); );
}); });
const canExport = computed(() => {
// If user is only member, he can't export
// member = has is_member property, but not is_expert or is_supervisor
if (!allCourseSessionActions.has("is_member")) {
// is berufsbildner or expert or supervisor
return true;
}
if (
allCourseSessionActions.has("is_expert") ||
allCourseSessionActions.has("is_supervisor")
) {
// is member
return true;
}
return false;
});
function personRoleDisplayValue(personCourseSession: DashboardPersonCourseSessionType) { function personRoleDisplayValue(personCourseSession: DashboardPersonCourseSessionType) {
if ( if (
["SUPERVISOR", "EXPERT", "LEARNING_MENTOR"].includes(personCourseSession.user_role) [
"SUPERVISOR",
"EXPERT",
"LEARNING_MENTOR",
"BERUFSBILDNER",
"LEARNING_MENTOR",
].includes(personCourseSession.user_role)
) { ) {
return personCourseSession.user_role_display; return personCourseSession.user_role_display;
} }
@ -310,31 +337,12 @@ function personRoleDisplayValue(personCourseSession: DashboardPersonCourseSessio
return ""; return "";
} }
function exportData() { async function exportData() {
const courseSessionIdsSet = new Set<string>(); const requestData = {
// get all course session ids from users courseSessionUserIds: filteredPersons.value.map((person) => person.csu_id),
if (selectedSession.value.id === UNFILTERED) { };
for (const person of filteredPersons.value) { const data = await exportPersons(requestData, userStore.language);
for (const courseSession of person.course_sessions) { openDataAsXls(data.encoded_data, data.file_name);
courseSessionIdsSet.add(courseSession.id);
}
}
} else {
courseSessionIdsSet.add(selectedSession.value.id);
}
// construct StatisticsFilterItems for export call
const items: StatisticsFilterItem[] = [];
for (const csId of courseSessionIdsSet) {
items.push({
_id: "",
course_session_id: csId,
generation: "",
circle_id: "",
region: "",
});
}
exportDataAsXls(items, exportPersons, userStore.language);
} }
watch(selectedCourse, () => { watch(selectedCourse, () => {
@ -366,7 +374,7 @@ watch(selectedRegion, () => {
<div class="mb-10 flex items-center justify-between"> <div class="mb-10 flex items-center justify-between">
<h2 class="my-4">{{ $t("a.Personen") }}</h2> <h2 class="my-4">{{ $t("a.Personen") }}</h2>
<button <button
v-if="userStore.course_session_experts.length > 0" v-if="canExport"
class="flex" class="flex"
data-cy="export-button" data-cy="export-button"
@click="exportData" @click="exportData"

View File

@ -20,6 +20,7 @@ import type {
DueDate, DueDate,
XlsExportRequestData, XlsExportRequestData,
XlsExportResponseData, XlsExportResponseData,
XlsPersonExportRequestData,
} from "@/types"; } from "@/types";
export type DashboardPersonRoleType = export type DashboardPersonRoleType =
@ -79,6 +80,7 @@ export type DashboardPersonType = {
avatar_url: string; avatar_url: string;
avatar_url_small: string; avatar_url_small: string;
chosen_profile: string; chosen_profile: string;
csu_id: string;
competence_metrics?: { competence_metrics?: {
passed_count: number; passed_count: number;
failed_count: number; failed_count: number;
@ -273,7 +275,7 @@ export async function exportCompetenceElements(
} }
export async function exportPersons( export async function exportPersons(
data: XlsExportRequestData, data: XlsPersonExportRequestData,
language: string language: string
): Promise<XlsExportResponseData> { ): Promise<XlsExportResponseData> {
return await itPost("/api/dashboard/export/persons/", data, { return await itPost("/api/dashboard/export/persons/", data, {

View File

@ -129,6 +129,18 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
return Boolean(hasPreview && (inLearningPath() || inCompetenceProfile())); return Boolean(hasPreview && (inLearningPath() || inCompetenceProfile()));
}); });
const allCourseSessionActions = computed(() => {
const actionsSet = new Set();
allCourseSessions.value.forEach((item) => {
item.actions.forEach((action) => {
actionsSet.add(action);
});
});
return actionsSet;
});
return { return {
uniqueCourseSessionsByCourse, uniqueCourseSessionsByCourse,
allCurrentCourseSessions, allCurrentCourseSessions,
@ -146,5 +158,6 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
// only used for unit testing // only used for unit testing
allCourseSessions, allCourseSessions,
allCourseSessionActions,
}; };
}); });

View File

@ -643,6 +643,10 @@ export interface XlsExportRequestData {
circleIds: number[]; circleIds: number[];
} }
export interface XlsPersonExportRequestData {
courseSessionUserIds: string[];
}
export interface XlsExportResponseData { export interface XlsExportResponseData {
encoded_data: string; encoded_data: string;
file_name: string; file_name: string;

View File

@ -35,6 +35,7 @@ from vbv_lernwelt.competence.factories import (
) )
from vbv_lernwelt.competence.models import ActionCompetence from vbv_lernwelt.competence.models import ActionCompetence
from vbv_lernwelt.core.constants import ( from vbv_lernwelt.core.constants import (
TEST_AUSBILDUNGSVERANTWORTLICHER1_USER_ID,
TEST_BERUFSBILDNER1_USER_ID, TEST_BERUFSBILDNER1_USER_ID,
TEST_COURSE_SESSION_BERN_ID, TEST_COURSE_SESSION_BERN_ID,
TEST_COURSE_SESSION_ZURICH_ID, TEST_COURSE_SESSION_ZURICH_ID,
@ -385,6 +386,31 @@ def create_test_course(
), ),
role="BERUFSBILDNER", role="BERUFSBILDNER",
) )
# Add Ausbildungsverantwortlicher
AgentParticipantRelation.objects.create(
agent=User.objects.get(id=TEST_AUSBILDUNGSVERANTWORTLICHER1_USER_ID),
participant=CourseSessionUser.objects.get(
user__id=TEST_STUDENT1_USER_ID,
course_session=cs_bern,
),
role="LEARNING_MENTOR",
)
AgentParticipantRelation.objects.create(
agent=User.objects.get(id=TEST_AUSBILDUNGSVERANTWORTLICHER1_USER_ID),
participant=CourseSessionUser.objects.get(
user__id=TEST_STUDENT2_USER_ID,
course_session=cs_zurich,
),
role="LEARNING_MENTOR",
)
AgentParticipantRelation.objects.create(
agent=User.objects.get(id=TEST_AUSBILDUNGSVERANTWORTLICHER1_USER_ID),
participant=CourseSessionUser.objects.get(
user__id=TEST_STUDENT3_USER_ID,
course_session=cs_bern,
),
role="LEARNING_MENTOR",
)
return course return course

View File

@ -5,14 +5,12 @@ import structlog
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from openpyxl import Workbook from openpyxl import Workbook
from vbv_lernwelt.core.models import User from vbv_lernwelt.course.models import CourseSessionUser
from vbv_lernwelt.course.models import CourseSession
from vbv_lernwelt.course_session.services.export_attendance import ( from vbv_lernwelt.course_session.services.export_attendance import (
add_user_headers, add_user_headers,
make_export_filename, make_export_filename,
sanitize_sheet_name,
) )
from vbv_lernwelt.dashboard.utils import create_person_list_with_roles from vbv_lernwelt.dashboard.utils import create_csu_dict
PERSONS_EXPORT_FILENAME = _("export_personen") PERSONS_EXPORT_FILENAME = _("export_personen")
@ -20,28 +18,22 @@ logger = structlog.get_logger(__name__)
def export_persons( def export_persons(
user: User, course_session_users: list[CourseSessionUser],
course_session_ids: list[str],
save_as_file: bool = False, save_as_file: bool = False,
) -> Optional[bytes]: ) -> Optional[bytes]:
if not course_session_ids: if not course_session_users:
return return
wb = Workbook() wb = Workbook()
# remove the first sheet is just easier than keeping track of the active sheet # remove the first sheet is just easier than keeping track of the active sheet
wb.remove(wb.active) wb.remove(wb.active)
csu_data = [
user_with_roles = create_person_list_with_roles( create_csu_dict(csu, include_private_data=True) for csu in course_session_users
user, course_session_ids, include_private_data=True ]
) csu_data.sort(key=lambda x: x["last_name"])
course_sessions = CourseSession.objects.filter(id__in=course_session_ids)
for cs in course_sessions:
_create_sheet( _create_sheet(
wb, wb,
cs.title, csu_data,
cs.id,
user_with_roles,
) )
if save_as_file: if save_as_file:
@ -56,13 +48,11 @@ def export_persons(
def _create_sheet( def _create_sheet(
wb: Workbook, wb: Workbook,
title: str, course_session_user_data: list[dict],
cs_id: int,
user_with_roles,
): ):
sheet = wb.create_sheet(title=sanitize_sheet_name(title)) sheet = wb.create_sheet()
if len(user_with_roles) == 0: if len(course_session_user_data) == 0:
return sheet return sheet
# headers # headers
@ -71,7 +61,7 @@ def _create_sheet(
sheet.cell(row=1, column=col_idx, value=str(_("Telefon"))) sheet.cell(row=1, column=col_idx, value=str(_("Telefon")))
sheet.cell(row=1, column=col_idx + 1, value=str(_("Rolle"))) sheet.cell(row=1, column=col_idx + 1, value=str(_("Rolle")))
_add_rows(sheet, user_with_roles, cs_id) _add_rows(sheet, course_session_user_data)
return sheet return sheet
@ -79,27 +69,11 @@ def _create_sheet(
def _add_rows( def _add_rows(
sheet, sheet,
users, users,
course_session_id,
): ):
idx_offset = 0 idx_offset = 0
for row_idx, user in enumerate(users, start=2): for row_idx, user in enumerate(users, start=2):
user_role = _role_as_string(user.get("role"))
def get_user_cs_by_id(user_cs, cs_id):
return next((cs for cs in user_cs if int(cs.get("id")) == cs_id), None)
user_cs = get_user_cs_by_id(user["course_sessions"], course_session_id)
if not user_cs:
logger.warning(
"User not found in course session",
user_id=user["user_id"],
course_session_id=course_session_id,
)
idx_offset += 1
continue
user_role = _role_as_string(user_cs.get("user_role"))
idx = row_idx - idx_offset idx = row_idx - idx_offset
sheet.cell(row=idx, column=1, value=user["first_name"]) sheet.cell(row=idx, column=1, value=user["first_name"])

View File

@ -4,6 +4,7 @@ from django.utils.translation import activate
from openpyxl import load_workbook from openpyxl import load_workbook
from vbv_lernwelt.core.constants import ( from vbv_lernwelt.core.constants import (
TEST_AUSBILDUNGSVERANTWORTLICHER1_USER_ID,
TEST_STUDENT1_USER_ID, TEST_STUDENT1_USER_ID,
TEST_STUDENT2_USER_ID, TEST_STUDENT2_USER_ID,
TEST_STUDENT3_USER_ID, TEST_STUDENT3_USER_ID,
@ -13,9 +14,9 @@ from vbv_lernwelt.core.constants import (
from vbv_lernwelt.core.create_default_users import create_default_users from vbv_lernwelt.core.create_default_users import create_default_users
from vbv_lernwelt.core.models import User from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.creators.test_course import create_test_course from vbv_lernwelt.course.creators.test_course import create_test_course
from vbv_lernwelt.course.models import CourseSession from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
from vbv_lernwelt.course_session.tests.test_attendance_export import ExportBaseTestCase from vbv_lernwelt.course_session.tests.test_attendance_export import ExportBaseTestCase
from vbv_lernwelt.dashboard.person_export import export_persons from vbv_lernwelt.dashboard.views import _export_persons_as_xls_data
from vbv_lernwelt.learnpath.models import Circle from vbv_lernwelt.learnpath.models import Circle
@ -26,6 +27,8 @@ class PersonsExportTestCase(ExportBaseTestCase):
create_default_users() create_default_users()
create_test_course(include_vv=False, with_sessions=True) create_test_course(include_vv=False, with_sessions=True)
self.default_sheet_name = "Sheet"
self.course_session_be = CourseSession.objects.get(title="Test Bern 2022 a") self.course_session_be = CourseSession.objects.get(title="Test Bern 2022 a")
self.course_session_zh = CourseSession.objects.get(title="Test Zürich 2022 a") self.course_session_zh = CourseSession.objects.get(title="Test Zürich 2022 a")
@ -36,10 +39,32 @@ class PersonsExportTestCase(ExportBaseTestCase):
self.test_trainer1 = User.objects.get(id=TEST_TRAINER1_USER_ID) self.test_trainer1 = User.objects.get(id=TEST_TRAINER1_USER_ID)
self.test_trainer2 = User.objects.get(id=TEST_TRAINER2_USER_ID) self.test_trainer2 = User.objects.get(id=TEST_TRAINER2_USER_ID)
self.test_ausbildungsverantwortlicher1 = User.objects.get(
id=TEST_AUSBILDUNGSVERANTWORTLICHER1_USER_ID
)
self.test_student1 = User.objects.get(id=TEST_STUDENT1_USER_ID) self.test_student1 = User.objects.get(id=TEST_STUDENT1_USER_ID)
self.test_student2 = User.objects.get(id=TEST_STUDENT2_USER_ID) self.test_student2 = User.objects.get(id=TEST_STUDENT2_USER_ID)
self.test_student3 = User.objects.get(id=TEST_STUDENT3_USER_ID) self.test_student3 = User.objects.get(id=TEST_STUDENT3_USER_ID)
self.test_student1_csu_be = CourseSessionUser.objects.get(
user=self.test_student1, course_session=self.course_session_be
)
self.test_student2_csu_be = CourseSessionUser.objects.get(
user=self.test_student2, course_session=self.course_session_be
)
self.test_student2_csu_zh = CourseSessionUser.objects.get(
user=self.test_student2, course_session=self.course_session_zh
)
self.test_student3_csu_be = CourseSessionUser.objects.get(
user=self.test_student3, course_session=self.course_session_be
)
self.test_trainer1_csu_be = CourseSessionUser.objects.get(
user=self.test_trainer1, course_session=self.course_session_be
)
self.test_trainer2_csu_zh = CourseSessionUser.objects.get(
user=self.test_trainer2, course_session=self.course_session_zh
)
self.test_student1_row = [ self.test_student1_row = [
self.test_student1.first_name, self.test_student1.first_name,
self.test_student1.last_name, self.test_student1.last_name,
@ -91,9 +116,9 @@ class PersonsExportTestCase(ExportBaseTestCase):
return expected_data return expected_data
def _generate_workbook(self, user, course_session_ids): def _generate_workbook(self, user, course_session_ids):
export_data = io.BytesIO( data = _export_persons_as_xls_data(user, course_session_ids)
export_persons(user, course_session_ids, save_as_file=False) self.assertIsNotNone(data)
) export_data = io.BytesIO(data) # type: ignore
return load_workbook(export_data) return load_workbook(export_data)
def _make_header(self): def _make_header(self):
@ -107,10 +132,16 @@ class PersonsExportTestCase(ExportBaseTestCase):
] ]
def test_export_persons(self): def test_export_persons(self):
wb = self._generate_workbook(self.test_trainer1, [self.course_session_be.id]) export_course_session_user_ids = [
self.test_student1_csu_be.id,
self.test_student2_csu_be.id,
self.test_student3_csu_be.id,
self.test_trainer1_csu_be.id,
]
wb = self._generate_workbook(self.test_trainer1, export_course_session_user_ids)
self.assertEqual(len(wb.sheetnames), 1) self.assertEqual(len(wb.sheetnames), 1)
self.assertEqual(wb.sheetnames[0], "Test Bern 2022 a") self.assertEqual(wb.sheetnames[0], self.default_sheet_name)
wb.active = wb["Test Bern 2022 a"] wb.active = wb[self.default_sheet_name]
data = self._generate_expected_data( data = self._generate_expected_data(
[ [
@ -120,33 +151,64 @@ class PersonsExportTestCase(ExportBaseTestCase):
self.test_trainer1_row, self.test_trainer1_row,
] ]
) )
self._check_export(wb, data, 5, 6)
self._check_export(wb, data, 4, 6) export_course_session_user_ids = [
self.test_student2_csu_zh.id,
wb = self._generate_workbook(self.test_trainer2, [self.course_session_zh.id]) self.test_trainer2_csu_zh.id,
]
wb = self._generate_workbook(self.test_trainer2, export_course_session_user_ids)
self.assertEqual(len(wb.sheetnames), 1) self.assertEqual(len(wb.sheetnames), 1)
self.assertEqual(wb.sheetnames[0], "Test Zürich 2022 a") self.assertEqual(wb.sheetnames[0], self.default_sheet_name)
wb.active = wb["Test Zürich 2022 a"] wb.active = wb[self.default_sheet_name]
data = self._generate_expected_data( data = self._generate_expected_data(
[self.test_student2_row, self.test_trainer2_row] [self.test_student2_row, self.test_trainer2_row]
) )
self._check_export(wb, data, 3, 6) self._check_export(wb, data, 3, 6)
def test_cannot_export_other_session(self): def test_can_only_export_with_role(self):
wb = self._generate_workbook(self.test_trainer1, [self.course_session_zh.id]) csu = [
self.test_student1_csu_be.id,
self.test_student2_csu_be.id,
self.test_student3_csu_be.id,
self.test_student2_csu_zh.id,
]
wb = self._generate_workbook(self.test_trainer2, csu)
self.assertEqual(len(wb.sheetnames), 1) self.assertEqual(len(wb.sheetnames), 1)
self.assertEqual(wb.sheetnames[0], "Test Zürich 2022 a") self.assertEqual(wb.sheetnames[0], self.default_sheet_name)
wb.active = wb["Test Zürich 2022 a"] wb.active = wb[self.default_sheet_name]
self._check_export(wb, [[None] * 6], 1, 6) data = self._generate_expected_data([self.test_student2_row])
self._check_export(wb, data, 1, 6)
def test_can_only_export_with_agent_participant_relation(self):
csu = [
self.test_student1_csu_be.id,
self.test_student2_csu_be.id,
self.test_student3_csu_be.id,
self.test_student2_csu_zh.id,
]
wb = self._generate_workbook(self.test_ausbildungsverantwortlicher1, csu)
self.assertEqual(len(wb.sheetnames), 1)
self.assertEqual(wb.sheetnames[0], self.default_sheet_name)
wb.active = wb[self.default_sheet_name]
data = self._generate_expected_data([self.test_student2_row])
self._check_export(wb, data, 1, 6)
def test_export_in_fr(self): def test_export_in_fr(self):
activate("fr") activate("fr")
wb = self._generate_workbook(self.test_trainer1, [self.course_session_be.id]) export_course_session_user_ids = [
self.test_student1_csu_be.id,
self.test_student2_csu_be.id,
self.test_student3_csu_be.id,
self.test_trainer1_csu_be.id,
]
wb = self._generate_workbook(self.test_trainer1, export_course_session_user_ids)
self.assertEqual(len(wb.sheetnames), 1) self.assertEqual(len(wb.sheetnames), 1)
self.assertEqual(wb.sheetnames[0], "Test Bern 2022 a") self.assertEqual(wb.sheetnames[0], self.default_sheet_name)
wb.active = wb["Test Bern 2022 a"] wb.active = wb[self.default_sheet_name]
header = [ header = [
"Prénom", "Prénom",
@ -165,10 +227,16 @@ class PersonsExportTestCase(ExportBaseTestCase):
def test_export_in_it(self): def test_export_in_it(self):
activate("it") activate("it")
wb = self._generate_workbook(self.test_trainer1, [self.course_session_be.id]) export_course_session_user_ids = [
self.test_student1_csu_be.id,
self.test_student2_csu_be.id,
self.test_student3_csu_be.id,
self.test_trainer1_csu_be.id,
]
wb = self._generate_workbook(self.test_trainer1, export_course_session_user_ids)
self.assertEqual(len(wb.sheetnames), 1) self.assertEqual(len(wb.sheetnames), 1)
self.assertEqual(wb.sheetnames[0], "Test Bern 2022 a") self.assertEqual(wb.sheetnames[0], self.default_sheet_name)
wb.active = wb["Test Bern 2022 a"] wb.active = wb[self.default_sheet_name]
header = [ header = [
"Nome", "Nome",

View File

@ -95,20 +95,20 @@ def create_course_session_dict(course_session_object, my_role, user_role):
} }
def create_person_list_with_roles( def create_csu_dict(csu: CourseSessionUser, include_private_data=False):
user, course_session_ids=None, include_private_data=False user_data = create_user_dict(csu.user, include_private_data)
): user_data["csu_id"] = csu.id
def create_csu_dict(csu: CourseSessionUser):
user_data = create_user_dict(csu.user)
user_data["chosen_profile"] = ( user_data["chosen_profile"] = (
csu.chosen_profile.code if csu.chosen_profile else "all" csu.chosen_profile.code if csu.chosen_profile else "all"
) )
user_data["paid_datetime"] = ( user_data["paid_datetime"] = (
csu.paid_datetime.isoformat() if csu.paid_datetime else None csu.paid_datetime.isoformat() if csu.paid_datetime else None
) )
user_data["role"] = csu.role
return user_data return user_data
def create_user_dict(user_object: User):
def create_user_dict(user_object: User, include_private_data=False):
user_data = { user_data = {
"user_id": user_object.id, "user_id": user_object.id,
"first_name": user_object.first_name, "first_name": user_object.first_name,
@ -123,9 +123,12 @@ def create_person_list_with_roles(
user_data["Lehrvertragsnummer"] = user_object.additional_json_data.get( user_data["Lehrvertragsnummer"] = user_object.additional_json_data.get(
"Lehrvertragsnummer", "" "Lehrvertragsnummer", ""
) )
return user_data return user_data
def create_person_list_with_roles(
user, course_session_ids=None, include_private_data=False
):
course_sessions = get_course_sessions_with_roles_for_user(user) course_sessions = get_course_sessions_with_roles_for_user(user)
if course_session_ids: if course_session_ids:
course_sessions = [ course_sessions = [
@ -140,7 +143,9 @@ def create_person_list_with_roles(
).select_related("user") ).select_related("user")
my_role = user_role(cs.roles) my_role = user_role(cs.roles)
for csu in course_session_users: for csu in course_session_users:
person_data = result_persons.get(csu.user.id, create_csu_dict(csu)) person_data = result_persons.get(
csu.user.id, create_csu_dict(csu, include_private_data)
)
person_data["course_sessions"].append( person_data["course_sessions"].append(
create_course_session_dict(cs, my_role, csu.role) create_course_session_dict(cs, my_role, csu.role)
) )
@ -154,7 +159,9 @@ def create_person_list_with_roles(
participant_user = relation.participant.user participant_user = relation.participant.user
if participant_user.id not in result_persons: if participant_user.id not in result_persons:
person_data = create_csu_dict(relation.participant) person_data = create_csu_dict(
relation.participant, include_private_data
)
person_data["course_sessions"] = [course_session_entry] person_data["course_sessions"] = [course_session_entry]
result_persons[participant_user.id] = person_data result_persons[participant_user.id] = person_data
else: else:
@ -193,7 +200,7 @@ def create_person_list_with_roles(
) )
if mentor_relation.agent.id not in result_persons: if mentor_relation.agent.id not in result_persons:
person_data = create_user_dict(mentor_relation.agent) person_data = create_user_dict(mentor_relation.agent, include_private_data)
person_data["course_sessions"] = [course_session_entry] person_data["course_sessions"] = [course_session_entry]
result_persons[mentor_relation.agent.id] = person_data result_persons[mentor_relation.agent.id] = person_data
else: else:

View File

@ -24,7 +24,10 @@ from vbv_lernwelt.competence.services import (
query_competence_course_session_edoniq_tests, query_competence_course_session_edoniq_tests,
) )
from vbv_lernwelt.core.models import User from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.models import CourseConfiguration, CourseSessionUser from vbv_lernwelt.course.models import (
CourseConfiguration,
CourseSessionUser,
)
from vbv_lernwelt.course.views import logger from vbv_lernwelt.course.views import logger
from vbv_lernwelt.course_session.services.export_attendance import ( from vbv_lernwelt.course_session.services.export_attendance import (
ATTENDANCE_EXPORT_FILENAME, ATTENDANCE_EXPORT_FILENAME,
@ -463,16 +466,43 @@ def export_feedback_as_xsl(request):
@api_view(["POST"]) @api_view(["POST"])
def export_persons_as_xsl(request): def export_persons_as_xsl(request):
requested_course_session_ids = request.data.get("courseSessionIds", []) requested_course_session_user_ids = request.data.get("courseSessionUserIds", [])
course_sessions_with_roles = _get_permitted_courses_sessions_for_user( data = _export_persons_as_xls_data(request.user, requested_course_session_user_ids)
request.user, requested_course_session_ids if data:
) # noqa
data = export_persons(
request.user,
[cswr.id for cswr in course_sessions_with_roles],
)
return _make_excel_response(data, PERSONS_EXPORT_FILENAME) return _make_excel_response(data, PERSONS_EXPORT_FILENAME)
return Response(status=status.HTTP_400_BAD_REQUEST)
def _export_persons_as_xls_data(user: User, course_session_user_ids: List[str]):
permitted_course_session_users = _get_permitted_csus_for_user(
user, course_session_user_ids
)
return export_persons(permitted_course_session_users)
def _get_permitted_csus_for_user(
user: User, requested_coursesessionuser_ids: List[str]
) -> List[CourseSessionUser]:
# Premit course session users where user is agent (Berufsbildner, Lernbegleiter)
premitted_from_agent_participant_rel = CourseSessionUser.objects.filter(
id__in=requested_coursesessionuser_ids,
agentparticipantrelation__agent=user,
)
# Premit course session users where user has a certain role in the user's course session
ALLOWED_ROLES = ["EXPERT", "SUPERVISOR"]
requested_course_session_ids = CourseSessionUser.objects.filter(
id__in=requested_coursesessionuser_ids
).values_list("course_session__id", flat=True)
permitted_course_sessions = _get_course_sessions_with_roles_for_user(
user, ALLOWED_ROLES, requested_course_session_ids
)
permitted_from_role = CourseSessionUser.objects.filter(
id__in=requested_coursesessionuser_ids,
course_session__in=[x.id for x in permitted_course_sessions],
)
return set(premitted_from_agent_participant_rel) | set(permitted_from_role)
def _get_permitted_courses_sessions_for_user( def _get_permitted_courses_sessions_for_user(