safe groupe création
[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 """
03b395db 160 return "%s %s" % (self.get_salaire(), self.dernier_salaire_remun().devise.code, )
62dbbb71
OL
161
162 def get_salaire_euro_display(self):
163 """
164 Moyen rapide de récupérer le salaire correspodant à un dossier. Par contre,
165 toutes les rémuérations n'ont pas de devise associées, c'est pourquoi on récupère
166 les anciennes rémunérations pour rechercher si elle existait auparavant.
167 La valeur est est affichée en Euros en se servant du taux actuel.
168 """
03b395db 169 return "%s EUR" % (self.get_dernier_salaire_remun().en_euros())
7e43f9b6 170
a3121a38
AJ
171LIEN_PARENTE_CHOICES = (
172 ('Conjoint', 'Conjoint'),
173 ('Conjointe', 'Conjointe'),
174 ('Fille', 'Fille'),
175 ('Fils', 'Fils'),
176)
177
178class AyantDroit(models.Model):
9afaa55e 179 # Identification
a3121a38
AJ
180 id = models.IntegerField(primary_key=True)
181 nom = models.CharField(max_length=255)
182 prenom = models.CharField(max_length=255)
9afaa55e 183 # Relation
184 employe = models.ForeignKey('Employe', db_column='employe',
185 related_name='employe')
186 lien_parente = models.CharField(max_length=10, null=True, blank=True,
187 choices=LIEN_PARENTE_CHOICES)
188 # Méta
a3121a38
AJ
189 commentaire = models.TextField(null=True, blank=True)
190 actif = models.BooleanField()
191
192
193class Remuneration(models.Model):
9afaa55e 194 # Identification
a3121a38
AJ
195 id = models.IntegerField(primary_key=True)
196 dossier = models.ForeignKey('Dossier', db_column='dossier')
197 type = models.ForeignKey('TypeRemuneration', db_column='type')
9afaa55e 198 type_revalorisation = models.ForeignKey('TypeRevalorisation',
199 db_column='type_revalorisation',
200 null=True, blank=True)
139686f2 201 montant = models.FloatField(null=True, blank=True)
03b395db 202 devise = models.ForeignKey('Devise', to_field='id', db_column='devise', null=True, blank=True)
139686f2
NC
203 date_effective = models.DateField(null=True, blank=True)
204 pourcentage = models.IntegerField(null=True, blank=True)
9afaa55e 205 # Méta
a3121a38 206 date_creation = models.DateField(auto_now_add=True)
139686f2
NC
207 user_creation = models.IntegerField(null=True, blank=True) #User ou employé
208 desactivation = models.NullBooleanField(null=True, blank=True) #
209 date_desactivation = models.DateField(null=True, blank=True)
210 user_desactivation = models.IntegerField(null=True, blank=True) #User ou employé
211 annulation = models.NullBooleanField(null=True, blank=True)
212 date_annulation = models.DateField(null=True, blank=True)
213 user_annulation = models.IntegerField(null=True, blank=True) #User ou employé
a3121a38 214
7e43f9b6
OL
215 def __unicode__(self):
216 try:
217 devise = self.devise.code
218 except:
219 devise = "???"
03b395db
OL
220 return "%s %s (%s EUR - %s)" % (self.montant, devise, self.en_euros(), self.get_taux_historique(), )
221
222 def get_taux_historique(self):
223 tauxchange = TauxChange.objects.filter(devise=self.devise, annee=self.date_creation.year)[0]
224 return tauxchange
225
226 def en_euros(self):
227 return int(self.montant * self.get_taux_historique().taux)
7e43f9b6 228
a3121a38 229class FamilleEmploi(models.Model):
9afaa55e 230 # Identification
a3121a38
AJ
231 id = models.IntegerField(primary_key=True)
232 nom = models.CharField(max_length=255)
9afaa55e 233 # Méta
a3121a38
AJ
234 actif = models.BooleanField()
235
236class TypePoste(models.Model):
9afaa55e 237 # Identification
a3121a38
AJ
238 id = models.IntegerField(primary_key=True)
239 nom = models.CharField(max_length=255)
240 nom_feminin = models.CharField(max_length=255)
241 description = models.CharField(max_length=255)
242 is_responsable = models.BooleanField()
9afaa55e 243 famille_emploi = models.ForeignKey('FamilleEmploi',
244 db_column='famille_emploi')
245 # Méta
a3121a38
AJ
246 date_modification = models.DateField(auto_now=True)
247 actif = models.BooleanField()
248
5d680e84
NC
249 def __unicode__(self):
250 return u'%s' % self.nom
6d704629 251
252 class Meta:
253 ordering = ['nom']
5d680e84
NC
254
255
a3121a38
AJ
256TYPE_PAIEMENT_CHOICES = (
257 ('Régulier', 'Régulier'),
258 ('Ponctuel', 'Ponctuel'),
259)
260
261NATURE_REMUNERATION_CHOICES = (
262 ('Accessoire', 'Accessoire'),
263 ('Charges', 'Charges'),
264 ('Indemnité', 'Indemnité'),
265 ('RAS', 'RAS'),
266 ('Traitement', 'Traitement'),
267)
268
269class TypeRemuneration(models.Model):
9afaa55e 270 # Identification
a3121a38
AJ
271 id = models.IntegerField(primary_key=True)
272 nom = models.CharField(max_length=255)
9afaa55e 273 type_paiement = models.CharField(max_length=30,
274 choices=TYPE_PAIEMENT_CHOICES)
275 nature_remuneration = models.CharField(max_length=30,
276 choices=NATURE_REMUNERATION_CHOICES)
277 # Méta
a3121a38 278 actif = models.BooleanField()
cb1d62b5
NC
279
280 def __unicode__(self):
281 return u'%s' % self.nom
282
283
a3121a38 284class TypeRevalorisation(models.Model):
9afaa55e 285 # Identification
a3121a38
AJ
286 id = models.IntegerField(primary_key=True)
287 nom = models.CharField(max_length=255)
9afaa55e 288 # Méta
a3121a38
AJ
289 actif = models.BooleanField()
290
291PROPORTION_CHOICES = (
292 ('0.5', '0.5'),
293 ('1', '1'),
294)
295
f258e4e7 296class PosteManager(SecurityManager):
1c7d67ce
OL
297 """
298 Chargement de tous les objets FK existants sur chaque QuerySet.
299 """
f258e4e7
OL
300 prefixe_implantation = 'implantation'
301
1c7d67ce
OL
302 def get_query_set(self):
303 fkeys = (
304 'implantation',
305 'type_poste',
306 )
307 return super(PosteManager, self).get_query_set().select_related(*fkeys).all()
308
a3121a38 309class Poste(models.Model):
9afaa55e 310 # Identification
a3121a38 311 id = models.IntegerField(primary_key=True)
5d680e84 312 implantation = models.ForeignKey('datamaster_modeles.Implantation',
9afaa55e 313 db_column='implantation', related_name='+')
a3121a38
AJ
314 type_poste = models.ForeignKey('TypePoste', db_column='type_poste')
315 proportion = models.CharField(max_length=10, choices=PROPORTION_CHOICES)
316 #(sert à quoi?) renommer "regime_travail" ou autre? convertir data en % (data * 100; ex: 1 = 100%)
9afaa55e 317 # Méta
a3121a38
AJ
318 date_modification = models.DateField(auto_now=True)
319 actif = models.BooleanField()
320
1c7d67ce
OL
321 # Managers
322 objects = PosteManager()
323
5d680e84 324 def __unicode__(self):
9afaa55e 325 return u'%s - %s [%s]' % (self.implantation, self.type_poste.nom,
326 self.id)
5d680e84
NC
327
328
a3121a38 329class Service(models.Model):
9afaa55e 330 # Identification
a3121a38
AJ
331 id = models.IntegerField(primary_key=True)
332 nom = models.CharField(max_length=255)
9afaa55e 333 # Méta
a3121a38
AJ
334 actif = models.BooleanField()
335
5d680e84
NC
336 def __unicode__(self):
337 return u'%s' % self.nom
6d704629 338
339 class Meta:
340 ordering = ['nom']
5d680e84
NC
341
342
a3121a38
AJ
343TYPE_ORGANISME_CHOICES = (
344 ('MAD', 'Mise à disposition'),
345 ('DET', 'Détachement'),
346)
347
348class OrganismeBstg(models.Model):
9afaa55e 349 # Identification
a3121a38
AJ
350 id = models.IntegerField(primary_key=True)
351 nom = models.CharField(max_length=255)
352 type = models.CharField(max_length=10, choices=TYPE_ORGANISME_CHOICES)
9afaa55e 353 # Méta
a3121a38
AJ
354 actif = models.BooleanField()
355
139686f2
NC
356 def __unicode__(self):
357 return u'%s (%s)' % (self.nom, self.type)
358
0f23302a 359 class Meta:
360 ordering = ['type', 'nom']
361
139686f2 362
a3121a38
AJ
363CONTRAT_CATEGORIE_CHOICES= (
364 ('A', 'A'),
365 ('C', 'C'),
366)
367class Statut(models.Model):
9afaa55e 368 # Identification
a3121a38
AJ
369 id = models.IntegerField(primary_key=True)
370 code = models.CharField(max_length=25, unique=True)
371 nom = models.CharField(max_length=255)
9afaa55e 372 type_contrat_categorie = models.CharField(max_length=10,
373 choices=CONTRAT_CATEGORIE_CHOICES)
a3121a38 374 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
9afaa55e 375 # Méta
a3121a38
AJ
376 actif = models.BooleanField()
377
139686f2 378 def __unicode__(self):
0f23302a 379 return u'%s : %s' % (self.code, self.nom)
139686f2 380
a3121a38
AJ
381TYPE_CLASSEMENT_CHOICES = (
382 ('S', 'S'),
383 ('T', 'T'),
384)
385class Classement(models.Model):
9afaa55e 386 # Identification
a3121a38
AJ
387 id = models.IntegerField(primary_key=True)
388 type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES)
389 echelon = models.IntegerField()
390 degre = models.IntegerField()
391 coefficient = models.FloatField()
9afaa55e 392 # Méta
a3121a38
AJ
393 commentaire = models.TextField(null=True, blank=True)
394 date_modification = models.DateField(auto_now=True)
395 actif = models.BooleanField()
396
5d680e84
NC
397 def __unicode__(self):
398 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
399 self.coefficient)
e57fb3d8 400 class Meta:
401 ordering = ['type','echelon','degre','coefficient']
5d680e84 402
6301bd59 403class TauxChange(models.Model):
9afaa55e 404 # Identification
6301bd59 405 id = models.IntegerField(primary_key=True)
9afaa55e 406 devise = models.ForeignKey('Devise', to_field='code', db_column='devise')
6301bd59
OL
407 annee = models.IntegerField()
408 taux = models.FloatField()
9afaa55e 409 # Relations
410 implantation = models.ForeignKey('datamaster_modeles.Implantation',
411 db_column='implantation',
412 related_name='taux_change')
6301bd59 413
03b395db
OL
414 def __unicode__(self):
415 return u"%s %s : %s" % (self.devise, self.annee, self.taux)
416
6301bd59
OL
417class ValeurPointManager(models.Manager):
418 """
419 Manager qui travaille uniquement sur les valeurs du point de l'année en cours.
420 """
421 mois = datetime.datetime.now().month
422 annee_courante = datetime.datetime.now().year
423
424 # Pour le mois de janvier et décembre on mets les 2 années pour faire la transition
425 if mois == 1:
426 filtre_annee = (annee_courante-1, annee_courante)
427 elif mois == 12:
428 filtre_annee = (annee_courante, annee_courante+1)
429 else:
430 filtre_annee = (annee_courante,)
431
432 def get_query_set(self):
433 return super(ValeurPointManager, self).get_query_set().select_related('implantation').filter(annee__in=self.filtre_annee)
434
5d680e84 435
a3121a38 436class ValeurPoint(models.Model):
9afaa55e 437 # Identification
a3121a38
AJ
438 id = models.IntegerField(primary_key=True)
439 valeur = models.FloatField()
9afaa55e 440 implantation = models.ForeignKey('datamaster_modeles.Implantation',
441 db_column='implantation',
442 related_name='valeurs_point')
443 # Méta
a3121a38 444 annee = models.IntegerField()
6301bd59
OL
445
446 # Stockage de tous les taux de change pour optimiser la recherche de la devise associée
447 annee_courante = datetime.datetime.now().year
448 tauxchange = TauxChange.objects.select_related('devise').filter(annee=annee_courante)
449
450 def get_tauxchange_courant(self):
451 """
452 Recherche le taux courant associé à la valeur d'un point.
453 Tous les taux de l'année courante sont chargés, pour optimiser un affichage en liste.
454 (On pourrait probablement améliorer le manager pour lui greffer le taux courant sous forme de JOIN)
455 """
456 for tauxchange in self.tauxchange:
457 if tauxchange.implantation_id == self.implantation_id:
458 return tauxchange
459 return None
a3121a38 460
5d680e84 461 def __unicode__(self):
17353922
OL
462 tx = self.get_tauxchange_courant()
463 if tx:
464 devise_code = tx.devise.code
465 else:
466 devise_code = "??"
da3ca955 467 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
6d704629 468
469 class Meta:
470 ordering = ['valeur']
5d680e84 471
4dd75e7b 472 objects = models.Manager()
6301bd59 473 actuelles = ValeurPointManager()
a3121a38 474
5d680e84 475
a3121a38
AJ
476class Devise(models.Model):
477 id = models.IntegerField(primary_key=True)
478 code = models.CharField(max_length=10, unique=True)
479 nom = models.CharField(max_length=255)
480
5d680e84
NC
481 def __unicode__(self):
482 return u'%s - %s' % (self.code, self.nom)
483
484
a3121a38 485class TypeContrat(models.Model):
9afaa55e 486 # Identification
a3121a38
AJ
487 id = models.IntegerField(primary_key=True)
488 nom = models.CharField(max_length=255)
489 nom_long = models.CharField(max_length=255) #description
9afaa55e 490 categorie = models.CharField(max_length=10,
491 choices=CONTRAT_CATEGORIE_CHOICES)
492 # Méta
a3121a38
AJ
493 actif = models.BooleanField()
494
139686f2 495 def __unicode__(self):
0f23302a 496 return u'%s' % (self.nom)