poste etat decorateur
[auf_rh_dae.git] / project / dae / forms.py
CommitLineData
5d680e84 1# -*- encoding: utf-8 -*-
ce110fb9 2
f258e4e7 3from django.db.models import Q
5d680e84 4from django import forms
36341125 5from django.forms.models import inlineformset_factory
e88caaf0 6from django.contrib.admin import widgets as admin_widgets
afc204bf 7from ajax_select.fields import AutoCompleteSelectField
8fa94e8b 8from auf.django.workflow.forms import WorkflowFormMixin
5d680e84 9from datamaster_modeles import models as ref
5d680e84 10from dae import models as dae
f258e4e7 11from utils import get_employe_from_user, is_user_dans_service
5d680e84 12from rh_v1 import models as rh
f258e4e7
OL
13from workflow import grp_drh
14
15def _implantation_choices(obj, request):
16 # TRAITEMENT NORMAL
17 employe = get_employe_from_user(request.user)
18 # SERVICE
19 if is_user_dans_service(request.user):
20 q = Q(**{ 'id' : employe.implantation_id })
21 # REGION
22 else:
23 q = Q(**{ 'region' : employe.implantation.region })
24
25 # TRAITEMENT DRH
26 if grp_drh in request.user.groups.all():
27 q = Q()
28 return [('', '----------')] + [(i.id, unicode(i), )for i in ref.Implantation.objects.filter(q)]
29
30def _employe_choices(obj, request):
31 q = Q(id_rh__isnull=True) & Q(id_rh__isnull=True)
32
33 # TRAITEMENT NORMAL
34 employe = get_employe_from_user(request.user)
35 # SERVICE
36 if is_user_dans_service(request.user):
37 q_region_service = Q(implantation1=employe.implantation) | Q(implantation2=employe.implantation)
38 # REGION
39 else:
40 q_region_service = Q(implantation1__region=employe.implantation.region) | Q(implantation2__region=employe.implantation.region)
41 # TRAITEMENT DRH
42 if grp_drh in request.user.groups.all():
43 q_region_service = Q()
44
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)
53
54 def option_label(employe):
55 return "%s %s" % (employe.nom.upper(), employe.prenom.title())
56
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],
60 key=lambda t: t[1])
61
5d680e84 62
4bce4d24
OL
63def 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)
66 return label
9cb4de55
OL
67
68class PostePieceForm(inlineformset_factory(dae.Poste, dae.PostePiece)):
69 pass
70
71class DossierPieceForm(inlineformset_factory(dae.Dossier, dae.DossierPiece)):
72 pass
73
151e7bd0
OL
74class FinancementForm(inlineformset_factory(dae.Poste, dae.PosteFinancement, extra=1)):
75 pass
76
03b395db
OL
77
78class DossierComparaisonForm(forms.ModelForm):
79
80 recherche = AutoCompleteSelectField('dossiers', required=False)
81 poste = forms.CharField(max_length=255, widget=forms.TextInput(attrs={'size':'60'}))
82
83 class Model:
84 model = dae.DossierComparaison
85
86
87class DossierComparaisonForm(inlineformset_factory(dae.Dossier, dae.DossierComparaison, extra=3, max_num=3, form=DossierComparaisonForm)):
88 pass
89
72db8238
OL
90class JustificationNouvelEmployeForm(inlineformset_factory(dae.Dossier,
91 dae.JustificationNouvelEmploye,
92 extra=0,
93 can_delete=False,
94 exclude=('question',))):
95 """
96 Formulaire de justification d'un nouvel employé.
97 Le dossier a besoin d'être enregistré une première fois afin de prépopuler les questions.
98 """
99 def __init__(self, *args, **kwargs):
100 instance = kwargs['instance']
101 if instance.id:
1cc5e025 102 q_ids = [j.question.id for j in instance.justificationnouvelemploye_set.filter(dossier=instance)]
72db8238
OL
103 for q in dae.JustificationQuestion.objects.filter(type="N"):
104 if q.id in q_ids:
105 continue
106 j = dae.JustificationNouvelEmploye()
107 j.dossier = instance
108 j.question = q
109 j.save()
110 super(self.__class__, self).__init__(*args, **kwargs)
111
112class JustificationAutreEmployeForm(inlineformset_factory(dae.Dossier,
113 dae.JustificationAutreEmploye,
114 extra=0,
115 can_delete=False,
116 exclude=('question',))):
117 """
118 Formulaire de justification d'un nouvel employé.
119 Le dossier a besoin d'être enregistré une première fois afin de prépopuler les questions.
120 """
121 def __init__(self, *args, **kwargs):
122 instance = kwargs['instance']
123 if instance.id:
1cc5e025 124 q_ids = [j.question.id for j in instance.justificationautreemploye_set.filter(dossier=instance)]
72db8238
OL
125 for q in dae.JustificationQuestion.objects.filter(type="R"):
126 if q.id in q_ids:
127 continue
128 j = dae.JustificationAutreEmploye()
129 j.dossier = instance
130 j.question = q
131 j.save()
132 super(self.__class__, self).__init__(*args, **kwargs)
5d680e84 133
1b217058 134class PosteForm(forms.ModelForm):
5d680e84 135 """ Formulaire des postes. """
3121c13c
OL
136
137
5d680e84
NC
138 class Meta:
139 model = dae.Poste
ce110fb9 140
5d680e84 141 fields = ('poste', 'implantation', 'type_poste', 'service', 'nom',
154677c3 142 'responsable', 'local', 'expatrie', 'mise_a_disposition',
5d680e84
NC
143 'appel', 'date_debut', 'date_fin', 'actif',
144 'regime_travail', 'regime_travail_nb_heure_semaine',
145 'classement_min', 'classement_max',
146 'valeur_point_min', 'valeur_point_max',
3d627bfd 147 'devise_min', 'devise_max',
5d680e84
NC
148 'salaire_min', 'salaire_max', 'indemn_min', 'indemn_max',
149 'autre_min', 'autre_max', 'devise_comparaison',
150 'comp_locale_min', 'comp_locale_max',
151 'comp_universite_min', 'comp_universite_max',
152 'comp_fonctionpub_min', 'comp_fonctionpub_max',
153 'comp_ong_min', 'comp_ong_max',
8fa94e8b 154 'comp_autre_min', 'comp_autre_max',
2e092e0c 155 'justification',
8fa94e8b 156 )
154677c3 157 widgets = dict(appel=forms.RadioSelect(),
3d627bfd 158 nom=forms.TextInput(attrs={'size': 60},),
e88caaf0
OL
159 date_debut=admin_widgets.AdminDateWidget(),
160 date_fin=admin_widgets.AdminDateWidget(),
2e092e0c 161 justification=forms.Textarea(attrs={'cols': 80},),
3d627bfd 162 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
163 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
164 )
5d680e84 165
3121c13c
OL
166 responsable=AutoCompleteSelectField('responsables', required=True)
167 #responsable = forms.ModelChoiceField(
168 # queryset=rh.Poste.objects.select_related(depth=1))
139686f2 169
5d680e84 170 # La liste des choix est laissée vide. Voir __init__ pour la raison.
5efcd48e 171 poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste",
d949462d 172 choices=(), required=False)
5d680e84 173
4dd75e7b
OL
174 valeur_point_min = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
175 valeur_point_max = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
6301bd59 176
c2458db6 177 def __init__(self, *args, **kwargs):
5d680e84
NC
178 """ Mise à jour dynamique du contenu du menu des postes.
179
180 Si on ne met le menu à jour de cette façon, à chaque instantiation du
181 formulaire, son contenu est mis en cache par le système et il ne
182 reflète pas les changements apportés par les ajouts, modifications,
183 etc...
184
139686f2
NC
185 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
186 car le "id" de chaque choix est spécial (voir _poste_choices).
187
5d680e84 188 """
c2458db6 189 request = kwargs.pop('request')
5d680e84 190 super(PosteForm, self).__init__(*args, **kwargs)
f258e4e7
OL
191 self.fields['poste'].choices = self._poste_choices(request)
192 self.fields['implantation'].choices = _implantation_choices(self, request)
5d680e84 193
cc3098d0
OL
194 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
195 if self.instance and self.instance.id is None:
196 dossiers = self.instance.get_dossiers()
197 if len(dossiers) > 0:
198 self.initial['service'] = dossiers[0].service_id
9508a5b8
OL
199 self.initial['nom'] = "%s %s" % (self.initial['nom'], self.instance.get_complement_nom())
200
cc3098d0 201
f258e4e7 202 def _poste_choices(self, request):
5d680e84
NC
203 """ Menu déroulant pour les postes.
204
205 Constitué des postes de dae et des postes de rh_v1 qui n'ont pas
206 d'équivalent dans dae.
207
208 """
f258e4e7
OL
209 dae_ = dae.Poste.objects.ma_region_ou_service(request.user).filter(actif=True, id_rh__isnull=True)
210 copies = dae.Poste.objects.ma_region_ou_service(request.user).exclude(id_rh__isnull=True)
5d680e84 211 id_copies = [p.id_rh_id for p in copies.all()]
f258e4e7 212 rhv1 = rh.Poste.objects.ma_region_ou_service(request.user).filter(actif=True).exclude(id__in=id_copies)
139686f2
NC
213 # Optimisation de la requête
214 rhv1 = rhv1.select_related(depth=1)
5d680e84 215
98d51b59 216 return [('', 'Nouveau poste')] + \
4bce4d24
OL
217 sorted([('dae-%s' % p.id, label_poste_display(p)) for p in dae_ | copies] +
218 [('rh-%s' % p.id, label_poste_display(p)) for p in rhv1],
5d680e84 219 key=lambda t: t[1])
3ed49093 220
4dd75e7b
OL
221 def clean(self):
222 """
223 Validation conditionnelles de certains champs.
224 """
225 cleaned_data = self.cleaned_data
226
227 # Gestion de la mise à disposition
228 mise_a_disposition = cleaned_data.get("mise_a_disposition")
229 valeur_point_min = cleaned_data.get("valeur_point_min")
230 valeur_point_max = cleaned_data.get("valeur_point_max")
231 if mise_a_disposition is False and (valeur_point_min is None or valeur_point_max is None):
232 msg = u"Ce champ est obligatoire."
233 self._errors["valeur_point_min"] = self.error_class([msg])
234 self._errors["valeur_point_max"] = self.error_class([msg])
235 raise forms.ValidationError("Les valeurs de point sont vides")
236
237 return cleaned_data
238
239
240
494ff2be
NC
241 def save(self, *args, **kwargs):
242 kwargs2 = kwargs.copy()
243 kwargs2['commit'] = False
244 poste = super(PosteForm, self).save(*args, **kwargs2)
245 # id_rh
246 if 'commit' not in kwargs or kwargs['commit']:
247 poste.save()
248 return poste
249
3ed49093 250
139686f2
NC
251class ChoosePosteForm(forms.ModelForm):
252 class Meta:
253 model = dae.Poste
254 fields = ('poste',)
255
256 # La liste des choix est laissée vide. Voir PosteForm.__init__.
257 poste = forms.ChoiceField(choices=(), required=False)
258
4ee6d70a 259 def __init__(self, request=None, *args, **kwargs):
139686f2 260 super(ChoosePosteForm, self).__init__(*args, **kwargs)
4ee6d70a 261 self.fields['poste'].choices = self._poste_choices(request)
139686f2 262
4ee6d70a 263 def _poste_choices(self, request):
139686f2 264 """ Menu déroulant pour les postes. """
4ee6d70a
OL
265 dae_ = dae.Poste.objects.ma_region_ou_service(request.user).filter(id_rh__isnull=True)
266 copies = dae.Poste.objects.ma_region_ou_service(request.user).exclude(id_rh__isnull=True)
139686f2
NC
267 id_copies = [p.id_rh_id for p in copies.all()]
268
98d51b59 269 return [('', '----------')] + \
139686f2
NC
270 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies],
271 key=lambda t: t[1])
272
273
139686f2
NC
274class EmployeForm(forms.ModelForm):
275 """ Formulaire des employés. """
276 class Meta:
277 model = dae.Employe
278 fields = ('employe', 'nom', 'prenom', 'genre')
279
280 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
281 employe = forms.ChoiceField(choices=(), required=False)
282
ac6235f6 283 def __init__(self, *args, **kwargs):
139686f2 284 """ Mise à jour dynamique du contenu du menu des employés. """
ac6235f6 285 request = kwargs.pop('request', None)
139686f2 286 super(EmployeForm, self).__init__(*args, **kwargs)
f258e4e7 287 self.fields['employe'].choices = _employe_choices(self, request)
139686f2 288
139686f2
NC
289
290
291class DossierForm(forms.ModelForm):
292 """ Formulaire des dossiers. """
293 class Meta:
b1baa306 294 exclude= ('etat', )
139686f2 295 model = dae.Dossier
4d25e2ba 296 widgets = dict(statut_residence=forms.RadioSelect(),
0e0aeb7e
OL
297 contrat_date_debut=admin_widgets.AdminDateWidget(),
298 contrat_date_fin=admin_widgets.AdminDateWidget(),
4d25e2ba 299 )
e6f52402
OL
300
301class PosteWorkflowForm(WorkflowFormMixin):
302
303 class Meta:
304 fields = ('etat', )
305 model = dae.Poste
306
307class DossierWorkflowForm(WorkflowFormMixin):
308
309 class Meta:
310 fields = ('etat', )
311 model = dae.Dossier