1 # -*- encoding: utf-8 -*-
6 from collections
import defaultdict
7 from datetime
import date
8 from simplejson
import dumps
11 from django
.core
.urlresolvers
import reverse
12 from django
.http
import Http404
, HttpResponse
, HttpResponseGone
13 from django
.shortcuts
import redirect
, render_to_response
, get_object_or_404
14 from django
.template
import Context
, RequestContext
15 from django
.template
.loader
import get_template
16 from django
.contrib
import messages
17 from django
.conf
import settings
19 from reversion
.models
import Version
21 from project
.dae
import models
as dae
22 from project
.rh_v1
import models
as rh
24 from decorators
import dae_groupe_requis
, \
25 poste_dans_ma_region_ou_service
, \
26 dossier_dans_ma_region_ou_service
, \
27 vieux_dossier_dans_ma_region_ou_service
, \
28 employe_dans_ma_region_ou_service
, \
29 dossier_est_modifiable
, \
35 for d
in rh
.Devise
.objects
.all():
36 annee
= date
.today().year
37 taux
= rh
.TauxChange
.objects
.filter(annee
=annee
, devise
=d
)
42 data
['taux_euro'] = taux
[0].taux
43 data
['devise_code'] = d
.code
47 def reponse_pdf(template_src
, context_dict
):
49 Générer une réponse HTTP avec un PDF
51 import ho
.pisa
as pisa
54 for f
in ('css/pdf.css', 'css/dae.css'):
55 css_file
= os
.path
.join(settings
.MEDIA_ROOT
, f
)
56 css
+= open(css_file
, 'r').read()
57 context_dict
['css'] = css
59 template
= get_template(template_src
)
60 context
= Context(context_dict
)
61 html
= template
.render(context
)
62 result
= StringIO
.StringIO()
63 pdf
= pisa
.pisaDocument(html
, result
, encoding
='UTF-8')
65 return HttpResponse(result
.getvalue(), mimetype
='application/pdf')
66 return HttpResponse("impossible de générer le pdf! %s" % html
)
71 return render_to_response('dae/index.html', {}, RequestContext(request
))
74 @poste_dans_ma_region_ou_service
75 def poste_consulter(request
, key
):
76 source
, id = key
.split('-')
77 poste
= get_object_or_404(dae
.Poste
, pk
=id)
80 validationForm
= PosteWorkflowForm(request
.POST
, instance
=poste
, request
=request
)
81 if validationForm
.is_valid():
83 messages
.add_message(request
, messages
.SUCCESS
, "La validation a été enregistrée.")
84 return redirect('poste_consulter', key
=key
)
86 validationForm
= PosteWorkflowForm(instance
=poste
, request
=request
)
88 vars = {'poste' : poste
, 'validationForm' : validationForm
, }
91 mode
= request
.GET
.get('mode', None)
93 return render_to_response('dae/poste_consulter.html', vars, RequestContext(request
))
95 return reponse_pdf('dae/poste_pdf.html', vars)
97 return render_to_response('dae/poste_pdf.html', vars, RequestContext(request
))
101 @poste_dans_ma_region_ou_service
102 @poste_est_modifiable
103 def poste(request
, key
=None):
104 """ Formulaire pour un poste.
106 Permet de créer ou modifier un poste. Si le poste n'existe que dans rh_v1
107 il est automatiquement copié dans dae.
110 poste
, data
, vars = None, dict(), dict()
115 source
, id = key
.split('-')
118 poste
= get_object_or_404(dae
.Poste
, pk
=id)
120 p
= get_object_or_404(rh
.Poste
, pk
=id)
121 # Initialisation avec les valeurs du poste de rh_v1
122 poste
= dae
.Poste(id_rh
=p
, nom
=p
.type_poste
.nom
)
123 for field
in ('implantation', 'type_poste', 'actif'):
124 setattr(poste
, field
, getattr(p
, field
))
130 data
.update(dict(request
.POST
.items()))
131 form
= PosteForm(data
, instance
=poste
, request
=request
)
132 financementForm
= FinancementForm(request
.POST
, instance
=poste
)
133 piecesForm
= PostePieceForm(request
.POST
, request
.FILES
, instance
=poste
)
134 if form
.is_valid() and piecesForm
.is_valid() and financementForm
.is_valid():
136 piecesForm
.instance
= poste
138 financementForm
.instance
= poste
139 financementForm
.save()
140 messages
.add_message(request
, messages
.SUCCESS
, "Le poste %s a été sauvegardé." % poste
)
141 if request
.POST
.has_key('save'):
142 return redirect('poste_consulter', key
='dae-%s' % poste
.id)
144 return redirect('poste', key
='dae-%s' % poste
.id)
147 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
150 # 'initial' évite la validation prémature lors d'une copie de poste de
152 form
= PosteForm(initial
=data
, instance
=poste
, request
=request
)
153 piecesForm
= PostePieceForm(instance
=poste
)
154 financementForm
= FinancementForm(instance
=poste
)
156 vars.update(dict(form
=form
, poste
=poste
, poste_key
=key
, piecesForm
=piecesForm
, financementForm
=financementForm
))
158 return render_to_response('dae/poste.html', vars, RequestContext(request
))
161 def postes_liste(request
):
162 """ Liste des postes. """
164 vars['postes_a_traiter'] = dae
.Poste
.objects
.mes_choses_a_faire(request
.user
).filter(pourvu
=False).order_by('-date_creation')
165 vars['postes_vacants'] = dae
.Poste
.objects
.ma_region_ou_service(request
.user
).filter(pourvu
=False).order_by('-date_creation')
166 vars['postes_pourvus'] = dae
.Poste
.objects
.ma_region_ou_service(request
.user
).filter(pourvu
=True).order_by('-date_creation')
167 return render_to_response('dae/postes_liste.html', vars, RequestContext(request
))
169 def filtered_type_remun():
170 defaut
= (2, 3, 8, 17) # salaire de base, indemnité de fonction, charges patronales
171 return rh
.TypeRemuneration
.objects
.filter(pk__in
=defaut
)
174 @dossier_dans_ma_region_ou_service
175 def embauche_consulter(request
, dossier_id
):
176 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier_id
)
179 validationForm
= DossierWorkflowForm(request
.POST
, instance
=dossier
, request
=request
)
180 if validationForm
.is_valid():
181 validationForm
.save()
182 messages
.add_message(request
, messages
.SUCCESS
, "La validation a été enregistrée.")
183 return redirect('embauche_consulter', dossier_id
=dossier
.id)
185 validationForm
= DossierWorkflowForm(instance
=dossier
, request
=request
)
189 'validationForm' : validationForm
,
192 mode
= request
.GET
.get('mode', None)
194 return render_to_response('dae/embauche_consulter.html', vars, RequestContext(request
))
196 return reponse_pdf('dae/embauche_pdf.html', vars)
198 return render_to_response('dae/embauche_pdf.html', vars, RequestContext(request
))
201 @dossier_dans_ma_region_ou_service
202 @dossier_est_modifiable
203 def embauche(request
, key
=None, dossier_id
=None):
204 """ Formulaire d'autorisation d'embauche. """
206 vars = dict(step
='poste', form
=ChoosePosteForm(request
=request
))
208 type_remun
= filtered_type_remun()
209 vars = dict(type_remun
=type_remun
)
210 source
, id = key
.split('-')
213 poste
= get_object_or_404(dae
.Poste
, pk
=id)
218 if request
.POST
['employe'] == '':
220 employe
= dae
.Employe()
222 employe_source
, id = request
.POST
['employe'].split('-')
223 if employe_source
== 'dae':
225 employe
= get_object_or_404(dae
.Employe
, pk
=id)
226 elif employe_source
== 'rh':
227 # Employé RH, on le copie dans DAE
228 e
= get_object_or_404(rh
.Employe
, pk
=id)
229 employe
= dae
.Employe(id_rh
=e
, prenom
=e
.prenom
, nom
=e
.nom
,
234 employe_form
= EmployeForm(request
.POST
, instance
=employe
, request
=request
)
237 if employe_form
.is_valid():
238 data
= dict(request
.POST
.items())
239 #with warnings.catch_warnings():
240 # warnings.simplefilter('ignore')
241 employe
= employe_form
.save()
242 data
['employe'] = 'dae-%s' % employe
.id
243 employe_form
= EmployeForm(data
, instance
=employe
, request
=request
)
246 dossier
= dae
.Dossier(poste
=poste
, employe
=employe
)
248 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier_id
)
249 dossier_form
= DossierForm(request
.POST
, instance
=dossier
)
250 piecesForm
= DossierPieceForm(request
.POST
, request
.FILES
, instance
=dossier
)
251 justificationsNouveauForm
= JustificationNouvelEmployeForm(request
.POST
, instance
=dossier
)
252 justificationsAutreForm
= JustificationAutreEmployeForm(request
.POST
, instance
=dossier
)
253 dossiersComparaisonsForm
= DossierComparaisonForm(request
.POST
, instance
=dossier
)
254 remunForm
= RemunForm(request
.POST
, instance
=dossier
)
255 print remunForm
.errors
256 if dossier_form
.is_valid() and \
257 piecesForm
.is_valid() and \
258 justificationsNouveauForm
.is_valid() and \
259 justificationsAutreForm
.is_valid() and \
260 dossiersComparaisonsForm
.is_valid() and \
261 remunForm
.is_valid():
263 dossier
= dossier_form
.save()
264 piecesForm
.instance
= dossier
266 justificationsNouveauForm
.instance
= dossier
267 justificationsNouveauForm
.save()
268 justificationsAutreForm
.instance
= dossier
269 justificationsAutreForm
.save()
270 dossiersComparaisonsForm
.instance
= dossier
271 dossiersComparaisonsForm
.save()
272 remunForm
.instance
= dossier
275 #if not dossier.remuneration_set.all():
276 # # Pré-peuplement des entrées de la section "coût
277 # # global", à l'exclusion de "Indemnité de fonction"
278 # for type in type_remun.all():
279 # dae.Remuneration(dossier=dossier, type=type,
280 # devise=dossier.devise).save()
283 # # Sauvegarde du coût global
284 # cg_lines = defaultdict(dict)
285 # for k, v in request.POST.items():
286 # if k.startswith('cg-'):
287 # prefix, field_name, cg_id = k.split('-')
288 # cg_lines[int(cg_id)][unicode(field_name)] = v
290 # for r in dossier.remuneration_set.all():
291 # print 'trying %r' % r
292 # if r.id in cg_lines:
293 # if cg_lines[r.id]['montant'] == '':
296 # for k, v in cg_lines[r.id].items():
300 messages
.add_message(request
, messages
.SUCCESS
, "Le dossier %s a été sauvegardé." % dossier
)
301 if request
.POST
.has_key('save'):
302 return redirect('embauche_consulter', dossier_id
=dossier
.id)
304 return redirect('embauche', key
=dossier
.poste
.key
, dossier_id
=dossier
.id)
307 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
310 dossier_form
= DossierForm(instance
=dossier
)
311 piecesForm
= DossierPieceForm(instance
=dossier
)
312 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
313 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
314 dossiersComparaisonsForm
= DossierComparaisonForm(instance
=dossier
)
315 remunForm
= RemunForm(instance
=dossier
)
317 # Initialisation d'un formulaire vide
318 dossier_rh
= rh
.Dossier()
319 poste_rh
= poste
.id_rh
321 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier_id
)
322 employe
= dossier
.employe
323 data
= dict(employe
='dae-%s' % employe
.id)
324 employe_form
= EmployeForm(initial
=data
, instance
=employe
, request
=request
)
326 dossier
= pre_filled_dossier(dossier_rh
, 'new', poste_rh
)
327 employe_form
= EmployeForm(request
=request
)
329 dossier_form
= DossierForm(instance
=dossier
)
330 piecesForm
= DossierPieceForm(instance
=dossier
)
331 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
332 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
333 dossiersComparaisonsForm
= DossierComparaisonForm(instance
=dossier
)
334 remunForm
= RemunForm(instance
=dossier
)
336 vars = dict(step
='employe',
337 type_remun
=type_remun
,
341 piecesForm
=piecesForm
,
343 justificationsNouveauForm
=justificationsNouveauForm
,
344 justificationsAutreForm
=justificationsAutreForm
,
345 dossiersComparaisonsForm
=dossiersComparaisonsForm
,
346 forms
=dict(employe
=employe_form
, dossier
=dossier_form
, )
350 return render_to_response('dae/embauche.html', vars,
351 RequestContext(request
))
353 @dossier_dans_ma_region_ou_service
354 def embauches_liste(request
):
355 """ Liste des embauches. """
357 vars['embauches'] = dae
.Dossier
.objects
.ma_region_ou_service(request
.user
).order_by('-date_creation')
358 return render_to_response('dae/embauches_liste.html', vars, RequestContext(request
))
360 def employe(request
, key
):
361 """ Récupération AJAX de l'employé pour la page d'embauche. """
362 data
= dict(employe
=key
)
366 employe
= dae
.Employe()
369 source
, id = key
.split('-')
372 employe
= get_object_or_404(dae
.Employe
, pk
=id)
374 e
= get_object_or_404(rh
.Employe
, id=id)
375 # Initialisation avec les valeurs de l'employé de rh_v1
376 employe
= dae
.Employe(id_rh
=e
)
377 for field
in ('prenom', 'nom', 'genre'):
378 setattr(employe
, field
, getattr(e
, field
))
380 return HttpResponse(EmployeForm(initial
=data
, instance
=employe
, request
=request
).as_table())
382 ################################################################################
384 ################################################################################
386 @employe_dans_ma_region_ou_service
387 def dossier(request
, poste_key
, employe_key
):
388 """ Récupération AJAX du dossier pour la page d'embauche. """
391 poste_source
, poste_id
= poste_key
.split('-')
392 poste
= get_object_or_404(dae
.Poste
, pk
=poste_id
)
394 # Récupérer la devise de l'implantation lié au poste
395 implantation_devise
= poste
.get_default_devise()
396 data
.update({'devise' : implantation_devise
.id})
398 if poste
.id_rh_id
is not None:
399 poste_rh
= get_object_or_404(rh
.Poste
, pk
=poste
.id_rh_id
)
403 ##########################################################################################
405 ##########################################################################################
406 if employe_key
== '':
407 employe_source
= 'new'
409 dossier_rh
= rh
.Dossier()
410 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
412 ##########################################################################################
414 ##########################################################################################
415 if employe_key
.startswith('dae'):
416 employe_source
, employe_id
= employe_key
.split('-')
417 employe_dae
= get_object_or_404(dae
.Employe
, pk
=employe_id
)
419 # récupération de l'ancien dossier rh v1 pour l'employe DAE
421 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_dae
.id_rh_id
, mandat_date_fin
=None)
422 except (rh
.Dossier
.DoesNotExist
):
423 dossier_rh
= rh
.Dossier()
425 # on tente de récupérer le dossier DAE, au pire on le contruit en le
426 # prépoluant avec son dossier rh v1.
428 dossier
= dae
.Dossier
.objects
.get(employe
=employe_dae
, poste
=poste
)
429 except (dae
.Dossier
.DoesNotExist
):
430 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
431 employe
= employe_dae
.id_rh
432 ##########################################################################################
434 ##########################################################################################
435 if employe_key
.startswith('rh'):
436 employe_source
, employe_id
= employe_key
.split('-')
437 employe_rh
= get_object_or_404(rh
.Employe
, pk
=employe_id
)
439 # récupération de l'ancien dossier rh v1 pour l'employe rh v1, s'il n'en a pas,
440 # on en fournit un nouveau qui servira uniquement un créer un nouveau dossier DAE.
442 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_rh
, mandat_date_fin
=None)
443 except (rh
.Dossier
.DoesNotExist
):
444 dossier_rh
= rh
.Dossier()
445 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
448 dossier_form
= DossierForm(initial
=data
, instance
=dossier
)
449 vars = dict(form
=dossier_form
, poste
=poste
, employe
=employe
)
450 return render_to_response('dae/embauche-dossier.html', vars,
451 RequestContext(request
))
453 # @Cette fonction est appelée à partir de fonctions déjà sécurisée
454 def pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
):
455 dossier
= dae
.Dossier()
457 if employe_source
!= 'new' and dossier_rh
.id:
458 dossier
.statut_anterieur
= dossier_rh
.statut
460 # Certains dossiers ont un classement à zéro
461 if dossier_rh
.classement_id
> 0:
462 dossier
.classement_anterieur
= dossier_rh
.classement
464 # Récupération du salaire de base
465 remun
= dossier_rh
.remuneration_set
.filter(type=1)
467 dossier
.salaire_anterieur
= remun
[0].montant
469 # Récupération du titulaire précédent
471 dossiers
= rh
.Dossier
.objects
.order_by('-mandat_date_fin')
472 dossiers
= dossiers
.filter(poste1
=poste_rh
) | dossiers
.filter(poste2
=poste_rh
)
474 # Ce bloc ignore toutes les erreurs, car les données de rh
475 # manquantes peuvent en générer
478 titulaire
= d
.employe
479 dossier
.employe_anterieur
= titulaire
480 dossier
.classement_titulaire_anterieur
= d
.classement
481 dossier
.statut_titulaire_anterieur
= d
.statut
482 dossier
.salaire_titulaire_anterieur
= \
483 d
.remuneration_set
.all()[0].montant
486 # TODO: afficher l'info, les champs ne sont pas dans le
487 # modèle dae.Dossier: nom, prenom, classement, salaire
490 except (rh
.Dossier
.DoesNotExist
):
491 dossier_rh
= rh
.Dossier()
496 @vieux_dossier_dans_ma_region_ou_service
497 def dossier_resume(request
, dossier_id
=None):
500 output : devise, devise_code, taux_euro
503 dossier
= rh
.Dossier
.objects
.get(id=dossier_id
)
505 return HttpResponseGone("Ce dossier n'est pas accessible")
508 data
['personne'] = unicode(dossier
.employe
)
509 data
['implantation'] = dossier
.implantation1
.id
510 data
['poste'] = u
"%s %s" % (dossier
.poste1
.type_poste
.nom
, dossier
.complement1
)
511 data
['montant'] = dossier
.get_salaire()
512 salaire
= dossier
.get_dernier_salaire_remun()
513 if salaire
is not None:
514 data
['devise'] = salaire
.devise
.id
515 data
['montant_euros'] = salaire
.en_euros()
517 data
['devise'] = None
518 data
['montant_euros'] = 0
519 return HttpResponse(dumps(data
))
521 def liste_postes(request
):
523 input : implantation_id
524 output : JSON liste de valeur point
526 method
= request
.method
527 params
= getattr(request
, method
, [])
530 # Voir le code de _poste_choices dans forms.py
531 dae_
= dae
.Poste
.objects
.filter(actif
=True, id_rh__isnull
=True)
532 copies
= dae
.Poste
.objects
.exclude(id_rh__isnull
=True)
533 rh_postes_actifs
= rh
.Poste
.objects
.filter(actif
=True)
535 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
536 implantation_id
= params
.get('implantation_id')
537 dae_
= dae_
.filter(implantation__id
=implantation_id
)
538 copies
= copies
.filter(implantation__id
=implantation_id
)
539 rh_postes_actifs
= rh_postes_actifs
.filter(implantation__id
=implantation_id
)
541 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
542 rhv1
= rh_postes_actifs
.exclude(id__in
=id_copies
)
543 rhv1
= rhv1
.select_related(depth
=1)
545 data
= [('', 'Nouveau poste')] + sorted([('dae-%s' % p
.id, label_poste_display(p
)) for p
in dae_ | copies
] + [('rh-%s' % p
.id, label_poste_display(p
)) for p
in rhv1
], key
=lambda t
: t
[1])
546 return HttpResponse(dumps(data
))
549 ################################################################################
550 # AJAX SECURITE non nécessaire
551 ################################################################################
552 def coefficient(request
):
557 method
= request
.method
558 params
= getattr(request
, method
, [])
560 if 'classement' in params
and params
.get('classement') is not u
"":
561 classement
= params
.get('classement')
562 classement
= rh
.Classement
.objects
.get(pk
=classement
)
563 data
['coefficient'] = classement
.coefficient
565 data
['coefficient'] = 0
566 return HttpResponse(dumps(data
))
572 output : devise, devise_code, taux_euro
574 method
= request
.method
575 params
= getattr(request
, method
, [])
577 if 'valeur_point' in params
and params
.get('valeur_point') is not u
"":
578 valeur_point
= params
.get('valeur_point')
579 valeur_point
= rh
.ValeurPoint
.objects
.get(pk
=valeur_point
)
580 annee
= valeur_point
.annee
581 implantation
= valeur_point
.implantation
582 taux
= rh
.TauxChange
.objects
.get(annee
=annee
,
583 implantation
=implantation
)
584 data
['devise'] = taux
.devise
.id
585 data
['valeur'] = valeur_point
.valeur
586 data
['devise_code'] = taux
.devise
.code
587 data
['taux_euro'] = taux
.taux
589 return HttpResponseGone("Vous devez choisir une valeur de point")
590 return HttpResponse(dumps(data
))
592 def devise_code(request
):
595 output : devise_code, taux_euro
597 method
= request
.method
598 params
= getattr(request
, method
, [])
600 if 'devise' in params
:
601 devise
= params
.get('devise')
602 devise
= rh
.Devise
.objects
.get(pk
=devise
)
603 annee
= date
.today().year
604 taux
= rh
.TauxChange
.objects
.filter(annee
=annee
, devise
=devise
)
606 return HttpResponseGone("Le taux n'est pas disponible")
607 data
['devise_code'] = devise
.code
608 data
['taux_euro'] = taux
[0].taux
609 return HttpResponse(dumps(data
))
611 def add_remun(request
, dossier
, type_remun
):
612 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
613 type_remun
= get_object_or_404(rh
.TypeRemuneration
, pk
=type_remun
)
614 dae
.Remuneration(dossier
=dossier
, devise
=dossier
.devise
,
615 type=type_remun
).save()
617 return render_to_response('dae/embauche-remun.html', dict(dossier
=dossier
),
618 RequestContext(request
))
620 def salaire(request
, implantation
, devise
, classement
):
621 if not devise
or not classement
:
624 taux_impl
= rh
.TauxChange
.objects
.filter(implantation
=implantation
) \
626 taux
= rh
.TauxChange
.objects
.filter(devise
=devise
).order_by('-annee')
627 vp
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation
) \
629 if vp
.count() * taux
.count() * taux_impl
.count() == 0:
632 classement
= get_object_or_404(rh
.Classement
, pk
=classement
)
633 taux
, taux_impl
, vp
= taux
[0].taux
, taux_impl
[0].taux
, vp
[0].valeur
635 salaire_euro
= round(vp
* classement
.coefficient
* taux_impl
, 2)
636 data
= dict(salaire_euro
=salaire_euro
, taux
=taux
,
637 salaire_devise
=round(salaire_euro
/ taux
, 2))
639 return HttpResponse(dumps(data
))
641 def liste_valeurs_point(request
):
643 input : implantation_id
644 output : JSON liste de valeur point
646 method
= request
.method
647 params
= getattr(request
, method
, [])
649 annee_courante
= datetime
.datetime
.now().year
650 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
651 implantation_id
= params
.get('implantation_id')
652 objects
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation_id
, annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
654 objects
= rh
.ValeurPoint
.objects
.filter(annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
656 data
.append({'id' : o
.id, 'label' : o
.__unicode__(), })
657 return HttpResponse(dumps(data
))