1 # -=- encoding: utf-8 -=-
4 from decimal
import Decimal
5 from dateutil
.relativedelta
import relativedelta
6 from datetime
import date
, timedelta
8 from django
.conf
import settings
9 from django
.core
.files
.storage
import FileSystemStorage
10 from django
.db
import models
11 from django
.db
.models
import Q
15 from auf
.django
.references
import models
as ref
17 from project
.dae
.managers
import (
18 PosteManager
, DossierManager
, ImplantationManager
)
19 from project
.dae
.workflow
import PosteWorkflow
, DossierWorkflow
20 from project
.dae
.workflow
import \
21 DOSSIER_ETAT_DRH_FINALISATION
, DOSSIER_ETAT_REGION_FINALISATION
, \
23 from project
.rh
import models
as rh
24 from project
.rh
.models
import HELP_TEXT_DATE
27 UPLOAD_STORAGE
= FileSystemStorage(settings
.PRIVE_MEDIA_ROOT
)
32 POSTE_APPEL_CHOICES
= (
33 ('interne', 'Interne'),
34 ('externe', 'Externe'),
37 ('N', u
"Nouveau poste"),
38 ('M', u
"Poste existant"),
39 ('E', u
"Évolution de poste"),
43 class DeviseException(Exception):
44 silent_variable_failure
= True
47 class Poste(PosteWorkflow
, rh
.Poste_
):
49 type_intervention
= models
.CharField(
50 max_length
=1, choices
=POSTE_ACTION
, default
='N'
54 id_rh
= models
.ForeignKey(
55 rh
.Poste
, null
=True, related_name
='postes_dae', editable
=False,
56 verbose_name
=u
"Mise à jour du poste"
60 indemn_expat_min
= models
.DecimalField(
61 max_digits
=13, decimal_places
=2, default
=0
63 indemn_expat_max
= models
.DecimalField(
64 max_digits
=12, decimal_places
=2, default
=0
66 indemn_fct_min
= models
.DecimalField(
67 max_digits
=12, decimal_places
=2, default
=0
69 indemn_fct_max
= models
.DecimalField(
70 max_digits
=12, decimal_places
=2, default
=0
72 charges_patronales_min
= models
.DecimalField(
73 max_digits
=12, decimal_places
=2, default
=0
75 charges_patronales_max
= models
.DecimalField(
76 max_digits
=12, decimal_places
=2, default
=0
80 def total_employe_min(self
):
81 res
= ((self
.salaire_min
or Decimal('0')) +
82 (self
.indemn_fct_min
or Decimal('0')) +
83 (self
.indemn_expat_min
or Decimal('0'))
88 def total_employe_max(self
):
89 return ((self
.salaire_max
or Decimal('0')) +
90 (self
.indemn_fct_max
or Decimal('0')) +
91 (self
.indemn_expat_max
or Decimal('0'))
95 objects
= PosteManager()
98 def traitement_min_cad(self
):
99 return ((self
.salaire_min
or Decimal('0')) +
100 (self
.indemn_fct_min
or Decimal('0')))
103 def traitement_max_cad(self
):
104 return ((self
.salaire_max
or Decimal('0')) +
105 (self
.indemn_fct_max
or Decimal('0')))
109 Les vues sont montées selon une clef spéciale
110 pour identifier la provenance du poste.
111 Cette méthode fournit un moyen de reconstruire cette clef
112 afin de générer les URLs.
114 return "dae-%s" % self
.id
115 key
= property(_get_key
)
117 def get_dossiers(self
):
119 Liste tous les anciens dossiers liés à ce poste.
120 (Le nom de la relation sur le rh.Poste est mal choisi
121 poste1 au lieu de dossier1)
122 Note1 : seulement le dosssier principal fait l'objet de la recherche.
123 Note2 : les dossiers sont retournés du plus récent au plus vieux.
124 (Ce test est fait en fonction du id,
125 car les dates de création sont absentes de rh v1).
127 if self
.id_rh
is None:
129 return self
.id_rh
.rh_dossiers
.all()
133 Retourne le poste RH s'il existe.
137 def importer_dans_rh(self
):
139 Importe le poste DAE dans un poste RH existant ou nouveau.
141 dans_rh
= self
.dans_rh()
142 poste_rh
= dans_rh
or rh
.Poste()
143 poste_rh
.nom
= self
.nom
144 poste_rh
.implantation
= self
.implantation
145 poste_rh
.type_poste
= self
.type_poste
146 poste_rh
.service
= self
.service
147 poste_rh
.responsable
= self
.responsable
148 poste_rh
.regime_travail
= self
.regime_travail
149 poste_rh
.regime_travail_nb_heure_semaine
= \
150 self
.regime_travail_nb_heure_semaine
151 poste_rh
.local
= self
.local
152 poste_rh
.expatrie
= self
.expatrie
153 poste_rh
.mise_a_disposition
= self
.mise_a_disposition
154 poste_rh
.appel
= self
.appel
155 poste_rh
.classement_min
= self
.classement_min
156 poste_rh
.classement_max
= self
.classement_max
157 poste_rh
.valeur_point_min
= self
.valeur_point_min
158 poste_rh
.valeur_point_max
= self
.valeur_point_max
159 poste_rh
.devise_min
= self
.devise_min
160 poste_rh
.devise_max
= self
.devise_max
161 poste_rh
.salaire_min
= self
.salaire_min
162 poste_rh
.salaire_max
= self
.salaire_max
163 poste_rh
.indemn_min
= self
.indemn_fct_min
164 poste_rh
.indemn_max
= self
.indemn_fct_max
165 poste_rh
.autre_min
= \
166 self
.indemn_expat_min
+ self
.charges_patronales_min
+ \
168 poste_rh
.autre_max
= \
169 self
.indemn_expat_max
+ self
.charges_patronales_max
+ \
171 poste_rh
.devise_comparaison
= self
.devise_comparaison
172 poste_rh
.comp_locale_min
= self
.comp_locale_min
173 poste_rh
.comp_locale_max
= self
.comp_locale_max
174 poste_rh
.comp_universite_min
= self
.comp_universite_min
175 poste_rh
.comp_universite_max
= self
.comp_universite_max
176 poste_rh
.comp_fonctionpub_min
= self
.comp_fonctionpub_min
177 poste_rh
.comp_fonctionpub_max
= self
.comp_fonctionpub_max
178 poste_rh
.comp_ong_min
= self
.comp_ong_min
179 poste_rh
.comp_ong_max
= self
.comp_ong_max
180 poste_rh
.comp_autre_min
= self
.comp_autre_min
181 poste_rh
.comp_autre_max
= self
.comp_autre_max
182 poste_rh
.justification
= self
.justification
184 poste_rh
.date_debut
= self
.date_debut
185 poste_rh
.date_fin
= self
.date_fin
188 for piece
in self
.dae_pieces
.all():
189 piece_rh
= poste_rh
.rh_pieces
.create(
193 if not settings
.DEBUG
:
194 piece_rh
.fichier
.save(
195 os
.path
.basename(piece
.fichier
.name
), piece
.fichier
198 rh
.PosteComparaison
.objects
.filter(poste
=poste_rh
).delete()
199 for comp
in self
.dae_comparaisons_internes
.all():
200 poste_rh
.rh_comparaisons_internes
.create(
201 implantation
=comp
.implantation
,
203 montant
=comp
.montant
,
207 rh
.PosteFinancement
.objects
.filter(poste
=poste_rh
).delete()
208 for financement
in self
.dae_financements
.all():
209 poste_rh
.rh_financements
.create(
210 type=financement
.type,
211 pourcentage
=financement
.pourcentage
,
212 commentaire
=financement
.commentaire
215 self
.id_rh
= poste_rh
219 def get_employe(self
):
221 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
223 dossiers
= self
.get_dossiers()
224 if len(dossiers
) > 0:
225 return dossiers
[0].employe
229 def get_default_devise(self
):
230 """Récupère la devise par défaut en fonction de l'implantation
234 implantation_devise
= rh
.TauxChange
.objects \
235 .filter(implantation
=self
.implantation
)[0].devise
237 implantation_devise
= 5 # EUR
238 return implantation_devise
240 #####################
241 # Classement de poste
242 #####################
244 def get_couts_minimum(self
):
245 return self
.salaire_min
+ self
.indemn_expat_min
+ \
246 self
.indemn_fct_min
+ self
.charges_patronales_min
+ \
249 def get_salaire_minimum(self
):
250 return self
.get_couts_minimum() - self
.charges_patronales_min
252 def get_taux_minimum(self
):
253 if self
.devise_min
.code
== 'EUR':
255 liste_taux
= self
.devise_min
.tauxchange_set
.order_by('-annee')
256 if len(liste_taux
) == 0:
257 raise DeviseException(
258 u
"La devise %s n'a pas de taux pour l'implantation %s" %
259 (self
.devise_min
, self
.implantation
))
261 return liste_taux
[0].taux
263 def get_couts_minimum_euros(self
):
264 return float(self
.get_couts_minimum()) * self
.get_taux_minimum()
266 def get_salaire_minimum_euros(self
):
267 return float(self
.get_salaire_minimum()) * self
.get_taux_minimum()
269 def get_couts_maximum(self
):
270 return self
.salaire_max
+ self
.indemn_expat_max
+ \
271 self
.indemn_fct_max
+ self
.charges_patronales_max
+ \
274 def get_salaire_maximum(self
):
275 return self
.get_couts_maximum() - self
.charges_patronales_max
277 def get_taux_maximum(self
):
278 if self
.devise_max
.code
== 'EUR':
280 liste_taux
= self
.devise_max
.tauxchange_set
.order_by('-annee')
281 if len(liste_taux
) == 0:
282 raise DeviseException(
283 u
"La devise %s n'a pas de taux pour l'implantation %s" %
284 (self
.devise_max
, self
.implantation
)
287 return liste_taux
[0].taux
289 def get_couts_maximum_euros(self
):
290 return float(self
.get_couts_maximum()) * self
.get_taux_maximum()
292 def get_salaire_maximum_euros(self
):
293 return float(self
.get_salaire_maximum()) * self
.get_taux_maximum()
295 def show_taux_minimum(self
):
297 return self
.get_taux_minimum()
298 except DeviseException
, e
:
301 def show_couts_minimum_euros(self
):
303 return self
.get_couts_minimum_euros()
304 except DeviseException
, e
:
307 def show_salaire_minimum_euros(self
):
309 return self
.get_salaire_minimum_euros()
310 except DeviseException
, e
:
313 def show_taux_maximum(self
):
315 return self
.get_taux_maximum()
316 except DeviseException
, e
:
319 def show_couts_maximum_euros(self
):
321 return self
.get_couts_maximum_euros()
322 except DeviseException
, e
:
325 def show_salaire_maximum_euros(self
):
327 return self
.get_salaire_maximum_euros()
328 except DeviseException
, e
:
331 # Comparaison de poste
332 def est_comparable(self
):
334 Si on a au moins une valeur de saisie dans les comparaisons, alors
335 le poste est comparable.
337 if self
.comp_universite_min
is None and \
338 self
.comp_fonctionpub_min
is None and \
339 self
.comp_locale_min
is None and \
340 self
.comp_ong_min
is None and \
341 self
.comp_autre_min
is None and \
342 self
.comp_universite_max
is None and \
343 self
.comp_fonctionpub_max
is None and \
344 self
.comp_locale_max
is None and \
345 self
.comp_ong_max
is None and \
346 self
.comp_autre_max
is None:
351 def get_taux_comparaison(self
):
353 return rh
.TauxChange
.objects \
354 .filter(devise
=self
.devise_comparaison
)[0].taux
358 def get_comp_universite_min_euros(self
):
359 return (float)(self
.comp_universite_min
) * self
.get_taux_comparaison()
361 def get_comp_fonctionpub_min_euros(self
):
362 return (float)(self
.comp_fonctionpub_min
) * self
.get_taux_comparaison()
364 def get_comp_locale_min_euros(self
):
365 return (float)(self
.comp_locale_min
) * self
.get_taux_comparaison()
367 def get_comp_ong_min_euros(self
):
368 return (float)(self
.comp_ong_min
) * self
.get_taux_comparaison()
370 def get_comp_autre_min_euros(self
):
371 return (float)(self
.comp_autre_min
) * self
.get_taux_comparaison()
373 def get_comp_universite_max_euros(self
):
374 return (float)(self
.comp_universite_max
) * self
.get_taux_comparaison()
376 def get_comp_fonctionpub_max_euros(self
):
377 return (float)(self
.comp_fonctionpub_max
) * self
.get_taux_comparaison()
379 def get_comp_locale_max_euros(self
):
380 return (float)(self
.comp_locale_max
) * self
.get_taux_comparaison()
382 def get_comp_ong_max_euros(self
):
383 return (float)(self
.comp_ong_max
) * self
.get_taux_comparaison()
385 def get_comp_autre_max_euros(self
):
386 return (float)(self
.comp_autre_max
) * self
.get_taux_comparaison()
388 def __unicode__(self
):
390 Cette fonction est consommatrice SQL car elle cherche les dossiers
391 qui ont été liés à celui-ci.
401 return u
'%s - %s (%s)' % data
403 reversion
.register(Poste
, format
='xml', follow
=[
404 'dae_financements', 'dae_pieces', 'dae_comparaisons_internes'
407 POSTE_FINANCEMENT_CHOICES
= (
408 ('A', 'A - Frais de personnel'),
409 ('B', 'B - Projet(s)-Titre(s)'),
414 class PosteFinancement(rh
.PosteFinancement_
):
415 poste
= models
.ForeignKey(
416 Poste
, db_column
='poste', related_name
='dae_financements'
419 reversion
.register(PosteFinancement
, format
='xml')
422 class PostePiece(rh
.PostePiece_
):
423 poste
= models
.ForeignKey(
424 Poste
, db_column
='poste', related_name
='dae_pieces'
427 reversion
.register(PostePiece
, format
='xml')
430 class PosteComparaison(rh
.PosteComparaison_
):
431 poste
= models
.ForeignKey(
432 Poste
, related_name
='dae_comparaisons_internes'
434 statut
= models
.ForeignKey(
435 rh
.Statut
, related_name
='+', verbose_name
=u
'Statut', null
=True,
438 classement
= models
.ForeignKey(
439 rh
.Classement
, related_name
='+', verbose_name
=u
'Classement',
440 null
=True, blank
=True
443 reversion
.register(PosteComparaison
, format
='xml')
446 class PosteComparaisonRemuneration(rh
.Remuneration_
):
447 poste_comparaison
= models
.ForeignKey(
448 PosteComparaison
, related_name
='poste_comparaison_remunerations'
451 reversion
.register(PosteComparaisonRemuneration
, format
='xml')
456 # TODO : migration pour m -> M, f -> F
464 class Employe(models
.Model
):
467 id_rh
= models
.ForeignKey(rh
.Employe
, null
=True, related_name
='+',
468 verbose_name
=u
'Employé')
469 nom
= models
.CharField(max_length
=255)
470 prenom
= models
.CharField(max_length
=255, verbose_name
=u
'Prénom')
471 genre
= models
.CharField(max_length
=1, choices
=GENRE_CHOICES
)
473 def __unicode__(self
):
474 return u
'%s %s' % (self
.prenom
, self
.nom
.upper())
478 Retourne l'employé RH associé à cet employé DAE.
482 def importer_dans_rh(self
):
484 Importe l'employé DAE dans un employé RH existant ou nouveau.
486 employe_rh
= self
.dans_rh() or rh
.Employe
.objects
.create(
491 self
.id_rh
= employe_rh
495 reversion
.register(Employe
, format
='xml')
500 STATUT_RESIDENCE_CHOICES
= (
502 ('expat', 'Expatrié'),
505 class Dossier(DossierWorkflow
, rh
.Dossier_
):
506 poste
= models
.ForeignKey(
507 'Poste', db_column
='poste', related_name
='dae_dossiers'
509 employe
= models
.ForeignKey(
510 'Employe', db_column
='employe',
511 related_name
='rh_dossiers', verbose_name
=u
"Employé"
513 organisme_bstg_autre
= models
.CharField(max_length
=255,
514 verbose_name
=u
"Autre organisme",
515 help_text
="indiquer l'organisme ici s'il n'est pas dans la liste",
519 # Lien avec le dossier
520 dossier_rh
= models
.ForeignKey(
521 rh
.Dossier
, related_name
='dossiers_dae', null
=True, blank
=True
524 # Données antérieures de l'employé
525 statut_anterieur
= models
.ForeignKey(
526 rh
.Statut
, related_name
='+', null
=True, blank
=True,
527 verbose_name
=u
'Statut antérieur')
528 classement_anterieur
= models
.ForeignKey(
529 rh
.Classement
, related_name
='+', null
=True, blank
=True,
530 verbose_name
=u
'Classement précédent')
531 salaire_anterieur
= models
.DecimalField(
532 max_digits
=12, decimal_places
=2, null
=True, default
=None,
533 blank
=True, verbose_name
=u
'Salaire précédent')
534 devise_anterieur
= models
.ForeignKey(
535 rh
.Devise
, related_name
='+', null
=True, blank
=True
537 type_contrat_anterieur
= models
.ForeignKey(
538 rh
.TypeContrat
, related_name
='+', null
=True, blank
=True,
539 verbose_name
=u
'Type contrat antérieur'
542 # Données du titulaire précédent
543 employe_anterieur
= models
.ForeignKey(
544 rh
.Employe
, related_name
='+', null
=True, blank
=True,
545 verbose_name
=u
'Employé précédent')
546 statut_titulaire_anterieur
= models
.ForeignKey(
547 rh
.Statut
, related_name
='+', null
=True, blank
=True,
548 verbose_name
=u
'Statut titulaire précédent')
549 classement_titulaire_anterieur
= models
.ForeignKey(
550 rh
.Classement
, related_name
='+', null
=True, blank
=True,
551 verbose_name
=u
'Classement titulaire précédent')
552 salaire_titulaire_anterieur
= models
.DecimalField(
553 max_digits
=12, decimal_places
=2, default
=None, null
=True,
554 blank
=True, verbose_name
=u
'Salaire titulaire précédent')
555 devise_titulaire_anterieur
= models
.ForeignKey(
556 rh
.Devise
, related_name
='+', null
=True, blank
=True
560 salaire
= models
.DecimalField(max_digits
=13, decimal_places
=2,
561 verbose_name
=u
'Salaire de base',
562 null
=True, default
=None)
563 devise
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
566 type_contrat
= models
.ForeignKey(rh
.TypeContrat
, related_name
='+')
567 contrat_date_debut
= models
.DateField(help_text
=HELP_TEXT_DATE
)
568 contrat_date_fin
= models
.DateField(null
=True, blank
=True,
569 help_text
=HELP_TEXT_DATE
)
572 justif_nouveau_statut_label
= u
'Justifier le statut que ce type ' \
573 u
'de poste nécessite (national, expatrié, màd ou détachement)'
574 justif_nouveau_statut
= models
.TextField(
575 verbose_name
=justif_nouveau_statut_label
, null
=True, blank
=True
577 justif_nouveau_tmp_remplacement_label
= u
"Si l'employé effectue un " \
578 u
"remplacement temporaire, préciser"
579 justif_nouveau_tmp_remplacement
= models
.TextField(
580 verbose_name
=justif_nouveau_tmp_remplacement_label
, null
=True,
583 justif_nouveau_salaire_label
= u
"Si le salaire de l'employé ne " \
584 u
"correspond pas au classement du poste ou est différent " \
585 u
"du salaire antérieur, justifier "
586 justif_nouveau_salaire
= models
.TextField(
587 verbose_name
=justif_nouveau_salaire_label
, null
=True, blank
=True
589 justif_nouveau_commentaire_label
= u
"COMMENTAIRES ADDITIONNELS"
590 justif_nouveau_commentaire
= models
.TextField(
591 verbose_name
=justif_nouveau_commentaire_label
, null
=True, blank
=True
593 justif_rempl_type_contrat_label
= \
594 u
"Changement de type de contrat, ex : d'un CDD en CDI"
595 justif_rempl_type_contrat
= models
.TextField(
596 verbose_name
=justif_rempl_type_contrat_label
, null
=True, blank
=True
598 justif_rempl_statut_employe_label
= \
599 u
"Si le statut de l'employé a été modifié pour ce poste ; " \
600 u
"ex : national, expatrié, màd, détachement ? Si oui, justifier"
601 justif_rempl_statut_employe
= models
.TextField(
602 verbose_name
=justif_rempl_statut_employe_label
, null
=True, blank
=True
604 justif_rempl_evaluation_label
= \
605 u
"L'évaluation de l'employé est-elle favorable? Préciser"
606 justif_rempl_evaluation
= models
.TextField(
607 verbose_name
=justif_rempl_evaluation_label
, null
=True, blank
=True
609 justif_rempl_salaire_label
= \
610 u
"Si le salaire de l'employé est modifié et/ou ne correspond " \
611 u
"pas à son classement, justifier"
612 justif_rempl_salaire
= models
.TextField(
613 verbose_name
=justif_rempl_salaire_label
, null
=True, blank
=True
615 justif_rempl_commentaire_label
= u
"COMMENTAIRES ADDITIONNELS"
616 justif_rempl_commentaire
= models
.TextField(
617 verbose_name
=justif_rempl_commentaire_label
, null
=True, blank
=True
621 dae_numerisee
= models
.FileField(
622 upload_to
='dae/dae_numerisee', storage
=UPLOAD_STORAGE
, blank
=True,
623 null
=True, verbose_name
="DAE numérisée"
627 objects
= DossierManager()
629 def __init__(self
, *args
, **kwargs
):
630 # Bouchon pour créer une date fictive necessaire pour valider un
631 # dossier à cause de l'héritage
632 super(rh
.Dossier_
, self
).__init__(*args
, **kwargs
)
633 super(DossierWorkflow
, self
).__init__(*args
, **kwargs
)
635 self
.date_debut
= datetime
.datetime
.today()
637 def __unicode__(self
):
638 return u
'[%s] %s - %s' % (
639 self
.poste
.implantation
, self
.poste
.nom
, self
.employe
644 Retourne le dossier associé dans le système RH ou ``None`` s'il n'y
648 return self
.dossier_rh
650 poste_rh
= self
.poste
.dans_rh()
653 employe_rh
= self
.employe
.dans_rh()
654 if employe_rh
is None:
657 return rh
.Dossier
.objects
.get(
658 Q(date_debut
=None) |
Q(date_debut__lte
=today
),
659 Q(date_fin
=None) |
Q(date_fin__gte
=today
),
663 except rh
.Dossier
.DoesNotExist
:
666 def importer_dans_rh(self
):
668 Importe les données du dossier DAE dans un dossier RH existant ou
671 poste_rh
= self
.poste
.importer_dans_rh()
672 employe_rh
= self
.employe
.importer_dans_rh()
673 dossier_rh
= self
.dans_rh() or \
674 rh
.Dossier(poste
=poste_rh
, employe
=employe_rh
)
676 dossier_rh
.statut
= self
.statut
677 dossier_rh
.organisme_bstg
= self
.organisme_bstg
678 dossier_rh
.remplacement
= self
.remplacement
679 dossier_rh
.remplacement_de
= self
.remplacement_de
680 dossier_rh
.statut_residence
= self
.statut_residence
681 dossier_rh
.classement
= self
.classement
682 dossier_rh
.regime_travail
= self
.regime_travail
683 dossier_rh
.est_cadre
= self
.est_cadre
684 dossier_rh
.compte_compta
= self
.compte_compta
685 dossier_rh
.compte_courriel
= self
.compte_courriel
686 dossier_rh
.regime_travail_nb_heure_semaine
= \
687 self
.regime_travail_nb_heure_semaine
688 dossier_rh
.date_debut
= self
.contrat_date_debut
691 rh
.DossierComparaison
.objects
.filter(dossier
=dossier_rh
).delete()
692 for comp
in self
.dae_comparaisons
.all():
693 dossier_rh
.rh_comparaisons
.create(
694 implantation
=comp
.implantation
,
696 personne
=comp
.personne
,
697 montant
=comp
.montant
,
701 for contrat
in self
.dae_contrats
.all():
702 contrat_rh
= dossier_rh
.rh_contrats
.create(
703 type_contrat
=self
.type_contrat
,
704 date_debut
=self
.contrat_date_debut
,
705 date_fin
=self
.contrat_date_fin
,
707 contrat_rh
.fichier
.save(
708 os
.path
.basename(contrat
.fichier
.name
), contrat
.fichier
711 for piece
in self
.dae_dossierpieces
.all():
712 piece_rh
= dossier_rh
.rh_dossierpieces
.create(
715 if not settings
.DEBUG
:
716 piece_rh
.fichier
.save(
717 os
.path
.basename(piece
.fichier
.name
), piece
.fichier
720 if self
.dae_numerisee
:
721 dae_numerisee_rh
= dossier_rh
.rh_dossierpieces
.create(
724 if not settings
.DEBUG
:
725 dae_numerisee_rh
.fichier
.save(
726 os
.path
.basename(self
.dae_numerisee
.name
),
730 # Fermer les rémunérations qui commencent avant le début du contrat
731 dossier_rh
.rh_remunerations
.filter(
732 Q(date_debut
=None) |
Q(date_debut__lt
=self
.contrat_date_debut
),
733 Q(date_fin
=None) |
Q(date_fin__gte
=self
.contrat_date_debut
)
734 ).update(date_fin
=self
.contrat_date_debut
- timedelta(1))
736 # Effacer les rémunérations qui commencent à la date du contrat
737 dossier_rh
.rh_remunerations \
738 .filter(date_debut
=self
.contrat_date_debut
) \
741 for remun
in self
.dae_remunerations
.all():
742 dossier_rh
.rh_remunerations
.get_or_create(
744 type_revalorisation
=remun
.type_revalorisation
,
745 montant
=remun
.montant
,
747 commentaire
=remun
.commentaire
,
748 date_debut
=self
.contrat_date_debut
,
749 date_fin
=self
.contrat_date_fin
752 # Enregistrer le lien avec le dossier RH
753 self
.dossier_rh
= dossier_rh
758 def get_dossier_precedent_titulaire(self
):
760 rh_poste
= self
.poste
.id_rh
761 except rh
.Poste
.DoesNotExist
:
765 precedent_employe
= self
.employe_anterieur
766 except rh
.Employe
.DoesNotExist
:
769 qs
= rh
.Dossier
.objects
.filter(
771 employe
=precedent_employe
,
773 '-principal', 'date_fin')
778 # Retourne en le premier du queryset si la date de fin est None
779 # Sinon, retourne le plus récent selon la date de fin.
781 if first
.date_fin
== None:
784 return qs
.order_by('-principal', '-date_fin')[0]
786 def get_salaire_anterieur_euros(self
):
787 if self
.devise_anterieur
is None:
790 taux
= self
.taux_devise(self
.devise_anterieur
)
795 return int(round(float(self
.salaire_anterieur
) * float(taux
), 2))
797 def get_salaire_titulaire_anterieur_euros(self
):
798 if self
.devise_titulaire_anterieur
is None:
801 taux
= self
.taux_devise(self
.devise_titulaire_anterieur
)
807 float(self
.salaire_titulaire_anterieur
) * float(taux
), 2
811 return self
.etat
in (DOSSIER_ETAT_REGION_FINALISATION
,
812 DOSSIER_ETAT_DRH_FINALISATION
,
813 DOSSIER_ETAT_FINALISE
)
815 reversion
.register(Dossier
, format
='xml', follow
=[
816 'dae_dossierpieces', 'dae_comparaisons', 'dae_remunerations',
821 class DossierPiece(rh
.DossierPiece_
):
823 Documents relatifs au Dossier (à l'occupation de ce poste par employé).
824 Ex.: Lettre de motivation.
826 dossier
= models
.ForeignKey(
827 Dossier
, db_column
='dossier', related_name
='dae_dossierpieces'
830 reversion
.register(DossierPiece
, format
='xml')
833 class DossierComparaison(rh
.DossierComparaison_
):
835 Photo d'une comparaison salariale au moment de l'embauche.
837 dossier
= models
.ForeignKey(
838 Dossier
, related_name
='dae_comparaisons'
840 statut
= models
.ForeignKey(
841 rh
.Statut
, related_name
='+', verbose_name
='Statut', null
=True,
844 classement
= models
.ForeignKey(
845 rh
.Classement
, related_name
='+', verbose_name
='Classement',
846 null
=True, blank
=True
849 reversion
.register(DossierComparaison
, format
='xml')
851 class DossierComparaisonRemuneration(rh
.Remuneration_
):
852 dossier_comparaison
= models
.ForeignKey(
853 DossierComparaison
, related_name
='dossier_comparaison_remunerations'
856 reversion
.register(DossierComparaisonRemuneration
, format
='xml')
860 class Remuneration(rh
.Remuneration_
):
861 dossier
= models
.ForeignKey(
862 Dossier
, db_column
='dossier', related_name
='dae_remunerations'
865 reversion
.register(Remuneration
, format
='xml')
870 class Contrat(rh
.Contrat_
):
871 dossier
= models
.ForeignKey(
872 Dossier
, db_column
='dossier', related_name
='dae_contrats'
875 reversion
.register(Contrat
, format
='xml')
878 class ProxyDossierStatut(Dossier
):
881 verbose_name
= "Statut du dossier"
882 verbose_name_plural
= "Statut des dossiers"
885 class ProxyPosteStatut(Poste
):
888 verbose_name
= "Statut du poste"
889 verbose_name_plural
= "Statut des postes"
892 class ProxyImplantation(ref
.Implantation
):
894 # Ajout d'un manager pour ref.Implantation
895 dae_manager
= ImplantationManager()