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