[gest_crans_lc] Menu vente. Il manque l'éditon de solde via lc_ldap

En effet, il faut faire un truc propre pour éditer le solde, avec un lock
pour éviter les éditions concurrente entrainant des valeurs du solde incohérente.
du coup, pour le moment, quand on essaye (via le menu vente) ça lève une erreur.
Mais il ne manque que ça, ça doit pouvoir se faire.
This commit is contained in:
Valentin Samir 2014-03-23 20:33:04 +01:00
parent d017ddb44e
commit 0b9635a91d

View file

@ -17,6 +17,7 @@ import os
import sys
import ssl
import time
import copy
import ldap
import signal
import inspect
@ -31,6 +32,7 @@ from gestion.cert_utils import createCertRequest
from gestion.affich_tools import get_screen_size, coul
from gestion.chgpass import checkpass
import gestion.config as config
import gestion.config.factures
import lc_ldap.shortcuts
import lc_ldap.objets as objets
@ -142,6 +144,12 @@ class TailCall(object) :
def __str__(self):
return "TailCall<%s(%s%s%s)>" % (self.call.func_name, ', '.join(repr(a) for a in self.args), ', ' if self.args and self.kwargs else '', ', '.join("%s=%s" % (repr(k),repr(v)) for (k,v) in self.kwargs.items()))
def copy(self):
''' Patch the deepcopy dispatcher to pass modules back unchanged '''
result = TailCall(self.call, *list(self.args), **dict(self.kwargs))
result.stacklvl = self.stacklvl
return result
def __call__(self, *args, **kwargs):
self.kwargs.update(kwargs)
self.args = self.args + args
@ -251,6 +259,17 @@ class GestCrans(object):
self.dialog_last_access = time.time()
return self._dialog
def nyan(self, cont, *args, **kwargs):
(lines, cols) = get_screen_size()
print "\033[48;5;17m"
print " "*(lines * cols)
cols = int(min(cols/2, 65))
lines = int(lines) -1
cmd = "/usr/bin/nyancat -W %s -H %s" % (cols, lines)
os.system(cmd)
raise Continue(cont)
@tailcaller
def handle_dialog(self, cancel_cont, box, *args):
ctrlC=False
@ -2469,9 +2488,184 @@ les valeurs valident sont :
self.dialog.msgbox("todo", width=0, height=0)
return cont
def proprio_vente(self, proprio, cont):
self.dialog.msgbox("todo", width=0, height=0)
return cont
@tailcaller
def proprio_vente_set(self, article, cont):
def box():
if article['pu'] == '*':
return self.dialog.inputbox(title="Montant pour %s ?" % article['designation'],
text="", init=str(article.get('nombre','')), timeout=self.timeout, width=70)
else:
return self.dialog.inputbox(title="Nombre de %s ?" % article['designation'],
text="", timeout=self.timeout, init=str(article.get('nombre','1')), width=70)
def todo(article, output, cont):
article['nombre']=output
# Il faut entrer quelque chose
if not output:
raise ValueError("Merci d'entrer une valeur")
# Vérification des centimes
if article['pu'] == '*' and '.' in output:
if len(output.split('.', 1)[1])>2:
raise ValueError("Les centimes, c'est seulement deux chiffres après la virgule")
typ = float if article['pu'] == '*' else int
# Vérification du type de l'entré
try:
output=typ(output)
except ValueError:
raise ValueError("Merci d'entrez seulement des nombres")
# On définis le nombre d'entrée. Pour pu=* il y aura du trairement à faire
# avant de générer la facture : mettre pu à nombre et nombre à 1
# on le met comme ça pour pouvoir naviger aisément entre les écrans dialog
article['nombre'] = output
return article
(code, output) = self.handle_dialog(cont, box)
self_cont = TailCall(self.proprio_vente_set, article=article, cont=cont)
return self.handle_dialog_result(
code=code,
output=output,
cancel_cont=cont,
error_cont=self_cont,
codes_todo=[([self.dialog.DIALOG_OK], todo, [article, output, cont])]
)
@tailcaller
def proprio_vente(self, proprio, cont, tags=[], tag_paiment=None, to_set=[], have_set=[]):
box_paiement = {
"liquide" : "Espèces",
"cheque" : "Chèque",
"solde" : "Solde Crans (actuel : %s€)",
}
def box_choose_item(tags):
choices = []
for code, article in gestion.config.factures.items.items():
choices.append((code, u"%s%s" % (article['designation'], (u' (%s€)' % article['pu']) if article['pu'] != '*' else ""), 1 if code in tags else 0))
return self.dialog.checklist(
text="",
title="Vente de truc à %s %s" % (proprio.get("prenom", [''])[0], proprio["nom"][0]),
choices=choices,
timeout=self.timeout)
def box_choose_paiment(tag, articles):
box_paiement_order = ["liquide", "cheque"]
if "cransAccount" in proprio['objectClass']:
if not "SOLDE" in [art['code'] for art in articles]:
box_paiement_order.append("solde")
box_paiement["solde"] = box_paiement["solde"] % proprio["solde"][0]
choices = []
for key in box_paiement_order:
choices.append((key, box_paiement[key], 1 if key == tag else 0))
return self.dialog.radiolist(
text="",
title="Choix d'un mode de paiement pour %s %s" % (proprio.get("prenom", [''])[0], proprio["nom"][0]),
choices=choices,
timeout=self.timeout)
def choose_item(proprio, tags, articles, self_cont):
to_set=[]
for tag in tags:
articles[tag]['code']=tag
to_set.append(articles[tag])
raise Continue(self_cont(to_set=to_set, have_set=[]))
def number_of_items(to_set, have_set, self_cont):
# Où faut-il aller si l'utilisateur appuis sur annuler
if not have_set:
lcont = self_cont(to_set=[])
else:
lcont = self_cont(to_set=[have_set[-1]] + to_set, have_set=have_set[:-1])
art = self.proprio_vente_set(to_set[0], cont=lcont)
if not to_set[1:]:
total = 0
line=1
text=u"Résumé :\n"
for article in have_set + [art]:
if article['pu'] == '*':
total += article['nombre']
text+=u" * %s pour %s\n" % (article['designation'], article['nombre'])
else:
total += article['nombre']*article['pu']
text+=u" * %dx %s à %s\n" % (article['nombre'], article['designation'], article['pu'])
line+=1
text+=u"Total à payer : %s" % total
self.dialog.msgbox(text=text,
title="Résumé de la facture à payer",
width=70, height=5+line, timeout=self.timeout)
return self_cont(to_set=to_set[1:], have_set=have_set + [art])
def choose_paiment(have_set, tag, proprio, lcont, self_cont, cont):
if not tag:
raise ValueError("Il faut choisir un moyen de paiement")
code, comment = self.dialog.inputbox(text="Détail pour les espèce, nom de la note ou banque du chèque", title="Commentaire", width=70, timeout=self.timeout)
if code != self.dialog.DIALOG_OK:
raise Continue(self_cont)
if not comment:
raise ValueError("Commentaire nécessaire")
articles = copy.deepcopy(have_set)
for article in articles:
if article['pu'] == '*':
article['pu'] = article['nombre']
article['nombre'] = 1
with self.conn.newFacture(proprio.dn, {}) as facture:
facture['modePaiement']=unicode(tag, 'utf-8')
facture['article']=articles
facture['info']=unicode(comment, 'utf-8')
if self.confirm_item(item=facture,
text=u"Le paiement de %s€ a-t-il bien été reçu (mode : %s) ?\n" % (facture.total(), tag),
title=u"Validation du paiement",
timeout=self.timeout):
# Appeler créditer va créditer ou débiter le solde, sauver le proprio et créer la facture
facture.crediter()
arts = ["%s %s" % (art['nombre'], art['designation']) for art in facture['article'] if art['code'] != 'SOLDE']
if arts:
self.dialog.msgbox(
text=u"Vous pouvez remettre à l'adherent les articles (si se sont des articles) suivant :\n * %s" % '\n * '.join(arts),
title=u"Vente terminée",
width=0, height=0, timeout=self.timeout)
if tag == "solde":
self.dialog.msgbox(text=u"Le solde de l'adhérent à bien été débité", title="Solde débité", width=0, height=0, timeout=self.timeout)
if [a for a in facture['article'] if art['code'] == 'SOLDE']:
self.dialog.msgbox(text=u"Le solde de l'adhérent à bien été crédité", title="Solde crédité", width=0, height=0, timeout=self.timeout)
else:
self.dialog.msgbox(text=u"Le paiement n'ayant pas été reçue\nla vente est annulée", title="Annulation de la vente", width=0, height=0, timeout=self.timeout)
raise Continue(cont)
self_cont=TailCall(self.proprio_vente, proprio=proprio, cont=cont, tags=tags, tag_paiment=tag_paiment, to_set=to_set, have_set=have_set)
# S'il y a des article dont il faut définir la quantité
if to_set:
return self.handle_dialog_result(
code=self.dialog.DIALOG_OK,
output=None,
cancel_cont=None,
error_cont=self_cont,
codes_todo=[([self.dialog.DIALOG_OK], number_of_items, [to_set, have_set, self_cont])]
)
# Sinon, si tous les quantités de tous les articles sont définis
elif have_set:
lcont = self_cont.copy()
lcont(to_set=[have_set[-1]] + to_set, have_set=have_set[:-1])
(code, tag) = self.handle_dialog(lcont, box_choose_paiment, tag_paiment, have_set)
self_cont=self_cont(tag_paiment=tag)
lcont(tag_paiment=tag)
return self.handle_dialog_result(
code=code,
output=tag,
cancel_cont=lcont,
error_cont=self_cont,
codes_todo=[([self.dialog.DIALOG_OK], choose_paiment, [have_set, tag, proprio, lcont, self_cont, cont])]
)
# Sinon, on propose des articles à chosir
else:
(code, tags) = self.handle_dialog(cont, box_choose_item, tags)
self_cont=self_cont(tags=tags, have_set=[], to_set=[], tag_paiment=None)
return self.handle_dialog_result(
code=code,
output=tags,
cancel_cont=cont,
error_cont=self_cont,
codes_todo=[([self.dialog.DIALOG_OK], choose_item, [proprio, tags, copy.deepcopy(gestion.config.factures.items), self_cont])]
)
def create_adherent(self, cont):
def mycont(adherent=None, **kwargs):
@ -2561,7 +2755,7 @@ les valeurs valident sont :
'aMC': {'text':"Ajouter une machine à un club", 'callback': self.create_machine_club},
#'dC' : {'text':"Détruire un club", 'callback': self.delete_club},
'aKM': {'text':"Ajouter une machine à l'association", 'callback': self.create_machine_crans},
'' : {'text':"---------------------------------------",'callback': None},
'' : {'text':"---------------------------------------",'callback': self.nyan},
}
### Les clef qui n'existe pas sont toute renvoyé sur la clef ''
#menu_order = ["aA", "mA", "aMA", "dA", "", "mM", "dM", " ", "aC", "mC", "aMC", "dC", " ", "aKM"]