Pep8
[auf_rh_dae.git] / project / rh / masse_salariale.py
1 # -*- encoding: utf-8 -*-
2 import time
3 import datetime
4
5 from django.db.models import Q
6
7 from datamaster_modeles import models as ref
8
9 import rh.models as rh
10
11
12 KEY_DATE_DEBUT = "debut"
13 KEY_DATE_FIN = "fin"
14 TYPE_REMUN_BSTG = 3
15
16
17 class MasseSalariale():
18 """ Rapport de la masse salariale. """
19
20 def __init__(self, date_debut, date_fin):
21 """ date_debut: date de début pour les données temporelles
22 date_fin: idem
23 """
24 date_debut = datetime.date(
25 *time.strptime(date_debut, "%d-%m-%Y")[0:3]
26 )
27 date_fin = datetime.date(*time.strptime(date_fin, "%d-%m-%Y")[0:3])
28 rapport_date_delta = date_fin - date_debut
29
30 self.annee = date_fin.year
31
32 self.devise_base = rh.Devise.objects.filter(code='EUR')[0]
33 self.taux_change = {}
34
35 q_range = self.build_qs("date_", date_debut, date_fin)
36 q_range_d = self.build_qs("dossier__date_", date_debut, date_fin)
37 remunerations = rh.Remuneration.objects.filter(q_range) \
38 .filter(q_range_d) \
39 .exclude(supprime=True) \
40 .select_related("dossier", "dossier_employe", "dossier_poste")
41
42 employes = {}
43 for r in remunerations:
44 if r.dossier.employe_id not in employes:
45 employes[r.dossier.employe_id] = {
46 'dossiers': set(),
47 'remunerations': []
48 }
49 employes[r.dossier.employe_id]['remunerations'].append(r)
50 employes[r.dossier.employe_id]['dossiers'].add(r.dossier)
51
52 self.employes = employes
53
54 self.rapport = []
55
56 pays_list = ref.Pays.objects.all()
57 valeurs_point_par_imp = \
58 dict(
59 (v.implantation.id, v) for v in \
60 rh.ValeurPoint.objects.filter(annee=self.annee).all()
61 )
62 for item in self.employes.values():
63 dossiers = item['dossiers']
64 remuns = item['remunerations']
65 #TODO, choisir le dossier primaire
66 if len(dossiers) > 1:
67 #TODO
68 pass
69 dossier = list(dossiers)[0]
70 regime = dossier.poste.regime_travail
71
72 if dossier.poste.expatrie:
73 statut = "E"
74 else:
75 statut = "L"
76
77 #on détermine la date du début et fin du dossier si année en cours
78 try:
79 d_date_fin = dossier.date_fin \
80 if dossier.date_fin.year == date_fin.year else None
81 except AttributeError:
82 d_date_fin = None
83 try:
84 d_date_debut = dossier.date_debut \
85 if dossier.date_debut.year == date_fin.year else None
86 except AttributeError:
87 d_date_debut = None
88
89 pays = \
90 pays_list[dossier.poste.implantation.adresse_physique_pays.id]
91
92 #on détermine si les rémunérations sont tous dans la même devise
93 devise = remuns[0].devise
94 meme_devise = True
95 for r in remuns[1:]:
96 if devise != r.devise:
97 meme_devise = False
98
99 if not meme_devise:
100 for r in remuns:
101 self.convertir(r)
102
103 bstg_dossier = None
104 for d in dossiers:
105 if d.organisme_bstg:
106 bstg_dossier = d
107
108 bstg_remun = None
109 if bstg_dossier:
110 for r in bstg_dossier.rh_remunerations.all():
111 if r.type == TYPE_REMUN_BSTG:
112 bstg_remun = r
113
114 #Calcul du nombre de jours pour ce dossier.
115 try:
116 date_delta = dossier.date_fin - dossier.date_debut
117 except:
118 date_delta = rapport_date_delta
119
120 item_rapport = {
121 'bureau': dossier.poste.implantation.region.code,
122 'pays': pays,
123 'implantation': dossier.poste.implantation.nom_court,
124 'type_implantation': dossier.poste.implantation.type,
125 #'imputation': None,
126 'valeur_point':
127 #todo valeur du point si pas présent
128 valeurs_point_par_imp.get(
129 dossier.poste.implantation_id
130 ),
131 'numero_employe': dossier.employe_id,
132 'nom': dossier.employe.nom.upper(),
133 'prenom': dossier.employe.prenom,
134 'type_de_poste': dossier.poste.type_poste.nom,
135 'intitule_de_poste': dossier.poste.nom,
136 'niveau': dossier.classement,
137 'point': "%s" %
138 dossier.classement.coefficient \
139 if dossier.classement and
140 dossier.classement.coefficient
141 else "",
142 'regime_de_travail': "%s %%" % regime,
143 'local_expatrie': statut,
144 'statut': dossier.statut.code,
145 'date_fin_contrat': dossier.date_fin,
146 'date_debut': d_date_debut,
147 'date_fin': d_date_fin,
148 'nb_jours': date_delta.days,
149 'devise': remuns[0].devise,
150 'organisme_bstg': dossier.organisme_bstg,
151 'salaire_bstg_annuel': bstg_remun.montant \
152 if bstg_remun else None,
153 'salaire_bstg_total':
154 self.convertir(bstg_remun) \
155 * regime * date_delta.days \
156 if bstg_remun else None,
157 }
158
159 self.rapport.append(item_rapport)
160
161 def build_qs(self, prefix, date_debut, date_fin):
162 date_debut_null = \
163 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_DEBUT): True})
164 date_fin_null = \
165 Q(**{"%s%s__isnull" % (prefix, KEY_DATE_FIN): True})
166 date_debut_superieure_ou_egale_a_borne_gauche = \
167 Q(**{"%s%s__gte" % (prefix, KEY_DATE_DEBUT): date_debut})
168 date_debut_inferieure_ou_egale_a_borne_gauche = \
169 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_debut})
170 date_fin_superieure_ou_egale_a_borne_gauche = \
171 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_debut})
172 date_fin_inferieure_ou_egale_a_borne_droite = \
173 Q(**{"%s%s__lte" % (prefix, KEY_DATE_FIN): date_fin})
174 date_debut_inferieure_ou_egale_a_borne_droite = \
175 Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT): date_fin})
176 date_fin_superieure_ou_egale_a_borne_droite = \
177 Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN): date_fin})
178
179 q_range = \
180 (
181 date_debut_null & date_fin_null
182 ) | (
183 date_debut_inferieure_ou_egale_a_borne_gauche &
184 date_fin_superieure_ou_egale_a_borne_gauche &
185 date_fin_inferieure_ou_egale_a_borne_droite
186 ) | (
187 date_debut_superieure_ou_egale_a_borne_gauche &
188 date_debut_inferieure_ou_egale_a_borne_droite &
189 date_fin_superieure_ou_egale_a_borne_droite
190 ) | (
191 date_debut_inferieure_ou_egale_a_borne_gauche &
192 date_fin_superieure_ou_egale_a_borne_droite
193 ) | (
194 date_debut_null &
195 date_fin_superieure_ou_egale_a_borne_droite
196 ) | (
197 date_debut_inferieure_ou_egale_a_borne_gauche &
198 date_fin_null
199 )
200
201 return q_range
202
203 def convertir(self, remuneration):
204 if remuneration.devise != self.devise_base:
205 remuneration.montant = float(remuneration.montant) * \
206 self.trouver_taux(remuneration.devise).taux
207 remuneration.devise = self.devise_base
208
209 def trouver_taux(self, devise):
210 if devise.code not in self.taux_change:
211 t = rh.TauxChange.objects.filter(
212 devise=devise, annee=self.annee
213 )[0]
214 self.taux_change[devise.code] = t
215 return self.taux_change[devise.code]