1 # -=- encoding: utf-8 -=-
4 from django
.conf
import settings
5 from django
.core
.files
.storage
import FileSystemStorage
6 from django
.db
import models
8 from workflow
import PosteWorkflow
, DossierWorkflow
9 from workflow
import DOSSIER_ETAT_DRH_FINALISATION
10 from managers
import DossierManager
, PosteManager
11 import datamaster_modeles
.models
as ref
12 from rh_v1
import models
as rh
16 HELP_TEXT_DATE
= "format: aaaa-mm-jj"
17 REGIME_TRAVAIL_DEFAULT
=100.00
18 REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT
=35.00
22 storage_prive
= FileSystemStorage(settings
.PRIVE_MEDIA_ROOT
,
23 base_url
=settings
.PRIVE_MEDIA_URL
)
25 def poste_piece_dispatch(instance
, filename
):
26 path
= "poste/%s/%s" % (instance
.poste_id
, filename
)
29 def dossier_piece_dispatch(instance
, filename
):
30 path
= "dossier/%s/%s" % (instance
.dossier_id
, filename
)
36 POSTE_APPEL_CHOICES
= (
37 ('interne', 'Interne'),
38 ('externe', 'Externe'),
41 ('N', u
"Nouveau poste"),
42 ('M', u
"Poste existant"),
43 ('E', u
"Évolution de poste"),
48 class Poste(PosteWorkflow
, models
.Model
):
50 type_intervention
= models
.CharField(max_length
=1, choices
=POSTE_ACTION
, default
='N')
53 id_rh
= models
.ForeignKey(rh
.Poste
, null
=True, related_name
='+',
55 verbose_name
="Mise à jour du poste")
56 nom
= models
.CharField(verbose_name
="Titre du poste", max_length
=255)
57 implantation
= models
.ForeignKey(ref
.Implantation
)
58 type_poste
= models
.ForeignKey(rh
.TypePoste
, null
=True, related_name
='+')
59 service
= models
.ForeignKey(rh
.Service
, related_name
='+',
60 verbose_name
=u
"Direction/Service/Pôle support")
61 responsable
= models
.ForeignKey(rh
.Poste
, related_name
='+',
62 verbose_name
="Poste du responsable")
65 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
66 default
=REGIME_TRAVAIL_DEFAULT
,
67 verbose_name
="Temps de travail",
68 help_text
="% du temps complet")
69 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
71 default
=REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT
,
72 verbose_name
="Nb. heures par semaine")
75 local
= models
.BooleanField(verbose_name
="Local", default
=True, blank
=True)
76 expatrie
= models
.BooleanField(verbose_name
="Expatrié", default
=False,
78 mise_a_disposition
= models
.BooleanField(verbose_name
="Mise à disposition")
79 appel
= models
.CharField(max_length
=10, default
='interne',
80 verbose_name
="Appel à candidature",
81 choices
=POSTE_APPEL_CHOICES
)
84 classement_min
= models
.ForeignKey(rh
.Classement
, related_name
='+',
85 blank
=True, null
=True)
86 classement_max
= models
.ForeignKey(rh
.Classement
, related_name
='+',
87 blank
=True, null
=True)
88 valeur_point_min
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+',
89 blank
=True, null
=True)
90 valeur_point_max
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+',
91 blank
=True, null
=True)
92 devise_min
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
93 devise_max
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
94 salaire_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
96 salaire_max
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
97 indemn_expat_min
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
98 indemn_expat_max
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
99 indemn_fct_min
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
100 indemn_fct_max
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
101 charges_patronales_min
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
102 charges_patronales_max
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
103 autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
104 autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2, default
=0)
106 # Comparatifs de rémunération
107 devise_comparaison
= models
.ForeignKey(rh
.Devise
, related_name
='+',
109 comp_locale_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
110 null
=True, blank
=True)
111 comp_locale_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
112 null
=True, blank
=True)
113 comp_universite_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
114 null
=True, blank
=True)
115 comp_universite_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
116 null
=True, blank
=True)
117 comp_fonctionpub_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
118 null
=True, blank
=True)
119 comp_fonctionpub_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
120 null
=True, blank
=True)
121 comp_ong_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
122 null
=True, blank
=True)
123 comp_ong_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
124 null
=True, blank
=True)
125 comp_autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
126 null
=True, blank
=True)
127 comp_autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
128 null
=True, blank
=True)
131 justification
= models
.TextField()
134 date_creation
= models
.DateTimeField(auto_now_add
=True)
135 date_modification
= models
.DateTimeField(auto_now
=True)
136 date_debut
= models
.DateField(verbose_name
="Date de début",
137 help_text
=HELP_TEXT_DATE
)
138 date_fin
= models
.DateField(null
=True, blank
=True,
139 verbose_name
="Date de fin",
140 help_text
=HELP_TEXT_DATE
)
141 actif
= models
.BooleanField(default
=True)
142 pourvu
= models
.BooleanField(default
=False)
145 objects
= PosteManager()
149 Les vues sont montées selon une clef spéciale
150 pour identifier la provenance du poste.
151 Cette méthode fournit un moyen de reconstruire cette clef
152 afin de générer les URLs.
154 return "dae-%s" % self
.id
155 key
= property(_get_key
)
157 def get_dossiers(self
):
159 Liste tous les anciens dossiers liés à ce poste.
160 (Le nom de la relation sur le rh.Poste est mal choisi
161 poste1 au lieu de dossier1)
162 Note1 : seulement le dosssier principal fait l'objet de la recherche.
163 Note2 : les dossiers sont retournés du plus récent au plus vieux.
164 (Ce test est fait en fonction du id,
165 car les dates de création sont absentes de rh v1).
167 if self
.id_rh
is None:
169 postes
= [p
for p
in self
.id_rh
.poste1
.all()]
170 return sorted(postes
, key
=lambda poste
: poste
.id, reverse
=True)
172 def get_complement_nom(self
):
174 Inspecte les modèles rh v1 pour trouver dans le dernier dossier
175 un complément de titre de poste.
177 dossiers
= self
.get_dossiers()
178 if len(dossiers
) > 0:
179 nom
= dossiers
[0].complement1
184 def get_employe(self
):
186 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
188 dossiers
= self
.get_dossiers()
189 if len(dossiers
) > 0:
190 return dossiers
[0].employe
194 def get_default_devise(self
):
195 """Récupère la devise par défaut en fonction de l'implantation
199 implantation_devise
= rh
.TauxChange
.objects \
200 .filter(implantation
=self
.implantation
)[0].devise
202 implantation_devise
= 5 # EUR
203 return implantation_devise
205 #####################
206 # Classement de poste
207 #####################
209 def get_couts_minimum(self
):
210 return (float)(self
.salaire_min
+ self
.indemn_expat_min
+ + self
.indemn_fct_min
+ self
.charges_patronales_min
+ self
.autre_min
)
212 def get_taux_minimum(self
):
213 taux_changes
= rh
.TauxChange
.objects
.filter(devise
=self
.devise_min
).order_by('annee')
214 for t
in taux_changes
:
215 if t
.implantation
== self
.implantation
:
217 if len(taux_changes
) > 0:
218 return taux_changes
[0].taux
220 raise Exception('Taux indisponible pour la devise %s (%s)' % (self
.devise_min
, self
.implantation
))
222 def get_couts_minimum_euros(self
):
223 return self
.get_couts_minimum() * self
.get_taux_minimum()
225 def get_couts_maximum(self
):
226 return (float)(self
.salaire_max
+ self
.indemn_expat_max
+ + self
.indemn_fct_max
+ self
.charges_patronales_max
+ self
.autre_max
)
228 def get_taux_maximum(self
):
229 taux_changes
= rh
.TauxChange
.objects
.filter(devise
=self
.devise_max
).order_by('annee')
230 for t
in taux_changes
:
231 if t
.implantation
== self
.implantation
:
233 if len(taux_changes
) > 0:
234 return taux_changes
[0].taux
236 raise Exception('Taux indisponible pour la devise %s (%s)' % (self
.devise_max
, self
.implantation
))
238 def get_couts_maximum_euros(self
):
239 return self
.get_couts_maximum() * self
.get_taux_maximum()
242 def show_taux_minimum(self
):
244 return self
.get_taux_minimum()
248 def show_couts_minimum_euros(self
):
250 return self
.get_couts_minimum_euros()
254 def show_taux_maximum(self
):
256 return self
.get_taux_maximum()
260 def show_couts_maximum_euros(self
):
262 return self
.get_couts_maximum_euros()
267 ######################
268 # Comparaison de poste
269 ######################
271 def est_comparable(self
):
273 Si on a au moins une valeur de saisie dans les comparaisons, alors le poste
276 if self
.comp_universite_min
is None and \
277 self
.comp_fonctionpub_min
is None and \
278 self
.comp_locale_min
is None and \
279 self
.comp_ong_min
is None and \
280 self
.comp_autre_min
is None and \
281 self
.comp_universite_max
is None and \
282 self
.comp_fonctionpub_max
is None and \
283 self
.comp_locale_max
is None and \
284 self
.comp_ong_max
is None and \
285 self
.comp_autre_max
is None:
291 def get_taux_comparaison(self
):
293 return rh
.TauxChange
.objects
.filter(implantation
=self
.implantation
, devise
=self
.devise_comparaison
)[0].taux
297 def get_comp_universite_min_euros(self
):
298 return (float)(self
.comp_universite_min
) * self
.get_taux_comparaison()
300 def get_comp_fonctionpub_min_euros(self
):
301 return (float)(self
.comp_fonctionpub_min
) * self
.get_taux_comparaison()
303 def get_comp_locale_min_euros(self
):
304 return (float)(self
.comp_locale_min
) * self
.get_taux_comparaison()
306 def get_comp_ong_min_euros(self
):
307 return (float)(self
.comp_ong_min
) * self
.get_taux_comparaison()
309 def get_comp_autre_min_euros(self
):
310 return (float)(self
.comp_autre_min
) * self
.get_taux_comparaison()
312 def get_comp_universite_max_euros(self
):
313 return (float)(self
.comp_universite_max
) * self
.get_taux_comparaison()
315 def get_comp_fonctionpub_max_euros(self
):
316 return (float)(self
.comp_fonctionpub_max
) * self
.get_taux_comparaison()
318 def get_comp_locale_max_euros(self
):
319 return (float)(self
.comp_locale_max
) * self
.get_taux_comparaison()
321 def get_comp_ong_max_euros(self
):
322 return (float)(self
.comp_ong_max
) * self
.get_taux_comparaison()
324 def get_comp_autre_max_euros(self
):
325 return (float)(self
.comp_autre_max
) * self
.get_taux_comparaison()
328 def __unicode__(self
):
330 Cette fonction est consommatrice SQL car elle cherche les dossiers
331 qui ont été liés à celui-ci.
333 complement_nom_poste
= self
.get_complement_nom()
334 if complement_nom_poste
is None:
335 complement_nom_poste
= ""
341 return u
'%s - %s (%s)' % data
344 # Tester l'enregistrement car les models.py sont importés au complet
345 if not reversion
.is_registered(Poste
):
346 reversion
.register(Poste
)
349 POSTE_FINANCEMENT_CHOICES
= (
350 ('A', 'A - Frais de personnel'),
351 ('B', 'B - Projet(s)-Titre(s)'),
355 class PosteFinancement(models
.Model
):
356 poste
= models
.ForeignKey('Poste', related_name
='financements')
357 type = models
.CharField(max_length
=1, choices
=POSTE_FINANCEMENT_CHOICES
)
358 pourcentage
= models
.DecimalField(max_digits
=12, decimal_places
=2,
359 help_text
="ex.: 33.33 % (décimale avec point)")
360 commentaire
= models
.TextField(
361 help_text
="Spécifiez la source de financement.")
366 def __unicode__(self
):
367 return u
"%s %s %s" % (self
.get_type_display(), self
.pourcentage
, self
.commentaire
)
370 class PostePiece(models
.Model
):
371 """Documents relatifs au Poste
372 Ex.: Description de poste
374 poste
= models
.ForeignKey("Poste")
375 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
376 fichier
= models
.FileField(verbose_name
="Fichier",
377 upload_to
=poste_piece_dispatch
,
378 storage
=storage_prive
)
380 class PosteComparaison(models
.Model
):
381 poste
= models
.ForeignKey('Poste', related_name
='comparaisons_internes')
382 implantation
= models
.ForeignKey(ref
.Implantation
, null
=True, blank
=True)
383 nom
= models
.CharField(verbose_name
="Poste", max_length
=255, null
=True, blank
=True)
384 montant
= models
.IntegerField(null
=True)
385 devise
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+', null
=True, blank
=True)
386 montant_euros
= models
.IntegerField(null
=True)
391 # TODO : migration pour m -> M, f -> F
398 class Employe(models
.Model
):
401 id_rh
= models
.ForeignKey(rh
.Employe
, null
=True, related_name
='+',
402 verbose_name
='Employé')
403 nom
= models
.CharField(max_length
=255)
404 prenom
= models
.CharField(max_length
=255, verbose_name
='Prénom')
405 genre
= models
.CharField(max_length
=1, choices
=GENRE_CHOICES
)
407 def __unicode__(self
):
408 return u
'%s %s' % (self
.prenom
, self
.nom
.upper())
413 STATUT_RESIDENCE_CHOICES
= (
415 ('expat', 'Expatrié'),
418 COMPTE_COMPTA_CHOICES
= (
424 class Dossier(DossierWorkflow
, models
.Model
):
427 employe
= models
.ForeignKey('Employe', related_name
='+', editable
=False)
428 poste
= models
.ForeignKey('Poste', related_name
='dossiers', editable
=False)
429 statut
= models
.ForeignKey(rh
.Statut
, related_name
='+')
430 organisme_bstg
= models
.ForeignKey(rh
.OrganismeBstg
,
431 null
=True, blank
=True,
432 verbose_name
="Organisme",
433 help_text
="Si détaché (DET) ou mis à disposition (MAD), \
434 préciser l'organisme.",
436 organisme_bstg_autre
= models
.CharField(max_length
=255,
437 verbose_name
="Autre organisme",
438 help_text
="indiquer l'organisme ici s'il n'est pas dans la liste",
442 # Données antérieures de l'employé
443 statut_anterieur
= models
.ForeignKey(
444 rh
.Statut
, related_name
='+', null
=True, blank
=True,
445 verbose_name
='Statut antérieur')
446 classement_anterieur
= models
.ForeignKey(
447 rh
.Classement
, related_name
='+', null
=True, blank
=True,
448 verbose_name
='Classement précédent')
449 salaire_anterieur
= models
.DecimalField(
450 max_digits
=12, decimal_places
=2, null
=True, default
=None,
451 blank
=True, verbose_name
='Salaire précédent')
453 # Données du titulaire précédent
454 employe_anterieur
= models
.ForeignKey(
455 rh
.Employe
, related_name
='+', null
=True, blank
=True,
456 verbose_name
='Employé précédent')
457 statut_titulaire_anterieur
= models
.ForeignKey(
458 rh
.Statut
, related_name
='+', null
=True, blank
=True,
459 verbose_name
='Statut titulaire précédent')
460 classement_titulaire_anterieur
= models
.ForeignKey(
461 rh
.Classement
, related_name
='+', null
=True, blank
=True,
462 verbose_name
='Classement titulaire précédent')
463 salaire_titulaire_anterieur
= models
.DecimalField(
464 max_digits
=12, decimal_places
=2, default
=None, null
=True,
465 blank
=True, verbose_name
='Salaire titulaire précédent')
468 remplacement
= models
.BooleanField()
469 statut_residence
= models
.CharField(max_length
=10, default
='local',
470 verbose_name
="Statut",
471 choices
=STATUT_RESIDENCE_CHOICES
)
474 classement
= models
.ForeignKey(rh
.Classement
, related_name
='+',
475 null
=True, blank
=True,
476 verbose_name
='Classement proposé')
477 salaire
= models
.DecimalField(max_digits
=12, decimal_places
=2,
478 verbose_name
='Salaire de base',
479 null
=True, default
=None)
480 devise
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
481 regime_travail
= models
.DecimalField(max_digits
=12,
483 default
=REGIME_TRAVAIL_DEFAULT
,
484 verbose_name
="Régime de travail",
485 help_text
="% du temps complet")
486 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
488 default
=REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT
,
489 verbose_name
="Nb. heures par semaine")
492 type_contrat
= models
.ForeignKey(rh
.TypeContrat
, related_name
='+')
493 contrat_date_debut
= models
.DateField(help_text
="format: aaaa-mm-jj")
494 contrat_date_fin
= models
.DateField(null
=True, blank
=True,
495 help_text
="format: aaaa-mm-jj")
498 justif_nouveau_statut_label
= u
'Justifier le statut que ce type de poste nécessite (national, expatrié, màd ou détachement)'
499 justif_nouveau_statut
= models
.TextField(verbose_name
=justif_nouveau_statut_label
, null
=True, blank
=True)
500 justif_nouveau_tmp_remplacement_label
= u
"Si l'employé effectue un remplacement temporaire, préciser"
501 justif_nouveau_tmp_remplacement
= models
.TextField(verbose_name
=justif_nouveau_tmp_remplacement_label
, null
=True, blank
=True)
502 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 "
503 justif_nouveau_salaire
= models
.TextField(verbose_name
=justif_nouveau_salaire_label
, null
=True, blank
=True)
504 justif_nouveau_commentaire_label
= u
"COMMENTAIRES ADDITIONNELS"
505 justif_nouveau_commentaire
= models
.TextField(verbose_name
=justif_nouveau_commentaire_label
, null
=True, blank
=True)
506 justif_rempl_type_contrat_label
= u
"Changement de type de contrat, ex : d'un CDD en CDI"
507 justif_rempl_type_contrat
= models
.TextField(verbose_name
=justif_rempl_type_contrat_label
, null
=True, blank
=True)
508 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"
509 justif_rempl_statut_employe
= models
.TextField(verbose_name
=justif_rempl_statut_employe_label
, null
=True, blank
=True)
510 justif_rempl_evaluation_label
= u
"L'évaluation de l'employé est-elle favorable? Préciser"
511 justif_rempl_evaluation
= models
.TextField(verbose_name
=justif_rempl_evaluation_label
, null
=True, blank
=True)
512 justif_rempl_salaire_label
= u
"Si le salaire de l'employé est modifié et/ou ne correspond pas à son classement, justifier"
513 justif_rempl_salaire
= models
.TextField(verbose_name
=justif_rempl_salaire_label
, null
=True, blank
=True)
514 justif_rempl_commentaire_label
= u
"COMMENTAIRES ADDITIONNELS"
515 justif_rempl_commentaire
= models
.TextField(verbose_name
=justif_rempl_commentaire_label
, null
=True, blank
=True)
518 compte_compta
= models
.CharField(max_length
=10, default
='aucun',
519 verbose_name
=u
'Compte comptabilité',
520 choices
=COMPTE_COMPTA_CHOICES
)
521 compte_courriel
= models
.BooleanField()
524 date_creation
= models
.DateTimeField(auto_now_add
=True)
527 objects
= DossierManager()
529 def __unicode__(self
):
530 return u
'[%s] %s - %s' % (self
.poste
.implantation
, self
.poste
.nom
, self
.employe
)
532 def get_salaire_euros(self
):
534 tx
= rh
.TauxChange
.objects
.filter(implantation
=self
.poste
.implantation
, devise
=self
.devise
)[0].taux
537 return (float)(tx
) * (float)(self
.salaire
)
539 def get_remunerations_brutes(self
):
543 4 Indemnité d'expatriation
544 5 Indemnité pour frais
545 6 Indemnité de logement
546 7 Indemnité de fonction
547 8 Indemnité de responsabilité
548 9 Indemnité de transport
549 10 Indemnité compensatrice
550 11 Indemnité de subsistance
551 12 Indemnité différentielle
552 13 Prime d'installation
555 16 Indemnité de départ
556 18 Prime de 13ième mois
559 ids
= [1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19]
560 return [r
for r
in self
.remuneration_set
.all() if r
.type_id
in ids
]
562 def get_charges_salariales(self
):
564 20 Charges salariales ?
567 return [r
for r
in self
.remuneration_set
.all() if r
.type_id
in ids
]
569 def get_total_charges_salariales(self
):
571 for r
in self
.get_charges_salariales():
572 total
+= r
.montant_euro()
575 def get_charges_patronales(self
):
577 17 Charges patronales
580 return [r
for r
in self
.remuneration_set
.all() if r
.type_id
in ids
]
582 def get_total_charges_patronales(self
):
584 for r
in self
.get_charges_patronales():
585 total
+= r
.montant_euro()
588 def get_salaire_brut(self
):
590 somme des rémuérations brutes
593 for r
in self
.get_remunerations_brutes():
594 total
+= r
.montant_euro()
597 def get_salaire_net(self
):
599 salaire brut - charges salariales
602 for r
in self
.get_charges_salariales():
603 total_charges
+= r
.montant_euro()
604 return self
.get_salaire_brut() - total_charges
606 def get_couts_auf(self
):
608 salaire net + charges patronales
611 for r
in self
.get_charges_patronales():
612 total_charges
+= r
.montant_euro()
613 return self
.get_salaire_net() + total_charges
615 def get_remunerations_tierces(self
):
619 return [r
for r
in self
.remuneration_set
.all() if r
.type_id
in (2, )]
621 def get_total_remunerations_tierces(self
):
623 for r
in self
.get_remunerations_tierces():
624 total
+= r
.montant_euro()
628 # Tester l'enregistrement car les models.py sont importés au complet
629 if not reversion
.is_registered(Dossier
):
630 reversion
.register(Dossier
)
632 class DossierPiece(models
.Model
):
633 """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
634 Ex.: Lettre de motivation.
636 dossier
= models
.ForeignKey("Dossier")
637 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
638 fichier
= models
.FileField(verbose_name
="Fichier",
639 upload_to
=dossier_piece_dispatch
,
640 storage
=storage_prive
)
643 class DossierComparaison(models
.Model
):
645 Photo d'une comparaison salariale au moment de l'embauche.
647 dossier
= models
.ForeignKey('Dossier', related_name
='comparaisons')
648 implantation
= models
.ForeignKey(ref
.Implantation
, null
=True, blank
=True)
649 poste
= models
.CharField(max_length
=255, null
=True, blank
=True)
650 personne
= models
.CharField(max_length
=255, null
=True, blank
=True)
651 montant
= models
.IntegerField(null
=True)
652 devise
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+', null
=True, blank
=True)
653 montant_euros
= models
.IntegerField(null
=True)
658 class Remuneration(models
.Model
):
660 dossier
= models
.ForeignKey('Dossier', db_column
='dossier')
661 type = models
.ForeignKey(rh
.TypeRemuneration
, db_column
='type',
663 montant
= models
.DecimalField(max_digits
=12, decimal_places
=2,
665 devise
= models
.ForeignKey(rh
.Devise
, to_field
='code',
666 db_column
='devise', related_name
='+')
667 precision
= models
.CharField(max_length
=255, null
=True, blank
=True)
670 date_creation
= models
.DateField(auto_now_add
=True)
671 user_creation
= models
.IntegerField(null
=True, blank
=True) # TODO : user
673 def montant_mois(self
):
674 return round(self
.montant
/ 12, 2)
676 def taux_devise(self
):
677 return self
.devise
.tauxchange_set
.order_by('-annee').all()[0].taux
679 def montant_euro(self
):
680 return round(float(self
.montant
) * float(self
.taux_devise()), 2)
682 def montant_euro_mois(self
):
683 return round(self
.montant_euro() / 12, 2)