1 # -*- encoding: utf-8 -*-
7 from django
.db
.models
import Q
9 from datamaster_modeles
import models
as ref
10 import rh
.models
as rh
13 KEY_DATE_DEBUT
= "debut"
16 TYPE_REMUN_BSTG
= (3,)
18 TYPE_REMUN_BASE
= (1,)
19 TYPE_REMUN_FONC_RESP
= (7, 8)
20 TYPE_REMUN_EXPAT
= (4,)
21 TYPE_REMUN_LOGEMENT
= (6,)
22 TYPE_REMUN_TRANSP
= (9,)
23 TYPE_REMUN_13E
= (18,)
24 TYPE_REMUN_AUTRE_RECURR_NOT
= (1, 2, 3, 4, 6, 7, 8, 9, 18, 13, 14, 15, 19)
25 TYPE_PAIEMENT_PONCTUEL
= u
"Ponctuel"
26 TYPE_PRIME_INTERIM
= (19,)
27 TYPE_PRIME_INSTALLATION
= (13,)
28 TYPE_PRIME_DEMENAG
= (15,)
29 TYPE_PRIME_AVION
= (14,)
30 TYPE_NATURE_PAIEMENT
= u
"Accessoire"
31 TYPE_NATURE_CHARGES
= u
"Charges"
34 class MasseSalariale():
35 """ Rapport de la masse salariale. """
37 def __init__(self
, date_debut
, date_fin
, custom_filter
=None):
38 """ date_debut: date de début pour les données temporelles
41 date_debut
= datetime
.date(
42 *time
.strptime(date_debut
, "%d-%m-%Y")[0:3]
44 date_fin
= datetime
.date(*time
.strptime(date_fin
, "%d-%m-%Y")[0:3])
45 rapport_date_delta
= date_fin
- date_debut
47 self
.annee
= date_fin
.year
49 self
.devise_base
= rh
.Devise
.objects
.filter(code
='EUR')[0]
52 q_range
= self
.build_qs("date_", date_debut
, date_fin
)
53 q_range_d
= self
.build_qs("dossier__date_", date_debut
, date_fin
)
54 remunerations
= rh
.Remuneration
.objects
.filter(q_range
) \
58 remunerations
= remunerations
.filter(**custom_filter
)
60 remunerations
= remunerations
.exclude(supprime
=True) \
62 "dossier", "dossier_employe", "dossier_poste", "type"
66 for r
in remunerations
:
67 if r
.dossier
.employe_id
not in employes
:
68 employes
[r
.dossier
.employe_id
] = {
72 employes
[r
.dossier
.employe_id
]['remunerations'].append(r
)
73 employes
[r
.dossier
.employe_id
]['dossiers'].add(r
.dossier
)
75 self
.employes
= employes
79 pays_list
= ref
.Pays
.objects
.all()
80 valeurs_point_par_imp
= \
82 (v
.implantation
.id, v
) for v
in \
83 rh
.ValeurPoint
.objects
.filter(annee
=self
.annee
).all()
85 for item
in self
.employes
.values():
86 dossiers
= item
['dossiers']
87 remuns
= item
['remunerations']
88 #TODO, choisir le dossier primaire
92 dossier
= list(dossiers
)[0]
93 regime
= float(dossier
.poste
.regime_travail
) / 100
95 if dossier
.poste
.expatrie
:
100 #on détermine la date du début et fin du dossier si année en cours
102 d_date_fin
= dossier
.date_fin \
103 if dossier
.date_fin
.year
== date_fin
.year
else None
104 except AttributeError:
107 d_date_debut
= dossier
.date_debut \
108 if dossier
.date_debut
.year
== date_fin
.year
else None
109 except AttributeError:
113 pays_list
[dossier
.poste
.implantation
.adresse_physique_pays
.id]
115 #on détermine si les rémunérations sont tous dans la même devise
116 devise
= remuns
[0].devise
119 if devise
!= r
.devise
:
133 for r
in bstg_dossier
.rh_remunerations
.all():
134 if r
.type.id in TYPE_REMUN_BSTG
:
138 bstg_remun_euro
= bstg_remun
139 self
.convertir(bstg_remun_euro
)
140 print bstg_remun
.devise
, bstg_remun_euro
.devise
142 salaire_complement
= 0.0
162 montant
= float(r
.montant
)
164 if r
.type_id
in TYPE_REMUN_MAD
:
165 salaire_complement
+= montant
167 if r
.type_id
in TYPE_REMUN_BASE
:
168 salaire_base
+= montant
170 if r
.type_id
in TYPE_REMUN_FONC_RESP
:
171 indemnites
['fonc_resp'] += montant
173 if r
.type_id
in TYPE_REMUN_EXPAT
:
174 indemnites
['expat'] += montant
176 if r
.type_id
in TYPE_REMUN_LOGEMENT
:
177 indemnites
['logement'] += montant
179 if r
.type_id
in TYPE_REMUN_TRANSP
:
180 indemnites
['transp'] += montant
182 if r
.type_id
in TYPE_REMUN_13E
:
183 indemnites
['13e'] += montant
185 if r
.type_id
not in TYPE_REMUN_AUTRE_RECURR_NOT \
186 and r
.type.type_paiement
!= TYPE_PAIEMENT_PONCTUEL
:
187 indemnites
['autre_recurr'] += montant
189 if r
.type_id
in TYPE_PRIME_INTERIM
:
190 primes
['interim'] += montant
192 if r
.type_id
in TYPE_PRIME_INSTALLATION
:
193 primes
['installation'] += montant
195 if r
.type_id
in TYPE_PRIME_DEMENAG
:
196 primes
['demenagement'] += montant
198 if r
.type_id
in TYPE_PRIME_AVION
:
199 primes
['avion'] += montant
201 if r
.type_id
not in TYPE_REMUN_AUTRE_RECURR_NOT
and \
202 r
.type.nature_remuneration
== TYPE_NATURE_PAIEMENT
:
203 primes
['autre'] += montant
205 if r
.type.nature_remuneration
== TYPE_NATURE_CHARGES
:
208 total_indemnites
= sum(indemnites
.values())
210 #Calcul du nombre de jours pour ce dossier.
211 if dossier
.date_debut
and dossier
.date_debut
> date_debut
and \
212 not dossier
.date_fin
:
213 date_delta
= date_fin
- dossier
.date_fin
214 elif dossier
.date_fin
and dossier
.date_fin
< date_fin
and \
215 not dossier
.date_debut
:
216 date_delta
= dossier
.date_fin
- date_debut
217 elif dossier
.date_fin
and dossier
.date_debut
:
218 date_delta
= dossier
.date_fin
- date_debut
220 date_delta
= rapport_date_delta
222 masse_salariale
= (salaire_base
+ total_indemnites
+ \
223 sum(primes
.values()) + charges
)
224 masse_salariale_euro
= rh
.Remuneration(montant
=masse_salariale
,
225 devise
=remuns
[0].devise
)
226 self
.convertir(masse_salariale_euro
)
229 ('bureau', dossier
.poste
.implantation
.region
.code
),
230 ('pays', unicode(pays
)),
231 ('implantation', dossier
.poste
.implantation
.nom_court
),
232 ('type_implantation', dossier
.poste
.implantation
.type),
233 #'imputation', None),
235 #todo valeur du point si pas présent
236 valeurs_point_par_imp
.get(
237 dossier
.poste
.implantation_id
239 ('numero_employe', dossier
.employe_id
),
240 ('nom', dossier
.employe
.nom
.upper()),
241 ('prenom', dossier
.employe
.prenom
),
242 ('type_de_poste', dossier
.poste
.type_poste
.nom
),
243 ('intitule_de_poste', dossier
.poste
.nom
),
244 ('niveau', unicode(dossier
.classement
)),
246 dossier
.classement
.coefficient \
247 if dossier
.classement
and
248 dossier
.classement
.coefficient
250 ('regime_de_travail', "%s %%" % int(regime
* 100)),
251 ('local_expatrie', statut
),
252 ('statut', dossier
.statut
.code
),
253 ('date_fin_contrat', dossier
.date_fin
or ""),
254 ('date_debut', d_date_debut
or ""),
255 ('date_fin', d_date_fin
or ""),
256 ('nb_jours', date_delta
.days
),
257 ('devise', remuns
[0].devise
),
258 ('salaire_bstg_annuel', bstg_remun
.montant \
259 if bstg_remun
else ""),
260 ('salaire_bstg_total', bstg_remun_euro
.montant \
261 if bstg_remun
else ""),
262 ('organisme_bstg', dossier
.organisme_bstg
or ""),
263 ('salaire_base_brut', \
264 salaire_base
* regime
* (
265 date_delta
.days
/ rapport_date_delta
.days
267 ('salaire_complementaire', \
268 salaire_complement
* regime
* (
269 date_delta
.days
/ rapport_date_delta
.days
271 #'salaire_total', None
272 ('indemnite_fonctions', indemnites
['fonc_resp'] * \
274 (date_delta
.days
/ rapport_date_delta
.days
)),
275 ('indemnite_expat', indemnites
['expat'] * regime
* \
276 (date_delta
.days
/ rapport_date_delta
.days
)),
277 ('indemnite_logement', indemnites
['logement'] * \
279 (date_delta
.days
/ rapport_date_delta
.days
)),
280 ('indemnites_transp', indemnites
['transp'] * regime
* \
281 (date_delta
.days
/ rapport_date_delta
.days
)),
282 ('indemnites_13e', indemnites
['13e'] * regime
* \
283 (date_delta
.days
/ rapport_date_delta
.days
)),
284 ('indemnites_autre', indemnites
['autre_recurr'] * \
286 (date_delta
.days
/ rapport_date_delta
.days
)),
287 ('indemnites_total', total_indemnites
* regime
* \
288 (date_delta
.days
/ rapport_date_delta
.days
)),
290 total_indemnites
+ salaire_base
+
293 date_delta
.days
/ rapport_date_delta
.days
295 ('prime_interim', primes
['interim'] * regime
* \
296 (date_delta
.days
/ rapport_date_delta
.days
)),
297 ('prime_installation', primes
['installation'] * regime
* \
298 (date_delta
.days
/ rapport_date_delta
.days
)),
299 ('prime_demenagement', primes
['demenagement'] * regime
* \
300 (date_delta
.days
/ rapport_date_delta
.days
)),
301 ('prime_avion', primes
['avion'] * regime
* \
302 (date_delta
.days
/ rapport_date_delta
.days
)),
303 ('prime_autre', primes
['autre'] * regime
* \
304 (date_delta
.days
/ rapport_date_delta
.days
)),
305 ('prime_total', sum(primes
.values()) * regime
* \
306 (date_delta
.days
/ rapport_date_delta
.days
)),
307 ('charges_patronales', charges
),
308 ('charges_patronales_%s' % self
.annee
, charges
* regime
* \
309 (date_delta
.days
/ rapport_date_delta
.days
)),
310 ('masse_salariale', masse_salariale
),
311 ('masse_salariale_%s' % self
.annee
, masse_salariale
* \
313 date_delta
.days
/ rapport_date_delta
.days
315 ('masse_salariale__euro_%s' % self
.annee
, \
316 masse_salariale_euro
.montant
* regime
* (
317 date_delta
.days
/ rapport_date_delta
.days
321 self
.rapport
.append(item_rapport
)
323 def build_qs(self
, prefix
, date_debut
, date_fin
):
325 Q(**{"%s%s__isnull" % (prefix
, KEY_DATE_DEBUT
): True})
327 Q(**{"%s%s__isnull" % (prefix
, KEY_DATE_FIN
): True})
328 date_debut_superieure_ou_egale_a_borne_gauche
= \
329 Q(**{"%s%s__gte" % (prefix
, KEY_DATE_DEBUT
): date_debut
})
330 date_debut_inferieure_ou_egale_a_borne_gauche
= \
331 Q(**{"%s%s__lte" % (prefix
, KEY_DATE_DEBUT
): date_debut
})
332 date_fin_superieure_ou_egale_a_borne_gauche
= \
333 Q(**{"%s%s__gte" % (prefix
, KEY_DATE_FIN
): date_debut
})
334 date_fin_inferieure_ou_egale_a_borne_droite
= \
335 Q(**{"%s%s__lte" % (prefix
, KEY_DATE_FIN
): date_fin
})
336 date_debut_inferieure_ou_egale_a_borne_droite
= \
337 Q(**{"%s%s__lte" % (prefix
, KEY_DATE_DEBUT
): date_fin
})
338 date_fin_superieure_ou_egale_a_borne_droite
= \
339 Q(**{"%s%s__gte" % (prefix
, KEY_DATE_FIN
): date_fin
})
343 date_debut_null
& date_fin_null
345 date_debut_inferieure_ou_egale_a_borne_gauche
&
346 date_fin_superieure_ou_egale_a_borne_gauche
&
347 date_fin_inferieure_ou_egale_a_borne_droite
349 date_debut_superieure_ou_egale_a_borne_gauche
&
350 date_debut_inferieure_ou_egale_a_borne_droite
&
351 date_fin_superieure_ou_egale_a_borne_droite
353 date_debut_inferieure_ou_egale_a_borne_gauche
&
354 date_fin_superieure_ou_egale_a_borne_droite
357 date_fin_superieure_ou_egale_a_borne_droite
359 date_debut_inferieure_ou_egale_a_borne_gauche
&
365 def convertir(self
, remuneration
):
366 if remuneration
.devise
!= self
.devise_base
:
367 remuneration
.montant
= float(remuneration
.montant
) * \
368 self
.trouver_taux(remuneration
.devise
).taux
369 remuneration
.devise
= self
.devise_base
371 def trouver_taux(self
, devise
):
372 if devise
.code
not in self
.taux_change
:
373 t
= rh
.TauxChange
.objects
.filter(
374 devise
=devise
, annee
=self
.annee
376 self
.taux_change
[devise
.code
] = t
377 return self
.taux_change
[devise
.code
]
380 self
.csv_handle
= StringIO
.StringIO()
381 csv_writer
= csv
.writer(self
.csv_handle
, delimiter
=",",
382 doublequote
=False, escapechar
="\\", quoting
=csv
.QUOTE_ALL
,
384 header
= [v
[0] for v
in self
.rapport
[0]]
385 csv_writer
.writerow(header
)
386 for row
in self
.rapport
:
387 values
= [v
[1] for v
in row
]
389 [unicode(r
).encode('utf-8') for r
in values
]