diff --git a/api/views.py b/api/views.py index 1f6d1256..80d77d7b 100644 --- a/api/views.py +++ b/api/views.py @@ -783,7 +783,9 @@ def import_activities(request): ) res["count"] = len(res["users"]) except (ImportException, UnicodeDecodeError) as e: - res["error"] = "".join(traceback.TracebackException.from_exception(e).format()) + # msg = traceback.TracebackException.from_exception(e).format() + msg = e.args[0] + res["error"] = msg except BaseException: res["error"] = traceback.format_exc() diff --git a/common/bulk_import.py b/common/bulk_import.py index 76c1d119..dd470e64 100644 --- a/common/bulk_import.py +++ b/common/bulk_import.py @@ -78,8 +78,12 @@ def run( ) else: # We assign all activities without teacher in INBUS to the one selected by importing user - teacher_username = activities_to_teacher[ca.concreteActivityId] - teacher = User.objects.get(username=teacher_username) + try: + teacher_username = activities_to_teacher[ca.concreteActivityId] + teacher = User.objects.get(username=teacher_username) + except KeyError: + msg = f"There's no assigned teacher to activity {ca.code()}. Please, make sure you selected one." + raise ImportException(msg) if not is_teacher(teacher): teachers_group = Group.objects.get_by_natural_key("teachers") diff --git a/frontend/src/Teacher/InbusImport.vue b/frontend/src/Teacher/InbusImport.vue index f690f813..9bff1e82 100644 --- a/frontend/src/Teacher/InbusImport.vue +++ b/frontend/src/Teacher/InbusImport.vue @@ -41,6 +41,13 @@ interface Teacher { last_name: string; } +interface ImportRequest { + semester_id: number; + subject_abbr: string; + activities: number[]; + activities_to_teacher: { [key: number]: string }; +} + const busy = ref(false); const semesters = await loadSemesters(); @@ -175,15 +182,76 @@ async function loadTeachers(): Promise { return teachers; } +function classesWithoutTeacher() { + const classes_without_teacher: number[] = []; + for (const clazz of subject_inbus_schedule.value) { + if (!clazz.teacherFullNames) { + classes_without_teacher.push(clazz.concreteActivityId); + } + } + + return classes_without_teacher; +} + +function isRequestValid(req) { + const classes_without_teacher = classesWithoutTeacher(); + + for (const activity of req.activities) { + if (classes_without_teacher.includes(activity)) { + if (!req.activities_to_teacher.hasOwnProperty(activity)) { + return false; + } + } + } + + return true; +} + +function getCorrespondingActivityRepr(activity_id: number) { + for (const ca of subject_inbus_schedule.value) { + if (ca.concreteActivityId === activity_id) { + return `${ca.educationTypeAbbrev}/${ca.order}, ${ca.subjectVersionCompleteCode}`; + } + } +} + +function classesWithoutSelectedTeacher(req: ImportRequest) { + const classes_without_selected_teacher: string[] = []; + const classes_without_teacher = classesWithoutTeacher(); + //console.log('classes_without_teacher', classes_without_teacher); + + for (const activity_id of req.activities) { + if (classes_without_teacher.includes(activity_id)) { + if (!req.activities_to_teacher.hasOwnProperty(activity_id)) { + classes_without_selected_teacher.push(getCorrespondingActivityRepr(activity_id)); + } + } + } + + return classes_without_selected_teacher; +} + async function importActivities() { busy.value = true; - const req = { + const req: ImportRequest = { semester_id: semester.value, subject_abbr: subject_kelvin_selected.value, activities: classes_to_import.value, activities_to_teacher: activities_to_teacher_selected.value }; + if (!isRequestValid(req)) { + const classes_without_selected_teacher = classesWithoutSelectedTeacher(req); + const err_msg = + classes_without_selected_teacher.length > 1 + ? `Selected classes to import (${classes_without_selected_teacher.join(', ')}) don't have assigned teacher. Please, select ones.` + : `Selected class to import (${classes_without_selected_teacher}) doesn't have assigned teacher. Please, select one.`; + result.value = { users: [], count: 0, error: err_msg }; + busy.value = false; + + return; + } + const res = await fetch('/api/import/activities', { method: 'POST', headers: { @@ -254,6 +322,7 @@ function onTeacherSelected(event) { {{ ca.teacherFullNames }}