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