Commit | Line | Data |
---|---|---|
5d680e84 | 1 | # -*- encoding: utf-8 -*- |
ce110fb9 | 2 | |
bed0c4c9 | 3 | import datetime |
5a1f75cb | 4 | from django import forms |
80be36aa | 5 | from django.core.urlresolvers import reverse |
2e672700 | 6 | from django.forms.models import BaseInlineFormSet |
5a1f75cb | 7 | from django.forms.models import inlineformset_factory, modelformset_factory |
80be36aa OL |
8 | from django.db.models import Q, Max, Count |
9 | from django.shortcuts import redirect | |
10 | from django.contrib.admin import widgets as admin_widgets | |
5a1f75cb | 11 | |
75f0e87b DB |
12 | from ajax_select.fields import AutoCompleteSelectField |
13 | ||
14 | from auf.django.references import models as ref | |
15 | from auf.django.workflow.forms import WorkflowFormMixin | |
66fefd2f | 16 | from auf.django.workflow.models import WorkflowCommentaire |
75f0e87b | 17 | |
3383b2d1 | 18 | from project import groups |
17c90428 | 19 | from project.rh import models as rh |
17c90428 | 20 | from project.dae import models as dae |
34950f36 | 21 | from project.dae.workflow import POSTE_ETATS_BOUTONS, POSTE_ETAT_FINALISE |
1b31de9f | 22 | |
f258e4e7 | 23 | |
2e672700 OL |
24 | class BaseInlineFormSetWithInitial(BaseInlineFormSet): |
25 | """ | |
26 | Cette classe permet de fournir l'option initial aux inlineformsets. | |
27 | Elle devient désuette en django 1.4. | |
28 | """ | |
29 | def __init__(self, data=None, files=None, instance=None, | |
30 | save_as_new=False, prefix=None, queryset=None, **kwargs): | |
31 | ||
32 | self.initial_extra = kwargs.pop('initial', None) | |
33 | ||
34 | from django.db.models.fields.related import RelatedObject | |
35 | if instance is None: | |
36 | self.instance = self.fk.rel.to() | |
37 | else: | |
38 | self.instance = instance | |
39 | self.save_as_new = save_as_new | |
40 | # is there a better way to get the object descriptor? | |
41 | self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name() | |
42 | if queryset is None: | |
43 | queryset = self.model._default_manager | |
44 | qs = queryset.filter(**{self.fk.name: self.instance}) | |
45 | super(BaseInlineFormSetWithInitial, self).__init__(data, files, prefix=prefix, | |
46 | queryset=qs, **kwargs) | |
47 | ||
48 | def _construct_form(self, i, **kwargs): | |
49 | if self.is_bound and i < self.initial_form_count(): | |
50 | # Import goes here instead of module-level because importing | |
51 | # django.db has side effects. | |
52 | from django.db import connections | |
53 | pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name) | |
54 | pk = self.data[pk_key] | |
55 | pk_field = self.model._meta.pk | |
56 | pk = pk_field.get_db_prep_lookup('exact', pk, | |
57 | connection=connections[self.get_queryset().db]) | |
58 | if isinstance(pk, list): | |
59 | pk = pk[0] | |
60 | kwargs['instance'] = self._existing_object(pk) | |
61 | if i < self.initial_form_count() and not kwargs.get('instance'): | |
62 | kwargs['instance'] = self.get_queryset()[i] | |
63 | if i >= self.initial_form_count() and self.initial_extra: | |
64 | # Set initial values for extra forms | |
65 | try: | |
66 | kwargs['initial'] = self.initial_extra[i-self.initial_form_count()] | |
67 | except IndexError: | |
68 | pass | |
69 | ||
70 | defaults = {'auto_id': self.auto_id, 'prefix': self.add_prefix(i)} | |
71 | if self.is_bound: | |
72 | defaults['data'] = self.data | |
73 | defaults['files'] = self.files | |
74 | if self.initial: | |
75 | try: | |
76 | defaults['initial'] = self.initial[i] | |
77 | except IndexError: | |
78 | pass | |
79 | # Allow extra forms to be empty. | |
80 | if i >= self.initial_form_count(): | |
81 | defaults['empty_permitted'] = True | |
82 | defaults.update(kwargs) | |
83 | form = self.form(**defaults) | |
84 | self.add_fields(form, i) | |
85 | return form | |
86 | ||
87 | ||
f258e4e7 OL |
88 | def _implantation_choices(obj, request): |
89 | # TRAITEMENT NORMAL | |
3383b2d1 | 90 | employe = groups.get_employe_from_user(request.user) |
b0cf30b8 | 91 | q = Q(**{'zone_administrative': employe.implantation.zone_administrative}) |
f258e4e7 OL |
92 | |
93 | # TRAITEMENT DRH | |
3383b2d1 | 94 | user_groupes = [g.name for g in request.user.groups.all()] |
713b824a OL |
95 | if groups.DRH_NIVEAU_1 in user_groupes or \ |
96 | groups.DRH_NIVEAU_2 in user_groupes: | |
f258e4e7 | 97 | q = Q() |
5a1f75cb EMS |
98 | return [('', '----------')] + \ |
99 | [(i.id, unicode(i), )for i in ref.Implantation.objects.filter(q)] | |
100 | ||
f258e4e7 OL |
101 | |
102 | def _employe_choices(obj, request): | |
f258e4e7 | 103 | # TRAITEMENT NORMAL |
3383b2d1 | 104 | employe = groups.get_employe_from_user(request.user) |
b0cf30b8 EMS |
105 | q_dae_region_service = Q( |
106 | poste__implantation__zone_administrative=( | |
107 | employe.implantation.zone_administrative | |
5a1f75cb | 108 | ) |
b0cf30b8 EMS |
109 | ) |
110 | q_rh_region_service = Q( | |
111 | poste__implantation__zone_administrative=( | |
112 | employe.implantation.zone_administrative | |
5a1f75cb | 113 | ) |
b0cf30b8 | 114 | ) |
f258e4e7 | 115 | # TRAITEMENT DRH |
3383b2d1 | 116 | user_groupes = [g.name for g in request.user.groups.all()] |
713b824a OL |
117 | if groups.DRH_NIVEAU_1 in user_groupes or \ |
118 | groups.DRH_NIVEAU_2 in user_groupes: | |
072820fc OL |
119 | q_dae_region_service = Q() |
120 | q_rh_region_service = Q() | |
f258e4e7 | 121 | |
5a1f75cb EMS |
122 | # On filtre les employes avec les droits régionaux et on s'assure que |
123 | # c'est bien le dernier dossier en date pour sortir l'employe. On retient | |
124 | # un employé qui travaille présentement dans la même région que le user | |
125 | # connecté. | |
126 | dossiers_regionaux_ids = [ | |
127 | d.id for d in dae.Dossier.objects.filter(q_dae_region_service) | |
128 | ] | |
129 | employes_ids = [ | |
130 | d['employe'] | |
131 | for d in dae.Dossier.objects | |
132 | .values('employe') | |
133 | .annotate(dernier_dossier=Max('id')) | |
134 | if d['dernier_dossier'] in dossiers_regionaux_ids | |
135 | ] | |
072820fc OL |
136 | dae_employe = dae.Employe.objects.filter(id__in=employes_ids) |
137 | dae_ = dae_employe.filter(id_rh__isnull=True) | |
138 | copies = dae_employe.filter(Q(id_rh__isnull=False)) | |
f258e4e7 | 139 | id_copies = [p.id_rh_id for p in copies.all()] |
072820fc | 140 | |
5a1f75cb EMS |
141 | dossiers_regionaux_ids = [ |
142 | d.id for d in rh.Dossier.objects.filter(q_rh_region_service) | |
143 | ] | |
144 | employes_ids = [ | |
145 | d['employe'] | |
146 | for d in rh.Dossier.objects | |
147 | .values('employe') | |
148 | .annotate(dernier_dossier=Max('id')) | |
149 | if d['dernier_dossier'] in dossiers_regionaux_ids | |
150 | ] | |
151 | rhv1 = rh.Employe.objects \ | |
152 | .filter(id__in=employes_ids) \ | |
153 | .exclude(id__in=id_copies) | |
154 | ||
155 | # On ajoute les nouveaux Employés DAE qui ont été crées, mais qui n'ont | |
156 | # pas de Dossier associés | |
67c15007 OL |
157 | employes_avec_dae = [d.employe_id for d in dae.Dossier.objects.all()] |
158 | employes_orphelins = dae.Employe.objects.exclude(id__in=employes_avec_dae) | |
159 | ||
0339920c OL |
160 | def option_label(employe, extra=""): |
161 | if extra: | |
162 | extra = " [%s]" % extra | |
163 | return "%s %s %s" % (employe.nom.upper(), employe.prenom.title(), extra) | |
f258e4e7 | 164 | |
0339920c OL |
165 | lbl_rh = sorted([('rh-%s' % p.id, option_label(p, "existant dans rh")) for p in rhv1], |
166 | key=lambda t: t[1]) | |
167 | lbl_dae = sorted([('dae-%s' % p.id, option_label(p)) for p in dae_ | copies | employes_orphelins], | |
168 | key=lambda t: t[1]) | |
169 | return [('', 'Nouvel employé')] + lbl_rh + lbl_dae | |
5a1f75cb | 170 | |
f258e4e7 | 171 | |
4bce4d24 OL |
172 | def label_poste_display(poste): |
173 | """Formate un visuel pour un poste dans une liste déroulante""" | |
23294f7d OL |
174 | annee = "" |
175 | if poste.date_debut: | |
176 | annee = poste.date_debut.year | |
9c1ff333 OL |
177 | |
178 | nom = poste.nom | |
67ae0181 | 179 | label = u"%s (%s) %s [%s]" % ( |
34950f36 OL |
180 | annee, |
181 | poste.implantation.nom_court, | |
182 | nom, | |
67ae0181 | 183 | #poste.type_poste.categorie_emploi.nom, |
34950f36 | 184 | poste.id, |
93817ef3 | 185 | ) |
4bce4d24 | 186 | return label |
9cb4de55 | 187 | |
2e672700 | 188 | |
874949f3 | 189 | PostePieceFormSet = inlineformset_factory(dae.Poste, dae.PostePiece,) |
25086dcf | 190 | DossierPieceForm = inlineformset_factory(dae.Dossier, dae.DossierPiece) |
2e672700 | 191 | |
874949f3 OL |
192 | # Ce formset est utilisé dans le cas de la création de poste prépopulé avec les |
193 | # données de RH | |
194 | FinancementFormSetInitial = inlineformset_factory( | |
2e672700 OL |
195 | dae.Poste, |
196 | dae.PosteFinancement, | |
197 | formset=BaseInlineFormSetWithInitial, | |
198 | extra=2 | |
5a1f75cb | 199 | ) |
874949f3 OL |
200 | FinancementFormSet = inlineformset_factory( |
201 | dae.Poste, | |
202 | dae.PosteFinancement, | |
203 | extra=2 | |
204 | ) | |
5a1f75cb | 205 | |
03b395db OL |
206 | |
207 | class DossierComparaisonForm(forms.ModelForm): | |
11f22317 | 208 | |
03b395db | 209 | recherche = AutoCompleteSelectField('dossiers', required=False) |
5a1f75cb EMS |
210 | poste = forms.CharField( |
211 | max_length=255, widget=forms.TextInput(attrs={'size': '60'}) | |
212 | ) | |
03b395db | 213 | |
320d7584 | 214 | class Meta: |
03b395db | 215 | model = dae.DossierComparaison |
320d7584 | 216 | exclude = ('dossier',) |
03b395db | 217 | |
320d7584 EMS |
218 | DossierComparaisonFormSet = modelformset_factory( |
219 | dae.DossierComparaison, extra=3, max_num=3, form=DossierComparaisonForm | |
25086dcf | 220 | ) |
03b395db | 221 | |
5a1f75cb | 222 | |
068d1462 | 223 | class PosteComparaisonForm(forms.ModelForm): |
11f22317 | 224 | |
e503e64d | 225 | recherche = AutoCompleteSelectField('dae_postes', required=False) |
068d1462 | 226 | |
320d7584 | 227 | class Meta: |
068d1462 | 228 | model = dae.PosteComparaison |
320d7584 | 229 | exclude = ('poste',) |
068d1462 | 230 | |
874949f3 OL |
231 | # Ce formset est utilisé dans le cas de la création de poste prépopulé avec les |
232 | # données de RH | |
233 | PosteComparaisonFormSetInitial = inlineformset_factory( | |
2e672700 OL |
234 | dae.Poste, |
235 | dae.PosteComparaison, | |
236 | extra=3, | |
237 | max_num=3, | |
238 | form=PosteComparaisonForm, | |
2e672700 | 239 | formset=BaseInlineFormSetWithInitial, |
25086dcf | 240 | ) |
874949f3 OL |
241 | PosteComparaisonFormSet = inlineformset_factory( |
242 | dae.Poste, | |
243 | dae.PosteComparaison, | |
244 | extra=3, | |
245 | max_num=3, | |
246 | form=PosteComparaisonForm, | |
247 | ) | |
068d1462 | 248 | |
5a1f75cb | 249 | |
0a085c42 OL |
250 | class FlexibleRemunForm(forms.ModelForm): |
251 | ||
252 | montant_mensuel = forms.DecimalField(required=False) | |
253 | montant = forms.DecimalField(required=True, label='Montant annuel') | |
254 | ||
255 | class Meta: | |
256 | model = dae.Remuneration | |
257 | ||
dc4b78a7 OL |
258 | def clean_devise(self): |
259 | devise = self.cleaned_data['devise'] | |
67173010 OL |
260 | if devise.code == 'EUR': |
261 | return devise | |
5a1f75cb EMS |
262 | implantation = ref.Implantation.objects.get( |
263 | id=self.data['implantation'] | |
264 | ) | |
2455f48d | 265 | liste_taux = devise.tauxchange_set.order_by('-annee') |
dc4b78a7 | 266 | if len(liste_taux) == 0: |
5a1f75cb EMS |
267 | raise forms.ValidationError( |
268 | u"La devise %s n'a pas de taux pour l'implantation %s" % | |
269 | (devise, implantation) | |
270 | ) | |
dc4b78a7 OL |
271 | else: |
272 | return devise | |
273 | ||
25086dcf EMS |
274 | RemunForm = inlineformset_factory( |
275 | dae.Dossier, dae.Remuneration, extra=5, form=FlexibleRemunForm | |
276 | ) | |
0a085c42 | 277 | |
5a1f75cb | 278 | |
1b217058 | 279 | class PosteForm(forms.ModelForm): |
5d680e84 | 280 | """ Formulaire des postes. """ |
12c7f8a7 | 281 | |
ea7adc69 | 282 | # On ne propose que les services actifs |
5a1f75cb EMS |
283 | service = forms.ModelChoiceField( |
284 | queryset=rh.Service.objects.all(), required=True | |
285 | ) | |
ea7adc69 | 286 | |
5a1f75cb | 287 | responsable = AutoCompleteSelectField('responsables', required=True) |
12c7f8a7 OL |
288 | #responsable = forms.ModelChoiceField( |
289 | # queryset=rh.Poste.objects.select_related(depth=1)) | |
290 | ||
291 | # La liste des choix est laissée vide. Voir __init__ pour la raison. | |
292 | poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste", | |
293 | choices=(), required=False) | |
11f22317 | 294 | |
5a1f75cb EMS |
295 | valeur_point_min = forms.ModelChoiceField( |
296 | queryset=rh.ValeurPoint.actuelles.all(), required=False | |
297 | ) | |
298 | valeur_point_max = forms.ModelChoiceField( | |
299 | queryset=rh.ValeurPoint.actuelles.all(), required=False | |
300 | ) | |
11f22317 | 301 | |
5d680e84 NC |
302 | class Meta: |
303 | model = dae.Poste | |
c3be904d OL |
304 | fields = ('type_intervention', |
305 | 'poste', 'implantation', 'type_poste', 'service', 'nom', | |
154677c3 | 306 | 'responsable', 'local', 'expatrie', 'mise_a_disposition', |
b15bf543 | 307 | 'appel', 'date_debut', 'date_fin', |
5d680e84 NC |
308 | 'regime_travail', 'regime_travail_nb_heure_semaine', |
309 | 'classement_min', 'classement_max', | |
310 | 'valeur_point_min', 'valeur_point_max', | |
3d627bfd | 311 | 'devise_min', 'devise_max', |
5f61bccb OL |
312 | 'salaire_min', 'salaire_max', |
313 | 'indemn_expat_min', 'indemn_expat_max', | |
314 | 'indemn_fct_min', 'indemn_fct_max', | |
315 | 'charges_patronales_min', 'charges_patronales_max', | |
5d680e84 NC |
316 | 'autre_min', 'autre_max', 'devise_comparaison', |
317 | 'comp_locale_min', 'comp_locale_max', | |
318 | 'comp_universite_min', 'comp_universite_max', | |
319 | 'comp_fonctionpub_min', 'comp_fonctionpub_max', | |
320 | 'comp_ong_min', 'comp_ong_max', | |
8fa94e8b | 321 | 'comp_autre_min', 'comp_autre_max', |
2e092e0c | 322 | 'justification', |
8fa94e8b | 323 | ) |
c3be904d OL |
324 | widgets = dict(type_intervention=forms.RadioSelect(), |
325 | appel=forms.RadioSelect(), | |
3d627bfd | 326 | nom=forms.TextInput(attrs={'size': 60},), |
e88caaf0 OL |
327 | date_debut=admin_widgets.AdminDateWidget(), |
328 | date_fin=admin_widgets.AdminDateWidget(), | |
2e092e0c | 329 | justification=forms.Textarea(attrs={'cols': 80},), |
3d627bfd | 330 | #devise_min=forms.Select(attrs={'disabled':'disabled'}), |
331 | #devise_max=forms.Select(attrs={'disabled':'disabled'}), | |
332 | ) | |
5d680e84 | 333 | |
c2458db6 | 334 | def __init__(self, *args, **kwargs): |
5d680e84 NC |
335 | """ Mise à jour dynamique du contenu du menu des postes. |
336 | ||
337 | Si on ne met le menu à jour de cette façon, à chaque instantiation du | |
338 | formulaire, son contenu est mis en cache par le système et il ne | |
339 | reflète pas les changements apportés par les ajouts, modifications, | |
340 | etc... | |
341 | ||
139686f2 NC |
342 | Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField |
343 | car le "id" de chaque choix est spécial (voir _poste_choices). | |
344 | ||
5d680e84 | 345 | """ |
c2458db6 | 346 | request = kwargs.pop('request') |
5d680e84 | 347 | super(PosteForm, self).__init__(*args, **kwargs) |
f258e4e7 | 348 | self.fields['poste'].choices = self._poste_choices(request) |
9c1ff333 | 349 | |
5a1f75cb EMS |
350 | self.fields['implantation'].choices = \ |
351 | _implantation_choices(self, request) | |
5d680e84 | 352 | |
cc3098d0 OL |
353 | # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1 |
354 | if self.instance and self.instance.id is None: | |
355 | dossiers = self.instance.get_dossiers() | |
356 | if len(dossiers) > 0: | |
09aa8374 | 357 | self.initial['service'] = dossiers[0].poste.service |
9508a5b8 | 358 | |
f258e4e7 | 359 | def _poste_choices(self, request): |
5d680e84 | 360 | """ Menu déroulant pour les postes. |
9c1ff333 | 361 | Constitué des postes de RH |
5d680e84 | 362 | """ |
9c1ff333 OL |
363 | postes_rh = rh.Poste.objects.ma_region_ou_service(request.user).all() |
364 | postes_rh = postes_rh.select_related(depth=1) | |
5d680e84 | 365 | |
98d51b59 | 366 | return [('', 'Nouveau poste')] + \ |
9c1ff333 OL |
367 | sorted([('rh-%s' % p.id, label_poste_display(p)) for p in |
368 | postes_rh], | |
5d680e84 | 369 | key=lambda t: t[1]) |
3ed49093 | 370 | |
4dd75e7b OL |
371 | def clean(self): |
372 | """ | |
373 | Validation conditionnelles de certains champs. | |
374 | """ | |
5a1f75cb | 375 | cleaned_data = self.cleaned_data |
4dd75e7b | 376 | |
5a1f75cb EMS |
377 | if cleaned_data.get("local") is False \ |
378 | and cleaned_data.get("expatrie") is False: | |
379 | msg = "Le poste doit au moins être ouvert localement " \ | |
380 | "ou aux expatriés" | |
f42c6e20 OL |
381 | self._errors["local"] = self.error_class([msg]) |
382 | self._errors["expatrie"] = '' | |
383 | raise forms.ValidationError(msg) | |
f42c6e20 | 384 | |
4dd75e7b OL |
385 | return cleaned_data |
386 | ||
3ed49093 | 387 | |
34950f36 | 388 | class ChoosePosteForm(forms.Form): |
139686f2 | 389 | class Meta: |
139686f2 NC |
390 | fields = ('poste',) |
391 | ||
392 | # La liste des choix est laissée vide. Voir PosteForm.__init__. | |
34950f36 OL |
393 | postes_dae = forms.ChoiceField(choices=(), required=False) |
394 | postes_rh = forms.ChoiceField(choices=(), required=False) | |
139686f2 | 395 | |
4ee6d70a | 396 | def __init__(self, request=None, *args, **kwargs): |
139686f2 | 397 | super(ChoosePosteForm, self).__init__(*args, **kwargs) |
34950f36 OL |
398 | self.fields['postes_dae'].choices = self._poste_dae_choices(request) |
399 | self.fields['postes_rh'].choices = self._poste_rh_choices(request) | |
139686f2 | 400 | |
34950f36 OL |
401 | def _poste_dae_choices(self, request): |
402 | """ Menu déroulant pour les postes.""" | |
403 | postes_dae = dae.Poste.objects.ma_region_ou_service(request.user) \ | |
404 | .exclude(etat__in=(POSTE_ETAT_FINALISE, )) \ | |
405 | .annotate(num_dae=Count('dae_dossiers')) \ | |
406 | .filter(num_dae=0) \ | |
67ae0181 | 407 | .order_by('implantation', '-date_debut', ) |
139686f2 | 408 | |
98d51b59 | 409 | return [('', '----------')] + \ |
34950f36 OL |
410 | [('dae-%s' % p.id, label_poste_display(p)) for p in postes_dae] |
411 | ||
412 | def _poste_rh_choices(self, request): | |
413 | """ Menu déroulant pour les postes.""" | |
80be36aa | 414 | postes_dae = dae.Poste.objects.exclude(etat__in=(POSTE_ETAT_FINALISE, )) |
bed0c4c9 | 415 | today = datetime.date.today() |
80be36aa | 416 | id_poste_dae_commences = [p.id_rh_id for p in postes_dae if p.id_rh is not None] |
34950f36 | 417 | postes_rh = rh.Poste.objects.ma_region_ou_service(request.user) \ |
80be36aa | 418 | .exclude(id__in=id_poste_dae_commences) \ |
bed0c4c9 BS |
419 | .filter(Q(date_debut__lte=today) & |
420 | (Q(date_fin__gte=today) | | |
421 | Q(date_fin__isnull=True)) | |
422 | ) \ | |
67ae0181 | 423 | .order_by('implantation', '-date_debut', ) |
34950f36 OL |
424 | |
425 | return [('', '----------')] + \ | |
426 | [('rh-%s' % p.id, label_poste_display(p)) for p in postes_rh] | |
139686f2 | 427 | |
80be36aa OL |
428 | def clean(self): |
429 | cleaned_data = super(ChoosePosteForm, self).clean() | |
430 | postes_dae = cleaned_data.get("postes_dae") | |
431 | postes_rh = cleaned_data.get("postes_rh") | |
432 | if (postes_dae is u"" and postes_rh is u"") or \ | |
433 | (postes_dae is not u"" and postes_rh is not u""): | |
434 | raise forms.ValidationError("Choisissez un poste DAE ou un poste RH") | |
435 | return cleaned_data | |
436 | ||
437 | def redirect(self): | |
438 | poste_dae_key = self.cleaned_data.get("postes_dae") | |
439 | if poste_dae_key is not u"": | |
440 | return redirect(reverse('embauche', args=(poste_dae_key,))) | |
441 | poste_rh_key = self.cleaned_data.get("postes_rh") | |
442 | if poste_rh_key is not u"": | |
67ae0181 | 443 | return redirect("%s?creer_dossier_dae='M'" % reverse('poste', args=(poste_rh_key,))) |
139686f2 | 444 | |
139686f2 NC |
445 | class EmployeForm(forms.ModelForm): |
446 | """ Formulaire des employés. """ | |
447 | class Meta: | |
448 | model = dae.Employe | |
449 | fields = ('employe', 'nom', 'prenom', 'genre') | |
450 | ||
451 | # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison. | |
452 | employe = forms.ChoiceField(choices=(), required=False) | |
453 | ||
ac6235f6 | 454 | def __init__(self, *args, **kwargs): |
139686f2 | 455 | """ Mise à jour dynamique du contenu du menu des employés. """ |
ac6235f6 | 456 | request = kwargs.pop('request', None) |
139686f2 | 457 | super(EmployeForm, self).__init__(*args, **kwargs) |
f258e4e7 | 458 | self.fields['employe'].choices = _employe_choices(self, request) |
139686f2 | 459 | |
139686f2 | 460 | |
139686f2 NC |
461 | class DossierForm(forms.ModelForm): |
462 | """ Formulaire des dossiers. """ | |
463 | class Meta: | |
5a1f75cb | 464 | exclude = ('etat', 'employe', 'poste', 'date_debut',) |
139686f2 | 465 | model = dae.Dossier |
4d25e2ba | 466 | widgets = dict(statut_residence=forms.RadioSelect(), |
0e0aeb7e OL |
467 | contrat_date_debut=admin_widgets.AdminDateWidget(), |
468 | contrat_date_fin=admin_widgets.AdminDateWidget(), | |
4d25e2ba | 469 | ) |
e6f52402 | 470 | |
3799cafc | 471 | WF_HELP_TEXT = "" |
e0b93e3a | 472 | |
5a1f75cb | 473 | |
e6f52402 | 474 | class PosteWorkflowForm(WorkflowFormMixin): |
56589624 | 475 | bouton_libelles = POSTE_ETATS_BOUTONS |
5a1f75cb | 476 | |
e6f52402 OL |
477 | class Meta: |
478 | fields = ('etat', ) | |
479 | model = dae.Poste | |
9536ea21 | 480 | |
e0b93e3a | 481 | def __init__(self, *args, **kwargs): |
e54b7d5d | 482 | super(PosteWorkflowForm, self).__init__(*args, **kwargs) |
e0b93e3a OL |
483 | self.fields['etat'].help_text = WF_HELP_TEXT |
484 | ||
485 | ||
e6f52402 | 486 | class DossierWorkflowForm(WorkflowFormMixin): |
5a1f75cb EMS |
487 | bouton_libelles = POSTE_ETATS_BOUTONS # meme workflow que poste... |
488 | ||
e6f52402 | 489 | class Meta: |
9e40cfbe | 490 | fields = ('etat', ) |
e6f52402 | 491 | model = dae.Dossier |
e0b93e3a OL |
492 | |
493 | def __init__(self, *args, **kwargs): | |
e54b7d5d | 494 | super(DossierWorkflowForm, self).__init__(*args, **kwargs) |
e0b93e3a | 495 | self.fields['etat'].help_text = WF_HELP_TEXT |
e54b7d5d | 496 | self._etat_initial = self.instance.etat |
e0b93e3a | 497 | |
e54b7d5d EMS |
498 | def save(self): |
499 | super(DossierWorkflowForm, self).save() | |
500 | poste = self.instance.poste | |
66fefd2f OL |
501 | |
502 | # créer le commentaire automatique pour le poste associé | |
503 | commentaire = WorkflowCommentaire() | |
504 | commentaire.content_object = poste | |
505 | texte = u"Validation automatique à travers le dossier [%s] de %s\n%s" %( | |
506 | self.instance.id, | |
507 | self.instance, | |
508 | self.data.get('commentaire', ''), | |
509 | ) | |
510 | commentaire.texte = texte | |
511 | commentaire.etat_initial = self.instance._etat_courant | |
512 | commentaire.etat_final = self.instance.etat | |
513 | commentaire.owner = self.request.user | |
514 | commentaire.save() | |
515 | ||
516 | # force l'état du poste | |
517 | poste.etat = self.instance.etat | |
518 | poste.save() | |
9536ea21 | 519 | |
5a1f75cb | 520 | |
9536ea21 EMS |
521 | class ContratForm(forms.ModelForm): |
522 | ||
523 | class Meta: | |
9dfa4296 | 524 | fields = ('type_contrat', 'fichier', ) |
9536ea21 EMS |
525 | model = dae.Contrat |
526 | ||
5a1f75cb | 527 | |
c3f0b49f EMS |
528 | class DAENumeriseeForm(forms.ModelForm): |
529 | ||
530 | class Meta: | |
531 | model = dae.Dossier | |
532 | fields = ('dae_numerisee',) | |
cbfd7bd4 EMS |
533 | |
534 | ||
535 | class DAEFinaliseesSearchForm(forms.Form): | |
536 | q = forms.CharField( | |
537 | label='Recherche', required=False, | |
538 | widget=forms.TextInput(attrs={'size': 40}) | |
539 | ) | |
540 | importees = forms.ChoiceField( | |
541 | label='Importation', required=False, choices=( | |
542 | ('', ''), | |
543 | ('oui', 'DAE importées seulement'), | |
544 | ('non', 'DAE non-importées seulement'), | |
545 | ) | |
546 | ) |