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