Fixed student import

This commit is contained in:
Claude Paroz 2017-07-19 11:33:54 +02:00
parent 843526bf27
commit 26630687db
6 changed files with 79 additions and 56 deletions

View file

@ -118,7 +118,7 @@ ALLOWED_HOSTS = ['localhost', 'stages.pierre-coullery.ch']
# Mapping between column names of a tabular file and Student field names
STUDENT_IMPORT_MAPPING = {
'NO_CLOEE': 'ext_id',
'NOCLOEE': 'ext_id',
'NOM': 'last_name',
'PRENOM': 'first_name',
'RUE': 'street',
@ -129,8 +129,6 @@ STUDENT_IMPORT_MAPPING = {
'DATENAI': 'birth_date',
'NAVS13': 'avs',
'SEXE': 'gender',
'NO_EMPLOYEUR' : 'corporation',
'NO_FORMATEUR' : 'instructor',
'CLASSE_ACTUELLE': 'klass',
}

View file

@ -6,14 +6,6 @@ from django.db import models
from . import utils
def is_int(s):
try:
int(s)
return True
except ValueError:
return False
class Section(models.Model):
""" Filières """
name = models.CharField(max_length=20, verbose_name='Nom')
@ -156,7 +148,7 @@ class Student(models.Model):
return '%d ans%s' % (age_y, ' %d m.' % age_m if age_m > 0 else '')
@classmethod
def prepare_import(cls, student_values, corp_values, inst_values):
def prepare_import(cls, student_values):
''' Hook for tabimport, before new object get created '''
if 'klass' in student_values:
try:
@ -165,30 +157,8 @@ class Student(models.Model):
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 student_values and is_int(student_values['city'][:4]):
if 'city' in student_values and utils.is_int(student_values['city'][:4]):
student_values['pcode'], _, student_values['city'] = student_values['city'].partition(' ')
student_values['archived'] = False
return student_values

Binary file not shown.

View file

@ -3,7 +3,7 @@ import os
from datetime import date
from django.contrib.auth.models import User
from django.test import TestCase
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils.html import escape
@ -180,7 +180,8 @@ class ImportTests(TestCase):
self.client.login(username='me', password='mepassword')
with open(path, 'rb') as fh:
response = self.client.post(reverse('import-students'), {'upload': fh}, follow=True)
self.assertContains(response, escape("La classe '1ASEFEa' n'existe pas encore"))
msg = "\n".join(str(m) for m in response.context['messages'])
self.assertIn("La classe '1ASEFEa' n'existe pas encore", msg)
lev1 = Level.objects.create(name='1')
Klass.objects.create(
@ -193,9 +194,10 @@ class ImportTests(TestCase):
section=Section.objects.create(name='EDE'),
level=lev1,
)
with open(path, 'rb') as fh:
with open(path, 'rb') as fh: # , override_settings(DEBUG=True):
response = self.client.post(reverse('import-students'), {'upload': fh}, follow=True)
self.assertContains(response, "Created objects: 2")
msg = "\n".join(str(m) for m in response.context['messages'])
self.assertIn("Created objects: 2", msg)
def test_import_hp(self):
teacher = Teacher.objects.create(

View file

@ -12,3 +12,11 @@ def school_year(date, as_tuple=False):
return (start_year, start_year + 1)
else:
return "%d%d" % (start_year, start_year + 1)
def is_int(s):
try:
int(s)
return True
except ValueError:
return False

View file

@ -19,6 +19,7 @@ from .models import (
Klass, Section, Student, Teacher, Corporation, CorpContact, Course, Period,
Training, Availability,
)
from .utils import is_int
def school_year_start():
@ -319,33 +320,77 @@ class StudentImportView(ImportViewBase):
corporation_mapping = settings.CORPORATION_IMPORT_MAPPING
instructor_mapping = settings.INSTRUCTOR_IMPORT_MAPPING
def strip(val):
return val.strip() if isinstance(val, str) else val
obj_created = obj_modified = 0
seen_students_ids = set()
for line in up_file:
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()
val: strip(line[key]) for key, val in student_mapping.items()
}
if student_defaults['ext_id'] in seen_students_ids:
# Second line for student, ignore it
continue
seen_students_ids.add(student_defaults['ext_id'])
if isinstance(student_defaults['birth_date'], str):
student_defaults['birth_date'] = datetime.strptime(student_defaults['birth_date'], '%d.%m.%Y').date()
defaults = Student.prepare_import(
student_defaults, corporation_defaults, instructor_defaults
)
obj, created = Student.objects.get_or_create(
ext_id=line[student_rev_mapping['ext_id']], defaults=defaults)
if not created:
corporation_defaults = {
val: strip(line[key]) for key, val in corporation_mapping.items()
}
student_defaults['corporation'] = self.get_corporation(corporation_defaults)
instructor_defaults = {
val: strip(line[key]) for key, val in instructor_mapping.items()
}
student_defaults['instructor'] = self.get_instructor(student_defaults['corporation'], instructor_defaults)
defaults = Student.prepare_import(student_defaults)
try:
student = Student.objects.get(ext_id=student_defaults['ext_id'])
modified = False
for key, val in defaults.items():
setattr(obj, key, val)
obj.save()
obj_modified += 1
else:
if getattr(student, key) != val:
setattr(student, key, val)
modified = True
if modified:
student.save()
obj_modified += 1
except Student.DoesNotExist:
student = Student.objects.create(**defaults)
obj_created += 1
#FIXME: implement arch_staled
return obj_created, obj_modified
def get_corporation(self, corp_values):
if corp_values['ext_id'] == '':
return None
if 'city' in corp_values and is_int(corp_values['city'][:4]):
corp_values['pcode'], _, corp_values['city'] = corp_values['city'].partition(' ')
corp, created = Corporation.objects.get_or_create(
ext_id=corp_values['ext_id'],
defaults=corp_values
)
return corp
def get_instructor(self, corp, inst_values):
if inst_values['ext_id'] == '':
return None
try:
inst = CorpContact.objects.get(ext_id=inst_values['ext_id'])
except CorpContact.DoesNotExist:
try:
inst = corp.corpcontact_set.get(
first_name__iexact=inst_values['first_name'], last_name__iexact=inst_values['last_name']
)
inst.ext_id = inst_values['ext_id']
inst.save()
except CorpContact.DoesNotExist:
inst_values['corporation'] = corp
inst = CorpContact.objects.create(**inst_values)
return inst
class HPImportView(ImportViewBase):
"""