modeles responsable implantation
[auf_rh_dae.git] / project / rh / models.py
CommitLineData
e9bbd6ba 1# -=- encoding: utf-8 -=-
2
9afaa55e 3import datetime
83b7692b 4
5from django.core.files.storage import FileSystemStorage
49f9f116 6from django.db import models
83b7692b 7import settings
8
9import datamaster_modeles.models as ref
10
11
12# Upload de fichiers
13storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT,
14 base_url=settings.PRIVE_MEDIA_URL)
15
16def poste_piece_dispatch(instance, filename):
17 path = "poste/%s/%s" % (instance.poste_id, filename)
18 return path
19
20def dossier_piece_dispatch(instance, filename):
21 path = "dossier/%s/%s" % (instance.dossier_id, filename)
22 return path
23
24
25### POSTE
26
27POSTE_APPEL_CHOICES = (
28 ('interne', 'Interne'),
29 ('externe', 'Externe'),
30)
31
32class Poste(models.Model):
33 # Identification
34 id = models.IntegerField(primary_key=True)
35 nom = models.CharField(verbose_name="Titre du poste", max_length=255)
36 implantation = models.ForeignKey(ref.Implantation)
37 type_poste = models.ForeignKey(rh.TypePoste, null=True, related_name='+')
38 service = models.ForeignKey(rh.Service, related_name='+',
39 verbose_name=u"Direction/Service/Pôle support")
40 responsable = models.ForeignKey(rh.Poste, related_name='+',
41 verbose_name="Poste du responsable")
42
43 # Contrat
44 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
45 default=100,
46 verbose_name="Temps de travail",
47 help_text="% du temps complet")
48 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
49 decimal_places=2,
50 default=35,
51 verbose_name="Nb. heures par semaine")
52
53 # Recrutement
54 local = models.BooleanField(verbose_name="Local", default=True, blank=True)
55 expatrie = models.BooleanField(verbose_name="Expatrié", default=False,
56 blank=True)
57
58 # TODO null?
59 mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
60 appel = models.CharField(max_length=10, default='interne',
61 verbose_name="Appel à candidature",
62 choices=POSTE_APPEL_CHOICES)
63
64 # Rémunération
65 classement_min = models.ForeignKey(rh.Classement, related_name='+')
66 classement_max = models.ForeignKey(rh.Classement, related_name='+')
67 valeur_point_min = models.ForeignKey(rh.ValeurPoint, related_name='+',
68 blank=True, null=True)
69 valeur_point_max = models.ForeignKey(rh.ValeurPoint, related_name='+',
70 blank=True, null=True)
71 devise_min = models.ForeignKey(rh.Devise, default=5, related_name='+')
72 devise_max = models.ForeignKey(rh.Devise, default=5, related_name='+')
73 salaire_min = models.DecimalField(max_digits=12, decimal_places=2,
74 default=0)
75 salaire_max = models.DecimalField(max_digits=12, decimal_places=2,
76 default=0)
77 indemn_min = models.DecimalField(max_digits=12, decimal_places=2,
78 default=0)
79 indemn_max = models.DecimalField(max_digits=12, decimal_places=2,
80 default=0)
81 autre_min = models.DecimalField(max_digits=12, decimal_places=2,
82 default=0)
83 autre_max = models.DecimalField(max_digits=12, decimal_places=2,
84 default=0)
85
86 # Comparatifs de rémunération
87 devise_comparaison = models.ForeignKey(rh.Devise, related_name='+',
88 default=5)
89 comp_locale_min = models.DecimalField(max_digits=12, decimal_places=2,
90 null=True, blank=True)
91 comp_locale_max = models.DecimalField(max_digits=12, decimal_places=2,
92 null=True, blank=True)
93 comp_universite_min = models.DecimalField(max_digits=12, decimal_places=2,
94 null=True, blank=True)
95 comp_universite_max = models.DecimalField(max_digits=12, decimal_places=2,
96 null=True, blank=True)
97 comp_fonctionpub_min = models.DecimalField(max_digits=12, decimal_places=2,
98 null=True, blank=True)
99 comp_fonctionpub_max = models.DecimalField(max_digits=12, decimal_places=2,
100 null=True, blank=True)
101 comp_ong_min = models.DecimalField(max_digits=12, decimal_places=2,
102 null=True, blank=True)
103 comp_ong_max = models.DecimalField(max_digits=12, decimal_places=2,
104 null=True, blank=True)
105 comp_autre_min = models.DecimalField(max_digits=12, decimal_places=2,
106 null=True, blank=True)
107 comp_autre_max = models.DecimalField(max_digits=12, decimal_places=2,
108 null=True, blank=True)
109
110 # Justification
111 justification = models.TextField()
112
113 # Méta
114 date_validation = models.DateTimeField() #dae
115 date_creation = models.DateTimeField(auto_now_add=True)
116 date_modification = models.DateTimeField(auto_now=True)
117 date_debut = models.DateField(verbose_name="Date de début",
118 help_text="format: aaaa-mm-jj")
119 date_fin = models.DateField(null=True, blank=True,
120 verbose_name="Date de fin",
121 help_text="format: aaaa-mm-jj")
122 actif = models.BooleanField(default=True)
123
124 def __unicode__(self):
125 # gérer si poste est vacant ou non dans affichage
126 return u'%s - %s [%s]' % (self.implantation, self.nom, self.id)
127
128
129POSTE_FINANCEMENT_CHOICES = (
130 ('A', 'A - Frais de personnel'),
131 ('B', 'B - Projet(s)-Titre(s)'),
132 ('C', 'C - Autre')
133)
134
135class PosteFinancement(models.Model):
136 poste = models.ForeignKey('Poste', related_name='financements')
137 type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
138 pourcentage = models.DecimalField(max_digits=12, decimal_places=2,
139 help_text="ex.: 33.33 % (décimale avec point)")
140 commentaire = models.TextField(
141 help_text="Spécifiez la source de financement.")
142
143 class Meta:
144 ordering = ['type']
145
146class PostePiece(models.Model):
147 poste = models.ForeignKey("Poste")
148 nom = models.CharField(verbose_name="Nom", max_length=255)
149 fichier = models.FileField(verbose_name="Fichier",
150 upload_to=poste_piece_dispatch,
151 storage=storage_prive)
152
153
154### EMPLOYÉ/PERSONNE
e9bbd6ba 155
156GENRE_CHOICES = (
157 ('M', 'Homme'),
158 ('F', 'Femme'),
159)
160SITUATION_CHOICES = (
161 ('C', 'Célibataire'),
162 ('F', 'Fiancé'),
163 ('M', 'Marié'),
164)
165
83b7692b 166class Employe(models.Model):
9afaa55e 167 # Identification
e9bbd6ba 168 id = models.IntegerField(primary_key=True)
169 nom = models.CharField(max_length=255)
170 prenom = models.CharField(max_length=255)
83b7692b 171 nationalite = models.ForeignKey(ref.Pays, to_field='code',
9afaa55e 172 related_name='employes_nationalite',
173 db_column='nationalite')
e9bbd6ba 174 date_naissance = models.DateField(null=True, blank=True)
83b7692b 175
9afaa55e 176 # Infos personnelles
177 genre = models.CharField(max_length=1, null=True, blank=True,
178 choices=GENRE_CHOICES)
179 situation_famille = models.CharField(max_length=1, null=True, blank=True,
180 choices=SITUATION_CHOICES)
e9bbd6ba 181 date_entree = models.DateField(null=True, blank=True) #devrait pas être là
83b7692b 182
9afaa55e 183 # Coordonnées
e9bbd6ba 184 tel_domicile = models.CharField(max_length=255, null=True, blank=True)
185 tel_cellulaire = models.CharField(max_length=255, null=True, blank=True)
186 adresse = models.CharField(max_length=255, null=True, blank=True)
187 no_rue = models.CharField(max_length=255, null=True, blank=True)
188 ville = models.CharField(max_length=255, null=True, blank=True)
189 province = models.CharField(max_length=255, null=True, blank=True)
190 code_postal = models.CharField(max_length=255, null=True, blank=True)
83b7692b 191 pays = models.ForeignKey(ref.Pays, to_field='code',
9afaa55e 192 null=True, blank=True,
193 related_name='employes', db_column='pays')
83b7692b 194
9afaa55e 195 # Métas
e9bbd6ba 196 date_creation = models.DateField(auto_now_add=True)
197 date_maj = models.DateField(auto_now=True)
198 commentaire = models.TextField(null=True, blank=True)
9afaa55e 199
200 def __unicode__(self):
201 return u'%s %s' % (self.prenom, self.nom)
202
203
e9bbd6ba 204LIEN_PARENTE_CHOICES = (
205 ('Conjoint', 'Conjoint'),
206 ('Conjointe', 'Conjointe'),
207 ('Fille', 'Fille'),
208 ('Fils', 'Fils'),
209)
210
211class AyantDroit(models.Model):
9afaa55e 212 # Identification
e9bbd6ba 213 id = models.IntegerField(primary_key=True)
214 nom = models.CharField(max_length=255)
215 prenom = models.CharField(max_length=255)
83b7692b 216
9afaa55e 217 # Relation
218 employe = models.ForeignKey('Employe', db_column='employe',
219 related_name='ayants_droit')
220 lien_parente = models.CharField(max_length=10, null=True, blank=True,
221 choices=LIEN_PARENTE_CHOICES)
83b7692b 222
9afaa55e 223 # Méta
e9bbd6ba 224 commentaire = models.TextField(null=True, blank=True)
225 actif = models.BooleanField()
83b7692b 226
227
228### DOSSIER
229
230STATUT_RESIDENCE_CHOICES = (
231 ('local', 'Local'),
232 ('expat', 'Expatrié'),
233)
234
235COMPTE_COMPTA_CHOICES = (
236 ('coda', 'CODA'),
237 ('scs', 'SCS'),
238 ('aucun', 'Aucun'),
239)
240
241class Dossier(models.Model):
242 # Identification
243 id = models.IntegerField(primary_key=True)
244 #code = models.CharField(max_length=10, unique=True)
245 employe = models.ForeignKey('Employe', db_column='employe')
246 poste = models.ForeignKey('Poste', related_name='+', editable=False)
247 #responsable_implantation1 = models.IntegerField()
248 statut = models.ForeignKey('Statut', related_name='+') # blank=True, null=True ?
249 organisme_bstg = models.ForeignKey('OrganismeBstg',
250 null=True, blank=True,
251 verbose_name="Organisme",
252 help_text="Si détaché (DET) ou mis à disposition (MAD), \
253 préciser l'organisme.",
254 related_name='+')
255 organisme_bstg_autre = models.CharField(max_length=255,
256 verbose_name="Autre organisme",
257 help_text="indiquer l'organisme ici s'il n'est pas dans la liste",
258 null=True,
259 blank=True,)
260
261 # Recrutement
262 remplacement = models.BooleanField()
263 #remplacement_de = models.ForeignKey('Employe', db_column='remplacement_de',
264# related_name='replaced_by',
265# blank=True, null=True)
266 statut_residence = models.CharField(max_length=10, default='local',
267 verbose_name="Statut",
268 choices=STATUT_RESIDENCE_CHOICES)
269
270 # Rémunération
271 classement = models.ForeignKey(rh.Classement, related_name='+',
272 verbose_name='Classement proposé')
273 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
274 verbose_name="Régime de travail",
275 help_text="% du temps complet")
276 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
277 decimal_places=2, verbose_name="Nb. heures par semaine")
278
279 # Mandat
280# mandat_date_debut = models.DateField()
281# mandat_date_fin = models.DateField(null=True, blank=True)
282 # Contrat
283 type_contrat = models.ForeignKey('TypeContrat', related_name='+')
284 contrat_date_debut = models.DateField(help_text="format: aaaa-mm-jj")
285 contrat_date_fin = models.DateField(null=True, blank=True,
286 help_text="format: aaaa-mm-jj")
287 # Comptes
288 compte_compta = models.CharField(max_length=10, default='aucun',
289 verbose_name=u'Compte comptabilité',
290 choices=COMPTE_COMPTA_CHOICES)
291 compte_courriel = models.BooleanField()
e9bbd6ba 292
83b7692b 293 # Méta
294 date_creation = models.DateTimeField(auto_now_add=True)
295 date_modification = models.DateField(auto_now=True)
296 commentaire = models.TextField(null=True, blank=True)
297
298 def __unicode__(self):
299 return u'%s - %s' % (self.poste.nom, self.employe)
300
301class DossierPiece(models.Model):
302 dossier = models.ForeignKey("Dossier")
303 nom = models.CharField(verbose_name="Nom", max_length=255)
304 fichier = models.FileField(verbose_name="Fichier",
305 upload_to=dossier_piece_dispatch,
306 storage=storage_prive)
307
308
309### RÉMUNÉRATION
e9bbd6ba 310
311class Remuneration(models.Model):
9afaa55e 312 # Identification
e9bbd6ba 313 id = models.IntegerField(primary_key=True)
314 dossier = models.ForeignKey('Dossier', db_column='dossier')
83b7692b 315 type = models.ForeignKey('TypeRemuneration', db_column='type',
316 related_name='+')
317 # TODO: what's that?
318# type_revalorisation = models.ForeignKey('TypeRevalorisation',
319# db_column='type_revalorisation',
320# null=True, blank=True)
321 montant = models.FloatField(null=True, blank=True) # Annuel
322 devise = models.ForeignKey('Devise', to_field='code', db_column='devise')#,
323 #null=True, blank=True)
324 precision = models.CharField(max_length=255, null=True, blank=True)
325 #date_effective = models.DateField(null=True, blank=True)
326 #pourcentage = models.IntegerField(null=True, blank=True)
327
9afaa55e 328 # Méta
e9bbd6ba 329 date_creation = models.DateField(auto_now_add=True)
9afaa55e 330 user_creation = models.IntegerField(null=True, blank=True) #User ou employé
83b7692b 331# desactivation = models.BooleanField(null=True, blank=True) #
332# date_desactivation = models.DateField(null=True, blank=True)
333# user_desactivation = models.IntegerField(null=True, blank=True) #User ou employé
334# annulation = models.BooleanField(null=True, blank=True)
335# date_annulation = models.DateField(null=True, blank=True)
336# user_annulation = models.IntegerField(null=True, blank=True) #User ou employé
337
338 def montant_mois(self):
339 return round(self.montant / 12, 2)
340
341 def taux_devise(self):
342 return self.devise.tauxchange_set.order_by('-annee').all()[0].taux
343
344 def montant_euro(self):
345 return round(float(self.montant) / float(self.taux_devise()), 2)
346
347 def montant_euro_mois(self):
348 return round(self.montant_euro() / 12, 2)
9afaa55e 349
350 def __unicode__(self):
351 try:
352 devise = self.devise.code
353 except:
354 devise = "???"
355 return "%s %s" % (self.montant, devise)
83b7692b 356
357
358### JUSTIFICATIONS
359
360TYPE_JUSTIFICATIONS = (
361 ('N', 'Nouvel employé'),
362 ('R', 'Renouvellement employé'),
363)
364
365class JustificationQuestion(models.Model):
366 question = models.CharField(max_length=255)
367 type = models.CharField(max_length=255, choices=TYPE_JUSTIFICATIONS)
e9bbd6ba 368
83b7692b 369 def __unicode__(self,):
370 return self.question
371
372class JustificationNouvelEmploye(models.Model):
373 dossier = models.ForeignKey("Dossier")
374 question = models.ForeignKey("JustificationQuestion")
375 reponse = models.TextField()
376
377class JustificationAutreEmploye(models.Model):
378 dossier = models.ForeignKey("Dossier")
379 question = models.ForeignKey("JustificationQuestion")
380 reponse = models.TextField()
381
382
383### RÉFÉRENCES RH
384
e9bbd6ba 385class FamilleEmploi(models.Model):
9afaa55e 386 # Identification
e9bbd6ba 387 id = models.IntegerField(primary_key=True)
388 nom = models.CharField(max_length=255)
9afaa55e 389 # Méta
e9bbd6ba 390 actif = models.BooleanField()
391
392class TypePoste(models.Model):
9afaa55e 393 # Identification
e9bbd6ba 394 id = models.IntegerField(primary_key=True)
395 nom = models.CharField(max_length=255)
396 nom_feminin = models.CharField(max_length=255)
397 description = models.CharField(max_length=255)
398 is_responsable = models.BooleanField()
9afaa55e 399 famille_emploi = models.ForeignKey('FamilleEmploi',
400 db_column='famille_emploi')
401 # Méta
e9bbd6ba 402 date_modification = models.DateField(auto_now=True)
403 actif = models.BooleanField()
404
405 def __unicode__(self):
406 return u'%s' % self.nom
407
408
409TYPE_PAIEMENT_CHOICES = (
410 ('Régulier', 'Régulier'),
411 ('Ponctuel', 'Ponctuel'),
412)
413
414NATURE_REMUNERATION_CHOICES = (
415 ('Accessoire', 'Accessoire'),
416 ('Charges', 'Charges'),
417 ('Indemnité', 'Indemnité'),
418 ('RAS', 'RAS'),
419 ('Traitement', 'Traitement'),
420)
421
422class TypeRemuneration(models.Model):
9afaa55e 423 # Identification
e9bbd6ba 424 id = models.IntegerField(primary_key=True)
425 nom = models.CharField(max_length=255)
9afaa55e 426 type_paiement = models.CharField(max_length=30,
427 choices=TYPE_PAIEMENT_CHOICES)
428 nature_remuneration = models.CharField(max_length=30,
429 choices=NATURE_REMUNERATION_CHOICES)
430 # Méta
e9bbd6ba 431 actif = models.BooleanField()
9afaa55e 432
433 def __unicode__(self):
434 return u'%s' % self.nom
e9bbd6ba 435
436class TypeRevalorisation(models.Model):
9afaa55e 437 # Identification
e9bbd6ba 438 id = models.IntegerField(primary_key=True)
439 nom = models.CharField(max_length=255)
9afaa55e 440 # Méta
e9bbd6ba 441 actif = models.BooleanField()
442
e9bbd6ba 443class Service(models.Model):
9afaa55e 444 # Identification
e9bbd6ba 445 id = models.IntegerField(primary_key=True)
446 nom = models.CharField(max_length=255)
9afaa55e 447 # Méta
e9bbd6ba 448 actif = models.BooleanField()
449
450 def __unicode__(self):
451 return u'%s' % self.nom
9afaa55e 452
453 class Meta:
454 ordering = ['nom']
e9bbd6ba 455
456
457TYPE_ORGANISME_CHOICES = (
458 ('MAD', 'Mise à disposition'),
459 ('DET', 'Détachement'),
460)
461
462class OrganismeBstg(models.Model):
9afaa55e 463 # Identification
e9bbd6ba 464 id = models.IntegerField(primary_key=True)
465 nom = models.CharField(max_length=255)
466 type = models.CharField(max_length=10, choices=TYPE_ORGANISME_CHOICES)
9afaa55e 467 # Méta
e9bbd6ba 468 actif = models.BooleanField()
469
9afaa55e 470 def __unicode__(self):
471 return u'%s (%s)' % (self.nom, self.type)
472
473 class Meta:
474 ordering = ['type', 'nom']
475
83b7692b 476
e9bbd6ba 477CONTRAT_CATEGORIE_CHOICES= (
478 ('A', 'A'),
479 ('C', 'C'),
480)
83b7692b 481
e9bbd6ba 482class Statut(models.Model):
9afaa55e 483 # Identification
e9bbd6ba 484 id = models.IntegerField(primary_key=True)
485 code = models.CharField(max_length=25, unique=True)
486 nom = models.CharField(max_length=255)
9afaa55e 487 type_contrat_categorie = models.CharField(max_length=10,
488 choices=CONTRAT_CATEGORIE_CHOICES)
e9bbd6ba 489 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
9afaa55e 490 # Méta
e9bbd6ba 491 actif = models.BooleanField()
492
9afaa55e 493 def __unicode__(self):
494 return u'%s : %s' % (self.code, self.nom)
495
83b7692b 496
e9bbd6ba 497TYPE_CLASSEMENT_CHOICES = (
498 ('S', 'S'),
499 ('T', 'T'),
500)
83b7692b 501
e9bbd6ba 502class Classement(models.Model):
9afaa55e 503 # Identification
e9bbd6ba 504 id = models.IntegerField(primary_key=True)
505 type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES)
506 echelon = models.IntegerField()
507 degre = models.IntegerField()
508 coefficient = models.FloatField()
9afaa55e 509 # Méta
e9bbd6ba 510 commentaire = models.TextField(null=True, blank=True)
511 date_modification = models.DateField(auto_now=True)
512 actif = models.BooleanField()
513
514 def __unicode__(self):
515 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
516 self.coefficient)
9afaa55e 517 class Meta:
518 ordering = ['type','echelon','degre','coefficient']
e9bbd6ba 519
9afaa55e 520class TauxChange(models.Model):
521 # Identification
e9bbd6ba 522 id = models.IntegerField(primary_key=True)
9afaa55e 523 devise = models.ForeignKey('Devise', to_field='code', db_column='devise')
e9bbd6ba 524 annee = models.IntegerField()
9afaa55e 525 taux = models.FloatField()
526 # Relations
83b7692b 527 implantation = models.ForeignKey(ref.Implantation,
9afaa55e 528 db_column='implantation',
529 related_name='taux_change')
e9bbd6ba 530
9afaa55e 531class ValeurPoint(models.Model):
532 # Identification
e9bbd6ba 533 id = models.IntegerField(primary_key=True)
9afaa55e 534 valeur = models.FloatField()
83b7692b 535 implantation = models.ForeignKey(ref.Implantation,
9afaa55e 536 db_column='implantation',
537 related_name='valeurs_point')
538 # Méta
e9bbd6ba 539 annee = models.IntegerField()
9afaa55e 540
541 # Stockage de tous les taux de change pour optimiser la recherche de la devise associée
542 annee_courante = datetime.datetime.now().year
543 tauxchange = TauxChange.objects.select_related('devise').filter(annee=annee_courante)
544
545 def __unicode__(self):
546 tx = self.get_tauxchange_courant()
547 if tx:
548 devise_code = tx.devise.code
549 else:
550 devise_code = "??"
551 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
552
553 class Meta:
554 ordering = ['valeur']
e9bbd6ba 555
e9bbd6ba 556class Devise(models.Model):
557 id = models.IntegerField(primary_key=True)
558 code = models.CharField(max_length=10, unique=True)
559 nom = models.CharField(max_length=255)
560
561 def __unicode__(self):
562 return u'%s - %s' % (self.code, self.nom)
563
e9bbd6ba 564class TypeContrat(models.Model):
9afaa55e 565 # Identification
e9bbd6ba 566 id = models.IntegerField(primary_key=True)
567 nom = models.CharField(max_length=255)
568 nom_long = models.CharField(max_length=255) #description
9afaa55e 569 categorie = models.CharField(max_length=10,
570 choices=CONTRAT_CATEGORIE_CHOICES)
571 # Méta
e9bbd6ba 572 actif = models.BooleanField()
49f9f116 573
9afaa55e 574 def __unicode__(self):
575 return u'%s' % (self.nom)
30be56d5 576
577class ResponsableImplantation(models.Model):
578 """Le responsable d'une implantation.
579 Anciennement géré sur le Dossier du responsable.
580 """
581 employe = models.ForeignKey('Employe', null=True, blank=True)
582 implantation = models.ForeignKey(ref.Implantation, unique=True)
583
584 def __unicode__(self):
585 return u'%s : %s' % (self.implantation, self.employe)
586
587 class Meta:
588 ordering = ['implantation__nom']