From 7b56a156857fa0fcc06d9da1dd315e16767a803d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Elliott=20B=C3=A9cue?= Date: Tue, 23 Jun 2015 17:25:12 +0200 Subject: [PATCH] =?UTF-8?q?La=20modification=20du=20solde=20cr=C3=A9e=20un?= =?UTF-8?q?e=20facture,=20et=20on=20enl=C3=A8ve=20solde=20de=20vente.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gestion/config/factures.py | 5 - gestion/gest_crans.py | 233 ++++++++++++++++++++++--------------- gestion/ldap_crans.py | 2 +- 3 files changed, 139 insertions(+), 101 deletions(-) diff --git a/gestion/config/factures.py b/gestion/config/factures.py index 27f1ae9a..a56df76a 100644 --- a/gestion/config/factures.py +++ b/gestion/config/factures.py @@ -20,11 +20,6 @@ ITEMS = { 'designation': u'Reliure plastique', 'pu': 0.12, }, - 'SOLDE': { - 'designation': u'Rechargement du solde', - 'pu': '*', - 'imprimeur': True, - }, 'PULL_ZIP_MARK': { 'designation': u'Zipper marqué', 'pu': 39.18, diff --git a/gestion/gest_crans.py b/gestion/gest_crans.py index 7d0d95ac..e3b04507 100755 --- a/gestion/gest_crans.py +++ b/gestion/gest_crans.py @@ -24,7 +24,7 @@ To = ['root@crans.org'] import string import os import sys -import dialog +import dialog as dialog_module from whos import aff import signal import getopt @@ -47,7 +47,7 @@ isdeconnecteur = user_tests.isdeconnecteur() db = crans_ldap() droits = db.search("uid=%s" % script_utilisateur)['adherent'][0].droits() -isimprimeur = u"Imprimeur" in droits +isimprimeur = u"Imprimeur" in droits iscontroleur = u'Tresorier' in droits isbureau = u'Bureau' in droits encoding = sys.stdin.encoding or 'UTF-8' @@ -62,13 +62,13 @@ if u'Nounou' in droits: # Sinon on utilise celui du système. DIALOGRC = '/etc/dialog.rc' - dlg = dialog.Dialog(DIALOGRC=DIALOGRC) + dlg = dialog_module.Dialog(DIALOGRC=DIALOGRC) else: # Si on est pas nounou, on est libre de faire ce que l'on veut avec la # variable d'environnement DIALOGRC. DIALOGRC = '' - dlg = dialog.Dialog() + dlg = dialog_module.Dialog() def dialog(arg): @@ -264,7 +264,7 @@ def set_etudes(adher): arg += u'"Autre" ""' annul, result = dialog(arg) if annul: return 1 - elif etudes[0] in [ 'P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7', 'P8', 'P9', 'P10', 'P11', 'P12', 'P13' ]: + elif etudes[0] in ['P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7', 'P8', 'P9', 'P10', 'P11', 'P12', 'P13']: arg += u'--default-item "%s" ' % adher.etudes(1) arg += u'--menu "Choisissez l\'année administrative" 0 0 0 ' arg += u'"Deug 1" "Deug 1ère année" ' @@ -664,9 +664,11 @@ def set_droits(adher): # Droits supprimés qui abonnaient à une ML old_mls = [] for droit in diff: - old_mls.extend([m for m in droits_mls.keys() - if m[0] == '+' and droit in droits_mls[m] - and m not in old_mls]) + old_mls.extend([ + m for m in droits_mls.keys() + if m[0] == '+' and droit in droits_mls[m] + and m not in old_mls + ]) # MLs pour lesquelles un autre droit abonne encore for droit in new: @@ -689,8 +691,10 @@ def set_droits(adher): del_mls.append(resml.strip()) if del_mls: - db.services_to_restart('desabonner_ml', - map(lambda m: "%s$%s" % (adher.mail(), m), resultmls)) + db.services_to_restart('desabonner_ml', [ + "%s$%s" % (adher.mail(), mailing_list) + for mailing_list in resultmls + ]) # On modifie ! e = None @@ -722,7 +726,7 @@ def set_actif(adher): checklist.append(u'"1" "Compte mail/serveur désactivé" "%s"' % (inactif)) # Il y a qqch de modifiable, on construit la checklist - arg = u'--title "Statut du compte %s" ' % adher.Nom() + arg = u'--title "Statut du compte %s" ' % adher.Nom() arg += u'--separate-output ' arg += u'--checklist "" 0 0 0 ' arg += u' '.join(checklist) @@ -841,23 +845,23 @@ def set_imprimeurs(club): break if not choix: # Redemande le choix - cprint (u'Choix invalide') + cprint(u'Choix invalide') continue if choix: break if not choix: continue - arg = u'--title "Enlever un imprimeur" ' + arg = u'--title "Enlever un imprimeur" ' arg += u'--yesno "Enlever l\'imprimeur %s ? \n\n" 0 0' % choix.Nom() no, res = dialog(arg) if not no: if club.imprimeurs(retirer=str(choix.id())): - arg = u'--title "Enlever un imprimeur" ' + arg = u'--title "Enlever un imprimeur" ' arg += u'--msgbox "Imprimeur enlevé\n\n\n" 0 0' dialog(arg) else: - arg = u'--title "Enlever un imprimeur" ' + arg = u'--title "Enlever un imprimeur" ' arg += u'--msgbox "Cet adhérent n\'est pas imprimeur du club !\n\n\n" 0 0' dialog(arg) @@ -865,11 +869,11 @@ def set_imprimeurs(club): newimp = select(club, u'd\'un nouvel imprimeur a', 'ro') if newimp: if club.imprimeurs(ajouter=str(newimp.id())): - arg = u'--title "Ajout imprimeur" ' + arg = u'--title "Ajout imprimeur" ' arg += u'--msgbox "Imprimeur ajouté\n\n\n" 0 0' dialog(arg) else: - arg = u'--title "Ajout imprimeur" ' + arg = u'--title "Ajout imprimeur" ' arg += u'--msgbox "Cet adhérent est déjà imprimeur !\n\n\n" 0 0' dialog(arg) continue @@ -1011,9 +1015,35 @@ def set_solde(clas): annul, res = dialog(arg) if annul: return 1 + _montant = float(res[0]) + + menu = [] + + menu.append(u'"Liquide" "Espèces" ') + menu.append(u'"Cheque" "Chèque" ') + menu.append(u'"Carte" "Carte bancaire" ') + menu.append(u'"Note" "Note Kfet (attention, moins traçable)" ') + + if _montant > 0: + _kword = u"Crédit" + _kword2 = u"paiement" + else: + _kword = u"Débit" + _kword2 = u"retrait" + + # Il y a qqch de modifiable, on construit la checklist + arg = u'--title "%s du solde de %s" ' % (_kword, clas.Nom()) + arg += u'--menu "Mode de %s : " 0 0 0 ' % (_kword2,) + arg += u''.join(menu) + + annul, result = dialog(arg) + if annul: return 1 + + _mode = result[0] + # Ajout du commentaire - arg = u'--title "Crédit / débit du compte de %s" ' % clas.Nom() - arg += u'--inputbox "Commentaire à insérer ?" 0 0' + arg = u'--title "%s du solde de %s" ' % (_kword, clas.Nom()) + arg += u'--inputbox "Commentaire à insérer (nom de note, …) ?" 0 0' annul, comment = dialog(arg) if not annul: @@ -1022,22 +1052,27 @@ def set_solde(clas): else: comment = None + f = Facture(clas) + f.ajoute({'nombre': 1, 'code':'SOLDE', 'designation': "Solde Crans", 'pu': _montant}) + f.modePaiement(_mode.lower()) + try: - clas._data['uid'][0] - except KeyError: - arg = u'--title "Opération impossible" ' - arg += u'--msgbox "Il faut créer un compte Cr@ns pour modifier le solde" 0 0' - dialog(arg) - return - try: - clas.solde(res[0], comment) - db.services_to_restart('mail_solde', ['%s a fait %s euros pour %s [%s]' %(script_utilisateur, res[0],clas._data['uid'][0], comment)]) - break + # Met aussi à jour le solde. + f.recuPaiement(strftime("%Y-%m-%d %H:%M:%S")) + f.save() + db.services_to_restart('mail_solde', [ + '%s a fait %s euros pour %s [mode: %s, remarque: %s]' % + (script_utilisateur, _montant, clas._data['uid'][0], _mode, comment) + ]) except ValueError, c: arg = u'--title "Opération impossible" ' arg += u'--msgbox "%s\n\n\n" 0 0' % to_unicode(c.args[0]) dialog(arg) + arg = u'--title "%s du solde de %s" ' % (_kword, clas.Nom()) + arg += u'--msgbox "Modification effectuée, merci de noter le numéro de facture %s." 0 0' % (f.numero(),) + dialog(arg) + def set_vente(proprio): u""" Vend un objet à l'adherent : génère la facture associée. @@ -1064,7 +1099,7 @@ def set_vente(proprio): # Il y a qqch de modifiable, on construit la checklist - arg = u'--title "Vente de consomables à %s" ' % proprio.Nom() + arg = u'--title "Vente de consomables à %s" ' % proprio.Nom() arg += u'--separate-output ' arg += u'--checklist "%s\n" 0 0 0 ' % '\n'.join(texte) arg += u' '.join(checklist) @@ -1083,7 +1118,7 @@ def set_vente(proprio): annul, res = dialog(arg) if annul: return 1 try: - nombre=int(res[0]) + nombre = int(res[0]) break except ValueError, c: arg = u'--title "Opération impossible" ' @@ -1095,7 +1130,7 @@ def set_vente(proprio): annul, res = dialog(arg) if annul: return 1 try: - nombre=float(res[0]) + nombre = float(res[0]) break except ValueError, c: arg = u'--title "Opération impossible" ' @@ -1124,36 +1159,35 @@ def set_vente(proprio): menu.append(u'"Spc" "Espèces" ') menu.append(u'"Chq" "Chèque" ') menu.append(u'"Cb" "Carte bancaire" ') - if isimprimeur: + if isimprimeur and proprio.solde() - f.total() > 0: menu.append(u'"Sol" "Solde Crans (actuel : %s€)" ' % (proprio.solde())) # Il y a qqch de modifiable, on construit la checklist - arg = u'--title "Vente de consomables à %s" ' % proprio.Nom() + arg = u'--title "Vente de consomables à %s" ' % proprio.Nom() arg += u'--menu "Mode de paiement : " 0 0 0 ' arg += u''.join(menu) annul, result = dialog(arg) if annul: return 1 - #print result # Ajout du commentaire arg = u'--title "Crédit / débit du compte de %s" ' % proprio.Nom() arg += u'--inputbox "Commentaire à insérer ?" 0 0' if result[0] == "Spc": f.modePaiement('liquide') - paiement=u"Espèce" + paiement = u"Espèce" annul, comment = dialog(arg) elif result[0] == "Cb": f.modePaiement('carte') - paiement=u"Carte Bancaire" + paiement = u"Carte Bancaire" comment = None elif result[0] == "Chq": f.modePaiement('cheque') - paiement=u"Chèque" + paiement = u"Chèque" annul, comment = dialog(arg) elif result[0] == "Sol" and isimprimeur: f.modePaiement('solde') - paiement=u"Solde Crans" + paiement = u"Solde Crans" comment = None if comment and comment[0]: @@ -1161,15 +1195,15 @@ def set_vente(proprio): else: comment = None - return (f,paiement,comment) + return (f, paiement, comment) - def confirm_and_pay((f,paiement,comment)): - arg = u'--title "Validation du paiement" ' + def confirm_and_pay((f, paiement, comment)): + arg = u'--title "Validation du paiement" ' arg += u'--yesno "Le paiement de %s€ a-t-il bien été reçu (mode : %s) ?\n" 0 0 ' % (f.total(), paiement) no, result = dialog(arg) if no: arg = u'--title "Annulation de la vente" ' - arg += u'--msgbox "Le paiement n\'ayant pas été reçue\nla vente est annulée\n" 0 0' + arg += u'--msgbox "Le paiement n\'ayant pas été reçu\nla vente est annulée\n" 0 0' dialog(arg) return 1 else: @@ -1177,9 +1211,10 @@ def set_vente(proprio): f.recuPaiement(strftime("%Y-%m-%d %H:%M:%S")) f.save() arg = u'--title "Vente terminée" ' - arg += u'--msgbox "Vous pouvez remettre à l\'adherent les articles suivant :\n%s\n\nMerci de noter la facture: fid=%s" 0 0' % ('\n'.join( - ["%s %s" % (art['nombre'], art['designation']) for art in f.articles()]), - f.numero()) + arg += u'--msgbox "Vous pouvez remettre à l\'adherent les articles suivant :\n%s\n\nMerci de noter la facture: fid=%s" 0 0' % ('\n'.join([ + "%s %s" % (art['nombre'], art['designation']) + for art in f.articles() + ]), f.numero()) dialog(arg) except ValueError as error: f.delete() @@ -1399,7 +1434,7 @@ def set_admin(proprio): # Il y a qqch de modifiable, on construit la checklist - arg = u'--title "Etat administratif de %s" ' % proprio.Nom() + arg = u'--title "Etat administratif de %s" ' % proprio.Nom() arg += u'--separate-output ' arg += u'--checklist "%s\n" 0 0 0 ' % '\n'.join(texte) arg += u' '.join(checklist) @@ -1470,15 +1505,15 @@ def set_adhesion(proprio): facture._set('debutAdhesion', []) facture.supprime(pop=True) return 1 - res = res[0] - if res in ["Liquide", "Cheque", "Carte"]: + _mode = res[0] + if _mode in ["Liquide", "Cheque", "Carte"]: arg = u'--title "Avertissement" ' arg += u'--msgbox "Une facture sera créée, après validation par le trésorier, l\'adhérent\npourra y accéder via l\'intranet ou la demander." 0 0' dialog(arg) - facture.modePaiement(res.lower()) + facture.modePaiement(_mode.lower()) break else: - facture.modePaiement(res.lower()) + facture.modePaiement(_mode.lower()) break in_facture = facture @@ -1591,15 +1626,15 @@ def set_connexion(proprio): facture._set('debutConnexion', []) facture.supprime(pop=True) continue - res = res[0] - if res in ["Liquide", "Cheque", "Carte"]: + _mode = res[0] + if _mode in ["Liquide", "Cheque", "Carte"]: arg = u'--title "Avertissement" ' arg += u'--msgbox "Une facture sera créée, après validation par le trésorier, l\'adhérent\npourra y accéder via l\'intranet ou la demander." 0 0' dialog(arg) - facture.modePaiement(res.lower()) + facture.modePaiement(_mode.lower()) break else: - facture.modePaiement(res.lower()) + facture.modePaiement(_mode.lower()) break else: break @@ -1662,7 +1697,7 @@ def modif_club(club): arg += u'"Alias" "Créer ou supprimer un alias mail" ' if isdeconnecteur: arg += u'"Blackliste" "Modifier la blackliste du club" ' - if isimprimeur: + if isimprimeur and club.compte(): arg += u'"Solde" "Effectuer un débit/crédit pour ce club" ' arg += u'"Vente" "Vendre un cable ou adaptateur ethernet ou autre" ' @@ -1756,7 +1791,7 @@ def set_facture_recu(facture): """Change le reçu d'une facture """ - arg = u'--title "Reçu pour la facture fid=%s (%s)" ' % (facture.id(), facture.proprietaire().Nom()) + arg = u'--title "Reçu pour la facture fid=%s (%s)" ' % (facture.id(), facture.proprietaire().Nom()) arg += u'--separate-output ' arg += u'--checklist "État du paiement\n" 0 0 0 ' arg += u'"Pmt" "Paiement fourni." "%s"' % (on_off(facture.recuPaiement() is not None),) @@ -1773,7 +1808,7 @@ def set_facture_controle(facture): """Change le contrôle de la facture """ - arg = u'--title "Contrôle pour la facture fid=%s (%s)" ' % (facture.id(), facture.proprietaire().Nom()) + arg = u'--title "Contrôle pour la facture fid=%s (%s)" ' % (facture.id(), facture.proprietaire().Nom()) arg += u'--separate-output ' arg += u'--checklist "État du contrôle\n" 0 0 0 ' arg += u'"Ctl" "Contrôle OK." "%s" ' % (on_off(facture.controle() == "TRUE"),) @@ -1845,7 +1880,7 @@ def set_wifi(machine): if result[2].strip().lower() == "none" or result[3].strip().lower() == "none": machine.position(None) else: - machine.position((result[2].strip(),result[3].strip())) + machine.position((result[2].strip(), result[3].strip())) except ValueError, c: err += c.args[0] + '\n' if result[4].lower().strip() == "oui": @@ -1866,7 +1901,7 @@ def set_wifi(machine): variable = nvram.split('=')[0].strip() valeur = nvram.split('=')[1].strip() if valeur.lower() == "none": - valeur=None + valeur = None machine.nvram(variable, valeur) except ValueError, c: err += c.args[0] + '\n' # Des erreurs ? @@ -1931,7 +1966,7 @@ def set_machine(machine): err += c.args[0] + '\n' try: machine.ip(result[2]) except ValueError, c: - if len(c.args)>1 and c.args[1] == 1 and isadm: + if len(c.args) > 1 and c.args[1] == 1 and isadm: arg = u'--title "Plage d\'ip" ' arg += u'--yesno "La machine va être ajoutée en v6 only, continuer ? \n" 0 0' no, res = dialog(arg) @@ -1953,7 +1988,7 @@ def set_machine(machine): err += c.args[0] + '\n' # Plus d'IP libres, peut-être à traiter differement ? try: machine.mac(result[1]) except ValueError, c: - if len(c.args)>1 and c.args[1] == 1 and isadm: + if len(c.args) > 1 and c.args[1] == 1 and isadm: # Mac en double arg = u'--title "Adresse MAC" ' arg += u'--yesno "L\'adresse MAC existe déjà, continuer ? \n" 0 0' @@ -1966,7 +2001,7 @@ def set_machine(machine): err += c.args[0] + '\n' except EnvironmentError, c: err += c.args[0] + '\n' - elif len(c.args)>1 and c.args[1] == 3 and isadm: + elif len(c.args) > 1 and c.args[1] == 3 and isadm: # Mac douteuse arg = u'--title "Adresse MAC" ' arg += u'--yesno "L\'adresse MAC ne correspond à aucun constructeur, continuer ? \n" 0 0' @@ -2126,15 +2161,15 @@ def modif_adher(adher): # Préliminaire : si la chambre est inconnue on force la question if adher.chbre() == '????': - res= ['Chambre'] - arg = u'--title "Modification de %s" ' % adher.Nom() - arg += u'--msgbox "ERREUR : la chambre de cet adhérent est inconnue !\n\n\n" 0 0' - dialog(arg) + res = ['Chambre'] + arg = u'--title "Modification de %s" ' % adher.Nom() + arg += u'--msgbox "ERREUR : la chambre de cet adhérent est inconnue !\n\n\n" 0 0' + dialog(arg) elif adher.mail() == '': - res= ['Mail'] - arg = u'--title "Modification de %s" ' % adher.Nom() - arg += u'--msgbox "ERREUR : l\'adresse mail de cet adhérent est inconnue !\n\n\n" 0 0' - dialog(arg) + res = ['Mail'] + arg = u'--title "Modification de %s" ' % adher.Nom() + arg += u'--msgbox "ERREUR : l\'adresse mail de cet adhérent est inconnue !\n\n\n" 0 0' + dialog(arg) else: payant = not isinstance(adher, Club) and adher.adherentPayant() @@ -2402,7 +2437,7 @@ def select(clas, quoi, mde=''): si m = ro ouvre l'objet en mode read-only """ - s= ['', '', '', '', '', '', '', '', '', '', '', '', '', ''] + s = ['', '', '', '', '', '', '', '', '', '', '', '', '', ''] def unicodize(a): try: return unicode(a, 'utf-8') @@ -2443,10 +2478,11 @@ def select(clas, quoi, mde=''): dialog(arg) continue - s= [] + s = [] for i in result: i = i.strip().decode(encoding) - if not i: i= u'*' + if not i: + i = u'*' s.append(i) # Recherche par adresse mail/login @@ -2501,7 +2537,7 @@ def select(clas, quoi, mde=''): valid = res['adherent'] if not valid and (res['machine'] or res['facture']): # On va récupérer les adhérents correspondants aux machines trouvés - deja= [] + deja = [] for m in res['machine']: a = m.proprietaire() if a.id() in deja: continue @@ -2574,7 +2610,7 @@ def select(clas, quoi, mde=''): # Annulation du choix choix = None break - cprint (u'Répondre O ou N') + cprint(u'Répondre O ou N') # Retour à la confirmation if choix: @@ -2671,19 +2707,19 @@ def menu_principal(): # Ajout machine, adhérent à choisir proprio = select(db, u'adhérent auquel ajouter une machine a') if not proprio: continue - choix= 'aMc' + choix = 'aMc' elif choix == 'aMC': # Ajout machine, club à choisir proprio = select_club(db) if not proprio: continue - choix= 'aMc' + choix = 'aMc' elif choix == 'mM': # Modif machine, machine à choisir becane = select(db, u'machine à modifier m') if not becane: continue - choix= 'mMc' + choix = 'mMc' elif choix == "mF": # Modif d'une facture. Choisir facture. @@ -2702,30 +2738,37 @@ def menu_principal(): # Modif club proprio = select_club(db) if not proprio: continue - choix= 'mCc' + choix = 'mCc' elif choix == 'dA': # Destruction adhérent proprio = select(db, u'adhérent à détruire a') - if not proprio: continue - if del_adher(proprio): continue - del(proprio) ; proprio= None - del(becane) ; becane= None + if not proprio: + continue + if del_adher(proprio): + continue + del proprio + proprio = None + del becane + becane = None elif choix == 'dM': # Destruction machine becane = select(db, u'machine à détruire m') if not becane: continue if del_machine(becane): continue - del(becane) ; becane= None + del becane + becane = None elif choix == 'dC': # Destruction club proprio = select_club(db) if not proprio: continue if del_club(proprio): continue - del(proprio) ; proprio= None - del(becane) ; becane= None + del proprio + proprio = None + del becane + becane = None elif choix == 'dF': # Destruction machine @@ -2733,13 +2776,13 @@ def menu_principal(): if not facture: continue proprio = facture.proprietaire() if del_facture(facture): continue - del(facture) + del facture facture = None proprio.update_adhesion() proprio.update_connexion() proprio.save() - del(proprio) + del proprio proprio = None elif choix == 'aKM': @@ -2788,7 +2831,7 @@ def menu_principal(): arg += u'"Wifi" "Machine wireless" ' annul, result = dialog(arg) if annul: continue - choix= result[0] + choix = result[0] else: # Plus de machine fixe possible... arg = u'--title "Nouvelle machine" ' @@ -2814,20 +2857,20 @@ def menu_principal(): if choix == 'Wifi' or (choix == 'Fixe' and proprio.chbre() not in ['', 'EXT']): becane.mac("") except ValueError, c: - arg = u'--title "Nouvelle machine" ' + arg = u'--title "Nouvelle machine" ' arg += u'--msgbox "%s\n\n\n" 0 0' % to_unicode(c.args[0]) dialog(arg) continue if set_machine(becane): # Annulation - del(becane) + del becane becane = None if choix == 'mAc': # Modif propriétaire courant - del(becane) - becane= None + del becane + becane = None # Test club if isinstance(proprio, Club): if modif_club(proprio): @@ -2861,7 +2904,7 @@ def menu_principal(): proprio.update_adhesion() proprio.update_connexion() proprio.save() - del(proprio) + del proprio proprio = None elif choix == 'mCc': diff --git a/gestion/ldap_crans.py b/gestion/ldap_crans.py index 3ba86630..697690eb 100755 --- a/gestion/ldap_crans.py +++ b/gestion/ldap_crans.py @@ -4158,7 +4158,7 @@ class Facture(BaseClasseCrans): for art in ajoute: if int(art['nombre']) != float(art['nombre']): raise ValueError, u'nombre doit être un entier' - if round(art['pu'],2) != art['pu']: + if round(art['pu'], 2) != art['pu']: raise ValueError, u'pu ne doit pas avoir plus de 2 chiffres apres la virgule' art['nombre'] = int(art['nombre']) if '~~' in ' '.join([unicode(x) for x in art.values()]):