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