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