fix infos manqunates
[auf_rh_dae.git] / project / rh_v1 / models.py
CommitLineData
a3121a38
AJ
1# -=- encoding: utf-8 -=-
2
6301bd59 3import datetime
a3121a38
AJ
4from django.db import models
5from datamaster_modeles.models import Pays, Implantation
f258e4e7 6from dae.managers import SecurityManager
a3121a38
AJ
7
8GENRE_CHOICES = (
139686f2
NC
9 ('m', 'Homme'),
10 ('f', 'Femme'),
a3121a38
AJ
11)
12SITUATION_CHOICES = (
13 ('C', 'Célibataire'),
14 ('F', 'Fiancé'),
15 ('M', 'Marié'),
16)
17
18class Employe(models.Model):
9afaa55e 19 # Identification
a3121a38
AJ
20 id = models.IntegerField(primary_key=True)
21 nom = models.CharField(max_length=255)
22 prenom = models.CharField(max_length=255)
9afaa55e 23 nationalite = models.ForeignKey('datamaster_modeles.Pays', to_field='code',
24 related_name='nationalite',
25 db_column='nationalite')
a3121a38 26 date_naissance = models.DateField(null=True, blank=True)
9afaa55e 27 # Infos personnelles
28 genre = models.CharField(max_length=1, null=True, blank=True,
29 choices=GENRE_CHOICES)
30 situation_famille = models.CharField(max_length=1, null=True, blank=True,
31 choices=SITUATION_CHOICES)
a3121a38 32 date_entree = models.DateField(null=True, blank=True) #devrait pas être là
9afaa55e 33 # Coordonnées
a3121a38
AJ
34 tel_domicile = models.CharField(max_length=255, null=True, blank=True)
35 tel_cellulaire = models.CharField(max_length=255, null=True, blank=True)
36 adresse = models.CharField(max_length=255, null=True, blank=True)
37 no_rue = models.CharField(max_length=255, null=True, blank=True)
38 ville = models.CharField(max_length=255, null=True, blank=True)
39 province = models.CharField(max_length=255, null=True, blank=True)
40 code_postal = models.CharField(max_length=255, null=True, blank=True)
9afaa55e 41 pays = models.ForeignKey('datamaster_modeles.Pays', to_field='code',
42 null=True, blank=True,
43 related_name='pays', db_column='pays')
44 # Métas
a3121a38
AJ
45 date_creation = models.DateField(auto_now_add=True)
46 date_maj = models.DateField(auto_now=True)
47 commentaire = models.TextField(null=True, blank=True)
139686f2
NC
48
49 def __unicode__(self):
50 return u'%s %s' % (self.prenom, self.nom)
51
52
a3121a38
AJ
53TYPE_DOSSIER_CHOICES = (
54 ('2', 'Local'),
55 ('1', 'Expatrié'),
56)
57
1c7d67ce
OL
58class DossierManager(models.Manager):
59 """
60 Chargement de tous les objets FK existants sur chaque QuerySet.
61 """
62 def get_query_set(self):
63 fkeys = (
64 'employe',
65 'poste1',
66 'implantation1',
67 'poste2',
68 'implantation2',
69 'service',
70 'responsable',
71 'remplacement_de',
72 'statut',
73 'organisme_bstg',
74 'classement',
75 'type_contrat',
76 )
77 return super(DossierManager, self).get_query_set().select_related(*fkeys).all()
78
a3121a38 79class Dossier(models.Model):
9afaa55e 80 # Identification
a3121a38
AJ
81 id = models.IntegerField(primary_key=True)
82 code = models.CharField(max_length=10, unique=True)
83 employe = models.ForeignKey('Employe', db_column='employe')
9afaa55e 84 # Postes
85 poste1 = models.ForeignKey('Poste', db_column='poste1',
86 related_name='poste1')
87 implantation1 = models.ForeignKey('datamaster_modeles.Implantation',
88 db_column='implantation1',
89 related_name='implantation1',
90 blank=True, null=True)
a3121a38
AJ
91 complement1 = models.TextField(null=True, blank=True)
92 responsable_implantation1 = models.IntegerField()
9afaa55e 93 poste2 = models.ForeignKey('Poste', db_column='poste2',
94 related_name='poste2',
95 blank=True, null=True)
96 implantation2 = models.ForeignKey('datamaster_modeles.Implantation',
97 db_column='implantation2',
98 related_name='implantation2',
99 null=True, blank=True)
a3121a38
AJ
100 complement2 = models.TextField(null=True, blank=True)
101 responsable_implantation2 = models.IntegerField()
9afaa55e 102 # Relations
103 service = models.ForeignKey('Service', db_column='service',
104 blank=True, null=True)
105 responsable = models.ForeignKey('Employe', db_column='responsable',
106 related_name='responsable',
107 blank=True, null=True)
108 remplacement_de = models.ForeignKey('Employe', db_column='remplacement_de',
109 related_name='remplacement_de',
110 blank=True, null=True)
a3121a38 111 type = models.CharField(max_length=1, choices=TYPE_DOSSIER_CHOICES)
9afaa55e 112 statut = models.ForeignKey('Statut', db_column='statut',
113 blank=True, null=True)
114 organisme_bstg = models.ForeignKey('OrganismeBstg',
115 db_column='organisme_bstg',
116 blank=True, null=True)
117 # Rémunération
118 classement = models.ForeignKey('Classement', db_column='classement',
119 blank=True, null=True)
a3121a38 120 regime_travail = models.IntegerField()
9afaa55e 121 # Mandat
a3121a38 122 mandat_date_debut = models.DateField()
f48decfd 123 mandat_date_fin = models.DateField(null=True, blank=True)
9afaa55e 124 # Contrat
a3121a38
AJ
125 contrat_date_debut = models.DateField()
126 contrat_date_fin = models.DateField()
9afaa55e 127 type_contrat = models.ForeignKey('TypeContrat', db_column='type_contrat',
128 blank=True, null=True)
129 # Meta
a3121a38
AJ
130 date_creation = models.DateField(auto_now_add=True)
131 date_maj = models.DateField(auto_now=True)
132 commentaire = models.TextField(null=True, blank=True)
133
1c7d67ce
OL
134 # Managers
135 objects = DossierManager()
0f23302a 136
137 def __unicode__(self):
138 return u'%s : %s %s' % (self.employe, self.poste1, self.complement1)
1c7d67ce 139
03b395db
OL
140 def get_dernier_salaire_remun(self):
141 remun = [r for r in self.remuneration_set.all() if r.type_id == 1] # type salaire de base
142 if len(remun) == 0:
143 return None
144 else:
03b395db
OL
145 return remun[0]
146
147 def get_salaire(self):
148 remun = self.get_dernier_salaire_remun()
149 if remun is not None:
150 return int(remun.montant)
151 else:
152 return None
153
7e43f9b6
OL
154 def get_salaire_display(self):
155 """
156 Moyen rapide de récupérer le salaire correspodant à un dossier. Par contre,
157 toutes les rémuérations n'ont pas de devise associées, c'est pourquoi on récupère
158 les anciennes rémunérations pour rechercher si elle existait auparavant.
159 """
d9aed39d
OL
160 if self.dernier_salaire_remun() is not None:
161 devise_code = self.dernier_salaire_remun().devise.code
162 else:
163 devise_code = '???'
164 return "%s %s" % (self.get_salaire(), devise_code, )
62dbbb71
OL
165
166 def get_salaire_euro_display(self):
167 """
168 Moyen rapide de récupérer le salaire correspodant à un dossier. Par contre,
169 toutes les rémuérations n'ont pas de devise associées, c'est pourquoi on récupère
170 les anciennes rémunérations pour rechercher si elle existait auparavant.
171 La valeur est est affichée en Euros en se servant du taux actuel.
172 """
03b395db 173 return "%s EUR" % (self.get_dernier_salaire_remun().en_euros())
7e43f9b6 174
a3121a38
AJ
175LIEN_PARENTE_CHOICES = (
176 ('Conjoint', 'Conjoint'),
177 ('Conjointe', 'Conjointe'),
178 ('Fille', 'Fille'),
179 ('Fils', 'Fils'),
180)
181
182class AyantDroit(models.Model):
9afaa55e 183 # Identification
a3121a38
AJ
184 id = models.IntegerField(primary_key=True)
185 nom = models.CharField(max_length=255)
186 prenom = models.CharField(max_length=255)
9afaa55e 187 # Relation
188 employe = models.ForeignKey('Employe', db_column='employe',
189 related_name='employe')
190 lien_parente = models.CharField(max_length=10, null=True, blank=True,
191 choices=LIEN_PARENTE_CHOICES)
192 # Méta
a3121a38
AJ
193 commentaire = models.TextField(null=True, blank=True)
194 actif = models.BooleanField()
195
196
197class Remuneration(models.Model):
9afaa55e 198 # Identification
a3121a38
AJ
199 id = models.IntegerField(primary_key=True)
200 dossier = models.ForeignKey('Dossier', db_column='dossier')
201 type = models.ForeignKey('TypeRemuneration', db_column='type')
9afaa55e 202 type_revalorisation = models.ForeignKey('TypeRevalorisation',
203 db_column='type_revalorisation',
204 null=True, blank=True)
139686f2 205 montant = models.FloatField(null=True, blank=True)
03b395db 206 devise = models.ForeignKey('Devise', to_field='id', db_column='devise', null=True, blank=True)
139686f2
NC
207 date_effective = models.DateField(null=True, blank=True)
208 pourcentage = models.IntegerField(null=True, blank=True)
9afaa55e 209 # Méta
a3121a38 210 date_creation = models.DateField(auto_now_add=True)
139686f2
NC
211 user_creation = models.IntegerField(null=True, blank=True) #User ou employé
212 desactivation = models.NullBooleanField(null=True, blank=True) #
213 date_desactivation = models.DateField(null=True, blank=True)
214 user_desactivation = models.IntegerField(null=True, blank=True) #User ou employé
215 annulation = models.NullBooleanField(null=True, blank=True)
216 date_annulation = models.DateField(null=True, blank=True)
217 user_annulation = models.IntegerField(null=True, blank=True) #User ou employé
a3121a38 218
7e43f9b6
OL
219 def __unicode__(self):
220 try:
221 devise = self.devise.code
222 except:
223 devise = "???"
03b395db
OL
224 return "%s %s (%s EUR - %s)" % (self.montant, devise, self.en_euros(), self.get_taux_historique(), )
225
226 def get_taux_historique(self):
d9aed39d
OL
227 """
228 Retourne le taux en vigueur durant l'année considérée. Un taux de 0 est crée, si le taux de change
229 n'existe pas.
230 """
231 taux = TauxChange.objects.filter(devise=self.devise, annee=self.date_creation.year)
232 if len(taux) > 0:
233 return taux[0]
234 else:
235 return None
03b395db
OL
236
237 def en_euros(self):
d9aed39d
OL
238 tauxchange = self.get_taux_historique()
239 if tauxchange is not None:
240 return int(self.montant * tauxchange.taux)
241 else:
242 return 0
7e43f9b6 243
a3121a38 244class FamilleEmploi(models.Model):
9afaa55e 245 # Identification
a3121a38
AJ
246 id = models.IntegerField(primary_key=True)
247 nom = models.CharField(max_length=255)
9afaa55e 248 # Méta
a3121a38
AJ
249 actif = models.BooleanField()
250
251class TypePoste(models.Model):
9afaa55e 252 # Identification
a3121a38
AJ
253 id = models.IntegerField(primary_key=True)
254 nom = models.CharField(max_length=255)
255 nom_feminin = models.CharField(max_length=255)
256 description = models.CharField(max_length=255)
257 is_responsable = models.BooleanField()
9afaa55e 258 famille_emploi = models.ForeignKey('FamilleEmploi',
259 db_column='famille_emploi')
260 # Méta
a3121a38
AJ
261 date_modification = models.DateField(auto_now=True)
262 actif = models.BooleanField()
263
5d680e84
NC
264 def __unicode__(self):
265 return u'%s' % self.nom
6d704629 266
267 class Meta:
268 ordering = ['nom']
5d680e84
NC
269
270
a3121a38
AJ
271TYPE_PAIEMENT_CHOICES = (
272 ('Régulier', 'Régulier'),
273 ('Ponctuel', 'Ponctuel'),
274)
275
276NATURE_REMUNERATION_CHOICES = (
277 ('Accessoire', 'Accessoire'),
278 ('Charges', 'Charges'),
279 ('Indemnité', 'Indemnité'),
280 ('RAS', 'RAS'),
281 ('Traitement', 'Traitement'),
282)
283
284class TypeRemuneration(models.Model):
9afaa55e 285 # Identification
a3121a38
AJ
286 id = models.IntegerField(primary_key=True)
287 nom = models.CharField(max_length=255)
9afaa55e 288 type_paiement = models.CharField(max_length=30,
289 choices=TYPE_PAIEMENT_CHOICES)
290 nature_remuneration = models.CharField(max_length=30,
291 choices=NATURE_REMUNERATION_CHOICES)
292 # Méta
a3121a38 293 actif = models.BooleanField()
cb1d62b5
NC
294
295 def __unicode__(self):
296 return u'%s' % self.nom
297
298
a3121a38 299class TypeRevalorisation(models.Model):
9afaa55e 300 # Identification
a3121a38
AJ
301 id = models.IntegerField(primary_key=True)
302 nom = models.CharField(max_length=255)
9afaa55e 303 # Méta
a3121a38
AJ
304 actif = models.BooleanField()
305
306PROPORTION_CHOICES = (
307 ('0.5', '0.5'),
308 ('1', '1'),
309)
310
f258e4e7 311class PosteManager(SecurityManager):
1c7d67ce
OL
312 """
313 Chargement de tous les objets FK existants sur chaque QuerySet.
314 """
f258e4e7
OL
315 prefixe_implantation = 'implantation'
316
1c7d67ce
OL
317 def get_query_set(self):
318 fkeys = (
319 'implantation',
320 'type_poste',
321 )
322 return super(PosteManager, self).get_query_set().select_related(*fkeys).all()
323
a3121a38 324class Poste(models.Model):
9afaa55e 325 # Identification
a3121a38 326 id = models.IntegerField(primary_key=True)
5d680e84 327 implantation = models.ForeignKey('datamaster_modeles.Implantation',
9afaa55e 328 db_column='implantation', related_name='+')
a3121a38
AJ
329 type_poste = models.ForeignKey('TypePoste', db_column='type_poste')
330 proportion = models.CharField(max_length=10, choices=PROPORTION_CHOICES)
331 #(sert à quoi?) renommer "regime_travail" ou autre? convertir data en % (data * 100; ex: 1 = 100%)
9afaa55e 332 # Méta
a3121a38
AJ
333 date_modification = models.DateField(auto_now=True)
334 actif = models.BooleanField()
335
1c7d67ce
OL
336 # Managers
337 objects = PosteManager()
338
5d680e84 339 def __unicode__(self):
9afaa55e 340 return u'%s - %s [%s]' % (self.implantation, self.type_poste.nom,
341 self.id)
5d680e84
NC
342
343
a3121a38 344class Service(models.Model):
9afaa55e 345 # Identification
a3121a38
AJ
346 id = models.IntegerField(primary_key=True)
347 nom = models.CharField(max_length=255)
9afaa55e 348 # Méta
a3121a38
AJ
349 actif = models.BooleanField()
350
5d680e84
NC
351 def __unicode__(self):
352 return u'%s' % self.nom
6d704629 353
354 class Meta:
355 ordering = ['nom']
5d680e84
NC
356
357
a3121a38
AJ
358TYPE_ORGANISME_CHOICES = (
359 ('MAD', 'Mise à disposition'),
360 ('DET', 'Détachement'),
361)
362
363class OrganismeBstg(models.Model):
9afaa55e 364 # Identification
a3121a38
AJ
365 id = models.IntegerField(primary_key=True)
366 nom = models.CharField(max_length=255)
367 type = models.CharField(max_length=10, choices=TYPE_ORGANISME_CHOICES)
9afaa55e 368 # Méta
a3121a38
AJ
369 actif = models.BooleanField()
370
139686f2
NC
371 def __unicode__(self):
372 return u'%s (%s)' % (self.nom, self.type)
373
0f23302a 374 class Meta:
375 ordering = ['type', 'nom']
376
139686f2 377
a3121a38
AJ
378CONTRAT_CATEGORIE_CHOICES= (
379 ('A', 'A'),
380 ('C', 'C'),
381)
382class Statut(models.Model):
9afaa55e 383 # Identification
a3121a38
AJ
384 id = models.IntegerField(primary_key=True)
385 code = models.CharField(max_length=25, unique=True)
386 nom = models.CharField(max_length=255)
9afaa55e 387 type_contrat_categorie = models.CharField(max_length=10,
388 choices=CONTRAT_CATEGORIE_CHOICES)
a3121a38 389 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
9afaa55e 390 # Méta
a3121a38
AJ
391 actif = models.BooleanField()
392
139686f2 393 def __unicode__(self):
0f23302a 394 return u'%s : %s' % (self.code, self.nom)
139686f2 395
a3121a38
AJ
396TYPE_CLASSEMENT_CHOICES = (
397 ('S', 'S'),
398 ('T', 'T'),
399)
400class Classement(models.Model):
9afaa55e 401 # Identification
a3121a38
AJ
402 id = models.IntegerField(primary_key=True)
403 type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES)
404 echelon = models.IntegerField()
405 degre = models.IntegerField()
406 coefficient = models.FloatField()
9afaa55e 407 # Méta
a3121a38
AJ
408 commentaire = models.TextField(null=True, blank=True)
409 date_modification = models.DateField(auto_now=True)
410 actif = models.BooleanField()
411
5d680e84
NC
412 def __unicode__(self):
413 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
414 self.coefficient)
e57fb3d8 415 class Meta:
416 ordering = ['type','echelon','degre','coefficient']
5d680e84 417
6301bd59 418class TauxChange(models.Model):
9afaa55e 419 # Identification
6301bd59 420 id = models.IntegerField(primary_key=True)
d9aed39d 421 devise = models.ForeignKey('Devise', to_field='id', db_column='devise')
6301bd59
OL
422 annee = models.IntegerField()
423 taux = models.FloatField()
9afaa55e 424 # Relations
425 implantation = models.ForeignKey('datamaster_modeles.Implantation',
426 db_column='implantation',
427 related_name='taux_change')
6301bd59 428
03b395db
OL
429 def __unicode__(self):
430 return u"%s %s : %s" % (self.devise, self.annee, self.taux)
431
6301bd59
OL
432class ValeurPointManager(models.Manager):
433 """
434 Manager qui travaille uniquement sur les valeurs du point de l'année en cours.
435 """
436 mois = datetime.datetime.now().month
437 annee_courante = datetime.datetime.now().year
438
439 # Pour le mois de janvier et décembre on mets les 2 années pour faire la transition
440 if mois == 1:
441 filtre_annee = (annee_courante-1, annee_courante)
442 elif mois == 12:
443 filtre_annee = (annee_courante, annee_courante+1)
444 else:
445 filtre_annee = (annee_courante,)
446
447 def get_query_set(self):
448 return super(ValeurPointManager, self).get_query_set().select_related('implantation').filter(annee__in=self.filtre_annee)
449
5d680e84 450
a3121a38 451class ValeurPoint(models.Model):
9afaa55e 452 # Identification
a3121a38
AJ
453 id = models.IntegerField(primary_key=True)
454 valeur = models.FloatField()
9afaa55e 455 implantation = models.ForeignKey('datamaster_modeles.Implantation',
456 db_column='implantation',
457 related_name='valeurs_point')
458 # Méta
a3121a38 459 annee = models.IntegerField()
6301bd59
OL
460
461 # Stockage de tous les taux de change pour optimiser la recherche de la devise associée
462 annee_courante = datetime.datetime.now().year
463 tauxchange = TauxChange.objects.select_related('devise').filter(annee=annee_courante)
464
465 def get_tauxchange_courant(self):
466 """
467 Recherche le taux courant associé à la valeur d'un point.
468 Tous les taux de l'année courante sont chargés, pour optimiser un affichage en liste.
469 (On pourrait probablement améliorer le manager pour lui greffer le taux courant sous forme de JOIN)
470 """
471 for tauxchange in self.tauxchange:
472 if tauxchange.implantation_id == self.implantation_id:
473 return tauxchange
474 return None
a3121a38 475
5d680e84 476 def __unicode__(self):
17353922
OL
477 tx = self.get_tauxchange_courant()
478 if tx:
479 devise_code = tx.devise.code
480 else:
481 devise_code = "??"
da3ca955 482 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
6d704629 483
484 class Meta:
485 ordering = ['valeur']
5d680e84 486
4dd75e7b 487 objects = models.Manager()
6301bd59 488 actuelles = ValeurPointManager()
a3121a38 489
5d680e84 490
a3121a38
AJ
491class Devise(models.Model):
492 id = models.IntegerField(primary_key=True)
493 code = models.CharField(max_length=10, unique=True)
494 nom = models.CharField(max_length=255)
495
5d680e84
NC
496 def __unicode__(self):
497 return u'%s - %s' % (self.code, self.nom)
498
499
a3121a38 500class TypeContrat(models.Model):
9afaa55e 501 # Identification
a3121a38
AJ
502 id = models.IntegerField(primary_key=True)
503 nom = models.CharField(max_length=255)
504 nom_long = models.CharField(max_length=255) #description
9afaa55e 505 categorie = models.CharField(max_length=10,
506 choices=CONTRAT_CATEGORIE_CHOICES)
507 # Méta
a3121a38
AJ
508 actif = models.BooleanField()
509
139686f2 510 def __unicode__(self):
0f23302a 511 return u'%s' % (self.nom)