Code source de WeiFonctions

# -*- coding: utf-8 -*-

"""Ce module a pour but de regrouper toutes et seulement les fonctions
utiles à l'application Wei.

Évidemment elles sont toutes appelées avec comme premier
paramètre self.
"""

# Imports basiques
import time
import psycopg2

# Imports de fonctions de bases
import mail
import BaseFonctions
import ExceptionsNote
import ReadDatabase
from ServeurFonctions import _badparam, _pasledroit, _private_adhesion, _un_transfert
import ServeurFonctions

def wei_main(self):
    """
        Fonction donnant tous les droits et toutes les infos
        nécessaires au fonctionnement basique de l'application
        WEI.

        Ne prend aucun argument.

        Renvoie les droits wei, myself, inscriptions, preinscriptions
        sous la forme d'un dictionnaire de booléen.
    """
    response = dict()
    # On récupère les paramètres du WEI de l'année en cours
    con, cur = BaseFonctions.getcursor()
    cur.execute("SELECT wei_name, wei_begin, wei_end, wei_1a_available, wei_vieux_available, wei_contact, prix_wei_normalien, prix_wei_non_normalien FROM configurations;")
    response.update(cur.fetchone())

    # On récupère les droits utiles pour l'app WEI, à savoir :
    # ---> Les droits chef WEI (gestion des inscriptions): haswei
    # ---> Le droit myself (droit de s'inscrire au WEI): myself
    # ---> Le droit préinscription (Peut inscrire des 1A): preinscription
    # ---> Le droit inscription (Peut inscrire des 2A) : inscription
    haswei = self._has_acl("wei_admin")
    inscriptions = self._has_acl("inscriptions")
    myself = self._has_acl("myself")
    preinscriptions = self._has_acl("preinscriptions")

    # On renvoie la réponse sous la forme d'une dictionnaire
    response['haswei'] = haswei
    response['inscriptions'] = inscriptions
    response['preinscriptions'] = preinscriptions
    response['myself'] = myself

    self._debug(5, u"Envoi des droits WEI (%s)" % str(response))
    self._send(response)

def _role_prettify(value):
    """
        Transforme l'entrée role base de données en quelque chose de lisible
    """
    roles = value.split(';')
    roles_pretty = []

    for role in roles:
        if role == 'libre':
            roles_pretty.append("Électron libre")
        elif role == 'staff':
            roles_pretty.append("Staff")
        elif role == 'chef_bus':
            roles_pretty.append("Chef de bus")
        elif role == 'chef_equipe':
            roles_pretty.append("Chef d'équipe")
        else:
            roles_pretty.append("Inconnu")

    return ";".join(roles_pretty)


def wei_get_info(self, idwei):
    """
    Fonction renvoyant les informations d'un idwei
    """
    # On vérifie tout d'abord que l'utilisateur a bien les droits WEI
    if not self._has_acl("wei_admin"):
        _pasledroit(self, "wei_admin")

    # On ouvre une conneexion avec la base de données
    con, cur = BaseFonctions.getcursor()
    
    
    cur.execute("SELECT *, infos AS pbsante, dept AS section, note AS pseudo FROM wei_1a WHERE idwei = %s;", (idwei,))
    infowei = cur.fetchall()

    if not infowei:
        self._send(None, 404, u"cette préinscription wei n'existe pas.")
        self._debug(3, u"wei_get_info failed : l'idwei %s n'existe pas dans la table wei_1a." % (idwei,))
    else:
        response = dict(infowei[0])
        self._send(response)


