comparaison salariale
[auf_rh_dae.git] / project / rh_v1 / models.py
CommitLineData
a3121a38
AJ
1# -=- encoding: utf-8 -=-
2
6301bd59 3import datetime
a3121a38
AJ
4from django.db import models
5from datamaster_modeles.models import Pays, Implantation
6
7GENRE_CHOICES = (
139686f2
NC
8 ('m', 'Homme'),
9 ('f', 'Femme'),
a3121a38
AJ
10)
11SITUATION_CHOICES = (
12 ('C', 'Célibataire'),
13 ('F', 'Fiancé'),
14 ('M', 'Marié'),
15)
16
17class 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)
139686f2
NC
41
42 def __unicode__(self):
43 return u'%s %s' % (self.prenom, self.nom)
44
45
a3121a38
AJ
46TYPE_DOSSIER_CHOICES = (
47 ('2', 'Local'),
48 ('1', 'Expatrié'),
49)
50
1c7d67ce
OL
51class 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
a3121a38
AJ
72class 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')
f48decfd 79 implantation1 = models.ForeignKey('datamaster_modeles.Implantation', db_column='implantation1', related_name='implantation1', blank=True, null=True)
a3121a38
AJ
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)
f48decfd 83 implantation2 = models.ForeignKey('datamaster_modeles.Implantation', db_column='implantation2', related_name='implantation2', null=True, blank=True)
a3121a38
AJ
84 complement2 = models.TextField(null=True, blank=True)
85 responsable_implantation2 = models.IntegerField()
86 #Relations
f48decfd
NC
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)
a3121a38 90 type = models.CharField(max_length=1, choices=TYPE_DOSSIER_CHOICES)
f48decfd
NC
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)
a3121a38 93 #Rémunération
f48decfd 94 classement = models.ForeignKey('Classement', db_column='classement', blank=True, null=True)
a3121a38
AJ
95 regime_travail = models.IntegerField()
96 #Mandat
97 mandat_date_debut = models.DateField()
f48decfd 98 mandat_date_fin = models.DateField(null=True, blank=True)
a3121a38
AJ
99 #Contrat
100 contrat_date_debut = models.DateField()
101 contrat_date_fin = models.DateField()
f48decfd 102 type_contrat = models.ForeignKey('TypeContrat', db_column='type_contrat', blank=True, null=True)
a3121a38
AJ
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
1c7d67ce
OL
108 # Managers
109 objects = DossierManager()
0f23302a 110
111 def __unicode__(self):
112 return u'%s : %s %s' % (self.employe, self.poste1, self.complement1)
1c7d67ce 113
7e43f9b6
OL
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
a3121a38
AJ
130LIEN_PARENTE_CHOICES = (
131 ('Conjoint', 'Conjoint'),
132 ('Conjointe', 'Conjointe'),
133 ('Fille', 'Fille'),
134 ('Fils', 'Fils'),
135)
136
137class 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
150class 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')
139686f2
NC
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)
a3121a38
AJ
160 #Méta
161 date_creation = models.DateField(auto_now_add=True)
139686f2
NC
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é
a3121a38 169
7e43f9b6
OL
170 def __unicode__(self):
171 try:
172 devise = self.devise.code
173 except:
174 devise = "???"
175 return "%s %s" % (self.montant, devise)
176
a3121a38
AJ
177class 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
184class 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
5d680e84
NC
196 def __unicode__(self):
197 return u'%s' % self.nom
6d704629 198
199 class Meta:
200 ordering = ['nom']
5d680e84
NC
201
202
a3121a38
AJ
203TYPE_PAIEMENT_CHOICES = (
204 ('Régulier', 'Régulier'),
205 ('Ponctuel', 'Ponctuel'),
206)
207
208NATURE_REMUNERATION_CHOICES = (
209 ('Accessoire', 'Accessoire'),
210 ('Charges', 'Charges'),
211 ('Indemnité', 'Indemnité'),
212 ('RAS', 'RAS'),
213 ('Traitement', 'Traitement'),
214)
215
216class 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()
cb1d62b5
NC
224
225 def __unicode__(self):
226 return u'%s' % self.nom
227
228
a3121a38
AJ
229class 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
236PROPORTION_CHOICES = (
237 ('0.5', '0.5'),
238 ('1', '1'),
239)
240
1c7d67ce
OL
241class 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
a3121a38
AJ
252class Poste(models.Model):
253 #Identification
254 id = models.IntegerField(primary_key=True)
5d680e84
NC
255 implantation = models.ForeignKey('datamaster_modeles.Implantation',
256 db_column='implantation', related_name='+')
a3121a38
AJ
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
1c7d67ce
OL
264 # Managers
265 objects = PosteManager()
266
5d680e84 267 def __unicode__(self):
6d704629 268 return u'%s - %s [%s]' % (self.implantation, self.type_poste.nom, self.id)
5d680e84
NC
269
270
a3121a38
AJ
271class 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
5d680e84
NC
278 def __unicode__(self):
279 return u'%s' % self.nom
6d704629 280
281 class Meta:
282 ordering = ['nom']
5d680e84
NC
283
284
a3121a38
AJ
285TYPE_ORGANISME_CHOICES = (
286 ('MAD', 'Mise à disposition'),
287 ('DET', 'Détachement'),
288)
289
290class 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
139686f2
NC
298 def __unicode__(self):
299 return u'%s (%s)' % (self.nom, self.type)
300
0f23302a 301 class Meta:
302 ordering = ['type', 'nom']
303
139686f2 304
a3121a38
AJ
305CONTRAT_CATEGORIE_CHOICES= (
306 ('A', 'A'),
307 ('C', 'C'),
308)
309class 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
139686f2 319 def __unicode__(self):
0f23302a 320 return u'%s : %s' % (self.code, self.nom)
139686f2 321
a3121a38
AJ
322TYPE_CLASSEMENT_CHOICES = (
323 ('S', 'S'),
324 ('T', 'T'),
325)
326class 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
5d680e84
NC
338 def __unicode__(self):
339 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
340 self.coefficient)
e57fb3d8 341 class Meta:
342 ordering = ['type','echelon','degre','coefficient']
5d680e84 343
6301bd59
OL
344class 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
353class 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
5d680e84 371
a3121a38
AJ
372class 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()
6301bd59
OL
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
a3121a38 394
5d680e84 395 def __unicode__(self):
17353922
OL
396 tx = self.get_tauxchange_courant()
397 if tx:
398 devise_code = tx.devise.code
399 else:
400 devise_code = "??"
da3ca955 401 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
6d704629 402
403 class Meta:
404 ordering = ['valeur']
5d680e84 405
4dd75e7b 406 objects = models.Manager()
6301bd59 407 actuelles = ValeurPointManager()
a3121a38 408
5d680e84 409
a3121a38
AJ
410class 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
5d680e84
NC
415 def __unicode__(self):
416 return u'%s - %s' % (self.code, self.nom)
417
418
a3121a38
AJ
419class 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
139686f2 428 def __unicode__(self):
0f23302a 429 return u'%s' % (self.nom)