diff --git a/stages/models.py b/stages/models.py index 0ba1619..294ee14 100644 --- a/stages/models.py +++ b/stages/models.py @@ -135,44 +135,45 @@ class Teacher(models.Model): 'report': self.next_report, } - def calc_imputations(self): + def calc_imputations(self, ratios): """ Return a tuple for accountings charges """ activities = self.calc_activity() imputations = OrderedDict( - [('ASA', 0), ('ASSC', 0), ('ASE', 0), ('MP', 0), ('EDEpe', 0), ('EDEps', 0), - ('EDS', 0), ('CAS_FPP', 0), ('Direction', 0)] + [('ASAFE', 0), ('ASSCFE', 0), ('ASEFE', 0), ('MPTS', 0), ('MPS', 0), ('EDEpe', 0), ('EDEps', 0), + ('EDS', 0), ('CAS_FPP', 0)] ) courses = self.course_set.all() for key in imputations: imputations[key] = courses.filter(imputation__contains=key).aggregate(models.Sum('period'))['period__sum'] or 0 - # Split EDE periods in EDEpe and EDEps columns, in proportion + # Spliting imputations for EDE, ASE and ASSC ede = courses.filter(imputation='EDE').aggregate(models.Sum('period'))['period__sum'] or 0 if ede > 0: - pe = imputations['EDEpe'] - ps = imputations['EDEps'] - pe_percent = (pe / (pe + ps)) if (pe + ps) > 0 else 0.5 - pe_plus = round(ede * pe_percent) - imputations['EDEpe'] += pe_plus - imputations['EDEps'] += ede - pe_plus + pe = int(round(ede * ratios['edepe'], 0)) + imputations['EDEpe'] += pe + imputations['EDEps'] += ede - pe + + ase = courses.filter(imputation='ASE').aggregate(models.Sum('period'))['period__sum'] or 0 + if ase > 0: + asefe = int(round(ase * ratios['asefe'], 0)) + imputations['ASEFE'] += asefe + imputations['MPTS'] += ase - asefe + + assc = courses.filter(imputation='ASSC').aggregate(models.Sum('period'))['period__sum'] or 0 + if assc > 0: + asscfe = int(round(assc * ratios['asscfe'], 0)) + imputations['ASSCFE'] += asscfe + imputations['MPS'] += assc - asscfe # Split formation periods in proportions tot = sum(imputations.values()) if tot > 0: for key in imputations: - imputations[key] += round(imputations[key] / tot * activities['tot_formation']) + imputations[key] += round(imputations[key] / tot * activities['tot_formation'],0) - # Correct for rounding errors changing the first imputations value - tot = sum(imputations.values()) + self.previous_report - (self.next_report) - dif = tot - activities['tot_paye'] - if dif in [-1, 1]: - for k, v in imputations.items(): - if v > 0: - imputations[k] += 1 if dif == -1 else -1 - break return (activities, imputations) def total_logbook(self): @@ -555,13 +556,20 @@ IMPUTATION_CHOICES = ( ('ASAFE', 'ASAFE'), ('ASEFE', 'ASEFE'), ('ASSCFE', 'ASSCFE'), - ('MP', 'MP'), + + ('MPTS', 'MPTS'), + ('MPS', 'MPS'), + ('EDEpe', 'EDEpe'), ('EDEps', 'EDEps'), - ('EDE', 'EDE'), ('EDS', 'EDS'), ('CAS_FPP', 'CAS_FPP'), - ('Direction', 'Direction'), + + # To split afterwards + ('EDE', 'EDE'), + ('#Mandat_ASA', 'ASA'), + ('#Mandat_ASE', 'ASE'), + ('#Mandat_ASSC', 'ASSC'), ) diff --git a/stages/tests.py b/stages/tests.py index 0d089e7..7f12323 100644 --- a/stages/tests.py +++ b/stages/tests.py @@ -382,32 +382,41 @@ class TeacherTests(TestCase): self.assertEqual(self.teacher.next_report, -2) def test_calc_imputations(self): - result = self.teacher.calc_imputations() - self.assertEqual(result[1]['ASSC'], 9) + ratio = {'edepe': 0.45, 'asefe': 0.45, 'asscfe': 0.55} + result = self.teacher.calc_imputations(ratio) + self.assertEqual(result[1]['ASSCFE'], 9) self.assertEqual(result[1]['EDEpe'], 5) - # Test with only EDE data + # Test with only ASSC data t2 = Teacher.objects.create( first_name='Isidore', last_name='Gluck', birth_date='1986-01-01' ) Course.objects.create( - teacher=t2, period=13, subject='#ASE Colloque', imputation='ASSCFE', + teacher=t2, period=24, subject='#ASSCE Colloque', imputation='ASSC', ) Course.objects.create( - teacher=t2, period=5, subject='Cours EDE', imputation='EDE', + teacher=t2, period=130, subject='#Coaching', imputation='ASSC', ) Course.objects.create( - teacher=t2, period=17, subject='Sém. enfance 2', imputation='ASE', + teacher=t2, period=275, subject='Cours MP ASSC', imputation='MPS', + ) + Course.objects.create( + teacher=t2, period=450, subject='Cours ASSCFE', imputation='ASSCFE', ) - result = t2.calc_imputations() - self.assertEqual(result[1]['ASE'], 19) - self.assertEqual(result[1]['ASSC'], 16) # rounding correction (first col > 0) - self.assertEqual(result[1]['EDEpe'], 2) - self.assertEqual(result[1]['EDEps'], 3) - self.assertEqual(result[0]['tot_paye'], result[0]['tot_trav']) - self.assertEqual(result[0]['tot_paye'], 40) - self.assertEqual(result[0]['report'], 0) + t2.previous_report = 10 + + ratio = {'edepe': 0.45, 'asefe': 0.45, 'asscfe': 0.55} + + result = t2.calc_imputations(ratio) + + self.assertEqual(result[0]['tot_paye'], 1005) + self.assertEqual(result[0]['tot_formation'], 116) + self.assertEqual(result[0]['tot_mandats'], 154) + self.assertEqual(result[1]['ASSCFE'], 606) + self.assertEqual(result[1]['MPS'], 389) + + def test_export_imputations(self): self.client.login(username='me', password='mepassword') diff --git a/stages/views.py b/stages/views.py index e8ffd61..dbb3af5 100644 --- a/stages/views.py +++ b/stages/views.py @@ -15,7 +15,7 @@ from django.contrib import messages from django.core.files import File from django.core.mail import EmailMessage from django.db import transaction -from django.db.models import Case, Count, Value, When, Q +from django.db.models import Case, Count, Value, When, Q, Sum from django.db.models.functions import Concat from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect @@ -32,7 +32,7 @@ from .exports import OpenXMLExport from .forms import EmailBaseForm, PeriodForm, StudentImportForm, UploadHPFileForm, UploadReportForm from .models import ( Klass, Section, Option, Student, Teacher, Corporation, CorpContact, Course, Period, - Training, Availability, + Training, Availability ) from .pdf import ExpertEdeLetterPdf, UpdateDataFormPDF, MentorCompensationPdfForm from .utils import is_int @@ -402,17 +402,23 @@ class HPImportView(ImportViewBase): ('ASAFE', 'ASAFE'), ('ASEFE', 'ASEFE'), ('ASSCFE', 'ASSCFE'), - ('MP', 'MP'), - ('CMS', 'MP'), + + ('#Mandat_ASA', 'ASAFE'), + + ('MPTS', 'MPTS'), + ('MPS', 'MPS'), + ('CMS ASE', 'MPTS'), + ('CMS ASSC', 'MPS'), + ('EDEpe', 'EDEpe'), ('EDEps', 'EDEps'), - ('EDE', 'EDE'), ('EDS', 'EDS'), ('CAS_FPP', 'CAS_FPP'), - ('#Mandat_ASA', 'ASAFE'), - ('#Mandat_ASE', 'ASEFE'), - ('#Mandat_ASSC', 'ASSCFE'), - ('Direction', 'Direction'), + + # To split afterwards + ('EDE', 'EDE'), + ('#Mandat_ASE', 'ASE'), + ('#Mandat_ASSC', 'ASSC'), ]) def import_data(self, up_file): @@ -878,18 +884,37 @@ def stages_export(request, scope=None): return export.get_http_response('stages_export') +def _ratio_Ede_Ase_Assc(): + # Spliting for unattribued periods + tot_edeps = Course.objects.filter(imputation='EDEps').aggregate(Sum('period'))['period__sum'] or 0 + tot_edepe = Course.objects.filter(imputation='EDEpe').aggregate(Sum('period'))['period__sum'] or 0 + edepe_ratio = 1 if tot_edepe + tot_edeps == 0 else tot_edepe / (tot_edepe + tot_edeps) + + tot_asefe = Course.objects.filter(imputation='ASEFE').aggregate(Sum('period'))['period__sum'] or 0 + tot_mpts = Course.objects.filter(imputation='MPTS').aggregate(Sum('period'))['period__sum'] or 0 + asefe_ratio = 1 if tot_asefe + tot_mpts == 0 else tot_asefe / (tot_asefe + tot_mpts) + + tot_asscfe = Course.objects.filter(imputation='ASSCFE').aggregate(Sum('period'))['period__sum'] or 0 + tot_mps = Course.objects.filter(imputation='MPS').aggregate(Sum('period'))['period__sum'] or 0 + asscfe_ratio = 1 if tot_asscfe + tot_mps == 0 else tot_asscfe / (tot_asscfe + tot_mps) + + return {'edepe':edepe_ratio, 'asefe':asefe_ratio, 'asscfe': asscfe_ratio} + + def imputations_export(request): IMPUTATIONS_EXPORT_FIELDS = [ 'Nom', 'Prénom', 'Report passé', 'Ens', 'Discipline', 'Accomp.', 'Discipline', 'Total payé', 'Indice', 'Taux', 'Report futur', - 'ASA', 'ASSC', 'ASE', 'MP', 'EDEpe', 'EDEps', 'EDS', 'CAS_FPP', 'Direction' + 'ASA', 'ASSC', 'ASE', 'MPTS', 'MPS', 'EDEpe', 'EDEps', 'EDS', 'CAS_FPP' ] + ratios = _ratio_Ede_Ase_Assc() + export = OpenXMLExport('Imputations') export.write_line(IMPUTATIONS_EXPORT_FIELDS, bold=True) # Headers for teacher in Teacher.objects.filter(archived=False): - activities, imputations = teacher.calc_imputations() + activities, imputations = teacher.calc_imputations(ratios) values = [ teacher.last_name, teacher.first_name, teacher.previous_report, activities['tot_ens'], 'Ens. prof.', activities['tot_mandats'] + activities['tot_formation'], @@ -909,17 +934,19 @@ def export_sap(request): 'ZACT', 'ZBRA', 'ZOTP', 'ZCCO', 'ZORD', 'ZTAUX', ] MAPPING_OTP = { - 'ASA': 'CIFO01.03.02.03.01.02 - ASA EE', - 'ASE': 'CIFO01.03.02.04.01.02 - CFC ASE EE', - 'ASSC': 'CIFO01.03.02.04.02.02 - CFC ASSC EE', + 'ASAFE': 'CIFO01.03.02.03.01.02 - ASA EE', + 'ASEFE': 'CIFO01.03.02.04.01.02 - CFC ASE EE', + 'ASSCFE': 'CIFO01.03.02.04.02.02 - CFC ASSC EE', 'EDEpe': 'CIFO01.03.02.07.01.01 - EDE prat. prof. PT', 'EDEps': 'CIFO01.03.02.07.02.01 - EDE stages PT', 'EDS': 'CIFO01.03.02.07.03.02 - EDS EE', 'CAS_FPP': 'CIFO01.03.02.01.03 - Mandats divers (CAS FPP)', - 'MP' : 'Matu. Santé + Travail social', - 'Direction': 'Direction', + 'MPTS' : 'CIFO01.04.03.06.02.01 - MPTS ASE', + 'MPS': 'CIFO01.04.03.06.03.01 - MPS Santé', } + ratios = _ratio_Ede_Ase_Assc() + export = OpenXMLExport('Imputations') export.write_line(EXPORT_SAP_HEADERS, bold=True) # Headers start_date = '20.08.2018' @@ -931,7 +958,7 @@ def export_sap(request): stat = '' for teacher in Teacher.objects.filter(archived=False): - activities, imputations = teacher.calc_imputations() + activities, imputations = teacher.calc_imputations(ratios) for key in imputations: if imputations[key] > 0: values = [