def wei_get_listes(self, data):
    """
    Fonction renvoyant la liste des préinscrits et des
    inscrits au WEI.

    Prend 1 argument, 1a, qui spécifie où les entrées doivent être recherchées

    La réponse est, en fonction des cas:

     *   Si 1a vaut True :

      * ``liste_1a`` : liste des inscrits au WEI en 1A

     *   Sinon, un dictionnaire contenant 2 listes :

      * ``liste_pre`` : liste des préinscriptions, toutes années confondues
      * ``liste_insc`` : liste des inscriptions, toutes années confondues
    """

    # On vérifie avant toute chose que l'utilisateur a bien les droits WEI
    if not self._has_acl("wei_admin"):
        _pasledroit(self, "wei_admin")
        return

    _1a = data[0]

    # On ouvre une connexion avec la base de données
    con, cur = BaseFonctions.getcursor()

    if _1a:
        # Liste des inscriptions 1A
        cur.execute("""SELECT * FROM wei_1a ORDER BY idwei;""")
        liste_1a = cur.fetchall()

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE genre='M';")
        mecs = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE genre='F';")
        filles = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE genre='N';")
        nonbin = cur.fetchone()['count']
        
        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='A0';")
        infos = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='A1';")
        maths = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='A2';")
        phys = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='A\"2';")
        chimistes = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='A3';")
        bios = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept LIKE 'B%';")
        saphires = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='C';")
        designs = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='D2';")
        ecos = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='D3';")
        socios = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE dept='E';")
        anglaises = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE soge;")
        soge = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a WHERE ml_evenements;")
        ml_evenements = cur.fetchone()['count']

        cur.execute("SELECT COUNT(*) FROM wei_1a;")
        total = cur.fetchone()['count']

        response = {
            'liste_1a' : liste_1a,
            'mecs' : mecs,
            'filles' : filles,
            'nonbin' : nonbin,
            'infos' : infos,
            'maths' : maths,
            'phys' : phys,
            'chimistes' : chimistes,
            'bios' : bios,
            'saphires' : saphires,
            'designs' : designs,
            'ecos' : ecos,
            'socios' : socios,
            'anglaises' : anglaises,
            'soge' : soge,
            'ml_evenements' : ml_evenements,
            'total' : total,
        }

        self._send(response)
        return

    # On commence par chercher dans la base wei_vieux les préinscriptions WEI
    cur.execute("""SELECT wei_vieux.idwei,
                          comptes.pseudo,
                          comptes.idbde,
                          comptes.nom,
                          comptes.prenom,
                          wei_vieux.mail,
                          wei_vieux.tel,
                          wei_vieux.annee||wei_vieux.dept AS formation,
                          comptes.solde,
                          wei_vieux.normalien,
                          wei_vieux.conge,
                          wei_vieux.bus,
                          wei_vieux.role,
                          wei_vieux.paiement,
                          wei_vieux.payé,
                          wei_vieux.caution,
                          wei_vieux.readhere,
                          wei_vieux.pbsante
                    FROM wei_vieux,
                         comptes
                    WHERE (NOT wei_vieux.payé
                          OR NOT wei_vieux.caution)
                          AND comptes.idbde=wei_vieux.idbde
                    ORDER BY comptes.nom,
                             comptes.prenom;""")
    resultats = cur.fetchall()
    self._debug(4, u"Récupération des listes des préinscrits depuis wei_vieux")
    cur.execute("SELECT COUNT(*) FROM wei_vieux WHERE NOT payé OR NOT caution;")
    nb_pre = cur.fetchone()[0]
    cur.execute("SELECT COUNT(*) FROM wei_vieux WHERE payé;")
    nb_pre_paye = cur.fetchone()[0]
    cur.execute("SELECT COUNT(*) FROM wei_vieux WHERE caution;")
    nb_pre_caution = cur.fetchone()[0]

    liste_pre = [dict(r) for r in resultats]

    for entry in liste_pre:
        entry["role"] = _role_prettify(entry["role"])

    # On cherche ensuite les inscriptions WEI validées
    cur.execute("""SELECT wei_vieux.idwei,
                          comptes.pseudo,
                          comptes.idbde,
                          comptes.nom,
                          comptes.prenom,
                          wei_vieux.mail,
                          wei_vieux.tel,
                          wei_vieux.annee||wei_vieux.dept AS formation,
                          comptes.solde,
                          wei_vieux.normalien,
                          wei_vieux.conge,
                          wei_vieux.bus,
                          wei_vieux.role,
                          wei_vieux.paiement,
                          wei_vieux.payé,
                          wei_vieux.caution,
                          wei_vieux.readhere,
                          wei_vieux.pbsante
                    FROM wei_vieux,
                         comptes
                    WHERE payé
                      AND caution
                      AND comptes.idbde=wei_vieux.idbde
                    ORDER BY comptes.nom,
                             comptes.prenom;""")

    resultats = cur.fetchall()
    self._debug(4, u"Récupération de la liste des inscrits depuis wei_vieux")
    cur.execute("SELECT COUNT(idwei) FROM wei_vieux WHERE payé AND caution;")
    nb_insc = cur.fetchone()[0]

    liste_insc = [dict(r) for r in resultats]

    # On transforme les rôles base de données en rôle lisible
    for entry in liste_insc:
        entry["role"] = _role_prettify(entry["role"])

    # On renvoie la réponse sous forme d'un dictionnaire
    response = {
        'liste_pre' : liste_pre,
        'liste_insc' : liste_insc,
        'nb_pre' : [nb_pre, nb_pre_paye, nb_pre_caution],
        'nb_insc' : nb_insc,
    }

    self._send(response)

