Add excel import code
This commit is contained in:
parent
61ce0897cf
commit
9c1684bce3
|
|
@ -61,8 +61,6 @@ target/
|
||||||
# pyenv
|
# pyenv
|
||||||
.python-version
|
.python-version
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Environments
|
# Environments
|
||||||
.venv
|
.venv
|
||||||
venv/
|
venv/
|
||||||
|
|
@ -76,7 +74,6 @@ venv/
|
||||||
# mypy
|
# mypy
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
|
|
||||||
### Node template
|
### Node template
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
|
@ -159,10 +156,6 @@ typings/
|
||||||
# Local History for Visual Studio Code
|
# Local History for Visual Studio Code
|
||||||
.history/
|
.history/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Windows template
|
### Windows template
|
||||||
# Windows thumbnail cache files
|
# Windows thumbnail cache files
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
@ -272,6 +265,7 @@ tags
|
||||||
|
|
||||||
### Project template
|
### Project template
|
||||||
|
|
||||||
|
.~lock.*
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.ipython/
|
.ipython/
|
||||||
vendors.js
|
vendors.js
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,9 @@ mypy-extensions==0.4.3
|
||||||
nodeenv==1.6.0
|
nodeenv==1.6.0
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
openpyxl==3.1.2
|
openpyxl==3.1.2
|
||||||
# via wagtail
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# wagtail
|
||||||
packaging==21.3
|
packaging==21.3
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
|
|
|
||||||
|
|
@ -47,3 +47,4 @@ azure-storage-blob
|
||||||
azure-identity
|
azure-identity
|
||||||
|
|
||||||
boto3
|
boto3
|
||||||
|
openpyxl
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,9 @@ msal==1.22.0
|
||||||
msal-extensions==1.0.0
|
msal-extensions==1.0.0
|
||||||
# via azure-identity
|
# via azure-identity
|
||||||
openpyxl==3.1.2
|
openpyxl==3.1.2
|
||||||
# via wagtail
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# wagtail
|
||||||
packaging==21.3
|
packaging==21.3
|
||||||
# via
|
# via
|
||||||
# marshmallow
|
# marshmallow
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ class AssignmentApiTestCase(APITestCase):
|
||||||
self.cs = CourseSession.objects.create(
|
self.cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Lehrgang Session",
|
title="Test Lehrgang Session",
|
||||||
|
import_id="Test Lehrgang Session",
|
||||||
)
|
)
|
||||||
self.student = User.objects.get(username="student")
|
self.student = User.objects.get(username="student")
|
||||||
self.student_csu = CourseSessionUser.objects.create(
|
self.student_csu = CourseSessionUser.objects.create(
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ class UpdateAssignmentCompletionTestCase(TestCase):
|
||||||
self.course_session = CourseSession.objects.create(
|
self.course_session = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Bern 2022 a",
|
title="Bern 2022 a",
|
||||||
|
import_id="Bern 2022 a",
|
||||||
)
|
)
|
||||||
self.user = User.objects.get(username="student")
|
self.user = User.objects.get(username="student")
|
||||||
self.trainer = User.objects.get(username="admin")
|
self.trainer = User.objects.get(username="admin")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 3.2.13 on 2023-05-31 14:34
|
||||||
|
|
||||||
|
import django.contrib.auth.models
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelManagers(
|
||||||
|
name='user',
|
||||||
|
managers=[
|
||||||
|
('objects', django.contrib.auth.models.UserManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -2,8 +2,6 @@ from django.contrib.auth.models import AbstractUser
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import JSONField
|
from django.db.models import JSONField
|
||||||
|
|
||||||
from vbv_lernwelt.core.managers import UserManager
|
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -83,11 +83,13 @@ def create_test_course(include_uk=True, include_vv=True, with_sessions=False):
|
||||||
cs_bern = CourseSession.objects.create(
|
cs_bern = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Bern 2022 a",
|
title="Test Bern 2022 a",
|
||||||
|
import_id="Test Bern 2022 a",
|
||||||
id=TEST_COURSE_SESSION_BERN_ID,
|
id=TEST_COURSE_SESSION_BERN_ID,
|
||||||
)
|
)
|
||||||
cs_zurich = CourseSession.objects.create(
|
cs_zurich = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Zürich 2022 a",
|
title="Test Zürich 2022 a",
|
||||||
|
import_id="Test Zürich 2022 a",
|
||||||
id=TEST_COURSE_SESSION_ZURICH_ID,
|
id=TEST_COURSE_SESSION_ZURICH_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ def create_versicherungsvermittlerin_course():
|
||||||
cs = CourseSession.objects.create(
|
cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
||||||
title="Versicherungsvermittler/-in",
|
title="Versicherungsvermittler/-in",
|
||||||
|
import_id="Versicherungsvermittler/-in",
|
||||||
)
|
)
|
||||||
for user_data in default_users:
|
for user_data in default_users:
|
||||||
CourseSessionUser.objects.create(
|
CourseSessionUser.objects.create(
|
||||||
|
|
@ -185,6 +186,7 @@ def create_course_uk_de():
|
||||||
cs = CourseSession.objects.create(
|
cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_UK,
|
course_id=COURSE_UK,
|
||||||
title="Bern 2023 a",
|
title="Bern 2023 a",
|
||||||
|
import_id="Bern 2023 a",
|
||||||
attendance_courses=[
|
attendance_courses=[
|
||||||
{
|
{
|
||||||
"learningContentId": LearningContentAttendanceCourse.objects.get(
|
"learningContentId": LearningContentAttendanceCourse.objects.get(
|
||||||
|
|
@ -280,6 +282,7 @@ def create_course_uk_de():
|
||||||
cs = CourseSession.objects.create(
|
cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_UK,
|
course_id=COURSE_UK,
|
||||||
title="Zürich 2023 a",
|
title="Zürich 2023 a",
|
||||||
|
import_id="Zürich 2023 a",
|
||||||
)
|
)
|
||||||
# for user_data in default_users:
|
# for user_data in default_users:
|
||||||
# CourseSessionUser.objects.create(
|
# CourseSessionUser.objects.create(
|
||||||
|
|
@ -322,6 +325,7 @@ def create_course_uk_fr():
|
||||||
cs = CourseSession.objects.create(
|
cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_UK_FR,
|
course_id=COURSE_UK_FR,
|
||||||
title="Cours hors établissement année 1 - Région Fribourg",
|
title="Cours hors établissement année 1 - Région Fribourg",
|
||||||
|
import_id="Cours hors établissement année 1 - Région Fribourg",
|
||||||
)
|
)
|
||||||
|
|
||||||
csu = CourseSessionUser.objects.create(
|
csu = CourseSessionUser.objects.create(
|
||||||
|
|
@ -441,7 +445,8 @@ def create_course_training_de():
|
||||||
|
|
||||||
cs = CourseSession.objects.create(
|
cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_UK_TRAINING,
|
course_id=COURSE_UK_TRAINING,
|
||||||
title="Demo-Tag",
|
title="myVBV Training",
|
||||||
|
import_id="myVBV Training",
|
||||||
attendance_courses=[
|
attendance_courses=[
|
||||||
{
|
{
|
||||||
"learningContentId": LearningContentAttendanceCourse.objects.get(
|
"learningContentId": LearningContentAttendanceCourse.objects.get(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Generated by Django 3.2.13 on 2023-05-31 14:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('course', '0003_rename_attendance_days_coursesession_attendance_courses'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='coursesession',
|
||||||
|
name='generation',
|
||||||
|
field=models.TextField(blank=True, default=''),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='coursesession',
|
||||||
|
name='group',
|
||||||
|
field=models.TextField(blank=True, default=''),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='coursesession',
|
||||||
|
name='import_id',
|
||||||
|
field=models.TextField(default='', unique=True),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='coursesession',
|
||||||
|
name='region',
|
||||||
|
field=models.TextField(blank=True, default=''),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='coursesession',
|
||||||
|
name='title',
|
||||||
|
field=models.TextField(unique=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -215,7 +215,12 @@ class CourseSession(models.Model):
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
course = models.ForeignKey("course.Course", on_delete=models.CASCADE)
|
course = models.ForeignKey("course.Course", on_delete=models.CASCADE)
|
||||||
title = models.TextField()
|
title = models.TextField(unique=True)
|
||||||
|
import_id = models.TextField(unique=True)
|
||||||
|
|
||||||
|
generation = models.TextField(blank=True, default="")
|
||||||
|
region = models.TextField(blank=True, default="")
|
||||||
|
group = models.TextField(blank=True, default="")
|
||||||
|
|
||||||
start_date = models.DateField(null=True, blank=True)
|
start_date = models.DateField(null=True, blank=True)
|
||||||
end_date = models.DateField(null=True, blank=True)
|
end_date = models.DateField(null=True, blank=True)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ class CourseCompletionApiTestCase(APITestCase):
|
||||||
self.cs = CourseSession.objects.create(
|
self.cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Lehrgang Session",
|
title="Test Lehrgang Session",
|
||||||
|
import_id="Test Lehrgang Session",
|
||||||
)
|
)
|
||||||
csu = CourseSessionUser.objects.create(
|
csu = CourseSessionUser.objects.create(
|
||||||
course_session=self.cs,
|
course_session=self.cs,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ class CourseCompletionApiTestCase(APITestCase):
|
||||||
self.course_session = CourseSession.objects.create(
|
self.course_session = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Lehrgang Session",
|
title="Test Lehrgang Session",
|
||||||
|
import_id="Test Lehrgang Session",
|
||||||
)
|
)
|
||||||
|
|
||||||
self.client.login(username="student", password="test")
|
self.client.login(username="student", password="test")
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ class DocumentUploadApiTestCase(APITestCase):
|
||||||
self.course_session = CourseSession.objects.create(
|
self.course_session = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Lehrgang Session",
|
title="Test Lehrgang Session",
|
||||||
|
import_id="Test Lehrgang Session",
|
||||||
)
|
)
|
||||||
|
|
||||||
csu = CourseSessionUser.objects.create(
|
csu = CourseSessionUser.objects.create(
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ class FeedbackApiBaseTestCase(APITestCase):
|
||||||
self.course_session = CourseSession.objects.create(
|
self.course_session = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Lehrgang Session",
|
title="Test Lehrgang Session",
|
||||||
|
import_id="Test Lehrgang Session",
|
||||||
)
|
)
|
||||||
|
|
||||||
csu = CourseSessionUser.objects.create(
|
csu = CourseSessionUser.objects.create(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
|
from vbv_lernwelt.course.models import Course, CourseSession
|
||||||
|
|
||||||
|
|
||||||
def create_or_update_user(
|
def create_or_update_user(
|
||||||
|
|
@ -28,3 +31,32 @@ def create_or_update_user(
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
def create_or_update_course_session(course: Course, data: Dict[str, Any]):
|
||||||
|
"""
|
||||||
|
:param data: the following keys are required to process the data: Generation, Region, Klasse
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
# TODO: validation
|
||||||
|
generation = str(data["Generation"]).strip()
|
||||||
|
region = data["Region"].strip()
|
||||||
|
group = data["Klasse"].strip()
|
||||||
|
import_id = data["ID"].strip()
|
||||||
|
|
||||||
|
title = f"{region} {generation} {group}"
|
||||||
|
|
||||||
|
cs, _created = CourseSession.objects.get_or_create(
|
||||||
|
import_id=import_id, course=course
|
||||||
|
)
|
||||||
|
|
||||||
|
cs.generation = generation
|
||||||
|
cs.region = region
|
||||||
|
cs.group = group
|
||||||
|
cs.import_id = import_id
|
||||||
|
|
||||||
|
cs.additional_json_data["import_data"] = data
|
||||||
|
cs.save()
|
||||||
|
|
||||||
|
return cs
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,74 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
from openpyxl.reader.excel import load_workbook
|
||||||
|
|
||||||
|
from vbv_lernwelt.course.factories import CourseFactory
|
||||||
|
from vbv_lernwelt.importer.services import create_or_update_course_session
|
||||||
|
|
||||||
|
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
class ImportCourseSessionTestCase(TestCase):
|
||||||
|
def test_open_excel_file(self):
|
||||||
|
workbook = load_workbook(
|
||||||
|
filename=f"{test_dir}/Schulungen_Durchfuehrung_Trainer.xlsx"
|
||||||
|
)
|
||||||
|
sheet = workbook["Schulungen Durchführung"]
|
||||||
|
|
||||||
|
# Read the header row separately
|
||||||
|
header = [cell.value for cell in sheet[1]]
|
||||||
|
|
||||||
|
# Loop through the remaining rows in the sheet
|
||||||
|
for row in sheet.iter_rows(min_row=2, values_only=True):
|
||||||
|
row_with_header = list(zip(header, row))
|
||||||
|
print(row_with_header)
|
||||||
|
|
||||||
|
def test_create_or_update_course_session(self):
|
||||||
|
row = [
|
||||||
|
("ID", "DE 2023 A"),
|
||||||
|
("Generation", 2023),
|
||||||
|
("Region", "Deutschschweiz"),
|
||||||
|
("Klasse", "A"),
|
||||||
|
("Fahrzeug Start", "06.06.2023, 13:30"),
|
||||||
|
("Fahrzeug Ende", "06.06.2023, 15:00"),
|
||||||
|
(
|
||||||
|
"Fahrzeug Raum",
|
||||||
|
"https://teams.microsoft.com/l/meetup-join/19%3ameeting_N2I5YzViZTQtYTM2Ny00OTYwLTgzNzAtYWI4OTQzODcxNTlj%40thread.v2/0?context=%7b%22Tid%22%3a%22fedd03c8-a756-4803-8f27-0db8f7c488f2%22%2c%22Oid%22%3a%22f92e6382-3884-4e71-a2fd-b305a75d9812%22%7d",
|
||||||
|
),
|
||||||
|
("Fahrzeug Standort", None),
|
||||||
|
("Fahrzeug Adresse", None),
|
||||||
|
]
|
||||||
|
|
||||||
|
print(dict(row))
|
||||||
|
|
||||||
|
|
||||||
|
class CreateOrUpdateCourseSessionTestCase(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.course = CourseFactory(title="myVBV Training")
|
||||||
|
|
||||||
|
def test_create(self):
|
||||||
|
row = [
|
||||||
|
("ID", "DE 2023"),
|
||||||
|
("Generation", 2023),
|
||||||
|
("Region", "Deutschschweiz"),
|
||||||
|
("Klasse", "A"),
|
||||||
|
("Fahrzeug Start", "06.06.2023, 13:30"),
|
||||||
|
("Fahrzeug Ende", "06.06.2023, 15:00"),
|
||||||
|
(
|
||||||
|
"Fahrzeug Raum",
|
||||||
|
"https://teams.microsoft.com/l/meetup-join/19%3ameeting_N2I5YzViZTQtYTM2Ny00OTYwLTgzNzAtYWI4OTQzODcxNTlj%40thread.v2/0?context=%7b%22Tid%22%3a%22fedd03c8-a756-4803-8f27-0db8f7c488f2%22%2c%22Oid%22%3a%22f92e6382-3884-4e71-a2fd-b305a75d9812%22%7d",
|
||||||
|
),
|
||||||
|
("Fahrzeug Standort", None),
|
||||||
|
("Fahrzeug Adresse", None),
|
||||||
|
]
|
||||||
|
|
||||||
|
data = dict(row)
|
||||||
|
|
||||||
|
cs = create_or_update_course_session(self.course, data)
|
||||||
|
|
||||||
|
self.assertEqual(cs.import_id, "DE 2023")
|
||||||
|
self.assertEqual(cs.title, "Deutschschweiz 2023 A")
|
||||||
|
self.assertEqual(cs.generation, "2023")
|
||||||
|
self.assertEqual(cs.region, "Deutschschweiz")
|
||||||
|
self.assertEqual(cs.group, "A")
|
||||||
|
|
@ -45,6 +45,7 @@ class TestRetrieveLearingPathContents(APITestCase):
|
||||||
course_session = CourseSession.objects.create(
|
course_session = CourseSession.objects.create(
|
||||||
course_id=COURSE_TEST_ID,
|
course_id=COURSE_TEST_ID,
|
||||||
title="Test Lehrgang Session",
|
title="Test Lehrgang Session",
|
||||||
|
import_id="Test Lehrgang Session",
|
||||||
)
|
)
|
||||||
CourseSessionUser.objects.create(
|
CourseSessionUser.objects.create(
|
||||||
course_session=course_session,
|
course_session=course_session,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue