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