def wei_readherer(self, data):
    """
        Effectue la réadhésion d'un 2A+ inscrit au WEI
    """
    if not self._has_acl("wei_admin"):
        _pasledroit(self, "wei_admin")
        return

    idwei = data

    con, cur = BaseFonctions.getcursor()

    # On vérifie que c'est pas déjà fait
    cur.execute("SELECT * FROM wei_vieux WHERE idwei=%s;", (idwei,))

    inscr = cur.fetchone()

    annee = BaseFonctions.adhesion_current_year()
    cur.execute("SELECT count(*) AS nb FROM adhesions WHERE idbde=%s AND annee=%s;", (inscr["idbde"], annee))
    nb = cur.fetchone()['nb']

    if inscr["readhere"] or nb > 0:
        # La réadhésion a déjà été faite
        self._send(None, 14, u"L'adhérent a déjà été réadhéré pour l'année %d" % annee)
        return

    readh_data = {
        'idbde' : inscr["idbde"],
        'section' : "%s%s" % (inscr["annee"], inscr["dept"],),
        'wei' : True,
    }

    if inscr["paiement"] == "soge":
        pay = {
            'type' : 'soge',
            'commentaire' : u"Réadhésion",
        }
        readh_data["pay"] = pay

    if (not inscr["normalien"]) or (inscr["conge"]):
        cur.execute("UPDATE comptes SET normalien = FALSE WHERE idbde=%s;", (inscr["idbde"],))
        cur.execute("COMMIT;")
    else:
        cur.execute("UPDATE comptes SET normalien = TRUE WHERE idbde=%s;", (inscr["idbde"],))
        cur.execute("COMMIT;")

    self.readherer(readh_data)

    cur.execute("UPDATE wei_vieux SET (readhere, payé) = (TRUE, TRUE) WHERE idwei=%s;", (idwei,))
    cur.execute("COMMIT;")

def wei_search(self, data):
    """
    Fonction effectuant les recherches dans la table des inscriptions
    WEI à partir des champs donnés.

    ``data = [is_pre, id, champs]`` :

     * ``is_pre`` : booléen indiquant dans quelle table chercher (1a ou vieux)
     * ``id`` : idbde du compte appelant la fonction
     * ``champs`` :dictionnaire contenant les champs de recherche

    La réponse est un dictionnaire contenant les champs suivants :

     * ``done`` : booléen indiquant si le compte effectuant la recherche est déjà (pré)inscrit
     * ``resultats`` : liste contenant les résultats de la recherche
     * ``etat_demande`` : indique l'état de l'inscription de l'utilisateur (``None`` si non effectuée, ``False`` si non validée, ``True`` si validée)

    """
    is_pre = data[0]["is_pre"]
    idbde = data[0]["id"]
    champs = data[0]["champs"]
    id_registered = False
    etat_demande = None

    if is_pre:
        # On cherche dans la table 1A
        con, cur = BaseFonctions.getcursor()

        cur.execute("""SELECT * FROM wei_1a WHERE idwei=%(idwei)s;""", champs)

        response = {
            'done' : False,
            'resultats' : cur.fetchall(),
            'etat_demande' : None,
        }

        self._send(response)

    else:
        # On recherche dans la table vieux
        auth_fields = [
            'idwei',
            'idbde',
            'nom',
            'prenom',
            'tel',
            'urgence_nom',
            'urgence_tel',
            'mail',
            'annee',
            'dept',
            'paiement',
            'normalien',
            'pseudo',
            'pbsante',
            'bus',
            'role',
            'payé',
            'caution',
        ]

        # On ouvre une connexion à la base de données
        con, cur = BaseFonctions.getcursor()

        # On récupère toutes les inscriptions vieux
        cur.execute("""SELECT ( payé AND caution ) AS valide, *
                         FROM wei_vieux
                        WHERE idbde=%s;""", (idbde,))

        etat_demande = cur.fetchone()
        self._debug(4, u"Récupération idbde, payé AND caution depuis wei_vieux")
        is_registered = "vieux" if etat_demande is not None else None

        # S'il n'est pas enregistré, il s'agit peut-être d'un 1A : On vérifie
        if not is_registered:
            cur.execute("SELECT nom, prenom, mail FROM comptes WHERE idbde=%s;", (idbde,))
            nom, prenom, mail = cur.fetchone()

            cur.execute("SELECT * FROM wei_1a WHERE ((nom ILIKE %s) AND (prenom ILIKE %s)) OR mail=%s;", (nom, prenom, mail,))

            etat_demande = cur.fetchone()
            is_registered = "1a" if etat_demande is not None else None


        # On vérifie qu'il n'y ait pas de champ non-présents dans la table
        if not set(champs.keys()).issubset(auth_fields):
            self._send(None, 900, "Les champs %s ne sont pas supportés dans la table wei_vieux." % repr(set(champs.keys()).difference(auth_fields)))

        else:
            # On construit la requête SQL de recherche
            requete_where = "WHERE" if champs else ""
            where_args = []
            value = None
            for key in auth_fields:
                value = champs.get(key)
                if value:
                    where_args.append(" " + key + "=%("+ key +")s ")


            requete = "SELECT * FROM wei_vieux " + requete_where + "AND".join(where_args) + ";"

            cur.execute(requete, champs)
            self._debug(4, u"Recherche dans les tables WEI avec %s" % str(champs))

            # On renvoie les résultats
            resultats = cur.fetchall()

            response = {
                'done' : is_registered,
                'resultats' : resultats,
                'etat_demande' : etat_demande,
            }

            self._send(response)

