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