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