def wei_compute_form(self, data):
    """
    Fonction effectuant traitant les données des formulaires d'inscription
    en fonction du type de formulaire (1A/vieux)

    ``data = ["type", formulaire]`` :

     * ``type`` : indique le type de formulaire soumis (``'1a'`` ou ``'vieux'``)
     * ``formulaire`` est un dictionnaire représentant ledit formulaire.

    """
    form_type = data[0]
    form = data[1]

    if form_type == '1a':
        _wei_1a(self, form)
    elif form_type == 'vieux':
        idbde = form.get("idbde", -300)
        pseudo = form.get("pseudo", "")

        con, cur = BaseFonctions.getcursor()
        cur.execute("""SELECT comptes.idbde,
                              comptes.pseudo
                         FROM comptes,
                              aliases
                        WHERE aliases.alias=%s
                        AND aliases.idbde=comptes.idbde;""", (pseudo, ))

        res = cur.fetchone()
        if res:
            idbde = res[0]
            pseudo = res[1]

            form["idbde"] = idbde
            form["pseudo"] = pseudo

        try:
            compte = ReadDatabase.get_compte(idbde) if idbde != -300 else ReadDatabase.get_compte_by_pseudo(pseudo)
            compte_type = compte.get("type", "inconnu")

        except ExceptionsNote.Error404:
            compte_type = "inexistant"

        if compte_type != "personne":
            self._send(None, 905, "Formulaire invalide : ce compte est de type %s" % compte_type)
            self._debug(3, u"#%d ne peut pas être inscrit au WEI (type %s)" % (idbde, compte_type, ))
        else:
            _wei_vieux(self, form)
    else:
        self._send(None, 901, "%s n'est pas un type de formulaire reconnu" % form_type)

def _wei_1a(self, form):
    """
        Fonction traitant les formulaires 1A
    """

    haswei = self._has_acl("wei_admin")
    inscriptions = self._has_acl("inscriptions")
    myself = self._has_acl("myself")
    preinscriptions = self._has_acl("preinscriptions")

    response = {
        'haswei' : haswei,
        'inscriptions' : inscriptions,
        'preinscriptions' : preinscriptions,
        'myself' : myself,
    }

    if not inscriptions:
        _pasledroit(self, "inscriptions")
        return

    conn, cur = BaseFonctions.getcursor()

    cur.execute("SELECT wei_1a_available FROM configurations;")

    if not cur.fetchone()['wei_1a_available']:
        self._send(None, 911, "Les inscriptions sont fermées")
        return

    try:
        cur.execute("""
    INSERT INTO wei_1a (nom, prenom, genre, adresse, mail, ml_evenements, normalien, tel, urgence_nom, urgence_tel,
                        dept, note, infos, soge, q_soirees, q_alcools, q_encadrement, q_groupe, q_sociable, q_chants, q_boire, q_assos, q_suiveur, q_activites, q_personnes, q_conquetes, q_mots, petit_mot)
    VALUES
            (%(nom)s,
             %(prenom)s,
             %(genre)s,
             %(adresse)s,
             %(mail)s,
             %(ml_evenements)s,
             %(normalien)s,
             %(tel)s,
             %(urgence_nom)s,
             %(urgence_tel)s,
             %(dept)s,
             %(note)s,
             %(infos)s,
             %(soge)s,
             %(q_soirees)s,
             %(q_alcools)s,
             %(q_encadrement)s,
             %(q_groupe)s,
             %(q_sociable)s,
             %(q_chants)s,
             %(q_boire)s,
             %(q_assos)s,
             %(q_suiveur)s,
             %(q_activites)s,
             %(q_personnes)s,
             %(q_conquetes)s,
             %(q_mots)s,
             %(petit_mot)s);""", form)

        cur.execute("COMMIT;")
    except psycopg2.IntegrityError:
        self._send(None, 912, "L'inscription est déjà enregistrée")
        return

    self._send(response)
    self._debug(1, u"Inscription 1A enregistrée (%s %s)" % (form['prenom'], form['nom'],))

