fix infos manqunates
[auf_rh_dae.git] / project / rh_v1 / models.py
1 # -=- encoding: utf-8 -=-
2
3 import datetime
4 from django.db import models
5 from datamaster_modeles.models import Pays, Implantation
6 from dae.managers import SecurityManager
7
8 GENRE_CHOICES = (
9 ('m', 'Homme'),
10 ('f', 'Femme'),
11 )
12 SITUATION_CHOICES = (
13 ('C', 'Célibataire'),
14 ('F', 'Fiancé'),
15 ('M', 'Marié'),
16 )
17
18 class Employe(models.Model):
19 # Identification
20 id = models.IntegerField(primary_key=True)
21 nom = models.CharField(max_length=255)
22 prenom = models.CharField(max_length=255)
23 nationalite = models.ForeignKey('datamaster_modeles.Pays', to_field='code',
24 related_name='nationalite',
25 db_column='nationalite')
26 date_naissance = models.DateField(null=True, blank=True)
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)
32 date_entree = models.DateField(null=True, blank=True) #devrait pas être là
33 # Coordonnées
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)
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
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)
48
49 def __unicode__(self):
50 return u'%s %s' % (self.prenom, self.nom)
51
52
53 TYPE_DOSSIER_CHOICES = (
54 ('2', 'Local'),
55 ('1', 'Expatrié'),
56 )
57
58 class 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
79 class Dossier(models.Model):
80 # Identification
81 id = models.IntegerField(primary_key=True)
82 code = models.CharField(max_length=10, unique=True)
83 employe = models.ForeignKey('Employe', db_column='employe')
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)
91 complement1 = models.TextField(null=True, blank=True)
92 responsable_implantation1 = models.IntegerField()
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)
100 complement2 = models.TextField(null=True, blank=True)
101 responsable_implantation2 = models.IntegerField()
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)
111 type = models.CharField(max_length=1, choices=TYPE_DOSSIER_CHOICES)
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)
120 regime_travail = models.IntegerField()
121 # Mandat
122 mandat_date_debut = models.DateField()
123 mandat_date_fin = models.DateField(null=True, blank=True)
124 # Contrat
125 contrat_date_debut = models.DateField()
126 contrat_date_fin = models.DateField()
127 type_contrat = models.ForeignKey('TypeContrat', db_column='type_contrat',
128 blank=True, null=True)
129 # Meta
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
134 # Managers
135 objects = DossierManager()
136
137 def __unicode__(self):
138 return u'%s : %s %s' % (self.employe, self.poste1, self.complement1)
139
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:
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
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 """
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, )
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 """
173 return "%s EUR" % (self.get_dernier_salaire_remun().en_euros())
174
175 LIEN_PARENTE_CHOICES = (
176 ('Conjoint', 'Conjoint'),
177 ('Conjointe', 'Conjointe'),
178 ('Fille', 'Fille'),
179 ('Fils', 'Fils'),
180 )
181
182 class AyantDroit(models.Model):
183 # Identification
184 id = models.IntegerField(primary_key=True)
185 nom = models.CharField(max_length=255)
186 prenom = models.CharField(max_length=255)
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
193 commentaire = models.TextField(null=True, blank=True)
194 actif = models.BooleanField()
195
196
197 class Remuneration(models.Model):
198 # Identification
199 id = models.IntegerField(primary_key=True)
200 dossier = models.ForeignKey('Dossier', db_column='dossier')
201 type = models.ForeignKey('TypeRemuneration', db_column='type')
202 type_revalorisation = models.ForeignKey('TypeRevalorisation',
203 db_column='type_revalorisation',
204 null=True, blank=True)
205 montant = models.FloatField(null=True, blank=True)
206 devise = models.ForeignKey('Devise', to_field='id', db_column='devise', null=True, blank=True)
207 date_effective = models.DateField(null=True, blank=True)
208 pourcentage = models.IntegerField(null=True, blank=True)
209 # Méta
210 date_creation = models.DateField(auto_now_add=True)
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é
218
219 def __unicode__(self):
220 try:
221 devise = self.devise.code
222 except:
223 devise = "???"
224 return "%s %s (%s EUR - %s)" % (self.montant, devise, self.en_euros(), self.get_taux_historique(), )
225
226 def get_taux_historique(self):
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
236
237 def en_euros(self):
238 tauxchange = self.get_taux_historique()
239 if tauxchange is not None:
240 return int(self.montant * tauxchange.taux)
241 else:
242 return 0
243
244 class FamilleEmploi(models.Model):
245 # Identification
246 id = models.IntegerField(primary_key=True)
247 nom = models.CharField(max_length=255)
248 # Méta
249 actif = models.BooleanField()
250
251 class TypePoste(models.Model):
252 # Identification
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()
258 famille_emploi = models.ForeignKey('FamilleEmploi',
259 db_column='famille_emploi')
260 # Méta
261 date_modification = models.DateField(auto_now=True)
262 actif = models.BooleanField()
263
264 def __unicode__(self):
265 return u'%s' % self.nom
266
267 class Meta:
268 ordering = ['nom']
269
270
271 TYPE_PAIEMENT_CHOICES = (
272 ('Régulier', 'Régulier'),
273 ('Ponctuel', 'Ponctuel'),
274 )
275
276 NATURE_REMUNERATION_CHOICES = (
277 ('Accessoire', 'Accessoire'),
278 ('Charges', 'Charges'),
279 ('Indemnité', 'Indemnité'),
280 ('RAS', 'RAS'),
281 ('Traitement', 'Traitement'),
282 )
283
284 class TypeRemuneration(models.Model):
285 # Identification
286 id = models.IntegerField(primary_key=True)
287 nom = models.CharField(max_length=255)
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
293 actif = models.BooleanField()
294
295 def __unicode__(self):
296 return u'%s' % self.nom
297
298
299 class TypeRevalorisation(models.Model):
300 # Identification
301 id = models.IntegerField(primary_key=True)
302 nom = models.CharField(max_length=255)
303 # Méta
304 actif = models.BooleanField()
305
306 PROPORTION_CHOICES = (
307 ('0.5', '0.5'),
308 ('1', '1'),
309 )
310
311 class PosteManager(SecurityManager):
312 """
313 Chargement de tous les objets FK existants sur chaque QuerySet.
314 """
315 prefixe_implantation = 'implantation'
316
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
324 class Poste(models.Model):
325 # Identification
326 id = models.IntegerField(primary_key=True)
327 implantation = models.ForeignKey('datamaster_modeles.Implantation',
328 db_column='implantation', related_name='+')
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%)
332 # Méta
333 date_modification = models.DateField(auto_now=True)
334 actif = models.BooleanField()
335
336 # Managers
337 objects = PosteManager()
338
339 def __unicode__(self):
340 return u'%s - %s [%s]' % (self.implantation, self.type_poste.nom,
341 self.id)
342
343
344 class Service(models.Model):
345 # Identification
346 id = models.IntegerField(primary_key=True)
347 nom = models.CharField(max_length=255)
348 # Méta
349 actif = models.BooleanField()
350
351 def __unicode__(self):
352 return u'%s' % self.nom
353
354 class Meta:
355 ordering = ['nom']
356
357
358 TYPE_ORGANISME_CHOICES = (
359 ('MAD', 'Mise à disposition'),
360 ('DET', 'Détachement'),
361 )
362
363 class OrganismeBstg(models.Model):
364 # Identification
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)
368 # Méta
369 actif = models.BooleanField()
370
371 def __unicode__(self):
372 return u'%s (%s)' % (self.nom, self.type)
373
374 class Meta:
375 ordering = ['type', 'nom']
376
377
378 CONTRAT_CATEGORIE_CHOICES= (
379 ('A', 'A'),
380 ('C', 'C'),
381 )
382 class Statut(models.Model):
383 # Identification
384 id = models.IntegerField(primary_key=True)
385 code = models.CharField(max_length=25, unique=True)
386 nom = models.CharField(max_length=255)
387 type_contrat_categorie = models.CharField(max_length=10,
388 choices=CONTRAT_CATEGORIE_CHOICES)
389 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
390 # Méta
391 actif = models.BooleanField()
392
393 def __unicode__(self):
394 return u'%s : %s' % (self.code, self.nom)
395
396 TYPE_CLASSEMENT_CHOICES = (
397 ('S', 'S'),
398 ('T', 'T'),
399 )
400 class Classement(models.Model):
401 # Identification
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()
407 # Méta
408 commentaire = models.TextField(null=True, blank=True)
409 date_modification = models.DateField(auto_now=True)
410 actif = models.BooleanField()
411
412 def __unicode__(self):
413 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
414 self.coefficient)
415 class Meta:
416 ordering = ['type','echelon','degre','coefficient']
417
418 class TauxChange(models.Model):
419 # Identification
420 id = models.IntegerField(primary_key=True)
421 devise = models.ForeignKey('Devise', to_field='id', db_column='devise')
422 annee = models.IntegerField()
423 taux = models.FloatField()
424 # Relations
425 implantation = models.ForeignKey('datamaster_modeles.Implantation',
426 db_column='implantation',
427 related_name='taux_change')
428
429 def __unicode__(self):
430 return u"%s %s : %s" % (self.devise, self.annee, self.taux)
431
432 class 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
450
451 class ValeurPoint(models.Model):
452 # Identification
453 id = models.IntegerField(primary_key=True)
454 valeur = models.FloatField()
455 implantation = models.ForeignKey('datamaster_modeles.Implantation',
456 db_column='implantation',
457 related_name='valeurs_point')
458 # Méta
459 annee = models.IntegerField()
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
475
476 def __unicode__(self):
477 tx = self.get_tauxchange_courant()
478 if tx:
479 devise_code = tx.devise.code
480 else:
481 devise_code = "??"
482 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
483
484 class Meta:
485 ordering = ['valeur']
486
487 objects = models.Manager()
488 actuelles = ValeurPointManager()
489
490
491 class 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
496 def __unicode__(self):
497 return u'%s - %s' % (self.code, self.nom)
498
499
500 class TypeContrat(models.Model):
501 # Identification
502 id = models.IntegerField(primary_key=True)
503 nom = models.CharField(max_length=255)
504 nom_long = models.CharField(max_length=255) #description
505 categorie = models.CharField(max_length=10,
506 choices=CONTRAT_CATEGORIE_CHOICES)
507 # Méta
508 actif = models.BooleanField()
509
510 def __unicode__(self):
511 return u'%s' % (self.nom)