diff --git a/docs/SchemaRelationnel.odg b/docs/SchemaRelationnel.odg index 0906431..7c5443c 100644 Binary files a/docs/SchemaRelationnel.odg and b/docs/SchemaRelationnel.odg differ diff --git a/stages/admin.py b/stages/admin.py index 923d290..632a09e 100644 --- a/stages/admin.py +++ b/stages/admin.py @@ -41,15 +41,29 @@ class CorpContactAdmin(admin.ModelAdmin): list_display = ('__str__', 'corporation', 'role') ordering = ('last_name', 'first_name') search_fields = ('last_name', 'first_name', 'role') - fields = (('corporation', 'is_main', 'always_cc'), + fields = (('corporation',), ('sections', 'is_main', 'always_cc'), ('title', 'last_name', 'first_name'), 'role', ('tel', 'email')) + formfield_overrides = { + models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, + } + + def get_form(self, *args, **kwargs): + form = super().get_form(*args, **kwargs) + form.base_fields['sections'].widget.can_add_related = False + return form + class ContactInline(admin.StackedInline): model = CorpContact - fields = (('is_main', 'always_cc'), ('title', 'last_name', 'first_name'), + fields = (('sections', 'is_main', 'always_cc'), + ('title', 'last_name', 'first_name'), ('role', 'tel', 'email')) extra = 1 + formfield_overrides = { + models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, + } + class CorporationAdmin(admin.ModelAdmin): list_display = ('name', 'short_name', 'pcode', 'city') diff --git a/stages/migrations/0004_corpcontact_sections.py b/stages/migrations/0004_corpcontact_sections.py new file mode 100644 index 0000000..4bc9b6b --- /dev/null +++ b/stages/migrations/0004_corpcontact_sections.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.1 on 2016-01-15 18:24 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stages', '0003_add_corp_fields'), + ] + + operations = [ + migrations.AddField( + model_name='corpcontact', + name='sections', + field=models.ManyToManyField(blank=True, to='stages.Section'), + ), + ] diff --git a/stages/models.py b/stages/models.py index e4e14de..f9a59e5 100644 --- a/stages/models.py +++ b/stages/models.py @@ -151,6 +151,7 @@ class CorpContact(models.Model): role = models.CharField(max_length=40, verbose_name='Fonction', blank=True) tel = models.CharField(max_length=20, blank=True, verbose_name='Téléphone') email = models.CharField(max_length=100, blank=True, verbose_name='Courriel') + sections = models.ManyToManyField(Section, blank=True) class Meta: verbose_name = "Contact" diff --git a/stages/tests.py b/stages/tests.py index 9ccf004..b42f64d 100644 --- a/stages/tests.py +++ b/stages/tests.py @@ -17,7 +17,7 @@ class StagesTest(TestCase): self.client.login(username='me', password='mepassword') def test_export(self): - response1 = self.client.get(reverse('stages_export')) + response1 = self.client.get(reverse('stages_export', args=['all'])) self.assertEqual(response1.status_code, 200) response2 = self.client.get(reverse('stages_export'), {'period': '2', 'non_attr': '0'}) diff --git a/stages/views.py b/stages/views.py index 402e1de..2df0261 100644 --- a/stages/views.py +++ b/stages/views.py @@ -1,6 +1,3 @@ -# -*- encoding: utf-8 -*- -from __future__ import unicode_literals - import json from collections import OrderedDict from datetime import date, datetime, timedelta @@ -215,7 +212,8 @@ def del_training(request): EXPORT_FIELDS = [ ('Prénom', 'student__first_name'), ('Nom', 'student__last_name'), ('ID externe', 'student__ext_id'), - ('Classe', 'student__klass__name'), ('Filière', 'student__klass__section__name'), + ('Classe', 'student__klass__name'), + ('Filière', 'student__klass__section__name'), ('Nom du stage', 'availability__period__title'), ('Début', 'availability__period__start_date'), ('Fin', 'availability__period__end_date'), ('Remarques stage', 'comment'), @@ -258,7 +256,6 @@ NON_ATTR_EXPORT_FIELDS = [ ] def stages_export(request, scope=None): - from datetime import date from openpyxl import Workbook from openpyxl.styles import Font, Style from openpyxl.writer.excel import save_virtual_workbook @@ -266,7 +263,7 @@ def stages_export(request, scope=None): period_filter = request.GET.get('period') non_attributed = bool(int(request.GET.get('non_attr', 0))) - export_fields = EXPORT_FIELDS + export_fields = OrderedDict(EXPORT_FIELDS) contact_test_field = 'availability__contact__last_name' corp_name_field = 'availability__corporation__name' @@ -274,7 +271,7 @@ def stages_export(request, scope=None): if non_attributed: # Export non attributed availabilities for a specific period query = Availability.objects.filter(period_id=period_filter, training__isnull=True) - export_fields = NON_ATTR_EXPORT_FIELDS + export_fields = OrderedDict(NON_ATTR_EXPORT_FIELDS) contact_test_field = 'contact__last_name' corp_name_field = 'corporation__name' else: @@ -288,38 +285,49 @@ def stages_export(request, scope=None): query = Training.objects.filter(availability__period__end_date__gt=school_year_start()) # Prepare "default" contacts (when not defined on training) - default_contacts = dict((c, '') for c in Corporation.objects.all().values_list('name', flat=True)) - always_ccs = dict((c, []) for c in Corporation.objects.all().values_list('name', flat=True)) - for contact in CorpContact.objects.all().select_related('corporation').order_by('corporation'): - if not default_contacts[contact.corporation.name] or contact.is_main is True: - default_contacts[contact.corporation.name] = contact - if contact.always_cc: - always_ccs[contact.corporation.name].append(contact) + section_names = Section.objects.all().values_list('name', flat=True) + default_contacts = dict( + (c, {s: '' for s in section_names}) + for c in Corporation.objects.all().values_list('name', flat=True) + ) + always_ccs = dict( + (c, {s: [] for s in section_names}) + for c in Corporation.objects.all().values_list('name', flat=True) + ) + for contact in CorpContact.objects.all().select_related('corporation' + ).prefetch_related('sections').order_by('corporation'): + for section in contact.sections.all(): + if not default_contacts[contact.corporation.name][section.name] or contact.is_main is True: + default_contacts[contact.corporation.name][section.name] = contact + if contact.always_cc: + always_ccs[contact.corporation.name][section.name].append(contact) wb = Workbook() ws = wb.get_active_sheet() ws.title = 'Stages' bold = Style(font=Font(bold=True)) # Headers - for col_idx, header in enumerate([f[0] for f in export_fields], start=1): + for col_idx, header in enumerate(export_fields.keys(), start=1): cell = ws.cell(row=1, column=col_idx) cell.value = header cell.style = bold # Data - query_keys = [f[1] for f in export_fields if f[1] is not None] + query_keys = [f for f in export_fields.values() if f is not None] for row_idx, tr in enumerate(query.values(*query_keys), start=2): for col_idx, field in enumerate(query_keys, start=1): ws.cell(row=row_idx, column=col_idx).value = tr[field] if tr[contact_test_field] is None: # Use default contact - contact = default_contacts.get(tr[corp_name_field]) + contact = default_contacts.get(tr[corp_name_field], {}).get(tr[export_fields['Filière']]) if contact: ws.cell(row=row_idx, column=col_idx-3).value = contact.title ws.cell(row=row_idx, column=col_idx-2).value = contact.first_name ws.cell(row=row_idx, column=col_idx-1).value = contact.last_name ws.cell(row=row_idx, column=col_idx).value = contact.email - if always_ccs[tr[corp_name_field]]: - ws.cell(row=row_idx, column=col_idx+1).value = "; ".join([c.email for c in always_ccs[tr[corp_name_field]]]) + if always_ccs[tr[corp_name_field]].get(tr[export_fields['Filière']]): + ws.cell(row=row_idx, column=col_idx+1).value = "; ".join( + [c.email for c in always_ccs[tr[corp_name_field]].get(tr[export_fields['Filière']])] + ) response = HttpResponse(save_virtual_workbook(wb), content_type='application/ms-excel') response['Content-Disposition'] = 'attachment; filename=%s%s.xlsx' % (