wip
[auf_rh_dae.git] / project / dae / models.py
CommitLineData
bd28238f 1# -=- encoding: utf-8 -=-
3f3cf5f3 2
5633fa41 3from django.conf import settings
36341125 4from django.core.files.storage import FileSystemStorage
a9c281dd
OL
5from django.db import models
6import reversion
3f5cbabe 7from rh import models as rh
afc204bf 8from workflow import PosteWorkflow, DossierWorkflow
c511cd1f
EMS
9from workflow import DOSSIER_ETAT_DRH_FINALISATION, DOSSIER_ETAT_REGION_FINALISATION, \
10 DOSSIER_ETAT_FINALISE
a2c3ad52 11from auf.django.metadata.models import AUFMetadata
3f5cbabe 12from managers import *
4047b783 13from rh.models import HELP_TEXT_DATE
bd28238f 14
bd28238f 15
d766bf2c 16# Upload de fichiers
34dad720 17UPLOAD_STORAGE = FileSystemStorage(settings.PRIVE_MEDIA_ROOT)
d766bf2c 18
36341125 19
2d4d2fcf 20### POSTE
21
22POSTE_APPEL_CHOICES = (
23 ('interne', 'Interne'),
24 ('externe', 'Externe'),
25)
c3be904d
OL
26POSTE_ACTION = (
27 ('N', u"Nouveau poste"),
28 ('M', u"Poste existant"),
29 ('E', u"Évolution de poste"),
30)
31
36341125 32
ae5c920b
OL
33class DeviseException(Exception):
34 silent_variable_failure = True
35
1c7d67ce 36
3f5cbabe 37class Poste(PosteWorkflow, rh.Poste_):
c3be904d
OL
38
39 type_intervention = models.CharField(max_length=1, choices=POSTE_ACTION, default='N')
40
bd28238f 41 # Modèle existant
5d680e84 42 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
2d4d2fcf 43 editable=False,
c1195471 44 verbose_name=u"Mise à jour du poste")
bd28238f
NC
45
46 # Rémunération
3f5cbabe 47 indemn_expat_min = models.DecimalField(max_digits=13, decimal_places=2, default=0)
5f61bccb
OL
48 indemn_expat_max = models.DecimalField(max_digits=12, decimal_places=2, default=0)
49 indemn_fct_min = models.DecimalField(max_digits=12, decimal_places=2, default=0)
50 indemn_fct_max = models.DecimalField(max_digits=12, decimal_places=2, default=0)
51 charges_patronales_min = models.DecimalField(max_digits=12, decimal_places=2, default=0)
52 charges_patronales_max = models.DecimalField(max_digits=12, decimal_places=2, default=0)
bd28238f 53
1c7d67ce
OL
54 # Managers
55 objects = PosteManager()
56
317ce433
OL
57
58 def est_importe(self):
59 """Test si le poste a déjà été importé"""
60 return ImportPoste.objects.filter(dae=self).exists()
61
62 def importer(self):
317ce433
OL
63 if self.est_importe():
64 return ImportPoste.objects.get(dae=self)
65 rh_poste = rh.Poste()
66 # Faire une copie profonde de l'objet.
67 # PosteFinancement, PosteComparaison, Remun modele a ajuster...
a184c555
OL
68
69 def copy_model(src, dst, exclude=[]):
70 keys = [f.name for f in src._meta.fields if f.name not in ['id', ] + exclude]
71 for k in keys:
72 setattr(dst, k, getattr(src, k))
73 return dst
74
75 rh_poste = copy_model(self, rh_poste)
76 rh_poste.save()
77 print rh_poste.id
78
79 for o in self.dae_financements.all():
80 rh_financement = rh.PosteFinancement()
81 rh_financement = copy_model(o, rh_financement, exclude=['poste',])
82 rh_financement.poste = rh_poste
83 rh_financement.save()
84
85 for o in self.dae_pieces.all():
86 rh_piece = rh.PostePiece()
87 rh_piece = copy_model(o, rh_piece, exclude=['poste',])
88 rh_piece.poste = rh_poste
89 rh_piece.save()
90
91 for o in self.dae_comparaisons_internes.all():
92 rh_comp = rh.PosteComparaison()
93 rh_comp = copy_model(o, rh_financement, exclude=['poste',])
94 rh_comp.poste = rh_poste
95 rh_comp.save()
96
317ce433
OL
97 return rh_poste
98
03858ba5
OL
99 def _get_key(self):
100 """
1bc84af4 101 Les vues sont montées selon une clef spéciale
2d4d2fcf 102 pour identifier la provenance du poste.
1bc84af4 103 Cette méthode fournit un moyen de reconstruire cette clef
2d4d2fcf 104 afin de générer les URLs.
03858ba5
OL
105 """
106 return "dae-%s" % self.id
107 key = property(_get_key)
108
f3333b0e
OL
109 def get_dossiers(self):
110 """
111 Liste tous les anciens dossiers liés à ce poste.
1bc84af4 112 (Le nom de la relation sur le rh.Poste est mal choisi
2d4d2fcf 113 poste1 au lieu de dossier1)
f3333b0e 114 Note1 : seulement le dosssier principal fait l'objet de la recherche.
1bc84af4
EMS
115 Note2 : les dossiers sont retournés du plus récent au plus vieux.
116 (Ce test est fait en fonction du id,
2d4d2fcf 117 car les dates de création sont absentes de rh v1).
f3333b0e
OL
118 """
119 if self.id_rh is None:
120 return []
16b1454e 121 return self.id_rh.rh_dossiers.all()
428e3c0b 122
f3333b0e
OL
123
124 def get_employe(self):
125 """
126 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
127 """
128 dossiers = self.get_dossiers()
129 if len(dossiers) > 0:
130 return dossiers[0].employe
131 else:
132 return None
133
179f6b49 134 def get_default_devise(self):
1bc84af4 135 """Récupère la devise par défaut en fonction de l'implantation
2d4d2fcf 136 (EUR autrement)
137 """
179f6b49 138 try:
6e4600ef 139 implantation_devise = rh.TauxChange.objects \
140 .filter(implantation=self.implantation)[0].devise
179f6b49
OL
141 except:
142 implantation_devise = 5 # EUR
143 return implantation_devise
144
c0413a6f
OL
145 #####################
146 # Classement de poste
147 #####################
148
149 def get_couts_minimum(self):
83b94a87
EMS
150 return self.salaire_min + self.indemn_expat_min + self.indemn_fct_min + self.charges_patronales_min + self.autre_min
151
152 def get_salaire_minimum(self):
153 return self.get_couts_minimum() - self.charges_patronales_min
c0413a6f
OL
154
155 def get_taux_minimum(self):
4e439a89
OL
156 if self.devise_min.code == 'EUR':
157 return 1
2455f48d 158 liste_taux = self.devise_min.tauxchange_set.order_by('-annee')
4e439a89
OL
159 if len(liste_taux) == 0:
160 raise DeviseException(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise_min, self.implantation))
b6825282 161 else:
4e439a89 162 return liste_taux[0].taux
c0413a6f
OL
163
164 def get_couts_minimum_euros(self):
fa5b95ed 165 return float(self.get_couts_minimum()) * self.get_taux_minimum()
c0413a6f 166
83b94a87 167 def get_salaire_minimum_euros(self):
fa5b95ed 168 return float(self.get_salaire_minimum()) * self.get_taux_minimum()
83b94a87 169
c0413a6f 170 def get_couts_maximum(self):
83b94a87
EMS
171 return self.salaire_max + self.indemn_expat_max + self.indemn_fct_max + self.charges_patronales_max + self.autre_max
172
173 def get_salaire_maximum(self):
174 return self.get_couts_maximum() - self.charges_patronales_max
c0413a6f
OL
175
176 def get_taux_maximum(self):
4e439a89
OL
177 if self.devise_max.code == 'EUR':
178 return 1
2455f48d 179 liste_taux = self.devise_max.tauxchange_set.order_by('-annee')
4e439a89
OL
180 if len(liste_taux) == 0:
181 raise DeviseException(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise_max, self.implantation))
b6825282 182 else:
4e439a89 183 return liste_taux[0].taux
c0413a6f
OL
184
185 def get_couts_maximum_euros(self):
fa5b95ed 186 return float(self.get_couts_maximum()) * self.get_taux_maximum()
c0413a6f 187
83b94a87 188 def get_salaire_maximum_euros(self):
fa5b95ed 189 return float(self.get_salaire_maximum()) * self.get_taux_maximum()
12c7f8a7
OL
190
191 def show_taux_minimum(self):
192 try:
193 return self.get_taux_minimum()
83b94a87 194 except DeviseException, e:
12c7f8a7
OL
195 return e
196
197 def show_couts_minimum_euros(self):
198 try:
199 return self.get_couts_minimum_euros()
83b94a87
EMS
200 except DeviseException, e:
201 return e
202
203 def show_salaire_minimum_euros(self):
204 try:
205 return self.get_salaire_minimum_euros()
206 except DeviseException, e:
12c7f8a7
OL
207 return e
208
209 def show_taux_maximum(self):
210 try:
211 return self.get_taux_maximum()
83b94a87 212 except DeviseException, e:
12c7f8a7
OL
213 return e
214
215 def show_couts_maximum_euros(self):
216 try:
217 return self.get_couts_maximum_euros()
83b94a87
EMS
218 except DeviseException, e:
219 return e
220
221 def show_salaire_maximum_euros(self):
222 try:
223 return self.get_salaire_maximum_euros()
224 except DeviseException, e:
12c7f8a7
OL
225 return e
226
227
c0413a6f
OL
228 ######################
229 # Comparaison de poste
230 ######################
a3fee9c5
OL
231
232 def est_comparable(self):
233 """
234 Si on a au moins une valeur de saisie dans les comparaisons, alors le poste
235 est comparable.
236 """
237 if self.comp_universite_min is None and \
238 self.comp_fonctionpub_min is None and \
239 self.comp_locale_min is None and \
240 self.comp_ong_min is None and \
241 self.comp_autre_min is None and \
242 self.comp_universite_max is None and \
243 self.comp_fonctionpub_max is None and \
244 self.comp_locale_max is None and \
245 self.comp_ong_max is None and \
246 self.comp_autre_max is None:
247 return False
248 else:
249 return True
1bc84af4 250
a3fee9c5 251
c0413a6f
OL
252 def get_taux_comparaison(self):
253 try:
2455f48d 254 return rh.TauxChange.objects.filter(devise=self.devise_comparaison)[0].taux
c0413a6f
OL
255 except:
256 return 1
257
258 def get_comp_universite_min_euros(self):
259 return (float)(self.comp_universite_min) * self.get_taux_comparaison()
260
261 def get_comp_fonctionpub_min_euros(self):
262 return (float)(self.comp_fonctionpub_min) * self.get_taux_comparaison()
263
264 def get_comp_locale_min_euros(self):
265 return (float)(self.comp_locale_min) * self.get_taux_comparaison()
266
267 def get_comp_ong_min_euros(self):
268 return (float)(self.comp_ong_min) * self.get_taux_comparaison()
269
270 def get_comp_autre_min_euros(self):
271 return (float)(self.comp_autre_min) * self.get_taux_comparaison()
272
273 def get_comp_universite_max_euros(self):
274 return (float)(self.comp_universite_max) * self.get_taux_comparaison()
275
276 def get_comp_fonctionpub_max_euros(self):
277 return (float)(self.comp_fonctionpub_max) * self.get_taux_comparaison()
278
279 def get_comp_locale_max_euros(self):
280 return (float)(self.comp_locale_max) * self.get_taux_comparaison()
281
282 def get_comp_ong_max_euros(self):
283 return (float)(self.comp_ong_max) * self.get_taux_comparaison()
284
285 def get_comp_autre_max_euros(self):
286 return (float)(self.comp_autre_max) * self.get_taux_comparaison()
287
a9e52624 288
5d680e84 289 def __unicode__(self):
f3333b0e 290 """
1bc84af4 291 Cette fonction est consommatrice SQL car elle cherche les dossiers
2d4d2fcf 292 qui ont été liés à celui-ci.
f3333b0e 293 """
f3333b0e
OL
294 data = (
295 self.implantation,
296 self.type_poste.nom,
297 self.nom,
f3333b0e 298 )
a7c68130 299 return u'%s - %s (%s)' % data
5d680e84 300
bd28238f 301
a9c281dd
OL
302# Tester l'enregistrement car les models.py sont importés au complet
303if not reversion.is_registered(Poste):
304 reversion.register(Poste)
305
bd28238f 306
5d680e84
NC
307POSTE_FINANCEMENT_CHOICES = (
308 ('A', 'A - Frais de personnel'),
309 ('B', 'B - Projet(s)-Titre(s)'),
310 ('C', 'C - Autre')
311)
bd28238f 312
317ce433 313class PosteFinancement(rh.PosteFinancement_):
a4125771 314 pass
1d0f4eef 315
317ce433 316class PostePiece(rh.PostePiece_):
a4125771 317 pass
068d1462 318
317ce433 319class PosteComparaison(rh.PosteComparaison_):
766ca378
OL
320 statut = models.ForeignKey(rh.Statut, related_name='+', verbose_name=u'Statut', null=True, blank=True, )
321 classement = models.ForeignKey(rh.Classement, related_name='+', verbose_name=u'Classement', null=True, blank=True, )
068d1462 322
2d4d2fcf 323### EMPLOYÉ/PERSONNE
324
325# TODO : migration pour m -> M, f -> F
c589d980 326
bd28238f 327GENRE_CHOICES = (
139686f2
NC
328 ('m', 'Homme'),
329 ('f', 'Femme'),
bd28238f
NC
330)
331
a2c3ad52 332class Employe(AUFMetadata):
bd28238f
NC
333
334 # Modèle existant
428e3c0b 335 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+',
c1195471 336 verbose_name=u'Employé')
bd28238f 337 nom = models.CharField(max_length=255)
c1195471 338 prenom = models.CharField(max_length=255, verbose_name=u'Prénom')
07b40eda 339 genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
bd28238f 340
139686f2 341 def __unicode__(self):
2d4d2fcf 342 return u'%s %s' % (self.prenom, self.nom.upper())
139686f2 343
bd28238f 344
2d4d2fcf 345### DOSSIER
346
347STATUT_RESIDENCE_CHOICES = (
348 ('local', 'Local'),
349 ('expat', 'Expatrié'),
350)
351
bd28238f 352COMPTE_COMPTA_CHOICES = (
494ff2be
NC
353 ('coda', 'CODA'),
354 ('scs', 'SCS'),
355 ('aucun', 'Aucun'),
bd28238f
NC
356)
357
16b1454e
OL
358class Dossier(DossierWorkflow, rh.Dossier_):
359 poste = models.ForeignKey('Poste', db_column='poste', related_name='%(app_label)s_dossiers')
360 employe = models.ForeignKey('Employe', db_column='employe',
361 related_name='%(app_label)s_dossiers',
362 verbose_name=u"Employé")
0288adb5 363 organisme_bstg_autre = models.CharField(max_length=255,
c1195471 364 verbose_name=u"Autre organisme",
0288adb5
OL
365 help_text="indiquer l'organisme ici s'il n'est pas dans la liste",
366 null=True,
367 blank=True,)
bd28238f 368
139686f2
NC
369 # Données antérieures de l'employé
370 statut_anterieur = models.ForeignKey(
371 rh.Statut, related_name='+', null=True, blank=True,
c1195471 372 verbose_name=u'Statut antérieur')
139686f2
NC
373 classement_anterieur = models.ForeignKey(
374 rh.Classement, related_name='+', null=True, blank=True,
c1195471 375 verbose_name=u'Classement précédent')
139686f2
NC
376 salaire_anterieur = models.DecimalField(
377 max_digits=12, decimal_places=2, null=True, default=None,
481fbd33 378 blank=True, verbose_name=u'Salaire précédent')
e158c6de
DB
379 devise_anterieur = models.ForeignKey(rh.Devise, related_name='+',
380 null=True, blank=True)
381 type_contrat_anterieur = models.ForeignKey(rh.TypeContrat,
382 related_name='+', null=True, blank=True,
383 verbose_name=u'Type contrat antérieur', )
139686f2
NC
384
385 # Données du titulaire précédent
386 employe_anterieur = models.ForeignKey(
387 rh.Employe, related_name='+', null=True, blank=True,
c1195471 388 verbose_name=u'Employé précédent')
139686f2
NC
389 statut_titulaire_anterieur = models.ForeignKey(
390 rh.Statut, related_name='+', null=True, blank=True,
c1195471 391 verbose_name=u'Statut titulaire précédent')
139686f2
NC
392 classement_titulaire_anterieur = models.ForeignKey(
393 rh.Classement, related_name='+', null=True, blank=True,
c1195471 394 verbose_name=u'Classement titulaire précédent')
139686f2
NC
395 salaire_titulaire_anterieur = models.DecimalField(
396 max_digits=12, decimal_places=2, default=None, null=True,
481fbd33 397 blank=True, verbose_name=u'Salaire titulaire précédent')
f8c7c0b8 398 devise_titulaire_anterieur = models.ForeignKey(rh.Devise, related_name='+', null=True, blank=True)
494ff2be 399
bd28238f 400 # Rémunération
16b1454e 401 salaire = models.DecimalField(max_digits=13, decimal_places=2,
c1195471 402 verbose_name=u'Salaire de base',
2d4d2fcf 403 null=True, default=None)
e8e75458 404 devise = models.ForeignKey(rh.Devise, default=5, related_name='+')
bd28238f
NC
405
406 # Contrat
5d680e84 407 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
b666864e 408 contrat_date_debut = models.DateField(help_text=HELP_TEXT_DATE)
1f109689 409 contrat_date_fin = models.DateField(null=True, blank=True,
b666864e 410 help_text=HELP_TEXT_DATE)
bd28238f 411
29dffede
OL
412 # Justifications
413 justif_nouveau_statut_label = u'Justifier le statut que ce type de poste nécessite (national, expatrié, màd ou détachement)'
414 justif_nouveau_statut = models.TextField(verbose_name=justif_nouveau_statut_label, null=True, blank=True)
a83daab3 415 justif_nouveau_tmp_remplacement_label = u"Si l'employé effectue un remplacement temporaire, préciser"
29dffede 416 justif_nouveau_tmp_remplacement = models.TextField(verbose_name=justif_nouveau_tmp_remplacement_label, null=True, blank=True)
a83daab3 417 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 418 justif_nouveau_salaire = models.TextField(verbose_name=justif_nouveau_salaire_label, null=True, blank=True)
a83daab3 419 justif_nouveau_commentaire_label = u"COMMENTAIRES ADDITIONNELS"
29dffede
OL
420 justif_nouveau_commentaire = models.TextField(verbose_name=justif_nouveau_commentaire_label, null=True, blank=True)
421 justif_rempl_type_contrat_label = u"Changement de type de contrat, ex : d'un CDD en CDI"
422 justif_rempl_type_contrat = models.TextField(verbose_name=justif_rempl_type_contrat_label, null=True, blank=True)
a83daab3 423 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 424 justif_rempl_statut_employe = models.TextField(verbose_name=justif_rempl_statut_employe_label, null=True, blank=True)
a83daab3 425 justif_rempl_evaluation_label = u"L'évaluation de l'employé est-elle favorable? Préciser"
29dffede
OL
426 justif_rempl_evaluation = models.TextField(verbose_name=justif_rempl_evaluation_label, null=True, blank=True)
427 justif_rempl_salaire_label = u"Si le salaire de l'employé est modifié et/ou ne correspond pas à son classement, justifier"
428 justif_rempl_salaire = models.TextField(verbose_name=justif_rempl_salaire_label, null=True, blank=True)
a83daab3 429 justif_rempl_commentaire_label = u"COMMENTAIRES ADDITIONNELS"
29dffede
OL
430 justif_rempl_commentaire = models.TextField(verbose_name=justif_rempl_commentaire_label, null=True, blank=True)
431
bd28238f 432 # Comptes
dfc2c344 433 compte_compta = models.CharField(max_length=10, default='aucun',
434 verbose_name=u'Compte comptabilité',
435 choices=COMPTE_COMPTA_CHOICES)
bd28238f 436 compte_courriel = models.BooleanField()
428e3c0b 437
c3f0b49f
EMS
438 # DAE numérisée
439 dae_numerisee = models.FileField(upload_to='dae/dae_numerisee', storage=UPLOAD_STORAGE,
5be87e56 440 blank=True, null=True, verbose_name="DAE numérisée")
c3f0b49f 441
e4f56614
OL
442 # Managers
443 objects = DossierManager()
428e3c0b 444
16b1454e
OL
445 def __init__(self, *args, **kwargs):
446 # Bouchon pour créer une date fictive necessaire pour valider un dossier
447 # à cause de l'héritage
448 super(rh.Dossier_, self).__init__(*args, **kwargs)
449 super(DossierWorkflow, self).__init__(*args, **kwargs)
450 import datetime
451 self.date_debut = datetime.datetime.today()
452
aec2c91e 453 def __unicode__(self):
e4f56614 454 return u'[%s] %s - %s' % (self.poste.implantation, self.poste.nom, self.employe)
bd28238f 455
317ce433
OL
456 def est_importe(self):
457 """Test si le dossier a déjà été importé"""
458 return dae.ImportDossier.objects.filter(dae=self).exists()
459
460 def importer(self):
461 if not self.poste.est_importe():
462 raise Exception('Le poste de cette DAE doît être importé')
463 return True
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():
e84c8ef1 524 total += r.montant_euros()
bf6fbbcf
OL
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():
e84c8ef1 537 total += r.montant_euros()
a9e52624 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():
e84c8ef1 546 total += r.montant_euros()
bf6fbbcf
OL
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():
e84c8ef1 555 total_charges += r.montant_euros()
bf6fbbcf
OL
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():
e84c8ef1 564 total_charges += r.montant_euros()
bf6fbbcf
OL
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():
e84c8ef1 576 total += r.montant_euros()
a9e52624
OL
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='+')