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