poste dae -> poste rh
[auf_rh_dae.git] / project / dae / models.py
CommitLineData
bd28238f 1# -=- encoding: utf-8 -=-
3f3cf5f3 2
36341125 3import os
5633fa41 4from django.conf import settings
36341125 5from django.core.files.storage import FileSystemStorage
a9c281dd
OL
6from django.db import models
7import reversion
3f5cbabe 8from rh import models as rh
afc204bf 9from workflow import PosteWorkflow, DossierWorkflow
c511cd1f
EMS
10from workflow import DOSSIER_ETAT_DRH_FINALISATION, DOSSIER_ETAT_REGION_FINALISATION, \
11 DOSSIER_ETAT_FINALISE
bf6f2712 12import auf.django.references.models as ref
3f5cbabe 13from managers import *
bd28238f 14
bd28238f 15
2d4d2fcf 16# Constantes
b666864e 17HELP_TEXT_DATE = "format: jj-mm-aaaa"
2d4d2fcf 18REGIME_TRAVAIL_DEFAULT=100.00
19REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT=35.00
bd28238f 20
d766bf2c 21# Upload de fichiers
34dad720 22UPLOAD_STORAGE = FileSystemStorage(settings.PRIVE_MEDIA_ROOT)
d766bf2c 23
36341125 24
2d4d2fcf 25### POSTE
26
27POSTE_APPEL_CHOICES = (
28 ('interne', 'Interne'),
29 ('externe', 'Externe'),
30)
c3be904d
OL
31POSTE_ACTION = (
32 ('N', u"Nouveau poste"),
33 ('M', u"Poste existant"),
34 ('E', u"Évolution de poste"),
35)
36
36341125 37
ae5c920b
OL
38class DeviseException(Exception):
39 silent_variable_failure = True
40
1c7d67ce 41
3f5cbabe 42class Poste(PosteWorkflow, rh.Poste_):
c3be904d
OL
43
44 type_intervention = models.CharField(max_length=1, choices=POSTE_ACTION, default='N')
45
bd28238f 46 # Modèle existant
5d680e84 47 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
2d4d2fcf 48 editable=False,
c1195471 49 verbose_name=u"Mise à jour du poste")
bd28238f
NC
50
51 # Rémunération
3f5cbabe 52 indemn_expat_min = models.DecimalField(max_digits=13, decimal_places=2, default=0)
5f61bccb
OL
53 indemn_expat_max = models.DecimalField(max_digits=12, decimal_places=2, default=0)
54 indemn_fct_min = models.DecimalField(max_digits=12, decimal_places=2, default=0)
55 indemn_fct_max = models.DecimalField(max_digits=12, decimal_places=2, default=0)
56 charges_patronales_min = models.DecimalField(max_digits=12, decimal_places=2, default=0)
57 charges_patronales_max = models.DecimalField(max_digits=12, decimal_places=2, default=0)
bd28238f 58
1c7d67ce
OL
59 # Managers
60 objects = PosteManager()
61
317ce433
OL
62
63 def est_importe(self):
64 """Test si le poste a déjà été importé"""
65 return ImportPoste.objects.filter(dae=self).exists()
66
67 def importer(self):
68 from django.db.models import AutoField
69 if self.est_importe():
70 return ImportPoste.objects.get(dae=self)
71 rh_poste = rh.Poste()
72 # Faire une copie profonde de l'objet.
73 # PosteFinancement, PosteComparaison, Remun modele a ajuster...
a184c555
OL
74
75 def copy_model(src, dst, exclude=[]):
76 keys = [f.name for f in src._meta.fields if f.name not in ['id', ] + exclude]
77 for k in keys:
78 setattr(dst, k, getattr(src, k))
79 return dst
80
81 rh_poste = copy_model(self, rh_poste)
82 rh_poste.save()
83 print rh_poste.id
84
85 for o in self.dae_financements.all():
86 rh_financement = rh.PosteFinancement()
87 rh_financement = copy_model(o, rh_financement, exclude=['poste',])
88 rh_financement.poste = rh_poste
89 rh_financement.save()
90
91 for o in self.dae_pieces.all():
92 rh_piece = rh.PostePiece()
93 rh_piece = copy_model(o, rh_piece, exclude=['poste',])
94 rh_piece.poste = rh_poste
95 rh_piece.save()
96
97 for o in self.dae_comparaisons_internes.all():
98 rh_comp = rh.PosteComparaison()
99 rh_comp = copy_model(o, rh_financement, exclude=['poste',])
100 rh_comp.poste = rh_poste
101 rh_comp.save()
102
317ce433
OL
103 return rh_poste
104
03858ba5
OL
105 def _get_key(self):
106 """
1bc84af4 107 Les vues sont montées selon une clef spéciale
2d4d2fcf 108 pour identifier la provenance du poste.
1bc84af4 109 Cette méthode fournit un moyen de reconstruire cette clef
2d4d2fcf 110 afin de générer les URLs.
03858ba5
OL
111 """
112 return "dae-%s" % self.id
113 key = property(_get_key)
114
f3333b0e
OL
115 def get_dossiers(self):
116 """
117 Liste tous les anciens dossiers liés à ce poste.
1bc84af4 118 (Le nom de la relation sur le rh.Poste est mal choisi
2d4d2fcf 119 poste1 au lieu de dossier1)
f3333b0e 120 Note1 : seulement le dosssier principal fait l'objet de la recherche.
1bc84af4
EMS
121 Note2 : les dossiers sont retournés du plus récent au plus vieux.
122 (Ce test est fait en fonction du id,
2d4d2fcf 123 car les dates de création sont absentes de rh v1).
f3333b0e
OL
124 """
125 if self.id_rh is None:
126 return []
16b1454e 127 return self.id_rh.rh_dossiers.all()
428e3c0b 128
f3333b0e
OL
129 def get_complement_nom(self):
130 """
1bc84af4 131 Inspecte les modèles rh v1 pour trouver dans le dernier dossier
2d4d2fcf 132 un complément de titre de poste.
f3333b0e
OL
133 """
134 dossiers = self.get_dossiers()
135 if len(dossiers) > 0:
09aa8374 136 nom = dossiers[0].poste.nom
f3333b0e
OL
137 else:
138 nom = ""
a9c281dd 139 return nom
f3333b0e
OL
140
141 def get_employe(self):
142 """
143 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
144 """
145 dossiers = self.get_dossiers()
146 if len(dossiers) > 0:
147 return dossiers[0].employe
148 else:
149 return None
150
179f6b49 151 def get_default_devise(self):
1bc84af4 152 """Récupère la devise par défaut en fonction de l'implantation
2d4d2fcf 153 (EUR autrement)
154 """
179f6b49 155 try:
6e4600ef 156 implantation_devise = rh.TauxChange.objects \
157 .filter(implantation=self.implantation)[0].devise
179f6b49
OL
158 except:
159 implantation_devise = 5 # EUR
160 return implantation_devise
161
c0413a6f
OL
162 #####################
163 # Classement de poste
164 #####################
165
166 def get_couts_minimum(self):
83b94a87
EMS
167 return self.salaire_min + self.indemn_expat_min + self.indemn_fct_min + self.charges_patronales_min + self.autre_min
168
169 def get_salaire_minimum(self):
170 return self.get_couts_minimum() - self.charges_patronales_min
c0413a6f
OL
171
172 def get_taux_minimum(self):
4e439a89
OL
173 if self.devise_min.code == 'EUR':
174 return 1
2455f48d 175 liste_taux = self.devise_min.tauxchange_set.order_by('-annee')
4e439a89
OL
176 if len(liste_taux) == 0:
177 raise DeviseException(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise_min, self.implantation))
b6825282 178 else:
4e439a89 179 return liste_taux[0].taux
c0413a6f
OL
180
181 def get_couts_minimum_euros(self):
fa5b95ed 182 return float(self.get_couts_minimum()) * self.get_taux_minimum()
c0413a6f 183
83b94a87 184 def get_salaire_minimum_euros(self):
fa5b95ed 185 return float(self.get_salaire_minimum()) * self.get_taux_minimum()
83b94a87 186
c0413a6f 187 def get_couts_maximum(self):
83b94a87
EMS
188 return self.salaire_max + self.indemn_expat_max + self.indemn_fct_max + self.charges_patronales_max + self.autre_max
189
190 def get_salaire_maximum(self):
191 return self.get_couts_maximum() - self.charges_patronales_max
c0413a6f
OL
192
193 def get_taux_maximum(self):
4e439a89
OL
194 if self.devise_max.code == 'EUR':
195 return 1
2455f48d 196 liste_taux = self.devise_max.tauxchange_set.order_by('-annee')
4e439a89
OL
197 if len(liste_taux) == 0:
198 raise DeviseException(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise_max, self.implantation))
b6825282 199 else:
4e439a89 200 return liste_taux[0].taux
c0413a6f
OL
201
202 def get_couts_maximum_euros(self):
fa5b95ed 203 return float(self.get_couts_maximum()) * self.get_taux_maximum()
c0413a6f 204
83b94a87 205 def get_salaire_maximum_euros(self):
fa5b95ed 206 return float(self.get_salaire_maximum()) * self.get_taux_maximum()
12c7f8a7
OL
207
208 def show_taux_minimum(self):
209 try:
210 return self.get_taux_minimum()
83b94a87 211 except DeviseException, e:
12c7f8a7
OL
212 return e
213
214 def show_couts_minimum_euros(self):
215 try:
216 return self.get_couts_minimum_euros()
83b94a87
EMS
217 except DeviseException, e:
218 return e
219
220 def show_salaire_minimum_euros(self):
221 try:
222 return self.get_salaire_minimum_euros()
223 except DeviseException, e:
12c7f8a7
OL
224 return e
225
226 def show_taux_maximum(self):
227 try:
228 return self.get_taux_maximum()
83b94a87 229 except DeviseException, e:
12c7f8a7
OL
230 return e
231
232 def show_couts_maximum_euros(self):
233 try:
234 return self.get_couts_maximum_euros()
83b94a87
EMS
235 except DeviseException, e:
236 return e
237
238 def show_salaire_maximum_euros(self):
239 try:
240 return self.get_salaire_maximum_euros()
241 except DeviseException, e:
12c7f8a7
OL
242 return e
243
244
c0413a6f
OL
245 ######################
246 # Comparaison de poste
247 ######################
a3fee9c5
OL
248
249 def est_comparable(self):
250 """
251 Si on a au moins une valeur de saisie dans les comparaisons, alors le poste
252 est comparable.
253 """
254 if self.comp_universite_min is None and \
255 self.comp_fonctionpub_min is None and \
256 self.comp_locale_min is None and \
257 self.comp_ong_min is None and \
258 self.comp_autre_min is None and \
259 self.comp_universite_max is None and \
260 self.comp_fonctionpub_max is None and \
261 self.comp_locale_max is None and \
262 self.comp_ong_max is None and \
263 self.comp_autre_max is None:
264 return False
265 else:
266 return True
1bc84af4 267
a3fee9c5 268
c0413a6f
OL
269 def get_taux_comparaison(self):
270 try:
2455f48d 271 return rh.TauxChange.objects.filter(devise=self.devise_comparaison)[0].taux
c0413a6f
OL
272 except:
273 return 1
274
275 def get_comp_universite_min_euros(self):
276 return (float)(self.comp_universite_min) * self.get_taux_comparaison()
277
278 def get_comp_fonctionpub_min_euros(self):
279 return (float)(self.comp_fonctionpub_min) * self.get_taux_comparaison()
280
281 def get_comp_locale_min_euros(self):
282 return (float)(self.comp_locale_min) * self.get_taux_comparaison()
283
284 def get_comp_ong_min_euros(self):
285 return (float)(self.comp_ong_min) * self.get_taux_comparaison()
286
287 def get_comp_autre_min_euros(self):
288 return (float)(self.comp_autre_min) * self.get_taux_comparaison()
289
290 def get_comp_universite_max_euros(self):
291 return (float)(self.comp_universite_max) * self.get_taux_comparaison()
292
293 def get_comp_fonctionpub_max_euros(self):
294 return (float)(self.comp_fonctionpub_max) * self.get_taux_comparaison()
295
296 def get_comp_locale_max_euros(self):
297 return (float)(self.comp_locale_max) * self.get_taux_comparaison()
298
299 def get_comp_ong_max_euros(self):
300 return (float)(self.comp_ong_max) * self.get_taux_comparaison()
301
302 def get_comp_autre_max_euros(self):
303 return (float)(self.comp_autre_max) * self.get_taux_comparaison()
304
a9e52624 305
5d680e84 306 def __unicode__(self):
f3333b0e 307 """
1bc84af4 308 Cette fonction est consommatrice SQL car elle cherche les dossiers
2d4d2fcf 309 qui ont été liés à celui-ci.
f3333b0e
OL
310 """
311 complement_nom_poste = self.get_complement_nom()
c7a4aa2b
OL
312 if complement_nom_poste is None:
313 complement_nom_poste = ""
f3333b0e
OL
314 data = (
315 self.implantation,
316 self.type_poste.nom,
317 self.nom,
f3333b0e 318 )
a7c68130 319 return u'%s - %s (%s)' % data
5d680e84 320
bd28238f 321
a9c281dd
OL
322# Tester l'enregistrement car les models.py sont importés au complet
323if not reversion.is_registered(Poste):
324 reversion.register(Poste)
325
bd28238f 326
5d680e84
NC
327POSTE_FINANCEMENT_CHOICES = (
328 ('A', 'A - Frais de personnel'),
329 ('B', 'B - Projet(s)-Titre(s)'),
330 ('C', 'C - Autre')
331)
bd28238f 332
317ce433 333class PosteFinancement(rh.PosteFinancement_):
a4125771 334 pass
1d0f4eef 335
317ce433 336class PostePiece(rh.PostePiece_):
a4125771 337 pass
068d1462 338
317ce433 339class PosteComparaison(rh.PosteComparaison_):
766ca378
OL
340 statut = models.ForeignKey(rh.Statut, related_name='+', verbose_name=u'Statut', null=True, blank=True, )
341 classement = models.ForeignKey(rh.Classement, related_name='+', verbose_name=u'Classement', null=True, blank=True, )
068d1462 342
2d4d2fcf 343### EMPLOYÉ/PERSONNE
344
345# TODO : migration pour m -> M, f -> F
c589d980 346
bd28238f 347GENRE_CHOICES = (
139686f2
NC
348 ('m', 'Homme'),
349 ('f', 'Femme'),
bd28238f
NC
350)
351
bd28238f 352class Employe(models.Model):
bd28238f
NC
353
354 # Modèle existant
428e3c0b 355 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+',
c1195471 356 verbose_name=u'Employé')
bd28238f 357 nom = models.CharField(max_length=255)
c1195471 358 prenom = models.CharField(max_length=255, verbose_name=u'Prénom')
07b40eda 359 genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
bd28238f 360
139686f2 361 def __unicode__(self):
2d4d2fcf 362 return u'%s %s' % (self.prenom, self.nom.upper())
139686f2 363
bd28238f 364
2d4d2fcf 365### DOSSIER
366
367STATUT_RESIDENCE_CHOICES = (
368 ('local', 'Local'),
369 ('expat', 'Expatrié'),
370)
371
bd28238f 372COMPTE_COMPTA_CHOICES = (
494ff2be
NC
373 ('coda', 'CODA'),
374 ('scs', 'SCS'),
375 ('aucun', 'Aucun'),
bd28238f
NC
376)
377
16b1454e
OL
378class Dossier(DossierWorkflow, rh.Dossier_):
379 poste = models.ForeignKey('Poste', db_column='poste', related_name='%(app_label)s_dossiers')
380 employe = models.ForeignKey('Employe', db_column='employe',
381 related_name='%(app_label)s_dossiers',
382 verbose_name=u"Employé")
0288adb5 383 organisme_bstg_autre = models.CharField(max_length=255,
c1195471 384 verbose_name=u"Autre organisme",
0288adb5
OL
385 help_text="indiquer l'organisme ici s'il n'est pas dans la liste",
386 null=True,
387 blank=True,)
bd28238f 388
139686f2
NC
389 # Données antérieures de l'employé
390 statut_anterieur = models.ForeignKey(
391 rh.Statut, related_name='+', null=True, blank=True,
c1195471 392 verbose_name=u'Statut antérieur')
139686f2
NC
393 classement_anterieur = models.ForeignKey(
394 rh.Classement, related_name='+', null=True, blank=True,
c1195471 395 verbose_name=u'Classement précédent')
139686f2
NC
396 salaire_anterieur = models.DecimalField(
397 max_digits=12, decimal_places=2, null=True, default=None,
481fbd33 398 blank=True, verbose_name=u'Salaire précédent')
e158c6de
DB
399 devise_anterieur = models.ForeignKey(rh.Devise, related_name='+',
400 null=True, blank=True)
401 type_contrat_anterieur = models.ForeignKey(rh.TypeContrat,
402 related_name='+', null=True, blank=True,
403 verbose_name=u'Type contrat antérieur', )
139686f2
NC
404
405 # Données du titulaire précédent
406 employe_anterieur = models.ForeignKey(
407 rh.Employe, related_name='+', null=True, blank=True,
c1195471 408 verbose_name=u'Employé précédent')
139686f2
NC
409 statut_titulaire_anterieur = models.ForeignKey(
410 rh.Statut, related_name='+', null=True, blank=True,
c1195471 411 verbose_name=u'Statut titulaire précédent')
139686f2
NC
412 classement_titulaire_anterieur = models.ForeignKey(
413 rh.Classement, related_name='+', null=True, blank=True,
c1195471 414 verbose_name=u'Classement titulaire précédent')
139686f2
NC
415 salaire_titulaire_anterieur = models.DecimalField(
416 max_digits=12, decimal_places=2, default=None, null=True,
481fbd33 417 blank=True, verbose_name=u'Salaire titulaire précédent')
f8c7c0b8 418 devise_titulaire_anterieur = models.ForeignKey(rh.Devise, related_name='+', null=True, blank=True)
494ff2be 419
bd28238f 420 # Rémunération
16b1454e 421 salaire = models.DecimalField(max_digits=13, decimal_places=2,
c1195471 422 verbose_name=u'Salaire de base',
2d4d2fcf 423 null=True, default=None)
e8e75458 424 devise = models.ForeignKey(rh.Devise, default=5, related_name='+')
bd28238f
NC
425
426 # Contrat
5d680e84 427 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
b666864e 428 contrat_date_debut = models.DateField(help_text=HELP_TEXT_DATE)
1f109689 429 contrat_date_fin = models.DateField(null=True, blank=True,
b666864e 430 help_text=HELP_TEXT_DATE)
bd28238f 431
29dffede
OL
432 # Justifications
433 justif_nouveau_statut_label = u'Justifier le statut que ce type de poste nécessite (national, expatrié, màd ou détachement)'
434 justif_nouveau_statut = models.TextField(verbose_name=justif_nouveau_statut_label, null=True, blank=True)
a83daab3 435 justif_nouveau_tmp_remplacement_label = u"Si l'employé effectue un remplacement temporaire, préciser"
29dffede 436 justif_nouveau_tmp_remplacement = models.TextField(verbose_name=justif_nouveau_tmp_remplacement_label, null=True, blank=True)
a83daab3 437 justif_nouveau_salaire_label = u"Si le salaire de l'employé ne correspond pas au classement du poste ou est différent du salaire antérieur, justifier "
29dffede 438 justif_nouveau_salaire = models.TextField(verbose_name=justif_nouveau_salaire_label, null=True, blank=True)
a83daab3 439 justif_nouveau_commentaire_label = u"COMMENTAIRES ADDITIONNELS"
29dffede
OL
440 justif_nouveau_commentaire = models.TextField(verbose_name=justif_nouveau_commentaire_label, null=True, blank=True)
441 justif_rempl_type_contrat_label = u"Changement de type de contrat, ex : d'un CDD en CDI"
442 justif_rempl_type_contrat = models.TextField(verbose_name=justif_rempl_type_contrat_label, null=True, blank=True)
a83daab3 443 justif_rempl_statut_employe_label = u"Si le statut de l'employé a été modifié pour ce poste ; ex :national, expatrié, màd, détachement ? Si oui, justifier"
29dffede 444 justif_rempl_statut_employe = models.TextField(verbose_name=justif_rempl_statut_employe_label, null=True, blank=True)
a83daab3 445 justif_rempl_evaluation_label = u"L'évaluation de l'employé est-elle favorable? Préciser"
29dffede
OL
446 justif_rempl_evaluation = models.TextField(verbose_name=justif_rempl_evaluation_label, null=True, blank=True)
447 justif_rempl_salaire_label = u"Si le salaire de l'employé est modifié et/ou ne correspond pas à son classement, justifier"
448 justif_rempl_salaire = models.TextField(verbose_name=justif_rempl_salaire_label, null=True, blank=True)
a83daab3 449 justif_rempl_commentaire_label = u"COMMENTAIRES ADDITIONNELS"
29dffede
OL
450 justif_rempl_commentaire = models.TextField(verbose_name=justif_rempl_commentaire_label, null=True, blank=True)
451
bd28238f 452 # Comptes
dfc2c344 453 compte_compta = models.CharField(max_length=10, default='aucun',
454 verbose_name=u'Compte comptabilité',
455 choices=COMPTE_COMPTA_CHOICES)
bd28238f 456 compte_courriel = models.BooleanField()
428e3c0b 457
c3f0b49f
EMS
458 # DAE numérisée
459 dae_numerisee = models.FileField(upload_to='dae/dae_numerisee', storage=UPLOAD_STORAGE,
5be87e56 460 blank=True, null=True, verbose_name="DAE numérisée")
c3f0b49f 461
e4f56614
OL
462 # Managers
463 objects = DossierManager()
428e3c0b 464
16b1454e
OL
465 def __init__(self, *args, **kwargs):
466 # Bouchon pour créer une date fictive necessaire pour valider un dossier
467 # à cause de l'héritage
468 super(rh.Dossier_, self).__init__(*args, **kwargs)
469 super(DossierWorkflow, self).__init__(*args, **kwargs)
470 import datetime
471 self.date_debut = datetime.datetime.today()
472
aec2c91e 473 def __unicode__(self):
e4f56614 474 return u'[%s] %s - %s' % (self.poste.implantation, self.poste.nom, self.employe)
bd28238f 475
317ce433
OL
476 def est_importe(self):
477 """Test si le dossier a déjà été importé"""
478 return dae.ImportDossier.objects.filter(dae=self).exists()
479
480 def importer(self):
481 if not self.poste.est_importe():
482 raise Exception('Le poste de cette DAE doît être importé')
483 return True
484
a7186cbb
OL
485 def taux_devise(self):
486 if self.devise.code == 'EUR':
487 return 1
2455f48d 488 liste_taux = self.devise.tauxchange_set.order_by('-annee')
a7186cbb
OL
489 if len(liste_taux) == 0:
490 raise DeviseException(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise, self.poste.implantation))
491 else:
492 return liste_taux[0].taux
493
eed93931
OL
494 def get_salaire_anterieur_euros(self):
495 if self.devise_anterieur.code == 'EUR':
496 tx = 1
497 else:
2455f48d 498 liste_taux = self.devise_anterieur.tauxchange_set.order_by('-annee')
eed93931
OL
499 if len(liste_taux) == 0:
500 raise DeviseException(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise_anterieur, self.poste.implantation))
501 tx = liste_taux[0].taux
502 return (float)(tx) * (float)(self.salaire_anterieur)
503
504 def get_salaire_titulaire_anterieur_euros(self):
16b1454e
OL
505 if self.devise_titulaire_anterieur is None:
506 return None
2626f449 507 if self.devise_titulaire_anterieur.code == 'EUR':
eed93931
OL
508 tx = 1
509 else:
2455f48d 510 liste_taux = self.devise_titulaire_anterieur.tauxchange_set.order_by('-annee')
eed93931
OL
511 if len(liste_taux) == 0:
512 raise DeviseException(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise_titulaire_anterieur, self.poste.implantation))
513 tx = liste_taux[0].taux
514 return (float)(tx) * (float)(self.salaire_titulaire_anterieur)
515
b1baa306 516 def get_salaire_euros(self):
a7186cbb 517 tx = self.taux_devise()
b1baa306
OL
518 return (float)(tx) * (float)(self.salaire)
519
bf6fbbcf 520 def get_remunerations_brutes(self):
57bd966c 521 """
bf6fbbcf
OL
522 1 Salaire de base
523 3 Indemnité de base
524 4 Indemnité d'expatriation
525 5 Indemnité pour frais
526 6 Indemnité de logement
527 7 Indemnité de fonction
528 8 Indemnité de responsabilité
529 9 Indemnité de transport
530 10 Indemnité compensatrice
531 11 Indemnité de subsistance
532 12 Indemnité différentielle
533 13 Prime d'installation
534 14 Billet d'avion
535 15 Déménagement
536 16 Indemnité de départ
537 18 Prime de 13ième mois
538 19 Prime d'intérim
57bd966c 539 """
bf6fbbcf 540 ids = [1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19]
a4125771 541 return [r for r in self.dae_remunerations.all() if r.type_id in ids]
bf6fbbcf
OL
542
543 def get_charges_salariales(self):
544 """
545 20 Charges salariales ?
546 """
547 ids = [20, ]
a4125771 548 return [r for r in self.dae_remunerations.all() if r.type_id in ids]
bf6fbbcf
OL
549
550 def get_total_charges_salariales(self):
551 total = 0.0
552 for r in self.get_charges_salariales():
553 total += r.montant_euro()
554 return total
555
556 def get_charges_patronales(self):
557 """
558 17 Charges patronales
559 """
560 ids = [17, ]
a4125771 561 return [r for r in self.dae_remunerations.all() if r.type_id in ids]
bf6fbbcf
OL
562
563 def get_total_charges_patronales(self):
a9e52624 564 total = 0.0
bf6fbbcf 565 for r in self.get_charges_patronales():
a9e52624
OL
566 total += r.montant_euro()
567 return total
57bd966c 568
bf6fbbcf
OL
569 def get_salaire_brut(self):
570 """
571 somme des rémuérations brutes
572 """
573 total = 0.0
574 for r in self.get_remunerations_brutes():
575 total += r.montant_euro()
576 return total
577
578 def get_salaire_net(self):
579 """
580 salaire brut - charges salariales
581 """
582 total_charges = 0.0
583 for r in self.get_charges_salariales():
584 total_charges += r.montant_euro()
585 return self.get_salaire_brut() - total_charges
586
587 def get_couts_auf(self):
588 """
589 salaire net + charges patronales
590 """
591 total_charges = 0.0
592 for r in self.get_charges_patronales():
593 total_charges += r.montant_euro()
594 return self.get_salaire_net() + total_charges
595
596 def get_remunerations_tierces(self):
57bd966c 597 """
bf6fbbcf 598 2 Salaire MAD
57bd966c 599 """
a4125771 600 return [r for r in self.dae_remunerations.all() if r.type_id in (2, )]
57bd966c 601
bf6fbbcf 602 def get_total_remunerations_tierces(self):
a9e52624 603 total = 0.0
1bc84af4 604 for r in self.get_remunerations_tierces():
a9e52624
OL
605 total += r.montant_euro()
606 return total
607
c511cd1f
EMS
608 def valide(self):
609 return self.etat in (DOSSIER_ETAT_REGION_FINALISATION,
610 DOSSIER_ETAT_DRH_FINALISATION,
611 DOSSIER_ETAT_FINALISE)
612
bd28238f 613
0140cbd2 614# Tester l'enregistrement car les models.py sont importés au complet
615if not reversion.is_registered(Dossier):
616 reversion.register(Dossier)
bd28238f 617
a4125771 618class DossierPiece(rh.DossierPiece_):
2d4d2fcf 619 """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
620 Ex.: Lettre de motivation.
621 """
a4125771 622 pass
2d4d2fcf 623
a4125771 624class DossierComparaison(rh.DossierComparaison_):
03b395db
OL
625 """
626 Photo d'une comparaison salariale au moment de l'embauche.
627 """
766ca378
OL
628 statut = models.ForeignKey(rh.Statut, related_name='+', verbose_name='Statut', null=True, blank=True, )
629 classement = models.ForeignKey(rh.Classement, related_name='+', verbose_name='Classement', null=True, blank=True, )
03b395db 630
c589d980 631
2d4d2fcf 632### RÉMUNÉRATION
633
a4125771
OL
634class Remuneration(rh.Remuneration_):
635 pass
c1834169
EMS
636
637### CONTRATS
638
a4125771
OL
639class Contrat(rh.Contrat_):
640 pass
317ce433
OL
641
642# modèle de liaison entre les systèmes
643
644class ImportDossier(models.Model):
645 dae = models.ForeignKey('dae.Dossier', related_name='+')
646 rh = models.ForeignKey('rh.Dossier', related_name='+')
647
648class ImportPoste(models.Model):
649 dae = models.ForeignKey('dae.Poste', related_name='+')
650 rh = models.ForeignKey('rh.Poste', related_name='+')