1 # -=- encoding: utf-8 -=-
4 from django
.core
.files
.storage
import FileSystemStorage
5 from django
.db
import models
7 import datamaster_modeles
.models
as ref
8 from rh_v1
import models
as rh
11 STATUT_RESIDENCE_CHOICES
= (
13 ('expat', 'Expatrié'),
16 POSTE_APPEL_CHOICES
= (
17 ('interne', 'Interne'),
18 ('externe', 'Externe'),
21 POSTE_STATUT_CHOICES
= (
22 ('MAD', 'Mise à disposition'),
23 ('DET', 'Détachement'),
27 storage_prive
= FileSystemStorage(settings
.PRIVE_MEDIA_ROOT
, base_url
=settings
.PRIVE_MEDIA_URL
)
29 def poste_piece_dispatch(instance
, filename
):
30 path
= "poste/%s/%s" % (instance
.poste_id
, filename
)
33 def dossier_piece_dispatch(instance
, filename
):
34 path
= "dossier/%s/%s" % (instance
.dossier_id
, filename
)
38 class PostePiece(models
.Model
):
39 poste
= models
.ForeignKey("Poste")
40 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
41 fichier
= models
.FileField(verbose_name
="Fichier", upload_to
=poste_piece_dispatch
, storage
=storage_prive
)
43 class PosteManager(models
.Manager
):
45 Chargement de tous les objets FK existants sur chaque QuerySet.
47 def get_query_set(self
):
59 return super(PosteManager
, self
).get_query_set() \
60 .select_related(*fkeys
).all()
63 class Poste(models
.Model
):
65 id_rh
= models
.ForeignKey(rh
.Poste
, null
=True, related_name
='+',
67 verbose_name
="Mise à jour du poste")
68 nom
= models
.CharField(verbose_name
="Titre du poste", max_length
=255)
69 implantation
= models
.ForeignKey(ref
.Implantation
)
70 type_poste
= models
.ForeignKey(rh
.TypePoste
, null
=True, related_name
='+')
71 service
= models
.ForeignKey(rh
.Service
, related_name
='+',
72 verbose_name
=u
"Direction/Service/Pôle support")
73 responsable
= models
.ForeignKey(rh
.Poste
, related_name
='+',
74 verbose_name
="Poste du responsable")
76 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
78 verbose_name
="Temps de travail",
79 help_text
="% du temps complet")
80 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
83 verbose_name
="Nb. heures par semaine")
86 statut_residence
= models
.CharField(max_length
=10, default
='local',
87 verbose_name
="Statut",
88 choices
=STATUT_RESIDENCE_CHOICES
)
90 mise_a_disposition
= models
.BooleanField(verbose_name
="Mise à disposition")
91 appel
= models
.CharField(max_length
=10, default
='interne',
92 verbose_name
="Appel à candidature",
93 choices
=POSTE_APPEL_CHOICES
)
96 classement_min
= models
.ForeignKey(rh
.Classement
, related_name
='+')
97 classement_max
= models
.ForeignKey(rh
.Classement
, related_name
='+')
98 coefficient_min
= models
.FloatField(null
=True) # pour classement "hors grille"
99 coefficient_max
= models
.FloatField(null
=True) # pour classement "hors grille"
100 valeur_point_min
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+', blank
=True, null
=True)
101 valeur_point_max
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+', blank
=True, null
=True)
102 devise_min
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
103 devise_max
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
104 salaire_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
106 salaire_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
108 indemn_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
110 indemn_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
112 autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
114 autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
117 # Comparatifs de rémunération
118 devise_comparaison
= models
.ForeignKey(rh
.Devise
, related_name
='+',
120 comp_locale_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
121 null
=True, blank
=True)
122 comp_locale_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
123 null
=True, blank
=True)
124 comp_universite_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
125 null
=True, blank
=True)
126 comp_universite_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
127 null
=True, blank
=True)
128 comp_fonctionpub_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
129 null
=True, blank
=True)
130 comp_fonctionpub_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
131 null
=True, blank
=True)
132 comp_ong_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
133 null
=True, blank
=True)
134 comp_ong_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
135 null
=True, blank
=True)
136 comp_autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
137 null
=True, blank
=True)
138 comp_autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
139 null
=True, blank
=True)
142 validation_bureau_regional
= models
.BooleanField(verbose_name
="Validation bureau régional")
143 validation_bureau_regional_date
= models
.DateField(blank
=True, null
=True)
144 validation_drh
= models
.BooleanField(verbose_name
="Validation DRH")
145 validation_drh_date
= models
.DateField(blank
=True, null
=True)
146 validation_secretaire_general
= models
.BooleanField(verbose_name
="Validation secrétaire général")
147 validation_secretaire_general_date
= models
.DateField(blank
=True, null
=True)
148 validation_recteur
= models
.BooleanField(verbose_name
="Validation recteur")
149 validation_recteur_date
= models
.DateField(blank
=True, null
=True)
152 date_creation
= models
.DateTimeField(auto_now_add
=True)
153 date_modification
= models
.DateTimeField(auto_now
=True)
154 date_debut
= models
.DateField(verbose_name
="Date de début",
155 help_text
="format: aaaa-mm-jj")
156 date_fin
= models
.DateField(null
=True, blank
=True,
157 verbose_name
="Date de fin",
158 help_text
="format: aaaa-mm-jj")
159 actif
= models
.BooleanField(default
=True)
162 objects
= PosteManager()
166 Les vues sont montées selon une clef spéciale pour identifier la provenance du poste.
167 Cette méthode fournit un moyen de reconstruire cette clef afin de générer les URLs.
169 return "dae-%s" % self
.id
170 key
= property(_get_key
)
172 def get_dossiers(self
):
174 Liste tous les anciens dossiers liés à ce poste.
175 (Le nom de la relation sur le rh.Poste est mal choisi poste1 au lieu de dossier1)
176 Note1 : seulement le dosssier principal fait l'objet de la recherche.
177 Note2 : les dossiers sont retournés du plus récent au plus vieux. (Ce test est fait
178 en fonction du id, car les dates de création sont absentes de rh v1).
180 if self
.id_rh
is None:
182 postes
= [p
for p
in self
.id_rh
.poste1
.all()]
183 return sorted(postes
, key
=lambda poste
: poste
.id, reverse
=True)
185 def get_complement_nom(self
):
187 Inspecte les modèles rh v1 pour trouver dans le dernier dossier un complément de titre de poste.
189 dossiers
= self
.get_dossiers()
190 if len(dossiers
) > 0:
191 nom
= dossiers
[0].complement1
196 def get_employe(self
):
198 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
200 dossiers
= self
.get_dossiers()
201 if len(dossiers
) > 0:
202 return dossiers
[0].employe
206 def __unicode__(self
):
208 Cette fonction est consommatrice SQL car elle cherche les dossiers qui ont été liés à celui-ci.
210 complement_nom_poste
= self
.get_complement_nom()
211 if complement_nom_poste
is None:
212 complement_nom_poste
= ""
213 employe
= self
.get_employe()
221 complement_nom_poste
,
224 return u
'%s - %s (%s) [dae-%s %s %s]' % data
227 # Tester l'enregistrement car les models.py sont importés au complet
228 if not reversion
.is_registered(Poste
):
229 reversion
.register(Poste
)
232 POSTE_FINANCEMENT_CHOICES
= (
233 ('A', 'A - Frais de personnel'),
234 ('B', 'B - Projet(s)-Titre(s)'),
239 class PosteFinancement(models
.Model
):
240 montant
= models
.DecimalField(max_digits
=12, decimal_places
=2,
241 help_text
="ex.: 12000.00 € (décimale avec point, devise = EUR)")
242 poste
= models
.ForeignKey('Poste', related_name
='financements')
243 type = models
.CharField(max_length
=1, choices
=POSTE_FINANCEMENT_CHOICES
)
244 pourcentage
= models
.DecimalField(max_digits
=12, decimal_places
=2,
245 help_text
="ex.: 33.33 % (décimale avec point)")
246 commentaire
= models
.TextField(
247 help_text
="Spécifiez la source de financement.")
258 class Employe(models
.Model
):
261 id_rh
= models
.ForeignKey(rh
.Employe
, null
=True, related_name
='+',
262 verbose_name
='Employé')
263 nom
= models
.CharField(max_length
=255)
264 prenom
= models
.CharField(max_length
=255, verbose_name
='Prénom')
265 genre
= models
.CharField(max_length
=1, choices
=GENRE_CHOICES
,
266 null
=True, blank
=True)
268 def __unicode__(self
):
269 return u
'%s %s' % (self
.prenom
, self
.nom
)
272 COMPTE_COMPTA_CHOICES
= (
278 class DossierPiece(models
.Model
):
279 dossier
= models
.ForeignKey("Dossier")
280 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
281 fichier
= models
.FileField(verbose_name
="Fichier", upload_to
=dossier_piece_dispatch
, storage
=storage_prive
)
283 class Dossier(models
.Model
):
286 employe
= models
.ForeignKey('Employe', related_name
='+', editable
=False)
287 poste
= models
.ForeignKey('Poste', related_name
='+', editable
=False)
288 statut
= models
.ForeignKey(rh
.Statut
, related_name
='+')
289 organisme_bstg
= models
.ForeignKey(rh
.OrganismeBstg
,
290 null
=True, blank
=True,
291 verbose_name
="Organisme",
292 help_text
="Si détaché (DET) ou mis à disposition (MAD), \
293 préciser l'organisme.",
296 # Données antérieures de l'employé
297 statut_anterieur
= models
.ForeignKey(
298 rh
.Statut
, related_name
='+', null
=True, blank
=True,
299 verbose_name
='Statut antérieur')
301 classement_anterieur
= models
.ForeignKey(
302 rh
.Classement
, related_name
='+', null
=True, blank
=True,
303 verbose_name
='Classement précédent')
304 salaire_anterieur
= models
.DecimalField(
305 max_digits
=12, decimal_places
=2, null
=True, default
=None,
306 blank
=True, verbose_name
='Salaire précédent')
308 # Données du titulaire précédent
309 employe_anterieur
= models
.ForeignKey(
310 rh
.Employe
, related_name
='+', null
=True, blank
=True,
311 verbose_name
='Employé précédent')
312 statut_titulaire_anterieur
= models
.ForeignKey(
313 rh
.Statut
, related_name
='+', null
=True, blank
=True,
314 verbose_name
='Statut titulaire précédent')
315 classement_titulaire_anterieur
= models
.ForeignKey(
316 rh
.Classement
, related_name
='+', null
=True, blank
=True,
317 verbose_name
='Classement titulaire précédent')
318 salaire_titulaire_anterieur
= models
.DecimalField(
319 max_digits
=12, decimal_places
=2, default
=None, null
=True,
320 blank
=True, verbose_name
='Salaire titulaire précédent')
323 remplacement
= models
.BooleanField()
324 statut_residence
= models
.CharField(max_length
=10, default
='local',
325 verbose_name
="Statut",
326 choices
=STATUT_RESIDENCE_CHOICES
)
329 classement
= models
.ForeignKey(rh
.Classement
, related_name
='+',
330 verbose_name
='Classement proposé')
331 salaire
= models
.DecimalField(max_digits
=12, decimal_places
=2,
332 verbose_name
='Salaire de base',
333 null
=True, default
=None)
334 devise
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
335 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
336 verbose_name
="Régime de travail",
337 help_text
="% du temps complet")
338 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
339 decimal_places
=2, verbose_name
="Nb. heures par semaine")
342 type_contrat
= models
.ForeignKey(rh
.TypeContrat
, related_name
='+')
343 contrat_date_debut
= models
.DateField(help_text
="format: aaaa-mm-jj")
344 contrat_date_fin
= models
.DateField(null
=True, blank
=True,
345 help_text
="format: aaaa-mm-jj")
348 compte_compta
= models
.CharField(max_length
=10, default
='aucun',
349 verbose_name
=u
'Compte comptabilité',
350 choices
=COMPTE_COMPTA_CHOICES
)
351 compte_courriel
= models
.BooleanField()
354 date_creation
= models
.DateTimeField(auto_now_add
=True)
356 # Tester l'enregistrement car les models.py sont importés au complet
357 if not reversion
.is_registered(Dossier
):
358 reversion
.register(Dossier
)
360 class Remuneration(models
.Model
):
362 dossier
= models
.ForeignKey('Dossier', db_column
='dossier')
363 type = models
.ForeignKey(rh
.TypeRemuneration
, db_column
='type',
366 # type_revalorisation = models.ForeignKey('TypeRevalorisation',
367 # db_column='type_revalorisation')
368 montant
= models
.DecimalField(max_digits
=12, decimal_places
=2,
370 devise
= models
.ForeignKey(rh
.Devise
, to_field
='code',
371 db_column
='devise', related_name
='+')
372 precision
= models
.CharField(max_length
=255, null
=True, blank
=True)
373 # date_effective = models.DateField(null=True, blank=True)
374 # pourcentage = models.IntegerField(null=True, blank=True)
377 date_creation
= models
.DateField(auto_now_add
=True)
378 user_creation
= models
.IntegerField(null
=True, blank
=True)
379 # desactivation = models.BooleanField(default=False, blank=True)
380 # date_desactivation = models.DateField(null=True, blank=True)
381 # user_desactivation = models.IntegerField(null=True, blank=True)
382 # annulation = models.BooleanField(default=False, blank=True)
383 # date_annulation = models.DateField(null=True, blank=True)
384 # user_annulation = models.IntegerField(null=True, blank=True)
386 def montant_mois(self
):
387 return round(self
.montant
/ 12, 2)
389 def taux_devise(self
):
390 return self
.devise
.tauxchange_set
.order_by('-annee').all()[0].taux
392 def montant_euro(self
):
393 return round(float(self
.montant
) / float(self
.taux_devise()), 2)
395 def montant_euro_mois(self
):
396 return round(self
.montant_euro() / 12, 2)
399 class JustificationPoste(models
.Model
):
403 class JustificationEmploye(models
.Model
):
407 class DocumentPoste(models
.Model
):
411 class DocumentEmploye(models
.Model
):
415 class Validation(models
.Model
):
417 date
= models
.DateField()
419 # avis = ? (CHOICES?)
422 class ValidationPoste(models
.Model
):
423 poste
= models
.ForeignKey('Poste')
426 class ValidationEmploye(models
.Model
):
427 employe
= models
.ForeignKey('Employe')