eb1d5c4b9c787246f1bea4dbed70763b1ddbbcfc
[auf_rh_dae.git] / project / dae / models.py
1 # -=- encoding: utf-8 -=-
2 from django.db import models
3
4 import datamaster_modeles.models as ref
5 import project.rh_v1.models as rh
6
7
8 STATUT_RESIDENCE_CHOICES = (
9 ('local', 'Local'),
10 ('expat', 'Expatrié'),
11 )
12
13 POSTE_APPEL_CHOICES = (
14 ('interne', 'Interne'),
15 ('externe', 'Externe'),
16 )
17
18 POSTE_STATUT_CHOICES = (
19 ('MAD', 'Mise à disposition'),
20 ('DET', 'Détachement'),
21 )
22
23 class PosteManager(models.Manager):
24 """
25 Chargement de tous les objets FK existants sur chaque QuerySet.
26 """
27 def get_query_set(self):
28 fkeys = (
29 'id_rh',
30 'responsable',
31 'implantation',
32 'type_poste',
33 'service',
34 'classement_min',
35 'classement_max',
36 'valeur_point_min',
37 'valeur_point_max',
38 )
39 return super(PosteManager, self).get_query_set() \
40 .select_related(*fkeys).all()
41
42
43 class Poste(models.Model):
44 # Modèle existant
45 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
46 editable=False,
47 verbose_name="Mise à jour du poste")
48 nom = models.CharField(verbose_name="Titre du poste", max_length=255)
49 implantation = models.ForeignKey(ref.Implantation)
50 type_poste = models.ForeignKey(rh.TypePoste, null=True, related_name='+')
51 service = models.ForeignKey(rh.Service, related_name='+',
52 verbose_name=u"Direction/Service/Pôle support")
53 responsable = models.ForeignKey(rh.Poste, related_name='+',
54 verbose_name="Poste du responsable")
55
56 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
57 default=100,
58 verbose_name="Temps de travail",
59 help_text="% du temps complet")
60 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
61 decimal_places=2,
62 default=40,
63 verbose_name="Nb. heures par semaine")
64
65 # Recrutement
66 statut_residence = models.CharField(max_length=10, default='MAD',
67 verbose_name="Statut",
68 choices=STATUT_RESIDENCE_CHOICES)
69 # TODO null?
70 mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
71 appel = models.CharField(max_length=10, default='interne',
72 verbose_name="Appel à candidature",
73 choices=POSTE_APPEL_CHOICES)
74
75 # Rémunération
76 classement_min = models.ForeignKey(rh.Classement, related_name='+')
77 classement_max = models.ForeignKey(rh.Classement, related_name='+')
78 coefficient_min = models.FloatField(null=True) # pour classement "hors grille"
79 coefficient_max = models.FloatField(null=True) # pour classement "hors grille"
80 valeur_point_min = models.ForeignKey(rh.ValeurPoint, related_name='+', blank=True, null=True)
81 valeur_point_max = models.ForeignKey(rh.ValeurPoint, related_name='+', blank=True, null=True)
82 devise_min = models.ForeignKey(rh.Devise, default=5, related_name='+')
83 devise_max = models.ForeignKey(rh.Devise, default=5, related_name='+')
84 salaire_min = models.DecimalField(max_digits=12, decimal_places=2,
85 default=0)
86 salaire_max = models.DecimalField(max_digits=12, decimal_places=2,
87 default=0)
88 indemn_min = models.DecimalField(max_digits=12, decimal_places=2,
89 default=0)
90 indemn_max = models.DecimalField(max_digits=12, decimal_places=2,
91 default=0)
92 autre_min = models.DecimalField(max_digits=12, decimal_places=2,
93 default=0)
94 autre_max = models.DecimalField(max_digits=12, decimal_places=2,
95 default=0)
96
97 # Comparatifs de rémunération
98 devise_comparaison = models.ForeignKey(rh.Devise, related_name='+',
99 default=5)
100 comp_locale_min = models.DecimalField(max_digits=12, decimal_places=2,
101 null=True, blank=True)
102 comp_locale_max = models.DecimalField(max_digits=12, decimal_places=2,
103 null=True, blank=True)
104 comp_universite_min = models.DecimalField(max_digits=12, decimal_places=2,
105 null=True, blank=True)
106 comp_universite_max = models.DecimalField(max_digits=12, decimal_places=2,
107 null=True, blank=True)
108 comp_fonctionpub_min = models.DecimalField(max_digits=12, decimal_places=2,
109 null=True, blank=True)
110 comp_fonctionpub_max = models.DecimalField(max_digits=12, decimal_places=2,
111 null=True, blank=True)
112 comp_ong_min = models.DecimalField(max_digits=12, decimal_places=2,
113 null=True, blank=True)
114 comp_ong_max = models.DecimalField(max_digits=12, decimal_places=2,
115 null=True, blank=True)
116 comp_autre_min = models.DecimalField(max_digits=12, decimal_places=2,
117 null=True, blank=True)
118 comp_autre_max = models.DecimalField(max_digits=12, decimal_places=2,
119 null=True, blank=True)
120
121 # Méta
122 date_creation = models.DateTimeField(auto_now_add=True)
123 date_modification = models.DateTimeField(auto_now=True)
124 date_debut = models.DateField(verbose_name="Date de début",
125 help_text="format: aaaa-mm-jj")
126 date_fin = models.DateField(null=True, blank=True,
127 verbose_name="Date de fin",
128 help_text="format: aaaa-mm-jj")
129 actif = models.BooleanField(default=True)
130
131 # Managers
132 objects = PosteManager()
133
134 def get_dossiers(self):
135 """
136 Liste tous les anciens dossiers liés à ce poste.
137 (Le nom de la relation sur le rh.Poste est mal choisi poste1 au lieu de dossier1)
138 Note1 : seulement le dosssier principal fait l'objet de la recherche.
139 Note2 : les dossiers sont retournés du plus récent au plus vieux. (Ce test est fait
140 en fonction du id, car les dates de création sont absentes de rh v1).
141 """
142 if self.id_rh is None:
143 return []
144 postes = [p for p in self.id_rh.poste1.all()]
145 return sorted(postes, key=lambda poste: poste.id, reverse=True)
146
147 def get_complement_nom(self):
148 """
149 Inspecte les modèles rh v1 pour trouver dans le dernier dossier un complément de titre de poste.
150 """
151 dossiers = self.get_dossiers()
152 if len(dossiers) > 0:
153 nom = dossiers[0].complement1
154 else:
155 nom = ""
156
157 if nom == "":
158 return None
159 else:
160 return nom
161
162 def get_employe(self):
163 """
164 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
165 """
166 dossiers = self.get_dossiers()
167 if len(dossiers) > 0:
168 return dossiers[0].employe
169 else:
170 return None
171
172 def __unicode__(self):
173 """
174 Cette fonction est consommatrice SQL car elle cherche les dossiers qui ont été liés à celui-ci.
175 """
176 complement_nom_poste = self.get_complement_nom()
177 if complement_nom_poste is None:
178 complement_nom_poste = ""
179 employe = self.get_employe()
180 if employe is None:
181 employe = "VACANT"
182 data = (
183 self.implantation,
184 self.type_poste.nom,
185 self.nom,
186 self.id,
187 complement_nom_poste,
188 employe,
189 )
190 return u'%s - %s (%s) [dae-%s %s %s]' % data
191
192 def DISABLED_save(self, *args, **kwargs):
193 # calculate nb_mois = nb of months between date_debut and date_fin
194 from datetime import date
195 if not self.salaire_min:
196 self.salaire_min = self.classement_min * self.valeur_point_min
197 if not self.salaire_max:
198 self.salaire_max = self.classement_max * self.valeur_point_min
199 if not self.valeur_point_min:
200 self.valeur_point_min = \
201 rh.ValeurPoint.objects.filter(implantation=self.implantation)
202 if not self.valeur_point_max:
203 self.valeur_point_max = \
204 rh.ValeurPoint.objects.filter(implantation=self.implantation)
205 super(Subject, self).save(*args, **kwargs)
206
207
208 POSTE_FINANCEMENT_CHOICES = (
209 ('A', 'A - Frais de personnel'),
210 ('B', 'B - Projet(s)-Titre(s)'),
211 ('C', 'C - Autre')
212 )
213
214
215 class PosteFinancement(models.Model):
216 montant = models.DecimalField(max_digits=12, decimal_places=2,
217 help_text="ex.: 12000.00 € (décimale avec point, devise = EUR)")
218 poste = models.ForeignKey('Poste', related_name='financements')
219 type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
220 pourcentage = models.DecimalField(max_digits=12, decimal_places=2,
221 help_text="ex.: 33.33 % (décimale avec point)")
222 commentaire = models.TextField(
223 help_text="Spécifiez la source de financement.")
224
225 class Meta:
226 ordering = ['type']
227
228 GENRE_CHOICES = (
229 ('m', 'Homme'),
230 ('f', 'Femme'),
231 )
232
233
234 class Employe(models.Model):
235
236 # Modèle existant
237 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+')
238 nom = models.CharField(max_length=255)
239 prenom = models.CharField(max_length=255)
240 genre = models.CharField(max_length=1, choices=GENRE_CHOICES,
241 null=True, blank=True)
242
243 def __unicode__(self):
244 return u'%s %s' % (self.prenom, self.nom)
245
246
247 COMPTE_COMPTA_CHOICES = (
248 ('coda', 'CODA'),
249 ('scs', 'SCS'),
250 ('aucun', 'Aucun'),
251 )
252
253
254 class Dossier(models.Model):
255
256 # Modèle existant
257 employe = models.ForeignKey('Employe', related_name='+', editable=False)
258 poste = models.ForeignKey('Poste', related_name='+', editable=False)
259 statut = models.ForeignKey(rh.Statut, related_name='+')
260 organisme_bstg = models.ForeignKey(rh.OrganismeBstg, related_name='+')
261
262 # Données antérieures de l'employé
263 statut_anterieur = models.ForeignKey(
264 rh.Statut, related_name='+', null=True, blank=True,
265 verbose_name='Statut précédent')
266 classement_anterieur = models.ForeignKey(
267 rh.Classement, related_name='+', null=True, blank=True,
268 verbose_name='Classement précédent')
269 salaire_anterieur = models.DecimalField(
270 max_digits=12, decimal_places=2, null=True, default=None,
271 blank=True, verbose_name='Salaire précédent')
272
273 # Données du titulaire précédent
274 employe_anterieur = models.ForeignKey(
275 rh.Employe, related_name='+', null=True, blank=True,
276 verbose_name='Employé précédent')
277 statut_titulaire_anterieur = models.ForeignKey(
278 rh.Statut, related_name='+', null=True, blank=True,
279 verbose_name='Statut titulaire précédent')
280 classement_titulaire_anterieur = models.ForeignKey(
281 rh.Classement, related_name='+', null=True, blank=True,
282 verbose_name='Classement titulaire précédent')
283 salaire_titulaire_anterieur = models.DecimalField(
284 max_digits=12, decimal_places=2, default=None, null=True,
285 blank=True, verbose_name='Salaire titulaire précédent')
286
287 # Recrutement
288 remplacement = models.BooleanField()
289 statut_residence = models.CharField(max_length=10,
290 choices=STATUT_RESIDENCE_CHOICES)
291
292 # Rémunération
293 classement = models.ForeignKey(rh.Classement, related_name='+',
294 verbose_name='Classement proposé')
295 salaire = models.DecimalField(max_digits=12, decimal_places=2,
296 verbose_name='Salaire de base',
297 null=True, default=None)
298 devise = models.ForeignKey(rh.Devise, related_name='+')
299 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
300 verbose_name="Régime de travail")
301 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
302 decimal_places=2, verbose_name="Nbr heures par semaine")
303
304 # Contrat
305 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
306 contrat_date_debut = models.DateField()
307 contrat_date_fin = models.DateField()
308
309 # Comptes
310 compte_compta = models.CharField(max_length=10,
311 choices=COMPTE_COMPTA_CHOICES)
312 compte_courriel = models.BooleanField()
313
314
315 class Remuneration(models.Model):
316 # Identification
317 id = models.IntegerField(primary_key=True)
318 dossier = models.ForeignKey('Dossier', db_column='dossier')
319 type = models.ForeignKey('TypeRemuneration', db_column='type')
320 # TODO: what's that?
321 # type_revalorisation = models.ForeignKey('TypeRevalorisation',
322 # db_column='type_revalorisation')
323 montant = models.DecimalField(max_digits=12, decimal_places=2) # Annuel
324 devise = models.ForeignKey(rh.Devise, to_field='code',
325 db_column='devise', related_name='+')
326 date_effective = models.DateField(null=True, blank=True)
327 pourcentage = models.IntegerField(null=True, blank=True)
328
329 # Méta
330 date_creation = models.DateField(auto_now_add=True)
331 user_creation = models.IntegerField(null=True, blank=True)
332 desactivation = models.BooleanField(default=False, blank=True)
333 date_desactivation = models.DateField(null=True, blank=True)
334 user_desactivation = models.IntegerField(null=True, blank=True)
335 annulation = models.BooleanField(default=False, blank=True)
336 date_annulation = models.DateField(null=True, blank=True)
337 user_annulation = models.IntegerField(null=True, blank=True)
338
339
340 class JustificationPoste(models.Model):
341 pass
342
343
344 class JustificationEmploye(models.Model):
345 pass
346
347
348 class DocumentPoste(models.Model):
349 pass
350
351
352 class DocumentEmploye(models.Model):
353 pass
354
355
356 class Validation(models.Model):
357 # user
358 date = models.DateField()
359
360 # avis = ? (CHOICES?)
361
362
363 class ValidationPoste(models.Model):
364 poste = models.ForeignKey('Poste')
365
366
367 class ValidationEmploye(models.Model):
368 employe = models.ForeignKey('Employe')
369
370
371 class TypeRemuneration(models.Model):
372 ordre = models.IntegerField()
373 groupe = models.ForeignKey('GroupeTypeRemuneration')
374
375
376 class GroupeTypeRemuneration(models.Model):
377 nom = models.CharField(max_length=255)
378 ordre = models.IntegerField()