diff --git a/common/urls.py b/common/urls.py index ebd9891..3265871 100644 --- a/common/urls.py +++ b/common/urls.py @@ -10,6 +10,7 @@ urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^import_students/', views.StudentImportView.as_view(), name='import-students'), url(r'^import_hp/', views.HPImportView.as_view(), name='import-hp'), + url(r'^import_hp_contacts/', views.HPContactsImportView.as_view(), name='import-hp-contacts'), url(r'^attribution/$', views.AttributionView.as_view(), name='attribution'), url(r'^stages/export/(?Pall)?/?$', views.stages_export, name='stages_export'), diff --git a/stages/test_files/Export_HP_Formateurs.xlsx b/stages/test_files/Export_HP_Formateurs.xlsx new file mode 100644 index 0000000..93a9b6e Binary files /dev/null and b/stages/test_files/Export_HP_Formateurs.xlsx differ diff --git a/stages/tests.py b/stages/tests.py index aa7c7df..30c2cf8 100644 --- a/stages/tests.py +++ b/stages/tests.py @@ -299,7 +299,11 @@ class ImportTests(TestCase): with open(path, 'rb') as fh: # , override_settings(DEBUG=True): response = self.client.post(reverse('import-students'), {'upload': fh}, follow=True) msg = "\n".join(str(m) for m in response.context['messages']) - self.assertIn("Created objects: 2", msg) + self.assertIn("Objets créés : 2", msg) + student1 = Student.objects.get(last_name='Fellmann') + self.assertEqual(student1.corporation.name, "Crèche Les Mousaillons") + # Instructor not set through this import + self.assertIsNone(student1.instructor) def test_import_hp(self): teacher = Teacher.objects.create( @@ -309,5 +313,23 @@ class ImportTests(TestCase): self.client.login(username='me', password='mepassword') with open(path, 'rb') as fh: response = self.client.post(reverse('import-hp'), {'upload': fh}, follow=True) - self.assertContains(response, "Created objects: 13, modified objects: 10") + self.assertContains(response, "Objets créés : 13") + self.assertContains(response, "Objets modifiés : 10") self.assertEqual(teacher.course_set.count(), 13) + + def test_import_hp_contacts(self): + # Those data should have been imported with the student main import file. + corp = Corporation.objects.create( + ext_id=44444, name="Crèche Les Mousaillons", typ="Institution", street="Rue des champs 12", + city="Moulineaux", pcode="2500" + ) + st1 = Student.objects.create( + ext_id=164718, first_name='Margot', last_name='Fellmann', birth_date="1994-05-12", + pcode="2300", city="La Chaux-de-Fonds", corporation=corp) + + path = os.path.join(os.path.dirname(__file__), 'test_files', 'Export_HP_Formateurs.xlsx') + self.client.login(username='me', password='mepassword') + with open(path, 'rb') as fh: + response = self.client.post(reverse('import-hp-contacts'), {'upload': fh}, follow=True) + st1.refresh_from_db() + self.assertEqual(st1.instructor.last_name, 'Geiser') diff --git a/stages/views.py b/stages/views.py index 9a0bfe6..aef6eee 100644 --- a/stages/views.py +++ b/stages/views.py @@ -301,14 +301,19 @@ class ImportViewBase(FormView): imp_file = CSVImportedFile(File(upfile)) else: imp_file = FileFactory(upfile) - created, modified = self.import_data(imp_file) + stats = self.import_data(imp_file) except Exception as e: if settings.DEBUG: raise messages.error(self.request, _("The import failed. Error message: %s") % e) else: - messages.info(self.request, _("Created objects: %(cr)d, modified objects: %(mod)d") % { - 'cr': created, 'mod': modified}) + non_fatal_errors = stats.get('errors', []) + if 'created' in stats: + messages.info(self.request, "Objets créés : %d" % stats['created']) + if 'modified' in stats: + messages.info(self.request, "Objets modifiés : %d" % stats['modified']) + if non_fatal_errors: + messages.warning(self.request, "Erreurs rencontrées: %s" % "\n".join(non_fatal_errors)) return HttpResponseRedirect(reverse('admin:index')) @@ -344,11 +349,6 @@ class StudentImportView(ImportViewBase): } 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']) @@ -364,7 +364,7 @@ class StudentImportView(ImportViewBase): student = Student.objects.create(**defaults) obj_created += 1 #FIXME: implement arch_staled - return obj_created, obj_modified + return {'created': obj_created, 'modified': obj_modified} def get_corporation(self, corp_values): if corp_values['ext_id'] == '': @@ -377,23 +377,6 @@ class StudentImportView(ImportViewBase): ) 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): """ @@ -462,7 +445,54 @@ class HPImportView(ImportViewBase): obj.period += period obj_modified += 1 obj.save() - return obj_created, obj_modified + return {'created': obj_created, 'modified': obj_modified} + + +class HPContactsImportView(ImportViewBase): + """ + Importation du fichier Hyperplanning contenant les formateurs d'étudiants. + """ + form_class = UploadHPFileForm + + def import_data(self, up_file): + obj_modified = 0 + errors = [] + for line in up_file: + try: + student = Student.objects.get(ext_id=int(line['UID_ETU'])) + except Student.DoesNotExist: + errors.append( + "Impossible de trouver l'étudiant avec le numéro %s" % int(line['UID_ETU']) + ) + continue + try: + corp = Corporation.objects.get(ext_id=int(line['NoSIRET'])) + except Corporation.DoesNotExist: + errors.append( + "Impossible de trouver l'institution avec le numéro %s" % int(line['NoSIRET']) + ) + continue + + # Check corporation matches + if student.corporation_id != corp.pk: + # This import has priority over the corporation set by StudentImportView + student.corporation = corp + student.save() + + contact = corp.corpcontact_set.filter( + first_name__iexact=line['PRENOMMDS'].strip(), + last_name__iexact=line['NOMMDS'].strip() + ).first() + if contact is None: + contact = CorpContact.objects.create( + corporation=corp, first_name=line['PRENOMMDS'].strip(), + last_name=line['NOMMDS'].strip(), title=line['CIVMDS'], email=line['EMAILMDS'] + ) + if student.instructor != contact: + student.instructor = contact + student.save() + obj_modified += 1 + return {'modified': obj_modified, 'errors': errors} EXPORT_FIELDS = [ diff --git a/templates/admin/base_site.html b/templates/admin/base_site.html index efeca77..fa8c082 100644 --- a/templates/admin/base_site.html +++ b/templates/admin/base_site.html @@ -8,3 +8,11 @@ {% endblock %} {% block nav-global %}{% endblock %} + +{% block messages %} + {% if messages %} + + {% endif %} +{% endblock messages %} diff --git a/templates/admin/index.html b/templates/admin/index.html index 7150580..5983014 100644 --- a/templates/admin/index.html +++ b/templates/admin/index.html @@ -75,7 +75,8 @@