Commit aff2cf43 authored by Maxime Bombar's avatar Maxime Bombar

Merge branch 'invites_pot' into 'master'

Invites pot

See merge request !6
parents 4a7d99de 24a13ad1
......@@ -285,7 +285,8 @@ class Server(object):
retrait = retirer
historique_transactions = ServeurFonctions.historique_transactions
historique2csv = ServeurFonctions.historique2csv
valider_transaction = ServeurFonctions.valider_transaction
devalider_transaction = ServeurFonctions.devalider_transaction
......@@ -322,6 +323,8 @@ class Server(object):
stats_entree_pot = ServeurFonctions.stats_entree_pot
liste_invites_entres = ServeurFonctions.liste_invites_entres
### Fonctions pour l'application WEI
wei_get_info = WeiFonctions.wei_get_info
......
......@@ -89,9 +89,9 @@ def _has_acl(self, access, surdroit=False, sousdroit=False):
def _myself(self, idbde=None):
"""Vérifie si l'utilisateur courant a accès à ce compte parce que c'est le sien.
NB : il doit aussi avoir le droit ``myself`` (comme ça on peut se l'enlever volontairement "pour laisser").
Appelé sans le paramètre idbde, répond simplement si l'utilisateur courant peut accéder à son propre compte.
"""
prerequis = self.userid != "special" and self._has_acl("myself")
if idbde is None:
......@@ -116,9 +116,9 @@ def _kill_session(self):
def _refresh_session(self, droit):
"""Met à jour les timestamps de dernière action et parfois le cache de droits.
Est appelée à chaque action effectuée par le client.
"""
if (self.userid == "special"):
key = self.username
......@@ -140,9 +140,9 @@ def _refresh_session(self, droit):
def _has_timeouted(self, droit="alive"):
"""Vérifie que l'utilisateur n'est pas inactif depuis trop longtemps
pour être encore autorisé à utiliser le droit ``droit``.
Avec ``droit = "alive"``, vérifie qu'il est encore authentifié.
"""
if (self.userid == "special"):
key = self.username
......@@ -156,7 +156,7 @@ def _has_timeouted(self, droit="alive"):
# Si le droit n'a encore jamais été utilisé, on va prendre le timestamp de alive comme référence
if not self.auth.last_action_timestamps[key].has_key(droit):
droit = "alive"
droit = "alive"
if not self.auth.last_action_timestamps[key].has_key("alive"):
# si on n'a jamais rien fait, alors on peut considérer qu'on n'a pas encore timouté
return False
......@@ -182,13 +182,13 @@ def _badparam(self, failcmd):
#################################################################
def hello(self, data):
"""Réponse à un hello.
* Transmet un ``"ok"`` si la version du client est acceptée. (Indispensable pour continuer la communication)
* Sinon, transmet la liste des versions acceptées.
* ``data = "<version du client>"``
* ``data = ["<version du client>", "<IP de l'utilisateur>"]``
Seules certaines IPs réelles sont de confiance et autorisées à "cafter" l'IP de l'utilisateur (notamment le client web)
"""
if not (isinstance(data, unicode) or (isinstance(data, list) and [type(i) for i in data] == [unicode, unicode])):
......@@ -260,13 +260,13 @@ def die(self):
def login(self, data):
"""``data = [<username>, <password>, "bdd"/"special", <masque>]``
Réponse à un login.
``<masque>`` = *acl qu'on ne* **veut pas** *avoir pour cette session.*
* Pour un "special", c'est une liste de droits
* Pour un "bdd", c'est une liste ``[liste_des_droits, liste_des_surdroits, bool_supreme]``
Vérifie que l'utilisateur existe et a les droits suffisants pour se loguer.
Transmet les informations sur le compte si c'est le cas.
C'est ici que sont rejetés les comptes limités à certaines IPs.
......@@ -312,7 +312,7 @@ def login(self, data):
else:
aledroit = (self.auth.has_acl(userbdd.idbde, "login") # sans précision il n'y a pas de masque appliqué
or self.auth.has_acl(userbdd.idbde, "login", surdroit=True))
if aledroit:
# On vérifie que le compte demandé n'est pas limité
if auth_type == "bdd" and userbdd.idbde in config.limited_accounts.keys():
......@@ -352,9 +352,9 @@ def login(self, data):
def adduser(self, data):
"""Ajoute/met à jour un utilisateur spécial.
``data = [<user>, <password>, <newacl>]`` (avec ``"-"`` en ``password`` pour le laisser inchangé).
"""
if not((type(data) == list) and (len(data) == 3)
and ([type(i) for i in data] == [unicode, unicode, list])
......@@ -414,11 +414,11 @@ def users(self):
def whowith(self, data):
"""Transmet la liste des utilisateurs connectés et leurs ip, port ( + username, userid).
En appliquant un filtre conditionnel sur ces attributs.
``data = {"ip" : <listip>, "userid" : <listid>, "username" : <listnames>, "client" : <listversions>}``, chacune des clés pouvant être absente.
Renvoie les utilisateurs tels que (``utilisateur.ip`` ∈ ``<listip>``) **ET** (``utilisateur.userid`` ∈ ``<listid>``) …
"""
# on vérifie qu'on n'a que des paramètres de recherche corrects
if not ( (type(data) == dict)
......@@ -458,7 +458,7 @@ def whowith(self, data):
def client_speak(self, data):
"""Envoie un message à un ``Server`` particulier.
Peut être appelée par un client (special user only).
"""
if not ((type(data) == list) and (len(data) == 2)
and (type(data[0]) == int)):
......@@ -483,7 +483,7 @@ def client_speak(self, data):
def client_broadcast(self, message):
"""Envoie un message à tous les clients connectés.
Peut être appelée par un client (special user only).
"""
if self._has_acl("broadcast"):
prefixe = "Broadcast from %s (%s) :\n" % (self.username, self.idServer)
......@@ -500,13 +500,13 @@ def client_broadcast(self, message):
def search(self, data):
"""Fait une recherche sur les comptes.
Peut nécessiter les droits full_search en fonction des champs demandés.
``data = [<flags>, <liste_de_fields>, <terme_de_recherche>]``
ou ``data = [<flags>, <dico {<field>: <terme_de_recherche>}>]``
* les flags possibles sont :
* ``o`` : cherche aussi dans les comptes qui ne sont pas à jour d'adhésion
* ``a`` : affiche les alias
* ``A`` : cherche aussi dans les alias
......@@ -516,15 +516,15 @@ def search(self, data):
* ``i`` : insensible à la casse (ILIKE)
* ``x`` : exact match (LIKE 'terme') (le comportement par défaut est LIKE '%terme%') (``x`` écrase ``b``)
* ``c`` : recherche conjonctive
* les fields possibles : idbde, pseudo, nom, prenom, mail, fonction, commentaire
* fields nécessitant full_search : tel, adresse, pbsante
Fait recherche sur tous les champs avec les options précisées par les flags.
Transmet ensuite la liste des [idbde, nom, prenom, pseudo, mail, solde, section] qui matchent.
Les idbde<0 sont ignorés.
"""
dicotypes = {"idbde": int, "type": unicode, "pseudo": unicode, "nom": unicode,
"prenom": unicode, "tel": unicode, "mail": unicode, "adresse": unicode,
......@@ -656,7 +656,7 @@ def _handle_duplicate_account(self,prenom, nom, email, comptes, from_function):
def generate_reset_password(self, data):
"""Envoie un mail contenant un lien permettant de réinitialiser le mot de passe du compte.
``data`` = [<prenom>, <nom>, <mail>]
"""
if not((type(data) == list)
......@@ -699,9 +699,9 @@ def generate_reset_password(self, data):
def confirm_reset_password(self, data):
"""Change le mot de passe grâce à un token reçu par mail.
``data`` = [<token>, <nouveau mot de passe>]
_log relevant ids : idbde
"""
if not((type(data) == list)
......@@ -744,9 +744,9 @@ def confirm_reset_password(self, data):
def confirm_email(self, data):
"""
Confirme l'adresse mail du compte grâce à un token reçu par mail.
``data`` = [<idbde>, <hash>]
_log relevant ids : idbde
"""
if not((type(data) == list)
......@@ -816,11 +816,11 @@ def historique_pseudo(self, data):
def search_historique_pseudo(self, data):
"""Effectue une recherche dans les historiques de pseudos,
même ceux qui ne référencent plus le compte.
``data = [<terme de recherche>, <filter "b", "x" ou "">]``
Transmet la liste de ceux qui ont matché.
"""
if not ((type(data) == list) and ([type(i) for i in data] == [unicode, unicode]) and data[1] in ["", "b", "x"]):
_badparam(self, u"search_historique_pseudo")
......@@ -848,9 +848,9 @@ def search_historique_pseudo(self, data):
def chgpass(self, data):
"""Change le mot de passe d'un compte.
``data = [<idbde>, <nouveau mdp>]`` *(non hashé)*
_log relevant ids : idbde
"""
if not((type(data) == list) and (len(data) == 2) and ([type(i) for i in data] == [int, unicode]) and (data[0] > 0)):
......@@ -878,9 +878,9 @@ def chgpass(self, data):
def update_compte(self, data):
"""``data = <un dictionnaire>``
Modifie le compte.
On ne fournit que les champs qu'on cherche à modifier. Les champs possibles sont :
* ``"idbde"`` : **ne peut pas être modifié**, sert à identifier le compte qu'on cherche à modifier.
* ``"type"`` : ``"personne"`` ou ``"club"``
......@@ -896,12 +896,12 @@ def update_compte(self, data):
* ``"pbsante"`` : problème de santé ou allergie alimentaire particulièr-e dont le BDE devrait avoir connaissance (pour le WEI, par exemple)
* ``"droits"`` : liste des droits
* ``"surdroits"`` : liste des surdroits
* ``"report_period"`` : durée (en minutes) entre deux rapports. (-1 = jamais, 0 = dès qu'une transaction a lieu)
* ``"report_period"`` : durée (en minutes) entre deux rapports. (-1 = jamais, 0 = dès qu'une transaction a lieu)
* ``"next_report_date"`` : date du prochain rapport mail (cf :py:func:`BaseFonctions.isPgsqlDate` pour le format de date)
* ``"bloque"`` : si vrai, le compte ne peut plus effectuer de transactions
* ``"section"`` : section pour l'année en cours
* ``"commentaire"`` : random garbage
_log relevant ids : idbde
"""
if not ((type(data) == dict)
......@@ -1099,10 +1099,10 @@ def update_compte(self, data):
def update_photo(self, data):
"""``data = [<idbde>, <la photo base64-encodée>, <format de la photo>]``
Range la photo dans le répertoire des photos après resize/conversion.
Insulte si le format de photo n'est pas pris en charge ou si sa taille est trop grande.
"""
if not((type(data) == list) and ([type(i) for i in data] == [int, unicode, unicode])):
_badparam(self, u"update_photo")
......@@ -1166,9 +1166,9 @@ def update_photo(self, data):
def get_last_modified_photo(self, data):
"""``data = <idbde>``
Transmet la date (timestamp unix) de dernière modification de la photo n°``<idbde>``.
"""
if not(type(data) == int):
_badparam(self, u"get_last_modified_photo")
......@@ -1249,10 +1249,10 @@ def compte(self, data):
def preinscrire(self, dico):
"""Enregistre une préinscription.
Les données sont envoyées sous forme d'un dico ``{"champ": <valeur>}``
Vérifie que les champs indispensables (``"nom"``, ``"prenom"`` et ``"mail"``) sont corrects.
_log relevant ids : preid
"""
dicotypes = {"type": unicode, "nom": unicode, "prenom": unicode, "tel": unicode, "mail": unicode,
......@@ -1320,9 +1320,9 @@ def preinscrire(self, dico):
def get_preinscription(self, data):
"""``data = <preid>``
Transmet les informations d'une préinscription.
"""
if not (type(data) == int) and (data > 0):
_badparam(self, u"get_preinscription")
......@@ -1354,9 +1354,9 @@ def get_preinscriptions(self):
def del_preinscription(self, data):
"""``data = <preid>``
Supprime une préinscription.
_log relevant ids : preid
"""
if not(type(data) == int and data > 0):
......@@ -1375,9 +1375,9 @@ def del_preinscription(self, data):
def get_default_pseudo(self, data):
"""``data = [<nom>, <prénom>]``
Transmet le résultat de la génération du pseudo pour ce couple (nom, prénom).
"""
if not((type(data) == list) and ([type(i) for i in data] == [unicode] * 2)):
_badparam(self, u"get_default_pseudo")
......@@ -1392,13 +1392,13 @@ def get_default_pseudo(self, data):
def _private_adhesion(self, idbde, annee, debit, section, wei=False, cur=None):
"""Adhère ``idbde`` pour l'année ``annee``.
Enregistre la transaction ``"Adhésion"`` et l'adhésion.
Update le solde sans faire de vérification. (crédite la note 0).
Retourne l'id de la transaction d'adhésion et celui de l'adhésion elle-même.
Si on l'appelle avec ``cur=<un_curseur>``, ce curseur est utilisé et n'est pas COMMITé à la fin.
"""
if cur == None:
con, cur = BaseFonctions.getcursor()
......@@ -1421,35 +1421,35 @@ def _private_adhesion(self, idbde, annee, debit, section, wei=False, cur=None):
def inscrire(self, data):
"""
Deux possibilités :
* ``data = [<ident>, <dico>, <pay>, <from_wei>]``
* ``data = [<ident>, <dico>, <pay>, <from_wei>, <override_adh>]``
Si <from_wei> est faux, <ident> est une <preid>
* Valide une préinscription.
** ``<preid>`` est l'identifiant de préinscription,
** ``<dico>`` contient des tas d'infos (``"wei"`` et ``"annee"`` étant obligatoires)
** ``<pay> = [<on_note>, <type_de_paiement>, <params>]``, avec :
** ``<on_note>`` = solde à ajouter à la note (en centimes)
** ``<type_de_paiement>`` à valeur dans ``"cheque", "especes", "virement", "soge"``
** ``params = {"nom": <nom>, "prenom": <prenom>, "banque": <banque>}``
** ``<overripde_adh>`` est le montant qu'on veut que l'adhérent paye pour son inscription
(facultatif, nécessite le droit ``"adhesions_admin"`` si différent du montant par défaut)
Sinon <ident> est un <idwei> :
** <idwei> est l'identifiant du wei
** <dico> contient des tas d'infos
** ``<pay> = [<on_note>, <type_de_paiement>, <params>]``, avec : plus tard ....
_log relevant ids : preid, idbde, id de la transaction de crédit (ou NULL),
id de moyen de paiement (ou NULL), id de la transaction d'adhésion (ou NULL), id de l'adhésion (ou NULL)
"""
dicotypes = {"type": unicode, "nom": unicode, "prenom": unicode, "mail": unicode,
"pseudo": unicode, "passwd": unicode, "normalien": unicode, "fonction": unicode,
......@@ -1544,7 +1544,7 @@ def inscrire(self, data):
else:
# Si rien n'est proposé, il faut lui créer son pseudo par défaut
pre_dico["pseudo"] = BaseFonctions.default_pseudo(pre_dico["nom"], pre_dico["prenom"])
# Et lui générer un mot de passe
# Et lui générer un mot de passe
real_passwd, hashedpass = BaseFonctions.random_chain(7, 8)
# Le clair, on lui enverra par mail dès qu'on connaîtra son idbde
# Le hashé, on le mettra dans la base
......@@ -1635,7 +1635,7 @@ def __price_today(self):
if __in_cheap_period(self):
return prix_adhesion_late
else:
return prix_adhesion
return prix_adhesion
def get_tarifs_adhesion(self):
"""Envoie les prix des adhésions avec ou sans WEI."""
......@@ -1654,16 +1654,16 @@ def get_tarifs_adhesion(self):
def readherer(self, data):
"""Effectue une réadhésion.
``data`` = un dico
* Clés obligatoires : ``"idbde"``, ``"section"``.
* Clé facultative : ``"wei"``, ``"pay"``
* ``pay`` = un dico.
* Clé obligatoire : ``"type"`` (``"especes"``, ``"cheque"``, ``"virement"``)
* Clés conditionnelles : ``"prenom"``, ``"nom"``, ``"banque"`` (à fournir si type est ``"cheque"`` ou ``"virement"``)
* Clés facutatives : ``"montant"`` (par défaut, vaudra le montant de l'adhésion)
_log relevant ids : idbde, id de la transaction de crédit pré-adhésion (ou NULL),
id du moyen de paiement (ou NULL), id de la transaction d'adhésion, id de l'adhésion
"""
......@@ -1725,16 +1725,16 @@ def readherer(self, data):
else:
self._debug(3, u"réadhésion de %s pour %s failed : déjà %s adhésion pour ces données." % (idbde, annee, nb))
self._send(None, 14, u"%s a déjà adhéré pour l'année %s." % (idbde, annee))
def supprimer_compte(self, data):
"""
Place le champ ``deleted`` du compte à ``true``.
data = ``<idbde>`` ou ``[<idbde>, True]``.
Échoue si le solde du compte est non nul.
Si le deuxième paramètre est à True, anonymise le compte.
_log relevant ids : idbde
"""
if isinstance(data, int):
......@@ -1760,20 +1760,20 @@ def supprimer_compte(self, data):
self._debug(3, u"supprimer_compte : erreur : %s a un solde non nul." % (idbde))
self._send(None, 410, u"Tu ne peux pas supprimer ce compte, car son solde est non nul.")
return
# On vérifie si le compte à supprimer n'a pas plus de droits que l'utilisateur courant (vite)
if not BaseFonctions.hasMoreRights(Compte(ReadDatabase.get_compte(self.userid)), compte):
self._debug(3, u"supprimer_compte : erreur : %s a plus de droits que %s." % (idbde, self.userid))
self._send(None, 411, u"Ce compte a trop de droits.")
return
if anonymise:
compte.anonymise()
con, cur = BaseFonctions.getcursor()
compte.deleted = True
compte.save(cur)
self._log("supprimer_compte", cur, data, [idbde])
cur.execute("COMMIT;")
self._debug(1, u"compte %s supprimé." % (idbde))
......@@ -1835,9 +1835,9 @@ def get_boutons(self, search_et_categ):
def get_un_bouton(self, data):
"""``data = <id>``
Transmet les informations sur le bouton n°``<id>``.
"""
if not((type(data) == int) and (data > 0)):
_badparam(self, u"get_un_bouton")
......@@ -1886,15 +1886,15 @@ def get_clubs(self):
def create_bouton(self, data):
"""
``data = {"label" : <nom du bouton>, "montant" : <prix en centimes>, "destinataire" : <idbde du compte à créditer>, "categorie" : <nom de la catégorie>, "affiche" : <booléen afficher le bouton ?>, "description" : <description du bouton>, "consigne" : <booléen est-ce une bouteille consignée ?> }``
Champs obligatoires : label, montant, destinataire, categorie
Valeur par défaut des champs facultatifs : affiche : ``True``, description : ``""``, consigne : ``False``
Ajoute un bouton. La catégorie doit déjà exister.
*(créer des catégories doit se faire en accès direct à la base)*
_log relevant ids : idbouton
"""
champs_obligatoires = ["label", "montant", "destinataire", "categorie"]
......@@ -1960,9 +1960,9 @@ def create_bouton(self, data):
def update_bouton(self, data):
"""
``data`` = un dictionnaire contenant au moins la clé ``"id"`` et pouvant contenir les clés de ``create_bouton``.
Édite le bouton ``data["id"]``.
_log relevant ids : idbouton
"""
dicotypes = {"id": int, "label": unicode, "montant": int, "destinataire": int, "categorie": unicode,
......@@ -2023,7 +2023,7 @@ def update_bouton(self, data):
def delete_bouton(self, ident):
"""
Supprime le bouton n°``ident``.
_log relevant ids : idbouton
"""
if not(type(ident) == int):
......@@ -2041,12 +2041,12 @@ def delete_bouton(self, ident):
def _insert_transaction(self, typ, idemetteur, iddestinataire, qte, montant, description, categorie, valide, cantinvalidate=False, cur=None):
"""Met une transaction dans la table et update les soldes émetteur et destinataire si ``valide = True``.
Ne sert qu'à factoriser du code et ne fait absolument aucune vérification.
Renvoie l'id de la transaction.
*Si on l'appelle avec ``cur=<un_curseur>``, celui-ci est utilisé et n'est pas COMMITé à la fin.*
"""
# Comme on ne fait aucune vérification, mais qu'on n'a quand même pas totalement
# confiance en l'appelant, on va faire le tout dans un try
......@@ -2087,24 +2087,24 @@ def _une_transaction(self, typ, idemetteur, iddestinataire, qte, montant, descri
cantinvalidate=False, cur=None):
"""Effectue la transaction demandée. Ne peut pas être appelée par le client.
Ne fait pas de vérification de droits.
Si l'émetteur a un solde trop faible, et que l'utilisateur
courant n'a pas les droits nécessaires, la transaction est enregistrée en ``valide = false``.
Ne log rien, ne debug rien (c'est le rôle des fonctions appelantes).
Renvoie une paire :
* une chaîne de la forme ``"{ok|failed} : {normal|forced|overforced}[ needed]"``
* l'id de la transaction
On peut l'appeler avec ``doitanyway`` à ``True`` et alors, pour peu que les comptes existent,
on fera la transaction, même si les comptes ne sont pas à jour d'adhésion
ou si les droits forced/overforced ne sont pas présents. (Utile pour les adhésions)
Si ``justtesting`` est à ``True``, la transaction n'est pas insérée, on répond juste si elle aurait pu être faite.
*Si on l'appelle avec ``cur=<un_curseur>``, il est utilisé et n'est pas COMMITé à la fin.*
"""
# Le typ est limité
if not(typ in config.types_transactions):
......@@ -2236,7 +2236,7 @@ def _un_credit_ou_un_retrait(self, retrait, mode, compte, montant, commentaire,
result, idtransaction = _une_transaction(self, doingwhat, idem, iddest, 1, montant, commentaire,
doingwhat.title(), acl_forced, acl_overforced, doitanyway=doitanyway, cur=cur)
success = (result.split()[0] == "ok")
log_ids = [idem, iddest, idtransaction]
# Si il y a une table liée
if table:
......@@ -2277,25 +2277,25 @@ def _un_credit_ou_un_retrait(self, retrait, mode, compte, montant, commentaire,
def _un_credit(self, mode, destinataire, montant, commentaire, params_pay={}, doitanyway=False, cur=None):
"""Aucune vérification, effectue vraiment le crédit.
Ne peut pas être appelée par le client.
Update en conséquence les soldes de -1, -2, -3 et du destinataire.
Crée le cheque ou le virement si besoin.
* ``mode`` = ``"cheque"``, ``"especes"``, ``"virement"`` ou ``"soge"``
* ``params_pay = {"nom": "Passoire", "prenom": "Toto", "banque": s"sogé"}``
"""
return _un_credit_ou_un_retrait(self, False, mode, destinataire, montant, commentaire, params_pay, doitanyway, cur=cur)
def crediter(self, data):
"""``data = [<iddestinataire>, <montant>, <typ_paiement>, <params_pay>]``
Fait un crédit (pas de possibilité de faire plusieurs crédits à la fois).
``<params_pay> = {"nom": <nom>, "prenom": <prénom>, "banque": <banque>, ["comm"/"commentaire"/"motif" : "plouf plouf"]}``
(``<params_pay>`` peut rester vide pour un crédit espèces)
_log relevant ids : idbde du destinataire, id de la transaction, id du moyen de paiement (ou NULL)
"""
if not((type(data) == list) and (len(data) == 4)
......@@ -2360,9 +2360,9 @@ def _une_conso(self, successes, idcompte, idbouton, qte, forced=False, overforce
"""
Fait consommer un bouton à un compte.
Ne peut pas être appelée par le client.
Ne fait pas de vérification de droits (fait seulement des choses différentes en fonction de forced/overforced/rien).
_log relevant ids : idemetteur, iddestinataire, idbouton, idtransaction
"""
# On va d'abord chercher les objets en question
......@@ -2410,12 +2410,12 @@ def _une_conso(self, successes, idcompte, idbouton, qte, forced=False, overforce
def consos(self, data):
"""``data`` = liste de ``[<idbouton>, <idcompte>, <quantité>]``
Fait consommer tous les boutons à tous les comptes.
Transmet une liste de ``[<retcode>, [<idbouton>, <idbde>], <errmsg>]`` correspondant au succès
des différentes transactions demandées.
"""
if not((type(data) == list) and (len(data) > 0)
and ([type(i) for i in data] == [list] * len(data))
......@@ -2464,10 +2464,10 @@ def _un_transfert(self, successes, idemetteur, iddestinataire, montant, qte, mot
"""
Effectue un seul transfert.
Ne peut pas être appelée par le client.
Ne fait pas de vérification de droits (fait seulement des choses différentes en fonction de
forced/overforced/rien). Renvoie quand même un échec sur des montants<0.
_log relevant ids : idemetteur, iddestinataire, idtransaction
"""
# On vérifie montant >= 0
......@@ -2523,12 +2523,12 @@ def _un_transfert(self, successes, idemetteur, iddestinataire, montant, qte, mot
def transferts(self, data):
"""``data = [<liste_d'émetteurs>, <liste_de_recepteurs>, <montant>, <motif>]``
Effectue le même transfert de chacun des émetteurs vers chacun des destinataires.
Transmet une liste de ``[<retcode>, [<emetteur>, <destinataire>], <errmsg>]`` correspondant au succès
des différentes transactions (autant que de #émetteurs * #destinataires).
"""
if not((type(data) == list)
......@@ -2598,10 +2598,10 @@ def _un_don(self, successes, iddestinataire, montant, motif):
"""
Effectue un seul don.
Ne peut pas être appelée par le client.
Ne fait pas de vérification de droits, empêche juste de finir en négatif.
Renvoie quand même un échec sur des montants<0.
_log relevant ids : idemetteur, iddestinataire, idtransaction
"""
# On commence par vérifier qu'on est pas un special user
......@@ -2647,12 +2647,12 @@ def _un_don(self, successes, iddestinataire, montant, motif):
def dons(self, data):
"""``data = [<liste_de_destinataires>, <montant>, <motif>]``
Effectue le même don vers chacun des destinataires.
Renvoie une liste de ``[<retcode>, <iddestinataire>, <errmsg>]`` correspondant
au succès des différentes transactions (une par destinataire).
"""
if not((type(data) == list)
and (len(data) == 3)
......@@ -2707,25 +2707,25 @@ def dons(self, data):
def _un_retrait(self, mode, emetteur, montant, commentaire, params_pay={}):
"""Aucune vérification, effectue vraiment le retrait.
Ne peut pas être appelée par le client.
Update en conséquence les soldes de -1, -2, -3 et de l'émetteur.
Crée le cheque ou le virement si besoin. (en ``retrait = true``)
* ``mode`` = ``"cheque"``, ``"especes"`` ou ``"virement"``
* ``paramas_pay = {"nom": "Passoire", "prenom": "Toto", "banque": "sogé"}``
"""
_un_credit_ou_un_retrait(self, True, mode, emetteur, montant, commentaire, params_pay, doitanyway=False)
def retirer(self, data):
"""``data = [<idemetteur>, <montant>, <typ_paiement>, <params_pay>]``
Fait un retrait (pas de possibilité de faire plusieurs retraits à la fois).
``<params_pay> = {"nom": <nom>, "prenom": <prénom>, "banque": <banque>, ["comm"/"commentaire"/"motif" : "plouf plouf"]}``
(``<params_pay>`` peut rester vide pour un retrait espèces).
"""
if not((type(data) == list) and (len(data) == 4)
and (type(data[0]) == type(data[1]) == int)
......@@ -2778,9 +2778,9 @@ def retirer(self, data):
def alias(self, data):
"""
``data = [<idbde>, <alias>]``
Ajoute un alias à un compte.
_log relevant ids : idbde, idalias
"""
if not ((type(data) == list)
......@@ -2818,10 +2818,10 @@ def alias(self, data):
def unalias(self, data):
"""
``data = [<id>, <booléen all>]``
* Si ``all = False`` : supprime l'alias d'id ``<id>``
* Si ``all = True`` : supprime tous les alias du compte d'idbde ``<id>``