views.py 98.6 KB
Newer Older
1 2 3
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

4
"""Définitions des views.
5

6 7 8
   Une fonction par page servie.
   """

9
### Imports
Vincent Le gallic's avatar
Vincent Le gallic committed
10
import django
11

12 13 14 15 16
# Modules standard utiles
import random
import random
import json
import base64
17 18 19
import subprocess
import os
import shutil
20
import urllib
21
import re
22 23
from datetime import datetime
from tempfile import mkdtemp
24

25
# Les objets de réponse HTTP
26
from django.http import HttpResponse, HttpResponseRedirect, Http404
27
# Pour renvoyer facilement un template
28
from django.shortcuts import render, get_object_or_404
29
from django.template import RequestContext, Context, TemplateDoesNotExist
Maxime Bombar's avatar
Maxime Bombar committed
30
from django.template.loader import render_to_string
31 32
# Pour html-escaper, notamment
import django.utils.html
33

34 35 36
# Pour protéger les données sensibles dans un POST en mode DEBUG
from django.views.decorators.debug import sensitive_post_parameters

37 38 39
# Les formset pour avoir plusieurs fields() identiques dans un form()
from django.forms import formset_factory

40 41
#: Import pour la traduction
from django.utils.translation import ugettext_lazy as _
42

43 44
# Les paramètres django
import settings
45

46 47
# Les formulaires
import forms
48 49 50 51
# Les messages
import messages
# La communication avec le backend
import nk
52 53
# Les utilitaires
import utilities
54 55
# Des utilitaires pour lesquels on n'a pas envie de rappeler ``module.`` à chaque fois
from utilities import standard_page, standard_page_withignores
56 57
# Gestion des requêtes AJAJ
import ajaj
58

59 60 61
#: Ce module contient les valeurs qu'on a besoin de conserver
#: d'une requête HTTP du client à une autre
import keep_alive
62

63
import basic
64

65
@sensitive_post_parameters('password')
66
def login_page(request):
Vincent Le gallic's avatar
Vincent Le gallic committed
67
    """Renvoie la page de login ou traite les données du formulaire de login"""
68
    if request.method == "POST":
Vincent Le gallic's avatar
Vincent Le gallic committed
69
        # on récupère le formulaire
70
        form = forms.LoginForm(request.POST, label_suffix=" :")
71
        if form.is_valid():
Vincent Le gallic's avatar
Vincent Le gallic committed
72 73
            username = form.cleaned_data["username"]
            password = form.cleaned_data["password"]
74
            masque_droits = form.cleaned_data["droits"]
75
            masque_droits = settings.ACL_MASKS[masque_droits][1]
76
            # On tente un login
77
            return nk.login_NK(request, username, password, form, masque_droits)
78
    else:
79
        form = forms.LoginForm(label_suffix=" :")
80
    variables = basic._fundamental_variables()
81
    variables["form"] = form
82
    return render(request, "note/login.html", variables)
83

84 85
def index(request):
    """La page qui ne sert à rien"""
86
    # On peuple les variables, sans demander la socket
87
    success, sock_ou_response, variables = utilities.get_varsock(request)
88
    if success:
89
        return render(request, "note/index.html", variables)
90 91 92 93
    else:
        # Une erreur a eu lieu
        response = sock_ou_response
        return response
94

95 96 97
def logout(request):
    """Fonction de déconnexion"""
    if request.session.get("logged", None) == "ok": # Il est possible qu'en fait on ait déjà timeout, donc pas besoin de vraiment se déloguer.
98
        # On enlève logged du cookie Django
99 100
        request.session["logged"] = "no"
        # Il faut fermer la socket
101
        success, sock_ou_response = nk.socket_still_alive(request)
102 103 104
        if not success:
            return sock_ou_response
        sock = sock_ou_response
105 106
        sock.write(json.dumps(["exit"]))
        sock.close()
107 108
        # On supprime la socket de keep_alive.CONNS
        idbde = request.session["whoami"]["idbde"]
109
        del keep_alive.CONNS[idbde]
110
        # On renvoie sur la page de login
111
        messages.add_success(request, messages.SUCCMSG_LOGOUT)
112 113
    return HttpResponseRedirect(settings.NOTE_LOGIN_URL)

114
@sensitive_post_parameters("password", "password_confirm")
115
def regen_pw(request, token):
Vincent Le gallic's avatar
Vincent Le gallic committed
116 117
    """Page pour demander l'envoie par mail d'un token de changement de mot de passe
       et pour changer le mot de passe quand on vient avec ce token."""
118
    variables = basic._fundamental_variables()
Vincent Le gallic's avatar
Vincent Le gallic committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
    if token:
        if request.method == "POST":
            form = forms.PasswordForm(request.POST, label_suffix=" :")
            if form.is_valid():
                try:
                    sock = nk.connect_NK(request)
                except nk.NKError as exc:
                    return nk.gerer_NKError(request, exc)
                new_pass = form.cleaned_data["password"]
                data = [token, new_pass]
                sock.write(json.dumps(["confirm_reset_password", data]))
                out = nk.full_read(sock)
                errors = out["errmsg"]
                if errors:
                    messages.add_error(request, errors)
                else:
                    messages.add_success(request, out["msg"])
        else:
            form = forms.PasswordForm(label_suffix=" :")
        variables["form"] = form
        return render(request, "note/regen_pw.html", variables)
    else :
        if request.method == "POST":
            form = forms.Regen_pwForm(request.POST, label_suffix=" :")
            if form.is_valid():
                try:
                    sock = nk.connect_NK(request)
                except nk.NKError as exc:
                    return nk.gerer_NKError(request, exc)
                nom = form.cleaned_data["nom"]
                prenom = form.cleaned_data["prenom"]
                mail = form.cleaned_data["mail"]
                data = [prenom,nom,mail]
                sock.write(json.dumps(["generate_reset_password", data]))
                out = nk.full_read(sock)
                errors = out["errmsg"]
                if errors:
                    messages.add_error(request, errors)
                else:
                    messages.add_success(request, out["msg"])
        else:
            form = forms.Regen_pwForm(label_suffix=" :")
        variables["form"] = form
        return render(request, "note/ask_regen_pw.html", variables)
163

164 165

@standard_page
166 167
def consos(request, sock, kwargs):
    """La page des consos.
168

169 170 171 172
       Dans ``kwargs`` :
        * ``double="-double"`` si on a demandé le mode conso double
        """
    variables = {"double_stack_mode" : kwargs["double"], "page_consos" : True}
173
    categories = utilities._get_boutons_categories(sock, request, False)
174
    variables["categories"] = categories
175
    boutons = utilities._get_boutons(sock, request)
176 177 178 179 180 181 182
    variables["boutons"] = [(categ, [b for b in boutons if b["categorie"] == categ]) for categ in categories]
    sock.write(json.dumps(["historique_transactions", "last"]))
    out = nk.full_read(sock)
    if nk._is_success_code(out["retcode"]):
        variables["historique"] = out["msg"]
    else:
        messages.add_error(request, out["errmsg"])
Charlie Jacomme's avatar
Charlie Jacomme committed
183
    sock.write(json.dumps(["mayi", "transferts"]))
184
    variables["hastransfert"] = nk.full_read(sock)["msg"]
185
    sock.write(json.dumps(["mayi", "credits"]))
186
    variables["hascredit"] = nk.full_read(sock)["msg"]
187
    sock.write(json.dumps(["mayi", "retraits"]))
188
    variables["hasretrait"] = nk.full_read(sock)["msg"]
189 190 191 192 193 194 195 196 197
    # Le formulaire de Crédit
    variables["credit_form"] = forms.CreditRetraitForm(prefix="credit_form", label_suffix=" :")
    # Le formulaire de Retrait
    variables["retrait_form"] = forms.CreditRetraitForm(prefix="retrait_form", label_suffix=" :")
    # Le formulaire de Transfert
    variables["transfert_form"] = forms.TransfertForm(prefix="transfert_form", label_suffix=" :")
    return (variables, "note/consos.html")

@standard_page
198
def dons(request, sock, kwargs):
199 200 201
    """La page des dons"""
    variables = {}
    # Le formulaire de Don
202
    variables["don_form"] = forms.TransfertForm(prefix='transfert_form', label_suffix=" :")
203 204 205
    return (variables, "note/dons.html")

@standard_page
206
def activites(request, sock, kwargs):
207
    """Affichage des activités
208

209 210
       Dans ``kwargs`` :
        * ``admin`` qui vaut ``"/admin"`` si on a demandé le mode admin
211
        * ̀ `old``   qui vaut ``"/old"``   si on a demandé le mode old
212
        """
213
    admin, old = kwargs["admin"], kwargs["old"]
214
    asked_admin = (admin == "/admin")
215
    asked_old = (old == "/old")
216 217 218 219 220 221
    # on récupère les droits de l'user
    sock.write(json.dumps(["mayi", "full_rights"]))
    rights = nk.full_read(sock)["msg"]
    # on regarde si on certains droits
    hasadmin = ("activites_admin" in rights["droits"])
    hasnote = ("note" in rights["droits"])
222 223
    # on est en mode administration si on en a le droit ET qu'on l'a demandé
    isadmin = asked_admin and hasadmin
224 225
    # on est en mode affichage_old  si on en a le droit ET qu'on a demandé old
    isold = asked_old and hasadmin
226 227 228
    if request.method == "POST":
        return HttpResponse("Bad Request", status=400)
    else:
229
        liste_activites = utilities._get_activites(sock, isadmin, request, isold=isold)
230 231 232
        # On affiche la liste des activités en ajoutant les variables standard
        variables = {"activites": liste_activites,
                     "hasadmin": hasadmin,
233
                     "isadmin": isadmin,
234 235
                     "isold": isold,
                     "hasnote": hasnote}
236 237 238
        return (variables, "note/activites.html")

@standard_page
239
def activite(request, sock, kwargs):
240
    """Affichage d'une activité pour y inviter
241

242 243 244 245 246 247 248 249 250 251 252 253
       Dans ``kwargs`` :
        * ``idact``
        * ``admin`` qui vaut ``"/admin"`` si on a demandé le mode admin
        """
    idact, admin = kwargs["idact"], kwargs["admin"]
    asked_admin = (admin == "/admin")
    # On demande si on le droit d'être admin
    sock.write(json.dumps(["mayi", "activites_admin"]))
    hasadmin = nk.full_read(sock)["msg"]
    # On est en mode administration si on en a le droit ET qu'on l'a demandé
    isadmin = asked_admin and hasadmin
    # On récupère l'activité
254
    activite = utilities._get_activite(sock, idact, request)
255 256 257 258 259 260 261 262 263 264 265 266 267
    if request.method == "POST":
        form = forms.InviteForm(request.POST, label_suffix=" :")
        if form.is_valid():
            nom = form.cleaned_data["nom"]
            prenom = form.cleaned_data["prenom"]
            data = [nom, prenom, idact]
            if isadmin: # un admin doit préciser le reponsable (en cas d'échec ce sera lui le responsable)
                try:
                    data.append(int(request.POST["idrespo"]))
                except:
                    pass
            sock.write(json.dumps(["add_invite", [data, "A" * isadmin]]))
            out = nk.full_read(sock)
268 269
            erreur = out["errmsg"]
            if erreur:
270 271 272
                if out["retcode"] == 110:
                    messages.add_warning(request, erreur)
                else:
273
                    messages.add_error(request, erreur)
274
            else:
275
                messages.add_success(request, messages.SUCCMSG_ADDINV)
276
                return HttpResponseRedirect("{}activites/{}{}/".format(settings.NOTE_ROOT_URL, idact, "/admin" * isadmin))
Charlie Jacomme's avatar
Charlie Jacomme committed
277

278
    else:
279
        form = forms.InviteForm(label_suffix=" :", initial=activite)
280
    liste_invites = utilities._get_invites(sock, idact, isadmin, request)
281 282 283 284 285 286 287
    # on prépare les variables
    variables = {"activite": activite,
                 "form": form,
                 "liste_invites": liste_invites,
                 "hasadmin": hasadmin,
                 "isadmin": isadmin}
    return (variables, "note/invitation.html")
Vincent Le gallic's avatar
Vincent Le gallic committed
288

289
@standard_page
290
def activite_gestion(request, sock, kwargs):
291
    """Page de gestion d'une activité.
292

293 294 295 296 297 298 299 300 301
       Dans ``kwargs`` :
        * ``idact`` : n° de l'activité à gérer
        * ``validation`` : fin de l'url, peut être ``"/validate"``, ``"/invalidate"`` ou ``/delete``
       """
    validation, idact = kwargs["validation"], kwargs["idact"]
    variables_standard = kwargs["variables_standard"]
    if (request.method == "GET") and (validation == "/delete"):
        # suppression de l'activité effectuée par une fonction dédiée
        utilities._del_activite(sock, request, idact)
302
        return HttpResponseRedirect('{}activites/'.format(settings.NOTE_ROOT_URL))
303 304 305 306
    sock.write(json.dumps(["mayi", "activites_admin"]))
    hasadmin = nk.full_read(sock)["msg"]
    if not hasadmin:
        messages.add_error(request, _(u"Tu n'as pas le droit activites_admin !"))
307
        return HttpResponseRedirect("{}activites/".format(settings.NOTE_ROOT_URL))
308
    activite = utilities._get_activite(sock, idact, request, computecandelete=True, whoami=variables_standard["whoami"], isadmin=True)
309
    variables = {}
310
    variables["activite"] = activite
311
    variables["hasadmin"] = hasadmin
312
    if validation == "/validate":
313
        action, data, succmsg = "valider_activite", idact, messages.SUCCMSG_VALIDACT
314
    elif validation == "/invalidate":
315 316 317 318
        action, data, succmsg = "devalider_activite", idact, messages.SUCCMSG_DEVALIDACT
    elif validation in ["/open", "/close"]:
        action, data = "openclose_activite", [(validation == "/open"), idact]
        succmsg = messages.SUCCMSG_OUVRACT if data[0] else messages.SUCCMSG_FERMACT
Vincent Le gallic's avatar
Vincent Le gallic committed
319
    else:
320 321
        action = None
    if action:
322
        sock.write(json.dumps([action, data]))
323 324 325 326 327 328 329 330
        out = nk.full_read(sock)
        if nk._is_success_code(out["retcode"]):
            if out["retcode"] == 0:
                messages.add_success(request, succmsg)
            else:
                messages.add_warning(request, out["errmsg"])
        else:
            messages.add_error(request, out["errmsg"])
331
        return HttpResponseRedirect('{}activites/{}/gestion/'.format(settings.NOTE_ROOT_URL, idact))
332
    return (variables, "note/activite_gestion.html")
333

334
@standard_page
335
def activite_gestion_modifier(request, sock, kwargs):
336
    """Page pour voir/éditer une activité, en tant qu'admin
337

338 339 340
       Dans ``kwargs`` :
        * ``idact`` : n° de l'activité à modifier
        """
341 342 343 344 345

    sock.write(json.dumps(["mayi", "activites_admin"]))
    hasadmin = nk.full_read(sock)["msg"]
    if not hasadmin:
        messages.add_error(request, _(u"Tu n'as pas le droit activites_admin !"))
346
        return HttpResponseRedirect("{}activites/".format(settings.NOTE_ROOT_URL))
347

348 349
    idact = kwargs["idact"]
    variables = {}
350
    activite = utilities._get_activite(sock, idact, request)
351
    variables["activite"] = activite
352
    variables["hasadmin"] = hasadmin
353 354 355 356
    if request.method == "GET":
        form = forms.ActiviteForm(label_suffix=" :", initial=activite)
        variables["form"] = form
        return (variables, "note/activite_modifier.html")
357
    else:
358 359 360 361 362 363 364 365 366 367 368 369 370
        form = forms.ActiviteForm(request.POST, label_suffix=" :")
        variables["form"] = form
        if form.is_valid():
            keysact = activite.keys()
            # on regarde les champs qui sont différents
            actdata = {k: v for (k, v) in form.cleaned_data.items() if k in keysact and (v != activite[k])}
            if actdata != {}:
                # On rajoute l'idact
                actdata["id"] = idact
                # On demande toujours à faire l'update en tant qu'admin
                #  de toutes façon ça ne provoque pas d'erreur si on ne l'est pas
                tosend = [actdata, "A"]
                sock.write(json.dumps(["update_activite", tosend]))
371
                out = nk.full_read(sock)
372
                if nk._is_success_code(out["retcode"]):
373
                    messages.add_success(request, messages.SUCCMSG_CHGACT)
374
                else:
375 376 377
                    messages.add_error(request, out["errmsg"])
                    return (variables, "note/activite_modifier.html")
            # on renvoie sur la page de visualisation de l'activité modifiée
378
            return HttpResponseRedirect("{}activites/{}/gestion/".format(settings.NOTE_ROOT_URL, idact))
379
        else:
380 381 382
            return (variables, "note/activite_modifier.html")

@standard_page_withignores(["idact"])
383
def mes_activites(request, sock, kwargs):
384
    """Page "Mes Activités" (ajout, modification, suppression si non encore validée)
385

386 387 388 389 390 391 392
       Dans ``kwargs`` :
        * ``idact`` si on modifie une activité
        * ``delete="/delete"`` si on supprime une activité
        """
    idact, delete = kwargs["idact"], kwargs["delete"]
    variables_standard = kwargs["variables_standard"]
    variables = {}
393 394 395
    # on demande si on le droit d'être admin
    sock.write(json.dumps(["mayi", "activites_admin"]))
    hasadmin = nk.full_read(sock)["msg"]
396
    variables["hasadmin"] = hasadmin
397
    if idact is None:
398
        mes_activites = utilities._get_activites(sock, False, False, request, computecandelete=True, whoami=variables_standard["whoami"], mine=True)
399 400 401 402 403 404 405
        variables["activites"] = mes_activites
        if request.method == "POST":
            form = forms.ActiviteForm(request.POST, label_suffix=" :", listeimprimee=False)
            if form.is_valid():
                actdata = form.cleaned_data
                del actdata["id"]
                sock.write(json.dumps(["add_activite", actdata]))
406 407
                out = nk.full_read(sock)
                if nk._is_success_code(out["retcode"]):
408
                    messages.add_success(request, messages.SUCCMSG_ADDACT)
409
                    return HttpResponseRedirect('{}mes_activites/'.format(settings.NOTE_ROOT_URL))
410
                else:
411
                    messages.add_error(request, out["errmsg"])
412
        else:
413 414
            form = forms.ActiviteForm(label_suffix=" :", listeimprimee=False)
        variables["form"] = form
415
        return (variables, "note/mes_activites.html")
416
    else:
417 418
        if delete == "/delete":
            succeed = utilities._del_activite(sock, request, idact)
419 420
            return HttpResponseRedirect('{}mes_activites/'.format(settings.NOTE_ROOT_URL))
        activite = utilities._get_activite(sock, idact, request, fallback='{}mes_activites/'.format(settings.NOTE_ROOT_URL))
421
        variables["activite"] = activite
422
        if request.method == "GET":
423
            form = forms.ActiviteForm(label_suffix=" :", initial=activite, listeimprimee=False)
424
        else:
425
            form = forms.ActiviteForm(request.POST, label_suffix=" :", listeimprimee=False)
426
            if form.is_valid():
427 428 429 430
                actdata = {champ: valeur for (champ, valeur) in form.cleaned_data.items() if (champ == "id") or (valeur != activite[champ])}
                sock.write(json.dumps(["update_activite", [actdata, "A"]]))
                out = nk.full_read(sock)
                if nk._is_success_code(out["retcode"]):
431
                    messages.add_success(request, messages.SUCCMSG_CHGACT)
432
                    return HttpResponseRedirect('{}mes_activites/'.format(settings.NOTE_ROOT_URL))
433 434 435
                else:
                    messages.add_error(request, out["errmsg"])
        variables["form"] = form
436
        return (variables, "note/activite_modifier.html")
437

438
@standard_page
439
def del_invite(request, sock, kwargs):
440
    """Suppression d'un invité
441

442 443 444 445
       Dans ``kwargs`` :
        * ``idact`` : l'activité dont on veut retirer l'invité
        * ``idinv`` : l'invité qu'on veut retirer
        * ``admin="/admin"`` si on est mode administration"""
446

447 448 449 450 451 452 453
    variables = {}
    idact, idinv = kwargs["idact"], kwargs["idinv"]
    admin = (kwargs["admin"] == "/admin")
    if idinv != -1:
        # On demande toujours la suppression avec le flag "A",
        # de toutes façons il est ignoré par le serveur si on n'a pas les droits
        sock.write(json.dumps(["del_invite", [idinv, "A"]]))
454
        out = nk.full_read(sock)
455
        if out["retcode"] == 404:
456
            messages.add_error(request, messages.ERRMSG_IDINV_FAIL.format(idinv))
457
        elif nk._is_success_code(out["retcode"]):
458
            messages.add_success(request, messages.SUCCMSG_DELINV)
459
        else:
460
            messages.add_error(request, out["errmsg"])
461
    return HttpResponseRedirect(u"{}activites/{}/{}".format(settings.NOTE_ROOT_URL, idact, "admin/" * admin))
462

463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
@standard_page
def liste_invites_entres(request, sock, kwargs):
    """Affiche la liste des invités qui sont rentrés à l'activité

       Dans ``kwargs`` :
        * ``idact`` : l'activité dont on veut la liste des invités rentrés
    """

    variables = {}
    idact = kwargs["idact"]

    #On récupère l'ensemble des droits dont dispose l'utilisateur
    sock.write(json.dumps(["mayi", "full_rights"]))
    out = nk.full_read(sock)

    if not nk._is_success_code(out["retcode"]):
        messages.add_error(request, out["errmsg"])
        return HttpResponseRedirect("{}activites/".format(settings.NOTE_ROOT_URL))
    else:
        droits =  out["msg"]["droits"]
        hasadmin = "activites_admin" in droits

    if not hasadmin:
       messages.add_error(request, _(u"Tu n'as pas le droit activites_admin !"))
       return HttpResponseRedirect("{}index/".format(settings.NOTE_ROOT_URL))

    # On récupère la liste des invités qui sont rentrés à cette activité
    sock.write(json.dumps(["liste_invites_entres", [idact,]]))
    out = nk.full_read(sock)
    if out["retcode"] == 404:
        messages.add_error(request, messages.ERRMSG_IDACT_FAIL % (idact,))
        return HttpResponseRedirect("{}activites/".format(settings.NOTE_ROOT_URL))
    elif not nk._is_success_code(out["retcode"]):
        messages.add_error(request, out["errmsg"])
        return HttpResponseRedirect("{}activites/".format(settings.NOTE_ROOT_URL))

    else:
        invites_entres = out["msg"]
        # On prépare les variables
        variables = {"invites_entres": invites_entres,
                     "idact" : idact,
                     "hasadmin": hasadmin,
505
                     "nb_invites": len(invites_entres),
506 507 508 509 510 511
                     }


    return (variables, "note/invites_entres.html")


512
@standard_page_withignores(["idbde"])
513
def comptes(request, sock, kwargs):
514
    """La page de recherche d'un compte ou qui l'affiche.
515

516 517 518 519
       Dans ``kwargs`` :
        * ``idbde`` si on affiche un compte
        """
    idbde = kwargs["idbde"]
520
    if request.method == "GET":
521 522
        if idbde is None:
            return ({}, "note/comptes.html")
523
        else:
524
            variables = utilities._prepare_variables(sock, idbde, request)
525
            variables["active"] = "compte"
526
            return (variables, "note/un_compte.html")
527
    else:
528
        return HttpResponse("Méthode invalide", status=400)
Vincent Le gallic's avatar
Vincent Le gallic committed
529

530
@standard_page_withignores(["idbde", "idact"])
531 532
def readhesions(request, sock, kwargs):
    """La page de recherche d'un compte ou qui l'affiche.
533

534 535
       Dans ``kwargs`` :
        * ``idbde`` si on affiche un compte
536
        * ``idact`` si on vient d'une entrée pot
537
        """
538
    idbde, idact = kwargs["idbde"], kwargs["idact"]
539
    tarifs = utilities._get_tarifs_adhesion(sock)
540 541 542 543 544
    if request.method == "GET":
        if idbde is None:
            return ({}, "note/readhesions.html")
        else:
            variables = utilities._prepare_variables(sock, idbde, request)
545
            variables.update(tarifs)
546
            form = forms.ReadhesionForm(label_suffix=" :",initial={"pay_nom" : variables["compte"]["nom"],"pay_prenom" : variables["compte"]["prenom"]})
547 548 549 550 551 552 553 554 555 556 557 558
            variables["form"] = form
            return (variables, "note/une_readhesion.html")
    else:
        form = forms.ReadhesionForm(request.POST, label_suffix=" :")
        if form.is_valid():
            readhdata = form.cleaned_data
            # Il faut formater ça correctement pour l'envoyer au serveur NK
            pay = {"type": readhdata["type_de_paiement"], "montant" : readhdata["on_note"],
                    "nom": readhdata["pay_nom"], "prenom": readhdata["pay_prenom"], "banque": readhdata["pay_banque"]}
            # On vire les champs en question du dico
            for champ in ["on_note", "type_de_paiement", "pay_nom", "pay_prenom", "pay_banque"]:
                del readhdata[champ]
559
            # On cherche à savoir combien lui coûte l'adhésion
560
            tarif = tarifs["prix_adhesion"]
561
            pay["montant"] += tarif
562 563
            if pay["type"] != "none":
                readhdata["pay"] = pay
564 565 566 567
            readhdata["idbde"] = idbde
            sock.write(json.dumps(["readherer", readhdata]))
            out = nk.full_read(sock)
            if nk._is_success_code(out["retcode"]):
568
                messages.add_success(request, messages.SUCCMSG_READHESION)
569 570
            else:
                messages.add_error(request, out["errmsg"])
571
                return HttpResponseRedirect("{}readhesions/{}/".format(settings.NOTE_ROOT_URL, idbde))
572 573
            # si on provient de la page d'entrée pot alors on y retourne
            if idact is not None:
574
                return HttpResponseRedirect("{}activites/{}/entree/".format(settings.NOTE_ROOT_URL, idact))
575 576
            # sinon on renvoie sur la page de réadhésion
            else:
577
                return HttpResponseRedirect("{}readhesions/".format(settings.NOTE_ROOT_URL ))
578

579
        else:
580 581 582
            variables = utilities._prepare_variables(sock, idbde, request)
            variables.update(tarifs)
            variables["form"] = form
583
            # Le formulaire de réadhésion n'est pas valide, on renvoie le formulaire incomplet
584
            return (variables, "note/une_readhesion.html")
585

586
@standard_page
587
def historique_transactions(request, sock, kwargs):
588
    """Page de l'historique des transactions d'un compte.
589

590 591
       Dans ``kwargs`` :
        * ``idbde`` : id du compte dont on veut l'historique des transactions.
592
        * ``num_page`` : numéro de la page de l'historique demandé
593 594
        """
    idbde = kwargs["idbde"]
595 596
    nb = 1000 # Arbitraire, nb de consos par page

597
    if idbde is None:
598
        return HttpResponseRedirect('{}comptes/'.format(settings.NOTE_ROOT_URL))
599 600 601
    elif "num_page" in kwargs:
        num_page = int(kwargs["num_page"])
    else:
602
        return HttpResponseRedirect('{}comptes/{}/historique/1/'.format(settings.NOTE_ROOT_URL, idbde))
603

604
    variables = utilities._prepare_variables(sock, idbde, request)
605
    sock.write(json.dumps(["historique_transactions", [idbde, num_page, nb]]))
606 607
    out = nk.full_read(sock)
    if nk._is_success_code(out["retcode"]):
608 609
        variables['historique'] = out["msg"]['historique']
        variables['nb_transactions'] = out["msg"]['nb_transactions']
610 611
        variables['nb_pages'] = out["msg"]['nb_pages']
        variables['num_page'] = out["msg"]['num_page']
612
    else:
613
        messages.add_error(request, out["errmsg"])
614 615 616
    if variables['num_page'] != num_page:
        # Au cas où le serveur aurait eu besoin de renuméroter,
        # si l'utilisateur demande un page < 1 ou > max
617
        return HttpResponseRedirect("{}comptes/{}/historique/{}/".format(settings.NOTE_ROOT_URL, idbde, variables["num_page"],))
618
    variables["active"] = "historique"
619
    return (variables, "note/un_compte_historique.html")
620

621
@standard_page
622
def comptes_advanced(request, sock, kwargs):
Vincent Le gallic's avatar
Vincent Le gallic committed
623
    """Page de recherche avancée"""
624 625 626 627 628 629
    variables = {}
    # On cherche si on a le droit full_search
    sock.write(json.dumps(["mayi", "full_search"]))
    mayi = nk.full_read(sock)["msg"]
    variables["acl_full_search"] = mayi
    # certains champs ne seront accessibles qu'aux utilisateurs ayant les droits full_search
630
    variables["full_search_fields"] = ["tel", "adresse", "pbsante"]
631 632 633
    if request.method == "GET":
        form = forms.SearchForm(label_suffix=" :")
        variables["form"] = form
634
        variables["search_flags"] = "cio" # par défaut, la recherche est case-insensitive et sur les comptes non à jour
635
        variables["exactfilter"] = "b" # par défaut, on matche sur le début du mot
Vincent Le gallic's avatar
Vincent Le gallic committed
636
    else:
637 638 639 640 641 642 643 644 645 646
        form = forms.SearchForm(request.POST, label_suffix=" :")
        checked_fields = [champ[4:] for (champ, valeur) in request.POST.items() if (champ[:4] == "box_") and (valeur == "on")]
        variables["checked_fields"] = checked_fields
        exactfilter = request.POST["exactfilter"]
        variables["exactfilter"] = exactfilter
        search_flags_dico = {"search_alias": "A",
                             "give_alias": "a",
                             "search_historique": "H",
                             "give_historique": "h",
                             "case_insensitive": "i",
647 648
                             "old_accounts": "o",
                             "conjunctive_search" : "c"}
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
        search_flags = "".join([search_flags_dico.get(champ, "") for champ in request.POST.keys()])
        if form.is_valid():
            # On récupère toutes les données sur lesquelles on doit chercher
            searching = {champ: form.cleaned_data[champ] for champ in checked_fields}
            searchfields = searching.keys()
            if "alias" in searchfields:
                search_flags += "A"
            if "historique" in searchfields:
                search_flags += "H"
            variables["search_flags"] = search_flags
            flags = exactfilter + search_flags
            tosend = [flags, searching]
            sock.write(json.dumps(["search", tosend]))
            out = nk.full_read(sock)
            if nk._is_success_code(out["retcode"]):
                # les champs alias et historiques ont déjà été gentiments post-processés par le serveur
                # mais quand il n'y en a pas, on récupère null, pythonisé en None, et c'est moche
                liste = out["msg"]
                for i in range(len(liste)):
                    for champ in ["aliases", "historiques"]:
                        if liste[i].get(champ, "") == None:
                            liste[i][champ] = u""
                variables["search_result"] = liste
                variables["give_alias"] = ("a" in search_flags)
                variables["give_historique"] = ("h" in search_flags)
                return (variables, "note/recherche_avancee_resultats.html")
675
            else:
676
                messages.add_error(request, out["errmsg"])
677
                variables["form"] = form
678 679 680
        else:
            variables["form"] = form
    return (variables, "note/recherche_avancee.html")
681

