New accounting rules

This commit is contained in:
alazo 2018-06-06 08:41:31 +02:00 committed by Claude Paroz
parent 42c55f5521
commit 261ed1e99b
3 changed files with 97 additions and 53 deletions

View file

@ -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'),
)

View file

@ -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')

View file

@ -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 = [