utilisation de inline formset dans le form pour le financement
[auf_rh_dae.git] / project / dae / forms.py
CommitLineData
5d680e84 1# -*- encoding: utf-8 -*-
ce110fb9 2
5d680e84 3from django import forms
36341125 4from django.forms.models import inlineformset_factory
e88caaf0 5from django.contrib.admin import widgets as admin_widgets
8fa94e8b 6from auf.django.workflow.forms import WorkflowFormMixin
5d680e84
NC
7from datamaster_modeles import models as ref
8
9from dae import models as dae
10from rh_v1 import models as rh
11
9cb4de55
OL
12
13class PostePieceForm(inlineformset_factory(dae.Poste, dae.PostePiece)):
14 pass
15
16class DossierPieceForm(inlineformset_factory(dae.Dossier, dae.DossierPiece)):
17 pass
18
151e7bd0
OL
19class FinancementForm(inlineformset_factory(dae.Poste, dae.PosteFinancement, extra=1)):
20 pass
21
5d680e84 22
a05cc82d
OL
23class PosteValidationForm(forms.ModelForm):
24 """ Validation d'un poste"""
25 class Meta:
26 model = dae.Poste
27 fields = (
28 'validation_bureau_regional',
29 'validation_drh',
30 'validation_secretaire_general',
31 'validation_recteur',
32 )
33
8fa94e8b 34class PosteForm(WorkflowFormMixin):
5d680e84
NC
35 """ Formulaire des postes. """
36 class Meta:
37 model = dae.Poste
ce110fb9 38
5d680e84
NC
39 fields = ('poste', 'implantation', 'type_poste', 'service', 'nom',
40 'responsable', 'statut_residence', 'mise_a_disposition',
41 'appel', 'date_debut', 'date_fin', 'actif',
42 'regime_travail', 'regime_travail_nb_heure_semaine',
43 'classement_min', 'classement_max',
96d32304 44 'coefficient_min', 'coefficient_max',
5d680e84 45 'valeur_point_min', 'valeur_point_max',
3d627bfd 46 'devise_min', 'devise_max',
5d680e84
NC
47 'salaire_min', 'salaire_max', 'indemn_min', 'indemn_max',
48 'autre_min', 'autre_max', 'devise_comparaison',
49 'comp_locale_min', 'comp_locale_max',
50 'comp_universite_min', 'comp_universite_max',
51 'comp_fonctionpub_min', 'comp_fonctionpub_max',
52 'comp_ong_min', 'comp_ong_max',
8fa94e8b
OL
53 'comp_autre_min', 'comp_autre_max',
54 'etat',
55 )
5d680e84 56 widgets = dict(statut_residence=forms.RadioSelect(),
ce110fb9 57 appel=forms.RadioSelect(),
3d627bfd 58 nom=forms.TextInput(attrs={'size': 60},),
e88caaf0
OL
59 date_debut=admin_widgets.AdminDateWidget(),
60 date_fin=admin_widgets.AdminDateWidget(),
3d627bfd 61 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
62 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
63 )
5d680e84 64
98d51b59 65 responsable = forms.ModelChoiceField(
139686f2
NC
66 queryset=rh.Poste.objects.select_related(depth=1))
67
5d680e84 68 # La liste des choix est laissée vide. Voir __init__ pour la raison.
5efcd48e 69 poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste",
d949462d 70 choices=(), required=False)
5d680e84 71
4dd75e7b
OL
72 valeur_point_min = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
73 valeur_point_max = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
6301bd59 74
5d680e84
NC
75 def __init__(self, *args, **kwargs):
76 """ Mise à jour dynamique du contenu du menu des postes.
77
78 Si on ne met le menu à jour de cette façon, à chaque instantiation du
79 formulaire, son contenu est mis en cache par le système et il ne
80 reflète pas les changements apportés par les ajouts, modifications,
81 etc...
82
139686f2
NC
83 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
84 car le "id" de chaque choix est spécial (voir _poste_choices).
85
5d680e84
NC
86 """
87 super(PosteForm, self).__init__(*args, **kwargs)
88 self.fields['poste'].choices = self._poste_choices()
89
cc3098d0
OL
90 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
91 if self.instance and self.instance.id is None:
92 dossiers = self.instance.get_dossiers()
93 if len(dossiers) > 0:
94 self.initial['service'] = dossiers[0].service_id
9508a5b8
OL
95 self.initial['nom'] = "%s %s" % (self.initial['nom'], self.instance.get_complement_nom())
96
cc3098d0 97
5d680e84
NC
98 def _poste_choices(self):
99 """ Menu déroulant pour les postes.
100
101 Constitué des postes de dae et des postes de rh_v1 qui n'ont pas
102 d'équivalent dans dae.
103
104 """
6d704629 105 dae_ = dae.Poste.objects.filter(actif=True, id_rh__isnull=True)
5d680e84
NC
106 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
107 id_copies = [p.id_rh_id for p in copies.all()]
6d704629 108 rhv1 = rh.Poste.objects.filter(actif=True).exclude(id__in=id_copies)
139686f2
NC
109 # Optimisation de la requête
110 rhv1 = rhv1.select_related(depth=1)
5d680e84 111
98d51b59 112 return [('', 'Nouveau poste')] + \
5d680e84
NC
113 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies] +
114 [('rh-%s' % p.id, unicode(p)) for p in rhv1],
115 key=lambda t: t[1])
3ed49093 116
4dd75e7b
OL
117 def clean(self):
118 """
119 Validation conditionnelles de certains champs.
120 """
121 cleaned_data = self.cleaned_data
122
123 # Gestion de la mise à disposition
124 mise_a_disposition = cleaned_data.get("mise_a_disposition")
125 valeur_point_min = cleaned_data.get("valeur_point_min")
126 valeur_point_max = cleaned_data.get("valeur_point_max")
127 if mise_a_disposition is False and (valeur_point_min is None or valeur_point_max is None):
128 msg = u"Ce champ est obligatoire."
129 self._errors["valeur_point_min"] = self.error_class([msg])
130 self._errors["valeur_point_max"] = self.error_class([msg])
131 raise forms.ValidationError("Les valeurs de point sont vides")
132
133 return cleaned_data
134
135
136
494ff2be
NC
137 def save(self, *args, **kwargs):
138 kwargs2 = kwargs.copy()
139 kwargs2['commit'] = False
140 poste = super(PosteForm, self).save(*args, **kwargs2)
141 # id_rh
142 if 'commit' not in kwargs or kwargs['commit']:
143 poste.save()
144 return poste
145
3ed49093 146
139686f2
NC
147class ChoosePosteForm(forms.ModelForm):
148 class Meta:
149 model = dae.Poste
150 fields = ('poste',)
151
152 # La liste des choix est laissée vide. Voir PosteForm.__init__.
153 poste = forms.ChoiceField(choices=(), required=False)
154
155 def __init__(self, *args, **kwargs):
156 super(ChoosePosteForm, self).__init__(*args, **kwargs)
157 self.fields['poste'].choices = self._poste_choices()
158
159 def _poste_choices(self):
160 """ Menu déroulant pour les postes. """
161 dae_ = dae.Poste.objects.filter(id_rh__isnull=True)
162 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
163 id_copies = [p.id_rh_id for p in copies.all()]
164
98d51b59 165 return [('', '----------')] + \
139686f2
NC
166 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies],
167 key=lambda t: t[1])
168
169
139686f2
NC
170class EmployeForm(forms.ModelForm):
171 """ Formulaire des employés. """
172 class Meta:
173 model = dae.Employe
174 fields = ('employe', 'nom', 'prenom', 'genre')
175
176 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
177 employe = forms.ChoiceField(choices=(), required=False)
178
179 def __init__(self, *args, **kwargs):
180 """ Mise à jour dynamique du contenu du menu des employés. """
181 super(EmployeForm, self).__init__(*args, **kwargs)
182 self.fields['employe'].choices = self._employe_choices()
183
184 def _employe_choices(self):
185 """ Menu déroulant pour les employés. """
186 dae_ = dae.Employe.objects.filter(id_rh__isnull=True)
187 copies = dae.Employe.objects.exclude(id_rh__isnull=True)
188 id_copies = [p.id_rh_id for p in copies.all()]
189 rhv1 = rh.Employe.objects.exclude(id__in=id_copies)
190
191 return [('', 'Nouvel employé')] + \
192 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies] +
193 [('rh-%s' % p.id, unicode(p)) for p in rhv1],
194 key=lambda t: t[1])
195
196
197class DossierForm(forms.ModelForm):
198 """ Formulaire des dossiers. """
199 class Meta:
200 model = dae.Dossier
4d25e2ba 201 widgets = dict(statut_residence=forms.RadioSelect(),
0e0aeb7e
OL
202 contrat_date_debut=admin_widgets.AdminDateWidget(),
203 contrat_date_fin=admin_widgets.AdminDateWidget(),
4d25e2ba 204 )