ajout PJ au dossier (NON TESTE, ajax fait disparaitre mon form...)
[auf_rh_dae.git] / project / dae / models.py
CommitLineData
bd28238f 1# -=- encoding: utf-8 -=-
3f3cf5f3 2
36341125
OL
3import os
4from django.core.files.storage import FileSystemStorage
a9c281dd
OL
5from django.db import models
6import reversion
bd28238f 7import datamaster_modeles.models as ref
a9c281dd 8from rh_v1 import models as rh
36341125 9import settings
bd28238f
NC
10
11STATUT_RESIDENCE_CHOICES = (
5d680e84
NC
12 ('local', 'Local'),
13 ('expat', 'Expatrié'),
bd28238f
NC
14)
15
16POSTE_APPEL_CHOICES = (
5d680e84
NC
17 ('interne', 'Interne'),
18 ('externe', 'Externe'),
bd28238f
NC
19)
20
21POSTE_STATUT_CHOICES = (
22 ('MAD', 'Mise à disposition'),
23 ('DET', 'Détachement'),
24)
25
d766bf2c 26# Upload de fichiers
36341125
OL
27storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT, base_url=settings.PRIVE_MEDIA_URL)
28
29def poste_piece_dispatch(instance, filename):
30 path = "poste/%s/%s" % (instance.poste.id, filename)
31 return path
32
d766bf2c
OL
33def dossier_piece_dispatch(instance, filename):
34 path = "dossier/%s/%s" % (instance.dossier.id, filename)
35 return path
36
36341125
OL
37
38class 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
1c7d67ce
OL
43class 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 )
98d51b59
NC
59 return super(PosteManager, self).get_query_set() \
60 .select_related(*fkeys).all()
1c7d67ce
OL
61
62
bd28238f 63class Poste(models.Model):
bd28238f 64 # Modèle existant
5d680e84 65 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
98d51b59
NC
66 editable=False,
67 verbose_name="Mise à jour du poste")
ce110fb9 68 nom = models.CharField(verbose_name="Titre du poste", max_length=255)
5d680e84
NC
69 implantation = models.ForeignKey(ref.Implantation)
70 type_poste = models.ForeignKey(rh.TypePoste, null=True, related_name='+')
98d51b59
NC
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='+',
5efcd48e 74 verbose_name="Poste du responsable")
9a85768a 75
5d680e84 76 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
5efcd48e 77 default=100,
78 verbose_name="Temps de travail",
79 help_text="% du temps complet")
5d680e84 80 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
5efcd48e 81 decimal_places=2,
82 default=40,
83 verbose_name="Nb. heures par semaine")
bd28238f
NC
84
85 # Recrutement
98d51b59 86 statut_residence = models.CharField(max_length=10, default='MAD',
5efcd48e 87 verbose_name="Statut",
bd28238f 88 choices=STATUT_RESIDENCE_CHOICES)
5d680e84 89 # TODO null?
a3508c67 90 mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
98d51b59
NC
91 appel = models.CharField(max_length=10, default='interne',
92 verbose_name="Appel à candidature",
5d680e84 93 choices=POSTE_APPEL_CHOICES)
bd28238f
NC
94
95 # Rémunération
5d680e84
NC
96 classement_min = models.ForeignKey(rh.Classement, related_name='+')
97 classement_max = models.ForeignKey(rh.Classement, related_name='+')
96d32304 98 coefficient_min = models.FloatField(null=True) # pour classement "hors grille"
99 coefficient_max = models.FloatField(null=True) # pour classement "hors grille"
4dd75e7b
OL
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)
3d627bfd 102 devise_min = models.ForeignKey(rh.Devise, default=5, related_name='+')
103 devise_max = models.ForeignKey(rh.Devise, default=5, related_name='+')
5d680e84
NC
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='+',
a3508c67 119 default=5)
5d680e84
NC
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)
bd28238f
NC
140
141 # Méta
5d680e84
NC
142 date_creation = models.DateTimeField(auto_now_add=True)
143 date_modification = models.DateTimeField(auto_now=True)
98d51b59 144 date_debut = models.DateField(verbose_name="Date de début",
9fb2ccd9 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")
bd28238f
NC
149 actif = models.BooleanField(default=True)
150
1c7d67ce
OL
151 # Managers
152 objects = PosteManager()
153
f3333b0e
OL
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 = ""
a9c281dd 176 return nom
f3333b0e
OL
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
5d680e84 188 def __unicode__(self):
f3333b0e
OL
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()
c7a4aa2b
OL
193 if complement_nom_poste is None:
194 complement_nom_poste = ""
f3333b0e 195 employe = self.get_employe()
c7a4aa2b
OL
196 if employe is None:
197 employe = "VACANT"
f3333b0e
OL
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
5d680e84
NC
207
208 def DISABLED_save(self, *args, **kwargs):
bd28238f
NC
209 # calculate nb_mois = nb of months between date_debut and date_fin
210 from datetime import date
bd28238f
NC
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
a9c281dd
OL
223# Tester l'enregistrement car les models.py sont importés au complet
224if not reversion.is_registered(Poste):
225 reversion.register(Poste)
226
bd28238f 227
5d680e84
NC
228POSTE_FINANCEMENT_CHOICES = (
229 ('A', 'A - Frais de personnel'),
230 ('B', 'B - Projet(s)-Titre(s)'),
231 ('C', 'C - Autre')
232)
bd28238f
NC
233
234
5d680e84 235class PosteFinancement(models.Model):
43d04712 236 montant = models.DecimalField(max_digits=12, decimal_places=2,
237 help_text="ex.: 12000.00 € (décimale avec point, devise = EUR)")
5d680e84
NC
238 poste = models.ForeignKey('Poste', related_name='financements')
239 type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
43d04712 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.")
bd28238f 244
43d04712 245 class Meta:
246 ordering = ['type']
bd28238f
NC
247
248GENRE_CHOICES = (
139686f2
NC
249 ('m', 'Homme'),
250 ('f', 'Femme'),
bd28238f
NC
251)
252
253
254class Employe(models.Model):
bd28238f
NC
255
256 # Modèle existant
da3ca955 257 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+',
258 verbose_name='Employé')
bd28238f 259 nom = models.CharField(max_length=255)
da3ca955 260 prenom = models.CharField(max_length=255, verbose_name='Prénom')
494ff2be
NC
261 genre = models.CharField(max_length=1, choices=GENRE_CHOICES,
262 null=True, blank=True)
bd28238f 263
139686f2
NC
264 def __unicode__(self):
265 return u'%s %s' % (self.prenom, self.nom)
266
bd28238f
NC
267
268COMPTE_COMPTA_CHOICES = (
494ff2be
NC
269 ('coda', 'CODA'),
270 ('scs', 'SCS'),
271 ('aucun', 'Aucun'),
bd28238f
NC
272)
273
d766bf2c
OL
274class 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)
bd28238f
NC
278
279class Dossier(models.Model):
bd28238f
NC
280
281 # Modèle existant
139686f2
NC
282 employe = models.ForeignKey('Employe', related_name='+', editable=False)
283 poste = models.ForeignKey('Poste', related_name='+', editable=False)
5d680e84
NC
284 statut = models.ForeignKey(rh.Statut, related_name='+')
285 organisme_bstg = models.ForeignKey(rh.OrganismeBstg, related_name='+')
bd28238f 286
139686f2
NC
287 # Données antérieures de l'employé
288 statut_anterieur = models.ForeignKey(
289 rh.Statut, related_name='+', null=True, blank=True,
da3ca955 290 verbose_name='Statut antérieur')
291 #type contrat
139686f2
NC
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')
494ff2be 312
bd28238f
NC
313 # Recrutement
314 remplacement = models.BooleanField()
bd28238f
NC
315 statut_residence = models.CharField(max_length=10,
316 choices=STATUT_RESIDENCE_CHOICES)
317
318 # Rémunération
494ff2be
NC
319 classement = models.ForeignKey(rh.Classement, related_name='+',
320 verbose_name='Classement proposé')
321 salaire = models.DecimalField(max_digits=12, decimal_places=2,
bd28238f 322 verbose_name='Salaire de base',
494ff2be 323 null=True, default=None)
5d680e84 324 devise = models.ForeignKey(rh.Devise, related_name='+')
7ad7408e
NC
325 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
326 verbose_name="Régime de travail")
139686f2 327 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
7ad7408e 328 decimal_places=2, verbose_name="Nbr heures par semaine")
bd28238f
NC
329
330 # Contrat
5d680e84 331 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
bd28238f
NC
332 contrat_date_debut = models.DateField()
333 contrat_date_fin = models.DateField()
bd28238f
NC
334
335 # Comptes
336 compte_compta = models.CharField(max_length=10,
337 choices=COMPTE_COMPTA_CHOICES)
338 compte_courriel = models.BooleanField()
339
340
341class Remuneration(models.Model):
5d680e84 342 # Identification
bd28238f
NC
343 id = models.IntegerField(primary_key=True)
344 dossier = models.ForeignKey('Dossier', db_column='dossier')
345 type = models.ForeignKey('TypeRemuneration', db_column='type')
5d680e84
NC
346 # TODO: what's that?
347 # type_revalorisation = models.ForeignKey('TypeRevalorisation',
348 # db_column='type_revalorisation')
98d51b59 349 montant = models.DecimalField(max_digits=12, decimal_places=2) # Annuel
494ff2be 350 devise = models.ForeignKey(rh.Devise, to_field='code',
5d680e84 351 db_column='devise', related_name='+')
494ff2be
NC
352 date_effective = models.DateField(null=True, blank=True)
353 pourcentage = models.IntegerField(null=True, blank=True)
bd28238f 354
5d680e84 355 # Méta
bd28238f 356 date_creation = models.DateField(auto_now_add=True)
494ff2be 357 user_creation = models.IntegerField(null=True, blank=True)
139686f2 358 desactivation = models.BooleanField(default=False, blank=True)
494ff2be
NC
359 date_desactivation = models.DateField(null=True, blank=True)
360 user_desactivation = models.IntegerField(null=True, blank=True)
139686f2
NC
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)
bd28238f
NC
364
365
366class JustificationPoste(models.Model):
367 pass
368
369
370class JustificationEmploye(models.Model):
371 pass
372
373
374class DocumentPoste(models.Model):
375 pass
376
377
378class DocumentEmploye(models.Model):
379 pass
380
381
382class Validation(models.Model):
383 # user
384 date = models.DateField()
385
386 # avis = ? (CHOICES?)
387
388
389class ValidationPoste(models.Model):
390 poste = models.ForeignKey('Poste')
391
392
393class ValidationEmploye(models.Model):
394 employe = models.ForeignKey('Employe')
395
396
397class TypeRemuneration(models.Model):
398 ordre = models.IntegerField()
399 groupe = models.ForeignKey('GroupeTypeRemuneration')
400
401
402class GroupeTypeRemuneration(models.Model):
403 nom = models.CharField(max_length=255)
404 ordre = models.IntegerField()