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