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