retrait des coeff
[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 89 fields = ('poste', 'implantation', 'type_poste', 'service', 'nom',
154677c3 90 'responsable', 'local', 'expatrie', 'mise_a_disposition',
5d680e84
NC
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',
3d627bfd 95 'devise_min', 'devise_max',
5d680e84
NC
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',
8fa94e8b 102 'comp_autre_min', 'comp_autre_max',
2e092e0c 103 'justification',
8fa94e8b
OL
104 'etat',
105 )
154677c3 106 widgets = dict(appel=forms.RadioSelect(),
3d627bfd 107 nom=forms.TextInput(attrs={'size': 60},),
e88caaf0
OL
108 date_debut=admin_widgets.AdminDateWidget(),
109 date_fin=admin_widgets.AdminDateWidget(),
2e092e0c 110 justification=forms.Textarea(attrs={'cols': 80},),
3d627bfd 111 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
112 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
113 )
5d680e84 114
3121c13c
OL
115 responsable=AutoCompleteSelectField('responsables', required=True)
116 #responsable = forms.ModelChoiceField(
117 # queryset=rh.Poste.objects.select_related(depth=1))
139686f2 118
5d680e84 119 # La liste des choix est laissée vide. Voir __init__ pour la raison.
5efcd48e 120 poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste",
d949462d 121 choices=(), required=False)
5d680e84 122
4dd75e7b
OL
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)
6301bd59 125
5d680e84
NC
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
139686f2
NC
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
5d680e84
NC
137 """
138 super(PosteForm, self).__init__(*args, **kwargs)
139 self.fields['poste'].choices = self._poste_choices()
140
cc3098d0
OL
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
9508a5b8
OL
146 self.initial['nom'] = "%s %s" % (self.initial['nom'], self.instance.get_complement_nom())
147
cc3098d0 148
5d680e84
NC
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 """
6d704629 156 dae_ = dae.Poste.objects.filter(actif=True, id_rh__isnull=True)
5d680e84
NC
157 copies = dae.Poste.objects.exclude(id_rh__isnull=True)
158 id_copies = [p.id_rh_id for p in copies.all()]
6d704629 159 rhv1 = rh.Poste.objects.filter(actif=True).exclude(id__in=id_copies)
139686f2
NC
160 # Optimisation de la requête
161 rhv1 = rhv1.select_related(depth=1)
5d680e84 162
98d51b59 163 return [('', 'Nouveau poste')] + \
4bce4d24
OL
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],
5d680e84 166 key=lambda t: t[1])
3ed49093 167
4dd75e7b
OL
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
494ff2be
NC
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
3ed49093 197
139686f2
NC
198class 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
98d51b59 216 return [('', '----------')] + \
139686f2
NC
217 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies],
218 key=lambda t: t[1])
219
220
139686f2
NC
221class 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 return [('', 'Nouvel employé')] + \
243 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies] +
244 [('rh-%s' % p.id, unicode(p)) for p in rhv1],
245 key=lambda t: t[1])
246
247
248class DossierForm(forms.ModelForm):
249 """ Formulaire des dossiers. """
250 class Meta:
251 model = dae.Dossier
4d25e2ba 252 widgets = dict(statut_residence=forms.RadioSelect(),
0e0aeb7e
OL
253 contrat_date_debut=admin_widgets.AdminDateWidget(),
254 contrat_date_fin=admin_widgets.AdminDateWidget(),
4d25e2ba 255 )