From 8716e3401a1790c24ffd7d4825d86f56ef92e8b3 Mon Sep 17 00:00:00 2001 From: Vincent Le Gallic Date: Wed, 10 Feb 2016 06:02:04 +0100 Subject: [PATCH] =?utf8?q?[bde/credits=5Fduplicates]=20Plus=20d'options=20?= =?utf8?q?et=20demande=20de=20d=C3=A9validation=20interactive?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- bde/credits_duplicates.py | 57 +++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/bde/credits_duplicates.py b/bde/credits_duplicates.py index 6c9f635..dc98725 100755 --- a/bde/credits_duplicates.py +++ b/bde/credits_duplicates.py @@ -8,6 +8,7 @@ import psycopg2.extras import collections import pprint import subprocess +import argparse import pretty_print @@ -16,7 +17,7 @@ def getcursor(): con.set_client_encoding("utf-8") return (con, con.cursor(cursor_factory = psycopg2.extras.DictCursor)) -def get_data(cur, delai='1 minute'): +def get_data(cur, delai='1 minute', date='1970-01-01'): """ Récupère les paires de crédits effectués à moins de ``delai`` d'intervalle. ``delai`` est un chaîne de caractères que PostGreSQL comprendra comme une durée. @@ -61,8 +62,7 @@ def get_data(cur, delai='1 minute'): t2.description AS desc2 FROM credits t1,credits t2, comptes c WHERE t1.destinataire = c.idbde - AND t1.date >= '2016-01-01' - AND t2.date >= '2016-01-01' + AND t1.date >= %(date)s AND t2.date >= %(date)s AND t1.type='crédit' AND t2.type='crédit' AND t1.id != t2.id @@ -75,7 +75,7 @@ def get_data(cur, delai='1 minute'): AND (t2.date - t1.date) <= %(delai)s AND (t2.date - t1.date) >= '0 s'; """ - cur.execute(req, {"delai" : delai}) + cur.execute(req, {"delai" : delai, "date" : date}) l = cur.fetchall() return l @@ -116,19 +116,48 @@ def get_transactions(cur, ids): cur.execute("SELECT * FROM credits WHERE id IN (%s)" % ids) return cur.fetchall() - -if __name__ == "__main__": - con, cur = getcursor() - data = get_data(cur) - blocks = sort_by_blocks(data) +def interactive(blocks, cur, args): + """ + Propose intéractivement (sauf si les ``args`` en décident autrement) de dévalider les transactions doublons + ou d'afficher une liste de toutes celles à dévalider. + """ + ids_to_devalidate = [] for b in blocks: + lb = [int(i) for i in b.split(",")] l = get_transactions(cur, b) formatted = pretty_print.sql_pretty_print(l, keys=["id", "date", "type", "emetteur", "destinataire", "quantite", "montant", "description", "valide", "cantinvalidate"]) - p = subprocess.Popen(["less"], stdin=subprocess.PIPE) - p.communicate(formatted.encode("utf-8")) + if not args.noless: + p = subprocess.Popen(["less"], stdin=subprocess.PIPE) + p.communicate(formatted.encode("utf-8")) print formatted print "IDs : %s" % b - idkeep = int(b.split(",")[0]) - ans = raw_input("Ne garder que %s (= dévalider les autres) ? [o/N]" % idkeep) + idkeep = lb[0] + question = "Ne garder que %s (= dévalider les autres) ? [o/N/s]" % idkeep + if args.no or args.store: + ans = "s" if args.store else "n" + print question, ans + else: + ans = raw_input(question) if ans.lower() in ["o", "y"]: - print "bim !" + print "DESTROY !" + elif ans.lower() in ["s"]: + lb.remove(idkeep) + ids_to_devalidate.extend(lb) + if ids_to_devalidate: + print "\nIDs de transactions à dévalider :\n" + ",".join([str(i) for i in ids_to_devalidate]) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Liste les crédits semblables trop proches dans le temps et propose de les dévalider tous sauf 1.") + + parser.add_argument('-n', '--no', help="Bypasse l'interactif et répond non à toutes les questions", action="store_true") + parser.add_argument('--store', help="Bypasse l'interactif et répond store à toutes les questions", action="store_true") + parser.add_argument('--date', help="Se limiter aux transactions après DATE", type=str, action="store", default='1970-01-01') + parser.add_argument('-t', '--deltat', help="Choisir la durée au-dessus de laquelle 2 crédits sont considérés comme différents", type=str, action="store", default='1 minute') + parser.add_argument('--no-less', '--noless', dest="noless", help="Se dispenser d'afficher les blocks dans un less. À réserver aux terminaux assez larges.", action="store_true") + + args = parser.parse_args() + + con, cur = getcursor() + data = get_data(cur, delai=args.deltat, date=args.date) + blocks = sort_by_blocks(data) + interactive(blocks, cur, args) -- 2.39.2