def _wei_vieux(self, form):
    """
        Fonction traitant les formulaires 2A+, et stockant les
        résultats dans une base de données.

    _log relevant ids : idbde
    """
    haswei = self._has_acl("wei_admin")
    inscriptions = self._has_acl("inscriptions")
    myself = self._has_acl("myself")
    preinscriptions = self._has_acl("preinscriptions")

    con, cur = BaseFonctions.getcursor()

    cur.execute("SELECT wei_vieux_available FROM configurations;")

    if not cur.fetchone()['wei_vieux_available']:
        self._send(None, 911, "Les inscriptions sont fermées")
        return

    this_account = ReadDatabase.get_compte(self.userid)

    # Liste des champs autorisés pour l'insertion dans la base de données
    champs = [
        'idbde',
        'nom',
        'prenom',
        'tel',
        'urgence_nom',
        'urgence_tel',
        'mail',
        'annee',
        'dept',
        'paiement',
        'normalien',
        'conge',
        'pseudo',
        'pbsante',
        'bus',
        'role',
    ]

    # On vérifie que les champs du formulaire sont acceptables
    if not set(form.keys()).issubset(champs):
        self._send(None, 902, "Le formulaire n'est pas conforme : (%s) non reconnus" % repr(set(form.keys()).difference(champs)))
        self._debug(3, u"Formulaire d'inscription non conforme")
    elif not inscriptions and this_account["idbde"] != form["idbde"]:
        _pasledroit(self, "inscriptions")
    else:
        # On vérifie que la personne n'est pas déjà inscrite
        cur.execute("SELECT idwei, idbde FROM wei_vieux WHERE pseudo=%(pseudo)s", form)
        res = cur.fetchone()
        if res:
            self._send(None, 907, u"%s est déjà inscrit au WEI pour cette année" % form["pseudo"])
            self._debug(3, u"#%d est déjà inscrit au WEI !" % res[1])
            return

        # On récupère les infos du compte dont le pseudo est spécifié dans le formulaire
        cur.execute("SELECT idbde,nom,prenom FROM comptes WHERE pseudo=%(pseudo)s;", form)
        res = cur.fetchone()
        if not res:
            self._send(None, 903, "Aucun idbde ne correspond au pseudo %s" % form["pseudo"])
            self._debug(3, u"pseudo %s introuvable dans la table comptes" % form["pseudo"])
        else:
            idbde, nom, prenom = res;
            form["idbde"] = idbde
            form["nom"] = nom
            form["prenom"] = prenom

            # On traite le résultat de la recherche
            # On enregistre la préinscription dans la base de données
            form["idbde"] = idbde
            cur.execute("""INSERT INTO
                               wei_vieux (idbde, nom, prenom, tel, urgence_nom, urgence_tel, mail, annee, dept, paiement, normalien, conge, pseudo, pbsante, bus, role)
                               VALUES
                                  (%(idbde)s,
                                   %(nom)s,
                                   %(prenom)s,
                                   %(tel)s,
                                   %(urgence_nom)s,
                                   %(urgence_tel)s,
                                   %(mail)s,
                                   %(annee)s,
                                   %(dept)s,
                                   %(paiement)s,
                                   %(normalien)s,
                                   %(conge)s,
                                   %(pseudo)s,
                                   %(pbsante)s,
                                   %(bus)s,
                                   %(role)s);""",
                        form)
            self._log("_wei_vieux", cur, "Inscription de #%d au WEI" % (idbde,), [idbde])
            cur.execute("COMMIT;")

            response = {
                'haswei' : haswei,
                'inscriptions' : inscriptions,
                'preinscriptions' : preinscriptions,
                'myself' : myself,
            }

            self._send(response)
            self._debug(1, u"Inscription de #%d au WEI" % (idbde, ))


