merge rh et dev
[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 return "%s %s" % (self.get_salaire(), self.dernier_salaire_remun().devise.code, )
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 """
169 return "%s EUR" % (self.get_dernier_salaire_remun().en_euros())
170
171 LIEN_PARENTE_CHOICES = (
172 ('Conjoint', 'Conjoint'),
173 ('Conjointe', 'Conjointe'),
174 ('Fille', 'Fille'),
175 ('Fils', 'Fils'),
176 )
177
178 class AyantDroit(models.Model):
179 # Identification
180 id = models.IntegerField(primary_key=True)
181 nom = models.CharField(max_length=255)
182 prenom = models.CharField(max_length=255)
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
189 commentaire = models.TextField(null=True, blank=True)
190 actif = models.BooleanField()
191
192
193 class Remuneration(models.Model):
194 # Identification
195 id = models.IntegerField(primary_key=True)
196 dossier = models.ForeignKey('Dossier', db_column='dossier')
197 type = models.ForeignKey('TypeRemuneration', db_column='type')
198 type_revalorisation = models.ForeignKey('TypeRevalorisation',
199 db_column='type_revalorisation',
200 null=True, blank=True)
201 montant = models.FloatField(null=True, blank=True)
202 devise = models.ForeignKey('Devise', to_field='id', db_column='devise', null=True, blank=True)
203 date_effective = models.DateField(null=True, blank=True)
204 pourcentage = models.IntegerField(null=True, blank=True)
205 # Méta
206 date_creation = models.DateField(auto_now_add=True)
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é
214
215 def __unicode__(self):
216 try:
217 devise = self.devise.code
218 except:
219 devise = "???"
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)
228
229 class FamilleEmploi(models.Model):
230 # Identification
231 id = models.IntegerField(primary_key=True)
232 nom = models.CharField(max_length=255)
233 # Méta
234 actif = models.BooleanField()
235
236 class TypePoste(models.Model):
237 # Identification
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()
243 famille_emploi = models.ForeignKey('FamilleEmploi',
244 db_column='famille_emploi')
245 # Méta
246 date_modification = models.DateField(auto_now=True)
247 actif = models.BooleanField()
248
249 def __unicode__(self):
250 return u'%s' % self.nom
251
252 class Meta:
253 ordering = ['nom']
254
255
256 TYPE_PAIEMENT_CHOICES = (
257 ('Régulier', 'Régulier'),
258 ('Ponctuel', 'Ponctuel'),
259 )
260
261 NATURE_REMUNERATION_CHOICES = (
262 ('Accessoire', 'Accessoire'),
263 ('Charges', 'Charges'),
264 ('Indemnité', 'Indemnité'),
265 ('RAS', 'RAS'),
266 ('Traitement', 'Traitement'),
267 )
268
269 class TypeRemuneration(models.Model):
270 # Identification
271 id = models.IntegerField(primary_key=True)
272 nom = models.CharField(max_length=255)
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
278 actif = models.BooleanField()
279
280 def __unicode__(self):
281 return u'%s' % self.nom
282
283
284 class TypeRevalorisation(models.Model):
285 # Identification
286 id = models.IntegerField(primary_key=True)
287 nom = models.CharField(max_length=255)
288 # Méta
289 actif = models.BooleanField()
290
291 PROPORTION_CHOICES = (
292 ('0.5', '0.5'),
293 ('1', '1'),
294 )
295
296 class PosteManager(SecurityManager):
297 """
298 Chargement de tous les objets FK existants sur chaque QuerySet.
299 """
300 prefixe_implantation = 'implantation'
301
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
309 class Poste(models.Model):
310 # Identification
311 id = models.IntegerField(primary_key=True)
312 implantation = models.ForeignKey('datamaster_modeles.Implantation',
313 db_column='implantation', related_name='+')
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%)
317 # Méta
318 date_modification = models.DateField(auto_now=True)
319 actif = models.BooleanField()
320
321 # Managers
322 objects = PosteManager()
323
324 def __unicode__(self):
325 return u'%s - %s [%s]' % (self.implantation, self.type_poste.nom,
326 self.id)
327
328
329 class Service(models.Model):
330 # Identification
331 id = models.IntegerField(primary_key=True)
332 nom = models.CharField(max_length=255)
333 # Méta
334 actif = models.BooleanField()
335
336 def __unicode__(self):
337 return u'%s' % self.nom
338
339 class Meta:
340 ordering = ['nom']
341
342
343 TYPE_ORGANISME_CHOICES = (
344 ('MAD', 'Mise à disposition'),
345 ('DET', 'Détachement'),
346 )
347
348 class OrganismeBstg(models.Model):
349 # Identification
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)
353 # Méta
354 actif = models.BooleanField()
355
356 def __unicode__(self):
357 return u'%s (%s)' % (self.nom, self.type)
358
359 class Meta:
360 ordering = ['type', 'nom']
361
362
363 CONTRAT_CATEGORIE_CHOICES= (
364 ('A', 'A'),
365 ('C', 'C'),
366 )
367 class Statut(models.Model):
368 # Identification
369 id = models.IntegerField(primary_key=True)
370 code = models.CharField(max_length=25, unique=True)
371 nom = models.CharField(max_length=255)
372 type_contrat_categorie = models.CharField(max_length=10,
373 choices=CONTRAT_CATEGORIE_CHOICES)
374 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
375 # Méta
376 actif = models.BooleanField()
377
378 def __unicode__(self):
379 return u'%s : %s' % (self.code, self.nom)
380
381 TYPE_CLASSEMENT_CHOICES = (
382 ('S', 'S'),
383 ('T', 'T'),
384 )
385 class Classement(models.Model):
386 # Identification
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()
392 # Méta
393 commentaire = models.TextField(null=True, blank=True)
394 date_modification = models.DateField(auto_now=True)
395 actif = models.BooleanField()
396
397 def __unicode__(self):
398 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
399 self.coefficient)
400 class Meta:
401 ordering = ['type','echelon','degre','coefficient']
402
403 class TauxChange(models.Model):
404 # Identification
405 id = models.IntegerField(primary_key=True)
406 devise = models.ForeignKey('Devise', to_field='code', db_column='devise')
407 annee = models.IntegerField()
408 taux = models.FloatField()
409 # Relations
410 implantation = models.ForeignKey('datamaster_modeles.Implantation',
411 db_column='implantation',
412 related_name='taux_change')
413
414 def __unicode__(self):
415 return u"%s %s : %s" % (self.devise, self.annee, self.taux)
416
417 class 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
435
436 class ValeurPoint(models.Model):
437 # Identification
438 id = models.IntegerField(primary_key=True)
439 valeur = models.FloatField()
440 implantation = models.ForeignKey('datamaster_modeles.Implantation',
441 db_column='implantation',
442 related_name='valeurs_point')
443 # Méta
444 annee = models.IntegerField()
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
460
461 def __unicode__(self):
462 tx = self.get_tauxchange_courant()
463 if tx:
464 devise_code = tx.devise.code
465 else:
466 devise_code = "??"
467 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
468
469 class Meta:
470 ordering = ['valeur']
471
472 objects = models.Manager()
473 actuelles = ValeurPointManager()
474
475
476 class 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
481 def __unicode__(self):
482 return u'%s - %s' % (self.code, self.nom)
483
484
485 class TypeContrat(models.Model):
486 # Identification
487 id = models.IntegerField(primary_key=True)
488 nom = models.CharField(max_length=255)
489 nom_long = models.CharField(max_length=255) #description
490 categorie = models.CharField(max_length=10,
491 choices=CONTRAT_CATEGORIE_CHOICES)
492 # Méta
493 actif = models.BooleanField()
494
495 def __unicode__(self):
496 return u'%s' % (self.nom)