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 objects
= PosteManager()
83 def traitement_min_cad(self
):
84 return ((self
.salaire_min
or Decimal('0')) +
85 (self
.indemn_fct_min
or Decimal('0')))
88 def traitement_max_cad(self
):
89 return ((self
.salaire_max
or Decimal('0')) +
90 (self
.indemn_fct_max
or Decimal('0')))
94 Les vues sont montées selon une clef spéciale
95 pour identifier la provenance du poste.
96 Cette méthode fournit un moyen de reconstruire cette clef
97 afin de générer les URLs.
99 return "dae-%s" % self
.id
100 key
= property(_get_key
)
102 def get_dossiers(self
):
104 Liste tous les anciens dossiers liés à ce poste.
105 (Le nom de la relation sur le rh.Poste est mal choisi
106 poste1 au lieu de dossier1)
107 Note1 : seulement le dosssier principal fait l'objet de la recherche.
108 Note2 : les dossiers sont retournés du plus récent au plus vieux.
109 (Ce test est fait en fonction du id,
110 car les dates de création sont absentes de rh v1).
112 if self
.id_rh
is None:
114 return self
.id_rh
.rh_dossiers
.all()
118 Retourne le poste RH s'il existe.
122 def importer_dans_rh(self
):
124 Importe le poste DAE dans un poste RH existant ou nouveau.
126 dans_rh
= self
.dans_rh()
127 poste_rh
= dans_rh
or rh
.Poste()
128 poste_rh
.nom
= self
.nom
129 poste_rh
.implantation
= self
.implantation
130 poste_rh
.type_poste
= self
.type_poste
131 poste_rh
.service
= self
.service
132 poste_rh
.responsable
= self
.responsable
133 poste_rh
.regime_travail
= self
.regime_travail
134 poste_rh
.regime_travail_nb_heure_semaine
= \
135 self
.regime_travail_nb_heure_semaine
136 poste_rh
.local
= self
.local
137 poste_rh
.expatrie
= self
.expatrie
138 poste_rh
.mise_a_disposition
= self
.mise_a_disposition
139 poste_rh
.appel
= self
.appel
140 poste_rh
.classement_min
= self
.classement_min
141 poste_rh
.classement_max
= self
.classement_max
142 poste_rh
.valeur_point_min
= self
.valeur_point_min
143 poste_rh
.valeur_point_max
= self
.valeur_point_max
144 poste_rh
.devise_min
= self
.devise_min
145 poste_rh
.devise_max
= self
.devise_max
146 poste_rh
.salaire_min
= self
.salaire_min
147 poste_rh
.salaire_max
= self
.salaire_max
148 poste_rh
.indemn_min
= self
.indemn_fct_min
149 poste_rh
.indemn_max
= self
.indemn_fct_max
150 poste_rh
.autre_min
= \
151 self
.indemn_expat_min
+ self
.charges_patronales_min
+ \
153 poste_rh
.autre_max
= \
154 self
.indemn_expat_max
+ self
.charges_patronales_max
+ \
156 poste_rh
.devise_comparaison
= self
.devise_comparaison
157 poste_rh
.comp_locale_min
= self
.comp_locale_min
158 poste_rh
.comp_locale_max
= self
.comp_locale_max
159 poste_rh
.comp_universite_min
= self
.comp_universite_min
160 poste_rh
.comp_universite_max
= self
.comp_universite_max
161 poste_rh
.comp_fonctionpub_min
= self
.comp_fonctionpub_min
162 poste_rh
.comp_fonctionpub_max
= self
.comp_fonctionpub_max
163 poste_rh
.comp_ong_min
= self
.comp_ong_min
164 poste_rh
.comp_ong_max
= self
.comp_ong_max
165 poste_rh
.comp_autre_min
= self
.comp_autre_min
166 poste_rh
.comp_autre_max
= self
.comp_autre_max
167 poste_rh
.justification
= self
.justification
169 poste_rh
.date_debut
= self
.date_debut
170 poste_rh
.date_fin
= self
.date_fin
173 for piece
in self
.dae_pieces
.all():
174 piece_rh
= poste_rh
.rh_pieces
.create(
178 if not settings
.DEBUG
:
179 piece_rh
.fichier
.save(
180 os
.path
.basename(piece
.fichier
.name
), piece
.fichier
183 rh
.PosteComparaison
.objects
.filter(poste
=poste_rh
).delete()
184 for comp
in self
.dae_comparaisons_internes
.all():
185 poste_rh
.rh_comparaisons_internes
.create(
186 implantation
=comp
.implantation
,
188 montant
=comp
.montant
,
192 rh
.PosteFinancement
.objects
.filter(poste
=poste_rh
).delete()
193 for financement
in self
.dae_financements
.all():
194 poste_rh
.rh_financements
.create(
195 type=financement
.type,
196 pourcentage
=financement
.pourcentage
,
197 commentaire
=financement
.commentaire
200 self
.id_rh
= poste_rh
204 def get_employe(self
):
206 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
208 dossiers
= self
.get_dossiers()
209 if len(dossiers
) > 0:
210 return dossiers
[0].employe
214 def get_default_devise(self
):
215 """Récupère la devise par défaut en fonction de l'implantation
219 implantation_devise
= rh
.TauxChange
.objects \
220 .filter(implantation
=self
.implantation
)[0].devise
222 implantation_devise
= 5 # EUR
223 return implantation_devise
225 #####################
226 # Classement de poste
227 #####################
229 def get_couts_minimum(self
):
230 return self
.salaire_min
+ self
.indemn_expat_min
+ \
231 self
.indemn_fct_min
+ self
.charges_patronales_min
+ \
234 def get_salaire_minimum(self
):
235 return self
.get_couts_minimum() - self
.charges_patronales_min
237 def get_taux_minimum(self
):
238 if self
.devise_min
.code
== 'EUR':
240 liste_taux
= self
.devise_min
.tauxchange_set
.order_by('-annee')
241 if len(liste_taux
) == 0:
242 raise DeviseException(
243 u
"La devise %s n'a pas de taux pour l'implantation %s" %
244 (self
.devise_min
, self
.implantation
))
246 return liste_taux
[0].taux
248 def get_couts_minimum_euros(self
):
249 return float(self
.get_couts_minimum()) * self
.get_taux_minimum()
251 def get_salaire_minimum_euros(self
):
252 return float(self
.get_salaire_minimum()) * self
.get_taux_minimum()
254 def get_couts_maximum(self
):
255 return self
.salaire_max
+ self
.indemn_expat_max
+ \
256 self
.indemn_fct_max
+ self
.charges_patronales_max
+ \
259 def get_salaire_maximum(self
):
260 return self
.get_couts_maximum() - self
.charges_patronales_max
262 def get_taux_maximum(self
):
263 if self
.devise_max
.code
== 'EUR':
265 liste_taux
= self
.devise_max
.tauxchange_set
.order_by('-annee')
266 if len(liste_taux
) == 0:
267 raise DeviseException(
268 u
"La devise %s n'a pas de taux pour l'implantation %s" %
269 (self
.devise_max
, self
.implantation
)
272 return liste_taux
[0].taux
274 def get_couts_maximum_euros(self
):
275 return float(self
.get_couts_maximum()) * self
.get_taux_maximum()
277 def get_salaire_maximum_euros(self
):
278 return float(self
.get_salaire_maximum()) * self
.get_taux_maximum()
280 def show_taux_minimum(self
):
282 return self
.get_taux_minimum()
283 except DeviseException
, e
:
286 def show_couts_minimum_euros(self
):
288 return self
.get_couts_minimum_euros()
289 except DeviseException
, e
:
292 def show_salaire_minimum_euros(self
):
294 return self
.get_salaire_minimum_euros()
295 except DeviseException
, e
:
298 def show_taux_maximum(self
):
300 return self
.get_taux_maximum()
301 except DeviseException
, e
:
304 def show_couts_maximum_euros(self
):
306 return self
.get_couts_maximum_euros()
307 except DeviseException
, e
:
310 def show_salaire_maximum_euros(self
):
312 return self
.get_salaire_maximum_euros()
313 except DeviseException
, e
:
316 # Comparaison de poste
317 def est_comparable(self
):
319 Si on a au moins une valeur de saisie dans les comparaisons, alors
320 le poste est comparable.
322 if self
.comp_universite_min
is None and \
323 self
.comp_fonctionpub_min
is None and \
324 self
.comp_locale_min
is None and \
325 self
.comp_ong_min
is None and \
326 self
.comp_autre_min
is None and \
327 self
.comp_universite_max
is None and \
328 self
.comp_fonctionpub_max
is None and \
329 self
.comp_locale_max
is None and \
330 self
.comp_ong_max
is None and \
331 self
.comp_autre_max
is None:
336 def get_taux_comparaison(self
):
338 return rh
.TauxChange
.objects \
339 .filter(devise
=self
.devise_comparaison
)[0].taux
343 def get_comp_universite_min_euros(self
):
344 return (float)(self
.comp_universite_min
) * self
.get_taux_comparaison()
346 def get_comp_fonctionpub_min_euros(self
):
347 return (float)(self
.comp_fonctionpub_min
) * self
.get_taux_comparaison()
349 def get_comp_locale_min_euros(self
):
350 return (float)(self
.comp_locale_min
) * self
.get_taux_comparaison()
352 def get_comp_ong_min_euros(self
):
353 return (float)(self
.comp_ong_min
) * self
.get_taux_comparaison()
355 def get_comp_autre_min_euros(self
):
356 return (float)(self
.comp_autre_min
) * self
.get_taux_comparaison()
358 def get_comp_universite_max_euros(self
):
359 return (float)(self
.comp_universite_max
) * self
.get_taux_comparaison()
361 def get_comp_fonctionpub_max_euros(self
):
362 return (float)(self
.comp_fonctionpub_max
) * self
.get_taux_comparaison()
364 def get_comp_locale_max_euros(self
):
365 return (float)(self
.comp_locale_max
) * self
.get_taux_comparaison()
367 def get_comp_ong_max_euros(self
):
368 return (float)(self
.comp_ong_max
) * self
.get_taux_comparaison()
370 def get_comp_autre_max_euros(self
):
371 return (float)(self
.comp_autre_max
) * self
.get_taux_comparaison()
373 def __unicode__(self
):
375 Cette fonction est consommatrice SQL car elle cherche les dossiers
376 qui ont été liés à celui-ci.
386 return u
'%s - %s (%s)' % data
388 reversion
.register(Poste
, format
='xml', follow
=[
389 'dae_financements', 'dae_pieces', 'dae_comparaisons_internes'
392 POSTE_FINANCEMENT_CHOICES
= (
393 ('A', 'A - Frais de personnel'),
394 ('B', 'B - Projet(s)-Titre(s)'),
399 class PosteFinancement(rh
.PosteFinancement_
):
400 poste
= models
.ForeignKey(
401 Poste
, db_column
='poste', related_name
='dae_financements'
404 reversion
.register(PosteFinancement
, format
='xml')
407 class PostePiece(rh
.PostePiece_
):
408 poste
= models
.ForeignKey(
409 Poste
, db_column
='poste', related_name
='dae_pieces'
412 reversion
.register(PostePiece
, format
='xml')
415 class PosteComparaison(rh
.PosteComparaison_
):
416 poste
= models
.ForeignKey(
417 Poste
, related_name
='dae_comparaisons_internes'
419 statut
= models
.ForeignKey(
420 rh
.Statut
, related_name
='+', verbose_name
=u
'Statut', null
=True,
423 classement
= models
.ForeignKey(
424 rh
.Classement
, related_name
='+', verbose_name
=u
'Classement',
425 null
=True, blank
=True
428 reversion
.register(PosteComparaison
, format
='xml')
431 class PosteComparaisonRemuneration(rh
.Remuneration_
):
432 poste_comparaison
= models
.ForeignKey(
433 PosteComparaison
, related_name
='poste_comparaison_remunerations'
436 reversion
.register(PosteComparaisonRemuneration
, format
='xml')
441 # TODO : migration pour m -> M, f -> F
449 class Employe(models
.Model
):
452 id_rh
= models
.ForeignKey(rh
.Employe
, null
=True, related_name
='+',
453 verbose_name
=u
'Employé')
454 nom
= models
.CharField(max_length
=255)
455 prenom
= models
.CharField(max_length
=255, verbose_name
=u
'Prénom')
456 genre
= models
.CharField(max_length
=1, choices
=GENRE_CHOICES
)
458 def __unicode__(self
):
459 return u
'%s %s' % (self
.prenom
, self
.nom
.upper())
463 Retourne l'employé RH associé à cet employé DAE.
467 def importer_dans_rh(self
):
469 Importe l'employé DAE dans un employé RH existant ou nouveau.
471 employe_rh
= self
.dans_rh() or rh
.Employe
.objects
.create(
476 self
.id_rh
= employe_rh
480 reversion
.register(Employe
, format
='xml')
485 STATUT_RESIDENCE_CHOICES
= (
487 ('expat', 'Expatrié'),
490 class Dossier(DossierWorkflow
, rh
.Dossier_
):
491 poste
= models
.ForeignKey(
492 'Poste', db_column
='poste', related_name
='dae_dossiers'
494 employe
= models
.ForeignKey(
495 'Employe', db_column
='employe',
496 related_name
='rh_dossiers', verbose_name
=u
"Employé"
498 organisme_bstg_autre
= models
.CharField(max_length
=255,
499 verbose_name
=u
"Autre organisme",
500 help_text
="indiquer l'organisme ici s'il n'est pas dans la liste",
504 # Lien avec le dossier
505 dossier_rh
= models
.ForeignKey(
506 rh
.Dossier
, related_name
='dossiers_dae', null
=True, blank
=True
509 # Données antérieures de l'employé
510 statut_anterieur
= models
.ForeignKey(
511 rh
.Statut
, related_name
='+', null
=True, blank
=True,
512 verbose_name
=u
'Statut antérieur')
513 classement_anterieur
= models
.ForeignKey(
514 rh
.Classement
, related_name
='+', null
=True, blank
=True,
515 verbose_name
=u
'Classement précédent')
516 salaire_anterieur
= models
.DecimalField(
517 max_digits
=12, decimal_places
=2, null
=True, default
=None,
518 blank
=True, verbose_name
=u
'Salaire précédent')
519 devise_anterieur
= models
.ForeignKey(
520 rh
.Devise
, related_name
='+', null
=True, blank
=True
522 type_contrat_anterieur
= models
.ForeignKey(
523 rh
.TypeContrat
, related_name
='+', null
=True, blank
=True,
524 verbose_name
=u
'Type contrat antérieur'
527 # Données du titulaire précédent
528 employe_anterieur
= models
.ForeignKey(
529 rh
.Employe
, related_name
='+', null
=True, blank
=True,
530 verbose_name
=u
'Employé précédent')
531 statut_titulaire_anterieur
= models
.ForeignKey(
532 rh
.Statut
, related_name
='+', null
=True, blank
=True,
533 verbose_name
=u
'Statut titulaire précédent')
534 classement_titulaire_anterieur
= models
.ForeignKey(
535 rh
.Classement
, related_name
='+', null
=True, blank
=True,
536 verbose_name
=u
'Classement titulaire précédent')
537 salaire_titulaire_anterieur
= models
.DecimalField(
538 max_digits
=12, decimal_places
=2, default
=None, null
=True,
539 blank
=True, verbose_name
=u
'Salaire titulaire précédent')
540 devise_titulaire_anterieur
= models
.ForeignKey(
541 rh
.Devise
, related_name
='+', null
=True, blank
=True
545 salaire
= models
.DecimalField(max_digits
=13, decimal_places
=2,
546 verbose_name
=u
'Salaire de base',
547 null
=True, default
=None)
548 devise
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
551 type_contrat
= models
.ForeignKey(rh
.TypeContrat
, related_name
='+')
552 contrat_date_debut
= models
.DateField(help_text
=HELP_TEXT_DATE
)
553 contrat_date_fin
= models
.DateField(null
=True, blank
=True,
554 help_text
=HELP_TEXT_DATE
)
557 justif_nouveau_statut_label
= u
'Justifier le statut que ce type ' \
558 u
'de poste nécessite (national, expatrié, màd ou détachement)'
559 justif_nouveau_statut
= models
.TextField(
560 verbose_name
=justif_nouveau_statut_label
, null
=True, blank
=True
562 justif_nouveau_tmp_remplacement_label
= u
"Si l'employé effectue un " \
563 u
"remplacement temporaire, préciser"
564 justif_nouveau_tmp_remplacement
= models
.TextField(
565 verbose_name
=justif_nouveau_tmp_remplacement_label
, null
=True,
568 justif_nouveau_salaire_label
= u
"Si le salaire de l'employé ne " \
569 u
"correspond pas au classement du poste ou est différent " \
570 u
"du salaire antérieur, justifier "
571 justif_nouveau_salaire
= models
.TextField(
572 verbose_name
=justif_nouveau_salaire_label
, null
=True, blank
=True
574 justif_nouveau_commentaire_label
= u
"COMMENTAIRES ADDITIONNELS"
575 justif_nouveau_commentaire
= models
.TextField(
576 verbose_name
=justif_nouveau_commentaire_label
, null
=True, blank
=True
578 justif_rempl_type_contrat_label
= \
579 u
"Changement de type de contrat, ex : d'un CDD en CDI"
580 justif_rempl_type_contrat
= models
.TextField(
581 verbose_name
=justif_rempl_type_contrat_label
, null
=True, blank
=True
583 justif_rempl_statut_employe_label
= \
584 u
"Si le statut de l'employé a été modifié pour ce poste ; " \
585 u
"ex : national, expatrié, màd, détachement ? Si oui, justifier"
586 justif_rempl_statut_employe
= models
.TextField(
587 verbose_name
=justif_rempl_statut_employe_label
, null
=True, blank
=True
589 justif_rempl_evaluation_label
= \
590 u
"L'évaluation de l'employé est-elle favorable? Préciser"
591 justif_rempl_evaluation
= models
.TextField(
592 verbose_name
=justif_rempl_evaluation_label
, null
=True, blank
=True
594 justif_rempl_salaire_label
= \
595 u
"Si le salaire de l'employé est modifié et/ou ne correspond " \
596 u
"pas à son classement, justifier"
597 justif_rempl_salaire
= models
.TextField(
598 verbose_name
=justif_rempl_salaire_label
, null
=True, blank
=True
600 justif_rempl_commentaire_label
= u
"COMMENTAIRES ADDITIONNELS"
601 justif_rempl_commentaire
= models
.TextField(
602 verbose_name
=justif_rempl_commentaire_label
, null
=True, blank
=True
606 dae_numerisee
= models
.FileField(
607 upload_to
='dae/dae_numerisee', storage
=UPLOAD_STORAGE
, blank
=True,
608 null
=True, verbose_name
="DAE numérisée"
612 objects
= DossierManager()
614 def __init__(self
, *args
, **kwargs
):
615 # Bouchon pour créer une date fictive necessaire pour valider un
616 # dossier à cause de l'héritage
617 super(rh
.Dossier_
, self
).__init__(*args
, **kwargs
)
618 super(DossierWorkflow
, self
).__init__(*args
, **kwargs
)
620 self
.date_debut
= datetime
.datetime
.today()
622 def __unicode__(self
):
623 return u
'[%s] %s - %s' % (
624 self
.poste
.implantation
, self
.poste
.nom
, self
.employe
629 Retourne le dossier associé dans le système RH ou ``None`` s'il n'y
633 return self
.dossier_rh
635 poste_rh
= self
.poste
.dans_rh()
638 employe_rh
= self
.employe
.dans_rh()
639 if employe_rh
is None:
642 return rh
.Dossier
.objects
.get(
643 Q(date_debut
=None) |
Q(date_debut__lte
=today
),
644 Q(date_fin
=None) |
Q(date_fin__gte
=today
),
648 except rh
.Dossier
.DoesNotExist
:
651 def importer_dans_rh(self
):
653 Importe les données du dossier DAE dans un dossier RH existant ou
656 poste_rh
= self
.poste
.importer_dans_rh()
657 employe_rh
= self
.employe
.importer_dans_rh()
658 dossier_rh
= self
.dans_rh() or \
659 rh
.Dossier(poste
=poste_rh
, employe
=employe_rh
)
661 dossier_rh
.statut
= self
.statut
662 dossier_rh
.organisme_bstg
= self
.organisme_bstg
663 dossier_rh
.remplacement
= self
.remplacement
664 dossier_rh
.remplacement_de
= self
.remplacement_de
665 dossier_rh
.statut_residence
= self
.statut_residence
666 dossier_rh
.classement
= self
.classement
667 dossier_rh
.regime_travail
= self
.regime_travail
668 dossier_rh
.est_cadre
= self
.est_cadre
669 dossier_rh
.compte_compta
= self
.compte_compta
670 dossier_rh
.compte_courriel
= self
.compte_courriel
671 dossier_rh
.regime_travail_nb_heure_semaine
= \
672 self
.regime_travail_nb_heure_semaine
673 dossier_rh
.date_debut
= self
.contrat_date_debut
676 rh
.DossierComparaison
.objects
.filter(dossier
=dossier_rh
).delete()
677 for comp
in self
.dae_comparaisons
.all():
678 dossier_rh
.rh_comparaisons
.create(
679 implantation
=comp
.implantation
,
681 personne
=comp
.personne
,
682 montant
=comp
.montant
,
686 for contrat
in self
.dae_contrats
.all():
687 contrat_rh
= dossier_rh
.rh_contrats
.create(
688 type_contrat
=self
.type_contrat
,
689 date_debut
=self
.contrat_date_debut
,
690 date_fin
=self
.contrat_date_fin
,
692 contrat_rh
.fichier
.save(
693 os
.path
.basename(contrat
.fichier
.name
), contrat
.fichier
696 for piece
in self
.dae_dossierpieces
.all():
697 piece_rh
= dossier_rh
.rh_dossierpieces
.create(
700 if not settings
.DEBUG
:
701 piece_rh
.fichier
.save(
702 os
.path
.basename(piece
.fichier
.name
), piece
.fichier
705 if self
.dae_numerisee
:
706 dae_numerisee_rh
= dossier_rh
.rh_dossierpieces
.create(
709 if not settings
.DEBUG
:
710 dae_numerisee_rh
.fichier
.save(
711 os
.path
.basename(self
.dae_numerisee
.name
),
715 # Fermer les rémunérations qui commencent avant le début du contrat
716 dossier_rh
.rh_remunerations
.filter(
717 Q(date_debut
=None) |
Q(date_debut__lt
=self
.contrat_date_debut
),
718 Q(date_fin
=None) |
Q(date_fin__gte
=self
.contrat_date_debut
)
719 ).update(date_fin
=self
.contrat_date_debut
- timedelta(1))
721 # Effacer les rémunérations qui commencent à la date du contrat
722 dossier_rh
.rh_remunerations \
723 .filter(date_debut
=self
.contrat_date_debut
) \
726 for remun
in self
.dae_remunerations
.all():
727 dossier_rh
.rh_remunerations
.get_or_create(
729 type_revalorisation
=remun
.type_revalorisation
,
730 montant
=remun
.montant
,
732 commentaire
=remun
.commentaire
,
733 date_debut
=self
.contrat_date_debut
,
734 date_fin
=self
.contrat_date_fin
737 # Enregistrer le lien avec le dossier RH
738 self
.dossier_rh
= dossier_rh
743 def get_dossier_precedent_titulaire(self
):
745 rh_poste
= self
.poste
.id_rh
746 except rh
.Poste
.DoesNotExist
:
750 precedent_employe
= self
.employe_anterieur
751 except rh
.Employe
.DoesNotExist
:
754 qs
= rh
.Dossier
.objects
.filter(
756 employe
=precedent_employe
,
758 '-principal', 'date_fin')
763 # Retourne en le premier du queryset si la date de fin est None
764 # Sinon, retourne le plus récent selon la date de fin.
766 if first
.date_fin
== None:
769 return qs
.order_by('-principal', '-date_fin')[0]
771 def get_salaire_anterieur_euros(self
):
772 if self
.devise_anterieur
is None:
775 taux
= self
.taux_devise(self
.devise_anterieur
)
780 return int(round(float(self
.salaire_anterieur
) * float(taux
), 2))
782 def get_salaire_titulaire_anterieur_euros(self
):
783 if self
.devise_titulaire_anterieur
is None:
786 taux
= self
.taux_devise(self
.devise_titulaire_anterieur
)
792 float(self
.salaire_titulaire_anterieur
) * float(taux
), 2
796 return self
.etat
in (DOSSIER_ETAT_REGION_FINALISATION
,
797 DOSSIER_ETAT_DRH_FINALISATION
,
798 DOSSIER_ETAT_FINALISE
)
800 reversion
.register(Dossier
, format
='xml', follow
=[
801 'dae_dossierpieces', 'dae_comparaisons', 'dae_remunerations',
806 class DossierPiece(rh
.DossierPiece_
):
808 Documents relatifs au Dossier (à l'occupation de ce poste par employé).
809 Ex.: Lettre de motivation.
811 dossier
= models
.ForeignKey(
812 Dossier
, db_column
='dossier', related_name
='dae_dossierpieces'
815 reversion
.register(DossierPiece
, format
='xml')
818 class DossierComparaison(rh
.DossierComparaison_
):
820 Photo d'une comparaison salariale au moment de l'embauche.
822 dossier
= models
.ForeignKey(
823 Dossier
, related_name
='dae_comparaisons'
825 statut
= models
.ForeignKey(
826 rh
.Statut
, related_name
='+', verbose_name
='Statut', null
=True,
829 classement
= models
.ForeignKey(
830 rh
.Classement
, related_name
='+', verbose_name
='Classement',
831 null
=True, blank
=True
834 reversion
.register(DossierComparaison
, format
='xml')
836 class DossierComparaisonRemuneration(rh
.Remuneration_
):
837 dossier_comparaison
= models
.ForeignKey(
838 DossierComparaison
, related_name
='dossier_comparaison_remunerations'
841 reversion
.register(DossierComparaisonRemuneration
, format
='xml')
845 class Remuneration(rh
.Remuneration_
):
846 dossier
= models
.ForeignKey(
847 Dossier
, db_column
='dossier', related_name
='dae_remunerations'
850 reversion
.register(Remuneration
, format
='xml')
855 class Contrat(rh
.Contrat_
):
856 dossier
= models
.ForeignKey(
857 Dossier
, db_column
='dossier', related_name
='dae_contrats'
860 reversion
.register(Contrat
, format
='xml')
863 class ProxyDossierStatut(Dossier
):
866 verbose_name
= "Statut du dossier"
867 verbose_name_plural
= "Statut des dossiers"
870 class ProxyPosteStatut(Poste
):
873 verbose_name
= "Statut du poste"
874 verbose_name_plural
= "Statut des postes"
877 class ProxyImplantation(ref
.Implantation
):
879 # Ajout d'un manager pour ref.Implantation
880 dae_manager
= ImplantationManager()