import collections
import pprint
import subprocess
+import argparse
import pretty_print
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.
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
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
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)