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
40 custom_filter: dictionnaire des paramètres à passer au queryset.
42 if not date_debut
and not date_fin
:
45 date_debut
= datetime
.date(
46 *time
.strptime(date_debut
, "%d-%m-%Y")[0:3]
48 date_fin
= datetime
.date(*time
.strptime(date_fin
, "%d-%m-%Y")[0:3])
49 rapport_date_delta
= date_fin
- date_debut
51 self
.annee
= date_fin
.year
53 self
.devise_base
= rh
.Devise
.objects
.filter(code
='EUR')[0]
56 q_range
= self
.build_qs("date_", date_debut
, date_fin
)
57 q_range_d
= self
.build_qs("dossier__date_", date_debut
, date_fin
)
58 remunerations
= rh
.Remuneration
.objects
.filter(q_range
) \
62 remunerations
= remunerations
.filter(**custom_filter
)
64 remunerations
= remunerations
.exclude(supprime
=True) \
66 "dossier", "dossier_employe", "dossier_poste", "type"
70 for r
in remunerations
:
71 if r
.dossier
.employe_id
not in employes
:
72 employes
[r
.dossier
.employe_id
] = {
76 employes
[r
.dossier
.employe_id
]['remunerations'].append(r
)
77 employes
[r
.dossier
.employe_id
]['dossiers'].add(r
.dossier
)
79 self
.employes
= employes
83 pays_list
= ref
.Pays
.objects
.all()
84 valeurs_point_par_imp
= \
86 (v
.implantation
.id, v
) for v
in \
87 rh
.ValeurPoint
.objects
.filter(annee
=self
.annee
).all()
89 for item
in self
.employes
.values():
90 dossiers
= item
['dossiers']
91 remuns
= item
['remunerations']
92 #TODO, choisir le dossier primaire
96 dossier
= list(dossiers
)[0]
97 regime
= float(dossier
.poste
.regime_travail
) / 100
99 if dossier
.poste
.expatrie
:
104 #on détermine la date du début et fin du dossier si année en cours
106 d_date_fin
= dossier
.date_fin \
107 if dossier
.date_fin
.year
== date_fin
.year
else None
108 except AttributeError:
111 d_date_debut
= dossier
.date_debut \
112 if dossier
.date_debut
.year
== date_fin
.year
else None
113 except AttributeError:
117 pays_list
[dossier
.poste
.implantation
.adresse_physique_pays
.id]
119 #on détermine si les rémunérations sont tous dans la même devise
120 devise
= remuns
[0].devise
123 if devise
!= r
.devise
:
137 for r
in bstg_dossier
.rh_remunerations
.all():
138 if r
.type.id in TYPE_REMUN_BSTG
:
142 bstg_remun_euro
= rh
.Remuneration(
143 montant
=bstg_remun
.montant
, devise
=bstg_remun
.devise
145 self
.convertir(bstg_remun_euro
)
147 salaire_complement
= 0.0
167 montant
= float(r
.montant
)
169 if r
.type_id
in TYPE_REMUN_MAD
:
170 salaire_complement
+= montant
172 if r
.type_id
in TYPE_REMUN_BASE
:
173 salaire_base
+= montant
175 if r
.type_id
in TYPE_REMUN_FONC_RESP
:
176 indemnites
['fonc_resp'] += montant
178 if r
.type_id
in TYPE_REMUN_EXPAT
:
179 indemnites
['expat'] += montant
181 if r
.type_id
in TYPE_REMUN_LOGEMENT
:
182 indemnites
['logement'] += montant
184 if r
.type_id
in TYPE_REMUN_TRANSP
:
185 indemnites
['transp'] += montant
187 if r
.type_id
in TYPE_REMUN_13E
:
188 indemnites
['13e'] += montant
190 if r
.type_id
not in TYPE_REMUN_AUTRE_RECURR_NOT \
191 and r
.type.type_paiement
!= TYPE_PAIEMENT_PONCTUEL
:
192 indemnites
['autre_recurr'] += montant
194 if r
.type_id
in TYPE_PRIME_INTERIM
:
195 primes
['interim'] += montant
197 if r
.type_id
in TYPE_PRIME_INSTALLATION
:
198 primes
['installation'] += montant
200 if r
.type_id
in TYPE_PRIME_DEMENAG
:
201 primes
['demenagement'] += montant
203 if r
.type_id
in TYPE_PRIME_AVION
:
204 primes
['avion'] += montant
206 if r
.type_id
not in TYPE_REMUN_AUTRE_RECURR_NOT
and \
207 r
.type.nature_remuneration
== TYPE_NATURE_PAIEMENT
:
208 primes
['autre'] += montant
210 if r
.type.nature_remuneration
== TYPE_NATURE_CHARGES
:
213 total_indemnites
= sum(indemnites
.values())
215 #Calcul du nombre de jours pour ce dossier.
216 if dossier
.date_debut
and dossier
.date_debut
> date_debut
and \
217 not dossier
.date_fin
:
218 date_delta
= date_fin
- dossier
.date_fin
219 elif dossier
.date_fin
and dossier
.date_fin
< date_fin
and \
220 not dossier
.date_debut
:
221 date_delta
= dossier
.date_fin
- date_debut
222 elif dossier
.date_fin
and dossier
.date_debut
:
223 date_delta
= dossier
.date_fin
- date_debut
225 date_delta
= rapport_date_delta
227 masse_salariale
= (salaire_base
+ total_indemnites
+ \
228 sum(primes
.values()) + charges
)
229 masse_salariale_euro
= rh
.Remuneration(montant
=masse_salariale
,
230 devise
=remuns
[0].devise
)
231 self
.convertir(masse_salariale_euro
)
234 ('bureau', dossier
.poste
.implantation
.region
.code
),
235 ('pays', unicode(pays
)),
236 ('implantation', dossier
.poste
.implantation
.nom_court
),
237 ('type_implantation', dossier
.poste
.implantation
.type),
238 #'imputation', None),
240 #todo valeur du point si pas présent
241 valeurs_point_par_imp
.get(
242 dossier
.poste
.implantation_id
244 ('numero_employe', dossier
.employe_id
),
245 ('nom', dossier
.employe
.nom
.upper()),
246 ('prenom', dossier
.employe
.prenom
),
247 ('type_de_poste', dossier
.poste
.type_poste
.nom
),
248 ('intitule_de_poste', dossier
.poste
.nom
),
249 ('niveau', unicode(dossier
.classement
)),
251 dossier
.classement
.coefficient \
252 if dossier
.classement
and
253 dossier
.classement
.coefficient
255 ('regime_de_travail', "%s %%" % int(regime
* 100)),
256 ('local_expatrie', statut
),
257 ('statut', dossier
.statut
.code
),
258 ('date_fin_contrat', dossier
.date_fin
or ""),
259 ('date_debut', d_date_debut
or ""),
260 ('date_fin', d_date_fin
or ""),
261 ('nb_jours', date_delta
.days
),
262 ('devise', remuns
[0].devise
),
263 ('salaire_bstg_annuel', bstg_remun
.montant \
264 if bstg_remun
else ""),
265 ('salaire_bstg_total', bstg_remun_euro
.montant \
266 if bstg_remun
else ""),
267 ('organisme_bstg', dossier
.organisme_bstg
or ""),
268 ('salaire_base_brut', \
269 salaire_base
* regime
* (
270 date_delta
.days
/ rapport_date_delta
.days
272 ('salaire_complementaire', \
273 salaire_complement
* regime
* (
274 date_delta
.days
/ rapport_date_delta
.days
276 #'salaire_total', None
277 ('indemnite_fonctions', indemnites
['fonc_resp'] * \
279 (date_delta
.days
/ rapport_date_delta
.days
)),
280 ('indemnite_expat', indemnites
['expat'] * regime
* \
281 (date_delta
.days
/ rapport_date_delta
.days
)),
282 ('indemnite_logement', indemnites
['logement'] * \
284 (date_delta
.days
/ rapport_date_delta
.days
)),
285 ('indemnites_transp', indemnites
['transp'] * regime
* \
286 (date_delta
.days
/ rapport_date_delta
.days
)),
287 ('indemnites_13e', indemnites
['13e'] * regime
* \
288 (date_delta
.days
/ rapport_date_delta
.days
)),
289 ('indemnites_autre', indemnites
['autre_recurr'] * \
291 (date_delta
.days
/ rapport_date_delta
.days
)),
292 ('indemnites_total', total_indemnites
* regime
* \
293 (date_delta
.days
/ rapport_date_delta
.days
)),
295 total_indemnites
+ salaire_base
+
298 date_delta
.days
/ rapport_date_delta
.days
300 ('prime_interim', primes
['interim'] * regime
* \
301 (date_delta
.days
/ rapport_date_delta
.days
)),
302 ('prime_installation', primes
['installation'] * regime
* \
303 (date_delta
.days
/ rapport_date_delta
.days
)),
304 ('prime_demenagement', primes
['demenagement'] * regime
* \
305 (date_delta
.days
/ rapport_date_delta
.days
)),
306 ('prime_avion', primes
['avion'] * regime
* \
307 (date_delta
.days
/ rapport_date_delta
.days
)),
308 ('prime_autre', primes
['autre'] * regime
* \
309 (date_delta
.days
/ rapport_date_delta
.days
)),
310 ('prime_total', sum(primes
.values()) * regime
* \
311 (date_delta
.days
/ rapport_date_delta
.days
)),
312 ('charges_patronales', charges
),
313 ('charges_patronales_%s' % self
.annee
, charges
* regime
* \
314 (date_delta
.days
/ rapport_date_delta
.days
)),
315 ('masse_salariale', masse_salariale
),
316 ('masse_salariale_%s' % self
.annee
, masse_salariale
* \
318 date_delta
.days
/ rapport_date_delta
.days
320 ('masse_salariale__euro_%s' % self
.annee
, \
321 masse_salariale_euro
.montant
* regime
* (
322 date_delta
.days
/ rapport_date_delta
.days
326 self
.rapport
.append(item_rapport
)
328 def build_qs(self
, prefix
, date_debut
, date_fin
):
330 Q(**{"%s%s__isnull" % (prefix
, KEY_DATE_DEBUT
): True})
332 Q(**{"%s%s__isnull" % (prefix
, KEY_DATE_FIN
): True})
333 date_debut_superieure_ou_egale_a_borne_gauche
= \
334 Q(**{"%s%s__gte" % (prefix
, KEY_DATE_DEBUT
): date_debut
})
335 date_debut_inferieure_ou_egale_a_borne_gauche
= \
336 Q(**{"%s%s__lte" % (prefix
, KEY_DATE_DEBUT
): date_debut
})
337 date_fin_superieure_ou_egale_a_borne_gauche
= \
338 Q(**{"%s%s__gte" % (prefix
, KEY_DATE_FIN
): date_debut
})
339 date_fin_inferieure_ou_egale_a_borne_droite
= \
340 Q(**{"%s%s__lte" % (prefix
, KEY_DATE_FIN
): date_fin
})
341 date_debut_inferieure_ou_egale_a_borne_droite
= \
342 Q(**{"%s%s__lte" % (prefix
, KEY_DATE_DEBUT
): date_fin
})
343 date_fin_superieure_ou_egale_a_borne_droite
= \
344 Q(**{"%s%s__gte" % (prefix
, KEY_DATE_FIN
): date_fin
})
348 date_debut_null
& date_fin_null
350 date_debut_inferieure_ou_egale_a_borne_gauche
&
351 date_fin_superieure_ou_egale_a_borne_gauche
&
352 date_fin_inferieure_ou_egale_a_borne_droite
354 date_debut_superieure_ou_egale_a_borne_gauche
&
355 date_debut_inferieure_ou_egale_a_borne_droite
&
356 date_fin_superieure_ou_egale_a_borne_droite
358 date_debut_inferieure_ou_egale_a_borne_gauche
&
359 date_fin_superieure_ou_egale_a_borne_droite
362 date_fin_superieure_ou_egale_a_borne_droite
364 date_debut_inferieure_ou_egale_a_borne_gauche
&
370 def convertir(self
, remuneration
):
371 if remuneration
.devise
!= self
.devise_base
:
372 remuneration
.montant
= float(remuneration
.montant
) * \
373 self
.trouver_taux(remuneration
.devise
).taux
374 remuneration
.devise
= self
.devise_base
376 def trouver_taux(self
, devise
):
377 if devise
.code
not in self
.taux_change
:
378 t
= rh
.TauxChange
.objects
.filter(
379 devise
=devise
, annee
=self
.annee
381 self
.taux_change
[devise
.code
] = t
382 return self
.taux_change
[devise
.code
]
385 self
.csv_handle
= StringIO
.StringIO()
386 csv_writer
= csv
.writer(self
.csv_handle
, delimiter
=",",
387 doublequote
=False, escapechar
="\\", quoting
=csv
.QUOTE_ALL
,
389 header
= [v
[0] for v
in self
.rapport
[0]]
390 csv_writer
.writerow(header
)
391 for row
in self
.rapport
:
392 values
= [v
[1] for v
in row
]
394 [unicode(r
).encode('utf-8') for r
in values
]