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