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 storage_prive
= FileSystemStorage(settings
.PRIVE_MEDIA_ROOT
,
14 base_url
=settings
.PRIVE_MEDIA_URL
)
16 def poste_piece_dispatch(instance
, filename
):
17 path
= "poste/%s/%s" % (instance
.poste_id
, filename
)
20 def dossier_piece_dispatch(instance
, filename
):
21 path
= "dossier/%s/%s" % (instance
.dossier_id
, filename
)
27 POSTE_APPEL_CHOICES
= (
28 ('interne', 'Interne'),
29 ('externe', 'Externe'),
32 class Poste(models
.Model
):
34 id = models
.IntegerField(primary_key
=True)
35 nom
= models
.CharField(verbose_name
="Titre du poste", max_length
=255)
37 implantation
= models
.ForeignKey(ref
.Implantation
)
38 type_poste
= models
.ForeignKey(rh
.TypePoste
, null
=True, related_name
='+')
39 service
= models
.ForeignKey(rh
.Service
, related_name
='+',
40 verbose_name
=u
"Direction/Service/Pôle support")
41 responsable
= models
.ForeignKey(rh
.Poste
, related_name
='+',
42 verbose_name
="Poste du responsable")
45 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
47 verbose_name
="Temps de travail",
48 help_text
="% du temps complet")
49 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
52 verbose_name
="Nb. heures par semaine")
55 local
= models
.BooleanField(verbose_name
="Local", default
=True, blank
=True)
56 expatrie
= models
.BooleanField(verbose_name
="Expatrié", default
=False,
60 mise_a_disposition
= models
.BooleanField(verbose_name
="Mise à disposition")
61 appel
= models
.CharField(max_length
=10, default
='interne',
62 verbose_name
="Appel à candidature",
63 choices
=POSTE_APPEL_CHOICES
)
66 classement_min
= models
.ForeignKey(rh
.Classement
, related_name
='+')
67 classement_max
= models
.ForeignKey(rh
.Classement
, related_name
='+')
68 valeur_point_min
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+',
69 blank
=True, null
=True)
70 valeur_point_max
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+',
71 blank
=True, null
=True)
72 devise_min
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
73 devise_max
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
74 salaire_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
76 salaire_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
78 indemn_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
80 indemn_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
82 autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
84 autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
87 # Comparatifs de rémunération
88 devise_comparaison
= models
.ForeignKey(rh
.Devise
, related_name
='+',
90 comp_locale_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
91 null
=True, blank
=True)
92 comp_locale_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
93 null
=True, blank
=True)
94 comp_universite_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
95 null
=True, blank
=True)
96 comp_universite_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
97 null
=True, blank
=True)
98 comp_fonctionpub_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
99 null
=True, blank
=True)
100 comp_fonctionpub_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
101 null
=True, blank
=True)
102 comp_ong_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
103 null
=True, blank
=True)
104 comp_ong_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
105 null
=True, blank
=True)
106 comp_autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
107 null
=True, blank
=True)
108 comp_autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
109 null
=True, blank
=True)
112 justification
= models
.TextField()
115 date_validation
= models
.DateTimeField() # provenance : dae
116 date_creation
= models
.DateTimeField(auto_now_add
=True)
117 date_modification
= models
.DateTimeField(auto_now
=True)
118 date_debut
= models
.DateField(verbose_name
="Date de début",
119 help_text
="format: aaaa-mm-jj")
120 date_fin
= models
.DateField(null
=True, blank
=True,
121 verbose_name
="Date de fin",
122 help_text
="format: aaaa-mm-jj")
123 actif
= models
.BooleanField(default
=True)
125 def __unicode__(self
):
126 # gérer si poste est vacant ou non dans affichage
127 return u
'%s - %s [%s]' % (self
.implantation
, self
.nom
, self
.id)
130 POSTE_FINANCEMENT_CHOICES
= (
131 ('A', 'A - Frais de personnel'),
132 ('B', 'B - Projet(s)-Titre(s)'),
136 class PosteFinancement(models
.Model
):
137 poste
= models
.ForeignKey('Poste', related_name
='financements')
138 type = models
.CharField(max_length
=1, choices
=POSTE_FINANCEMENT_CHOICES
)
139 pourcentage
= models
.DecimalField(max_digits
=12, decimal_places
=2,
140 help_text
="ex.: 33.33 % (décimale avec point)")
141 commentaire
= models
.TextField(
142 help_text
="Spécifiez la source de financement.")
147 class PostePiece(models
.Model
):
148 """Documents relatifs au Poste
149 Ex.: Description de poste
151 poste
= models
.ForeignKey("Poste")
152 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
153 fichier
= models
.FileField(verbose_name
="Fichier",
154 upload_to
=poste_piece_dispatch
,
155 storage
=storage_prive
)
164 SITUATION_CHOICES
= (
165 ('C', 'Célibataire'),
170 class Employe(models
.Model
):
172 id = models
.IntegerField(primary_key
=True)
173 nom
= models
.CharField(max_length
=255)
174 prenom
= models
.CharField(max_length
=255)
175 nationalite
= models
.ForeignKey(ref
.Pays
, to_field
='code',
176 related_name
='employes_nationalite',
177 db_column
='nationalite')
178 date_naissance
= models
.DateField(null
=True, blank
=True)
181 genre
= models
.CharField(max_length
=1, null
=True, blank
=True,
182 choices
=GENRE_CHOICES
)
183 situation_famille
= models
.CharField(max_length
=1, null
=True, blank
=True,
184 choices
=SITUATION_CHOICES
)
185 date_entree
= models
.DateField(verbose_name
="Date d'entrée à l'AUF",
186 null
=True, blank
=True)
189 tel_domicile
= models
.CharField(max_length
=255, null
=True, blank
=True)
190 tel_cellulaire
= models
.CharField(max_length
=255, null
=True, blank
=True)
191 adresse
= models
.CharField(max_length
=255, null
=True, blank
=True)
192 no_rue
= models
.CharField(max_length
=255, null
=True, blank
=True)
193 ville
= models
.CharField(max_length
=255, null
=True, blank
=True)
194 province
= models
.CharField(max_length
=255, null
=True, blank
=True)
195 code_postal
= models
.CharField(max_length
=255, null
=True, blank
=True)
196 pays
= models
.ForeignKey(ref
.Pays
, to_field
='code',
197 null
=True, blank
=True,
198 related_name
='employes', db_column
='pays')
201 date_creation
= models
.DateField(auto_now_add
=True)
202 date_maj
= models
.DateField(auto_now
=True) # date_modification
203 commentaire
= models
.TextField(null
=True, blank
=True)
205 def __unicode__(self
):
206 return u
'%s %s' % (self
.prenom
, self
.nom
)
208 class EmployePiece(models
.Model
):
209 """Documents relatifs à l'employé
212 employe
= models
.ForeignKey("Employe")
213 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
214 fichier
= models
.FileField(verbose_name
="Fichier",
215 upload_to
=dossier_piece_dispatch
,
216 storage
=storage_prive
)
219 LIEN_PARENTE_CHOICES
= (
220 ('Conjoint', 'Conjoint'),
221 ('Conjointe', 'Conjointe'),
226 class AyantDroit(models
.Model
):
228 id = models
.IntegerField(primary_key
=True)
229 nom
= models
.CharField(max_length
=255)
230 prenom
= models
.CharField(max_length
=255)
232 # date_naissance facultatif
236 employe
= models
.ForeignKey('Employe', db_column
='employe',
237 related_name
='ayants_droit')
238 lien_parente
= models
.CharField(max_length
=10, null
=True, blank
=True,
239 choices
=LIEN_PARENTE_CHOICES
)
242 commentaire
= models
.TextField(null
=True, blank
=True)
243 actif
= models
.BooleanField()
248 STATUT_RESIDENCE_CHOICES
= (
250 ('expat', 'Expatrié'),
253 COMPTE_COMPTA_CHOICES
= (
259 class Dossier(models
.Model
):
261 id = models
.IntegerField(primary_key
=True)
262 #code = models.CharField(max_length=10, unique=True)
263 employe
= models
.ForeignKey('Employe', db_column
='employe')
264 poste
= models
.ForeignKey('Poste', related_name
='+', editable
=False)
265 statut
= models
.ForeignKey('Statut', related_name
='+') # blank=True, null=True ?
266 organisme_bstg
= models
.ForeignKey('OrganismeBstg',
267 null
=True, blank
=True,
268 verbose_name
="Organisme",
269 help_text
="Si détaché (DET) ou mis à disposition (MAD), \
270 préciser l'organisme.",
274 remplacement
= models
.BooleanField() # default False
275 statut_residence
= models
.CharField(max_length
=10, default
='local',
276 verbose_name
="Statut",
277 choices
=STATUT_RESIDENCE_CHOICES
)
280 classement
= models
.ForeignKey(rh
.Classement
, related_name
='+')
281 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
282 verbose_name
="Régime de travail",
283 help_text
="% du temps complet") # default = 100
284 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
285 decimal_places
=2, verbose_name
="Nb. heures par semaine") # default = 35
287 # Occupation du Poste par cet Employe (anciennement "mandat")
288 date_debut
= models
.DateField(verbose_name
="Date de début d'occupation de poste")
289 date_fin
= models
.DateField(verbose_name
="Date de fin d'occupation de poste",
290 null
=True, blank
=True)
296 date_creation
= models
.DateTimeField(auto_now_add
=True)
297 date_modification
= models
.DateField(auto_now
=True)
298 commentaire
= models
.TextField(null
=True, blank
=True)
300 def __unicode__(self
):
301 return u
'%s - %s' % (self
.poste
.nom
, self
.employe
)
303 class DossierPiece(models
.Model
):
304 """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
305 Ex.: Lettre de motivation.
307 dossier
= models
.ForeignKey("Dossier")
308 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
309 fichier
= models
.FileField(verbose_name
="Fichier",
310 upload_to
=dossier_piece_dispatch
,
311 storage
=storage_prive
)
313 class DossierCommentaire(models
.Model
):
314 dossier
= models
.ForeignKey("Dossier")
315 commentaire
= models
.TextField(null
=True, blank
=True)
320 class Remuneration(models
.Model
):
322 id = models
.IntegerField(primary_key
=True)
323 dossier
= models
.ForeignKey('Dossier', db_column
='dossier')
324 type = models
.ForeignKey('TypeRemuneration', db_column
='type',
327 type_revalorisation
= models
.ForeignKey('TypeRevalorisation',
328 db_column
='type_revalorisation',
329 null
=True, blank
=True)
330 montant
= models
.FloatField(null
=True, blank
=True) # Annuel (12 mois, 52 semaines, 364 jours)
331 devise
= models
.ForeignKey('Devise', to_field
='code', db_column
='devise')#,
332 #null=True, blank=True)
333 precision
= models
.CharField(max_length
=255, null
=True, blank
=True) # precision = commentaire
334 date_debut
= models
.DateField(null
=True, blank
=True) # anciennement date_effectif
335 #date_fin = null=True
338 date_creation
= models
.DateField(auto_now_add
=True)
339 user_creation
= models
.IntegerField(null
=True, blank
=True) #User ou employé
340 # desactivation = models.BooleanField(null=True, blank=True) #
341 # date_desactivation = models.DateField(null=True, blank=True)
342 # user_desactivation = models.IntegerField(null=True, blank=True) #User ou employé
343 # annulation = models.BooleanField(null=True, blank=True)
344 # date_annulation = models.DateField(null=True, blank=True)
345 # user_annulation = models.IntegerField(null=True, blank=True) #User ou employé
347 def montant_mois(self
):
348 return round(self
.montant
/ 12, 2)
350 def taux_devise(self
):
351 return self
.devise
.tauxchange_set
.order_by('-annee').all()[0].taux
353 def montant_euro(self
):
354 return round(float(self
.montant
) / float(self
.taux_devise()), 2)
356 def montant_euro_mois(self
):
357 return round(self
.montant_euro() / 12, 2)
359 def __unicode__(self
):
361 devise
= self
.devise
.code
364 return "%s %s" % (self
.montant
, devise
)
366 class HistoriqueRemuneration(models
.Model
):
367 dossier
= models
.ForeignKey("Dossier")
368 # toujours pertinent si pour chaque Remuneration j'ai dd et df?
373 class FamilleEmploi(models
.Model
):
375 id = models
.IntegerField(primary_key
=True)
376 nom
= models
.CharField(max_length
=255)
378 actif
= models
.BooleanField()
380 class TypePoste(models
.Model
):
382 id = models
.IntegerField(primary_key
=True)
383 nom
= models
.CharField(max_length
=255)
384 nom_feminin
= models
.CharField(max_length
=255)
385 #description = models.CharField(max_length=255)
386 is_responsable
= models
.BooleanField()
387 famille_emploi
= models
.ForeignKey('FamilleEmploi',
388 db_column
='famille_emploi')
390 date_modification
= models
.DateField(auto_now
=True)
391 actif
= models
.BooleanField()
393 def __unicode__(self
):
394 return u
'%s' % self
.nom
397 TYPE_PAIEMENT_CHOICES
= (
398 ('Régulier', 'Régulier'),
399 ('Ponctuel', 'Ponctuel'),
402 NATURE_REMUNERATION_CHOICES
= (
403 ('Accessoire', 'Accessoire'),
404 ('Charges', 'Charges'),
405 ('Indemnité', 'Indemnité'),
406 ('RAS', 'Rémunération autre source'),
407 ('Traitement', 'Traitement'),
410 class TypeRemuneration(models
.Model
):
412 id = models
.IntegerField(primary_key
=True)
413 nom
= models
.CharField(max_length
=255)
414 type_paiement
= models
.CharField(max_length
=30,
415 choices
=TYPE_PAIEMENT_CHOICES
)
416 nature_remuneration
= models
.CharField(max_length
=30,
417 choices
=NATURE_REMUNERATION_CHOICES
)
419 actif
= models
.BooleanField()
421 def __unicode__(self
):
422 return u
'%s' % self
.nom
424 class TypeRevalorisation(models
.Model
):
425 """Justification du changement de la Remuneration.
426 (Actuellement utilisé dans aucun traitement informatique)
429 id = models
.IntegerField(primary_key
=True)
430 nom
= models
.CharField(max_length
=255)
432 actif
= models
.BooleanField()
434 class Service(models
.Model
):
436 id = models
.IntegerField(primary_key
=True)
437 nom
= models
.CharField(max_length
=255)
439 actif
= models
.BooleanField()
441 def __unicode__(self
):
442 return u
'%s' % self
.nom
448 TYPE_ORGANISME_CHOICES
= (
449 ('MAD', 'Mise à disposition'),
450 ('DET', 'Détachement'),
453 class OrganismeBstg(models
.Model
):
455 id = models
.IntegerField(primary_key
=True)
456 nom
= models
.CharField(max_length
=255)
457 type = models
.CharField(max_length
=10, choices
=TYPE_ORGANISME_CHOICES
)
461 actif
= models
.BooleanField()
463 def __unicode__(self
):
464 return u
'%s (%s)' % (self
.nom
, self
.type)
467 ordering
= ['type', 'nom']
470 CONTRAT_CATEGORIE_CHOICES
= (
475 class Statut(models
.Model
):
477 id = models
.IntegerField(primary_key
=True)
478 code
= models
.CharField(max_length
=25, unique
=True)
479 nom
= models
.CharField(max_length
=255)
480 type_contrat_categorie
= models
.CharField(max_length
=10,
481 choices
=CONTRAT_CATEGORIE_CHOICES
)
482 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
483 # A = AUF, C = Contractuel ???
485 actif
= models
.BooleanField()
487 def __unicode__(self
):
488 return u
'%s : %s' % (self
.code
, self
.nom
)
491 TYPE_CLASSEMENT_CHOICES
= (
496 class Classement(models
.Model
):
498 id = models
.IntegerField(primary_key
=True)
499 type = models
.CharField(max_length
=10, choices
=TYPE_CLASSEMENT_CHOICES
)
500 echelon
= models
.IntegerField()
501 degre
= models
.IntegerField()
502 coefficient
= models
.FloatField()
503 # annee # au lieu de date_debut et date_fin
505 commentaire
= models
.TextField(null
=True, blank
=True)
506 date_modification
= models
.DateField(auto_now
=True)
507 actif
= models
.BooleanField()
509 def __unicode__(self
):
510 return u
'%s.%s.%s (%s)' % (self
.type, self
.echelon
, self
.degre
,
513 ordering
= ['type','echelon','degre','coefficient']
515 class TauxChange(models
.Model
):
516 """Taux de change de la devise vers l'euro (EUR)
517 pour cette année budgétaire.
520 id = models
.IntegerField(primary_key
=True)
521 devise
= models
.ForeignKey('Devise', to_field
='code', db_column
='devise')
522 annee
= models
.IntegerField()
523 taux
= models
.FloatField()
525 class ValeurPoint(models
.Model
):
527 id = models
.IntegerField(primary_key
=True)
528 valeur
= models
.FloatField()
530 implantation
= models
.ForeignKey(ref
.Implantation
,
531 db_column
='implantation',
532 related_name
='valeurs_point')
534 annee
= models
.IntegerField()
536 # Stockage de tous les taux de change pour optimiser la recherche de la devise associée
537 annee_courante
= datetime
.datetime
.now().year
538 tauxchange
= TauxChange
.objects
.select_related('devise').filter(annee
=annee_courante
)
540 def __unicode__(self
):
541 tx
= self
.get_tauxchange_courant()
543 devise_code
= tx
.devise
.code
546 return u
'%s %s (%s-%s)' % (self
.valeur
, devise_code
, self
.implantation_id
, self
.annee
)
549 ordering
= ['valeur']
551 class Devise(models
.Model
):
552 id = models
.IntegerField(primary_key
=True)
553 code
= models
.CharField(max_length
=10, unique
=True)
554 nom
= models
.CharField(max_length
=255)
556 def __unicode__(self
):
557 return u
'%s - %s' % (self
.code
, self
.nom
)
559 class TypeContrat(models
.Model
):
561 id = models
.IntegerField(primary_key
=True)
562 nom
= models
.CharField(max_length
=255)
563 nom_long
= models
.CharField(max_length
=255) #description
564 categorie
= models
.CharField(max_length
=10,
565 choices
=CONTRAT_CATEGORIE_CHOICES
) # A, C?
567 actif
= models
.BooleanField()
569 def __unicode__(self
):
570 return u
'%s' % (self
.nom
)
572 class ResponsableImplantation(models
.Model
):
573 """Le responsable d'une implantation.
574 Anciennement géré sur le Dossier du responsable.
576 employe
= models
.ForeignKey('Employe', null
=True, blank
=True)
577 implantation
= models
.ForeignKey(ref
.Implantation
, unique
=True)
579 def __unicode__(self
):
580 return u
'%s : %s' % (self
.implantation
, self
.employe
)
583 ordering
= ['implantation__nom']
585 class Contrat(models
.Model
):
586 dossier
= models
.ForeignKey("Dossier") # 1 contrat peut être dans plusieurs dossier Dossier.contrat = m2m Contrat
587 type_contrat
= models
.ForeignKey('TypeContrat', related_name
='+')
588 date_debut
= models
.DateField(help_text
="format: aaaa-mm-jj")
589 date_fin
= models
.DateField(null
=True, blank
=True,
590 help_text
="format: aaaa-mm-jj")
592 class Evenement(models
.Models
):
598 class EvenementRemuneration(models
.Model
):
601 # structure de rémunération hérité de abstract ici