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