def wei_update_tables(self, data):
    """
    Fonction mettant à jour les statuts d'inscription dans les tables WEI.

    ``data = [operations]`` :

     * ``operations`` est un dictionnaire contenant les valeurs des cases cochées dans le formulaire de la liste des inscrits.

    Renvoie ``None`` dans tous les cas.
    """
    operations = data[0]

    con, cur = BaseFonctions.getcursor()

    retmsg = u""
    retcode = 0

    try:
        # On récupère la liste complète des (pré)inscriptions
        cur.execute("SELECT idbde, idwei, payé, caution, (normalien AND NOT conge), paiement AS normalien FROM wei_vieux;")
        list_select = cur.fetchall()

        for idbde, idwei, paye, caution, normalien, paiement in list_select:
            # On regarde dans un premier temps la case 'WEI Payé'
            value = operations.get(u'payé_%d' % idwei, None)
            if value is None and paye is True:
                cur.execute("UPDATE wei_vieux SET payé=FALSE WHERE idwei=%s;", (idwei, ))
                self._debug(1, u"Modif de %d : payé->FALSE" % (idwei, ))
            elif value == u'on' and paye is False:
                cur.execute("UPDATE wei_vieux SET payé=TRUE WHERE idwei=%s;", (idwei, ))
                self._debug(1, u"Modif de %d : payé->TRUE" % (idwei, ))
            else:
                pass

            # On regarde ensuite la case 'Caution'
            value = operations.get(u'caution_%d' % idwei, None)
            if value is None and caution is True:
                cur.execute("UPDATE wei_vieux SET caution=FALSE WHERE idwei=%s;", (idwei, ))
                self._debug(1, u"Modif de %d : caution->FALSE" % (idwei, ))
            elif value == u'on' and caution is False:
                cur.execute("UPDATE wei_vieux SET caution=TRUE WHERE idwei=%s;", (idwei, ))
                self._debug(1, u"Modif de %d : caution->TRUE" % (idwei, ))
            else:
                pass

            # On regarde enfin la case 'Supprimer'
            value = operations.get(u'supprimer_%d' % idwei, None)
            if value == u'on':
                # On recrédite le prix du WEI si jamais il a déjà été payé
                if paye and not (paiement == 'soge'):
                    if normalien:
                        requete_prix = "SELECT prix_wei_normalien FROM configurations;"
                    else:
                        requete_prix = "SELECT prix_wei_non_normalien FROM configurations;"
                    cur.execute(requete_prix)
                    a_rembourser = cur.fetchone()[0]
                    _un_transfert(self, [], 0, idbde, a_rembourser, "Remboursement WEI")
                cur.execute("DELETE FROM wei_vieux WHERE idwei=%s;", (idwei, ))
                self._debug(1, u"Suppression de %d" % (idwei, ))
            else:
                pass

        cur.execute("COMMIT;")
        self._log("wei_update_tables", cur, "Les modifications suivantes ont été COMMITées %s" % str(operations))

    except psycopg2.Error as e:
        retcode = 904
        retmsg = "La modification de la base de données a échoué :\n" + e.pgerror

    if retcode != 0:
        self._send(None, retcode, retmsg)
        self._debug(2, u"Les tables WEI ont subi un ROLLBACK")
    else:
        self._send(None)
        self._debug(1, u"Les modifications ont été COMMITées")

def wei_modify(self, data):
    """
    Modifie les données d'une entrée des tables WEI à partir des données fournies

    ``data = [idwei, donnees]`` :

     * ``idwei`` : id de l'entrée à mettre à jour
     * ``donnees`` : un dictionnaire contenant les données à injecter dans la table

    """
    idwei = data[0]
    form = data[1]

    haswei = self._has_acl("wei_admin")
    inscriptions = self._has_acl("inscriptions")
    myself = self._has_acl("myself")
    preinscriptions = self._has_acl("preinscriptions")

    # Liste des champs autorisés pour l'insertion dans la base de données
    champs = [
        'idbde',
        'nom',
        'prenom',
        'tel',
        'urgence_nom',
        'urgence_tel',
        'mail',
        'annee',
        'dept',
        'paiement',
        'normalien',
        'conge',
        'pseudo',
        'pbsante',
        'bus',
        'role',
    ]

    # On vérifie que les champs du formulaire sont acceptables
    if not set(form.keys()).issubset(champs):
        self._send(None, 902, "Le formulaire n'est pas conforme : (%s) non reconnus" % repr(set(form.keys()).difference(champs)))
        self._debug(3, u"Formulaire d'inscription non conforme")
    elif not haswei:
        _pasledroit(self, "wei_admin")
    elif not form.keys():
        self._send(None)
        self._debug(3, u"Aucun champ modifié pour idwei #%d" % idwei)
    else:
        con, cur = BaseFonctions.getcursor()

        retcode = 0
        retmsg = u""

        formkeys = form.keys()

        requete = "UPDATE wei_vieux SET (%s)" % ",".join(formkeys)
        requete += " = (%%(%s)s)" % ")s,%(".join(formkeys)
        requete += " WHERE idwei=%(idwei)s;"

        form["idwei"] = idwei

        try:
            cur.execute(requete, form)
            cur.execute("COMMIT;")

        except psycopg2.Error as e:
            retcode = 904
            retmsg = "La modification de la base de données a échoué :\n" + e.pgerror

        if retcode != 0:
            self._send(None, retcode, retmsg)
            self._debug(2, u"Les tables WEI ont subi un ROLLBACK")
        else:
            self._send(None)
            self._debug(1, u"Les modifications ont été COMMITées")

