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