[#2658] Retrait du hack app_label() dans rh.models
[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
JPC
7
8from datamaster_modeles import models as ref
4ba84959
EMS
9from django.db.models import Q, Count
10
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')