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