682
@standard_page
683
def modifier_compte(request, sock, kwargs):
684
    """Page de modification de compte.
685

686 687 688 689 690 691
       Dans ``kwargs`` :
        * ``idbde`` : id du compte à modifier
        """
    idbde = kwargs["idbde"]
    variables_standard = kwargs["variables_standard"]
    variables = utilities._prepare_variables(sock, idbde, request, form=True, whoami=variables_standard["whoami"])
692 693 694 695 696
    # On vérifie si l'utilisateur tente de se modifier lui-même
    updating_myself = False
    if variables["whoami"]["idbde"] == idbde and "myself" in variables["whoami"]["full_rights"]:
        updating_myself = True
    variables["updating_myself"] = updating_myself
697 698 699 700
    if request.method == "GET":
        if variables.has_key("compte"):
            form = forms.CompteForm(initial=variables["compte"])
        else:
701
            return HttpResponseRedirect("{}comptes/".format(settings.NOTE_ROOT_URL))
702 703 704 705 706
    elif request.method == "POST":
        # on a envoyé un formulaire de modification du compte
        form = forms.CompteForm(request.POST)
        if form.is_valid():
            fields = form.cleaned_data
707 708
            gotcompte = variables.has_key("compte")
            if not gotcompte:
709
                return HttpResponseRedirect("{}comptes/".format(settings.NOTE_ROOT_URL))
710 711 712 713 714 715 716 717
            compte = variables["compte"]
            keyscompte = compte.keys()
            # on regarde les champs qui sont différents
            tosend = {k: v for (k, v) in form.cleaned_data.items() if k in keyscompte and (v != compte[k])}
            # les droits ça se gère un peu spécialement
            # avec des virgules et des cases à cocher
            for champ in ["droits", "surdroits"]:
                n = len(champ) + 1
718
                droitsousur = [case[n:] for (case, valeur) in request.POST.items() if case.startswith("{}_".format(champ)) and (valeur == "on")]
719
                liste = compte[champ]
720 721 722 723 724 725 726 727 728 729 730
                if set(droitsousur) != set(liste):
                    tosend[champ] = u",".join(droitsousur)
            if tosend != {}: # si il y a vraiment quelque chose à faire
                # on rajoute l'idbde
                tosend["idbde"] = idbde
                # si on n'a pas les droits wei (et que ce n'est pas notre compte)
                #  on ne tient pas compte du contenu de "numsecu" et "pbsante"
                if not variables["has_wei"]:
                    if tosend.has_key("pbsante"):
                        del tosend["pbsante"]
                sock.write(json.dumps(["update_compte", tosend]))
731 732
                out = nk.full_read(sock)
                if nk._is_success_code(out["retcode"]):
733
                    messages.add_success(request, messages.SUCCMSG_ACCOUNT_CHANGED)
734
                else:
735
                    messages.add_error(request, out["errmsg"])
736
                    variables["form"] = form
737
                    return (variables, "note/modifier_compte.html")
738 739
            # si on provient de la page listedroits alors on y retourne
            if request.META["HTTP_REFERER"].endswith("listedroits"):
740
                return HttpResponseRedirect("{}listedroits/".format(settings.NOTE_ROOT_URL ))
741 742
            # sinon renvoie sur la page de visualisation du compte modifié, même si rien n'a été modifié
            else:
743
                return HttpResponseRedirect("{}comptes/{}/".format(settings.NOTE_ROOT_URL, idbde))
744 745 746
        else:
            variables["form"] = form
            return (variables, "note/modifier_compte.html")
747 748 749
    variables["form"] = form
    variables["active"] = "modifier"
    return (variables, "note/modifier_compte.html")
750

751
@standard_page
752
def supprimer_compte(request, sock, kwargs):
753
    """Page de confirmation de suppression de compte.
754

755 756 757 758 759 760 761 762 763 764
       Dans ``kwargs`` :
        * ``idbde`` : id du compte à supprimer
        """
    idbde = kwargs["idbde"]
    variables = {"button_class" : "btn-danger", "button_content" : u"Confirmer la suppression"}
    variables_standard = kwargs["variables_standard"]
    variables.update(utilities._prepare_variables(sock, idbde, request, form=True, whoami=variables_standard["whoami"]))
    if request.method == "GET":
        if variables.has_key("compte"):
            form = forms.DeleteCompteForm(initial=variables["compte"])
765
        else:
766
            return HttpResponseRedirect("{}comptes/".format(settings.NOTE_ROOT_URL))
767 768 769 770 771 772
    elif request.method == "POST":
        # on a envoyé un formulaire de suppression du compte
        form = forms.DeleteCompteForm(request.POST)
        if form.is_valid():
            fields = form.cleaned_data
            if not variables.has_key("compte"):
773
                return HttpResponseRedirect("{}comptes/".format(settings.NOTE_ROOT_URL))
774 775 776 777 778 779
            compte = variables["compte"]
            # on regarde les champs qui sont différents
            tosend = [idbde, fields["anonymiser"]]
            sock.write(json.dumps(["supprimer_compte", tosend]))
            out = nk.full_read(sock)
            if nk._is_success_code(out["retcode"]):
780
                messages.add_success(request, messages.SUCCMSG_ACCOUNT_DELETED)
781
                # on renvoie sur la page de visualisation du compte supprimé
782
                return HttpResponseRedirect("{}comptes/{}/".format(settings.NOTE_ROOT_URL, idbde))
783 784
            else:
                messages.add_error(request, out["errmsg"])
785 786 787
    variables["form"] = form
    variables["active"] = "supprimer"
    return (variables, "note/supprimer_compte.html")
788

789
@standard_page
790
def update_photo(request, sock, kwargs):
791
    """La page de modification des photos.
792

793 794 795 796
       Dans ``kwargs`` :
        * ``idbde`` : id du compte dont on veut modifier la photo
        """
    idbde = kwargs["idbde"]
797
    variables = {}
798
    variables = utilities._prepare_variables(sock, idbde, request)
799 800 801 802 803 804 805 806 807
    if request.method == "POST":
        form = forms.PhotoForm(request.POST, request.FILES, label_suffix=" :")
        if form.is_valid():
            photo = request.FILES["photo"]
            # On envoie la photo au serveur NK
            photodata = photo.read()
            photob64 = base64.b64encode(photodata)
            format = photo.name.rsplit('.',1)[-1]
            sock.write(json.dumps(["update_photo", [idbde, photob64, format]]))
808 809
            answer = nk.full_read(sock)
            if nk._is_success_code(answer["retcode"]):
810
                messages.add_success(request, messages.SUCCMSG_PHOTO_UPDATED)
811
                return HttpResponseRedirect('{}comptes/{}/'.format(settings.NOTE_ROOT_URL, idbde))
812
            else:
813
                messages.add_error(request, answer["errmsg"])
814 815 816
    else:
        form = forms.PhotoForm(label_suffix=" :")
    variables["form"] = form
817
    variables["active"] = "modifier photo"
818
    return (variables, "note/un_compte_photo.html")
819

820
@standard_page
821
def historique_pseudo(request, sock, kwargs):
822
    """La page de visualisation de l'historique des pseudos.
823

824 825 826 827 828 829
       Dans ``kwargs`` :
        * ``idbde`` : id du compte ont on veut l'historique des pseudos
       """
    idbde = kwargs["idbde"]
    variables = {}
    if request.method == "GET":
830 831 832
        compte = utilities._get_historique_pseudo(sock, idbde, request)
        variables["compte"] = compte
        variables["historique_pseudo"] = compte["historique_pseudo"]
833 834
        return (variables, "note/historique_pseudo.html")
    else:
835
        return HttpResponse("Bad request method : {}".format(request.method))
836

837
@standard_page
838
def search_historique_pseudo(request, sock, kwargs):
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
    """Page de recherche par ancien pseudo (même inactif)."""
    variables = {}
    if request.method == "GET":
        form = forms.SearchHistoriquePseudoForm(label_suffix=" :", initial={"exactfilter": "b"})
        variables["form"] = form
    else:
        form = forms.SearchHistoriquePseudoForm(request.POST, label_suffix=" :")
        if form.is_valid():
            tosend = [form.cleaned_data["historique"], form.cleaned_data["exactfilter"]]
            sock.write(json.dumps(["search_historique_pseudo", tosend]))
            out = nk.full_read(sock)
            if nk._is_success_code(out["retcode"]):
                variables["is_displaying"] = True
                liste = out["msg"]
                variables["search_result"] = liste
854
            else:
855
                messages.add_error(request, out["errmsg"])
856
        else:
857 858 859 860
            variables["form"] = form
    return (variables, "note/search_historique_pseudo.html")

@standard_page
861
def aliases(request, sock, kwargs):
862
    """La page de gestion des aliases.
863

864 865 866 867 868
       Dans ``kwargs`` :
        * ``idbde`` : l'id du compte
        """
    idbde = kwargs["idbde"]
    variables = {}
869 870
    compte = utilities._get_aliases(sock, idbde, request)
    variables["compte"] = compte
871 872 873 874 875 876 877 878 879 880
    if request.method == "GET":
        form = forms.AliasForm(label_suffix=" :")
    else:
        form = forms.AliasForm(request.POST, label_suffix=" :")
        if form.is_valid():
            alias = form.cleaned_data["alias"]
            tosend = [idbde, alias]
            sock.write(json.dumps(["alias", tosend]))
            out = nk.full_read(sock)
            if nk._is_success_code(out["retcode"]):
881
                messages.add_success(request, messages.SUCCMSG_ALIAS_ADDED)
882
                return HttpResponseRedirect("{}comptes/{}/aliases/".format(settings.NOTE_ROOT_URL, idbde))
883 884 885 886
            else:
                messages.add_error(request, out["errmsg"])
    variables["form"] = form
    return (variables, "note/aliases.html")
887

888
@standard_page
889
def unalias(request, sock, kwargs):
890
    """Fonction appelée lorsqu'on veut supprimer un/des alias.
891

892 893 894 895 896 897 898 899 900 901 902
       Dans ``kwargs`` :
        * ``idbde`` : id du compte dont on veut supprimer un/des alias
        * ``delall="_all"`` si on veut supprimer tous les alias du compte (prioritaire)
        * ``idalias`` : id d'un alias à supprimer
        """
    variables = {}
    idbde, delall, idalias = kwargs["idbde"], kwargs["delall"], kwargs["idalias"]
    if request.method == "GET":
        delete_all = (delall == "_all")
        if delete_all:
            sock.write(json.dumps(["unalias", [idbde, True]]))
903
        else:
904 905 906
            try:
                idalias = int(idalias)
            except:
907 908
                messages.add_error(request, messages.ERRMSG_IDALIAS_INVALID.format(idalias))
                return HttpResponseRedirect("{}comptes/{}/aliases/".format(settings.NOTE_ROOT_URL, idbde))
909 910 911 912
            sock.write(json.dumps(["unalias", [idalias, False]]))
        out = nk.full_read(sock)
        if nk._is_success_code(out["retcode"]):
            if delete_all:
913
                msg = messages.SUCCMSG_ALIAS_ALLDELETED
914
            else:
915
                msg = messages.SUCCMSG_ALIAS_DELETED
916 917 918
            messages.add_success(request, msg)
        else:
            messages.add_error(request, out["errmsg"])
919
        return HttpResponseRedirect("{}comptes/{}/aliases/".format(settings.NOTE_ROOT_URL, idbde))
920
    else:
921
        return HttpResponse("Bad request method : {}".format(request.method))
922

923
@sensitive_post_parameters("password")
924
@standard_page
925
def password(request, sock, kwargs):
926
    """Page de changement de mot de passe.
927

928 929 930 931 932 933
       Dans ``kwargs`` :
        * ``idbde`` : id du compte dont on veut changer le mot de passe
        """
    idbde = kwargs["idbde"]
    variables = {}
    if request.method == "GET":
934 935 936 937 938 939
        compte = utilities._get_compte(sock, idbde, request)
        variables["compte"] = compte
        if kwargs["variables_standard"]["whoami"]["idbde"] == idbde:
            # On peut changer son propre mot de passe
            variables["form"] = forms.PasswordForm(label_suffix=" :")
        elif idbde <= 0:
940
            messages.add_error(request, messages.ERRMSG_PASSWORD_NEGATIVE_IDBDE)
941 942 943 944 945
        else:
            # Il faut alors vérifier si il a le droit chgpass
            sock.write(json.dumps(["mayi", "chgpass"]))
            out = nk.full_read(sock)["msg"]
            if out == True:
946 947
                variables["form"] = forms.PasswordForm(label_suffix=" :")
            else:
948
                messages.add_error(request, messages.ERRMSG_NO_ACL_CHGPASS)
949
        return (variables, "note/password.html")
950
    else:
