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
)
25 class Commentaire(models
.Model
):
26 texte
= models
.TextField()
28 date_creation
= models
.DateTimeField(auto_now_add
=True)
29 date_modification
= models
.DateField(auto_now
=True)
30 owner
= models
.ForeignKey("auth.User")
31 actif
= models
.BooleanField()
37 HELP_TEXT_DATE
= "format: aaaa-mm-jj"
42 POSTE_APPEL_CHOICES
= (
43 ('interne', 'Interne'),
44 ('externe', 'Externe'),
47 class Poste(models
.Model
):
49 id = models
.IntegerField(primary_key
=True)
50 nom
= models
.CharField(verbose_name
="Titre du poste", max_length
=255)
51 nom_feminin
= models
.CharField(verbose_name
="Titre du poste", max_length
=255)
52 implantation
= models
.ForeignKey(ref
.Implantation
)
53 type_poste
= models
.ForeignKey(rh
.TypePoste
, null
=True, related_name
='+')
54 service
= models
.ForeignKey(rh
.Service
, related_name
='+',
55 verbose_name
=u
"Direction/Service/Pôle support")
56 responsable
= models
.ForeignKey(rh
.Poste
, related_name
='+',
57 verbose_name
="Poste du responsable")
60 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
62 verbose_name
="Temps de travail",
63 help_text
="% du temps complet")
64 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
67 verbose_name
="Nb. heures par semaine")
70 local
= models
.BooleanField(verbose_name
="Local", default
=True, blank
=True)
71 expatrie
= models
.BooleanField(verbose_name
="Expatrié", default
=False,
75 mise_a_disposition
= models
.BooleanField(verbose_name
="Mise à disposition")
76 appel
= models
.CharField(max_length
=10, default
='interne',
77 verbose_name
="Appel à candidature",
78 choices
=POSTE_APPEL_CHOICES
)
81 classement_min
= models
.ForeignKey(rh
.Classement
, related_name
='+',
82 blank
=True, null
=True)
83 classement_max
= models
.ForeignKey(rh
.Classement
, related_name
='+',
84 blank
=True, null
=True)
85 valeur_point_min
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+',
86 blank
=True, null
=True)
87 valeur_point_max
= models
.ForeignKey(rh
.ValeurPoint
, related_name
='+',
88 blank
=True, null
=True)
89 devise_min
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
90 devise_max
= models
.ForeignKey(rh
.Devise
, default
=5, related_name
='+')
91 salaire_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
93 salaire_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
95 indemn_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
97 indemn_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
99 autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
101 autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
104 # Comparatifs de rémunération
105 devise_comparaison
= models
.ForeignKey(rh
.Devise
, related_name
='+',
107 comp_locale_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
108 null
=True, blank
=True)
109 comp_locale_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
110 null
=True, blank
=True)
111 comp_universite_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
112 null
=True, blank
=True)
113 comp_universite_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
114 null
=True, blank
=True)
115 comp_fonctionpub_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
116 null
=True, blank
=True)
117 comp_fonctionpub_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
118 null
=True, blank
=True)
119 comp_ong_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
120 null
=True, blank
=True)
121 comp_ong_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
122 null
=True, blank
=True)
123 comp_autre_min
= models
.DecimalField(max_digits
=12, decimal_places
=2,
124 null
=True, blank
=True)
125 comp_autre_max
= models
.DecimalField(max_digits
=12, decimal_places
=2,
126 null
=True, blank
=True)
129 justification
= models
.TextField()
132 date_validation
= models
.DateTimeField(null
=True, blank
=True) # de dae
133 date_creation
= models
.DateTimeField(auto_now_add
=True)
134 date_modification
= models
.DateTimeField(auto_now
=True)
135 date_debut
= models
.DateField(verbose_name
="Date de début",
136 help_text
=HELP_TEXT_DATE
)
137 date_fin
= models
.DateField(null
=True, blank
=True,
138 verbose_name
="Date de fin",
140 actif
= models
.BooleanField(default
=True)
142 def __unicode__(self
):
143 # gérer si poste est vacant ou non dans affichage
144 return u
'%s - %s [%s]' % (self
.implantation
, self
.nom
, self
.id)
147 POSTE_FINANCEMENT_CHOICES
= (
148 ('A', 'A - Frais de personnel'),
149 ('B', 'B - Projet(s)-Titre(s)'),
153 class PosteFinancement(models
.Model
):
154 poste
= models
.ForeignKey('Poste', related_name
='financements')
155 type = models
.CharField(max_length
=1, choices
=POSTE_FINANCEMENT_CHOICES
)
156 pourcentage
= models
.DecimalField(max_digits
=12, decimal_places
=2,
157 help_text
="ex.: 33.33 % (décimale avec point)")
158 commentaire
= models
.TextField(
159 help_text
="Spécifiez la source de financement.")
164 class PostePiece(models
.Model
):
165 """Documents relatifs au Poste
166 Ex.: Description de poste
168 poste
= models
.ForeignKey("Poste")
169 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
170 fichier
= models
.FileField(verbose_name
="Fichier",
171 upload_to
=poste_piece_dispatch
,
172 storage
=storage_prive
)
174 class PosteCommentaire(Commentaire
):
175 poste
= models
.ForeignKey("Poste")
183 SITUATION_CHOICES
= (
184 ('C', 'Célibataire'),
189 class Employe(models
.Model
):
191 id = models
.IntegerField(primary_key
=True)
192 nom
= models
.CharField(max_length
=255)
193 prenom
= models
.CharField(max_length
=255)
194 nationalite
= models
.ForeignKey(ref
.Pays
, to_field
='code',
195 related_name
='employes_nationalite',
196 db_column
='nationalite')
197 date_naissance
= models
.DateField(null
=True, blank
=True)
200 genre
= models
.CharField(max_length
=1, choices
=GENRE_CHOICES
)
201 situation_famille
= models
.CharField(max_length
=1, null
=True, blank
=True,
202 choices
=SITUATION_CHOICES
)
203 date_entree
= models
.DateField(verbose_name
="Date d'entrée à l'AUF",
204 null
=True, blank
=True)
207 tel_domicile
= models
.CharField(max_length
=255, null
=True, blank
=True)
208 tel_cellulaire
= models
.CharField(max_length
=255, null
=True, blank
=True)
209 adresse
= models
.CharField(max_length
=255, null
=True, blank
=True)
210 no_rue
= models
.CharField(max_length
=255, null
=True, blank
=True)
211 ville
= models
.CharField(max_length
=255, null
=True, blank
=True)
212 province
= models
.CharField(max_length
=255, null
=True, blank
=True)
213 code_postal
= models
.CharField(max_length
=255, null
=True, blank
=True)
214 pays
= models
.ForeignKey(ref
.Pays
, to_field
='code',
215 null
=True, blank
=True,
216 related_name
='employes', db_column
='pays')
219 date_creation
= models
.DateField(auto_now_add
=True)
220 date_maj
= models
.DateField(auto_now
=True) # date_modification
222 def __unicode__(self
):
223 return u
'%s %s' % (self
.prenom
, self
.nom
)
225 class EmployePiece(models
.Model
):
226 """Documents relatifs à l'employé
229 employe
= models
.ForeignKey("Employe")
230 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
231 fichier
= models
.FileField(verbose_name
="Fichier",
232 upload_to
=dossier_piece_dispatch
,
233 storage
=storage_prive
)
235 class EmployeCommentaire(Commentaire
):
236 employe
= models
.ForeignKey("Employe")
238 LIEN_PARENTE_CHOICES
= (
239 ('Conjoint', 'Conjoint'),
240 ('Conjointe', 'Conjointe'),
245 class AyantDroit(models
.Model
):
247 id = models
.IntegerField(primary_key
=True)
248 nom
= models
.CharField(max_length
=255)
249 prenom
= models
.CharField(max_length
=255)
251 # date_naissance facultatif
255 employe
= models
.ForeignKey('Employe', db_column
='employe',
256 related_name
='ayants_droit')
257 lien_parente
= models
.CharField(max_length
=10, null
=True, blank
=True,
258 choices
=LIEN_PARENTE_CHOICES
)
261 commentaire
= models
.TextField(null
=True, blank
=True)
262 actif
= models
.BooleanField()
264 class AyantDroitCommentaire(Commentaire
):
265 ayant_droit
= models
.ForeignKey("AyantDroit")
269 STATUT_RESIDENCE_CHOICES
= (
271 ('expat', 'Expatrié'),
274 COMPTE_COMPTA_CHOICES
= (
280 class Dossier(models
.Model
):
282 id = models
.IntegerField(primary_key
=True)
283 #code = models.CharField(max_length=10, unique=True)
284 employe
= models
.ForeignKey('Employe', db_column
='employe')
285 poste
= models
.ForeignKey('Poste', related_name
='+', editable
=False)
286 statut
= models
.ForeignKey('Statut', related_name
='+') # blank=True, null=True ?
287 organisme_bstg
= models
.ForeignKey('OrganismeBstg',
288 null
=True, blank
=True,
289 verbose_name
="Organisme",
290 help_text
="Si détaché (DET) ou mis à disposition (MAD), \
291 préciser l'organisme.",
295 remplacement
= models
.BooleanField() # default False
296 statut_residence
= models
.CharField(max_length
=10, default
='local',
297 verbose_name
="Statut",
298 choices
=STATUT_RESIDENCE_CHOICES
)
301 classement
= models
.ForeignKey(rh
.Classement
, related_name
='+',
302 null
=True, blank
=True)
303 regime_travail
= models
.DecimalField(max_digits
=12, decimal_places
=2,
304 verbose_name
="Régime de travail",
305 help_text
="% du temps complet") # default = 100
306 regime_travail_nb_heure_semaine
= models
.DecimalField(max_digits
=12,
307 decimal_places
=2, verbose_name
="Nb. heures par semaine") # default = 35
309 # Occupation du Poste par cet Employe (anciennement "mandat")
310 date_debut
= models
.DateField(help_text
=HELP_TEXT_DATE
,
311 verbose_name
="Date de début d'occupation de poste")
312 date_fin
= models
.DateField(help_text
=HELP_TEXT_DATE
,
313 null
=True, blank
=True,
314 verbose_name
="Date de fin d'occupation de poste")
316 date_debut
= models
.DateField(verbose_name
="Date de début",
317 help_text
=HELP_TEXT_DATE
)
318 date_fin
= models
.DateField(null
=True, blank
=True,
319 verbose_name
="Date de fin",
320 help_text
=HELP_TEXT_DATE
)
325 date_creation
= models
.DateTimeField(auto_now_add
=True)
326 date_modification
= models
.DateField(auto_now
=True)
328 def __unicode__(self
):
329 return u
'%s - %s' % (self
.poste
.nom
, self
.employe
)
331 class DossierPiece(models
.Model
):
332 """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
333 Ex.: Lettre de motivation.
335 dossier
= models
.ForeignKey("Dossier")
336 nom
= models
.CharField(verbose_name
="Nom", max_length
=255)
337 fichier
= models
.FileField(verbose_name
="Fichier",
338 upload_to
=dossier_piece_dispatch
,
339 storage
=storage_prive
)
341 class DossierCommentaire(Commentaire
):
342 dossier
= models
.ForeignKey("Dossier")
346 class Remuneration(models
.Model
):
348 id = models
.IntegerField(primary_key
=True)
349 dossier
= models
.ForeignKey('Dossier', db_column
='dossier')
350 type = models
.ForeignKey('TypeRemuneration', db_column
='type',
353 type_revalorisation
= models
.ForeignKey('TypeRevalorisation',
354 db_column
='type_revalorisation',
355 null
=True, blank
=True)
356 montant
= models
.FloatField(null
=True, blank
=True) # Annuel (12 mois, 52 semaines, 364 jours)
357 devise
= models
.ForeignKey('Devise', to_field
='code', db_column
='devise')#,
358 #null=True, blank=True)
359 commentaire
= models
.CharField(max_length
=255, null
=True, blank
=True) # commentaire = precision
360 date_debut
= models
.DateField(null
=True, blank
=True) # anciennement date_effectif
361 #date_fin = null=True
364 date_creation
= models
.DateField(auto_now_add
=True)
365 user_creation
= models
.IntegerField(null
=True, blank
=True) #User ou employé
366 # desactivation = models.BooleanField(null=True, blank=True) #
367 # date_desactivation = models.DateField(null=True, blank=True)
368 # user_desactivation = models.IntegerField(null=True, blank=True) #User ou employé
369 # annulation = models.BooleanField(null=True, blank=True)
370 # date_annulation = models.DateField(null=True, blank=True)
371 # user_annulation = models.IntegerField(null=True, blank=True) #User ou employé
373 def montant_mois(self
):
374 return round(self
.montant
/ 12, 2)
376 def taux_devise(self
):
377 return self
.devise
.tauxchange_set
.order_by('-annee').all()[0].taux
379 def montant_euro(self
):
380 return round(float(self
.montant
) / float(self
.taux_devise()), 2)
382 def montant_euro_mois(self
):
383 return round(self
.montant_euro() / 12, 2)
385 def __unicode__(self
):
387 devise
= self
.devise
.code
390 return "%s %s" % (self
.montant
, devise
)
392 class HistoriqueRemuneration(models
.Model
):
393 dossier
= models
.ForeignKey("Dossier")
394 # toujours pertinent si pour chaque Remuneration j'ai dd et df?
399 class FamilleEmploi(models
.Model
):
401 id = models
.IntegerField(primary_key
=True)
402 nom
= models
.CharField(max_length
=255)
404 actif
= models
.BooleanField()
406 class TypePoste(models
.Model
):
408 id = models
.IntegerField(primary_key
=True)
409 nom
= models
.CharField(max_length
=255)
410 nom_feminin
= models
.CharField(max_length
=255)
411 #description = models.CharField(max_length=255)
412 is_responsable
= models
.BooleanField()
413 famille_emploi
= models
.ForeignKey('FamilleEmploi',
414 db_column
='famille_emploi')
416 date_modification
= models
.DateField(auto_now
=True)
417 actif
= models
.BooleanField()
419 def __unicode__(self
):
420 return u
'%s' % self
.nom
423 TYPE_PAIEMENT_CHOICES
= (
424 ('Régulier', 'Régulier'),
425 ('Ponctuel', 'Ponctuel'),
428 NATURE_REMUNERATION_CHOICES
= (
429 ('Accessoire', 'Accessoire'),
430 ('Charges', 'Charges'),
431 ('Indemnité', 'Indemnité'),
432 ('RAS', 'Rémunération autre source'),
433 ('Traitement', 'Traitement'),
436 class TypeRemuneration(models
.Model
):
438 id = models
.IntegerField(primary_key
=True)
439 nom
= models
.CharField(max_length
=255)
440 type_paiement
= models
.CharField(max_length
=30,
441 choices
=TYPE_PAIEMENT_CHOICES
)
442 nature_remuneration
= models
.CharField(max_length
=30,
443 choices
=NATURE_REMUNERATION_CHOICES
)
445 actif
= models
.BooleanField()
447 def __unicode__(self
):
448 return u
'%s' % self
.nom
450 class TypeRevalorisation(models
.Model
):
451 """Justification du changement de la Remuneration.
452 (Actuellement utilisé dans aucun traitement informatique)
455 id = models
.IntegerField(primary_key
=True)
456 nom
= models
.CharField(max_length
=255)
458 actif
= models
.BooleanField()
460 class Service(models
.Model
):
462 id = models
.IntegerField(primary_key
=True)
463 nom
= models
.CharField(max_length
=255)
465 actif
= models
.BooleanField()
467 def __unicode__(self
):
468 return u
'%s' % self
.nom
474 TYPE_ORGANISME_CHOICES
= (
475 ('MAD', 'Mise à disposition'),
476 ('DET', 'Détachement'),
479 class OrganismeBstg(models
.Model
):
481 id = models
.IntegerField(primary_key
=True)
482 nom
= models
.CharField(max_length
=255)
483 type = models
.CharField(max_length
=10, choices
=TYPE_ORGANISME_CHOICES
)
487 actif
= models
.BooleanField()
489 def __unicode__(self
):
490 return u
'%s (%s)' % (self
.nom
, self
.type)
493 ordering
= ['type', 'nom']
496 CONTRAT_CATEGORIE_CHOICES
= (
501 class Statut(models
.Model
):
503 id = models
.IntegerField(primary_key
=True)
504 code
= models
.CharField(max_length
=25, unique
=True)
505 nom
= models
.CharField(max_length
=255)
506 type_contrat_categorie
= models
.CharField(max_length
=10,
507 choices
=CONTRAT_CATEGORIE_CHOICES
)
508 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
509 # A = AUF, C = Contractuel ???
511 actif
= models
.BooleanField()
513 def __unicode__(self
):
514 return u
'%s : %s' % (self
.code
, self
.nom
)
517 TYPE_CLASSEMENT_CHOICES
= (
522 class Classement(models
.Model
):
524 id = models
.IntegerField(primary_key
=True)
525 type = models
.CharField(max_length
=10, choices
=TYPE_CLASSEMENT_CHOICES
)
526 echelon
= models
.IntegerField()
527 degre
= models
.IntegerField()
528 coefficient
= models
.FloatField()
529 # annee # au lieu de date_debut et date_fin
531 commentaire
= models
.TextField(null
=True, blank
=True)
532 date_modification
= models
.DateField(auto_now
=True)
533 actif
= models
.BooleanField()
535 def __unicode__(self
):
536 return u
'%s.%s.%s (%s)' % (self
.type, self
.echelon
, self
.degre
,
539 ordering
= ['type','echelon','degre','coefficient']
541 class TauxChange(models
.Model
):
542 """Taux de change de la devise vers l'euro (EUR)
543 pour cette année budgétaire.
546 id = models
.IntegerField(primary_key
=True)
547 devise
= models
.ForeignKey('Devise', to_field
='code', db_column
='devise')
548 annee
= models
.IntegerField()
549 taux
= models
.FloatField()
551 class ValeurPoint(models
.Model
):
553 id = models
.IntegerField(primary_key
=True)
554 valeur
= models
.FloatField()
556 implantation
= models
.ForeignKey(ref
.Implantation
,
557 db_column
='implantation',
558 related_name
='valeurs_point')
560 annee
= models
.IntegerField()
562 # Stockage de tous les taux de change pour optimiser la recherche de la devise associée
563 annee_courante
= datetime
.datetime
.now().year
564 tauxchange
= TauxChange
.objects
.select_related('devise').filter(annee
=annee_courante
)
566 def __unicode__(self
):
567 tx
= self
.get_tauxchange_courant()
569 devise_code
= tx
.devise
.code
572 return u
'%s %s (%s-%s)' % (self
.valeur
, devise_code
, self
.implantation_id
, self
.annee
)
575 ordering
= ['valeur']
577 class Devise(models
.Model
):
578 id = models
.IntegerField(primary_key
=True)
579 code
= models
.CharField(max_length
=10, unique
=True)
580 nom
= models
.CharField(max_length
=255)
582 def __unicode__(self
):
583 return u
'%s - %s' % (self
.code
, self
.nom
)
585 class TypeContrat(models
.Model
):
587 id = models
.IntegerField(primary_key
=True)
588 nom
= models
.CharField(max_length
=255)
589 nom_long
= models
.CharField(max_length
=255) #description
590 categorie
= models
.CharField(max_length
=10,
591 choices
=CONTRAT_CATEGORIE_CHOICES
) # A, C?
593 actif
= models
.BooleanField()
595 def __unicode__(self
):
596 return u
'%s' % (self
.nom
)
598 class ResponsableImplantation(models
.Model
):
599 """Le responsable d'une implantation.
600 Anciennement géré sur le Dossier du responsable.
602 employe
= models
.ForeignKey('Employe', null
=True, blank
=True)
603 implantation
= models
.ForeignKey(ref
.Implantation
, unique
=True)
605 def __unicode__(self
):
606 return u
'%s : %s' % (self
.implantation
, self
.employe
)
609 ordering
= ['implantation__nom']
611 class Contrat(models
.Model
):
612 dossier
= models
.ForeignKey("Dossier") # 1 contrat peut être dans plusieurs dossier Dossier.contrat = m2m Contrat
613 type_contrat
= models
.ForeignKey('TypeContrat', related_name
='+')
614 date_debut
= models
.DateField(help_text
=HELP_TEXT_DATE
)
615 date_fin
= models
.DateField(null
=True, blank
=True,
616 help_text
=HELP_TEXT_DATE
)
618 class Evenement(models
.Models
):
624 class EvenementRemuneration(models
.Model
):
627 # structure de rémunération hérité de abstract ici