def wei_modify1a(self, data):
    """
    Modifie les données d'une entrée des tables WEI à partir des données fournies

    ``data = [idwei, donnees]`` :

     * ``idwei`` : id de l'entrée à mettre à jour
     * ``donnees`` : dictionnaire contenant les données à injecter dans la table

    """
    idwei = data[0]
    form = data[1]

    haswei = self._has_acl("wei_admin")
    inscriptions = self._has_acl("inscriptions")
    myself = self._has_acl("myself")
    preinscriptions = self._has_acl("preinscriptions")

    # Liste des champs autorisés pour l'insertion dans la base de données
    champs = [
        'nom',
        'prenom',
        'genre',
        'adresse',
        'mail',
        'normalien',
        'tel',
        'urgence_nom',
        'urgence_tel',
        'dept',
        'note',
        'infos',
        'soge',

        'q_soirees',
        'q_alcools',
        'q_encadrement',
        'q_groupe',
        'q_sociable',
        'q_chants',

        'q_boire',
        'q_assos',
        'q_suiveur',
        'q_activites',
        'q_personnes',
        'q_conquetes',

        'q_mots',

        'petit_mot',
        'ml_evenements',
    ]

    # On vérifie que les champs du formulaire sont acceptables
    if not set(form.keys()).issubset(champs):
        self._send(None, 902, "Le formulaire n'est pas conforme : (%s) non reconnus" % repr(set(form.keys()).difference(champs)))
        self._debug(3, u"Formulaire d'inscription non conforme")
    elif not haswei:
        _pasledroit(self, "wei_admin")
    elif not form.keys():
        self._send(None)
        self._debug(3, u"Aucun champ modifié pour idwei #%d" % idwei)
    else:
        con, cur = BaseFonctions.getcursor()

        retcode = 0
        retmsg = u""

        formkeys = form.keys()

        requete = "UPDATE wei_1a SET (%s)" % ",".join(formkeys)
        requete += " = (%%(%s)s)" % ")s,%(".join(formkeys)
        requete += " WHERE idwei=%(idwei)s;"

        form["idwei"] = idwei

        try:
            cur.execute(requete, form)
            cur.execute("COMMIT;")

        except psycopg2.Error as e:
            retcode = 904
            retmsg = "La modification de la base de données a échoué :\n" + e.pgerror

        if retcode != 0:
            self._send(None, retcode, retmsg)
            self._debug(2, u"Les tables WEI ont subi un ROLLBACK")
        else:
            self._send(None)
            self._debug(1, u"Les modifications ont été COMMITées")

