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