Import students from excel
This commit is contained in:
parent
d6df9b624b
commit
32233ec38e
|
|
@ -7,14 +7,14 @@ from django.db import migrations
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('core', '0001_initial'),
|
("core", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterModelManagers(
|
migrations.AlterModelManagers(
|
||||||
name='user',
|
name="user",
|
||||||
managers=[
|
managers=[
|
||||||
('objects', django.contrib.auth.models.UserManager()),
|
("objects", django.contrib.auth.models.UserManager()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ class CourseSessionUserAdmin(admin.ModelAdmin):
|
||||||
]
|
]
|
||||||
list_filter = [
|
list_filter = [
|
||||||
"course_session",
|
"course_session",
|
||||||
|
"role",
|
||||||
]
|
]
|
||||||
|
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
|
|
|
||||||
|
|
@ -45,15 +45,16 @@ from vbv_lernwelt.course.creators.versicherungsvermittlerin import (
|
||||||
create_versicherungsvermittlerin_with_categories,
|
create_versicherungsvermittlerin_with_categories,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course.models import (
|
from vbv_lernwelt.course.models import (
|
||||||
|
Course,
|
||||||
CoursePage,
|
CoursePage,
|
||||||
CourseSession,
|
CourseSession,
|
||||||
CourseSessionUser,
|
CourseSessionUser,
|
||||||
Course,
|
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course.services import mark_course_completion
|
from vbv_lernwelt.course.services import mark_course_completion
|
||||||
from vbv_lernwelt.feedback.creators.create_demo_feedback import create_feedback
|
from vbv_lernwelt.feedback.creators.create_demo_feedback import create_feedback
|
||||||
from vbv_lernwelt.importer.services import (
|
from vbv_lernwelt.importer.services import (
|
||||||
import_course_sessions_from_excel,
|
import_course_sessions_from_excel,
|
||||||
|
import_students_from_excel,
|
||||||
import_trainers_from_excel,
|
import_trainers_from_excel,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.learnpath.create_vv_new_learning_path import (
|
from vbv_lernwelt.learnpath.create_vv_new_learning_path import (
|
||||||
|
|
@ -460,6 +461,10 @@ def create_course_training_de():
|
||||||
course,
|
course,
|
||||||
f"{current_dir}/../../../importer/tests/Schulungen_Durchfuehrung_Trainer.xlsx",
|
f"{current_dir}/../../../importer/tests/Schulungen_Durchfuehrung_Trainer.xlsx",
|
||||||
)
|
)
|
||||||
|
import_students_from_excel(
|
||||||
|
course,
|
||||||
|
f"{current_dir}/../../../importer/tests/Schulungen_Teilnehmende.xlsx",
|
||||||
|
)
|
||||||
|
|
||||||
for cs in CourseSession.objects.filter(course_id=COURSE_UK_TRAINING):
|
for cs in CourseSession.objects.filter(course_id=COURSE_UK_TRAINING):
|
||||||
cs.assignment_details_list = [
|
cs.assignment_details_list = [
|
||||||
|
|
|
||||||
|
|
@ -6,33 +6,33 @@ from django.db import migrations, models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('course', '0003_rename_attendance_days_coursesession_attendance_courses'),
|
("course", "0003_rename_attendance_days_coursesession_attendance_courses"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='coursesession',
|
model_name="coursesession",
|
||||||
name='generation',
|
name="generation",
|
||||||
field=models.TextField(blank=True, default=''),
|
field=models.TextField(blank=True, default=""),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='coursesession',
|
model_name="coursesession",
|
||||||
name='group',
|
name="group",
|
||||||
field=models.TextField(blank=True, default=''),
|
field=models.TextField(blank=True, default=""),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='coursesession',
|
model_name="coursesession",
|
||||||
name='import_id',
|
name="import_id",
|
||||||
field=models.TextField(blank=True, default=''),
|
field=models.TextField(blank=True, default=""),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='coursesession',
|
model_name="coursesession",
|
||||||
name='region',
|
name="region",
|
||||||
field=models.TextField(blank=True, default=''),
|
field=models.TextField(blank=True, default=""),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='coursesession',
|
model_name="coursesession",
|
||||||
name='title',
|
name="title",
|
||||||
field=models.TextField(unique=True),
|
field=models.TextField(unique=True),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Dict, Any
|
from typing import Any, Dict
|
||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
from openpyxl.reader.excel import load_workbook
|
from openpyxl.reader.excel import load_workbook
|
||||||
|
|
@ -6,11 +6,11 @@ from openpyxl.reader.excel import load_workbook
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.course.models import Course, CourseSession, CourseSessionUser
|
from vbv_lernwelt.course.models import Course, CourseSession, CourseSessionUser
|
||||||
from vbv_lernwelt.importer.utils import (
|
from vbv_lernwelt.importer.utils import (
|
||||||
try_parse_datetime,
|
|
||||||
parse_circle_group_string,
|
|
||||||
calc_header_tuple_list_from_pyxl_sheet,
|
calc_header_tuple_list_from_pyxl_sheet,
|
||||||
|
parse_circle_group_string,
|
||||||
|
try_parse_datetime,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.learnpath.models import LearningContentAttendanceCourse, Circle
|
from vbv_lernwelt.learnpath.models import Circle, LearningContentAttendanceCourse
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
@ -183,3 +183,41 @@ def create_or_update_trainer(course: Course, data: Dict[str, Any]):
|
||||||
if csu:
|
if csu:
|
||||||
csu.expert.add(circle)
|
csu.expert.add(circle)
|
||||||
csu.save()
|
csu.save()
|
||||||
|
|
||||||
|
|
||||||
|
def import_students_from_excel(course: Course, filename: str):
|
||||||
|
workbook = load_workbook(filename=filename)
|
||||||
|
sheet = workbook.active
|
||||||
|
|
||||||
|
tuple_list = calc_header_tuple_list_from_pyxl_sheet(sheet)
|
||||||
|
for row in tuple_list:
|
||||||
|
create_or_update_student(course, dict(row))
|
||||||
|
|
||||||
|
|
||||||
|
def create_or_update_student(course: Course, data: Dict[str, Any]):
|
||||||
|
logger.debug(
|
||||||
|
"create_or_update_student",
|
||||||
|
course=course.title,
|
||||||
|
data=data,
|
||||||
|
label="import",
|
||||||
|
)
|
||||||
|
|
||||||
|
user = create_or_update_user(
|
||||||
|
email=data["Email"],
|
||||||
|
first_name=data["Vorname"],
|
||||||
|
last_name=data["Name"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO: handle language
|
||||||
|
|
||||||
|
# general expert handling
|
||||||
|
import_ids = [i.strip() for i in data["Durchführungen"].split(",")]
|
||||||
|
for import_id in import_ids:
|
||||||
|
course_session = CourseSession.objects.filter(
|
||||||
|
import_id=import_id, course=course
|
||||||
|
).first()
|
||||||
|
if course_session:
|
||||||
|
csu, _created = CourseSessionUser.objects.get_or_create(
|
||||||
|
course_session_id=course_session.id, user_id=user.id
|
||||||
|
)
|
||||||
|
csu.save()
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -6,7 +6,7 @@ from openpyxl.reader.excel import load_workbook
|
||||||
|
|
||||||
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, CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
||||||
from vbv_lernwelt.importer.services import create_or_update_trainer
|
from vbv_lernwelt.importer.services import create_or_update_student
|
||||||
from vbv_lernwelt.importer.utils import calc_header_tuple_list_from_pyxl_sheet
|
from vbv_lernwelt.importer.utils import calc_header_tuple_list_from_pyxl_sheet
|
||||||
|
|
||||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
@ -15,6 +15,12 @@ test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
class ImportStudentsTestCase(TestCase):
|
class ImportStudentsTestCase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.course = create_test_course(include_vv=False)
|
self.course = create_test_course(include_vv=False)
|
||||||
|
self.course_session_a = CourseSession.objects.create(
|
||||||
|
course=self.course,
|
||||||
|
title="Deutschschweiz 2023 A",
|
||||||
|
import_id="DE 2023 A",
|
||||||
|
group="A",
|
||||||
|
)
|
||||||
|
|
||||||
def test_import_excel_file(self):
|
def test_import_excel_file(self):
|
||||||
workbook = load_workbook(filename=f"{test_dir}/Schulungen_Teilnehmende.xlsx")
|
workbook = load_workbook(filename=f"{test_dir}/Schulungen_Teilnehmende.xlsx")
|
||||||
|
|
@ -23,51 +29,48 @@ class ImportStudentsTestCase(TestCase):
|
||||||
tuple_list = calc_header_tuple_list_from_pyxl_sheet(sheet)
|
tuple_list = calc_header_tuple_list_from_pyxl_sheet(sheet)
|
||||||
for row in tuple_list:
|
for row in tuple_list:
|
||||||
print(row)
|
print(row)
|
||||||
|
create_or_update_student(self.course, dict(row))
|
||||||
|
|
||||||
|
self.assertEqual(CourseSessionUser.objects.count(), 26)
|
||||||
|
|
||||||
|
|
||||||
class CreateOrUpdateCourseSessionTestCase(TestCase):
|
class CreateOrUpdateStudentTestCase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.course = create_test_course(include_vv=False)
|
self.course = create_test_course(include_vv=False)
|
||||||
self.course_session_a = CourseSession.objects.create(
|
self.course_session_a = CourseSession.objects.create(
|
||||||
course=self.course,
|
course=self.course,
|
||||||
title="Deutschschweiz 2023 A",
|
title="Deutschschweiz 2023 A",
|
||||||
import_id="DE 2023",
|
import_id="DE 2023 A",
|
||||||
group="A",
|
group="A",
|
||||||
)
|
)
|
||||||
self.course_session_a = CourseSession.objects.create(
|
|
||||||
course=self.course,
|
|
||||||
title="Deutschschweiz 2023 B",
|
|
||||||
import_id="DE 2023",
|
|
||||||
group="B",
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_create_course_session(self):
|
def test_create_student(self):
|
||||||
row = [
|
row = [
|
||||||
("Name", "Hänni"),
|
("Name", "Rascher"),
|
||||||
("Vorname", "Fabienne"),
|
("Vorname", "Barbara"),
|
||||||
("Email", "fabienne.haenni@vbv-afa.ch"),
|
("Email", "barbara.rascher@vbv-afa.ch"),
|
||||||
("Sprache", "de"),
|
("Sprache", "de"),
|
||||||
("Generation", "DE 2023"),
|
("Durchführungen", "DE 2023 A"),
|
||||||
("Klasse", "A, B"),
|
("Datum", datetime(2023, 9, 6, 0, 0)),
|
||||||
("Circles", "Fahrzeug (A, B), Reisen (A), KMU (B)"),
|
(None, "VBV"),
|
||||||
("Status Referenten", "ok"),
|
(None, None),
|
||||||
(None, "Schulung D"),
|
(None, None),
|
||||||
("Klasse foo", datetime(2023, 6, 6, 0, 0)),
|
(None, None),
|
||||||
|
(None, None),
|
||||||
]
|
]
|
||||||
|
|
||||||
create_or_update_trainer(self.course, dict(row))
|
create_or_update_student(self.course, dict(row))
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
CourseSessionUser.objects.filter(
|
CourseSessionUser.objects.filter(
|
||||||
user__email="fabienne.haenni@vbv-afa.ch"
|
user__email="barbara.rascher@vbv-afa.ch"
|
||||||
).count(),
|
).count(),
|
||||||
2,
|
1,
|
||||||
)
|
)
|
||||||
|
|
||||||
csu = CourseSessionUser.objects.get(
|
csu = CourseSessionUser.objects.get(
|
||||||
course_session=self.course_session_a,
|
course_session=self.course_session_a,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(csu.role, CourseSessionUser.Role.EXPERT)
|
self.assertEqual(csu.role, CourseSessionUser.Role.MEMBER)
|
||||||
self.assertEqual(csu.user.email, "fabienne.haenni@vbv-afa.ch")
|
self.assertEqual(csu.user.email, "barbara.rascher@vbv-afa.ch")
|
||||||
self.assertEqual(csu.expert.all().first().title, "Fahrzeug")
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,18 @@ test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
class ImportTrainerTestCase(TestCase):
|
class ImportTrainerTestCase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.course = create_test_course(include_vv=False)
|
self.course = create_test_course(include_vv=False)
|
||||||
|
self.course_session_a = CourseSession.objects.create(
|
||||||
|
course=self.course,
|
||||||
|
title="Deutschschweiz 2023 A",
|
||||||
|
import_id="DE 2023 A",
|
||||||
|
group="A",
|
||||||
|
)
|
||||||
|
self.course_session_a = CourseSession.objects.create(
|
||||||
|
course=self.course,
|
||||||
|
title="Deutschschweiz 2023 B",
|
||||||
|
import_id="DE 2023 B",
|
||||||
|
group="B",
|
||||||
|
)
|
||||||
|
|
||||||
def test_import_excel_file(self):
|
def test_import_excel_file(self):
|
||||||
workbook = load_workbook(
|
workbook = load_workbook(
|
||||||
|
|
@ -26,8 +38,10 @@ class ImportTrainerTestCase(TestCase):
|
||||||
print(row)
|
print(row)
|
||||||
create_or_update_trainer(self.course, dict(row))
|
create_or_update_trainer(self.course, dict(row))
|
||||||
|
|
||||||
|
self.assertEqual(CourseSessionUser.objects.count(), 4)
|
||||||
|
|
||||||
class CreateOrUpdateCourseSessionTestCase(TestCase):
|
|
||||||
|
class CreateOrUpdateTrainerTestCase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.course = create_test_course(include_vv=False)
|
self.course = create_test_course(include_vv=False)
|
||||||
self.course_session_a = CourseSession.objects.create(
|
self.course_session_a = CourseSession.objects.create(
|
||||||
|
|
@ -43,7 +57,7 @@ class CreateOrUpdateCourseSessionTestCase(TestCase):
|
||||||
group="B",
|
group="B",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_create_course_session(self):
|
def test_create_trainer(self):
|
||||||
row = [
|
row = [
|
||||||
("Name", "Hänni"),
|
("Name", "Hänni"),
|
||||||
("Vorname", "Fabienne"),
|
("Vorname", "Fabienne"),
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ from datetime import date, datetime
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from vbv_lernwelt.importer.utils import (
|
from vbv_lernwelt.importer.utils import (
|
||||||
try_parse_date,
|
|
||||||
try_parse_int,
|
|
||||||
try_parse_datetime,
|
|
||||||
parse_circle_group_string,
|
parse_circle_group_string,
|
||||||
|
try_parse_date,
|
||||||
|
try_parse_datetime,
|
||||||
|
try_parse_int,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
import re
|
import re
|
||||||
from typing import Any, Tuple, Union, Optional, List
|
from typing import Any, List, Optional, Tuple, Union
|
||||||
|
|
||||||
from dateutil.parser import parse
|
from dateutil.parser import parse
|
||||||
from six import string_types
|
from six import string_types
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue