comparaison salariale
[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" % (remun[0].montant, devise)
129
130 LIEN_PARENTE_CHOICES = (
131 ('Conjoint', 'Conjoint'),
132 ('Conjointe', 'Conjointe'),
133 ('Fille', 'Fille'),
134 ('Fils', 'Fils'),
135 )
136
137 class AyantDroit(models.Model):
138 #Identification
139 id = models.IntegerField(primary_key=True)
140 nom = models.CharField(max_length=255)
141 prenom = models.CharField(max_length=255)
142 #Relation
143 employe = models.ForeignKey('Employe', db_column='employe', related_name='employe')
144 lien_parente = models.CharField(max_length=10, choices=LIEN_PARENTE_CHOICES, null=True, blank=True)
145 #Méta
146 commentaire = models.TextField(null=True, blank=True)
147 actif = models.BooleanField()
148
149
150 class Remuneration(models.Model):
151 #Identification
152 id = models.IntegerField(primary_key=True)
153 dossier = models.ForeignKey('Dossier', db_column='dossier')
154 type = models.ForeignKey('TypeRemuneration', db_column='type')
155 type_revalorisation = models.ForeignKey('TypeRevalorisation', db_column='type_revalorisation', null=True, blank=True)
156 montant = models.FloatField(null=True, blank=True)
157 devise = models.ForeignKey('Devise', to_field='code', db_column='devise', null=True, blank=True)
158 date_effective = models.DateField(null=True, blank=True)
159 pourcentage = models.IntegerField(null=True, blank=True)
160 #Méta
161 date_creation = models.DateField(auto_now_add=True)
162 user_creation = models.IntegerField(null=True, blank=True) #User ou employé
163 desactivation = models.NullBooleanField(null=True, blank=True) #
164 date_desactivation = models.DateField(null=True, blank=True)
165 user_desactivation = models.IntegerField(null=True, blank=True) #User ou employé
166 annulation = models.NullBooleanField(null=True, blank=True)
167 date_annulation = models.DateField(null=True, blank=True)
168 user_annulation = models.IntegerField(null=True, blank=True) #User ou employé
169
170 def __unicode__(self):
171 try:
172 devise = self.devise.code
173 except:
174 devise = "???"
175 return "%s %s" % (self.montant, devise)
176
177 class FamilleEmploi(models.Model):
178 #Identification
179 id = models.IntegerField(primary_key=True)
180 nom = models.CharField(max_length=255)
181 #Méta
182 actif = models.BooleanField()
183
184 class TypePoste(models.Model):
185 #Identification
186 id = models.IntegerField(primary_key=True)
187 nom = models.CharField(max_length=255)
188 nom_feminin = models.CharField(max_length=255)
189 description = models.CharField(max_length=255)
190 is_responsable = models.BooleanField()
191 famille_emploi = models.ForeignKey('FamilleEmploi', db_column='famille_emploi')
192 #Méta
193 date_modification = models.DateField(auto_now=True)
194 actif = models.BooleanField()
195
196 def __unicode__(self):
197 return u'%s' % self.nom
198
199 class Meta:
200 ordering = ['nom']
201
202
203 TYPE_PAIEMENT_CHOICES = (
204 ('Régulier', 'Régulier'),
205 ('Ponctuel', 'Ponctuel'),
206 )
207
208 NATURE_REMUNERATION_CHOICES = (
209 ('Accessoire', 'Accessoire'),
210 ('Charges', 'Charges'),
211 ('Indemnité', 'Indemnité'),
212 ('RAS', 'RAS'),
213 ('Traitement', 'Traitement'),
214 )
215
216 class TypeRemuneration(models.Model):
217 #Identification
218 id = models.IntegerField(primary_key=True)
219 nom = models.CharField(max_length=255)
220 type_paiement = models.CharField(max_length=30, choices=TYPE_PAIEMENT_CHOICES)
221 nature_remuneration = models.CharField(max_length=30, choices=NATURE_REMUNERATION_CHOICES)
222 #Méta
223 actif = models.BooleanField()
224
225 def __unicode__(self):
226 return u'%s' % self.nom
227
228
229 class TypeRevalorisation(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 PROPORTION_CHOICES = (
237 ('0.5', '0.5'),
238 ('1', '1'),
239 )
240
241 class PosteManager(models.Manager):
242 """
243 Chargement de tous les objets FK existants sur chaque QuerySet.
244 """
245 def get_query_set(self):
246 fkeys = (
247 'implantation',
248 'type_poste',
249 )
250 return super(PosteManager, self).get_query_set().select_related(*fkeys).all()
251
252 class Poste(models.Model):
253 #Identification
254 id = models.IntegerField(primary_key=True)
255 implantation = models.ForeignKey('datamaster_modeles.Implantation',
256 db_column='implantation', related_name='+')
257 type_poste = models.ForeignKey('TypePoste', db_column='type_poste')
258 proportion = models.CharField(max_length=10, choices=PROPORTION_CHOICES)
259 #(sert à quoi?) renommer "regime_travail" ou autre? convertir data en % (data * 100; ex: 1 = 100%)
260 #Méta
261 date_modification = models.DateField(auto_now=True)
262 actif = models.BooleanField()
263
264 # Managers
265 objects = PosteManager()
266
267 def __unicode__(self):
268 return u'%s - %s [%s]' % (self.implantation, self.type_poste.nom, self.id)
269
270
271 class Service(models.Model):
272 #Identification
273 id = models.IntegerField(primary_key=True)
274 nom = models.CharField(max_length=255)
275 #Méta
276 actif = models.BooleanField()
277
278 def __unicode__(self):
279 return u'%s' % self.nom
280
281 class Meta:
282 ordering = ['nom']
283
284
285 TYPE_ORGANISME_CHOICES = (
286 ('MAD', 'Mise à disposition'),
287 ('DET', 'Détachement'),
288 )
289
290 class OrganismeBstg(models.Model):
291 #Identification
292 id = models.IntegerField(primary_key=True)
293 nom = models.CharField(max_length=255)
294 type = models.CharField(max_length=10, choices=TYPE_ORGANISME_CHOICES)
295 #Méta
296 actif = models.BooleanField()
297
298 def __unicode__(self):
299 return u'%s (%s)' % (self.nom, self.type)
300
301 class Meta:
302 ordering = ['type', 'nom']
303
304
305 CONTRAT_CATEGORIE_CHOICES= (
306 ('A', 'A'),
307 ('C', 'C'),
308 )
309 class Statut(models.Model):
310 #Identification
311 id = models.IntegerField(primary_key=True)
312 code = models.CharField(max_length=25, unique=True)
313 nom = models.CharField(max_length=255)
314 type_contrat_categorie = models.CharField(max_length=10, choices=CONTRAT_CATEGORIE_CHOICES)
315 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
316 #Méta
317 actif = models.BooleanField()
318
319 def __unicode__(self):
320 return u'%s : %s' % (self.code, self.nom)
321
322 TYPE_CLASSEMENT_CHOICES = (
323 ('S', 'S'),
324 ('T', 'T'),
325 )
326 class Classement(models.Model):
327 #Identification
328 id = models.IntegerField(primary_key=True)
329 type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES)
330 echelon = models.IntegerField()
331 degre = models.IntegerField()
332 coefficient = models.FloatField()
333 #Méta
334 commentaire = models.TextField(null=True, blank=True)
335 date_modification = models.DateField(auto_now=True)
336 actif = models.BooleanField()
337
338 def __unicode__(self):
339 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
340 self.coefficient)
341 class Meta:
342 ordering = ['type','echelon','degre','coefficient']
343
344 class TauxChange(models.Model):
345 #Identification
346 id = models.IntegerField(primary_key=True)
347 devise = models.ForeignKey('Devise', db_column='devise')
348 annee = models.IntegerField()
349 taux = models.FloatField()
350 #Relations
351 implantation = models.ForeignKey('datamaster_modeles.Implantation', db_column='implantation')
352
353 class ValeurPointManager(models.Manager):
354 """
355 Manager qui travaille uniquement sur les valeurs du point de l'année en cours.
356 """
357 mois = datetime.datetime.now().month
358 annee_courante = datetime.datetime.now().year
359
360 # Pour le mois de janvier et décembre on mets les 2 années pour faire la transition
361 if mois == 1:
362 filtre_annee = (annee_courante-1, annee_courante)
363 elif mois == 12:
364 filtre_annee = (annee_courante, annee_courante+1)
365 else:
366 filtre_annee = (annee_courante,)
367
368 def get_query_set(self):
369 return super(ValeurPointManager, self).get_query_set().select_related('implantation').filter(annee__in=self.filtre_annee)
370
371
372 class ValeurPoint(models.Model):
373 #Identification
374 id = models.IntegerField(primary_key=True)
375 valeur = models.FloatField()
376 implantation = models.ForeignKey('datamaster_modeles.Implantation', db_column='implantation')
377 #Méta
378 annee = models.IntegerField()
379
380 # Stockage de tous les taux de change pour optimiser la recherche de la devise associée
381 annee_courante = datetime.datetime.now().year
382 tauxchange = TauxChange.objects.select_related('devise').filter(annee=annee_courante)
383
384 def get_tauxchange_courant(self):
385 """
386 Recherche le taux courant associé à la valeur d'un point.
387 Tous les taux de l'année courante sont chargés, pour optimiser un affichage en liste.
388 (On pourrait probablement améliorer le manager pour lui greffer le taux courant sous forme de JOIN)
389 """
390 for tauxchange in self.tauxchange:
391 if tauxchange.implantation_id == self.implantation_id:
392 return tauxchange
393 return None
394
395 def __unicode__(self):
396 tx = self.get_tauxchange_courant()
397 if tx:
398 devise_code = tx.devise.code
399 else:
400 devise_code = "??"
401 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
402
403 class Meta:
404 ordering = ['valeur']
405
406 objects = models.Manager()
407 actuelles = ValeurPointManager()
408
409
410 class Devise(models.Model):
411 id = models.IntegerField(primary_key=True)
412 code = models.CharField(max_length=10, unique=True)
413 nom = models.CharField(max_length=255)
414
415 def __unicode__(self):
416 return u'%s - %s' % (self.code, self.nom)
417
418
419 class TypeContrat(models.Model):
420 #Identification
421 id = models.IntegerField(primary_key=True)
422 nom = models.CharField(max_length=255)
423 nom_long = models.CharField(max_length=255) #description
424 categorie = models.CharField(max_length=10, choices=CONTRAT_CATEGORIE_CHOICES)
425 #Méta
426 actif = models.BooleanField()
427
428 def __unicode__(self):
429 return u'%s' % (self.nom)