Masse salariale: ajout ne_pas_grouper filtre
[auf_rh_dae.git] / project / rh / masse_salariale.py
CommitLineData
98d6eb6c
JPC
1# -*- encoding: utf-8 -*-
2import time
3import datetime
899aea3b
JPC
4import csv
5import StringIO
07f120f3 6import itertools
98d6eb6c
JPC
7
8from django.db.models import Q
9
10from datamaster_modeles import models as ref
c99116c3 11import rh.ods as ods
98d6eb6c
JPC
12import rh.models as rh
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,)
07f120f3
JPC
28TYPE_REMUN_ALL_INDEMNITES = list(itertools.chain(*(TYPE_REMUN_BSTG,
29 TYPE_REMUN_MAD, TYPE_REMUN_BASE, TYPE_REMUN_FONC_RESP,
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"
43b30700 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)
79
80 remunerations = remunerations.exclude(supprime=True) \
899aea3b
JPC
81 .select_related(
82 "dossier", "dossier_employe", "dossier_poste", "type"
83 )
98d6eb6c 84
c99116c3
JPC
85 contenu = {}
86
87 lineariser_dossiers = not ne_pas_grouper
88
98d6eb6c 89 for r in remunerations:
c99116c3
JPC
90 if lineariser_dossiers:
91 key = r.dossier.employe_id
92 else:
93 key = r.dossier_id
94
95 if key not in contenu:
96 contenu[key] = {
9163be6f
JPC
97 'dossiers': set(),
98 'remunerations': []
99 }
c99116c3
JPC
100 if lineariser_dossiers:
101 contenu[key]['remunerations'].append(r)
102 else:
103 if r.dossier_id == key:
104 contenu[key]['remunerations'].append(r)
105 contenu[key]['dossiers'].add(r.dossier)
9163be6f 106
98d6eb6c
JPC
107 self.rapport = []
108
57e2b793
JPC
109 pays_list = {}
110 for pays in ref.Pays.objects.all():
111 pays_list[pays.id] = pays
112
98d6eb6c
JPC
113 valeurs_point_par_imp = \
114 dict(
9163be6f
JPC
115 (v.implantation.id, v) for v in \
116 rh.ValeurPoint.objects.filter(annee=self.annee).all()
98d6eb6c 117 )
57e2b793
JPC
118
119 self.headers = (
3c8ffdfb
JPC
120 ('bureau', u"Bureau", {'columnwidth': '2cm'}),
121 ('pays', u"Pays", {'columnwidth': '3.5cm'}),
122 ('implantation', u"Implantation", {'columnwidth': '3cm'}),
5c5de149 123 ('valeur_point', u"Valeur du point",
3c8ffdfb
JPC
124 {'columnwidth': '2.3cm'}),
125 ('numero_employe', u"Numéro d'employé",
126 {'columnwidth': '2.4cm'}),
127 ('nom', u"Nom", {'columnwidth': '5.4cm'}),
128 ('prenom', u"Prénom", {'columnwidth': '4.8cm'}),
129 ('type_de_poste', u"Type de poste", {'columnwidth': '2.7cm'}),
130 ('intitule_de_poste', u"Intitulé du poste",
131 {'columnwidth': '7.25cm'}),
fa4ae139 132 ('niveau', u"Niveau actel", {'columnwidth': '1.75cm'}),
3c8ffdfb 133 ('point', u"Point", {'columnwidth': '1.75cm'}),
fa4ae139 134 ('regime_de_travail', u"Régime de travail actuel",
3c8ffdfb
JPC
135 {'columnwidth': '2cm'}),
136 ('local_expatrie', u"Local / Expatrié",
137 {'columnwidth': '2.25cm'}),
138 ('statut', u"Statut", {'columnwidth': '1.25cm'}),
139 ('date_fin_contrat', u"Date de fin de contrat",
140 {'columnwidth': '2cm'}),
e232bfe8 141 HEADER_SEPARATOR,
3c8ffdfb
JPC
142 ('date_debut', u"Date de début", {'columnwidth': '1.92cm'}),
143 ('date_fin', u"Date de fin", {'columnwidth': '1.92cm'}),
144 ('nb_jours', u"Nombre de jours", {'columnwidth': '2.82cm'}),
e232bfe8 145 HEADER_SEPARATOR,
3c8ffdfb 146 ('devise', u"Devise", {'columnwidth': '1.46cm'}),
cb9cce2b 147 ('salaire_bstg_annuel', u"Salaire BSTG ANNUEL",
3c8ffdfb 148 {'columnwidth': '2.5cm'}),
cb9cce2b 149 ('salaire_bstg_total', u"Salaire BSTG total ",
3c8ffdfb
JPC
150 {'columnwidth': '2.5cm'}),
151 ('organisme_bstg', u"Organisme BSTG",
152 {'columnwidth': '2.9cm'}),
e232bfe8 153 HEADER_SEPARATOR,
fa4ae139 154 ('salaire_theorique', u"Salaire théorique actuel",
9fd09bdc 155 {'columnwidth': '2.5cm', 'background-color': '#ecab44'}),
3c8ffdfb 156 ('salaire_base_brut', u"Salaire de base brut",
9fd09bdc 157 {'columnwidth': '2.5cm', 'background-color': '#ecab44'}),
3c8ffdfb 158 ('salaire_complementaire', u"Salaire complémentaire",
9fd09bdc 159 {'columnwidth': '2.5cm', 'background-color': '#ecab44'}),
e232bfe8 160 HEADER_SEPARATOR,
3c8ffdfb 161 ('indemnite_fonctions', u"Indemnités de fonctions",
9fd09bdc 162 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 163 ('indemnite_expat', u"Indemnités d'expatriation",
9fd09bdc
JPC
164 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
165 ('indemnite_scolarite', u"Indemnités de frais de scolarité",
166 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 167 ('indemnite_logement', u"Indemnités de logement",
9fd09bdc 168 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 169 ('indemnite_transp', u"Indemnités de transport",
9fd09bdc 170 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 171 ('indemnite_13e', u"Indemnités 13e mois",
9fd09bdc 172 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 173 ('prime_interim', u"Prime d'intérim",
9fd09bdc 174 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 175 ('indemnite_autre', u"Autre indemnités",
9fd09bdc 176 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
3c8ffdfb 177 ('indemnite_sous_total', u"Sous-total d'indemnités",
9fd09bdc 178 {'columnwidth': '2.5cm', 'background-color': '#fff840'}),
e232bfe8 179 HEADER_SEPARATOR,
3c8ffdfb 180 ('prime_installation', u"Prime d'installation",
9fd09bdc 181 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 182 ('prime_demenagement', u"Prime de déménagement",
9fd09bdc 183 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 184 ('prime_avion', u"Prime d'avion",
9fd09bdc 185 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 186 ('prime_autre', u"Autre prime",
9fd09bdc 187 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
3c8ffdfb 188 ('prime_sous_total', u"Total des primes",
9fd09bdc 189 {'columnwidth': '2.5cm', 'background-color': '#d7fb0f'}),
e232bfe8 190 HEADER_SEPARATOR,
3c8ffdfb 191 ('charges_patronales', u"Charges patronales",
9fd09bdc 192 {'columnwidth': '2.5cm', 'background-color': '#fb680f'}),
3c8ffdfb 193 ('charges_autre', u"Autres charges patronales",
9fd09bdc 194 {'columnwidth': '2.5cm', 'background-color': '#fb680f'}),
3c8ffdfb 195 ('charges_sous_total', u"Sous-total des charges patronales",
9fd09bdc 196 {'columnwidth': '2.5cm', 'background-color': '#fb680f'}),
e232bfe8 197 HEADER_SEPARATOR,
2139e9a7
JPC
198 ('sous_total_traitement_annee', u"Total traitement %s" % \
199 self.annee,
9fd09bdc 200 {'background-color': '#f88680'}),
2139e9a7
JPC
201 ('sous_total_indemnite_annee', u"Total indemnités %s" % \
202 self.annee,
9fd09bdc 203 {'background-color': '#f88680'}),
2139e9a7
JPC
204 ('sous_total_accessoire_annee', u"Total accessoires %s" % \
205 self.annee,
9fd09bdc 206 {'background-color': '#f88680'}),
2139e9a7
JPC
207 ('sous_total_charges_annee', u"Total charges %s" % \
208 self.annee,
9fd09bdc 209 {'background-color': '#f88680'}),
e232bfe8 210 HEADER_SEPARATOR,
cb9cce2b 211 ('masse_salariale', u"Masse salariale annuelle",
9fd09bdc 212 {'columnwidth': '2.5cm', 'background-color': '#e6c6ed'}),
3c8ffdfb 213 ('masse_salariale_annee', u"Masse salariale %s" % self.annee,
9fd09bdc 214 {'columnwidth': '2.5cm', 'background-color': '#e6c6ed'}),
cb9cce2b 215 ('masse_salariale_annee_euro', u"Masse salariale %s EUR" % \
9fd09bdc
JPC
216 self.annee, {
217 'columnwidth': '2.5cm',
218 'background-color': '#e6c6ed'
219 }
220 ),
57e2b793
JPC
221 )
222
778fb9d6
JPC
223 grand_total = 0.0
224 grand_total_euro = 0.0
225
c99116c3 226 for item in contenu.values():
98d6eb6c
JPC
227 dossiers = item['dossiers']
228 remuns = item['remunerations']
07f120f3 229
07f120f3
JPC
230 for d in dossiers:
231 if d.principal:
232 dossier = list(dossiers)[0]
233
95ad7aab 234 regime = float(dossier.poste.regime_travail) / 100
9163be6f 235
f7fc1166 236 if dossier.statut_residence == "expat":
98d6eb6c
JPC
237 statut = "E"
238 else:
239 statut = "L"
240
9163be6f
JPC
241 #on détermine la date du début et fin du dossier si année en cours
242 try:
243 d_date_fin = dossier.date_fin \
244 if dossier.date_fin.year == date_fin.year else None
245 except AttributeError:
246 d_date_fin = None
247 try:
248 d_date_debut = dossier.date_debut \
249 if dossier.date_debut.year == date_fin.year else None
250 except AttributeError:
251 d_date_debut = None
98d6eb6c
JPC
252
253 pays = \
254 pays_list[dossier.poste.implantation.adresse_physique_pays.id]
255
256 #on détermine si les rémunérations sont tous dans la même devise
257 devise = remuns[0].devise
258 meme_devise = True
259 for r in remuns[1:]:
260 if devise != r.devise:
261 meme_devise = False
262
263 if not meme_devise:
264 for r in remuns:
265 self.convertir(r)
266
267 bstg_dossier = None
268 for d in dossiers:
269 if d.organisme_bstg:
270 bstg_dossier = d
271
9163be6f 272 bstg_remun = None
98d6eb6c 273 if bstg_dossier:
9163be6f 274 for r in bstg_dossier.rh_remunerations.all():
958e67e8 275 if r.type.id in TYPE_REMUN_BSTG:
9163be6f 276 bstg_remun = r
98d6eb6c 277
958e67e8 278 if bstg_remun:
df37184c
JPC
279 bstg_remun_euro = rh.Remuneration(
280 montant=bstg_remun.montant, devise=bstg_remun.devise
281 )
958e67e8 282 self.convertir(bstg_remun_euro)
958e67e8 283
4d17560e
JPC
284 salaire_complement = 0.0
285 salaire_base = 0.0
286 indemnites = {
287 'fonc_resp': 0.0,
288 'expat': 0.0,
9fd09bdc 289 'scolarite': 0.0,
4d17560e
JPC
290 'logement': 0.0,
291 'transp': 0.0,
292 '13e': 0.0,
293 'autre_recurr': 0.0,
07f120f3 294 'interim': 0.0,
4d17560e 295 }
95ad7aab
JPC
296
297 primes = {
95ad7aab
JPC
298 'installation': 0.0,
299 'demenagement': 0.0,
300 'avion': 0.0,
301 'autre': 0.0,
302 }
07f120f3
JPC
303 charges = {
304 'patronale': 0.0,
305 'autre': 0.0,
306 }
5c5de149
JPC
307
308 total_remun_annee = {
309 'traitement': 0.0,
310 'indemnite': 0.0,
311 'accessoire': 0.0,
312 'charges': 0.0,
313 }
314
b4869de0 315 #Calcul du nombre de jours pour ce dossier.
34b3b5c6
JPC
316 dossier_date_delta = self.calculer_nombre_jours(
317 dossier.date_debut, dossier.date_fin,
318 date_debut, date_fin)
b4869de0 319
2139e9a7
JPC
320 masse_salariale = 0.0
321 masse_salariale_annee = 0.0
4d17560e 322 for r in remuns:
2139e9a7 323 montant = float(r.montant)
fa4ae139
JPC
324 if r.date_fin is None and dossier.date_fin is not None:
325 r.date_fin = min(date_fin, dossier.date_fin)
2139e9a7 326 facteur = self.calculer_nombre_jours(
fa4ae139
JPC
327 r.date_debut, r.date_fin,
328 date_debut, date_fin).days \
329 / float(rapport_date_delta.days)
95ad7aab
JPC
330
331 if r.type_id in TYPE_REMUN_MAD:
2139e9a7
JPC
332 salaire_complement += montant * facteur
333 else:
334 masse_salariale += montant
335 masse_salariale_annee += montant * facteur
4d17560e 336
95ad7aab 337 if r.type_id in TYPE_REMUN_BASE:
2139e9a7 338 salaire_base += montant * facteur
4d17560e 339
95ad7aab 340 if r.type_id in TYPE_REMUN_FONC_RESP:
2139e9a7 341 indemnites['fonc_resp'] += montant * facteur
4d17560e 342
95ad7aab 343 if r.type_id in TYPE_REMUN_EXPAT:
2139e9a7 344 indemnites['expat'] += montant * facteur
4d17560e 345
9fd09bdc 346 if r.type_id in TYPE_REMUN_SCOLARITE:
2139e9a7 347 indemnites['scolarite'] += montant * facteur
9fd09bdc 348
95ad7aab 349 if r.type_id in TYPE_REMUN_LOGEMENT:
2139e9a7 350 indemnites['logement'] += montant * facteur
4d17560e 351
95ad7aab 352 if r.type_id in TYPE_REMUN_TRANSP:
2139e9a7 353 indemnites['transp'] += montant * facteur
4d17560e 354
95ad7aab 355 if r.type_id in TYPE_REMUN_13E:
2139e9a7 356 indemnites['13e'] += montant * facteur
4d17560e 357
95ad7aab 358 if r.type_id in TYPE_PRIME_INTERIM:
2139e9a7 359 indemnites['interim'] += montant * facteur
07f120f3
JPC
360
361 if r.type_id not in TYPE_REMUN_ALL_INDEMNITES \
362 and r.type.nature_remuneration == TYPE_NATURE_INDEMN:
2139e9a7 363 indemnites['autre_recurr'] += montant * facteur
95ad7aab
JPC
364
365 if r.type_id in TYPE_PRIME_INSTALLATION:
2139e9a7 366 primes['installation'] += montant * facteur
95ad7aab
JPC
367
368 if r.type_id in TYPE_PRIME_DEMENAG:
2139e9a7 369 primes['demenagement'] += montant * facteur
95ad7aab
JPC
370
371 if r.type_id in TYPE_PRIME_AVION:
2139e9a7 372 primes['avion'] += montant * facteur
95ad7aab 373
07f120f3 374 if r.type_id not in TYPE_PRIME_ALL and \
95ad7aab 375 r.type.nature_remuneration == TYPE_NATURE_PAIEMENT:
2139e9a7 376 primes['autre'] += montant * facteur
95ad7aab 377
07f120f3 378 if r.type_id in TYPE_CHARGE_PATRONALE:
2139e9a7 379 charges['patronale'] += montant * facteur
07f120f3
JPC
380
381 if r.type_id not in TYPE_CHARGE_ALL and \
382 r.type.nature_remuneration == TYPE_NATURE_CHARGES:
2139e9a7 383 charges['autre'] += montant * facteur
899aea3b 384
5c5de149 385 if r.type.nature_remuneration == TYPE_NATURE_INDEMN:
2139e9a7 386 total_remun_annee['indemnite'] += montant * facteur
5c5de149
JPC
387
388 if r.type.nature_remuneration == TYPE_NATURE_PAIEMENT:
2139e9a7 389 total_remun_annee['accessoire'] += montant * facteur
5c5de149
JPC
390
391 if r.type.nature_remuneration == TYPE_NATURE_CHARGES:
2139e9a7 392 total_remun_annee['charges'] += montant * facteur
5c5de149
JPC
393
394 if r.type.nature_remuneration == TYPE_NATURE_TRAITEMENT:
2139e9a7 395 total_remun_annee['traitement'] += montant * facteur
5c5de149 396
4d17560e
JPC
397 total_indemnites = sum(indemnites.values())
398
df37184c 399 masse_salariale_euro = rh.Remuneration(montant=masse_salariale,
023bdc65
JPC
400 devise=remuns[0].devise)
401 self.convertir(masse_salariale_euro)
402
22b53270
JPC
403 if dossier.classement and dossier.classement.coefficient:
404 coefficient = dossier.classement.coefficient
405 else:
406 coefficient = ""
407
408 #todo valeur du point si pas présent
409 valeur_point = valeurs_point_par_imp.get(
410 dossier.poste.implantation_id
411 ) or ""
412
3244a3c2 413 salaire_theorique = (
22b53270 414 round(valeur_point.valeur * int(coefficient) * regime, 2) \
3244a3c2 415 if valeur_point and coefficient and regime else None)
22b53270 416
57e2b793
JPC
417 item_rapport = {
418 'bureau': dossier.poste.implantation.region.code,
419 'pays': unicode(pays),
420 'implantation': dossier.poste.implantation.nom_court,
421 'type_implantation': dossier.poste.implantation.type,
422 #'imputation': None,
423 'valeur_point': valeur_point,
424 'numero_employe': dossier.employe_id,
425 'nom': dossier.employe.nom.upper(),
426 'prenom': dossier.employe.prenom,
427 'type_de_poste': dossier.poste.type_poste.nom,
f7fc1166
JPC
428 'intitule_de_poste': dossier.poste.nom_feminin
429 if dossier.employe.genre == "F" else
430 dossier.poste.nom,
57e2b793
JPC
431 'niveau': unicode(dossier.classement),
432 'point': coefficient,
433 'regime_de_travail': "%s %%" % int(regime * 100),
434 'local_expatrie': statut,
435 'statut': dossier.statut.code,
436 'date_fin_contrat': dossier.date_fin or "",
437 'date_debut': d_date_debut or "",
438 'date_fin': d_date_fin or "",
b4869de0 439 'nb_jours': dossier_date_delta.days,
cb9cce2b 440 'devise': remuns[0].devise.code,
57e2b793
JPC
441 'salaire_bstg_annuel': bstg_remun.montant \
442 if bstg_remun else "",
443 'salaire_bstg_total': bstg_remun_euro.montant \
444 if bstg_remun else "",
445 'organisme_bstg': dossier.organisme_bstg or "",
446 'salaire_theorique': salaire_theorique,
447 'salaire_base_brut': \
0c5e0d8e 448 salaire_base * regime,
57e2b793 449 'salaire_complementaire': \
0c5e0d8e 450 salaire_complement * regime,
57e2b793
JPC
451 #'salaire_total': None
452 'indemnite_fonctions': indemnites['fonc_resp'] * \
0c5e0d8e
JPC
453 regime,
454 'indemnite_expat': indemnites['expat'] * regime,
9fd09bdc 455 'indemnite_scolarite': indemnites['scolarite'] * \
0c5e0d8e 456 regime,
57e2b793 457 'indemnite_logement': indemnites['logement'] * \
0c5e0d8e
JPC
458 regime,
459 'indemnite_transp': indemnites['transp'] * regime,
460 'indemnite_13e': indemnites['13e'] * regime,
461 'prime_interim': indemnites['interim'] * regime,
57e2b793 462 'indemnite_autre': indemnites['autre_recurr'] * \
0c5e0d8e
JPC
463 regime,
464 'indemnite_sous_total': total_indemnites * regime,
57e2b793 465 'total_brut': (
95ad7aab
JPC
466 total_indemnites + salaire_base +
467 salaire_complement
0c5e0d8e
JPC
468 ) * regime,
469 'prime_installation': primes['installation'] * regime,
470 'prime_demenagement': primes['demenagement'] * regime,
471 'prime_avion': primes['avion'] * regime,
472 'prime_autre': primes['autre'] * regime,
473 'prime_sous_total': sum(primes.values()) * regime,
2139e9a7
JPC
474 'charges_patronales': charges['patronale'] * regime,
475 'charges_autre': charges['autre'] * regime,
476 'charges_sous_total': sum(charges.values()) * regime,
5c5de149 477 'sous_total_traitement_annee': \
2139e9a7 478 total_remun_annee['traitement'] * regime,
5c5de149 479 'sous_total_indemnite_annee': \
2139e9a7 480 total_remun_annee['indemnite'] * regime,
5c5de149 481 'sous_total_accessoire_annee': \
2139e9a7 482 total_remun_annee['accessoire'] * regime,
5c5de149 483 'sous_total_charges_annee': \
2139e9a7
JPC
484 total_remun_annee['charges'] * regime,
485 'masse_salariale': masse_salariale * regime,
486 'masse_salariale_annee': masse_salariale_annee * regime,
5c5de149 487 'masse_salariale_annee_euro': \
0c5e0d8e 488 masse_salariale_euro.montant * regime,
43b30700 489 'sep': ods.Separator(),
57e2b793 490 }
98d6eb6c 491
3d2b92bc 492 grand_total += round(masse_salariale, 2)
c99116c3 493 grand_total_euro += round(masse_salariale_euro.montant * regime
b4869de0
JPC
494 * (
495 dossier_date_delta.days / rapport_date_delta.days
496 ), 2)
778fb9d6 497
98d6eb6c
JPC
498 self.rapport.append(item_rapport)
499
3b1a2937
JPC
500 self.rapport = sorted(self.rapport, key=lambda r: r['nom'])
501
778fb9d6
JPC
502 self.grand_totaux = (grand_total, grand_total_euro)
503
2139e9a7
JPC
504 def calculer_nombre_jours(self, debut, fin, debut_limite, fin_limite):
505 """Calcul le nombre de jours entre fin et debut, sans dépasser
34b3b5c6
JPC
506 les limites. Si debut ou fin set null, on prend debut_limite/fin_limi
507 """
508
509 if not debut:
510 debut = debut_limite
511 if not fin:
512 fin = fin_limite
513
514 if debut < debut_limite:
515 debut = debut_limite
516 if fin > fin_limite:
517 fin = fin_limite
518
519 fin += datetime.timedelta(days=1)
520 return fin - debut
521
98d6eb6c
JPC
522 def build_qs(self, prefix, date_debut, date_fin):
523 date_debut_null = \
524 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_DEBUT): True})
525 date_fin_null = \
526 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_FIN): True})
527 date_debut_superieure_ou_egale_a_borne_gauche = \
528 Q(**{"%s%s__gte" % (prefix, KEY_DATE_DEBUT): date_debut})
529 date_debut_inferieure_ou_egale_a_borne_gauche = \
530 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_debut})
531 date_fin_superieure_ou_egale_a_borne_gauche = \
532 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_debut})
533 date_fin_inferieure_ou_egale_a_borne_droite = \
534 Q(**{"%s%s__lte" % (prefix, KEY_DATE_FIN): date_fin})
535 date_debut_inferieure_ou_egale_a_borne_droite = \
536 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_fin})
537 date_fin_superieure_ou_egale_a_borne_droite = \
538 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_fin})
539
540 q_range = \
541 (
0c5e0d8e 542 date_debut_null & date_fin_null
98d6eb6c 543 ) | (
0c5e0d8e
JPC
544 date_fin_superieure_ou_egale_a_borne_gauche &
545 date_fin_inferieure_ou_egale_a_borne_droite &
546 (
547 date_debut_inferieure_ou_egale_a_borne_gauche |
548 date_debut_null
549 )
98d6eb6c 550 ) | (
0c5e0d8e
JPC
551 date_debut_superieure_ou_egale_a_borne_gauche &
552 date_debut_inferieure_ou_egale_a_borne_droite &
553 (
554 date_fin_superieure_ou_egale_a_borne_droite |
555 date_fin_null
556 )
98d6eb6c 557 ) | (
0c5e0d8e
JPC
558 date_debut_inferieure_ou_egale_a_borne_gauche &
559 date_fin_superieure_ou_egale_a_borne_droite
98d6eb6c 560 ) | (
0c5e0d8e
JPC
561 date_debut_null &
562 date_fin_superieure_ou_egale_a_borne_droite
98d6eb6c 563 ) | (
0c5e0d8e
JPC
564 date_debut_inferieure_ou_egale_a_borne_gauche &
565 date_fin_null
98d6eb6c 566 )
98d6eb6c
JPC
567 return q_range
568
569 def convertir(self, remuneration):
9163be6f 570 if remuneration.devise != self.devise_base:
8b6e7b9a
JPC
571 try:
572 remuneration.montant = float(remuneration.montant) * \
573 self.trouver_taux(remuneration.devise).taux
574 remuneration.devise = self.devise_base
575 except AttributeError:
576 pass
98d6eb6c
JPC
577
578 def trouver_taux(self, devise):
579 if devise.code not in self.taux_change:
8b6e7b9a
JPC
580 try:
581 t = rh.TauxChange.objects.filter(
582 devise=devise, annee=self.annee
583 )[0]
584 except IndexError:
585 return None
98d6eb6c
JPC
586 self.taux_change[devise.code] = t
587 return self.taux_change[devise.code]
899aea3b
JPC
588
589 def csv(self):
590 self.csv_handle = StringIO.StringIO()
023bdc65
JPC
591 csv_writer = csv.writer(self.csv_handle, delimiter=",",
592 doublequote=False, escapechar="\\", quoting=csv.QUOTE_ALL,
593 )
594 header = [v[0] for v in self.rapport[0]]
595 csv_writer.writerow(header)
596 for row in self.rapport:
597 values = [v[1] for v in row]
598 csv_writer.writerow(
599 [unicode(r).encode('utf-8') for r in values]
600 )
c99116c3
JPC
601
602 def ods(self):
3c8ffdfb
JPC
603 self.doc = ods.OpenDocumentSpreadsheet()
604 table = self.doc.add_table(name=u'Masse salariale %s' % self.annee)
605
606 for h in self.headers:
607 if len(h) > 2:
608 table.add_column(**h[2])
609
6d7419c4
JPC
610 table.add_row([h[1] for h in self.headers], rowheight='2cm')
611
612 for r in self.rapport:
613 table.add_row([r[h[0]] for h in self.headers])
3c8ffdfb 614
028b8438 615 #a.doc.write('hello_world.ods')