951 952 953 954 955
        form = forms.PasswordForm(request.POST, label_suffix=" :")
        if form.is_valid():
            newpass = form.cleaned_data["password"]
            tosend = [idbde, newpass]
            sock.write(json.dumps(["chgpass", tosend]))
956 957
            out = nk.full_read(sock)
            if nk._is_success_code(out["retcode"]):
958
                messages.add_success(request, messages.SUCCMSG_PASSWORD_CHANGED)
959
                return HttpResponseRedirect("{}comptes/{}/".format(settings.NOTE_ROOT_URL, idbde))
960
            else:
961
                messages.add_error(request, out["errmsg"])
962 963
                variables["form"] = form
                return (variables, "note/password.html")
964
        else:
965 966 967
            compte = utilities._get_compte(sock, idbde, request)
            variables["compte"] = compte
            variables["form"] = form
968 969
            return (variables, "note/password.html")

970

971
def _create_BoutonForm(sock, request, contenu=None, initial=None):
972 973
    """Un hack pour peupler au runtime
       les choices du champ destinataire d'un formulaire de création de bouton."""
974 975 976 977 978 979 980
    if initial == None:
        if contenu == None:
            form = forms.BoutonForm(label_suffix=" :")
        else:
            form = forms.BoutonForm(contenu, label_suffix=" :")
    else:
        form = forms.BoutonForm(label_suffix=" :", initial=initial)
981
    categories = utilities._get_boutons_categories(sock, request, True)
982
    form.fields['categorie'].choices = [[ca] * 2 for ca in categories]
983
    clubs = utilities._get_clubs(sock, request)
984
    form.fields['destinataire'].choices = [[cl["idbde"], cl["pseudo"]] for cl in clubs]
985
    return form
986

987
@standard_page
988
def boutons(request, sock, kwargs):
989
    """Page de gestion des boutons.
990

991 992 993 994 995 996 997 998 999 1000 1001
       Dans ``kwargs`` :
        * ``idbouton`` : id du bouton
        * ``delete="/delete"`` si on cherche à le supprimer
        """
    variables = {}
    idbouton = kwargs.get("idbouton")
    delete = kwargs.get("delete")
    if delete == "/delete":
        sock.write(json.dumps(["delete_bouton", idbouton]))
        out = nk.full_read(sock)
        if nk._is_success_code(out["retcode"]):
1002
            messages.add_success(request, messages.SUCCMSG_DELBUTTON)
1003 1004
        else:
            messages.add_error(request, out["errmsg"])
1005
        return HttpResponseRedirect('{}boutons/'.format(settings.NOTE_ROOT_URL))
1006 1007
    if request.method == "GET":
        if idbouton == None:
1008
            boutons = utilities._get_boutons(sock, request, hidden=True)
1009 1010
            variables["boutons"] = boutons
            # le formulaire est vide
1011
            form = _create_BoutonForm(sock, request)
1012
        else:
1013
            bouton = utilities._get_un_bouton(sock, idbouton, request, fallback='{}boutons/'.format(settings.NOTE_ROOT_URL))
1014 1015
            variables["un_bouton"] = bouton
            # le formulaire contient les données du bouton
1016
            form = _create_BoutonForm(sock, request, initial=bouton)
1017 1018
        variables["form"] = form
    else:
1019
        form = _create_BoutonForm(sock, request, contenu=request.POST)
1020 1021 1022 1023 1024 1025 1026
        if form.is_valid():
            if idbouton == None: # c'est donc un ajout
                sock.write(json.dumps(["create_bouton", form.cleaned_data]))
            else: # c'est une modification
                data = form.cleaned_data
                data["id"] = idbouton
                sock.write(json.dumps(["update_bouton", data]))
1027
            out = nk.full_read(sock)
1028 1029 1030 1031
            retcode = out["retcode"]
            if retcode == 103:
                # C'est le code "Ce bouton existe déjà, c'est pas la peine de l'ajouter"
                messages.add_success(request, out["errmsg"])
1032
                return HttpResponseRedirect("{}boutons/".format(settings.NOTE_ROOT_URL))
1033 1034
            elif nk._is_success_code(retcode):
                if idbouton == None: #ajout
1035
                    messages.add_success(request, messages.SUCCMSG_ADDBUTTON)
1036
                else: #modification
1037
                    messages.add_success(request, messages.SUCCMSG_CHGBUTTON)
1038
                return HttpResponseRedirect("{}boutons/".format(settings.NOTE_ROOT_URL))
1039
            else:
1040
                messages.add_error(request, out["errmsg"])
1041
        else:
1042
            if idbouton == None:
1043
                boutons = utilities._get_boutons(sock, request)
1044 1045
                variables["boutons"] = boutons
            else:
1046 1047 1048 1049
                # on est dans le cas : je poste pour modifier un bouton, mais j'ai échoué
                # on a besoin de la présence de la variable un_bouton mais on n'a pas besoin d'aller le chercher
                # on a juste besoin de son id
                variables["un_bouton"] = {"id": idbouton}
1050
            variables["form"] = form
1051
    return (variables, "note/boutons.html")
1052

1053
@standard_page
1054
def preinscriptions(request, sock, kwargs):
1055 1056 1057 1058
    """Page de gestion des préinscriptions."""
    variables = {}
    if request.method == "GET":
        form = forms.PreinscriptionForm(label_suffix=" :")
1059
    else:
1060 1061 1062 1063 1064 1065
        form = forms.PreinscriptionForm(request.POST, label_suffix=" :")
        if form.is_valid():
            preinsdata = form.cleaned_data
            sock.write(json.dumps(["preinscrire", preinsdata]))
            out = nk.full_read(sock)
            if nk._is_success_code(out["retcode"]):
1066
                messages.add_success(request, messages.SUCCMSG_PREINSCRIPTION_ADDED)
1067 1068 1069 1070 1071 1072
                # on ne fait pas un redirect, mais on vide le formulaire
                form = forms.PreinscriptionForm(label_suffix=" :")
            else:
                messages.add_error(request, out["errmsg"])
    variables["form"] = form
    return (variables, "note/preinscriptions.html")
1073

1074
@standard_page_withignores(["preid"])
1075
def inscriptions(request, sock, kwargs):
1076
    """Page de gestion des inscriptions.
1077

1078
       Dans ``kwargs`` :
1079
        * ``preid`` : preid de la préinscription dont on s'occupe, vaut idwei si on vient du wei
1080
        * ``delete="/delete"`` si on cherche à la supprimer