Masse salariale, fin de journée
[auf_rh_dae.git] / project / rh / masse_salariale.py
CommitLineData
98d6eb6c
JPC
1# -*- encoding: utf-8 -*-
2import time
3import datetime
4
5from django.db.models import Q
6
7from datamaster_modeles import models as ref
8
9import rh.models as rh
10
11
12KEY_DATE_DEBUT = "debut"
13KEY_DATE_FIN = "fin"
4d17560e
JPC
14
15TYPE_REMUN_BSTG = (3,)
16TYPE_REMUN_MAD = (2,)
17TYPE_REMUN_BASE = (1,)
95ad7aab 18TYPE_REMUN_FONC_RESP = (7, 8)
4d17560e
JPC
19TYPE_REMUN_EXPAT = (4,)
20TYPE_REMUN_LOGEMENT = (6,)
21TYPE_REMUN_TRANSP = (9,)
22TYPE_REMUN_13E = (18,)
95ad7aab 23TYPE_REMUN_AUTRE_RECURR_NOT = (1, 2, 3, 4, 6, 7, 8, 9, 18, 13, 14, 15, 19)
4d17560e 24TYPE_PAIEMENT_PONCTUEL = u"Ponctuel"
95ad7aab
JPC
25TYPE_PRIME_INTERIM = (19,)
26TYPE_PRIME_INSTALLATION = (13,)
27TYPE_PRIME_DEMENAG = (15,)
28TYPE_PRIME_AVION = (14,)
29TYPE_NATURE_PAIEMENT = u"Accessoire"
9163be6f 30
98d6eb6c
JPC
31class MasseSalariale():
32 """ Rapport de la masse salariale. """
33
34 def __init__(self, date_debut, date_fin):
35 """ date_debut: date de début pour les données temporelles
36 date_fin: idem
37 """
38 date_debut = datetime.date(
39 *time.strptime(date_debut, "%d-%m-%Y")[0:3]
40 )
41 date_fin = datetime.date(*time.strptime(date_fin, "%d-%m-%Y")[0:3])
9163be6f 42 rapport_date_delta = date_fin - date_debut
98d6eb6c
JPC
43
44 self.annee = date_fin.year
45
46 self.devise_base = rh.Devise.objects.filter(code='EUR')[0]
47 self.taux_change = {}
48
49 q_range = self.build_qs("date_", date_debut, date_fin)
50 q_range_d = self.build_qs("dossier__date_", date_debut, date_fin)
51 remunerations = rh.Remuneration.objects.filter(q_range) \
52 .filter(q_range_d) \
53 .exclude(supprime=True) \
95ad7aab 54 .select_related("dossier", "dossier_employe", "dossier_poste", "type")
98d6eb6c
JPC
55
56 employes = {}
57 for r in remunerations:
58 if r.dossier.employe_id not in employes:
9163be6f
JPC
59 employes[r.dossier.employe_id] = {
60 'dossiers': set(),
61 'remunerations': []
62 }
98d6eb6c
JPC
63 employes[r.dossier.employe_id]['remunerations'].append(r)
64 employes[r.dossier.employe_id]['dossiers'].add(r.dossier)
65
66 self.employes = employes
9163be6f 67
98d6eb6c
JPC
68 self.rapport = []
69
70 pays_list = ref.Pays.objects.all()
71 valeurs_point_par_imp = \
72 dict(
9163be6f
JPC
73 (v.implantation.id, v) for v in \
74 rh.ValeurPoint.objects.filter(annee=self.annee).all()
98d6eb6c
JPC
75 )
76 for item in self.employes.values():
77 dossiers = item['dossiers']
78 remuns = item['remunerations']
79 #TODO, choisir le dossier primaire
80 if len(dossiers) > 1:
81 #TODO
82 pass
83 dossier = list(dossiers)[0]
95ad7aab 84 regime = float(dossier.poste.regime_travail) / 100
9163be6f 85
98d6eb6c
JPC
86 if dossier.poste.expatrie:
87 statut = "E"
88 else:
89 statut = "L"
90
9163be6f
JPC
91 #on détermine la date du début et fin du dossier si année en cours
92 try:
93 d_date_fin = dossier.date_fin \
94 if dossier.date_fin.year == date_fin.year else None
95 except AttributeError:
96 d_date_fin = None
97 try:
98 d_date_debut = dossier.date_debut \
99 if dossier.date_debut.year == date_fin.year else None
100 except AttributeError:
101 d_date_debut = None
98d6eb6c
JPC
102
103 pays = \
104 pays_list[dossier.poste.implantation.adresse_physique_pays.id]
105
106 #on détermine si les rémunérations sont tous dans la même devise
107 devise = remuns[0].devise
108 meme_devise = True
109 for r in remuns[1:]:
110 if devise != r.devise:
111 meme_devise = False
112
113 if not meme_devise:
114 for r in remuns:
115 self.convertir(r)
116
117 bstg_dossier = None
118 for d in dossiers:
119 if d.organisme_bstg:
120 bstg_dossier = d
121
9163be6f 122 bstg_remun = None
98d6eb6c 123 if bstg_dossier:
9163be6f 124 for r in bstg_dossier.rh_remunerations.all():
4d17560e 125 if r.type in TYPE_REMUN_BSTG:
9163be6f 126 bstg_remun = r
98d6eb6c 127
4d17560e
JPC
128 salaire_complement = 0.0
129 salaire_base = 0.0
130 indemnites = {
131 'fonc_resp': 0.0,
132 'expat': 0.0,
133 'logement': 0.0,
134 'transp': 0.0,
135 '13e': 0.0,
136 'autre_recurr': 0.0,
137 }
95ad7aab
JPC
138
139 primes = {
140 'interim': 0.0,
141 'installation': 0.0,
142 'demenagement': 0.0,
143 'avion': 0.0,
144 'autre': 0.0,
145 }
4d17560e
JPC
146 for r in remuns:
147 montant = float(r.montant)
95ad7aab
JPC
148
149 if r.type_id in TYPE_REMUN_MAD:
4d17560e
JPC
150 salaire_complement += montant
151
95ad7aab 152 if r.type_id in TYPE_REMUN_BASE:
4d17560e
JPC
153 salaire_base += montant
154
95ad7aab 155 if r.type_id in TYPE_REMUN_FONC_RESP:
4d17560e
JPC
156 indemnites['fonc_resp'] += montant
157
95ad7aab 158 if r.type_id in TYPE_REMUN_EXPAT:
4d17560e
JPC
159 indemnites['expat'] += montant
160
95ad7aab 161 if r.type_id in TYPE_REMUN_LOGEMENT:
4d17560e
JPC
162 indemnites['logement'] += montant
163
95ad7aab 164 if r.type_id in TYPE_REMUN_TRANSP:
4d17560e
JPC
165 indemnites['transp'] += montant
166
95ad7aab 167 if r.type_id in TYPE_REMUN_13E:
4d17560e
JPC
168 indemnites['13e'] += montant
169
95ad7aab 170 if r.type_id not in TYPE_REMUN_AUTRE_RECURR_NOT \
4d17560e
JPC
171 and r.type.type_paiement != TYPE_PAIEMENT_PONCTUEL:
172 indemnites['autre_recurr'] += montant
173
95ad7aab
JPC
174 if r.type_id in TYPE_PRIME_INTERIM:
175 primes['interim'] += montant
176
177 if r.type_id in TYPE_PRIME_INSTALLATION:
178 primes['installation'] += montant
179
180 if r.type_id in TYPE_PRIME_DEMENAG:
181 primes['demenagement'] += montant
182
183 if r.type_id in TYPE_PRIME_AVION:
184 primes['avion'] += montant
185
186 if r.type_id not in TYPE_REMUN_AUTRE_RECURR_NOT and \
187 r.type.nature_remuneration == TYPE_NATURE_PAIEMENT:
188 primes['autre'] += montant
189
4d17560e
JPC
190 total_indemnites = sum(indemnites.values())
191
9163be6f 192 #Calcul du nombre de jours pour ce dossier.
4d17560e
JPC
193 if dossier.date_debut and dossier.date_debut > date_debut and \
194 not dossier.date_fin:
195 date_delta = date_fin - dossier.date_fin
196 elif dossier.date_fin and dossier.date_fin < date_fin and \
197 not dossier.date_debut:
198 date_delta = dossier.date_fin - date_debut
199 elif dossier.date_fin and dossier.date_debut:
200 date_delta = dossier.date_fin - date_debut
201 else:
9163be6f 202 date_delta = rapport_date_delta
98d6eb6c
JPC
203
204 item_rapport = {
205 'bureau': dossier.poste.implantation.region.code,
206 'pays': pays,
207 'implantation': dossier.poste.implantation.nom_court,
208 'type_implantation': dossier.poste.implantation.type,
209 #'imputation': None,
9163be6f
JPC
210 'valeur_point':
211 #todo valeur du point si pas présent
98d6eb6c
JPC
212 valeurs_point_par_imp.get(
213 dossier.poste.implantation_id
9163be6f 214 ),
98d6eb6c
JPC
215 'numero_employe': dossier.employe_id,
216 'nom': dossier.employe.nom.upper(),
217 'prenom': dossier.employe.prenom,
218 'type_de_poste': dossier.poste.type_poste.nom,
219 'intitule_de_poste': dossier.poste.nom,
220 'niveau': dossier.classement,
9163be6f 221 'point': "%s" %
98d6eb6c 222 dossier.classement.coefficient \
9163be6f
JPC
223 if dossier.classement and
224 dossier.classement.coefficient
98d6eb6c 225 else "",
95ad7aab 226 'regime_de_travail': "%s %%" % int(regime * 100),
98d6eb6c
JPC
227 'local_expatrie': statut,
228 'statut': dossier.statut.code,
229 'date_fin_contrat': dossier.date_fin,
9163be6f
JPC
230 'date_debut': d_date_debut,
231 'date_fin': d_date_fin,
98d6eb6c
JPC
232 'nb_jours': date_delta.days,
233 'devise': remuns[0].devise,
9163be6f
JPC
234 'salaire_bstg_annuel': bstg_remun.montant \
235 if bstg_remun else None,
236 'salaire_bstg_total':
237 self.convertir(bstg_remun) \
238 * regime * date_delta.days \
239 if bstg_remun else None,
4d17560e
JPC
240 'organisme_bstg': dossier.organisme_bstg,
241 'salaire_base_brut': \
95ad7aab
JPC
242 salaire_base * regime * (
243 date_delta.days / rapport_date_delta.days
244 ),
245 'salaire_complementaire': \
246 salaire_complement * regime * (
247 date_delta.days / rapport_date_delta.days
248 ),
249 #'salaire_total': None
250 'indemnite_fonctions': indemnites['fonc_resp'] * regime * \
251 (date_delta.days / rapport_date_delta.days),
252 'indemnite_expat': indemnites['expat'] * regime * \
253 (date_delta.days / rapport_date_delta.days),
254 'indemnite_logement': indemnites['logement'] * regime * \
255 (date_delta.days / rapport_date_delta.days),
256 'indemnites_transp': indemnites['transp'] * regime * \
257 (date_delta.days / rapport_date_delta.days),
258 'indemnites_13e': indemnites['13e'] * regime * \
259 (date_delta.days / rapport_date_delta.days),
260 'indemnites_autre': indemnites['autre_recurr'] * regime * \
261 (date_delta.days / rapport_date_delta.days),
262 'indemnites_total': total_indemnites * regime * \
263 (date_delta.days / rapport_date_delta.days),
264 'total_brut': (
265 total_indemnites + salaire_base +
266 salaire_complement
267 ) * regime * (
268 date_delta.days / rapport_date_delta.days
269 ),
270 'prime_interim': primes['interim'] * regime * \
271 (date_delta.days / rapport_date_delta.days),
272 'prime_installation': primes['installation'] * regime * \
273 (date_delta.days / rapport_date_delta.days),
274 'prime_demenagement': primes['demenagement'] * regime * \
275 (date_delta.days / rapport_date_delta.days),
276 'prime_avion': primes['avion'] * regime * \
277 (date_delta.days / rapport_date_delta.days),
278 'prime_autre': primes['autre'] * regime * \
279 (date_delta.days / rapport_date_delta.days),
280 'prime_total': sum(primes.values()) * regime * \
281 (date_delta.days / rapport_date_delta.days),
282 }
98d6eb6c
JPC
283
284 self.rapport.append(item_rapport)
285
98d6eb6c
JPC
286 def build_qs(self, prefix, date_debut, date_fin):
287 date_debut_null = \
288 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_DEBUT): True})
289 date_fin_null = \
290 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_FIN): True})
291 date_debut_superieure_ou_egale_a_borne_gauche = \
292 Q(**{"%s%s__gte" % (prefix, KEY_DATE_DEBUT): date_debut})
293 date_debut_inferieure_ou_egale_a_borne_gauche = \
294 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_debut})
295 date_fin_superieure_ou_egale_a_borne_gauche = \
296 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_debut})
297 date_fin_inferieure_ou_egale_a_borne_droite = \
298 Q(**{"%s%s__lte" % (prefix, KEY_DATE_FIN): date_fin})
299 date_debut_inferieure_ou_egale_a_borne_droite = \
300 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_fin})
301 date_fin_superieure_ou_egale_a_borne_droite = \
302 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_fin})
303
304 q_range = \
305 (
306 date_debut_null & date_fin_null
307 ) | (
308 date_debut_inferieure_ou_egale_a_borne_gauche &
309 date_fin_superieure_ou_egale_a_borne_gauche &
310 date_fin_inferieure_ou_egale_a_borne_droite
311 ) | (
312 date_debut_superieure_ou_egale_a_borne_gauche &
313 date_debut_inferieure_ou_egale_a_borne_droite &
314 date_fin_superieure_ou_egale_a_borne_droite
315 ) | (
316 date_debut_inferieure_ou_egale_a_borne_gauche &
317 date_fin_superieure_ou_egale_a_borne_droite
318 ) | (
319 date_debut_null &
320 date_fin_superieure_ou_egale_a_borne_droite
321 ) | (
322 date_debut_inferieure_ou_egale_a_borne_gauche &
323 date_fin_null
324 )
325
326 return q_range
327
328 def convertir(self, remuneration):
9163be6f
JPC
329 if remuneration.devise != self.devise_base:
330 remuneration.montant = float(remuneration.montant) * \
331 self.trouver_taux(remuneration.devise).taux
332 remuneration.devise = self.devise_base
98d6eb6c
JPC
333
334 def trouver_taux(self, devise):
335 if devise.code not in self.taux_change:
336 t = rh.TauxChange.objects.filter(
337 devise=devise, annee=self.annee
338 )[0]
339 self.taux_change[devise.code] = t
340 return self.taux_change[devise.code]