1 # -*- encoding: utf-8 -*-
4 from ordereddict
import OrderedDict
5 from django
import forms
6 from django
.core
.urlresolvers
import reverse
7 from django
.core
.exceptions
import MultipleObjectsReturned
8 from django
.forms
.models
import BaseInlineFormSet
9 from django
.forms
.models
import (
10 inlineformset_factory
,
14 from django
.db
.models
import Q
, Max
, Count
15 from django
.shortcuts
import redirect
16 from django
.contrib
.admin
import widgets
as admin_widgets
18 from ajax_select
.fields
import AutoCompleteSelectField
20 from auf
.django
.references
import models
as ref
21 from auf
.django
.workflow
.forms
import WorkflowFormMixin
22 from auf
.django
.workflow
.models
import WorkflowCommentaire
24 from project
import groups
25 from project
.rh
import models
as rh
26 from project
.dae
import models
as dae
27 from .widgets
import ReadOnlyChoiceWidget
, ReadOnlyWidget
28 from project
.dae
.workflow
import POSTE_ETATS_BOUTONS
, POSTE_ETAT_FINALISE
31 class BaseInlineFormSetWithInitial(BaseInlineFormSet
):
33 Cette classe permet de fournir l'option initial aux inlineformsets.
34 Elle devient désuette en django 1.4.
36 def __init__(self
, data
=None, files
=None, instance
=None,
37 save_as_new
=False, prefix
=None, queryset
=None, **kwargs
):
39 self
.initial_extra
= kwargs
.pop('initial', None)
41 from django
.db
.models
.fields
.related
import RelatedObject
43 self
.instance
= self
.fk
.rel
.to()
45 self
.instance
= instance
46 self
.save_as_new
= save_as_new
47 # is there a better way to get the object descriptor?
48 self
.rel_name
= RelatedObject(self
.fk
.rel
.to
, self
.model
, self
.fk
).get_accessor_name()
50 queryset
= self
.model
._default_manager
51 qs
= queryset
.filter(**{self
.fk
.name
: self
.instance
})
52 super(BaseInlineFormSetWithInitial
, self
).__init__(data
, files
, prefix
=prefix
,
53 queryset
=qs
, **kwargs
)
55 def _construct_form(self
, i
, **kwargs
):
56 if self
.is_bound
and i
< self
.initial_form_count():
57 # Import goes here instead of module-level because importing
58 # django.db has side effects.
59 from django
.db
import connections
60 pk_key
= "%s-%s" % (self
.add_prefix(i
), self
.model
._meta
.pk
.name
)
61 pk
= self
.data
[pk_key
]
62 pk_field
= self
.model
._meta
.pk
63 pk
= pk_field
.get_db_prep_lookup('exact', pk
,
64 connection
=connections
[self
.get_queryset().db
])
65 if isinstance(pk
, list):
67 kwargs
['instance'] = self
._existing_object(pk
)
68 if i
< self
.initial_form_count() and not kwargs
.get('instance'):
69 kwargs
['instance'] = self
.get_queryset()[i
]
70 if i
>= self
.initial_form_count() and self
.initial_extra
:
71 # Set initial values for extra forms
73 kwargs
['initial'] = self
.initial_extra
[i
-self
.initial_form_count()]
77 defaults
= {'auto_id': self
.auto_id
, 'prefix': self
.add_prefix(i
)}
79 defaults
['data'] = self
.data
80 defaults
['files'] = self
.files
83 defaults
['initial'] = self
.initial
[i
]
86 # Allow extra forms to be empty.
87 if i
>= self
.initial_form_count():
88 defaults
['empty_permitted'] = True
89 defaults
.update(kwargs
)
90 form
= self
.form(**defaults
)
91 self
.add_fields(form
, i
)
95 def _implantation_choices(obj
, request
):
97 employe
= groups
.get_employe_from_user(request
.user
)
98 q
= Q(**{'zone_administrative': employe
.implantation
.zone_administrative
})
101 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
102 if groups
.DRH_NIVEAU_1
in user_groupes
or \
103 groups
.DRH_NIVEAU_2
in user_groupes
:
105 return [('', '----------')] + \
106 [(i
.id, unicode(i
), )for i
in ref
.Implantation
.objects
.filter(q
)]
109 def _employe_choices(obj
, request
):
111 employe
= groups
.get_employe_from_user(request
.user
)
112 q_dae_region_service
= Q(
113 poste__implantation__zone_administrative
=(
114 employe
.implantation
.zone_administrative
117 q_rh_region_service
= Q(
118 poste__implantation__zone_administrative
=(
119 employe
.implantation
.zone_administrative
123 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
124 if groups
.DRH_NIVEAU_1
in user_groupes
or \
125 groups
.DRH_NIVEAU_2
in user_groupes
:
126 q_dae_region_service
= Q()
127 q_rh_region_service
= Q()
129 # On filtre les employes avec les droits régionaux et on s'assure que
130 # c'est bien le dernier dossier en date pour sortir l'employe. On retient
131 # un employé qui travaille présentement dans la même région que le user
133 dossiers_regionaux_ids
= [
134 d
.id for d
in dae
.Dossier
.objects
.filter(q_dae_region_service
)
138 for d
in dae
.Dossier
.objects
140 .annotate(dernier_dossier
=Max('id'))
141 if d
['dernier_dossier'] in dossiers_regionaux_ids
143 dae_employe
= dae
.Employe
.objects
.filter(id__in
=employes_ids
)
144 dae_
= dae_employe
.filter(id_rh__isnull
=True)
145 copies
= dae_employe
.filter(Q(id_rh__isnull
=False))
146 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
148 dossiers_regionaux_ids
= [
149 d
.id for d
in rh
.Dossier
.objects
.filter(q_rh_region_service
)
153 for d
in rh
.Dossier
.objects
155 .annotate(dernier_dossier
=Max('id'))
156 if d
['dernier_dossier'] in dossiers_regionaux_ids
158 rhv1
= rh
.Employe
.objects \
159 .filter(id__in
=employes_ids
) \
160 .exclude(id__in
=id_copies
)
162 # On ajoute les nouveaux Employés DAE qui ont été crées, mais qui n'ont
163 # pas de Dossier associés
164 employes_avec_dae
= [d
.employe_id
for d
in dae
.Dossier
.objects
.all()]
165 employes_orphelins
= dae
.Employe
.objects
.exclude(id__in
=employes_avec_dae
)
167 def option_label(employe
, extra
=""):
169 extra
= " [%s]" % extra
170 return "%s %s %s" % (employe
.nom
.upper(), employe
.prenom
.title(), extra
)
172 lbl_rh
= sorted([('rh-%s' % p
.id, option_label(p
, "existant dans rh")) for p
in rhv1
],
174 lbl_dae
= sorted([('dae-%s' % p
.id, option_label(p
)) for p
in dae_ | copies | employes_orphelins
],
176 return [('', 'Nouvel employé')] + lbl_rh
+ lbl_dae
179 def label_poste_display(poste
):
180 """Formate un visuel pour un poste dans une liste déroulante"""
183 annee
= poste
.date_debut
.year
186 label
= u
"%s (%s) %s [%s]" % (
188 poste
.implantation
.nom_court
,
190 #poste.type_poste.categorie_emploi.nom,
196 PostePieceFormSet
= inlineformset_factory(dae
.Poste
, dae
.PostePiece
,)
197 DossierPieceForm
= inlineformset_factory(dae
.Dossier
, dae
.DossierPiece
)
199 # Ce formset est utilisé dans le cas de la création de poste prépopulé avec les
201 FinancementFormSetInitial
= inlineformset_factory(
203 dae
.PosteFinancement
,
204 formset
=BaseInlineFormSetWithInitial
,
207 FinancementFormSet
= inlineformset_factory(
209 dae
.PosteFinancement
,
214 class DossierComparaisonForm(forms
.ModelForm
):
216 recherche
= AutoCompleteSelectField('dossiers', required
=False)
217 poste
= forms
.CharField(
218 max_length
=255, widget
=forms
.TextInput(attrs
={'size': '60'})
222 model
= dae
.DossierComparaison
223 exclude
= ('dossier',)
225 DossierComparaisonFormSet
= modelformset_factory(
226 dae
.DossierComparaison
, extra
=3, max_num
=3, form
=DossierComparaisonForm
230 class PosteComparaisonForm(forms
.ModelForm
):
232 recherche
= AutoCompleteSelectField('dae_postes', required
=False)
235 model
= dae
.PosteComparaison
238 # Ce formset est utilisé dans le cas de la création de poste prépopulé avec les
240 PosteComparaisonFormSetInitial
= inlineformset_factory(
242 dae
.PosteComparaison
,
245 form
=PosteComparaisonForm
,
246 formset
=BaseInlineFormSetWithInitial
,
248 PosteComparaisonFormSet
= inlineformset_factory(
250 dae
.PosteComparaison
,
253 form
=PosteComparaisonForm
,
257 class FlexibleRemunForm(forms
.ModelForm
):
258 # Utilisé dans templats.
259 montant_mensuel
= forms
.DecimalField(required
=False)
260 montant
= forms
.DecimalField(required
=True, label
='Montant annuel')
263 model
= dae
.Remuneration
265 def __init__(self
, *a
, **kw
):
266 super(FlexibleRemunForm
, self
).__init__(*a
, **kw
)
267 # self.fields['type'].widget = ReadOnlyChoiceWidget(choices=self.fields['type'].choices)
269 def clean_devise(self
):
270 devise
= self
.cleaned_data
['devise']
271 if devise
.code
== 'EUR':
273 implantation
= ref
.Implantation
.objects
.get(
274 id=self
.data
['implantation']
276 liste_taux
= devise
.tauxchange_set
.order_by('-annee')
277 if len(liste_taux
) == 0:
278 raise forms
.ValidationError(
279 u
"La devise %s n'a pas de taux pour l'implantation %s" %
280 (devise
, implantation
)
285 def has_changed(self
):
287 Modification de has_changed pour qu'il ignore les montant a 0
291 changed_data
= self
.changed_data
293 # Type is set in hidden fields, it shouldn't be changed by the
294 # user; ignore when checking if data has changed.
295 if 'type' in changed_data
:
296 changed_data
.pop(changed_data
.index('type'))
298 # Montant is set to 0 in javascript, ifnore 'montant' data if
301 # Generer le key tel qu'identifié dans self.data:
302 montant_key
= '-'.join((self
.prefix
, 'montant'))
304 if ('montant' in changed_data
and
305 self
.data
.get(montant_key
, '0') == '0'):
306 changed_data
.pop(changed_data
.index('montant'))
308 return bool(changed_data
)
311 class ReadOnlyRemunForm(FlexibleRemunForm
):
312 # Utilisé dans templats.
314 def __init__(self
, *a
, **kw
):
315 super (ReadOnlyRemunForm
, self
).__init__(*a
, **kw
)
316 for field
in self
.fields
:
317 field
= self
.fields
[field
]
318 if not isinstance(field
.widget
, (
319 forms
.widgets
.HiddenInput
,
320 forms
.widgets
.Select
)):
321 field
.widget
= ReadOnlyWidget()
322 elif isinstance(field
.widget
, forms
.widgets
.Select
):
323 field
.widget
= ReadOnlyChoiceWidget(choices
=field
.choices
)
326 class GroupedInlineFormset(BaseInlineFormSet
):
331 choice_overrides
=[]):
334 # Create pre-defined groups.
335 self
.groups
= OrderedDict()
337 self
.groups
[group
[0]] = {
343 # Assign each form to a group.
344 for form
in self
.forms
:
345 if bool(form
.initial
):
346 grp
= group_accessor(form
)
347 if grp
[0] not in self
.groups
:
348 self
.groups
[grp
[0]] = {
353 self
.groups
[grp
[0]]['forms'].append(form
)
355 # Add extra forms (n extra for each grop).
357 for i
in xrange(len(self
.groups
) * self
.extra
):
359 self
._construct_form(self
.initial_form_count() + i
))
361 for g
in self
.groups
:
362 for i
in xrange(self
.extra
):
363 self
.groups
[g
]['forms'].append(tmp_extras
.pop())
366 # Override form choices with the data provided in
368 for key
in choice_overrides
:
369 for form
in self
.groups
.get(key
, {'forms': []})['forms']:
370 for field_key
in choice_overrides
[key
]:
371 form
.fields
[field_key
].choices
= choice_overrides
[
375 # Create an iterable for easier access in template.
376 self
.group_list
= self
.groups
.values()
378 # def set_groups(self, group_accessor, groups, group_order=[]):
380 # group_accessor: A function that will get the key and name from
382 # group_order: list the group keys here in a list and
383 # GroupedInlineFormset.groups will be ordered (ordereddict) by
384 # the key sequence provided here. Any missing key from the
388 # # Build group list.
389 # self.groups = OrderedDict()
391 # # self.groups_and_forms = []
392 # for form in self.forms:
393 # group_key, group_name = group_accessor(form)
394 # if not temp_groups.has_key(group_key):
395 # temp_groups[group_key] = {
396 # 'name': group_name,
400 # temp_groups[group_key]['forms'].append(form)
402 # for order_key in group_order:
403 # if temp_groups.has_key(order_key):
404 # self.groups[order_key] = temp_groups.pop(order_key)
406 # for key in temp_groups:
407 # self.groups[key] = temp_groups[key]
411 # self.group_list = self.groups.values()
414 def remun_formset_factory(parent_model
,
416 form
=forms
.ModelForm
,
417 formset
=GroupedInlineFormset
,
426 formfield_callback
=None,
428 choice_overrides
=[]):
429 trs
= rh
.TypeRemuneration
.objects
.all()
430 # extra = max_num = trs.count()
431 fk
= _get_foreign_key(parent_model
, model
, fk_name
=fk_name
)
432 # enforce a max_num=1 when the foreign key to the parent model is unique.
437 'formfield_callback': formfield_callback
,
440 'can_delete': can_delete
,
441 'can_order': can_order
,
446 FormSet
= modelformset_factory(model
, **kwargs
)
448 FormSet
.read_only
= read_only
451 rtype
= form
.initial
['type']
452 if not isinstance(rtype
, rh
.TypeRemuneration
):
453 rtype
= rh
.TypeRemuneration
.objects
.get(id=rtype
)
454 return (rtype
.nature_remuneration
,
455 rtype
.nature_remuneration
460 # Monkey patch FormSet.
461 def __init__(inst
, *a
, **kw
):
462 super(inst
.__class__
, inst
).__init__(*a
, **kw
)
463 inst
.set_groups(groups
, grouper
, choice_overrides
)
465 FormSet
.__init__
= __init__
470 def remun_formset_factory_factory(read_only
=False):
472 Don't we love factory factories?
475 null_choice
= ('', '-' * 10)
476 extras
= 2 if not read_only
else 0
477 can_delete
= False if read_only
else True
478 form_class
= ReadOnlyRemunForm
if read_only
else FlexibleRemunForm
480 return remun_formset_factory(
485 can_delete
=can_delete
,
488 (u
'Traitement', u
'Traitement',),
489 (u
'Indemnité', u
'Indemnité',),
490 (u
'Charges', u
'Charges',),
491 (u
'Accessoire', u
'Accessoire',),
492 (u
'RAS', u
'Rémunération autre source',),
496 'type': [null_choice
] + list(
497 rh
.TypeRemuneration
.objects
.filter(
498 nature_remuneration
=u
'Traitement').values_list(
503 'type': [null_choice
] + list(
504 rh
.TypeRemuneration
.objects
.filter(
505 nature_remuneration
=u
'Indemnité').values_list(
510 'type': [null_choice
] + list(
511 rh
.TypeRemuneration
.objects
.filter(
512 nature_remuneration
=u
'Charges').values_list(
517 'type': [null_choice
] + list(
518 rh
.TypeRemuneration
.objects
.filter(
519 nature_remuneration
=u
'Accessoire').values_list(
524 'type': [null_choice
] + list(
525 rh
.TypeRemuneration
.objects
.filter(
526 nature_remuneration
=u
'RAS').values_list(
533 RemunForm
= remun_formset_factory_factory(read_only
=False)
534 ReadOnlyRemunFormSet
= remun_formset_factory_factory(read_only
=True)
537 class PosteForm(forms
.ModelForm
):
538 """ Formulaire des postes. """
540 # On ne propose que les services actifs
541 service
= forms
.ModelChoiceField(
542 queryset
=rh
.Service
.objects
.all(), required
=True
545 responsable
= AutoCompleteSelectField('responsables', required
=True)
546 #responsable = forms.ModelChoiceField(
547 # queryset=rh.Poste.objects.select_related(depth=1))
549 # La liste des choix est laissée vide. Voir __init__ pour la raison.
550 poste
= forms
.ChoiceField(label
="Nouveau poste ou évolution du poste",
551 choices
=(), required
=False)
553 valeur_point_min
= forms
.ModelChoiceField(
554 queryset
=rh
.ValeurPoint
.actuelles
.all(), required
=False
556 valeur_point_max
= forms
.ModelChoiceField(
557 queryset
=rh
.ValeurPoint
.actuelles
.all(), required
=False
562 fields
= ('type_intervention',
563 'poste', 'implantation', 'type_poste', 'service', 'nom',
564 'responsable', 'local', 'expatrie', 'mise_a_disposition',
565 'appel', 'date_debut', 'date_fin',
566 'regime_travail', 'regime_travail_nb_heure_semaine',
567 'classement_min', 'classement_max',
568 'valeur_point_min', 'valeur_point_max',
569 'devise_min', 'devise_max',
570 'salaire_min', 'salaire_max',
571 'indemn_expat_min', 'indemn_expat_max',
572 'indemn_fct_min', 'indemn_fct_max',
573 'charges_patronales_min', 'charges_patronales_max',
574 'autre_min', 'autre_max', 'devise_comparaison',
575 'comp_locale_min', 'comp_locale_max',
576 'comp_universite_min', 'comp_universite_max',
577 'comp_fonctionpub_min', 'comp_fonctionpub_max',
578 'comp_ong_min', 'comp_ong_max',
579 'comp_autre_min', 'comp_autre_max',
582 widgets
= dict(type_intervention
=forms
.RadioSelect(),
583 appel
=forms
.RadioSelect(),
584 nom
=forms
.TextInput(attrs
={'size': 60},),
585 date_debut
=admin_widgets
.AdminDateWidget(),
586 date_fin
=admin_widgets
.AdminDateWidget(),
587 justification
=forms
.Textarea(attrs
={'cols': 80},),
588 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
589 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
592 def __init__(self
, *args
, **kwargs
):
593 """ Mise à jour dynamique du contenu du menu des postes.
595 Si on ne met le menu à jour de cette façon, à chaque instantiation du
596 formulaire, son contenu est mis en cache par le système et il ne
597 reflète pas les changements apportés par les ajouts, modifications,
600 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
601 car le "id" de chaque choix est spécial (voir _poste_choices).
604 request
= kwargs
.pop('request')
605 super(PosteForm
, self
).__init__(*args
, **kwargs
)
606 self
.fields
['poste'].choices
= self
._poste_choices(request
)
608 self
.fields
['implantation'].choices
= \
609 _implantation_choices(self
, request
)
611 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
612 if self
.instance
and self
.instance
.id is None:
613 dossiers
= self
.instance
.get_dossiers()
614 if len(dossiers
) > 0:
615 self
.initial
['service'] = dossiers
[0].poste
.service
617 def _poste_choices(self
, request
):
618 """ Menu déroulant pour les postes.
619 Constitué des postes de RH
621 postes_rh
= rh
.Poste
.objects
.ma_region_ou_service(request
.user
).all()
622 postes_rh
= postes_rh
.select_related(depth
=1)
624 return [('', 'Nouveau poste')] + \
625 sorted([('rh-%s' % p
.id, label_poste_display(p
)) for p
in
631 Validation conditionnelles de certains champs.
633 cleaned_data
= self
.cleaned_data
635 if cleaned_data
.get("local") is False \
636 and cleaned_data
.get("expatrie") is False:
637 msg
= "Le poste doit au moins être ouvert localement " \
639 self
._errors
["local"] = self
.error_class([msg
])
640 self
._errors
["expatrie"] = ''
641 raise forms
.ValidationError(msg
)
646 class ChoosePosteForm(forms
.Form
):
650 # La liste des choix est laissée vide. Voir PosteForm.__init__.
651 postes_dae
= forms
.ChoiceField(choices
=(), required
=False)
652 postes_rh
= forms
.ChoiceField(choices
=(), required
=False)
654 def __init__(self
, request
=None, *args
, **kwargs
):
655 super(ChoosePosteForm
, self
).__init__(*args
, **kwargs
)
656 self
.fields
['postes_dae'].choices
= self
._poste_dae_choices(request
)
657 self
.fields
['postes_rh'].choices
= self
._poste_rh_choices(request
)
659 def _poste_dae_choices(self
, request
):
660 """ Menu déroulant pour les postes."""
661 postes_dae
= dae
.Poste
.objects
.ma_region_ou_service(request
.user
) \
662 .exclude(etat__in
=(POSTE_ETAT_FINALISE
, )) \
663 .annotate(num_dae
=Count('dae_dossiers')) \
665 .order_by('implantation', '-date_debut', )
667 return [('', '----------')] + \
668 [('dae-%s' % p
.id, label_poste_display(p
)) for p
in postes_dae
]
670 def _poste_rh_choices(self
, request
):
671 """ Menu déroulant pour les postes."""
672 postes_dae
= dae
.Poste
.objects
.exclude(etat__in
=(POSTE_ETAT_FINALISE
, ))
673 today
= datetime
.date
.today()
674 id_poste_dae_commences
= [p
.id_rh_id
for p
in postes_dae
if p
.id_rh
is not None]
675 postes_rh
= rh
.Poste
.objects
.ma_region_ou_service(request
.user
) \
676 .exclude(id__in
=id_poste_dae_commences
) \
677 .filter(Q(date_debut__lte
=today
) &
678 (Q(date_fin__gte
=today
) |
679 Q(date_fin__isnull
=True))
681 .order_by('implantation', '-date_debut', )
683 return [('', '----------')] + \
684 [('rh-%s' % p
.id, label_poste_display(p
)) for p
in postes_rh
]
687 cleaned_data
= super(ChoosePosteForm
, self
).clean()
688 postes_dae
= cleaned_data
.get("postes_dae")
689 postes_rh
= cleaned_data
.get("postes_rh")
690 if (postes_dae
is u
"" and postes_rh
is u
"") or \
691 (postes_dae
is not u
"" and postes_rh
is not u
""):
692 raise forms
.ValidationError("Choisissez un poste DAE ou un poste RH")
696 poste_dae_key
= self
.cleaned_data
.get("postes_dae")
697 if poste_dae_key
is not u
"":
698 return redirect(reverse('embauche', args
=(poste_dae_key
,)))
699 poste_rh_key
= self
.cleaned_data
.get("postes_rh")
700 if poste_rh_key
is not u
"":
701 return redirect("%s?creer_dossier_dae='M'" % reverse('poste', args
=(poste_rh_key
,)))
703 class EmployeForm(forms
.ModelForm
):
704 """ Formulaire des employés. """
707 fields
= ('employe', 'nom', 'prenom', 'genre')
709 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
710 employe
= forms
.ChoiceField(choices
=(), required
=False)
712 def __init__(self
, *args
, **kwargs
):
713 """ Mise à jour dynamique du contenu du menu des employés. """
714 request
= kwargs
.pop('request', None)
715 super(EmployeForm
, self
).__init__(*args
, **kwargs
)
716 self
.fields
['employe'].choices
= _employe_choices(self
, request
)
719 class DossierForm(forms
.ModelForm
):
720 """ Formulaire des dossiers. """
722 exclude
= ('etat', 'employe', 'poste', 'date_debut',)
724 widgets
= dict(statut_residence
=forms
.RadioSelect(),
725 contrat_date_debut
=admin_widgets
.AdminDateWidget(),
726 contrat_date_fin
=admin_widgets
.AdminDateWidget(),
732 class PosteWorkflowForm(WorkflowFormMixin
):
733 bouton_libelles
= POSTE_ETATS_BOUTONS
739 def __init__(self
, *args
, **kwargs
):
740 super(PosteWorkflowForm
, self
).__init__(*args
, **kwargs
)
741 self
.fields
['etat'].help_text
= WF_HELP_TEXT
744 class DossierWorkflowForm(WorkflowFormMixin
):
745 bouton_libelles
= POSTE_ETATS_BOUTONS
# meme workflow que poste...
751 def __init__(self
, *args
, **kwargs
):
752 super(DossierWorkflowForm
, self
).__init__(*args
, **kwargs
)
753 self
.fields
['etat'].help_text
= WF_HELP_TEXT
754 self
._etat_initial
= self
.instance
.etat
757 super(DossierWorkflowForm
, self
).save()
758 poste
= self
.instance
.poste
760 # créer le commentaire automatique pour le poste associé
761 commentaire
= WorkflowCommentaire()
762 commentaire
.content_object
= poste
763 texte
= u
"Validation automatique à travers le dossier [%s] de %s\n%s" %(
766 self
.data
.get('commentaire', ''),
768 commentaire
.texte
= texte
769 commentaire
.etat_initial
= self
.instance
._etat_courant
770 commentaire
.etat_final
= self
.instance
.etat
771 commentaire
.owner
= self
.request
.user
774 # force l'état du poste
775 poste
.etat
= self
.instance
.etat
779 class ContratForm(forms
.ModelForm
):
782 fields
= ('type_contrat', 'fichier', )
786 class DAENumeriseeForm(forms
.ModelForm
):
790 fields
= ('dae_numerisee',)
793 class DAEFinaliseesSearchForm(forms
.Form
):
795 label
='Recherche', required
=False,
796 widget
=forms
.TextInput(attrs
={'size': 40})
798 importees
= forms
.ChoiceField(
799 label
='Importation', required
=False, choices
=(
801 ('oui', 'DAE importées seulement'),
802 ('non', 'DAE non-importées seulement'),