recherche intelligente de gens
[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
4bce4d24
OL
12def 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
9cb4de55
OL
16
17class PostePieceForm(inlineformset_factory(dae.Poste, dae.PostePiece)):
18 pass
19
20class DossierPieceForm(inlineformset_factory(dae.Dossier, dae.DossierPiece)):
21 pass
22
151e7bd0
OL
23class FinancementForm(inlineformset_factory(dae.Poste, dae.PosteFinancement, extra=1)):
24 pass
25
72db8238
OL
26class 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:
1cc5e025 38 q_ids = [j.question.id for j in instance.justificationnouvelemploye_set.filter(dossier=instance)]
72db8238
OL
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
48class 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:
1cc5e025 60 q_ids = [j.question.id for j in instance.justificationautreemploye_set.filter(dossier=instance)]
72db8238
OL
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)
5d680e84 69
a05cc82d
OL
70class 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
3121c13c 81from ajax_select.fields import AutoCompleteSelectField
8fa94e8b 82class PosteForm(WorkflowFormMixin):
5d680e84 83 """ Formulaire des postes. """
3121c13c
OL
84
85
5d680e84
NC
86 class Meta:
87 model = dae.Poste
ce110fb9 88
5d680e84
NC
89 fields = ('poste', 'implantation', 'type_poste', 'service', 'nom',
90 'responsable', 'statut_residence', 'mise_a_disposition',
91 'appel', 'date_debut', 'date_fin', 'actif',
92 'regime_travail', 'regime_travail_nb_heure_semaine',
93 'classement_min', 'classement_max',
96d32304 94 'coefficient_min', 'coefficient_max',
5d680e84 95 'valeur_point_min', 'valeur_point_max',
3d627bfd 96 'devise_min', 'devise_max',
5d680e84
NC
97 'salaire_min', 'salaire_max', 'indemn_min', 'indemn_max',
98 'autre_min', 'autre_max', 'devise_comparaison',
99 'comp_locale_min', 'comp_locale_max',
100 'comp_universite_min', 'comp_universite_max',
101 'comp_fonctionpub_min', 'comp_fonctionpub_max',
102 'comp_ong_min', 'comp_ong_max',
8fa94e8b 103 'comp_autre_min', 'comp_autre_max',
2e092e0c 104 'justification',
8fa94e8b
OL
105 'etat',
106 )
5d680e84 107 widgets = dict(statut_residence=forms.RadioSelect(),
ce110fb9 108 appel=forms.RadioSelect(),
3d627bfd 109 nom=forms.TextInput(attrs={'size': 60},),
e88caaf0
OL
110 date_debut=admin_widgets.AdminDateWidget(),
111 date_fin=admin_widgets.AdminDateWidget(),
2e092e0c 112 justification=forms.Textarea(attrs={'cols': 80},),
3d627bfd 113 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
114 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
115 )
5d680e84 116
3121c13c
OL
117 responsable=AutoCompleteSelectField('responsables', required=True)
118 #responsable = forms.ModelChoiceField(
119 # queryset=rh.Poste.objects.select_related(depth=1))
139686f2 120
5d680e84 121 # La liste des choix est laissée vide. Voir __init__ pour la raison.
5efcd48e 122 poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste",
d949462d 123 choices=(), required=False)
5d680e84 124
4dd75e7b
OL
125 valeur_point_min = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
126 valeur_point_max = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
6301bd59 127
5d680e84
NC
128 def __init__(self, *args, **kwargs):
129 """ Mise à jour dynamique du contenu du menu des postes.
130
131 Si on ne met le menu à jour de cette façon, à chaque instantiation du
132 formulaire, son contenu est mis en cache par le système et il ne
133 reflète pas les changements apportés par les ajouts, modifications,
134 etc...
135
139686f2
NC
136 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
137 car le "id" de chaque choix est spécial (voir _poste_choices).
138
5d680e84
NC
139 """
140 super(PosteForm, self).__init__(*args, **kwargs)
141 self.fields['poste'].choices = self._poste_choices()
142
cc3098d0
OL
143 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
144 if self.instance and self.instance.id is None:
145 dossiers = self.instance.get_dossiers()
146 if len(dossiers) > 0:
147 self.initial['service'] = dossiers[0].service_id
9508a5b8
OL
148 self.initial['nom'] = "%s %s" % (self.initial['nom'], self.instance.get_complement_nom())
149
cc3098d0 150
5d680e84
NC
151 def _poste_choices(self):
152 """ Menu déroulant pour les postes.
153
154 Constitué des postes de dae et des postes de rh_v1 qui n'ont pas
155 d'équivalent dans dae.
156
157 """
6d704629 158 dae_ = dae.Poste.objects.filter(actif=True, id_rh__isnull=True)
5d680e84
NC
159 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
160 id_copies = [p.id_rh_id for p in copies.all()]
6d704629 161 rhv1 = rh.Poste.objects.filter(actif=True).exclude(id__in=id_copies)
139686f2
NC
162 # Optimisation de la requête
163 rhv1 = rhv1.select_related(depth=1)
5d680e84 164
98d51b59 165 return [('', 'Nouveau poste')] + \
4bce4d24
OL
166 sorted([('dae-%s' % p.id, label_poste_display(p)) for p in dae_ | copies] +
167 [('rh-%s' % p.id, label_poste_display(p)) for p in rhv1],
5d680e84 168 key=lambda t: t[1])
3ed49093 169
4dd75e7b
OL
170 def clean(self):
171 """
172 Validation conditionnelles de certains champs.
173 """
174 cleaned_data = self.cleaned_data
175
176 # Gestion de la mise à disposition
177 mise_a_disposition = cleaned_data.get("mise_a_disposition")
178 valeur_point_min = cleaned_data.get("valeur_point_min")
179 valeur_point_max = cleaned_data.get("valeur_point_max")
180 if mise_a_disposition is False and (valeur_point_min is None or valeur_point_max is None):
181 msg = u"Ce champ est obligatoire."
182 self._errors["valeur_point_min"] = self.error_class([msg])
183 self._errors["valeur_point_max"] = self.error_class([msg])
184 raise forms.ValidationError("Les valeurs de point sont vides")
185
186 return cleaned_data
187
188
189
494ff2be
NC
190 def save(self, *args, **kwargs):
191 kwargs2 = kwargs.copy()
192 kwargs2['commit'] = False
193 poste = super(PosteForm, self).save(*args, **kwargs2)
194 # id_rh
195 if 'commit' not in kwargs or kwargs['commit']:
196 poste.save()
197 return poste
198
3ed49093 199
139686f2
NC
200class ChoosePosteForm(forms.ModelForm):
201 class Meta:
202 model = dae.Poste
203 fields = ('poste',)
204
205 # La liste des choix est laissée vide. Voir PosteForm.__init__.
206 poste = forms.ChoiceField(choices=(), required=False)
207
208 def __init__(self, *args, **kwargs):
209 super(ChoosePosteForm, self).__init__(*args, **kwargs)
210 self.fields['poste'].choices = self._poste_choices()
211
212 def _poste_choices(self):
213 """ Menu déroulant pour les postes. """
214 dae_ = dae.Poste.objects.filter(id_rh__isnull=True)
215 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
216 id_copies = [p.id_rh_id for p in copies.all()]
217
98d51b59 218 return [('', '----------')] + \
139686f2
NC
219 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies],
220 key=lambda t: t[1])
221
222
139686f2
NC
223class EmployeForm(forms.ModelForm):
224 """ Formulaire des employés. """
225 class Meta:
226 model = dae.Employe
227 fields = ('employe', 'nom', 'prenom', 'genre')
228
229 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
230 employe = forms.ChoiceField(choices=(), required=False)
231
232 def __init__(self, *args, **kwargs):
233 """ Mise à jour dynamique du contenu du menu des employés. """
234 super(EmployeForm, self).__init__(*args, **kwargs)
235 self.fields['employe'].choices = self._employe_choices()
236
237 def _employe_choices(self):
238 """ Menu déroulant pour les employés. """
239 dae_ = dae.Employe.objects.filter(id_rh__isnull=True)
240 copies = dae.Employe.objects.exclude(id_rh__isnull=True)
241 id_copies = [p.id_rh_id for p in copies.all()]
242 rhv1 = rh.Employe.objects.exclude(id__in=id_copies)
243
244 return [('', 'Nouvel employé')] + \
245 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies] +
246 [('rh-%s' % p.id, unicode(p)) for p in rhv1],
247 key=lambda t: t[1])
248
249
250class DossierForm(forms.ModelForm):
251 """ Formulaire des dossiers. """
252 class Meta:
253 model = dae.Dossier
4d25e2ba 254 widgets = dict(statut_residence=forms.RadioSelect(),
0e0aeb7e
OL
255 contrat_date_debut=admin_widgets.AdminDateWidget(),
256 contrat_date_fin=admin_widgets.AdminDateWidget(),
4d25e2ba 257 )