[#2658] Intégré django-reversion à l'app rh
[auf_rh_dae.git] / project / rh / masse_salariale.py
CommitLineData
98d6eb6c 1# -*- encoding: utf-8 -*-
899aea3b 2import csv
4ba84959 3import datetime
07f120f3 4import itertools
4ba84959
EMS
5import StringIO
6import time
98d6eb6c 7
4c17e518 8from auf.django.references import models as ref
d104b0ae 9from django.db.models import Q, Count
75f0e87b 10
4ba84959
EMS
11from project.rh import ods
12from project.rh import models as rh
98d6eb6c
JPC
13
14
15KEY_DATE_DEBUT = "debut"
16KEY_DATE_FIN = "fin"
4d17560e
JPC
17
18TYPE_REMUN_BSTG = (3,)
19TYPE_REMUN_MAD = (2,)
20TYPE_REMUN_BASE = (1,)
95ad7aab 21TYPE_REMUN_FONC_RESP = (7, 8)
4d17560e
JPC
22TYPE_REMUN_EXPAT = (4,)
23TYPE_REMUN_LOGEMENT = (6,)
9fd09bdc 24TYPE_REMUN_SCOLARITE = (5,)
4d17560e
JPC
25TYPE_REMUN_TRANSP = (9,)
26TYPE_REMUN_13E = (18,)
95ad7aab 27TYPE_PRIME_INTERIM = (19,)
a6927189
JPC
28TYPE_REMUN_ALL_INDEMNITES = list(itertools.chain(*(
29 TYPE_REMUN_BSTG, TYPE_REMUN_BASE, TYPE_REMUN_FONC_RESP,
07f120f3 30 TYPE_REMUN_EXPAT, TYPE_REMUN_LOGEMENT, TYPE_REMUN_TRANSP,
9fd09bdc 31 TYPE_REMUN_13E, TYPE_PRIME_INTERIM, TYPE_REMUN_SCOLARITE)))
95ad7aab
JPC
32TYPE_PRIME_INSTALLATION = (13,)
33TYPE_PRIME_DEMENAG = (15,)
34TYPE_PRIME_AVION = (14,)
07f120f3
JPC
35TYPE_PRIME_ALL = list(itertools.chain(
36 *(TYPE_PRIME_INSTALLATION, TYPE_PRIME_DEMENAG, TYPE_PRIME_AVION)
37 ))
38TYPE_CHARGE_PATRONALE = (17,)
39TYPE_CHARGE_ALL = list(itertools.chain(*(TYPE_CHARGE_PATRONALE,)))
40TYPE_NATURE_INDEMN = u"Indemnité"
899aea3b
JPC
41TYPE_NATURE_PAIEMENT = u"Accessoire"
42TYPE_NATURE_CHARGES = u"Charges"
5c5de149 43TYPE_NATURE_TRAITEMENT = u"Traitement"
eabb27fd 44HEADER_SEPARATOR = ('sep', ods.Separator(), {'columnwidth': '0.4cm'})
899aea3b 45
9163be6f 46
98d6eb6c
JPC
47class MasseSalariale():
48 """ Rapport de la masse salariale. """
49
c99116c3
JPC
50 def __init__(self, date_debut, date_fin, custom_filter=None,
51 ne_pas_grouper=False):
98d6eb6c
JPC
52 """ date_debut: date de début pour les données temporelles
53 date_fin: idem
df37184c 54 custom_filter: dictionnaire des paramètres à passer au queryset.
98d6eb6c 55 """
df37184c
JPC
56 if not date_debut and not date_fin:
57 return
58
98d6eb6c
JPC
59 date_debut = datetime.date(
60 *time.strptime(date_debut, "%d-%m-%Y")[0:3]
61 )
62 date_fin = datetime.date(*time.strptime(date_fin, "%d-%m-%Y")[0:3])
5c5de149 63
9163be6f 64 rapport_date_delta = date_fin - date_debut
e5a3a08e 65 rapport_date_delta += datetime.timedelta(days=1)
98d6eb6c
JPC
66
67 self.annee = date_fin.year
68
69 self.devise_base = rh.Devise.objects.filter(code='EUR')[0]
70 self.taux_change = {}
71
72 q_range = self.build_qs("date_", date_debut, date_fin)
73 q_range_d = self.build_qs("dossier__date_", date_debut, date_fin)
74 remunerations = rh.Remuneration.objects.filter(q_range) \
75 .filter(q_range_d) \
023bdc65
JPC
76
77 if custom_filter:
78 remunerations = remunerations.filter(**custom_filter)
d9de50fa 79 self.custom_filter = custom_filter
023bdc65 80
e5d10ada
JPC
81 self.region = None
82 self.implantation = None
83 if 'dossier__poste__implantation__region' in custom_filter:
84 self.region = ref.Region.objects.get(
85 id=custom_filter['dossier__poste__implantation__region']
86 )
87 if 'dossier__poste__implantation' in custom_filter:
88 self.implantation = ref.Implantation.objects.get(
89 id=custom_filter['dossier__poste__implantation']
90 )
91
023bdc65 92 remunerations = remunerations.exclude(supprime=True) \
899aea3b
JPC
93 .select_related(
94 "dossier", "dossier_employe", "dossier_poste", "type"
95 )
98d6eb6c 96
d9de50fa
JPC
97 custom_filter = {}
98 for k, v in self.custom_filter.items():
99 custom_filter[k.replace('dossier__', '')] = v
a6927189 100 count_dossiers_by_employe = dict((d['id'], d['count']) for d in
d9de50fa
JPC
101 rh.Dossier.objects.filter(q_range).values('id') \
102 .filter(**custom_filter) \
103 .annotate(count=Count('employe')))
104
c99116c3
JPC
105 contenu = {}
106
107 lineariser_dossiers = not ne_pas_grouper
108
98d6eb6c 109 for r in remunerations:
c99116c3
JPC
110 if lineariser_dossiers:
111 key = r.dossier.employe_id
112 else:
113 key = r.dossier_id
114
115 if key not in contenu:
116 contenu[key] = {
9163be6f
JPC
117 'dossiers': set(),
118 'remunerations': []
119 }
c99116c3
JPC
120 if lineariser_dossiers:
121 contenu[key]['remunerations'].append(r)
122 else:
123 if r.dossier_id == key:
124 contenu[key]['remunerations'].append(r)
125 contenu[key]['dossiers'].add(r.dossier)
9163be6f 126
98d6eb6c
JPC
127 self.rapport = []
128
57e2b793
JPC
129 pays_list = {}
130 for pays in ref.Pays.objects.all():
131 pays_list[pays.id] = pays
132
98d6eb6c
JPC
133 valeurs_point_par_imp = \
134 dict(
9163be6f
JPC
135 (v.implantation.id, v) for v in \
136 rh.ValeurPoint.objects.filter(annee=self.annee).all()
98d6eb6c 137 )
57e2b793
JPC
138
139 self.headers = (
3c8ffdfb
JPC
140 ('bureau', u"Bureau", {'columnwidth': '2cm'}),
141 ('pays', u"Pays", {'columnwidth': '3.5cm'}),
142 ('implantation', u"Implantation", {'columnwidth': '3cm'}),
5c5de149 143 ('valeur_point', u"Valeur du point",
3c8ffdfb
JPC
144 {'columnwidth': '2.3cm'}),
145 ('numero_employe', u"Numéro d'employé",
146 {'columnwidth': '2.4cm'}),
147 ('nom', u"Nom", {'columnwidth': '5.4cm'}),
148 ('prenom', u"Prénom", {'columnwidth': '4.8cm'}),
149 ('type_de_poste', u"Type de poste", {'columnwidth': '2.7cm'}),
150 ('intitule_de_poste', u"Intitulé du poste",
151 {'columnwidth': '7.25cm'}),
fa4ae139 152 ('niveau', u"Niveau actel", {'columnwidth': '1.75cm'}),
3c8ffdfb 153 ('point', u"Point", {'columnwidth': '1.75cm'}),
a6927189 154 ('regime_de_travail', u"Régime de travail annuel",
3c8ffdfb
JPC
155 {'columnwidth': '2cm'}),
156 ('local_expatrie', u"Local / Expatrié",
157 {'columnwidth': '2.25cm'}),
158 ('statut', u"Statut", {'columnwidth': '1.25cm'}),
159 ('date_fin_contrat', u"Date de fin de contrat",
160 {'columnwidth': '2cm'}),
e232bfe8 161 HEADER_SEPARATOR,
3c8ffdfb
JPC
162 ('date_debut', u"Date de début", {'columnwidth': '1.92cm'}),
163 ('date_fin', u"Date de fin", {'columnwidth': '1.92cm'}),
164 ('nb_jours', u"Nombre de jours", {'columnwidth': '2.82cm'}),
e232bfe8 165 HEADER_SEPARATOR,
3c8ffdfb 166 ('devise', u"Devise", {'columnwidth': '1.46cm'}),
bab8ce55 167 ('salaire_bstg_annuel', u"Salaire BSTG ANNUEL",
3c8ffdfb 168 {'columnwidth': '2.5cm'}),
a6927189 169 ('salaire_bstg_euro', u"Salaire BSTG EUR",
3c8ffdfb
JPC
170 {'columnwidth': '2.5cm'}),
171 ('organisme_bstg', u"Organisme BSTG",
172 {'columnwidth': '2.9cm'}),
e232bfe8 173 HEADER_SEPARATOR,
bab8ce55 174 ('salaire_theorique', u"Salaire théorique ANNUEL",
9fd09bdc 175 {'columnwidth': '2.5cm', 'background-color': '#ecab44'}),
3c8ffdfb 176 ('salaire_base_brut', u"Salaire de base brut",
9fd09bdc 177 {'columnwidth': '2.5cm', 'background-color': '#ecab44'}),
3c8ffdfb 178 ('salaire_complementaire', u"Salaire complémentaire",
9fd09bdc 179 {'columnwidth': '2.5cm', 'background-color': '#ecab44'}),
e232bfe8 180 HEADER_SEPARATOR,
3c8ffdfb 181 ('indemnite_fonctions', u"Indemnités de fonctions",
9fd09bdc 182 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 183 ('indemnite_expat', u"Indemnités d'expatriation",
9fd09bdc
JPC
184 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
185 ('indemnite_scolarite', u"Indemnités de frais de scolarité",
186 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 187 ('indemnite_logement', u"Indemnités de logement",
9fd09bdc 188 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 189 ('indemnite_transp', u"Indemnités de transport",
9fd09bdc 190 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 191 ('indemnite_13e', u"Indemnités 13e mois",
9fd09bdc 192 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 193 ('prime_interim', u"Prime d'intérim",
9fd09bdc 194 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 195 ('indemnite_autre', u"Autre indemnités",
9fd09bdc 196 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 197 ('indemnite_sous_total', u"Sous-total d'indemnités",
9fd09bdc 198 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
e232bfe8 199 HEADER_SEPARATOR,
3c8ffdfb 200 ('prime_installation', u"Prime d'installation",
9fd09bdc 201 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 202 ('prime_demenagement', u"Prime de déménagement",
9fd09bdc 203 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 204 ('prime_avion', u"Prime d'avion",
9fd09bdc 205 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 206 ('prime_autre', u"Autre prime",
9fd09bdc 207 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 208 ('prime_sous_total', u"Total des primes",
9fd09bdc 209 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
e232bfe8 210 HEADER_SEPARATOR,
3c8ffdfb 211 ('charges_patronales', u"Charges patronales",
9fd09bdc 212 {'columnwidth': '2.5cm', 'background-color': '#fb680f'}),
3c8ffdfb 213 ('charges_autre', u"Autres charges patronales",
9fd09bdc 214 {'columnwidth': '2.5cm', 'background-color': '#fb680f'}),
3c8ffdfb 215 ('charges_sous_total', u"Sous-total des charges patronales",
9fd09bdc 216 {'columnwidth': '2.5cm', 'background-color': '#fb680f'}),
e232bfe8 217 HEADER_SEPARATOR,
bab8ce55 218 ('sous_total_traitement_annee', u"Total traitements",
7ab6c3c6 219 {'background-color': '#ecab44'}),
bab8ce55 220 ('sous_total_indemnite_annee', u"Total indemnités",
7ab6c3c6 221 {'background-color': '#fff840'}),
bab8ce55 222 ('sous_total_accessoire_annee', u"Total accessoires",
7ab6c3c6 223 {'background-color': '#d7fb0f'}),
bab8ce55 224 ('sous_total_charges_annee', u"Total charges",
7ab6c3c6 225 {'background-color': '#fb680f'}),
e232bfe8 226 HEADER_SEPARATOR,
bab8ce55 227 ('masse_salariale', u"Masse salariale ANNUELLE",
9fd09bdc 228 {'columnwidth': '2.5cm', 'background-color': '#e6c6ed'}),
bab8ce55 229 ('masse_salariale_annee', u"Masse salariale",
9fd09bdc 230 {'columnwidth': '2.5cm', 'background-color': '#e6c6ed'}),
cb9cce2b 231 ('masse_salariale_annee_euro', u"Masse salariale %s EUR" % \
9fd09bdc
JPC
232 self.annee, {
233 'columnwidth': '2.5cm',
234 'background-color': '#e6c6ed'
235 }
236 ),
57e2b793
JPC
237 )
238
778fb9d6
JPC
239 grand_total = 0.0
240 grand_total_euro = 0.0
241
d9de50fa
JPC
242 if not lineariser_dossiers:
243 for dossier_id, count in count_dossiers_by_employe.items():
244 if dossier_id not in contenu or \
245 len(contenu[dossier_id]['dossiers']) != count:
246 not_in = []
247 if dossier_id in contenu:
248 for d in contenu[dossier_id]['dossiers']:
249 not_in.append(d.id)
250 custom_filter = {}
251 for k, v in self.custom_filter.items():
252 custom_filter[k.replace('dossier__', '')] = v
253
254 employe_id = rh.Dossier.objects.values('employe').filter(
255 id=dossier_id).all()[0]['employe']
256 dossiers = rh.Dossier.objects.filter(q_range) \
257 .filter(employe=employe_id) \
258 .filter(**custom_filter) \
259 .all()
260 for d in dossiers:
261 if d.id not in contenu:
262 contenu[d.id] = {
263 'dossiers': set((d,)),
264 'remunerations': []
265 }
266 else:
267 contenu[d.id]['dossiers'].add(d)
268
bab8ce55
JPC
269 postes = rh.Poste.objects
270
271 custom_filter = {}
272 for k, v in self.custom_filter.items():
273 custom_filter[k.replace('dossier__poste__', '')] = v
274
275 if custom_filter:
276 postes = postes.filter(**custom_filter)
277
278 postes_vacants = [p for p in postes.filter(q_range).all()
279 if p.is_vacant()]
280 remuneration_base = rh.TypeRemuneration.objects.get(
281 id=TYPE_REMUN_BASE[0])
282 remuneration_indem = rh.TypeRemuneration(
283 nature_remuneration=TYPE_NATURE_INDEMN)
284 remuneration_charge = rh.TypeRemuneration(
285 nature_remuneration=TYPE_NATURE_CHARGES)
286 for p in postes_vacants:
287 d = rh.Dossier()
288 d.employe = rh.Employe()
289 d.statut = rh.Statut()
290 d.poste = p
291 d.classement = p.classement_max
292 d.point = p.valeur_point_max
9ff35df5
EMS
293 if p.devise_max:
294 remunerations = [
295 rh.Remuneration(
296 montant=p.salaire_max, devise=p.devise_max,
297 type=remuneration_base
298 ),
299 rh.Remuneration(
300 montant=p.indemn_max, devise=p.devise_max,
301 type=remuneration_indem
302 ),
303 rh.Remuneration(
304 montant=p.autre_max, devise=p.devise_max,
305 type=remuneration_charge
306 )
307 ]
308 else:
309 remunerations = [
310 rh.Remuneration(
311 montant=0, devise=self.devise_base, type=type
312 )
313 for type in (
314 remuneration_base, remuneration_indem,
315 remuneration_charge
316 )
317 ]
bab8ce55 318 contenu['p_%s' % p.id] = {
9ff35df5
EMS
319 'dossiers': set([d]),
320 'remunerations': remunerations
321 }
bab8ce55 322
c99116c3 323 for item in contenu.values():
98d6eb6c
JPC
324 dossiers = item['dossiers']
325 remuns = item['remunerations']
07f120f3 326
86bea0ed
EMS
327 if not dossiers:
328 continue
329 dossier = list(dossiers)[0]
07f120f3
JPC
330 for d in dossiers:
331 if d.principal:
86bea0ed 332 dossier = d
07f120f3 333
d3e403b2 334 regime = (float(dossier.regime_travail) / 100)
9163be6f 335
f7fc1166 336 if dossier.statut_residence == "expat":
98d6eb6c
JPC
337 statut = "E"
338 else:
339 statut = "L"
340
9163be6f
JPC
341 #on détermine la date du début et fin du dossier si année en cours
342 try:
343 d_date_fin = dossier.date_fin \
344 if dossier.date_fin.year == date_fin.year else None
345 except AttributeError:
346 d_date_fin = None
347 try:
348 d_date_debut = dossier.date_debut \
349 if dossier.date_debut.year == date_fin.year else None
350 except AttributeError:
351 d_date_debut = None
98d6eb6c
JPC
352
353 pays = \
354 pays_list[dossier.poste.implantation.adresse_physique_pays.id]
355
356 #on détermine si les rémunérations sont tous dans la même devise
d9de50fa
JPC
357 try:
358 devise = remuns[0].devise
359 except IndexError:
360 devise = self.devise_base
98d6eb6c
JPC
361 meme_devise = True
362 for r in remuns[1:]:
363 if devise != r.devise:
364 meme_devise = False
365
366 if not meme_devise:
367 for r in remuns:
368 self.convertir(r)
a6927189 369 devise = remuns[0].devise
98d6eb6c
JPC
370
371 bstg_dossier = None
372 for d in dossiers:
373 if d.organisme_bstg:
374 bstg_dossier = d
375
9163be6f 376 bstg_remun = None
98d6eb6c 377 if bstg_dossier:
9163be6f 378 for r in bstg_dossier.rh_remunerations.all():
a6927189
JPC
379 if r.type.id in TYPE_REMUN_MAD:
380 bstg_remun = rh.Remuneration(
381 montant=float(r.montant),
382 devise=r.devise
383 )
98d6eb6c 384
958e67e8 385 if bstg_remun:
df37184c 386 bstg_remun_euro = rh.Remuneration(
a6927189
JPC
387 montant=float(bstg_remun.montant),
388 devise=bstg_remun.devise
df37184c 389 )
958e67e8 390 self.convertir(bstg_remun_euro)
958e67e8 391
4d17560e
JPC
392 salaire_complement = 0.0
393 salaire_base = 0.0
394 indemnites = {
395 'fonc_resp': 0.0,
396 'expat': 0.0,
9fd09bdc 397 'scolarite': 0.0,
4d17560e
JPC
398 'logement': 0.0,
399 'transp': 0.0,
400 '13e': 0.0,
401 'autre_recurr': 0.0,
07f120f3 402 'interim': 0.0,
4d17560e 403 }
95ad7aab
JPC
404
405 primes = {
95ad7aab
JPC
406 'installation': 0.0,
407 'demenagement': 0.0,
408 'avion': 0.0,
409 'autre': 0.0,
410 }
07f120f3
JPC
411 charges = {
412 'patronale': 0.0,
413 'autre': 0.0,
414 }
5c5de149
JPC
415
416 total_remun_annee = {
417 'traitement': 0.0,
418 'indemnite': 0.0,
419 'accessoire': 0.0,
420 'charges': 0.0,
421 }
422
b4869de0 423 #Calcul du nombre de jours pour ce dossier.
34b3b5c6
JPC
424 dossier_date_delta = self.calculer_nombre_jours(
425 dossier.date_debut, dossier.date_fin,
426 date_debut, date_fin)
b4869de0 427
2139e9a7
JPC
428 masse_salariale = 0.0
429 masse_salariale_annee = 0.0
4d17560e 430 for r in remuns:
2139e9a7 431 montant = float(r.montant)
fa4ae139
JPC
432 if r.date_fin is None and dossier.date_fin is not None:
433 r.date_fin = min(date_fin, dossier.date_fin)
2139e9a7 434 facteur = self.calculer_nombre_jours(
fa4ae139
JPC
435 r.date_debut, r.date_fin,
436 date_debut, date_fin).days \
437 / float(rapport_date_delta.days)
95ad7aab 438
a6927189 439 if r.type_id in TYPE_REMUN_BSTG:
2139e9a7 440 salaire_complement += montant * facteur
a6927189
JPC
441
442 if r.type_id not in TYPE_REMUN_MAD:
2139e9a7 443 masse_salariale += montant
44083888 444 masse_salariale_annee += montant * regime
4d17560e 445
95ad7aab 446 if r.type_id in TYPE_REMUN_BASE:
2139e9a7 447 salaire_base += montant * facteur
4d17560e 448
95ad7aab 449 if r.type_id in TYPE_REMUN_FONC_RESP:
2139e9a7 450 indemnites['fonc_resp'] += montant * facteur
4d17560e 451
95ad7aab 452 if r.type_id in TYPE_REMUN_EXPAT:
2139e9a7 453 indemnites['expat'] += montant * facteur
4d17560e 454
9fd09bdc 455 if r.type_id in TYPE_REMUN_SCOLARITE:
2139e9a7 456 indemnites['scolarite'] += montant * facteur
9fd09bdc 457
95ad7aab 458 if r.type_id in TYPE_REMUN_LOGEMENT:
2139e9a7 459 indemnites['logement'] += montant * facteur
4d17560e 460
95ad7aab 461 if r.type_id in TYPE_REMUN_TRANSP:
2139e9a7 462 indemnites['transp'] += montant * facteur
4d17560e 463
95ad7aab 464 if r.type_id in TYPE_REMUN_13E:
2139e9a7 465 indemnites['13e'] += montant * facteur
4d17560e 466
95ad7aab 467 if r.type_id in TYPE_PRIME_INTERIM:
2139e9a7 468 indemnites['interim'] += montant * facteur
07f120f3
JPC
469
470 if r.type_id not in TYPE_REMUN_ALL_INDEMNITES \
a6927189
JPC
471 and r.type.nature_remuneration == TYPE_NATURE_INDEMN \
472 and r.type_id != TYPE_REMUN_MAD:
2139e9a7 473 indemnites['autre_recurr'] += montant * facteur
95ad7aab
JPC
474
475 if r.type_id in TYPE_PRIME_INSTALLATION:
2139e9a7 476 primes['installation'] += montant * facteur
95ad7aab
JPC
477
478 if r.type_id in TYPE_PRIME_DEMENAG:
2139e9a7 479 primes['demenagement'] += montant * facteur
95ad7aab
JPC
480
481 if r.type_id in TYPE_PRIME_AVION:
2139e9a7 482 primes['avion'] += montant * facteur
95ad7aab 483
07f120f3 484 if r.type_id not in TYPE_PRIME_ALL and \
95ad7aab 485 r.type.nature_remuneration == TYPE_NATURE_PAIEMENT:
2139e9a7 486 primes['autre'] += montant * facteur
95ad7aab 487
07f120f3 488 if r.type_id in TYPE_CHARGE_PATRONALE:
2139e9a7 489 charges['patronale'] += montant * facteur
07f120f3
JPC
490
491 if r.type_id not in TYPE_CHARGE_ALL and \
492 r.type.nature_remuneration == TYPE_NATURE_CHARGES:
2139e9a7 493 charges['autre'] += montant * facteur
899aea3b 494
494eba48
JPC
495 if r.type.nature_remuneration == TYPE_NATURE_INDEMN or \
496 r.type.id in (7,):
2139e9a7 497 total_remun_annee['indemnite'] += montant * facteur
5c5de149
JPC
498
499 if r.type.nature_remuneration == TYPE_NATURE_PAIEMENT:
2139e9a7 500 total_remun_annee['accessoire'] += montant * facteur
5c5de149
JPC
501
502 if r.type.nature_remuneration == TYPE_NATURE_CHARGES:
2139e9a7 503 total_remun_annee['charges'] += montant * facteur
5c5de149 504
a6927189 505 if (r.type.nature_remuneration == TYPE_NATURE_TRAITEMENT and
494eba48 506 r.type.id not in (TYPE_REMUN_MAD, 7)
a6927189 507 ) or r.type_id == TYPE_REMUN_BSTG:
2139e9a7 508 total_remun_annee['traitement'] += montant * facteur
5c5de149 509
4d17560e
JPC
510 total_indemnites = sum(indemnites.values())
511
31566c3d
JPC
512 masse_salariale_euro = rh.Remuneration(
513 montant=masse_salariale_annee, devise=devise)
023bdc65
JPC
514 self.convertir(masse_salariale_euro)
515
22b53270
JPC
516 if dossier.classement and dossier.classement.coefficient:
517 coefficient = dossier.classement.coefficient
518 else:
519 coefficient = ""
520
521 #todo valeur du point si pas présent
522 valeur_point = valeurs_point_par_imp.get(
523 dossier.poste.implantation_id
c48caab9
JPC
524 )
525 if valeur_point:
526 valeur_point_label = "%s %s" % (valeur_point.valeur,
527 valeur_point.devise.code)
528 else:
529 valeur_point_label = ""
22b53270 530
3244a3c2 531 salaire_theorique = (
22b53270 532 round(valeur_point.valeur * int(coefficient) * regime, 2) \
3244a3c2 533 if valeur_point and coefficient and regime else None)
22b53270 534
57e2b793
JPC
535 item_rapport = {
536 'bureau': dossier.poste.implantation.region.code,
537 'pays': unicode(pays),
538 'implantation': dossier.poste.implantation.nom_court,
539 'type_implantation': dossier.poste.implantation.type,
540 #'imputation': None,
c48caab9 541 'valeur_point': valeur_point_label,
57e2b793
JPC
542 'numero_employe': dossier.employe_id,
543 'nom': dossier.employe.nom.upper(),
544 'prenom': dossier.employe.prenom,
545 'type_de_poste': dossier.poste.type_poste.nom,
f7fc1166
JPC
546 'intitule_de_poste': dossier.poste.nom_feminin
547 if dossier.employe.genre == "F" else
548 dossier.poste.nom,
bab8ce55 549 'niveau': dossier.classement,
57e2b793
JPC
550 'point': coefficient,
551 'regime_de_travail': "%s %%" % int(regime * 100),
552 'local_expatrie': statut,
553 'statut': dossier.statut.code,
554 'date_fin_contrat': dossier.date_fin or "",
555 'date_debut': d_date_debut or "",
556 'date_fin': d_date_fin or "",
b4869de0 557 'nb_jours': dossier_date_delta.days,
d9de50fa 558 'devise': devise.code,
57e2b793
JPC
559 'salaire_bstg_annuel': bstg_remun.montant \
560 if bstg_remun else "",
a6927189 561 'salaire_bstg_euro': bstg_remun_euro.montant \
57e2b793
JPC
562 if bstg_remun else "",
563 'organisme_bstg': dossier.organisme_bstg or "",
564 'salaire_theorique': salaire_theorique,
565 'salaire_base_brut': \
0c5e0d8e 566 salaire_base * regime,
57e2b793 567 'salaire_complementaire': \
0c5e0d8e 568 salaire_complement * regime,
57e2b793
JPC
569 #'salaire_total': None
570 'indemnite_fonctions': indemnites['fonc_resp'] * \
0c5e0d8e
JPC
571 regime,
572 'indemnite_expat': indemnites['expat'] * regime,
9fd09bdc 573 'indemnite_scolarite': indemnites['scolarite'] * \
0c5e0d8e 574 regime,
57e2b793 575 'indemnite_logement': indemnites['logement'] * \
0c5e0d8e
JPC
576 regime,
577 'indemnite_transp': indemnites['transp'] * regime,
578 'indemnite_13e': indemnites['13e'] * regime,
579 'prime_interim': indemnites['interim'] * regime,
57e2b793 580 'indemnite_autre': indemnites['autre_recurr'] * \
0c5e0d8e
JPC
581 regime,
582 'indemnite_sous_total': total_indemnites * regime,
57e2b793 583 'total_brut': (
95ad7aab
JPC
584 total_indemnites + salaire_base +
585 salaire_complement
0c5e0d8e
JPC
586 ) * regime,
587 'prime_installation': primes['installation'] * regime,
588 'prime_demenagement': primes['demenagement'] * regime,
589 'prime_avion': primes['avion'] * regime,
590 'prime_autre': primes['autre'] * regime,
591 'prime_sous_total': sum(primes.values()) * regime,
2139e9a7
JPC
592 'charges_patronales': charges['patronale'] * regime,
593 'charges_autre': charges['autre'] * regime,
594 'charges_sous_total': sum(charges.values()) * regime,
5c5de149 595 'sous_total_traitement_annee': \
2139e9a7 596 total_remun_annee['traitement'] * regime,
5c5de149 597 'sous_total_indemnite_annee': \
2139e9a7 598 total_remun_annee['indemnite'] * regime,
5c5de149 599 'sous_total_accessoire_annee': \
2139e9a7 600 total_remun_annee['accessoire'] * regime,
5c5de149 601 'sous_total_charges_annee': \
2139e9a7
JPC
602 total_remun_annee['charges'] * regime,
603 'masse_salariale': masse_salariale * regime,
604 'masse_salariale_annee': masse_salariale_annee * regime,
5c5de149 605 'masse_salariale_annee_euro': \
0c5e0d8e 606 masse_salariale_euro.montant * regime,
43b30700 607 'sep': ods.Separator(),
57e2b793 608 }
98d6eb6c 609
c99116c3 610 grand_total_euro += round(masse_salariale_euro.montant * regime
b4869de0
JPC
611 * (
612 dossier_date_delta.days / rapport_date_delta.days
613 ), 2)
778fb9d6 614
98d6eb6c
JPC
615 self.rapport.append(item_rapport)
616
3b1a2937
JPC
617 self.rapport = sorted(self.rapport, key=lambda r: r['nom'])
618
778fb9d6
JPC
619 self.grand_totaux = (grand_total, grand_total_euro)
620
2139e9a7
JPC
621 def calculer_nombre_jours(self, debut, fin, debut_limite, fin_limite):
622 """Calcul le nombre de jours entre fin et debut, sans dépasser
34b3b5c6
JPC
623 les limites. Si debut ou fin set null, on prend debut_limite/fin_limi
624 """
625
626 if not debut:
627 debut = debut_limite
628 if not fin:
629 fin = fin_limite
630
631 if debut < debut_limite:
632 debut = debut_limite
633 if fin > fin_limite:
634 fin = fin_limite
635
636 fin += datetime.timedelta(days=1)
637 return fin - debut
638
98d6eb6c
JPC
639 def build_qs(self, prefix, date_debut, date_fin):
640 date_debut_null = \
641 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_DEBUT): True})
642 date_fin_null = \
643 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_FIN): True})
644 date_debut_superieure_ou_egale_a_borne_gauche = \
645 Q(**{"%s%s__gte" % (prefix, KEY_DATE_DEBUT): date_debut})
646 date_debut_inferieure_ou_egale_a_borne_gauche = \
647 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_debut})
648 date_fin_superieure_ou_egale_a_borne_gauche = \
649 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_debut})
650 date_fin_inferieure_ou_egale_a_borne_droite = \
651 Q(**{"%s%s__lte" % (prefix, KEY_DATE_FIN): date_fin})
652 date_debut_inferieure_ou_egale_a_borne_droite = \
653 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_fin})
654 date_fin_superieure_ou_egale_a_borne_droite = \
655 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_fin})
656
657 q_range = \
658 (
0c5e0d8e 659 date_debut_null & date_fin_null
98d6eb6c 660 ) | (
0c5e0d8e
JPC
661 date_fin_superieure_ou_egale_a_borne_gauche &
662 date_fin_inferieure_ou_egale_a_borne_droite &
663 (
664 date_debut_inferieure_ou_egale_a_borne_gauche |
665 date_debut_null
666 )
98d6eb6c 667 ) | (
0c5e0d8e
JPC
668 date_debut_superieure_ou_egale_a_borne_gauche &
669 date_debut_inferieure_ou_egale_a_borne_droite &
670 (
671 date_fin_superieure_ou_egale_a_borne_droite |
672 date_fin_null
673 )
98d6eb6c 674 ) | (
0c5e0d8e
JPC
675 date_debut_inferieure_ou_egale_a_borne_gauche &
676 date_fin_superieure_ou_egale_a_borne_droite
98d6eb6c 677 ) | (
0c5e0d8e
JPC
678 date_debut_null &
679 date_fin_superieure_ou_egale_a_borne_droite
98d6eb6c 680 ) | (
0c5e0d8e
JPC
681 date_debut_inferieure_ou_egale_a_borne_gauche &
682 date_fin_null
98d6eb6c 683 )
98d6eb6c
JPC
684 return q_range
685
686 def convertir(self, remuneration):
9163be6f 687 if remuneration.devise != self.devise_base:
8b6e7b9a
JPC
688 try:
689 remuneration.montant = float(remuneration.montant) * \
690 self.trouver_taux(remuneration.devise).taux
691 remuneration.devise = self.devise_base
692 except AttributeError:
693 pass
98d6eb6c
JPC
694
695 def trouver_taux(self, devise):
696 if devise.code not in self.taux_change:
8b6e7b9a
JPC
697 try:
698 t = rh.TauxChange.objects.filter(
699 devise=devise, annee=self.annee
700 )[0]
701 except IndexError:
702 return None
98d6eb6c
JPC
703 self.taux_change[devise.code] = t
704 return self.taux_change[devise.code]
899aea3b
JPC
705
706 def csv(self):
707 self.csv_handle = StringIO.StringIO()
023bdc65
JPC
708 csv_writer = csv.writer(self.csv_handle, delimiter=",",
709 doublequote=False, escapechar="\\", quoting=csv.QUOTE_ALL,
710 )
711 header = [v[0] for v in self.rapport[0]]
712 csv_writer.writerow(header)
713 for row in self.rapport:
714 values = [v[1] for v in row]
715 csv_writer.writerow(
716 [unicode(r).encode('utf-8') for r in values]
717 )
c99116c3
JPC
718
719 def ods(self):
3c8ffdfb 720 self.doc = ods.OpenDocumentSpreadsheet()
e5d10ada
JPC
721
722 nom = u"Masse salariale %s" % self.annee
723 if self.region:
fba0dde4 724 nom += u" %s" % self.region
e5d10ada 725 elif self.implantation:
fba0dde4 726 nom += u" %s" % self.implantation
e5d10ada
JPC
727
728 table = self.doc.add_table(name=nom)
3c8ffdfb
JPC
729
730 for h in self.headers:
731 if len(h) > 2:
732 table.add_column(**h[2])
733
6d7419c4
JPC
734 table.add_row([h[1] for h in self.headers], rowheight='2cm')
735
736 for r in self.rapport:
737 table.add_row([r[h[0]] for h in self.headers])
3c8ffdfb 738
028b8438 739 #a.doc.write('hello_world.ods')