autoriser les nx form
[auf_rh_dae.git] / project / dae / models.py
CommitLineData
bd28238f 1# -=- encoding: utf-8 -=-
3f3cf5f3 2
36341125 3import os
5633fa41 4from django.conf import settings
36341125 5from django.core.files.storage import FileSystemStorage
a9c281dd 6from django.db import models
5633fa41 7from django.db.models import Q
a9c281dd 8import reversion
afc204bf 9from workflow import PosteWorkflow, DossierWorkflow
1b217058
OL
10from workflow import dae_groupes, \
11 grp_administrateurs, \
12 grp_gestionnaires, \
13 grp_directeurs_bureau, \
14 grp_drh, \
15 grp_pole_financier, \
16 grp_haute_direction, \
17 grp_service_utilisateurs, \
18 grp_directeurs_service, \
19 grp_correspondants_rh
20
bd28238f 21import datamaster_modeles.models as ref
a9c281dd 22from rh_v1 import models as rh
5633fa41 23from utils import is_user_dans_service, get_employe_from_user
bd28238f
NC
24
25STATUT_RESIDENCE_CHOICES = (
5d680e84
NC
26 ('local', 'Local'),
27 ('expat', 'Expatrié'),
bd28238f
NC
28)
29
30POSTE_APPEL_CHOICES = (
5d680e84
NC
31 ('interne', 'Interne'),
32 ('externe', 'Externe'),
bd28238f
NC
33)
34
35POSTE_STATUT_CHOICES = (
36 ('MAD', 'Mise à disposition'),
37 ('DET', 'Détachement'),
38)
39
d766bf2c 40# Upload de fichiers
36341125
OL
41storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT, base_url=settings.PRIVE_MEDIA_URL)
42
43def poste_piece_dispatch(instance, filename):
fe13cd48 44 path = "poste/%s/%s" % (instance.poste_id, filename)
36341125
OL
45 return path
46
d766bf2c 47def dossier_piece_dispatch(instance, filename):
fe13cd48 48 path = "dossier/%s/%s" % (instance.dossier_id, filename)
d766bf2c
OL
49 return path
50
36341125
OL
51
52class PostePiece(models.Model):
53 poste = models.ForeignKey("Poste")
54 nom = models.CharField(verbose_name="Nom", max_length=255)
55 fichier = models.FileField(verbose_name="Fichier", upload_to=poste_piece_dispatch, storage=storage_prive)
56
1c7d67ce
OL
57class PosteManager(models.Manager):
58 """
59 Chargement de tous les objets FK existants sur chaque QuerySet.
60 """
61 def get_query_set(self):
62 fkeys = (
63 'id_rh',
64 'responsable',
65 'implantation',
66 'type_poste',
67 'service',
68 'classement_min',
69 'classement_max',
70 'valeur_point_min',
71 'valeur_point_max',
72 )
98d51b59
NC
73 return super(PosteManager, self).get_query_set() \
74 .select_related(*fkeys).all()
1c7d67ce 75
5633fa41
OL
76 def ma_region_ou_service(self, user):
77 """
78 Filtrage des postes en fonction du user connecté (region / service)
1b217058
OL
79 On s'intéresse aussi au groupe auquel appartient le user car certains groupes
80 peuvent tout voir.
5633fa41 81 """
1b217058 82
5633fa41 83 employe = get_employe_from_user(user)
1b217058
OL
84
85 ############################################
86 # TRAITEMENT NORMAL
87 ############################################
88
89 # SERVICE
5633fa41
OL
90 if is_user_dans_service(user):
91 q = Q(implantation=employe.implantation)
92 # REGION
93 else:
94 q = Q(implantation__region=employe.implantation.region)
1b217058
OL
95 liste = self.get_query_set().filter(q)
96
97 ############################################
98 # TRAITEMENT POLE FINANCIER
99 ############################################
100 if grp_pole_financier in user.groups.all():
101 liste = self.get_query_set().filter(etat=POSTE_ETAT_FINANCE)
102
103 ############################################
104 # TRAITEMENT HAUTE DIRECTION
105 ############################################
106 if grp_pole_financier in user.groups.all():
107 liste = self.get_query_set().filter(etat=POSTE_ETAT_HAUTE_DIRECTION)
108
109 ############################################
110 # TRAITEMENT DRH
111 ############################################
112 if grp_drh in user.groups.all():
113 liste = self.get_query_set()
114
115 return liste
1c7d67ce 116
8fa94e8b 117class Poste(PosteWorkflow, models.Model):
bd28238f 118 # Modèle existant
5d680e84 119 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
98d51b59
NC
120 editable=False,
121 verbose_name="Mise à jour du poste")
ce110fb9 122 nom = models.CharField(verbose_name="Titre du poste", max_length=255)
5d680e84
NC
123 implantation = models.ForeignKey(ref.Implantation)
124 type_poste = models.ForeignKey(rh.TypePoste, null=True, related_name='+')
98d51b59
NC
125 service = models.ForeignKey(rh.Service, related_name='+',
126 verbose_name=u"Direction/Service/Pôle support")
127 responsable = models.ForeignKey(rh.Poste, related_name='+',
5efcd48e 128 verbose_name="Poste du responsable")
9a85768a 129
5d680e84 130 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
5efcd48e 131 default=100,
132 verbose_name="Temps de travail",
133 help_text="% du temps complet")
5d680e84 134 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
5efcd48e 135 decimal_places=2,
5fe0ced5 136 default=35,
5efcd48e 137 verbose_name="Nb. heures par semaine")
bd28238f
NC
138
139 # Recrutement
154677c3
OL
140 local = models.BooleanField(verbose_name="Local", default=True, blank=True)
141 expatrie = models.BooleanField(verbose_name="Expatrié", default=False, blank=True)
142
5d680e84 143 # TODO null?
a3508c67 144 mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
98d51b59
NC
145 appel = models.CharField(max_length=10, default='interne',
146 verbose_name="Appel à candidature",
5d680e84 147 choices=POSTE_APPEL_CHOICES)
bd28238f
NC
148
149 # Rémunération
5d680e84
NC
150 classement_min = models.ForeignKey(rh.Classement, related_name='+')
151 classement_max = models.ForeignKey(rh.Classement, related_name='+')
7dcb8d40
OL
152
153 # En fait, les coefficient n'ont pas de valeur dans ces cas, les couts sont calculés
154 # et mis dans les coûts globals
155 #coefficient_min = models.FloatField(null=True) # pour classement "hors grille"
156 #coefficient_max = models.FloatField(null=True) # pour classement "hors grille"
157
4dd75e7b
OL
158 valeur_point_min = models.ForeignKey(rh.ValeurPoint, related_name='+', blank=True, null=True)
159 valeur_point_max = models.ForeignKey(rh.ValeurPoint, related_name='+', blank=True, null=True)
3d627bfd 160 devise_min = models.ForeignKey(rh.Devise, default=5, related_name='+')
161 devise_max = models.ForeignKey(rh.Devise, default=5, related_name='+')
5d680e84
NC
162 salaire_min = models.DecimalField(max_digits=12, decimal_places=2,
163 default=0)
164 salaire_max = models.DecimalField(max_digits=12, decimal_places=2,
165 default=0)
166 indemn_min = models.DecimalField(max_digits=12, decimal_places=2,
167 default=0)
168 indemn_max = models.DecimalField(max_digits=12, decimal_places=2,
169 default=0)
170 autre_min = models.DecimalField(max_digits=12, decimal_places=2,
171 default=0)
172 autre_max = models.DecimalField(max_digits=12, decimal_places=2,
173 default=0)
174
175 # Comparatifs de rémunération
176 devise_comparaison = models.ForeignKey(rh.Devise, related_name='+',
a3508c67 177 default=5)
5d680e84
NC
178 comp_locale_min = models.DecimalField(max_digits=12, decimal_places=2,
179 null=True, blank=True)
180 comp_locale_max = models.DecimalField(max_digits=12, decimal_places=2,
181 null=True, blank=True)
182 comp_universite_min = models.DecimalField(max_digits=12, decimal_places=2,
183 null=True, blank=True)
184 comp_universite_max = models.DecimalField(max_digits=12, decimal_places=2,
185 null=True, blank=True)
186 comp_fonctionpub_min = models.DecimalField(max_digits=12, decimal_places=2,
187 null=True, blank=True)
188 comp_fonctionpub_max = models.DecimalField(max_digits=12, decimal_places=2,
189 null=True, blank=True)
190 comp_ong_min = models.DecimalField(max_digits=12, decimal_places=2,
191 null=True, blank=True)
192 comp_ong_max = models.DecimalField(max_digits=12, decimal_places=2,
193 null=True, blank=True)
194 comp_autre_min = models.DecimalField(max_digits=12, decimal_places=2,
195 null=True, blank=True)
196 comp_autre_max = models.DecimalField(max_digits=12, decimal_places=2,
197 null=True, blank=True)
bd28238f 198
2e092e0c
OL
199 # Justification
200 justification = models.TextField()
201
bd28238f 202 # Méta
5d680e84
NC
203 date_creation = models.DateTimeField(auto_now_add=True)
204 date_modification = models.DateTimeField(auto_now=True)
98d51b59 205 date_debut = models.DateField(verbose_name="Date de début",
9fb2ccd9 206 help_text="format: aaaa-mm-jj")
207 date_fin = models.DateField(null=True, blank=True,
208 verbose_name="Date de fin",
209 help_text="format: aaaa-mm-jj")
bd28238f
NC
210 actif = models.BooleanField(default=True)
211
1c7d67ce
OL
212 # Managers
213 objects = PosteManager()
214
03858ba5
OL
215 def _get_key(self):
216 """
217 Les vues sont montées selon une clef spéciale pour identifier la provenance du poste.
218 Cette méthode fournit un moyen de reconstruire cette clef afin de générer les URLs.
219 """
220 return "dae-%s" % self.id
221 key = property(_get_key)
222
f3333b0e
OL
223 def get_dossiers(self):
224 """
225 Liste tous les anciens dossiers liés à ce poste.
226 (Le nom de la relation sur le rh.Poste est mal choisi poste1 au lieu de dossier1)
227 Note1 : seulement le dosssier principal fait l'objet de la recherche.
228 Note2 : les dossiers sont retournés du plus récent au plus vieux. (Ce test est fait
229 en fonction du id, car les dates de création sont absentes de rh v1).
230 """
231 if self.id_rh is None:
232 return []
233 postes = [p for p in self.id_rh.poste1.all()]
234 return sorted(postes, key=lambda poste: poste.id, reverse=True)
235
236 def get_complement_nom(self):
237 """
238 Inspecte les modèles rh v1 pour trouver dans le dernier dossier un complément de titre de poste.
239 """
240 dossiers = self.get_dossiers()
241 if len(dossiers) > 0:
242 nom = dossiers[0].complement1
243 else:
244 nom = ""
a9c281dd 245 return nom
f3333b0e
OL
246
247 def get_employe(self):
248 """
249 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
250 """
251 dossiers = self.get_dossiers()
252 if len(dossiers) > 0:
253 return dossiers[0].employe
254 else:
255 return None
256
179f6b49
OL
257 def get_default_devise(self):
258 """Récupère la devise par défaut en fonction de l'implantation (EUR autrement)"""
259 try:
260 implantation_devise = rh.TauxChange.objects.filter(implantation=self.implantation)[0].devise
261 except:
262 implantation_devise = 5 # EUR
263 return implantation_devise
264
c0413a6f
OL
265 #####################
266 # Classement de poste
267 #####################
268
269 def get_couts_minimum(self):
270 return (float)(self.salaire_min + self.indemn_min + self.autre_min)
271
272 def get_taux_minimum(self):
273 try:
274 return rh.TauxChange.objects.filter(implantation=self.implantation, devise=self.devise_min)[0].taux
275 except:
276 return 1
277
278 def get_couts_minimum_euros(self):
279 return self.get_couts_minimum() * self.get_taux_minimum()
280
281 def get_couts_maximum(self):
282 return (float)(self.salaire_max + self.indemn_max + self.autre_max)
283
284 def get_taux_maximum(self):
285 try:
286 return rh.TauxChange.objects.filter(implantation=self.implantation, devise=self.devise_max)[0].taux
287 except:
288 return 1
289
290 def get_couts_maximum_euros(self):
291 return self.get_couts_maximum() * self.get_taux_maximum()
292
293 ######################
294 # Comparaison de poste
295 ######################
296
297 def get_taux_comparaison(self):
298 try:
299 return rh.TauxChange.objects.filter(implantation=self.implantation, devise=self.devise_comparaison)[0].taux
300 except:
301 return 1
302
303 def get_comp_universite_min_euros(self):
304 return (float)(self.comp_universite_min) * self.get_taux_comparaison()
305
306 def get_comp_fonctionpub_min_euros(self):
307 return (float)(self.comp_fonctionpub_min) * self.get_taux_comparaison()
308
309 def get_comp_locale_min_euros(self):
310 return (float)(self.comp_locale_min) * self.get_taux_comparaison()
311
312 def get_comp_ong_min_euros(self):
313 return (float)(self.comp_ong_min) * self.get_taux_comparaison()
314
315 def get_comp_autre_min_euros(self):
316 return (float)(self.comp_autre_min) * self.get_taux_comparaison()
317
318 def get_comp_universite_max_euros(self):
319 return (float)(self.comp_universite_max) * self.get_taux_comparaison()
320
321 def get_comp_fonctionpub_max_euros(self):
322 return (float)(self.comp_fonctionpub_max) * self.get_taux_comparaison()
323
324 def get_comp_locale_max_euros(self):
325 return (float)(self.comp_locale_max) * self.get_taux_comparaison()
326
327 def get_comp_ong_max_euros(self):
328 return (float)(self.comp_ong_max) * self.get_taux_comparaison()
329
330 def get_comp_autre_max_euros(self):
331 return (float)(self.comp_autre_max) * self.get_taux_comparaison()
332
a9e52624 333
5d680e84 334 def __unicode__(self):
f3333b0e
OL
335 """
336 Cette fonction est consommatrice SQL car elle cherche les dossiers qui ont été liés à celui-ci.
337 """
338 complement_nom_poste = self.get_complement_nom()
c7a4aa2b
OL
339 if complement_nom_poste is None:
340 complement_nom_poste = ""
f3333b0e 341 employe = self.get_employe()
c7a4aa2b
OL
342 if employe is None:
343 employe = "VACANT"
f3333b0e
OL
344 data = (
345 self.implantation,
346 self.type_poste.nom,
347 self.nom,
348 self.id,
349 complement_nom_poste,
350 employe,
351 )
352 return u'%s - %s (%s) [dae-%s %s %s]' % data
5d680e84 353
bd28238f 354
a9c281dd
OL
355# Tester l'enregistrement car les models.py sont importés au complet
356if not reversion.is_registered(Poste):
357 reversion.register(Poste)
358
bd28238f 359
5d680e84
NC
360POSTE_FINANCEMENT_CHOICES = (
361 ('A', 'A - Frais de personnel'),
362 ('B', 'B - Projet(s)-Titre(s)'),
363 ('C', 'C - Autre')
364)
bd28238f
NC
365
366
5d680e84 367class PosteFinancement(models.Model):
5d680e84
NC
368 poste = models.ForeignKey('Poste', related_name='financements')
369 type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
43d04712 370 pourcentage = models.DecimalField(max_digits=12, decimal_places=2,
371 help_text="ex.: 33.33 % (décimale avec point)")
372 commentaire = models.TextField(
373 help_text="Spécifiez la source de financement.")
bd28238f 374
43d04712 375 class Meta:
376 ordering = ['type']
bd28238f 377
c0413a6f
OL
378 def __unicode__(self):
379 return u"%s %s %s" % (self.get_type_display(), self.pourcentage, self.commentaire)
380
bd28238f 381GENRE_CHOICES = (
139686f2
NC
382 ('m', 'Homme'),
383 ('f', 'Femme'),
bd28238f
NC
384)
385
386
387class Employe(models.Model):
bd28238f
NC
388
389 # Modèle existant
da3ca955 390 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+',
391 verbose_name='Employé')
bd28238f 392 nom = models.CharField(max_length=255)
da3ca955 393 prenom = models.CharField(max_length=255, verbose_name='Prénom')
494ff2be
NC
394 genre = models.CharField(max_length=1, choices=GENRE_CHOICES,
395 null=True, blank=True)
bd28238f 396
139686f2
NC
397 def __unicode__(self):
398 return u'%s %s' % (self.prenom, self.nom)
399
bd28238f
NC
400
401COMPTE_COMPTA_CHOICES = (
494ff2be
NC
402 ('coda', 'CODA'),
403 ('scs', 'SCS'),
404 ('aucun', 'Aucun'),
bd28238f
NC
405)
406
d766bf2c
OL
407class DossierPiece(models.Model):
408 dossier = models.ForeignKey("Dossier")
409 nom = models.CharField(verbose_name="Nom", max_length=255)
410 fichier = models.FileField(verbose_name="Fichier", upload_to=dossier_piece_dispatch, storage=storage_prive)
bd28238f 411
afc204bf 412class Dossier(DossierWorkflow, models.Model):
bd28238f
NC
413
414 # Modèle existant
139686f2
NC
415 employe = models.ForeignKey('Employe', related_name='+', editable=False)
416 poste = models.ForeignKey('Poste', related_name='+', editable=False)
5d680e84 417 statut = models.ForeignKey(rh.Statut, related_name='+')
dfc2c344 418 organisme_bstg = models.ForeignKey(rh.OrganismeBstg,
1f109689 419 null=True, blank=True,
dfc2c344 420 verbose_name="Organisme",
421 help_text="Si détaché (DET) ou mis à disposition (MAD), \
422 préciser l'organisme.",
423 related_name='+')
0288adb5
OL
424 organisme_bstg_autre = models.CharField(max_length=255,
425 verbose_name="Autre organisme",
426 help_text="indiquer l'organisme ici s'il n'est pas dans la liste",
427 null=True,
428 blank=True,)
bd28238f 429
139686f2
NC
430 # Données antérieures de l'employé
431 statut_anterieur = models.ForeignKey(
432 rh.Statut, related_name='+', null=True, blank=True,
da3ca955 433 verbose_name='Statut antérieur')
139686f2
NC
434 classement_anterieur = models.ForeignKey(
435 rh.Classement, related_name='+', null=True, blank=True,
436 verbose_name='Classement précédent')
437 salaire_anterieur = models.DecimalField(
438 max_digits=12, decimal_places=2, null=True, default=None,
439 blank=True, verbose_name='Salaire précédent')
440
441 # Données du titulaire précédent
442 employe_anterieur = models.ForeignKey(
443 rh.Employe, related_name='+', null=True, blank=True,
444 verbose_name='Employé précédent')
445 statut_titulaire_anterieur = models.ForeignKey(
446 rh.Statut, related_name='+', null=True, blank=True,
447 verbose_name='Statut titulaire précédent')
448 classement_titulaire_anterieur = models.ForeignKey(
449 rh.Classement, related_name='+', null=True, blank=True,
450 verbose_name='Classement titulaire précédent')
451 salaire_titulaire_anterieur = models.DecimalField(
452 max_digits=12, decimal_places=2, default=None, null=True,
453 blank=True, verbose_name='Salaire titulaire précédent')
494ff2be 454
bd28238f
NC
455 # Recrutement
456 remplacement = models.BooleanField()
4d25e2ba 457 statut_residence = models.CharField(max_length=10, default='local',
458 verbose_name="Statut",
bd28238f
NC
459 choices=STATUT_RESIDENCE_CHOICES)
460
461 # Rémunération
494ff2be
NC
462 classement = models.ForeignKey(rh.Classement, related_name='+',
463 verbose_name='Classement proposé')
464 salaire = models.DecimalField(max_digits=12, decimal_places=2,
bd28238f 465 verbose_name='Salaire de base',
494ff2be 466 null=True, default=None)
e8e75458 467 devise = models.ForeignKey(rh.Devise, default=5, related_name='+')
7ad7408e 468 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
4d25e2ba 469 verbose_name="Régime de travail",
470 help_text="% du temps complet")
139686f2 471 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
4d25e2ba 472 decimal_places=2, verbose_name="Nb. heures par semaine")
bd28238f
NC
473
474 # Contrat
5d680e84 475 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
4d25e2ba 476 contrat_date_debut = models.DateField(help_text="format: aaaa-mm-jj")
1f109689 477 contrat_date_fin = models.DateField(null=True, blank=True,
478 help_text="format: aaaa-mm-jj")
bd28238f
NC
479
480 # Comptes
dfc2c344 481 compte_compta = models.CharField(max_length=10, default='aucun',
482 verbose_name=u'Compte comptabilité',
483 choices=COMPTE_COMPTA_CHOICES)
bd28238f 484 compte_courriel = models.BooleanField()
0140cbd2 485
486 # Méta
487 date_creation = models.DateTimeField(auto_now_add=True)
aec2c91e 488
489 def __unicode__(self):
490 return u'%s - %s' % (self.poste.nom, self.employe)
bd28238f 491
b1baa306
OL
492 def get_salaire_euros(self):
493 try:
494 tx = rh.TauxChange.objects.filter(implantation=self.poste.implantation, devise=self.devise)[0].taux
495 except:
496 tx = 1
497 return (float)(tx) * (float)(self.salaire)
498
57bd966c
OL
499 def get_couts_auf(self):
500 """
501 On retire les MAD BSTG
502 """
503 return [r for r in self.remuneration_set.all() if r.type_id not in (2, )]
a9e52624
OL
504
505 def get_total_couts_auf(self):
506 total = 0.0
507 for r in self.get_couts_auf():
508 total += r.montant_euro()
509 return total
57bd966c
OL
510
511 def get_aides_auf(self):
512 """
513 On récupère les MAD BSTG
514 """
515 return [r for r in self.remuneration_set.all() if r.type_id in (2, )]
516
a9e52624
OL
517 def get_total_aides_auf(self):
518 total = 0.0
519 for r in self.get_aides_auf():
520 total += r.montant_euro()
521 return total
522
523 def get_total_remun(self):
524 return self.get_total_couts_auf() + self.get_total_aides_auf()
525
0140cbd2 526# Tester l'enregistrement car les models.py sont importés au complet
527if not reversion.is_registered(Dossier):
528 reversion.register(Dossier)
bd28238f
NC
529
530class Remuneration(models.Model):
5d680e84 531 # Identification
bd28238f 532 dossier = models.ForeignKey('Dossier', db_column='dossier')
cb1d62b5
NC
533 type = models.ForeignKey(rh.TypeRemuneration, db_column='type',
534 related_name='+')
5d680e84
NC
535 # TODO: what's that?
536 # type_revalorisation = models.ForeignKey('TypeRevalorisation',
537 # db_column='type_revalorisation')
cb1d62b5
NC
538 montant = models.DecimalField(max_digits=12, decimal_places=2,
539 null=True) # Annuel
494ff2be 540 devise = models.ForeignKey(rh.Devise, to_field='code',
5d680e84 541 db_column='devise', related_name='+')
cb1d62b5
NC
542 precision = models.CharField(max_length=255, null=True, blank=True)
543 # date_effective = models.DateField(null=True, blank=True)
544 # pourcentage = models.IntegerField(null=True, blank=True)
bd28238f 545
5d680e84 546 # Méta
bd28238f 547 date_creation = models.DateField(auto_now_add=True)
494ff2be 548 user_creation = models.IntegerField(null=True, blank=True)
cb1d62b5
NC
549 # desactivation = models.BooleanField(default=False, blank=True)
550 # date_desactivation = models.DateField(null=True, blank=True)
551 # user_desactivation = models.IntegerField(null=True, blank=True)
552 # annulation = models.BooleanField(default=False, blank=True)
553 # date_annulation = models.DateField(null=True, blank=True)
554 # user_annulation = models.IntegerField(null=True, blank=True)
bd28238f 555
ee91bc95
NC
556 def montant_mois(self):
557 return round(self.montant / 12, 2)
558
559 def taux_devise(self):
560 return self.devise.tauxchange_set.order_by('-annee').all()[0].taux
561
562 def montant_euro(self):
a9e52624 563 return round(float(self.montant) * float(self.taux_devise()), 2)
ee91bc95
NC
564
565 def montant_euro_mois(self):
566 return round(self.montant_euro() / 12, 2)
bd28238f
NC
567
568
72db8238
OL
569TYPE_JUSTIFICATIONS = (
570 ('N', 'Nouvel employé'),
571 ('R', 'Renouvellement employé'),
572)
bd28238f 573
72db8238
OL
574class JustificationQuestion(models.Model):
575 question = models.CharField(max_length=255)
576 type = models.CharField(max_length=255, choices=TYPE_JUSTIFICATIONS)
577
578 def __unicode__(self,):
579 return self.question
bd28238f 580
72db8238
OL
581class JustificationNouvelEmploye(models.Model):
582 dossier = models.ForeignKey("Dossier")
583 question = models.ForeignKey("JustificationQuestion")
584 reponse = models.TextField()
bd28238f 585
72db8238
OL
586class JustificationAutreEmploye(models.Model):
587 dossier = models.ForeignKey("Dossier")
588 question = models.ForeignKey("JustificationQuestion")
589 reponse = models.TextField()