1 # -=- encoding: utf-8 -=-
5 from django
.core
.files
.storage
import FileSystemStorage
6 from django
.db
import models
9 import datamaster_modeles
.models
as ref
13 HELP_TEXT_DATE
= "format: aaaa-mm-jj"
14 REGIME_TRAVAIL_DEFAULT
= 100.00
15 REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT
= 35.00
19 storage_prive
= FileSystemStorage(settings
.PRIVE_MEDIA_ROOT
,
20 base_url
=settings
.PRIVE_MEDIA_URL
)
22 def poste_piece_dispatch(instance
, filename
):
23 path
= "poste/%s/%s" % (instance
.poste_id
, filename
)
26 def dossier_piece_dispatch(instance
, filename
):
27 path
= "dossier/%s/%s" % (instance
.dossier_id
, filename
)
31 class Metadata(models
.Model
):
33 Metadata.actif = flag remplaçant la suppression.
34 actif == False : objet réputé supprimé.
36 actif
= models
.BooleanField(default
=True)
37 date_creation
= models
.DateField(auto_now_add
=True)
38 user_creation
= models
.ForeignKey('auth.User',
39 db_column
='user_creation', related_name
='+',
40 null
=True, blank
=True)
41 date_modification
= models
.DateField(auto_now
=True)
42 user_modification
= models
.ForeignKey('auth.User',
43 db_column
='user_modification', related_name
='+',
44 null
=True, blank
=True)
45 date_desactivation
= models
.DateField(null
=True, blank
=True)
46 user_desactivation
= models
.ForeignKey('auth.User',
47 db_column
='user_desactivation', related_name
='+',
48 null
=True, blank
=True)
53 class Commentaire(Metadata
):
54 texte
= models
.TextField()
55 owner
= models
.ForeignKey('auth.User', db_column
='owner', related_name
='+')
59 ordering
= ['-date_creation']
61 def __unicode__(self
):
62 return u
'%s' % (self
.texte
)
67 POSTE_APPEL_CHOICES
= (
68 ('interne', 'Interne'),
69 ('externe', 'Externe'),
72 class Poste_(Metadata
):
73 """Un Poste est un emploi (job) à combler dans une implantation.
74 Un Poste peut être comblé par un Employe, auquel cas un Dossier est créé.
75 Si on veut recruter 2 jardiniers, 2 Postes distincts existent.
78 nom
= models
.CharField(max_length
=255,
79 verbose_name
="Titre du poste", )
80 nom_feminin
= models
.CharField(max_length
=255,
81 verbose_name
="Titre du poste (au féminin)",
83 implantation
= models
.ForeignKey(ref
.Implantation
,
84 db_column
='implantation', related_name
='+')
85 type_poste
= models
.ForeignKey('TypePoste', db_column
='type_poste',
88 service
= models
.ForeignKey('Service', db_column
='service',
90 verbose_name
="Direction/Service/Pôle support",
91 default
=1) # default = Rectorat
92 responsable
= models
.ForeignKey('Poste', db_column
='responsable',
94 verbose_name
="Poste du responsable",
95 default
=149) # default = Recteur
98 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
99 default
=REGIME_TRAVAIL_DEFAULT
,
100 verbose_name
="Temps de travail",
101 help_text
="% du temps complet")
102 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
104 default
=REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT
,
105 verbose_name
="Nb. heures par semaine")
108 local
= models
.BooleanField(verbose_name
="Local", default
=True,
110 expatrie
= models
.BooleanField(verbose_name
="Expatrié", default
=False,
112 mise_a_disposition
= models
.BooleanField(
113 verbose_name
="Mise à disposition",
115 appel
= models
.CharField(max_length
=10,
116 verbose_name
="Appel à candidature",
117 choices
=POSTE_APPEL_CHOICES
,
121 classement_min
= models
.ForeignKey('Classement',
122 db_column
='classement_min', related_name
='+',
123 null
=True, blank
=True)
124 classement_max
= models
.ForeignKey('Classement',
125 db_column
='classement_max', related_name
='+',
126 null
=True, blank
=True)
127 valeur_point_min
= models
.ForeignKey('ValeurPoint',
128 db_column
='valeur_point_min', related_name
='+',
129 null
=True, blank
=True)
130 valeur_point_max
= models
.ForeignKey('ValeurPoint',
131 db_column
='valeur_point_max', related_name
='+',
132 null
=True, blank
=True)
133 devise_min
= models
.ForeignKey('Devise', db_column
='devise_min',
134 related_name
='+', default
=5)
135 devise_max
= models
.ForeignKey('Devise', db_column
='devise_max',
136 related_name
='+', default
=5)
137 salaire_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
139 salaire_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
141 indemn_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
143 indemn_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
145 autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
147 autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
150 # Comparatifs de rémunération
151 devise_comparaison
= models
.ForeignKey('Devise',
152 db_column
='devise_comparaison',
155 comp_locale_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
156 null
=True, blank
=True)
157 comp_locale_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
158 null
=True, blank
=True)
159 comp_universite_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
160 null
=True, blank
=True)
161 comp_universite_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
162 null
=True, blank
=True)
163 comp_fonctionpub_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
164 null
=True, blank
=True)
165 comp_fonctionpub_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
166 null
=True, blank
=True)
167 comp_ong_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
168 null
=True, blank
=True)
169 comp_ong_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
170 null
=True, blank
=True)
171 comp_autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
172 null
=True, blank
=True)
173 comp_autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
174 null
=True, blank
=True)
177 justification
= models
.TextField(null
=True, blank
=True)
180 date_validation
= models
.DateTimeField(null
=True, blank
=True) # de dae
181 date_debut
= models
.DateField(verbose_name
="Date de début",
182 help_text
=HELP_TEXT_DATE
)
183 date_fin
= models
.DateField(verbose_name
="Date de fin",
184 help_text
=HELP_TEXT_DATE
,
185 null
=True, blank
=True)
189 ordering
= ['implantation__nom', 'nom']
190 verbose_name
= "Poste"
191 verbose_name_plural
= "Postes"
193 def __unicode__(self
):
194 representation
= u
'%s - %s [%s]' % (self
.implantation
, self
.nom
,
197 representation
= representation
+ u
' (vacant)'
198 return representation
201 # TODO : si existe un dossier actif pour ce poste, return False
202 # self.dossier_set.all() fonctionne pas
207 __doc__
= Poste_
.__doc__
210 POSTE_FINANCEMENT_CHOICES
= (
211 ('A', 'A - Frais de personnel'),
212 ('B', 'B - Projet(s)-Titre(s)'),
217 class PosteFinancement_(models
.Model
):
218 """Pour un Poste, structure d'informations décrivant comment on prévoit
221 poste
= models
.ForeignKey('Poste', db_column
='poste',
222 related_name
='%(app_label)s_financements')
223 type = models
.CharField(max_length
=1, choices
=POSTE_FINANCEMENT_CHOICES
)
224 pourcentage
= models
.DecimalField(max_digits
=12, decimal_places
=2,
225 help_text
="ex.: 33.33 % (décimale avec point)")
226 commentaire
= models
.TextField(
227 help_text
="Spécifiez la source de financement.")
233 def __unicode__(self
):
234 return u
'%s : %s %' % (self
.type, self
.pourcentage
)
237 class PosteFinancement(PosteFinancement_
):
238 __doc__
= PosteFinancement_
.__doc__
241 class PostePiece(models
.Model
):
242 """Documents relatifs au Poste.
243 Ex.: Description de poste
245 poste
= models
.ForeignKey('Poste', db_column
='poste',
246 related_name
='pieces')
247 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
248 fichier
= models
.FileField(verbose_name
="Fichier",
249 upload_to
=poste_piece_dispatch
,
250 storage
=storage_prive
)
255 def __unicode__(self
):
256 return u
'%s' % (self
.nom
)
258 class PosteCommentaire(Commentaire
):
259 poste
= models
.ForeignKey('Poste', db_column
='poste', related_name
='+')
268 SITUATION_CHOICES
= (
269 ('C', 'Célibataire'),
274 class Employe(Metadata
):
275 """Personne occupant ou ayant occupé un Poste. Un Employe aura autant de
276 Dossiers qu'il occupe ou a occupé de Postes.
278 Cette classe aurait pu avantageusement s'appeler Personne car la notion
279 d'employé n'a pas de sens si aucun Dossier n'existe pour une personne.
282 nom
= models
.CharField(max_length
=255)
283 prenom
= models
.CharField(max_length
=255, verbose_name
="Prénom")
284 nom_affichage
= models
.CharField(max_length
=255,
285 verbose_name
="Nom d'affichage",
286 null
=True, blank
=True)
287 nationalite
= models
.ForeignKey(ref
.Pays
, to_field
='code',
288 db_column
='nationalite',
289 related_name
='employes_nationalite',
290 verbose_name
="Nationalité")
291 date_naissance
= models
.DateField(help_text
=HELP_TEXT_DATE
,
292 verbose_name
="Date de naissance",
293 null
=True, blank
=True)
294 genre
= models
.CharField(max_length
=1, choices
=GENRE_CHOICES
)
297 situation_famille
= models
.CharField(max_length
=1,
298 choices
=SITUATION_CHOICES
,
299 verbose_name
="Situation familiale",
300 null
=True, blank
=True)
301 date_entree
= models
.DateField(verbose_name
="Date d'entrée à l'AUF",
302 help_text
=HELP_TEXT_DATE
,
303 null
=True, blank
=True)
306 tel_domicile
= models
.CharField(max_length
=255,
307 verbose_name
="Tél. domicile",
308 null
=True, blank
=True)
309 tel_cellulaire
= models
.CharField(max_length
=255,
310 verbose_name
="Tél. cellulaire",
311 null
=True, blank
=True)
312 adresse
= models
.CharField(max_length
=255, null
=True, blank
=True)
313 ville
= models
.CharField(max_length
=255, null
=True, blank
=True)
314 province
= models
.CharField(max_length
=255, null
=True, blank
=True)
315 code_postal
= models
.CharField(max_length
=255, null
=True, blank
=True)
316 pays
= models
.ForeignKey(ref
.Pays
, to_field
='code', db_column
='pays',
317 related_name
='employes',
318 null
=True, blank
=True)
321 ordering
= ['nom_affichage','nom','prenom']
322 verbose_name
= "Employé"
323 verbose_name_plural
= "Employés"
325 def __unicode__(self
):
326 return u
'%s' % (self
.get_nom())
329 nom_affichage
= self
.nom_affichage
330 if not nom_affichage
:
331 nom_affichage
= u
'%s %s' % (self
.nom
.upper(), self
.prenom
)
334 class EmployePiece(models
.Model
):
335 """Documents relatifs à un employé.
338 employe
= models
.ForeignKey('Employe', db_column
='employe',
340 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
341 fichier
= models
.FileField(verbose_name
="Fichier",
342 upload_to
=dossier_piece_dispatch
,
343 storage
=storage_prive
)
348 def __unicode__(self
):
349 return u
'%s' % (self
.nom
)
351 class EmployeCommentaire(Commentaire
):
352 employe
= models
.ForeignKey('Employe', db_column
='employe',
356 LIEN_PARENTE_CHOICES
= (
357 ('Conjoint', 'Conjoint'),
358 ('Conjointe', 'Conjointe'),
363 class AyantDroit(Metadata
):
364 """Personne en relation avec un Employe.
367 nom
= models
.CharField(max_length
=255)
368 prenom
= models
.CharField(max_length
=255,
369 verbose_name
="Prénom",)
370 nom_affichage
= models
.CharField(max_length
=255,
371 verbose_name
="Nom d'affichage",
372 null
=True, blank
=True)
373 nationalite
= models
.ForeignKey(ref
.Pays
, to_field
='code',
374 db_column
='nationalite',
375 related_name
='ayantdroits_nationalite',
376 verbose_name
="Nationalité")
377 date_naissance
= models
.DateField(help_text
=HELP_TEXT_DATE
,
378 verbose_name
="Date de naissance",
379 null
=True, blank
=True)
380 genre
= models
.CharField(max_length
=1, choices
=GENRE_CHOICES
)
383 employe
= models
.ForeignKey('Employe', db_column
='employe',
384 related_name
='ayantdroits',
385 verbose_name
="Employé")
386 lien_parente
= models
.CharField(max_length
=10,
387 choices
=LIEN_PARENTE_CHOICES
,
388 verbose_name
="Lien de parenté",
389 null
=True, blank
=True)
392 ordering
= ['nom_affichage']
393 verbose_name
= "Ayant droit"
394 verbose_name_plural
= "Ayants droit"
396 def __unicode__(self
):
397 return u
'%s' % (self
.get_nom())
400 nom_affichage
= self
.nom_affichage
401 if not nom_affichage
:
402 nom_affichage
= u
'%s %s' % (self
.nom
.upper(), self
.prenom
)
405 class AyantDroitCommentaire(Commentaire
):
406 ayant_droit
= models
.ForeignKey('AyantDroit', db_column
='ayant_droit',
412 STATUT_RESIDENCE_CHOICES
= (
414 ('expat', 'Expatrié'),
417 COMPTE_COMPTA_CHOICES
= (
424 class Dossier_(Metadata
):
425 """Le Dossier regroupe les informations relatives à l'occupation
426 d'un Poste par un Employe. Un seul Dossier existe par Poste occupé
429 Plusieurs Contrats peuvent être associés au Dossier.
430 Une structure de Remuneration est rattachée au Dossier. Un Poste pour
431 lequel aucun Dossier n'existe est un poste vacant.
434 employe
= models
.ForeignKey('Employe', db_column
='employe',
436 verbose_name
="Employé")
437 poste
= models
.ForeignKey('Poste', db_column
='poste',
438 related_name
='+', editable
=False)
439 statut
= models
.ForeignKey('Statut', related_name
='+', default
=3)
440 organisme_bstg
= models
.ForeignKey('OrganismeBstg',
441 db_column
='organisme_bstg',
443 verbose_name
="Organisme",
444 help_text
="Si détaché (DET) ou \
445 mis à disposition (MAD), \
446 préciser l'organisme.",
447 null
=True, blank
=True)
450 remplacement
= models
.BooleanField(default
=False)
451 statut_residence
= models
.CharField(max_length
=10, default
='local',
452 verbose_name
="Statut",
453 choices
=STATUT_RESIDENCE_CHOICES
)
456 classement
= models
.ForeignKey('Classement', db_column
='classement',
458 null
=True, blank
=True)
459 regime_travail
= models
.DecimalField(max_digits
=12,
461 default
=REGIME_TRAVAIL_DEFAULT
,
462 verbose_name
="Régime de travail",
463 help_text
="% du temps complet")
464 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
466 default
=REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT
,
467 verbose_name
="Nb. heures par semaine")
469 # Occupation du Poste par cet Employe (anciennement "mandat")
470 date_debut
= models
.DateField(verbose_name
="Date de début d'occupation \
472 help_text
=HELP_TEXT_DATE
)
473 date_fin
= models
.DateField(verbose_name
="Date de fin d'occupation \
475 help_text
=HELP_TEXT_DATE
,
476 null
=True, blank
=True)
483 ordering
= ['employe__nom_affichage', 'employe__nom', 'poste__nom']
484 verbose_name
= "Dossier"
485 verbose_name_plural
= "Dossiers"
487 def __unicode__(self
):
488 poste
= self
.poste
.nom
489 if self
.employe
.genre
== 'F':
490 poste
= self
.poste
.nom_feminin
491 return u
'%s - %s' % (self
.employe
, poste
)
494 class Dossier(Dossier_
):
495 __doc__
= Dossier_
.__doc__
498 class DossierPiece(models
.Model
):
499 """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
500 Ex.: Lettre de motivation.
502 dossier
= models
.ForeignKey('Dossier', db_column
='dossier',
504 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
505 fichier
= models
.FileField(verbose_name
="Fichier",
506 upload_to
=dossier_piece_dispatch
,
507 storage
=storage_prive
)
512 def __unicode__(self
):
513 return u
'%s' % (self
.nom
)
515 class DossierCommentaire(Commentaire
):
516 dossier
= models
.ForeignKey('Dossier', db_column
='dossier',
522 class RemunerationMixin(Metadata
):
524 dossier
= models
.ForeignKey('Dossier', db_column
='dossier',
525 related_name
='%(app_label)s_%(class)s_remunerations')
526 type = models
.ForeignKey('TypeRemuneration', db_column
='type',
528 verbose_name
="Type de rémunération")
529 type_revalorisation
= models
.ForeignKey('TypeRevalorisation',
530 db_column
='type_revalorisation',
532 verbose_name
="Type de revalorisation",
533 null
=True, blank
=True)
534 montant
= models
.FloatField(null
=True, blank
=True,
536 # Annuel (12 mois, 52 semaines, 364 jours?)
537 devise
= models
.ForeignKey('Devise', to_field
='id',
538 db_column
='devise', related_name
='+',
540 # commentaire = precision
541 commentaire
= models
.CharField(max_length
=255, null
=True, blank
=True)
542 # date_debut = anciennement date_effectif
543 date_debut
= models
.DateField(help_text
=HELP_TEXT_DATE
,
544 verbose_name
="Date de début",
545 null
=True, blank
=True)
546 date_fin
= models
.DateField(help_text
=HELP_TEXT_DATE
,
547 verbose_name
="Date de fin",
548 null
=True, blank
=True)
552 ordering
= ['type__nom', '-date_fin']
554 def __unicode__(self
):
555 return u
'%s %s (%s)' % (self
.montant
, self
.devise
.code
, self
.type.nom
)
557 class Remuneration_(RemunerationMixin
):
558 """Structure de rémunération (données budgétaires) en situation normale
559 pour un Dossier. Si un Evenement existe, utiliser la structure de
560 rémunération EvenementRemuneration de cet événement.
563 def montant_mois(self
):
564 return round(self
.montant
/ 12, 2)
566 def taux_devise(self
):
567 return self
.devise
.tauxchange_set
.order_by('-annee').all()[0].taux
569 def montant_euro(self
):
570 return round(float(self
.montant
) / float(self
.taux_devise()), 2)
572 def montant_euro_mois(self
):
573 return round(self
.montant_euro() / 12, 2)
575 def __unicode__(self
):
577 devise
= self
.devise
.code
580 return "%s %s" % (self
.montant
, devise
)
584 verbose_name
= "Rémunération"
585 verbose_name_plural
= "Rémunérations"
588 class Remuneration(Remuneration_
):
589 __doc__
= Remuneration_
.__doc__
594 class Contrat(Metadata
):
595 """Document juridique qui encadre la relation de travail d'un Employe
596 pour un Poste particulier. Pour un Dossier (qui documente cette
597 relation de travail) plusieurs contrats peuvent être associés.
599 dossier
= models
.ForeignKey('Dossier', db_column
='dossier',
601 type_contrat
= models
.ForeignKey('TypeContrat', db_column
='type_contrat',
603 verbose_name
="Type de contrat")
604 date_debut
= models
.DateField(help_text
=HELP_TEXT_DATE
,
605 verbose_name
="Date de début")
606 date_fin
= models
.DateField(help_text
=HELP_TEXT_DATE
,
607 verbose_name
="Date de fin",
608 null
=True, blank
=True)
611 ordering
= ['dossier__employe__nom_affichage']
612 verbose_name
= "Contrat"
613 verbose_name_plural
= "Contrats"
615 def __unicode__(self
):
616 return u
'%s - %s' % (self
.dossier
, self
.id)
618 # TODO? class ContratPiece(models.Model):
623 class Evenement_(Metadata
):
624 """Un Evenement sert à déclarer une situation temporaire (exceptionnelle)
625 d'un Dossier qui vient altérer des informations normales liées à un Dossier
626 (ex.: la Remuneration).
628 Ex.: congé de maternité, maladie...
630 Lors de ces situations exceptionnelles, l'Employe a un régime de travail
631 différent et une rémunération en conséquence. On souhaite toutefois
632 conserver le Dossier intact afin d'éviter une re-saisie des données lors
633 du retour à la normale.
635 dossier
= models
.ForeignKey('Dossier', db_column
='dossier',
637 nom
= models
.CharField(max_length
=255)
638 date_debut
= models
.DateField(help_text
=HELP_TEXT_DATE
,
639 verbose_name
="Date de début")
640 date_fin
= models
.DateField(help_text
=HELP_TEXT_DATE
,
641 verbose_name
="Date de fin",
642 null
=True, blank
=True)
647 verbose_name
= "Évènement"
648 verbose_name_plural
= "Évènements"
650 def __unicode__(self
):
651 return u
'%s' % (self
.nom
)
654 class Evenement(Evenement_
):
655 __doc__
= Evenement_
.__doc__
658 class EvenementRemuneration_(RemunerationMixin
):
659 """Structure de rémunération liée à un Evenement qui remplace
660 temporairement la Remuneration normale d'un Dossier, pour toute la durée
663 evenement
= models
.ForeignKey("Evenement", db_column
='evenement',
665 verbose_name
="Évènement")
666 # TODO : le champ dossier hérité de Remuneration doit être dérivé
667 # de l'Evenement associé
671 ordering
= ['evenement', 'type__nom', '-date_fin']
672 verbose_name
= "Évènement - rémunération"
673 verbose_name_plural
= "Évènements - rémunérations"
676 class EvenementRemuneration(EvenementRemuneration_
):
677 __doc__
= EvenementRemuneration_
.__doc__
682 class FamilleEmploi(Metadata
):
683 """Catégorie utilisée dans la gestion des Postes.
684 Catégorie supérieure à TypePoste.
686 nom
= models
.CharField(max_length
=255)
690 verbose_name
= "Famille d'emploi"
691 verbose_name_plural
= "Familles d'emploi"
693 def __unicode__(self
):
694 return u
'%s' % (self
.nom
)
696 class TypePoste(Metadata
):
697 """Catégorie de Poste.
699 nom
= models
.CharField(max_length
=255)
700 nom_feminin
= models
.CharField(max_length
=255,
701 verbose_name
="Nom féminin")
703 is_responsable
= models
.BooleanField(default
=False,
704 verbose_name
="Poste de responsabilité")
705 famille_emploi
= models
.ForeignKey('FamilleEmploi',
706 db_column
='famille_emploi',
708 verbose_name
="Famille d'emploi")
712 verbose_name
= "Type de poste"
713 verbose_name_plural
= "Types de poste"
715 def __unicode__(self
):
716 return u
'%s' % (self
.nom
)
719 TYPE_PAIEMENT_CHOICES
= (
720 ('Régulier', 'Régulier'),
721 ('Ponctuel', 'Ponctuel'),
724 NATURE_REMUNERATION_CHOICES
= (
725 ('Accessoire', 'Accessoire'),
726 ('Charges', 'Charges'),
727 ('Indemnité', 'Indemnité'),
728 ('RAS', 'Rémunération autre source'),
729 ('Traitement', 'Traitement'),
732 class TypeRemuneration(Metadata
):
733 """Catégorie de Remuneration.
735 nom
= models
.CharField(max_length
=255)
736 type_paiement
= models
.CharField(max_length
=30,
737 choices
=TYPE_PAIEMENT_CHOICES
,
738 verbose_name
="Type de paiement")
739 nature_remuneration
= models
.CharField(max_length
=30,
740 choices
=NATURE_REMUNERATION_CHOICES
,
741 verbose_name
="Nature de la rémunération")
745 verbose_name
= "Type de rémunération"
746 verbose_name_plural
= "Types de rémunération"
748 def __unicode__(self
):
749 return u
'%s' % (self
.nom
)
751 class TypeRevalorisation(Metadata
):
752 """Justification du changement de la Remuneration.
753 (Actuellement utilisé dans aucun traitement informatique.)
755 nom
= models
.CharField(max_length
=255)
759 verbose_name
= "Type de revalorisation"
760 verbose_name_plural
= "Types de revalorisation"
762 def __unicode__(self
):
763 return u
'%s' % (self
.nom
)
765 class Service(Metadata
):
766 """Unité administrative où les Postes sont rattachés.
768 nom
= models
.CharField(max_length
=255)
772 verbose_name
= "Service"
773 verbose_name_plural
= "Services"
775 def __unicode__(self
):
776 return u
'%s' % (self
.nom
)
779 TYPE_ORGANISME_CHOICES
= (
780 ('MAD', 'Mise à disposition'),
781 ('DET', 'Détachement'),
784 class OrganismeBstg(Metadata
):
785 """Organisation d'où provient un Employe mis à disposition (MAD) de
786 ou détaché (DET) à l'AUF à titre gratuit.
788 (BSTG = bien et service à titre gratuit.)
790 nom
= models
.CharField(max_length
=255)
791 type = models
.CharField(max_length
=10, choices
=TYPE_ORGANISME_CHOICES
)
792 pays
= models
.ForeignKey(ref
.Pays
, to_field
='code',
794 related_name
='organismes_bstg',
795 null
=True, blank
=True)
798 ordering
= ['type', 'nom']
799 verbose_name
= "Organisme BSTG"
800 verbose_name_plural
= "Organismes BSTG"
802 def __unicode__(self
):
803 return u
'%s (%s)' % (self
.nom
, self
.get_type_display())
805 class Statut(Metadata
):
806 """Statut de l'Employe dans le cadre d'un Dossier particulier.
809 code
= models
.CharField(max_length
=25, unique
=True)
810 nom
= models
.CharField(max_length
=255)
814 verbose_name
= "Statut d'employé"
815 verbose_name_plural
= "Statuts d'employé"
817 def __unicode__(self
):
818 return u
'%s : %s' % (self
.code
, self
.nom
)
821 TYPE_CLASSEMENT_CHOICES
= (
823 ('T', 'T - Technicien'),
824 ('P', 'P - Professionel'),
826 ('D', 'D - Direction'),
827 ('SO', 'SO - Sans objet [expatriés]'),
828 ('HG', 'HG - Hors grille [direction]'),
832 class Classement_(Metadata
):
833 """Éléments de classement de la
834 "Grille générique de classement hiérarchique".
836 Utile pour connaître, pour un Dossier, le salaire de base théorique lié au
837 classement dans la grille. Le classement donne le coefficient utilisé dans:
839 salaire de base = coefficient * valeur du point de l'Implantation du Poste
842 type = models
.CharField(max_length
=10, choices
=TYPE_CLASSEMENT_CHOICES
)
843 echelon
= models
.IntegerField(verbose_name
="Échelon")
844 degre
= models
.IntegerField(verbose_name
="Degré")
845 coefficient
= models
.FloatField(default
=0, verbose_name
="Coéfficient")
847 # annee # au lieu de date_debut et date_fin
848 commentaire
= models
.TextField(null
=True, blank
=True)
852 ordering
= ['type','echelon','degre','coefficient']
853 verbose_name
= "Classement"
854 verbose_name_plural
= "Classements"
856 def __unicode__(self
):
857 return u
'%s.%s.%s (%s)' % (self
.type, self
.echelon
, self
.degre
,
860 class Classement(Classement_
):
861 __doc__
= Classement_
.__doc__
864 class TauxChange_(Metadata
):
865 """Taux de change de la devise vers l'euro (EUR)
866 pour chaque année budgétaire.
869 devise
= models
.ForeignKey('Devise', db_column
='devise',
871 annee
= models
.IntegerField(verbose_name
="Année")
872 taux
= models
.FloatField(verbose_name
="Taux vers l'euro")
876 ordering
= ['-annee', 'devise__code']
877 verbose_name
= "Taux de change"
878 verbose_name_plural
= "Taux de change"
880 def __unicode__(self
):
881 return u
'%s : %s € (%s)' % (self
.devise
, self
.taux
, self
.annee
)
884 class TauxChange(TauxChange_
):
885 __doc__
= TauxChange_
.__doc__
888 class ValeurPoint_(Metadata
):
889 """Utile pour connaître, pour un Dossier, le salaire de base théorique lié
890 au classement dans la grille. La ValeurPoint s'obtient par l'implantation
891 du Poste de ce Dossier : dossier.poste.implantation (pseudo code).
893 salaire de base = coefficient * valeur du point de l'Implantation du Poste
895 valeur
= models
.FloatField()
896 devise
= models
.ForeignKey('Devise', db_column
='devise',
897 related_name
='+', default
=5)
898 implantation
= models
.ForeignKey(ref
.Implantation
,
899 db_column
='implantation',
900 related_name
='%(app_label)s_valeur_point')
902 annee
= models
.IntegerField()
907 verbose_name
= "Valeur du point"
908 verbose_name_plural
= "Valeurs du point"
910 def __unicode__(self
):
911 return u
'%s %s (%s)' % (self
.valeur
, self
.devise
, self
.annee
)
914 class ValeurPoint(ValeurPoint_
):
915 __doc__
= ValeurPoint_
.__doc__
918 class Devise(Metadata
):
921 code
= models
.CharField(max_length
=10, unique
=True)
922 nom
= models
.CharField(max_length
=255)
926 verbose_name
= "Devise"
927 verbose_name_plural
= "Devises"
929 def __unicode__(self
):
930 return u
'%s - %s' % (self
.code
, self
.nom
)
932 class TypeContrat(Metadata
):
935 nom
= models
.CharField(max_length
=255)
936 nom_long
= models
.CharField(max_length
=255)
940 verbose_name
= "Type de contrat"
941 verbose_name_plural
= "Types de contrat"
943 def __unicode__(self
):
944 return u
'%s' % (self
.nom
)
949 class ResponsableImplantation(Metadata
):
950 """Le responsable d'une implantation.
951 Anciennement géré sur le Dossier du responsable.
953 employe
= models
.ForeignKey('Employe', db_column
='employe',
955 null
=True, blank
=True)
956 implantation
= models
.ForeignKey(ref
.Implantation
,
957 db_column
='implantation', related_name
='+',
960 def __unicode__(self
):
961 return u
'%s : %s' % (self
.implantation
, self
.employe
)
964 ordering
= ['implantation__nom']
965 verbose_name
= "Responsable d'implantation"
966 verbose_name_plural
= "Responsables d'implantation"