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