def wei_creer_note(self, idwei):
    """
        Crée une note à partir d'une inscription WEI pour 1A

        idwei est le numéro d'inscription WEI dans la table wei_1a

        _log relevant ids : idwei, id de la transaction d'adhésion, id de l'adhésion
    """
    # Droit WEI requis
    if not self._has_acl("wei_admin"):
        _pasledroit(self, "wei_admin")
        return

    con, cur = BaseFonctions.getcursor()

    # On récupère les infos de l'inscription
    cur.execute("SELECT * FROM wei_1a WHERE idwei=%s", (idwei,))

    inscription = dict(cur.fetchone())

    if inscription is None:
        self._send(None, 908, "L'inscription #%d n'existe pas dans les inscriptions 1A")
        self._debug(3, "%d introuvable dans wei_1a")
        return

    if inscription["adhere"]:
        self._send(None, 909, u"L'adhésion de %s %s a déjà été faite" % (inscription["prenom"], inscription["nom"],))
        return

    #
    # C'est ici que commence le gros du travail
    #

    # 0) On nettoie quelques infos et on en ajoute
    inscription["nom"] = inscription["nom"].title()
    inscription["prenom"] = inscription["prenom"].title()
    inscription["type"] = "personne"
    inscription["annee"] = BaseFonctions.adhesion_current_year()
    inscription["solde"] = 0
    inscription["pbsante"] = inscription["infos"]
    inscription["section"] = inscription["dept"]
    tomorrow = unicode(time.strftime("%Y-%m-%d", time.localtime(time.mktime(time.localtime()) + 3600*24)))
    inscription.update(**{"fonction": u"", "report_period":-1, "next_report_date": tomorrow, "bloque": False, "commentaire": u""})

    # 1) Le pseudo est-il disponible ?
    if not BaseFonctions.pseudo_libre(inscription["note"]):
        inscription["pseudo"] = BaseFonctions.default_pseudo(inscription["nom"], inscription["prenom"])
    else:
        inscription["pseudo"] = inscription["note"]

    # 2) On génère un mot de passe
    real_passwd, hashed_passwd = BaseFonctions.random_chain(7, 8)
    inscription["passwd"] = hashed_passwd

    # 3) On inscrit l'utilisateur dans la base de données
    cur.execute("""INSERT INTO comptes (type, pseudo, passwd, solde, nom, prenom, tel, mail, adresse, fonction, normalien, pbsante, report_period, next_report_date, bloque, commentaire)
                    VALUES (%(type)s, %(pseudo)s, %(passwd)s, 0, %(nom)s, %(prenom)s, %(tel)s, %(mail)s, %(adresse)s, %(fonction)s, %(normalien)s, %(pbsante)s, %(report_period)s, %(next_report_date)s, %(bloque)s, %(commentaire)s)
                    RETURNING idbde;""",
                inscription)

    # 4) On adhère l'adhérent pour la 1ère fois
    inscription["idbde"] = cur.fetchone()["idbde"]
    inscription["annee"] = BaseFonctions.adhesion_current_year()
    ids_credit_et_adh = _private_adhesion(self, inscription["idbde"], inscription["annee"], 0, inscription["section"], True, cur=cur)

    # 5) On lui envoie ses nouveaux identifiants
    mail.mail_inscription(inscription, real_passwd)

    cur.execute("UPDATE wei_1a SET adhere = TRUE WHERE idwei = %s;", (idwei,))

    # 6) C'est fait !
    self._log("wei_creer_note", cur, idwei, [idwei] + ids_credit_et_adh)
    cur.execute("COMMIT;")
    self._send(True)
    self._debug(1, u"%s %s est inscrit au BdE en tant que 1A !" % (inscription["prenom"], inscription["nom"]))

def wei_admin(self, data):
    """
        Traitement des paramètres du WEI modifiés par un GC WEI.
        data est un dictionnaire de paramètres avec les clés suivantes :
        *   wei_name (str)              :   Nom du WEI
        *   wei_contact (str)           :   Adresse de contact
        *   wei_begin (str)             :   Date de début du WEI
        *   wei_end (str)               :   Date de fin du WEI
        *   wei_1a_available (bool)     :   Ouverture des inscriptions 1A
        *   wei_vieux_available (bool)  :   Ouverture des inscriptions 2A+
        *   prix_wei_normalien (int)    :   Prix WEI normalien
        *   prix_wei_non_normalien (int):   Prix WEI non normalien
    """
    expected = {
        'wei_name' :  unicode,
        'wei_begin' : unicode,
        'wei_end' : unicode,
        'wei_contact' : unicode,
        'wei_1a_available' : bool,
        'wei_vieux_available' : bool,
        'prix_wei_normalien' : int,
        'prix_wei_non_normalien' : int,
    }

    if not isinstance(data, dict):
        _badparam(self, u"wei_admin")
        return
    elif not set(data.keys()).issubset(expected.keys()):
        _badparam(self, u"wei_admin")
        return
    elif not all([isinstance(data[key], expected[key]) for key in expected.keys()]):
        _badparam(self, u"wei_admin")
        return

    # Droit WEI requis
    if not self._has_acl("wei_admin"):
        _pasledroit(self, "wei_admin")
        return

    con, cur = BaseFonctions.getcursor()

    cur.execute("UPDATE configurations SET (wei_name, wei_begin, wei_end, wei_1a_available, wei_vieux_available, wei_contact, prix_wei_normalien, prix_wei_non_normalien) = (%(wei_name)s, %(wei_begin)s, %(wei_end)s, %(wei_1a_available)s, %(wei_vieux_available)s, %(wei_contact)s, %(prix_wei_normalien)s, %(prix_wei_non_normalien)s);", data)
    cur.execute("COMMIT;")

    self._send(True)
    self._debug(1, u"Paramètres du WEI modifiés")