recherche intelligente de gens
[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 from ajax_select.fields import AutoCompleteSelectField
82 class PosteForm(WorkflowFormMixin):
83 """ Formulaire des postes. """
84
85
86 class Meta:
87 model = dae.Poste
88
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',
94 'coefficient_min', 'coefficient_max',
95 'valeur_point_min', 'valeur_point_max',
96 'devise_min', 'devise_max',
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',
103 'comp_autre_min', 'comp_autre_max',
104 'justification',
105 'etat',
106 )
107 widgets = dict(statut_residence=forms.RadioSelect(),
108 appel=forms.RadioSelect(),
109 nom=forms.TextInput(attrs={'size': 60},),
110 date_debut=admin_widgets.AdminDateWidget(),
111 date_fin=admin_widgets.AdminDateWidget(),
112 justification=forms.Textarea(attrs={'cols': 80},),
113 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
114 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
115 )
116
117 responsable=AutoCompleteSelectField('responsables', required=True)
118 #responsable = forms.ModelChoiceField(
119 # queryset=rh.Poste.objects.select_related(depth=1))
120
121 # La liste des choix est laissée vide. Voir __init__ pour la raison.
122 poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste",
123 choices=(), required=False)
124
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)
127
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
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
139 """
140 super(PosteForm, self).__init__(*args, **kwargs)
141 self.fields['poste'].choices = self._poste_choices()
142
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
148 self.initial['nom'] = "%s %s" % (self.initial['nom'], self.instance.get_complement_nom())
149
150
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 """
158 dae_ = dae.Poste.objects.filter(actif=True, id_rh__isnull=True)
159 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
160 id_copies = [p.id_rh_id for p in copies.all()]
161 rhv1 = rh.Poste.objects.filter(actif=True).exclude(id__in=id_copies)
162 # Optimisation de la requête
163 rhv1 = rhv1.select_related(depth=1)
164
165 return [('', 'Nouveau poste')] + \
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],
168 key=lambda t: t[1])
169
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
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
199
200 class 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
218 return [('', '----------')] + \
219 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies],
220 key=lambda t: t[1])
221
222
223 class 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
250 class DossierForm(forms.ModelForm):
251 """ Formulaire des dossiers. """
252 class Meta:
253 model = dae.Dossier
254 widgets = dict(statut_residence=forms.RadioSelect(),
255 contrat_date_debut=admin_widgets.AdminDateWidget(),
256 contrat_date_fin=admin_widgets.AdminDateWidget(),
257 )