filtrage JS implantation, famille
[auf_rh_dae.git] / project / dae / forms.py
1 # -*- encoding: utf-8 -*-
2
3 from django import forms
4 from django.forms.models import inlineformset_factory
5 from django.contrib.admin import widgets as admin_widgets
6 from auf.django.workflow.forms import WorkflowFormMixin
7 from datamaster_modeles import models as ref
8
9 from dae import models as dae
10 from rh_v1 import models as rh
11
12 def label_poste_display(poste):
13 """Formate un visuel pour un poste dans une liste déroulante"""
14 label = u"%s - %s [%s]" %(poste.type_poste, poste.type_poste.famille_emploi.nom, poste.id)
15 return label
16
17 class PostePieceForm(inlineformset_factory(dae.Poste, dae.PostePiece)):
18 pass
19
20 class DossierPieceForm(inlineformset_factory(dae.Dossier, dae.DossierPiece)):
21 pass
22
23 class FinancementForm(inlineformset_factory(dae.Poste, dae.PosteFinancement, extra=1)):
24 pass
25
26 class JustificationNouvelEmployeForm(inlineformset_factory(dae.Dossier,
27 dae.JustificationNouvelEmploye,
28 extra=0,
29 can_delete=False,
30 exclude=('question',))):
31 """
32 Formulaire de justification d'un nouvel employé.
33 Le dossier a besoin d'être enregistré une première fois afin de prépopuler les questions.
34 """
35 def __init__(self, *args, **kwargs):
36 instance = kwargs['instance']
37 if instance.id:
38 q_ids = [j.question.id for j in instance.justificationnouvelemploye_set.filter(dossier=instance)]
39 for q in dae.JustificationQuestion.objects.filter(type="N"):
40 if q.id in q_ids:
41 continue
42 j = dae.JustificationNouvelEmploye()
43 j.dossier = instance
44 j.question = q
45 j.save()
46 super(self.__class__, self).__init__(*args, **kwargs)
47
48 class JustificationAutreEmployeForm(inlineformset_factory(dae.Dossier,
49 dae.JustificationAutreEmploye,
50 extra=0,
51 can_delete=False,
52 exclude=('question',))):
53 """
54 Formulaire de justification d'un nouvel employé.
55 Le dossier a besoin d'être enregistré une première fois afin de prépopuler les questions.
56 """
57 def __init__(self, *args, **kwargs):
58 instance = kwargs['instance']
59 if instance.id:
60 q_ids = [j.question.id for j in instance.justificationautreemploye_set.filter(dossier=instance)]
61 for q in dae.JustificationQuestion.objects.filter(type="R"):
62 if q.id in q_ids:
63 continue
64 j = dae.JustificationAutreEmploye()
65 j.dossier = instance
66 j.question = q
67 j.save()
68 super(self.__class__, self).__init__(*args, **kwargs)
69
70 class PosteValidationForm(forms.ModelForm):
71 """ Validation d'un poste"""
72 class Meta:
73 model = dae.Poste
74 fields = (
75 'validation_bureau_regional',
76 'validation_drh',
77 'validation_secretaire_general',
78 'validation_recteur',
79 )
80
81 class PosteForm(WorkflowFormMixin):
82 """ Formulaire des postes. """
83 class Meta:
84 model = dae.Poste
85
86 fields = ('poste', 'implantation', 'type_poste', 'service', 'nom',
87 'responsable', 'statut_residence', 'mise_a_disposition',
88 'appel', 'date_debut', 'date_fin', 'actif',
89 'regime_travail', 'regime_travail_nb_heure_semaine',
90 'classement_min', 'classement_max',
91 'coefficient_min', 'coefficient_max',
92 'valeur_point_min', 'valeur_point_max',
93 'devise_min', 'devise_max',
94 'salaire_min', 'salaire_max', 'indemn_min', 'indemn_max',
95 'autre_min', 'autre_max', 'devise_comparaison',
96 'comp_locale_min', 'comp_locale_max',
97 'comp_universite_min', 'comp_universite_max',
98 'comp_fonctionpub_min', 'comp_fonctionpub_max',
99 'comp_ong_min', 'comp_ong_max',
100 'comp_autre_min', 'comp_autre_max',
101 'justification',
102 'etat',
103 )
104 widgets = dict(statut_residence=forms.RadioSelect(),
105 appel=forms.RadioSelect(),
106 nom=forms.TextInput(attrs={'size': 60},),
107 date_debut=admin_widgets.AdminDateWidget(),
108 date_fin=admin_widgets.AdminDateWidget(),
109 justification=forms.Textarea(attrs={'cols': 80},),
110 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
111 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
112 )
113
114 responsable = forms.ModelChoiceField(
115 queryset=rh.Poste.objects.select_related(depth=1))
116
117 # La liste des choix est laissée vide. Voir __init__ pour la raison.
118 poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste",
119 choices=(), required=False)
120
121 valeur_point_min = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
122 valeur_point_max = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
123
124 def __init__(self, *args, **kwargs):
125 """ Mise à jour dynamique du contenu du menu des postes.
126
127 Si on ne met le menu à jour de cette façon, à chaque instantiation du
128 formulaire, son contenu est mis en cache par le système et il ne
129 reflète pas les changements apportés par les ajouts, modifications,
130 etc...
131
132 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
133 car le "id" de chaque choix est spécial (voir _poste_choices).
134
135 """
136 super(PosteForm, self).__init__(*args, **kwargs)
137 self.fields['poste'].choices = self._poste_choices()
138
139 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
140 if self.instance and self.instance.id is None:
141 dossiers = self.instance.get_dossiers()
142 if len(dossiers) > 0:
143 self.initial['service'] = dossiers[0].service_id
144 self.initial['nom'] = "%s %s" % (self.initial['nom'], self.instance.get_complement_nom())
145
146
147 def _poste_choices(self):
148 """ Menu déroulant pour les postes.
149
150 Constitué des postes de dae et des postes de rh_v1 qui n'ont pas
151 d'équivalent dans dae.
152
153 """
154 dae_ = dae.Poste.objects.filter(actif=True, id_rh__isnull=True)
155 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
156 id_copies = [p.id_rh_id for p in copies.all()]
157 rhv1 = rh.Poste.objects.filter(actif=True).exclude(id__in=id_copies)
158 # Optimisation de la requête
159 rhv1 = rhv1.select_related(depth=1)
160
161 return [('', 'Nouveau poste')] + \
162 sorted([('dae-%s' % p.id, label_poste_display(p)) for p in dae_ | copies] +
163 [('rh-%s' % p.id, label_poste_display(p)) for p in rhv1],
164 key=lambda t: t[1])
165
166 def clean(self):
167 """
168 Validation conditionnelles de certains champs.
169 """
170 cleaned_data = self.cleaned_data
171
172 # Gestion de la mise à disposition
173 mise_a_disposition = cleaned_data.get("mise_a_disposition")
174 valeur_point_min = cleaned_data.get("valeur_point_min")
175 valeur_point_max = cleaned_data.get("valeur_point_max")
176 if mise_a_disposition is False and (valeur_point_min is None or valeur_point_max is None):
177 msg = u"Ce champ est obligatoire."
178 self._errors["valeur_point_min"] = self.error_class([msg])
179 self._errors["valeur_point_max"] = self.error_class([msg])
180 raise forms.ValidationError("Les valeurs de point sont vides")
181
182 return cleaned_data
183
184
185
186 def save(self, *args, **kwargs):
187 kwargs2 = kwargs.copy()
188 kwargs2['commit'] = False
189 poste = super(PosteForm, self).save(*args, **kwargs2)
190 # id_rh
191 if 'commit' not in kwargs or kwargs['commit']:
192 poste.save()
193 return poste
194
195
196 class ChoosePosteForm(forms.ModelForm):
197 class Meta:
198 model = dae.Poste
199 fields = ('poste',)
200
201 # La liste des choix est laissée vide. Voir PosteForm.__init__.
202 poste = forms.ChoiceField(choices=(), required=False)
203
204 def __init__(self, *args, **kwargs):
205 super(ChoosePosteForm, self).__init__(*args, **kwargs)
206 self.fields['poste'].choices = self._poste_choices()
207
208 def _poste_choices(self):
209 """ Menu déroulant pour les postes. """
210 dae_ = dae.Poste.objects.filter(id_rh__isnull=True)
211 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
212 id_copies = [p.id_rh_id for p in copies.all()]
213
214 return [('', '----------')] + \
215 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies],
216 key=lambda t: t[1])
217
218
219 class EmployeForm(forms.ModelForm):
220 """ Formulaire des employés. """
221 class Meta:
222 model = dae.Employe
223 fields = ('employe', 'nom', 'prenom', 'genre')
224
225 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
226 employe = forms.ChoiceField(choices=(), required=False)
227
228 def __init__(self, *args, **kwargs):
229 """ Mise à jour dynamique du contenu du menu des employés. """
230 super(EmployeForm, self).__init__(*args, **kwargs)
231 self.fields['employe'].choices = self._employe_choices()
232
233 def _employe_choices(self):
234 """ Menu déroulant pour les employés. """
235 dae_ = dae.Employe.objects.filter(id_rh__isnull=True)
236 copies = dae.Employe.objects.exclude(id_rh__isnull=True)
237 id_copies = [p.id_rh_id for p in copies.all()]
238 rhv1 = rh.Employe.objects.exclude(id__in=id_copies)
239
240 return [('', 'Nouvel employé')] + \
241 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies] +
242 [('rh-%s' % p.id, unicode(p)) for p in rhv1],
243 key=lambda t: t[1])
244
245
246 class DossierForm(forms.ModelForm):
247 """ Formulaire des dossiers. """
248 class Meta:
249 model = dae.Dossier
250 widgets = dict(statut_residence=forms.RadioSelect(),
251 contrat_date_debut=admin_widgets.AdminDateWidget(),
252 contrat_date_fin=admin_widgets.AdminDateWidget(),
253 )