diff --git a/common/settings.py b/common/settings.py index fc94cf3..7d69991 100644 --- a/common/settings.py +++ b/common/settings.py @@ -118,16 +118,37 @@ ALLOWED_HOSTS = ['localhost', 'stages.pierre-coullery.ch'] # Mapping between column names of a tabular file and Student field names STUDENT_IMPORT_MAPPING = { - 'Num élève': 'ext_id', - 'Nom élève': 'last_name', - 'Prénom élève': 'first_name', - 'Rue élève': 'street', - 'Localité élève': 'city', # pcode is separated from city in prepare_import - 'Tél. élève': 'tel', - 'Natel élève': 'mobile', - 'Email RPN élève': 'email', - 'Date nais. élève': 'birth_date', - 'Classe': 'klass', + 'NO_CLOEE': 'ext_id', + 'NOM': 'last_name', + 'PRENOM': 'first_name', + 'RUE': 'street', + 'LOCALITE': 'city', # pcode is separated from city in prepare_import + 'TEL_PRIVE': 'tel', + 'TEL_MOBILE': 'mobile', + 'EMAIL_RPN': 'email', + 'DATENAI': 'birth_date', + 'NAVS13': 'avs', + 'SEXE': 'gender', + 'NO_EMPLOYEUR' : 'corporation', + 'NO_FORMATEUR' : 'instructor', + 'CLASSE_ACTUELLE': 'klass', +} + +CORPORATION_IMPORT_MAPPING = { + 'NO_EMPLOYEUR' : 'ext_id', + 'EMPLOYEUR' : 'name', + 'RUE_EMPLOYEUR': 'street', + 'LOCALITE_EMPLOYEUR': 'city', + 'TEL_EMPLOYEUR': 'tel', + 'CANTON_EMPLOYEUR' : 'district', +} + +INSTRUCTOR_IMPORT_MAPPING = { + 'NO_FORMATEUR': 'ext_id', + 'NOM_FORMATEUR': 'last_name', + 'PRENOM_FORMATEUR': 'first_name', + 'TEL_FORMATEUR': 'tel', + 'MAIL_FORMATEUR': 'email', } from .local_settings import * diff --git a/stages/models.py b/stages/models.py index 2fcb0a6..c893cdc 100644 --- a/stages/models.py +++ b/stages/models.py @@ -132,19 +132,42 @@ class Student(models.Model): return '%d ans%s' % (age_y, ' %d m.' % age_m if age_m > 0 else '') @classmethod - def prepare_import(cls, values): + def prepare_import(cls, student_values, corp_values, inst_values): ''' Hook for tabimport, before new object get created ''' - if 'klass' in values: + if 'klass' in student_values: try: - k = Klass.objects.get(name=values['klass']) + k = Klass.objects.get(name=student_values['klass']) except Klass.DoesNotExist: - raise Exception("La classe '%s' n'existe pas encore" % values['klass']) - values['klass'] = k + raise Exception("La classe '%s' n'existe pas encore" % student_values['klass']) + student_values['klass'] = k + + if 'corporation' in student_values: + if 'city' in corp_values and is_int(corp_values['city'][:4]): + corp_values['pcode'], _, corp_values['city'] = corp_values['city'].partition(' ') + if student_values['corporation'] != '': + obj, created = Corporation.objects.get_or_create( + ext_id=student_values['corporation'], + defaults = corp_values + ) + inst_values['corporation'] = obj + student_values['corporation'] = obj + else: + student_values['corporation'] = None + + if 'instructor' in student_values: + if student_values['instructor'] != '': + obj, created = CorpContact.objects.get_or_create( + ext_id=student_values['instructor'], + defaults = inst_values + ) + student_values['instructor'] = obj + else: + student_values['instructor'] = None # See if postal code included in city, and split them - if 'city' in values and is_int(values['city'][:4]): - values['pcode'], _, values['city'] = values['city'].partition(' ') - values['archived'] = False - return values + if 'city' in student_values and is_int(student_values['city'][:4]): + student_values['pcode'], _, student_values['city'] = student_values['city'].partition(' ') + student_values['archived'] = False + return student_values class Referent(models.Model): diff --git a/stages/test_files/EXPORT_GAN.xls b/stages/test_files/EXPORT_GAN.xls new file mode 100644 index 0000000..6b08ac6 Binary files /dev/null and b/stages/test_files/EXPORT_GAN.xls differ diff --git a/stages/tests.py b/stages/tests.py index 7e2198c..f663232 100644 --- a/stages/tests.py +++ b/stages/tests.py @@ -1,9 +1,11 @@ import json +import os from datetime import date from django.contrib.auth.models import User from django.test import TestCase from django.urls import reverse +from django.utils.html import escape from .models import ( Level, Domain, Section, Klass, Period, Student, Corporation, Availability, @@ -145,3 +147,30 @@ class PeriodTest(TestCase): per = Period.objects.create(title="Week test", section=self.section, level=self.level1, start_date=date(2013, 9, 12), end_date=date(2013, 9, 26)) self.assertEqual(per.weeks, 2) + + +class ImportTests(TestCase): + def setUp(self): + User.objects.create_user('me', 'me@example.org', 'mepassword') + + def test_import_gan(self): + path = os.path.join(os.path.dirname(__file__), 'test_files', 'EXPORT_GAN.xls') + self.client.login(username='me', password='mepassword') + with open(path, 'rb') as fh: + response = self.client.post(reverse('tabimport'), {'upload': fh}, follow=True) + self.assertContains(response, escape("La classe '1ASEFEa' n'existe pas encore")) + + lev1 = Level.objects.create(name='1') + Klass.objects.create( + name='1ASEFEa', + section=Section.objects.create(name='ASE'), + level=lev1, + ) + Klass.objects.create( + name='1EDS', + section=Section.objects.create(name='EDE'), + level=lev1, + ) + with open(path, 'rb') as fh: + response = self.client.post(reverse('tabimport'), {'upload': fh}, follow=True) + self.assertContains(response, "Created objects: 2") diff --git a/stages/views.py b/stages/views.py index 9f81750..fee6e1f 100644 --- a/stages/views.py +++ b/stages/views.py @@ -301,14 +301,28 @@ class StudentImportView(FormView): def import_data(self, up_file): """ Import Student data from uploaded file. """ - mapping = settings.STUDENT_IMPORT_MAPPING - rev_mapping = {v: k for k, v in mapping.items()} + student_mapping = settings.STUDENT_IMPORT_MAPPING + student_rev_mapping = {v: k for k, v in student_mapping.items()} + corporation_mapping = settings.CORPORATION_IMPORT_MAPPING + instructor_mapping = settings.INSTRUCTOR_IMPORT_MAPPING + obj_created = obj_modified = 0 for line in up_file: - defaults = dict((val, line[key]) for key, val in mapping.items() if val != 'ext_id') - defaults = Student.prepare_import(defaults) + student_defaults = { + val: line[key] for key, val in student_mapping.items() if val != 'ext_id' + } + corporation_defaults = { + val: line[key] for key, val in corporation_mapping.items() + } + instructor_defaults = { + val: line[key] for key, val in instructor_mapping.items() + } + + defaults = Student.prepare_import( + student_defaults, corporation_defaults, instructor_defaults + ) obj, created = Student.objects.get_or_create( - ext_id=line[rev_mapping['ext_id']], defaults=defaults) + ext_id=line[student_rev_mapping['ext_id']], defaults=defaults) if not created: for key, val in defaults.items(): setattr(obj, key, val)