1 # -*- encoding: utf-8 -*-
3 from django
.db
.models
import Q
4 from django
import forms
5 from django
.forms
.models
import inlineformset_factory
6 from django
.contrib
.admin
import widgets
as admin_widgets
7 from ajax_select
.fields
import AutoCompleteSelectField
8 from auf
.django
.workflow
.forms
import WorkflowFormMixin
9 from datamaster_modeles
import models
as ref
10 from dae
import models
as dae
11 from utils
import get_employe_from_user
, is_user_dans_service
12 from rh_v1
import models
as rh
13 from workflow
import grp_drh
15 def _implantation_choices(obj
, request
):
17 employe
= get_employe_from_user(request
.user
)
19 if is_user_dans_service(request
.user
):
20 q
= Q(**{ 'id' : employe
.implantation_id
})
23 q
= Q(**{ 'region' : employe
.implantation
.region
})
26 if grp_drh
in request
.user
.groups
.all():
28 return [('', '----------')] + [(i
.id, unicode(i
), )for i
in ref
.Implantation
.objects
.filter(q
)]
30 def _employe_choices(obj
, request
):
31 q
= Q(id_rh__isnull
=True) & Q(id_rh__isnull
=True)
34 employe
= get_employe_from_user(request
.user
)
36 if is_user_dans_service(request
.user
):
37 q_region_service
= Q(implantation1
=employe
.implantation
) |
Q(implantation2
=employe
.implantation
)
40 q_region_service
= Q(implantation1__region
=employe
.implantation
.region
) |
Q(implantation2__region
=employe
.implantation
.region
)
42 if grp_drh
in request
.user
.groups
.all():
43 q_region_service
= Q()
45 # Construction de la liste des employés en puisant dans DAE (pas d'info) et dans rh_v1
46 # Pour le filtrage par région/service, on est obligé d'aller regarder le dossier rh_v1
47 # car l'information dans le modèle rh_v1.Employe n'existe pas.
48 dae_
= dae
.Employe
.objects
.filter(id_rh__isnull
=True)
49 copies
= dae
.Employe
.objects
.filter(Q(id_rh__isnull
=False))
50 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
51 employes_ids
= list(set([d
.employe_id
for d
in rh
.Dossier
.objects
.filter(q_region_service
)]))
52 rhv1
= rh
.Employe
.objects
.filter(id__in
=employes_ids
).exclude(id__in
=id_copies
)
54 def option_label(employe
):
55 return "%s %s" % (employe
.nom
.upper(), employe
.prenom
.title())
57 return [('', 'Nouvel employé')] + \
58 sorted([('dae-%s' % p
.id, option_label(p
)) for p
in dae_ | copies
] +
59 [('rh-%s' % p
.id, option_label(p
)) for p
in rhv1
],
63 def label_poste_display(poste
):
64 """Formate un visuel pour un poste dans une liste déroulante"""
65 label
= u
"%s - %s [%s]" %(poste
.type_poste
, poste
.type_poste
.famille_emploi
.nom
, poste
.id)
68 class PostePieceForm(inlineformset_factory(dae
.Poste
, dae
.PostePiece
)):
71 class DossierPieceForm(inlineformset_factory(dae
.Dossier
, dae
.DossierPiece
)):
74 class FinancementForm(inlineformset_factory(dae
.Poste
, dae
.PosteFinancement
, extra
=1)):
77 class JustificationNouvelEmployeForm(inlineformset_factory(dae
.Dossier
,
78 dae
.JustificationNouvelEmploye
,
81 exclude
=('question',))):
83 Formulaire de justification d'un nouvel employé.
84 Le dossier a besoin d'être enregistré une première fois afin de prépopuler les questions.
86 def __init__(self
, *args
, **kwargs
):
87 instance
= kwargs
['instance']
89 q_ids
= [j
.question
.id for j
in instance
.justificationnouvelemploye_set
.filter(dossier
=instance
)]
90 for q
in dae
.JustificationQuestion
.objects
.filter(type="N"):
93 j
= dae
.JustificationNouvelEmploye()
97 super(self
.__class__
, self
).__init__(*args
, **kwargs
)
99 class JustificationAutreEmployeForm(inlineformset_factory(dae
.Dossier
,
100 dae
.JustificationAutreEmploye
,
103 exclude
=('question',))):
105 Formulaire de justification d'un nouvel employé.
106 Le dossier a besoin d'être enregistré une première fois afin de prépopuler les questions.
108 def __init__(self
, *args
, **kwargs
):
109 instance
= kwargs
['instance']
111 q_ids
= [j
.question
.id for j
in instance
.justificationautreemploye_set
.filter(dossier
=instance
)]
112 for q
in dae
.JustificationQuestion
.objects
.filter(type="R"):
115 j
= dae
.JustificationAutreEmploye()
119 super(self
.__class__
, self
).__init__(*args
, **kwargs
)
121 class PosteForm(forms
.ModelForm
):
122 """ Formulaire des postes. """
128 fields
= ('poste', 'implantation', 'type_poste', 'service', 'nom',
129 'responsable', 'local', 'expatrie', 'mise_a_disposition',
130 'appel', 'date_debut', 'date_fin', 'actif',
131 'regime_travail', 'regime_travail_nb_heure_semaine',
132 'classement_min', 'classement_max',
133 'valeur_point_min', 'valeur_point_max',
134 'devise_min', 'devise_max',
135 'salaire_min', 'salaire_max', 'indemn_min', 'indemn_max',
136 'autre_min', 'autre_max', 'devise_comparaison',
137 'comp_locale_min', 'comp_locale_max',
138 'comp_universite_min', 'comp_universite_max',
139 'comp_fonctionpub_min', 'comp_fonctionpub_max',
140 'comp_ong_min', 'comp_ong_max',
141 'comp_autre_min', 'comp_autre_max',
144 widgets
= dict(appel
=forms
.RadioSelect(),
145 nom
=forms
.TextInput(attrs
={'size': 60},),
146 date_debut
=admin_widgets
.AdminDateWidget(),
147 date_fin
=admin_widgets
.AdminDateWidget(),
148 justification
=forms
.Textarea(attrs
={'cols': 80},),
149 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
150 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
153 responsable
=AutoCompleteSelectField('responsables', required
=True)
154 #responsable = forms.ModelChoiceField(
155 # queryset=rh.Poste.objects.select_related(depth=1))
157 # La liste des choix est laissée vide. Voir __init__ pour la raison.
158 poste
= forms
.ChoiceField(label
="Nouveau poste ou évolution du poste",
159 choices
=(), required
=False)
161 valeur_point_min
= forms
.ModelChoiceField(queryset
=rh
.ValeurPoint
.actuelles
.all(), required
=False)
162 valeur_point_max
= forms
.ModelChoiceField(queryset
=rh
.ValeurPoint
.actuelles
.all(), required
=False)
164 def __init__(self
, *args
, **kwargs
):
165 """ Mise à jour dynamique du contenu du menu des postes.
167 Si on ne met le menu à jour de cette façon, à chaque instantiation du
168 formulaire, son contenu est mis en cache par le système et il ne
169 reflète pas les changements apportés par les ajouts, modifications,
172 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
173 car le "id" de chaque choix est spécial (voir _poste_choices).
176 request
= kwargs
.pop('request')
177 super(PosteForm
, self
).__init__(*args
, **kwargs
)
178 self
.fields
['poste'].choices
= self
._poste_choices(request
)
179 self
.fields
['implantation'].choices
= _implantation_choices(self
, request
)
181 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
182 if self
.instance
and self
.instance
.id is None:
183 dossiers
= self
.instance
.get_dossiers()
184 if len(dossiers
) > 0:
185 self
.initial
['service'] = dossiers
[0].service_id
186 self
.initial
['nom'] = "%s %s" % (self
.initial
['nom'], self
.instance
.get_complement_nom())
189 def _poste_choices(self
, request
):
190 """ Menu déroulant pour les postes.
192 Constitué des postes de dae et des postes de rh_v1 qui n'ont pas
193 d'équivalent dans dae.
196 dae_
= dae
.Poste
.objects
.ma_region_ou_service(request
.user
).filter(actif
=True, id_rh__isnull
=True)
197 copies
= dae
.Poste
.objects
.ma_region_ou_service(request
.user
).exclude(id_rh__isnull
=True)
198 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
199 rhv1
= rh
.Poste
.objects
.ma_region_ou_service(request
.user
).filter(actif
=True).exclude(id__in
=id_copies
)
200 # Optimisation de la requête
201 rhv1
= rhv1
.select_related(depth
=1)
203 return [('', 'Nouveau poste')] + \
204 sorted([('dae-%s' % p
.id, label_poste_display(p
)) for p
in dae_ | copies
] +
205 [('rh-%s' % p
.id, label_poste_display(p
)) for p
in rhv1
],
210 Validation conditionnelles de certains champs.
212 cleaned_data
= self
.cleaned_data
214 # Gestion de la mise à disposition
215 mise_a_disposition
= cleaned_data
.get("mise_a_disposition")
216 valeur_point_min
= cleaned_data
.get("valeur_point_min")
217 valeur_point_max
= cleaned_data
.get("valeur_point_max")
218 if mise_a_disposition
is False and (valeur_point_min
is None or valeur_point_max
is None):
219 msg
= u
"Ce champ est obligatoire."
220 self
._errors
["valeur_point_min"] = self
.error_class([msg
])
221 self
._errors
["valeur_point_max"] = self
.error_class([msg
])
222 raise forms
.ValidationError("Les valeurs de point sont vides")
228 def save(self
, *args
, **kwargs
):
229 kwargs2
= kwargs
.copy()
230 kwargs2
['commit'] = False
231 poste
= super(PosteForm
, self
).save(*args
, **kwargs2
)
233 if 'commit' not in kwargs
or kwargs
['commit']:
238 class ChoosePosteForm(forms
.ModelForm
):
243 # La liste des choix est laissée vide. Voir PosteForm.__init__.
244 poste
= forms
.ChoiceField(choices
=(), required
=False)
246 def __init__(self
, request
=None, *args
, **kwargs
):
247 super(ChoosePosteForm
, self
).__init__(*args
, **kwargs
)
248 self
.fields
['poste'].choices
= self
._poste_choices(request
)
250 def _poste_choices(self
, request
):
251 """ Menu déroulant pour les postes. """
252 dae_
= dae
.Poste
.objects
.ma_region_ou_service(request
.user
).filter(id_rh__isnull
=True)
253 copies
= dae
.Poste
.objects
.ma_region_ou_service(request
.user
).exclude(id_rh__isnull
=True)
254 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
256 return [('', '----------')] + \
257 sorted([('dae-%s' % p
.id, unicode(p
)) for p
in dae_ | copies
],
261 class EmployeForm(forms
.ModelForm
):
262 """ Formulaire des employés. """
265 fields
= ('employe', 'nom', 'prenom', 'genre')
267 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
268 employe
= forms
.ChoiceField(choices
=(), required
=False)
270 def __init__(self
, *args
, **kwargs
):
271 """ Mise à jour dynamique du contenu du menu des employés. """
272 request
= kwargs
.pop('request', None)
273 super(EmployeForm
, self
).__init__(*args
, **kwargs
)
274 self
.fields
['employe'].choices
= _employe_choices(self
, request
)
278 class DossierForm(forms
.ModelForm
):
279 """ Formulaire des dossiers. """
283 widgets
= dict(statut_residence
=forms
.RadioSelect(),
284 contrat_date_debut
=admin_widgets
.AdminDateWidget(),
285 contrat_date_fin
=admin_widgets
.AdminDateWidget(),
288 class PosteWorkflowForm(WorkflowFormMixin
):
294 class DossierWorkflowForm(WorkflowFormMixin
):