1 # -*- encoding: utf-8 -*-
4 from ordereddict
import OrderedDict
5 from dateutil
.relativedelta
import relativedelta
6 from django
import forms
7 from django
.core
.urlresolvers
import reverse
8 from django
.core
.exceptions
import MultipleObjectsReturned
9 from django
.forms
.models
import BaseInlineFormSet
10 from django
.forms
.models
import (
11 inlineformset_factory
,
15 from django
.db
.models
import Q
, Max
, Count
16 from django
.shortcuts
import redirect
17 from django
.contrib
.admin
import widgets
as admin_widgets
19 from ajax_select
.fields
import AutoCompleteSelectField
21 from auf
.django
.references
import models
as ref
22 from auf
.django
.workflow
.forms
import WorkflowFormMixin
23 from auf
.django
.workflow
.models
import WorkflowCommentaire
25 from project
import groups
26 from project
.rh
import models
as rh
27 from project
.dae
import models
as dae
28 from .widgets
import ReadOnlyChoiceWidget
, ReadOnlyWidget
29 from project
.dae
.workflow
import POSTE_ETATS_BOUTONS
, POSTE_ETAT_FINALISE
32 class BaseInlineFormSetWithInitial(BaseInlineFormSet
):
34 Cette classe permet de fournir l'option initial aux inlineformsets.
35 Elle devient désuette en django 1.4.
37 def __init__(self
, data
=None, files
=None, instance
=None,
38 save_as_new
=False, prefix
=None, queryset
=None, **kwargs
):
40 self
.initial_extra
= kwargs
.pop('initial', None)
42 from django
.db
.models
.fields
.related
import RelatedObject
44 self
.instance
= self
.fk
.rel
.to()
46 self
.instance
= instance
47 self
.save_as_new
= save_as_new
48 # is there a better way to get the object descriptor?
49 self
.rel_name
= RelatedObject(self
.fk
.rel
.to
, self
.model
, self
.fk
).get_accessor_name()
51 queryset
= self
.model
._default_manager
52 qs
= queryset
.filter(**{self
.fk
.name
: self
.instance
})
53 super(BaseInlineFormSetWithInitial
, self
).__init__(data
, files
, prefix
=prefix
,
54 queryset
=qs
, **kwargs
)
56 def _construct_form(self
, i
, **kwargs
):
57 if self
.is_bound
and i
< self
.initial_form_count():
58 # Import goes here instead of module-level because importing
59 # django.db has side effects.
60 from django
.db
import connections
61 pk_key
= "%s-%s" % (self
.add_prefix(i
), self
.model
._meta
.pk
.name
)
62 pk
= self
.data
[pk_key
]
63 pk_field
= self
.model
._meta
.pk
64 pk
= pk_field
.get_db_prep_lookup('exact', pk
,
65 connection
=connections
[self
.get_queryset().db
])
66 if isinstance(pk
, list):
68 kwargs
['instance'] = self
._existing_object(pk
)
69 if i
< self
.initial_form_count() and not kwargs
.get('instance'):
70 kwargs
['instance'] = self
.get_queryset()[i
]
71 if i
>= self
.initial_form_count() and self
.initial_extra
:
72 # Set initial values for extra forms
74 kwargs
['initial'] = self
.initial_extra
[i
-self
.initial_form_count()]
78 defaults
= {'auto_id': self
.auto_id
, 'prefix': self
.add_prefix(i
)}
80 defaults
['data'] = self
.data
81 defaults
['files'] = self
.files
84 defaults
['initial'] = self
.initial
[i
]
87 # Allow extra forms to be empty.
88 if i
>= self
.initial_form_count():
89 defaults
['empty_permitted'] = True
90 defaults
.update(kwargs
)
91 form
= self
.form(**defaults
)
92 self
.add_fields(form
, i
)
96 def _implantation_choices(obj
, request
):
98 employe
= groups
.get_employe_from_user(request
.user
)
99 q
= Q(**{'zone_administrative__in': groups
.get_zones_from_user(request
.user
)})
102 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
103 if groups
.DRH_NIVEAU_1
in user_groupes
or \
104 groups
.DRH_NIVEAU_2
in user_groupes
:
106 return [('', '----------')] + \
107 [(i
.id, unicode(i
), )for i
in ref
.Implantation
.objects
.filter(q
)]
110 def _employe_choices(obj
, request
):
112 employe
= groups
.get_employe_from_user(request
.user
)
113 q_dae_region_service
= Q(
114 poste__implantation__zone_administrative__in
=(
115 groups
.get_zones_from_user(request
.user
)
118 q_rh_region_service
= Q(
119 poste__implantation__zone_administrative__in
=(
120 groups
.get_zones_from_user(request
.user
)
124 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
125 if groups
.DRH_NIVEAU_1
in user_groupes
or \
126 groups
.DRH_NIVEAU_2
in user_groupes
:
127 q_dae_region_service
= Q()
128 q_rh_region_service
= Q()
130 # On filtre les employes avec les droits régionaux et on s'assure que
131 # c'est bien le dernier dossier en date pour sortir l'employe. On retient
132 # un employé qui travaille présentement dans la même région que le user
134 dossiers_regionaux_ids
= [
135 d
.id for d
in dae
.Dossier
.objects
.filter(q_dae_region_service
)
139 for d
in dae
.Dossier
.objects
141 .annotate(dernier_dossier
=Max('id'))
142 if d
['dernier_dossier'] in dossiers_regionaux_ids
144 dae_employe
= dae
.Employe
.objects
.filter(id__in
=employes_ids
)
145 dae_
= dae_employe
.filter(id_rh__isnull
=True)
146 copies
= dae_employe
.filter(Q(id_rh__isnull
=False))
147 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
149 dossiers_regionaux_ids
= [
150 d
.id for d
in rh
.Dossier
.objects
.filter(q_rh_region_service
)
154 for d
in rh
.Dossier
.objects
156 .annotate(dernier_dossier
=Max('id'))
157 if d
['dernier_dossier'] in dossiers_regionaux_ids
159 rhv1
= rh
.Employe
.objects \
160 .filter(id__in
=employes_ids
) \
161 .exclude(id__in
=id_copies
)
163 # On ajoute les nouveaux Employés DAE qui ont été crées, mais qui n'ont
164 # pas de Dossier associés
165 employes_avec_dae
= [d
.employe_id
for d
in dae
.Dossier
.objects
.all()]
166 employes_orphelins
= dae
.Employe
.objects
.exclude(id__in
=employes_avec_dae
)
168 def option_label(employe
, extra
=""):
170 extra
= " [%s]" % extra
171 return "%s %s %s" % (employe
.nom
.upper(), employe
.prenom
.title(), extra
)
173 lbl_rh
= sorted([('rh-%s' % p
.id, option_label(p
, "existant dans rh")) for p
in rhv1
],
175 lbl_dae
= sorted([('dae-%s' % p
.id, option_label(p
)) for p
in dae_ | copies | employes_orphelins
],
177 return [('', 'Nouvel employé')] + lbl_rh
+ lbl_dae
180 def label_poste_display(poste
):
181 """Formate un visuel pour un poste dans une liste déroulante"""
184 annee
= poste
.date_debut
.year
187 label
= u
"%s (%s) %s [%s]" % (
189 poste
.implantation
.nom_court
,
191 #poste.type_poste.categorie_emploi.nom,
197 PostePieceFormSet
= inlineformset_factory(dae
.Poste
, dae
.PostePiece
,)
198 DossierPieceForm
= inlineformset_factory(dae
.Dossier
, dae
.DossierPiece
)
200 # Ce formset est utilisé dans le cas de la création de poste prépopulé avec les
202 FinancementFormSetInitial
= inlineformset_factory(
204 dae
.PosteFinancement
,
205 formset
=BaseInlineFormSetWithInitial
,
208 FinancementFormSet
= inlineformset_factory(
210 dae
.PosteFinancement
,
215 class DossierComparaisonForm(forms
.ModelForm
):
217 recherche
= AutoCompleteSelectField('dossiers', required
=False)
218 poste
= forms
.CharField(
219 max_length
=255, widget
=forms
.TextInput(attrs
={'size': '60'})
221 cmp_dossier
= forms
.IntegerField(
222 widget
=forms
.widgets
.HiddenInput
,
227 model
= dae
.DossierComparaison
228 exclude
= ('dossier',)
230 DossierComparaisonFormSet
= modelformset_factory(
231 dae
.DossierComparaison
, extra
=3, max_num
=3, form
=DossierComparaisonForm
235 class PosteComparaisonForm(forms
.ModelForm
):
237 recherche
= AutoCompleteSelectField('dae_postes', required
=False)
239 cmp_poste
= forms
.IntegerField(
240 widget
=forms
.widgets
.HiddenInput
,
245 model
= dae
.PosteComparaison
248 # Ce formset est utilisé dans le cas de la création de poste prépopulé avec les
250 PosteComparaisonFormSetInitial
= inlineformset_factory(
252 dae
.PosteComparaison
,
255 form
=PosteComparaisonForm
,
256 formset
=BaseInlineFormSetWithInitial
,
258 PosteComparaisonFormSet
= inlineformset_factory(
260 dae
.PosteComparaison
,
263 form
=PosteComparaisonForm
,
267 class FlexibleRemunForm(forms
.ModelForm
):
268 # Utilisé dans templats.
269 montant_mensuel
= forms
.DecimalField(required
=False)
270 montant
= forms
.DecimalField(required
=True, label
='Montant annuel')
273 model
= dae
.Remuneration
275 def __init__(self
, *a
, **kw
):
276 super(FlexibleRemunForm
, self
).__init__(*a
, **kw
)
277 # self.fields['type'].widget = ReadOnlyChoiceWidget(choices=self.fields['type'].choices)
279 def clean_devise(self
):
280 devise
= self
.cleaned_data
['devise']
281 if devise
.code
== 'EUR':
283 implantation
= ref
.Implantation
.objects
.get(
284 id=self
.data
['implantation']
286 liste_taux
= devise
.tauxchange_set
.order_by('-annee')
287 if len(liste_taux
) == 0:
288 raise forms
.ValidationError(
289 u
"La devise %s n'a pas de taux pour l'implantation %s" %
290 (devise
, implantation
)
295 def has_changed(self
):
297 Modification de has_changed pour qu'il ignore les montant a 0
301 changed_data
= self
.changed_data
303 # Type is set in hidden fields, it shouldn't be changed by the
304 # user; ignore when checking if data has changed.
305 if 'type' in changed_data
:
306 changed_data
.pop(changed_data
.index('type'))
308 # Montant is set to 0 in javascript, ifnore 'montant' data if
311 # Generer le key tel qu'identifié dans self.data:
312 montant_key
= '-'.join((self
.prefix
, 'montant'))
314 if ('montant' in changed_data
and
315 self
.data
.get(montant_key
, '0') == '0'):
316 changed_data
.pop(changed_data
.index('montant'))
318 return bool(changed_data
)
321 class ReadOnlyRemunForm(FlexibleRemunForm
):
322 # Utilisé dans templats.
324 def __init__(self
, *a
, **kw
):
325 super (ReadOnlyRemunForm
, self
).__init__(*a
, **kw
)
326 for field
in self
.fields
:
327 field
= self
.fields
[field
]
328 if not isinstance(field
.widget
, (
329 forms
.widgets
.HiddenInput
,
330 forms
.widgets
.Select
)):
331 field
.widget
= ReadOnlyWidget()
332 elif isinstance(field
.widget
, forms
.widgets
.Select
):
333 field
.widget
= ReadOnlyChoiceWidget(choices
=field
.choices
)
336 class GroupedInlineFormset(BaseInlineFormSet
):
341 choice_overrides
=[]):
344 # Create pre-defined groups.
345 self
.groups
= OrderedDict()
347 self
.groups
[group
[0]] = {
353 # Assign each form to a group.
354 for form
in self
.forms
:
355 if bool(form
.initial
):
356 grp
= group_accessor(form
)
357 if grp
[0] not in self
.groups
:
358 self
.groups
[grp
[0]] = {
363 self
.groups
[grp
[0]]['forms'].append(form
)
365 # Add extra forms (n extra for each grop).
367 for i
in xrange(len(self
.groups
) * self
.extra
):
369 self
._construct_form(self
.initial_form_count() + i
))
371 for g
in self
.groups
:
372 for i
in xrange(self
.extra
):
373 tmp_form
= tmp_extras
.pop()
374 self
.groups
[g
]['forms'].append(tmp_form
)
375 self
.forms
.append(tmp_form
)
378 # Override form choices with the data provided in
380 for key
in choice_overrides
:
381 for form
in self
.groups
.get(key
, {'forms': []})['forms']:
382 for field_key
in choice_overrides
[key
]:
383 form
.fields
[field_key
].choices
= choice_overrides
[
387 # Create an iterable for easier access in template.
388 self
.group_list
= self
.groups
.values()
390 # def set_groups(self, group_accessor, groups, group_order=[]):
392 # group_accessor: A function that will get the key and name from
394 # group_order: list the group keys here in a list and
395 # GroupedInlineFormset.groups will be ordered (ordereddict) by
396 # the key sequence provided here. Any missing key from the
400 # # Build group list.
401 # self.groups = OrderedDict()
403 # # self.groups_and_forms = []
404 # for form in self.forms:
405 # group_key, group_name = group_accessor(form)
406 # if not temp_groups.has_key(group_key):
407 # temp_groups[group_key] = {
408 # 'name': group_name,
412 # temp_groups[group_key]['forms'].append(form)
414 # for order_key in group_order:
415 # if temp_groups.has_key(order_key):
416 # self.groups[order_key] = temp_groups.pop(order_key)
418 # for key in temp_groups:
419 # self.groups[key] = temp_groups[key]
423 # self.group_list = self.groups.values()
426 def remun_formset_factory(parent_model
,
428 form
=forms
.ModelForm
,
429 formset
=GroupedInlineFormset
,
438 formfield_callback
=None,
440 choice_overrides
=[]):
441 trs
= rh
.TypeRemuneration
.objects
.all()
442 # extra = max_num = trs.count()
443 fk
= _get_foreign_key(parent_model
, model
, fk_name
=fk_name
)
444 # enforce a max_num=1 when the foreign key to the parent model is unique.
449 'formfield_callback': formfield_callback
,
452 'can_delete': can_delete
,
453 'can_order': can_order
,
458 FormSet
= modelformset_factory(model
, **kwargs
)
460 FormSet
.read_only
= read_only
463 rtype
= form
.initial
['type']
464 if not isinstance(rtype
, rh
.TypeRemuneration
):
465 rtype
= rh
.TypeRemuneration
.objects
.get(id=rtype
)
466 return (rtype
.nature_remuneration
,
467 rtype
.nature_remuneration
472 # Monkey patch FormSet.
473 def __init__(inst
, *a
, **kw
):
474 super(inst
.__class__
, inst
).__init__(*a
, **kw
)
475 inst
.set_groups(groups
, grouper
, choice_overrides
)
477 FormSet
.__init__
= __init__
482 def remun_formset_factory_factory(read_only
=False, parent_model
=dae
.Dossier
, model
=dae
.Remuneration
):
484 Don't we love factory factories?
487 null_choice
= ('', '-' * 10)
488 extras
= 2 if not read_only
else 0
489 can_delete
= False if read_only
else True
490 form_class
= ReadOnlyRemunForm
if read_only
else FlexibleRemunForm
492 return remun_formset_factory(
497 can_delete
=can_delete
,
500 (u
'Traitement', u
'Traitement',),
501 (u
'Indemnité', u
'Indemnité',),
502 (u
'Charges', u
'Charges',),
503 (u
'Accessoire', u
'Accessoire',),
504 (u
'RAS', u
'Rémunération autre source',),
508 'type': [null_choice
] + list(
509 rh
.TypeRemuneration
.objects
.filter(
510 nature_remuneration
=u
'Traitement').values_list(
515 'type': [null_choice
] + list(
516 rh
.TypeRemuneration
.objects
.filter(
517 nature_remuneration
=u
'Indemnité').values_list(
522 'type': [null_choice
] + list(
523 rh
.TypeRemuneration
.objects
.filter(
524 nature_remuneration
=u
'Charges').values_list(
529 'type': [null_choice
] + list(
530 rh
.TypeRemuneration
.objects
.filter(
531 nature_remuneration
=u
'Accessoire').values_list(
536 'type': [null_choice
] + list(
537 rh
.TypeRemuneration
.objects
.filter(
538 nature_remuneration
=u
'RAS').values_list(
545 RemunForm
= remun_formset_factory_factory(
547 parent_model
=dae
.Dossier
,
548 model
=dae
.Remuneration
,
551 ReadOnlyRemunFormSet
= remun_formset_factory_factory(
553 parent_model
=dae
.Dossier
,
554 model
=dae
.Remuneration
,
557 PosteCompReadOnlyRemunFormSet
= remun_formset_factory_factory(
559 parent_model
=dae
.PosteComparaison
,
560 model
=dae
.PosteComparaisonRemuneration
,
563 DossierCompReadOnlyRemunFormSet
= remun_formset_factory_factory(
565 parent_model
=dae
.DossierComparaison
,
566 model
=dae
.DossierComparaisonRemuneration
,
570 class PosteForm(forms
.ModelForm
):
571 """ Formulaire des postes. """
573 # On ne propose que les services actifs
574 service
= forms
.ModelChoiceField(
575 queryset
=rh
.Service
.objects
.all(), required
=True
578 responsable
= AutoCompleteSelectField('responsables', required
=True)
579 #responsable = forms.ModelChoiceField(
580 # queryset=rh.Poste.objects.select_related(depth=1))
582 # La liste des choix est laissée vide. Voir __init__ pour la raison.
583 poste
= forms
.ChoiceField(label
="Nouveau poste ou évolution du poste",
584 choices
=(), required
=False)
586 valeur_point_min
= forms
.ModelChoiceField(
587 queryset
=rh
.ValeurPoint
.actuelles
.all(), required
=False
589 valeur_point_max
= forms
.ModelChoiceField(
590 queryset
=rh
.ValeurPoint
.actuelles
.all(), required
=False
595 fields
= ('type_intervention',
596 'poste', 'implantation', 'type_poste', 'service', 'nom',
597 'responsable', 'local', 'expatrie', 'mise_a_disposition',
598 'appel', 'date_debut', 'date_fin',
599 'regime_travail', 'regime_travail_nb_heure_semaine',
600 'classement_min', 'classement_max',
601 'valeur_point_min', 'valeur_point_max',
602 'devise_min', 'devise_max',
603 'salaire_min', 'salaire_max',
604 'indemn_expat_min', 'indemn_expat_max',
605 'indemn_fct_min', 'indemn_fct_max',
606 'charges_patronales_min', 'charges_patronales_max',
607 'autre_min', 'autre_max', 'devise_comparaison',
608 'comp_locale_min', 'comp_locale_max',
609 'comp_universite_min', 'comp_universite_max',
610 'comp_fonctionpub_min', 'comp_fonctionpub_max',
611 'comp_ong_min', 'comp_ong_max',
612 'comp_autre_min', 'comp_autre_max',
615 widgets
= dict(type_intervention
=forms
.RadioSelect(),
616 appel
=forms
.RadioSelect(),
617 nom
=forms
.TextInput(attrs
={'size': 60},),
618 date_debut
=admin_widgets
.AdminDateWidget(),
619 date_fin
=admin_widgets
.AdminDateWidget(),
620 justification
=forms
.Textarea(attrs
={'cols': 80},),
621 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
622 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
625 def __init__(self
, *args
, **kwargs
):
626 """ Mise à jour dynamique du contenu du menu des postes.
628 Si on ne met le menu à jour de cette façon, à chaque instantiation du
629 formulaire, son contenu est mis en cache par le système et il ne
630 reflète pas les changements apportés par les ajouts, modifications,
633 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
634 car le "id" de chaque choix est spécial (voir _poste_choices).
637 request
= kwargs
.pop('request')
638 super(PosteForm
, self
).__init__(*args
, **kwargs
)
639 self
.fields
['poste'].choices
= self
._poste_choices(request
)
641 self
.fields
['implantation'].choices
= \
642 _implantation_choices(self
, request
)
644 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
645 if self
.instance
and self
.instance
.id is None:
646 dossiers
= self
.instance
.get_dossiers()
647 if len(dossiers
) > 0:
648 self
.initial
['service'] = dossiers
[0].poste
.service
650 def _poste_choices(self
, request
):
651 """ Menu déroulant pour les postes.
652 Constitué des postes de RH
654 postes_rh
= rh
.Poste
.objects
.ma_region_ou_service(request
.user
).all()
655 postes_rh
= postes_rh
.select_related(depth
=1)
657 return [('', 'Nouveau poste')] + \
658 sorted([('rh-%s' % p
.id, label_poste_display(p
)) for p
in
664 Validation conditionnelles de certains champs.
666 cleaned_data
= self
.cleaned_data
668 if cleaned_data
.get("local") is False \
669 and cleaned_data
.get("expatrie") is False:
670 msg
= "Le poste doit au moins être ouvert localement " \
672 self
._errors
["local"] = self
.error_class([msg
])
673 self
._errors
["expatrie"] = ''
674 raise forms
.ValidationError(msg
)
679 class ChoosePosteForm(forms
.Form
):
683 # La liste des choix est laissée vide. Voir PosteForm.__init__.
684 postes_dae
= forms
.ChoiceField(choices
=(), required
=False)
685 postes_rh
= forms
.ChoiceField(choices
=(), required
=False)
687 def __init__(self
, request
=None, *args
, **kwargs
):
688 super(ChoosePosteForm
, self
).__init__(*args
, **kwargs
)
689 self
.fields
['postes_dae'].choices
= self
._poste_dae_choices(request
)
690 self
.fields
['postes_rh'].choices
= self
._poste_rh_choices(request
)
692 def _poste_dae_choices(self
, request
):
693 """ Menu déroulant pour les postes."""
694 postes_dae
= dae
.Poste
.objects
.ma_region_ou_service(request
.user
) \
695 .exclude(etat__in
=(POSTE_ETAT_FINALISE
, )) \
696 .annotate(num_dae
=Count('dae_dossiers')) \
698 .order_by('implantation', '-date_debut', )
700 return [('', '----------')] + \
701 [('dae-%s' % p
.id, label_poste_display(p
)) for p
in postes_dae
]
703 def _poste_rh_choices(self
, request
):
704 """ Menu déroulant pour les postes."""
705 postes_dae
= dae
.Poste
.objects
.exclude(etat__in
=(POSTE_ETAT_FINALISE
, ))
706 today
= datetime
.date
.today()
707 id_poste_dae_commences
= [p
.id_rh_id
for p
in postes_dae
if p
.id_rh
is not None]
708 postes_rh
= rh
.Poste
.objects
.ma_region_ou_service(request
.user
) \
709 .exclude(id__in
=id_poste_dae_commences
) \
710 .filter(Q(date_debut__lte
=today
) &
711 (Q(date_fin__gte
=today
) |
712 Q(date_fin__isnull
=True))
714 .order_by('implantation', '-date_debut', )
716 return [('', '----------')] + \
717 [('rh-%s' % p
.id, label_poste_display(p
)) for p
in postes_rh
]
720 cleaned_data
= super(ChoosePosteForm
, self
).clean()
721 postes_dae
= cleaned_data
.get("postes_dae")
722 postes_rh
= cleaned_data
.get("postes_rh")
723 if (postes_dae
is u
"" and postes_rh
is u
"") or \
724 (postes_dae
is not u
"" and postes_rh
is not u
""):
725 raise forms
.ValidationError("Choisissez un poste DAE ou un poste RH")
729 poste_dae_key
= self
.cleaned_data
.get("postes_dae")
730 if poste_dae_key
is not u
"":
731 return redirect(reverse('embauche', args
=(poste_dae_key
,)))
732 poste_rh_key
= self
.cleaned_data
.get("postes_rh")
733 if poste_rh_key
is not u
"":
734 return redirect("%s?creer_dossier_dae='M'" % reverse('poste', args
=(poste_rh_key
,)))
736 class EmployeForm(forms
.ModelForm
):
737 """ Formulaire des employés. """
740 fields
= ('employe', 'nom', 'prenom', 'genre')
742 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
743 employe
= forms
.ChoiceField(choices
=(), required
=False)
745 def __init__(self
, *args
, **kwargs
):
746 """ Mise à jour dynamique du contenu du menu des employés. """
747 request
= kwargs
.pop('request', None)
748 super(EmployeForm
, self
).__init__(*args
, **kwargs
)
749 self
.fields
['employe'].choices
= _employe_choices(self
, request
)
752 class DossierForm(forms
.ModelForm
):
753 """ Formulaire des dossiers. """
755 exclude
= ('etat', 'employe', 'poste', 'date_debut',)
757 widgets
= dict(statut_residence
=forms
.RadioSelect(),
758 contrat_date_debut
=admin_widgets
.AdminDateWidget(),
759 contrat_date_fin
=admin_widgets
.AdminDateWidget(),
765 class PosteWorkflowForm(WorkflowFormMixin
):
766 bouton_libelles
= POSTE_ETATS_BOUTONS
772 def __init__(self
, *args
, **kwargs
):
773 super(PosteWorkflowForm
, self
).__init__(*args
, **kwargs
)
774 self
.fields
['etat'].help_text
= WF_HELP_TEXT
777 class DossierWorkflowForm(WorkflowFormMixin
):
778 bouton_libelles
= POSTE_ETATS_BOUTONS
# meme workflow que poste...
784 def __init__(self
, *args
, **kwargs
):
785 super(DossierWorkflowForm
, self
).__init__(*args
, **kwargs
)
786 self
.fields
['etat'].help_text
= WF_HELP_TEXT
787 self
._etat_initial
= self
.instance
.etat
790 super(DossierWorkflowForm
, self
).save()
791 poste
= self
.instance
.poste
793 # créer le commentaire automatique pour le poste associé
794 commentaire
= WorkflowCommentaire()
795 commentaire
.content_object
= poste
796 texte
= u
"Validation automatique à travers le dossier [%s] de %s\n%s" %(
799 self
.data
.get('commentaire', ''),
801 commentaire
.texte
= texte
802 commentaire
.etat_initial
= self
.instance
._etat_courant
803 commentaire
.etat_final
= self
.instance
.etat
804 commentaire
.owner
= self
.request
.user
807 # force l'état du poste
808 poste
.etat
= self
.instance
.etat
812 class ContratForm(forms
.ModelForm
):
815 fields
= ('type_contrat', 'fichier', )
819 class DAENumeriseeForm(forms
.ModelForm
):
823 fields
= ('dae_numerisee',)
826 class DAEFinaliseesSearchForm(forms
.Form
):
828 label
='Recherche', required
=False,
829 widget
=forms
.TextInput(attrs
={'size': 40})
831 importees
= forms
.ChoiceField(
832 label
='Importation', required
=False, choices
=(
834 ('oui', 'DAE importées seulement'),
835 ('non', 'DAE non-importées seulement'),