rh.models ~= dae.models
[auf_rh_dae.git] / project / rh / models.py
1 # -=- encoding: utf-8 -=-
2
3 import datetime
4
5 from django.core.files.storage import FileSystemStorage
6 from django.db import models
7 import settings
8
9 import datamaster_modeles.models as ref
10
11
12 # Upload de fichiers
13 storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT,
14 base_url=settings.PRIVE_MEDIA_URL)
15
16 def poste_piece_dispatch(instance, filename):
17 path = "poste/%s/%s" % (instance.poste_id, filename)
18 return path
19
20 def dossier_piece_dispatch(instance, filename):
21 path = "dossier/%s/%s" % (instance.dossier_id, filename)
22 return path
23
24
25 ### POSTE
26
27 POSTE_APPEL_CHOICES = (
28 ('interne', 'Interne'),
29 ('externe', 'Externe'),
30 )
31
32 class 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
129 POSTE_FINANCEMENT_CHOICES = (
130 ('A', 'A - Frais de personnel'),
131 ('B', 'B - Projet(s)-Titre(s)'),
132 ('C', 'C - Autre')
133 )
134
135 class 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
146 class 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
155
156 GENRE_CHOICES = (
157 ('M', 'Homme'),
158 ('F', 'Femme'),
159 )
160 SITUATION_CHOICES = (
161 ('C', 'Célibataire'),
162 ('F', 'Fiancé'),
163 ('M', 'Marié'),
164 )
165
166 class Employe(models.Model):
167 # Identification
168 id = models.IntegerField(primary_key=True)
169 nom = models.CharField(max_length=255)
170 prenom = models.CharField(max_length=255)
171 nationalite = models.ForeignKey(ref.Pays, to_field='code',
172 related_name='employes_nationalite',
173 db_column='nationalite')
174 date_naissance = models.DateField(null=True, blank=True)
175
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)
181 date_entree = models.DateField(null=True, blank=True) #devrait pas être là
182
183 # Coordonnées
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)
191 pays = models.ForeignKey(ref.Pays, to_field='code',
192 null=True, blank=True,
193 related_name='employes', db_column='pays')
194
195 # Métas
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)
199
200 def __unicode__(self):
201 return u'%s %s' % (self.prenom, self.nom)
202
203
204 LIEN_PARENTE_CHOICES = (
205 ('Conjoint', 'Conjoint'),
206 ('Conjointe', 'Conjointe'),
207 ('Fille', 'Fille'),
208 ('Fils', 'Fils'),
209 )
210
211 class AyantDroit(models.Model):
212 # Identification
213 id = models.IntegerField(primary_key=True)
214 nom = models.CharField(max_length=255)
215 prenom = models.CharField(max_length=255)
216
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)
222
223 # Méta
224 commentaire = models.TextField(null=True, blank=True)
225 actif = models.BooleanField()
226
227
228 ### DOSSIER
229
230 STATUT_RESIDENCE_CHOICES = (
231 ('local', 'Local'),
232 ('expat', 'Expatrié'),
233 )
234
235 COMPTE_COMPTA_CHOICES = (
236 ('coda', 'CODA'),
237 ('scs', 'SCS'),
238 ('aucun', 'Aucun'),
239 )
240
241 class 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()
292
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
301 class 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
310
311 class Remuneration(models.Model):
312 # Identification
313 id = models.IntegerField(primary_key=True)
314 dossier = models.ForeignKey('Dossier', db_column='dossier')
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
328 # Méta
329 date_creation = models.DateField(auto_now_add=True)
330 user_creation = models.IntegerField(null=True, blank=True) #User ou employé
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)
349
350 def __unicode__(self):
351 try:
352 devise = self.devise.code
353 except:
354 devise = "???"
355 return "%s %s" % (self.montant, devise)
356
357
358 ### JUSTIFICATIONS
359
360 TYPE_JUSTIFICATIONS = (
361 ('N', 'Nouvel employé'),
362 ('R', 'Renouvellement employé'),
363 )
364
365 class JustificationQuestion(models.Model):
366 question = models.CharField(max_length=255)
367 type = models.CharField(max_length=255, choices=TYPE_JUSTIFICATIONS)
368
369 def __unicode__(self,):
370 return self.question
371
372 class JustificationNouvelEmploye(models.Model):
373 dossier = models.ForeignKey("Dossier")
374 question = models.ForeignKey("JustificationQuestion")
375 reponse = models.TextField()
376
377 class 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
385 class FamilleEmploi(models.Model):
386 # Identification
387 id = models.IntegerField(primary_key=True)
388 nom = models.CharField(max_length=255)
389 # Méta
390 actif = models.BooleanField()
391
392 class TypePoste(models.Model):
393 # Identification
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()
399 famille_emploi = models.ForeignKey('FamilleEmploi',
400 db_column='famille_emploi')
401 # Méta
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
409 TYPE_PAIEMENT_CHOICES = (
410 ('Régulier', 'Régulier'),
411 ('Ponctuel', 'Ponctuel'),
412 )
413
414 NATURE_REMUNERATION_CHOICES = (
415 ('Accessoire', 'Accessoire'),
416 ('Charges', 'Charges'),
417 ('Indemnité', 'Indemnité'),
418 ('RAS', 'RAS'),
419 ('Traitement', 'Traitement'),
420 )
421
422 class TypeRemuneration(models.Model):
423 # Identification
424 id = models.IntegerField(primary_key=True)
425 nom = models.CharField(max_length=255)
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
431 actif = models.BooleanField()
432
433 def __unicode__(self):
434 return u'%s' % self.nom
435
436 class TypeRevalorisation(models.Model):
437 # Identification
438 id = models.IntegerField(primary_key=True)
439 nom = models.CharField(max_length=255)
440 # Méta
441 actif = models.BooleanField()
442
443 class Service(models.Model):
444 # Identification
445 id = models.IntegerField(primary_key=True)
446 nom = models.CharField(max_length=255)
447 # Méta
448 actif = models.BooleanField()
449
450 def __unicode__(self):
451 return u'%s' % self.nom
452
453 class Meta:
454 ordering = ['nom']
455
456
457 TYPE_ORGANISME_CHOICES = (
458 ('MAD', 'Mise à disposition'),
459 ('DET', 'Détachement'),
460 )
461
462 class OrganismeBstg(models.Model):
463 # Identification
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)
467 # Méta
468 actif = models.BooleanField()
469
470 def __unicode__(self):
471 return u'%s (%s)' % (self.nom, self.type)
472
473 class Meta:
474 ordering = ['type', 'nom']
475
476
477 CONTRAT_CATEGORIE_CHOICES= (
478 ('A', 'A'),
479 ('C', 'C'),
480 )
481
482 class Statut(models.Model):
483 # Identification
484 id = models.IntegerField(primary_key=True)
485 code = models.CharField(max_length=25, unique=True)
486 nom = models.CharField(max_length=255)
487 type_contrat_categorie = models.CharField(max_length=10,
488 choices=CONTRAT_CATEGORIE_CHOICES)
489 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
490 # Méta
491 actif = models.BooleanField()
492
493 def __unicode__(self):
494 return u'%s : %s' % (self.code, self.nom)
495
496
497 TYPE_CLASSEMENT_CHOICES = (
498 ('S', 'S'),
499 ('T', 'T'),
500 )
501
502 class Classement(models.Model):
503 # Identification
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()
509 # Méta
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)
517 class Meta:
518 ordering = ['type','echelon','degre','coefficient']
519
520 class TauxChange(models.Model):
521 # Identification
522 id = models.IntegerField(primary_key=True)
523 devise = models.ForeignKey('Devise', to_field='code', db_column='devise')
524 annee = models.IntegerField()
525 taux = models.FloatField()
526 # Relations
527 implantation = models.ForeignKey(ref.Implantation,
528 db_column='implantation',
529 related_name='taux_change')
530
531 class ValeurPoint(models.Model):
532 # Identification
533 id = models.IntegerField(primary_key=True)
534 valeur = models.FloatField()
535 implantation = models.ForeignKey(ref.Implantation,
536 db_column='implantation',
537 related_name='valeurs_point')
538 # Méta
539 annee = models.IntegerField()
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']
555
556 class 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
564 class TypeContrat(models.Model):
565 # Identification
566 id = models.IntegerField(primary_key=True)
567 nom = models.CharField(max_length=255)
568 nom_long = models.CharField(max_length=255) #description
569 categorie = models.CharField(max_length=10,
570 choices=CONTRAT_CATEGORIE_CHOICES)
571 # Méta
572 actif = models.BooleanField()
573
574 def __unicode__(self):
575 return u'%s' % (self.nom)