initial complement nom poste
[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
1c7d67ce
OL
23class 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 )
98d51b59
NC
39 return super(PosteManager, self).get_query_set() \
40 .select_related(*fkeys).all()
1c7d67ce
OL
41
42
bd28238f 43class Poste(models.Model):
bd28238f 44 # Modèle existant
5d680e84 45 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
98d51b59
NC
46 editable=False,
47 verbose_name="Mise à jour du poste")
ce110fb9 48 nom = models.CharField(verbose_name="Titre du poste", max_length=255)
5d680e84
NC
49 implantation = models.ForeignKey(ref.Implantation)
50 type_poste = models.ForeignKey(rh.TypePoste, null=True, related_name='+')
98d51b59
NC
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='+',
5efcd48e 54 verbose_name="Poste du responsable")
9a85768a 55
5d680e84 56 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
5efcd48e 57 default=100,
58 verbose_name="Temps de travail",
59 help_text="% du temps complet")
5d680e84 60 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
5efcd48e 61 decimal_places=2,
62 default=40,
63 verbose_name="Nb. heures par semaine")
bd28238f
NC
64
65 # Recrutement
98d51b59 66 statut_residence = models.CharField(max_length=10, default='MAD',
5efcd48e 67 verbose_name="Statut",
bd28238f 68 choices=STATUT_RESIDENCE_CHOICES)
5d680e84 69 # TODO null?
a3508c67 70 mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
98d51b59
NC
71 appel = models.CharField(max_length=10, default='interne',
72 verbose_name="Appel à candidature",
5d680e84 73 choices=POSTE_APPEL_CHOICES)
bd28238f
NC
74
75 # Rémunération
5d680e84
NC
76 classement_min = models.ForeignKey(rh.Classement, related_name='+')
77 classement_max = models.ForeignKey(rh.Classement, related_name='+')
96d32304 78 coefficient_min = models.FloatField(null=True) # pour classement "hors grille"
79 coefficient_max = models.FloatField(null=True) # pour classement "hors grille"
4dd75e7b
OL
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)
3d627bfd 82 devise_min = models.ForeignKey(rh.Devise, default=5, related_name='+')
83 devise_max = models.ForeignKey(rh.Devise, default=5, related_name='+')
5d680e84
NC
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='+',
a3508c67 99 default=5)
5d680e84
NC
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)
bd28238f
NC
120
121 # Méta
5d680e84
NC
122 date_creation = models.DateTimeField(auto_now_add=True)
123 date_modification = models.DateTimeField(auto_now=True)
98d51b59 124 date_debut = models.DateField(verbose_name="Date de début",
9fb2ccd9 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")
bd28238f
NC
129 actif = models.BooleanField(default=True)
130
1c7d67ce
OL
131 # Managers
132 objects = PosteManager()
133
f3333b0e
OL
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
5d680e84 172 def __unicode__(self):
f3333b0e
OL
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()
c7a4aa2b
OL
177 if complement_nom_poste is None:
178 complement_nom_poste = ""
f3333b0e 179 employe = self.get_employe()
c7a4aa2b
OL
180 if employe is None:
181 employe = "VACANT"
f3333b0e
OL
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
5d680e84
NC
191
192 def DISABLED_save(self, *args, **kwargs):
bd28238f
NC
193 # calculate nb_mois = nb of months between date_debut and date_fin
194 from datetime import date
bd28238f
NC
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
5d680e84
NC
208POSTE_FINANCEMENT_CHOICES = (
209 ('A', 'A - Frais de personnel'),
210 ('B', 'B - Projet(s)-Titre(s)'),
211 ('C', 'C - Autre')
212)
bd28238f
NC
213
214
5d680e84 215class PosteFinancement(models.Model):
43d04712 216 montant = models.DecimalField(max_digits=12, decimal_places=2,
217 help_text="ex.: 12000.00 € (décimale avec point, devise = EUR)")
5d680e84
NC
218 poste = models.ForeignKey('Poste', related_name='financements')
219 type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
43d04712 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.")
bd28238f 224
43d04712 225 class Meta:
226 ordering = ['type']
bd28238f
NC
227
228GENRE_CHOICES = (
139686f2
NC
229 ('m', 'Homme'),
230 ('f', 'Femme'),
bd28238f
NC
231)
232
233
234class Employe(models.Model):
bd28238f
NC
235
236 # Modèle existant
5d680e84 237 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+')
bd28238f
NC
238 nom = models.CharField(max_length=255)
239 prenom = models.CharField(max_length=255)
494ff2be
NC
240 genre = models.CharField(max_length=1, choices=GENRE_CHOICES,
241 null=True, blank=True)
bd28238f 242
139686f2
NC
243 def __unicode__(self):
244 return u'%s %s' % (self.prenom, self.nom)
245
bd28238f
NC
246
247COMPTE_COMPTA_CHOICES = (
494ff2be
NC
248 ('coda', 'CODA'),
249 ('scs', 'SCS'),
250 ('aucun', 'Aucun'),
bd28238f
NC
251)
252
253
254class Dossier(models.Model):
bd28238f
NC
255
256 # Modèle existant
139686f2
NC
257 employe = models.ForeignKey('Employe', related_name='+', editable=False)
258 poste = models.ForeignKey('Poste', related_name='+', editable=False)
5d680e84
NC
259 statut = models.ForeignKey(rh.Statut, related_name='+')
260 organisme_bstg = models.ForeignKey(rh.OrganismeBstg, related_name='+')
bd28238f 261
139686f2
NC
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')
494ff2be 286
bd28238f
NC
287 # Recrutement
288 remplacement = models.BooleanField()
bd28238f
NC
289 statut_residence = models.CharField(max_length=10,
290 choices=STATUT_RESIDENCE_CHOICES)
291
292 # Rémunération
494ff2be
NC
293 classement = models.ForeignKey(rh.Classement, related_name='+',
294 verbose_name='Classement proposé')
295 salaire = models.DecimalField(max_digits=12, decimal_places=2,
bd28238f 296 verbose_name='Salaire de base',
494ff2be 297 null=True, default=None)
5d680e84 298 devise = models.ForeignKey(rh.Devise, related_name='+')
7ad7408e
NC
299 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
300 verbose_name="Régime de travail")
139686f2 301 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
7ad7408e 302 decimal_places=2, verbose_name="Nbr heures par semaine")
bd28238f
NC
303
304 # Contrat
5d680e84 305 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
bd28238f
NC
306 contrat_date_debut = models.DateField()
307 contrat_date_fin = models.DateField()
bd28238f
NC
308
309 # Comptes
310 compte_compta = models.CharField(max_length=10,
311 choices=COMPTE_COMPTA_CHOICES)
312 compte_courriel = models.BooleanField()
313
314
315class Remuneration(models.Model):
5d680e84 316 # Identification
bd28238f
NC
317 id = models.IntegerField(primary_key=True)
318 dossier = models.ForeignKey('Dossier', db_column='dossier')
319 type = models.ForeignKey('TypeRemuneration', db_column='type')
5d680e84
NC
320 # TODO: what's that?
321 # type_revalorisation = models.ForeignKey('TypeRevalorisation',
322 # db_column='type_revalorisation')
98d51b59 323 montant = models.DecimalField(max_digits=12, decimal_places=2) # Annuel
494ff2be 324 devise = models.ForeignKey(rh.Devise, to_field='code',
5d680e84 325 db_column='devise', related_name='+')
494ff2be
NC
326 date_effective = models.DateField(null=True, blank=True)
327 pourcentage = models.IntegerField(null=True, blank=True)
bd28238f 328
5d680e84 329 # Méta
bd28238f 330 date_creation = models.DateField(auto_now_add=True)
494ff2be 331 user_creation = models.IntegerField(null=True, blank=True)
139686f2 332 desactivation = models.BooleanField(default=False, blank=True)
494ff2be
NC
333 date_desactivation = models.DateField(null=True, blank=True)
334 user_desactivation = models.IntegerField(null=True, blank=True)
139686f2
NC
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)
bd28238f
NC
338
339
340class JustificationPoste(models.Model):
341 pass
342
343
344class JustificationEmploye(models.Model):
345 pass
346
347
348class DocumentPoste(models.Model):
349 pass
350
351
352class DocumentEmploye(models.Model):
353 pass
354
355
356class Validation(models.Model):
357 # user
358 date = models.DateField()
359
360 # avis = ? (CHOICES?)
361
362
363class ValidationPoste(models.Model):
364 poste = models.ForeignKey('Poste')
365
366
367class ValidationEmploye(models.Model):
368 employe = models.ForeignKey('Employe')
369
370
371class TypeRemuneration(models.Model):
372 ordre = models.IntegerField()
373 groupe = models.ForeignKey('GroupeTypeRemuneration')
374
375
376class GroupeTypeRemuneration(models.Model):
377 nom = models.CharField(max_length=255)
378 ordre = models.IntegerField()