fix #1553
[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
56589624 13from workflow import grp_drh, POSTE_ETATS_BOUTONS
f258e4e7
OL
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
e2185d45 74class FinancementForm(inlineformset_factory(dae.Poste, dae.PosteFinancement, extra=2)):
151e7bd0
OL
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
03b395db
OL
86class DossierComparaisonForm(inlineformset_factory(dae.Dossier, dae.DossierComparaison, extra=3, max_num=3, form=DossierComparaisonForm)):
87 pass
88
0a085c42
OL
89class FlexibleRemunForm(forms.ModelForm):
90
91 montant_mensuel = forms.DecimalField(required=False)
92 montant = forms.DecimalField(required=True, label='Montant annuel')
93
94 class Meta:
95 model = dae.Remuneration
96
97class RemunForm(inlineformset_factory(dae.Dossier, dae.Remuneration, extra=5, form=FlexibleRemunForm)):
98 pass
99
1b217058 100class PosteForm(forms.ModelForm):
5d680e84 101 """ Formulaire des postes. """
12c7f8a7
OL
102
103 responsable=AutoCompleteSelectField('responsables', required=True)
104 #responsable = forms.ModelChoiceField(
105 # queryset=rh.Poste.objects.select_related(depth=1))
106
107 # La liste des choix est laissée vide. Voir __init__ pour la raison.
108 poste = forms.ChoiceField(label="Nouveau poste ou évolution du poste",
109 choices=(), required=False)
110
111 valeur_point_min = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
112 valeur_point_max = forms.ModelChoiceField(queryset=rh.ValeurPoint.actuelles.all(), required=False)
3121c13c
OL
113
114
5d680e84
NC
115 class Meta:
116 model = dae.Poste
b15bf543 117 exclude = ('actif', )
c3be904d
OL
118 fields = ('type_intervention',
119 'poste', 'implantation', 'type_poste', 'service', 'nom',
154677c3 120 'responsable', 'local', 'expatrie', 'mise_a_disposition',
b15bf543 121 'appel', 'date_debut', 'date_fin',
5d680e84
NC
122 'regime_travail', 'regime_travail_nb_heure_semaine',
123 'classement_min', 'classement_max',
124 'valeur_point_min', 'valeur_point_max',
3d627bfd 125 'devise_min', 'devise_max',
5f61bccb
OL
126 'salaire_min', 'salaire_max',
127 'indemn_expat_min', 'indemn_expat_max',
128 'indemn_fct_min', 'indemn_fct_max',
129 'charges_patronales_min', 'charges_patronales_max',
5d680e84
NC
130 'autre_min', 'autre_max', 'devise_comparaison',
131 'comp_locale_min', 'comp_locale_max',
132 'comp_universite_min', 'comp_universite_max',
133 'comp_fonctionpub_min', 'comp_fonctionpub_max',
134 'comp_ong_min', 'comp_ong_max',
8fa94e8b 135 'comp_autre_min', 'comp_autre_max',
2e092e0c 136 'justification',
8fa94e8b 137 )
c3be904d
OL
138 widgets = dict(type_intervention=forms.RadioSelect(),
139 appel=forms.RadioSelect(),
3d627bfd 140 nom=forms.TextInput(attrs={'size': 60},),
e88caaf0
OL
141 date_debut=admin_widgets.AdminDateWidget(),
142 date_fin=admin_widgets.AdminDateWidget(),
2e092e0c 143 justification=forms.Textarea(attrs={'cols': 80},),
3d627bfd 144 #devise_min=forms.Select(attrs={'disabled':'disabled'}),
145 #devise_max=forms.Select(attrs={'disabled':'disabled'}),
146 )
5d680e84 147
c2458db6 148 def __init__(self, *args, **kwargs):
5d680e84
NC
149 """ Mise à jour dynamique du contenu du menu des postes.
150
151 Si on ne met le menu à jour de cette façon, à chaque instantiation du
152 formulaire, son contenu est mis en cache par le système et il ne
153 reflète pas les changements apportés par les ajouts, modifications,
154 etc...
155
139686f2
NC
156 Aussi, dans ce cas-ci, on ne peut pas utiliser un ModelChoiceField
157 car le "id" de chaque choix est spécial (voir _poste_choices).
158
5d680e84 159 """
c2458db6 160 request = kwargs.pop('request')
5d680e84 161 super(PosteForm, self).__init__(*args, **kwargs)
f258e4e7
OL
162 self.fields['poste'].choices = self._poste_choices(request)
163 self.fields['implantation'].choices = _implantation_choices(self, request)
5d680e84 164
cc3098d0
OL
165 # Quand le dae.Poste n'existe pas, on recherche dans les dossiers rhv1
166 if self.instance and self.instance.id is None:
167 dossiers = self.instance.get_dossiers()
168 if len(dossiers) > 0:
169 self.initial['service'] = dossiers[0].service_id
9508a5b8
OL
170 self.initial['nom'] = "%s %s" % (self.initial['nom'], self.instance.get_complement_nom())
171
cc3098d0 172
f258e4e7 173 def _poste_choices(self, request):
5d680e84
NC
174 """ Menu déroulant pour les postes.
175
176 Constitué des postes de dae et des postes de rh_v1 qui n'ont pas
177 d'équivalent dans dae.
178
179 """
f258e4e7
OL
180 dae_ = dae.Poste.objects.ma_region_ou_service(request.user).filter(actif=True, id_rh__isnull=True)
181 copies = dae.Poste.objects.ma_region_ou_service(request.user).exclude(id_rh__isnull=True)
5d680e84 182 id_copies = [p.id_rh_id for p in copies.all()]
f258e4e7 183 rhv1 = rh.Poste.objects.ma_region_ou_service(request.user).filter(actif=True).exclude(id__in=id_copies)
139686f2
NC
184 # Optimisation de la requête
185 rhv1 = rhv1.select_related(depth=1)
5d680e84 186
98d51b59 187 return [('', 'Nouveau poste')] + \
4bce4d24
OL
188 sorted([('dae-%s' % p.id, label_poste_display(p)) for p in dae_ | copies] +
189 [('rh-%s' % p.id, label_poste_display(p)) for p in rhv1],
5d680e84 190 key=lambda t: t[1])
3ed49093 191
4dd75e7b
OL
192 def clean(self):
193 """
194 Validation conditionnelles de certains champs.
195 """
196 cleaned_data = self.cleaned_data
197
198 # Gestion de la mise à disposition
199 mise_a_disposition = cleaned_data.get("mise_a_disposition")
200 valeur_point_min = cleaned_data.get("valeur_point_min")
201 valeur_point_max = cleaned_data.get("valeur_point_max")
202 if mise_a_disposition is False and (valeur_point_min is None or valeur_point_max is None):
203 msg = u"Ce champ est obligatoire."
204 self._errors["valeur_point_min"] = self.error_class([msg])
205 self._errors["valeur_point_max"] = self.error_class([msg])
206 raise forms.ValidationError("Les valeurs de point sont vides")
f42c6e20 207
f42c6e20
OL
208 if cleaned_data.get("local") is False and cleaned_data.get("expatrie") is False:
209 msg = "Le poste doit au moins être ouvert localement ou aux expatriés"
210 self._errors["local"] = self.error_class([msg])
211 self._errors["expatrie"] = ''
212 raise forms.ValidationError(msg)
213
214
4dd75e7b
OL
215 return cleaned_data
216
217
218
494ff2be
NC
219 def save(self, *args, **kwargs):
220 kwargs2 = kwargs.copy()
221 kwargs2['commit'] = False
222 poste = super(PosteForm, self).save(*args, **kwargs2)
223 # id_rh
224 if 'commit' not in kwargs or kwargs['commit']:
225 poste.save()
226 return poste
227
3ed49093 228
139686f2
NC
229class ChoosePosteForm(forms.ModelForm):
230 class Meta:
231 model = dae.Poste
232 fields = ('poste',)
233
234 # La liste des choix est laissée vide. Voir PosteForm.__init__.
235 poste = forms.ChoiceField(choices=(), required=False)
236
4ee6d70a 237 def __init__(self, request=None, *args, **kwargs):
139686f2 238 super(ChoosePosteForm, self).__init__(*args, **kwargs)
4ee6d70a 239 self.fields['poste'].choices = self._poste_choices(request)
139686f2 240
4ee6d70a 241 def _poste_choices(self, request):
139686f2 242 """ Menu déroulant pour les postes. """
4ee6d70a
OL
243 dae_ = dae.Poste.objects.ma_region_ou_service(request.user).filter(id_rh__isnull=True)
244 copies = dae.Poste.objects.ma_region_ou_service(request.user).exclude(id_rh__isnull=True)
139686f2
NC
245 id_copies = [p.id_rh_id for p in copies.all()]
246
98d51b59 247 return [('', '----------')] + \
139686f2
NC
248 sorted([('dae-%s' % p.id, unicode(p)) for p in dae_ | copies],
249 key=lambda t: t[1])
250
251
139686f2
NC
252class EmployeForm(forms.ModelForm):
253 """ Formulaire des employés. """
254 class Meta:
255 model = dae.Employe
256 fields = ('employe', 'nom', 'prenom', 'genre')
257
258 # La liste des choix est laissée vide. Voir Poste.__init__ pour la raison.
259 employe = forms.ChoiceField(choices=(), required=False)
260
ac6235f6 261 def __init__(self, *args, **kwargs):
139686f2 262 """ Mise à jour dynamique du contenu du menu des employés. """
ac6235f6 263 request = kwargs.pop('request', None)
139686f2 264 super(EmployeForm, self).__init__(*args, **kwargs)
f258e4e7 265 self.fields['employe'].choices = _employe_choices(self, request)
139686f2 266
139686f2
NC
267
268
269class DossierForm(forms.ModelForm):
270 """ Formulaire des dossiers. """
271 class Meta:
b1baa306 272 exclude= ('etat', )
139686f2 273 model = dae.Dossier
4d25e2ba 274 widgets = dict(statut_residence=forms.RadioSelect(),
0e0aeb7e
OL
275 contrat_date_debut=admin_widgets.AdminDateWidget(),
276 contrat_date_fin=admin_widgets.AdminDateWidget(),
4d25e2ba 277 )
e6f52402 278
3799cafc 279WF_HELP_TEXT = ""
e0b93e3a 280
e6f52402 281class PosteWorkflowForm(WorkflowFormMixin):
56589624 282 bouton_libelles = POSTE_ETATS_BOUTONS
e6f52402
OL
283 class Meta:
284 fields = ('etat', )
285 model = dae.Poste
56589624 286
e0b93e3a
OL
287 def __init__(self, *args, **kwargs):
288 super(self.__class__, self).__init__(*args, **kwargs)
289 self.fields['etat'].help_text = WF_HELP_TEXT
290
291
e6f52402 292class DossierWorkflowForm(WorkflowFormMixin):
56589624 293 bouton_libelles = POSTE_ETATS_BOUTONS # meme workflow que poste...
e6f52402
OL
294 class Meta:
295 fields = ('etat', )
296 model = dae.Dossier
e0b93e3a
OL
297
298 def __init__(self, *args, **kwargs):
299 super(self.__class__, self).__init__(*args, **kwargs)
300 self.fields['etat'].help_text = WF_HELP_TEXT
301