]>
gitweb.pimeys.fr Git - scripts-20-100.git/blob - bde/credits_duplicates.py
2 # -*- encoding: utf-8 -*-
4 """ Pour trouver les chèque dupliqués sur la note. """
16 con
= psycopg2
. connect ( database
= "note" )
17 con
. set_client_encoding ( "utf-8" )
18 return ( con
, con
. cursor ( cursor_factory
= psycopg2
. extras
. DictCursor
))
20 def get_data ( cur
, delai
= '1 minute' , date
= '1970-01-01' ):
22 Récupère les paires de crédits effectués à moins de ``delai`` d'intervalle.
23 ``delai`` est un chaîne de caractères que PostGreSQL comprendra comme une durée.
24 Les crédits doivent êtres valides, de même destinataire, de même montant.
25 Pour les crédits chèque, virement et carte bancaire, on vérifie qu'ils aient le même prénom,nom
27 req_create_credits
= """
28 CREATE TEMPORARY TABLE credits AS (
30 SELECT t.*, c.prenom, c.nom FROM transactions t, cheques c
31 WHERE t.type = 'crédit' AND t.emetteur = -1 AND t.id = c.idtransaction
35 SELECT t.*, v.prenom, v.nom FROM transactions t, virements v
36 WHERE t.type = 'crédit' AND t.emetteur = -3 AND t.id = v.idtransaction
40 SELECT t.*, cb.prenom, cb.nom FROM transactions t, carte_bancaires cb
41 WHERE t.type = 'crédit' AND t.emetteur = -4 AND t.id = cb.idtransaction
45 SELECT t.*, '', '' FROM transactions t
46 WHERE t.type = 'crédit' AND t.emetteur = -2
49 cur
. execute ( req_create_credits
)
51 cur
. execute ( "CREATE INDEX credits_index_id ON credits (id);" )
59 t2.date - t1.date AS deltaT,
63 t1.description AS desc1,
64 t2.description AS desc2
65 FROM credits t1,credits t2, comptes c
66 WHERE t1.destinataire = c.idbde
67 AND t1.date >= %(date)s AND t2.date >= %(date)s
73 AND t1.destinataire = t2.destinataire
74 AND t1.montant = t2.montant
75 AND t1.prenom = t2.prenom
77 AND (t2.date - t1.date) <= %(delai)s
78 AND (t2.date - t1.date) >= '0 s';
80 cur
. execute ( req
, { "delai" : delai
, "date" : date
})
84 def sort_by_blocks ( data
):
86 Regroupe les transactions qui vont ensemble.
87 Sort une liste de chaînes de caractères contenant les ids de chaque block comma-separated.
88 Oui, le format de sortie est dégueu, mais c'est nettement moin galère pour trouver les doublons.
90 map = collections
. defaultdict ( lambda : set ())
92 id1
, id2
= t
[ "id1" ], t
[ "id2" ]
99 # Comme on touche s en place et que c'est le même mutable qui a été mis
100 # comme valeur des 2 clés, il sera modifié par les étapes suivantes aussi
103 map [ id1
] = map [ id2
] = s
104 # On a tous les blocks, reste à ne garder qu'un exemplaire de chaque
105 result
= [ list ( s
) for s
in map . values ()]
108 result
= [ ", " . join ([ str ( i
) for i
in l
]) for l
in result
]
109 result
= list ( set ( result
))
112 def get_transactions ( cur
, ids
):
114 Récupère les informations de toutes les transactions dans la liste d'identifiants ``ids``
115 qui doit être donné sous la forme d'une chaîne de caractères d'ids comma-separated.
117 # yuk, mais le format correspond à ce qu'outpute sort_by_blocks
118 cur
. execute ( "SELECT * FROM credits WHERE id IN ( %s )" % ids
)
119 return cur
. fetchall ()
121 def interactive ( blocks
, cur
, args
):
123 Propose intéractivement (sauf si les ``args`` en décident autrement) de dévalider les transactions doublons
124 ou d'afficher une liste de toutes celles à dévalider.
126 ids_to_devalidate
= []
129 lb
= [ int ( i
) for i
in b
. split ( "," )]
130 l
= get_transactions ( cur
, b
)
131 formatted
= pretty_print
. sql_pretty_print ( l
, keys
=[ "id" , "date" , "type" , "emetteur" , "destinataire" , "quantite" , "montant" , "description" , "valide" , "cantinvalidate" , "prenom" , "nom" ])
133 p
= subprocess
. Popen ([ "less" ], stdin
= subprocess
. PIPE
)
134 p
. communicate ( formatted
. encode ( "utf-8" ))
138 question
= "Ne garder que %s (= dévalider les autres) ? [o/N/s]" % idkeep
139 if args
. no
or args
. store
:
140 ans
= "s" if args
. store
else "n"
143 ans
= raw_input ( question
)
144 if ans
. lower () in [ "o" , "y" ]:
146 elif ans
. lower () in [ "s" ]:
148 ids_to_devalidate
. extend ( lb
)
149 total
+= l
[ 0 ][ "montant" ] * ( len ( l
) - 1 )
150 if ids_to_devalidate
:
151 print " \n IDs de transactions à dévalider ( %s ) :" % len ( ids_to_devalidate
)
152 print "," . join ([ str ( i
) for i
in ids_to_devalidate
])
153 print "Montant total : %s " % ( total
,)
155 if __name__
== "__main__" :
156 parser
= argparse
. ArgumentParser ( description
= "Liste les crédits semblables trop proches dans le temps et propose de les dévalider tous sauf 1." )
158 parser
. add_argument ( '-n' , '--no' , help = "Bypasse l'interactif et répond non à toutes les questions" , action
= "store_true" )
159 parser
. add_argument ( '--store' , help = "Bypasse l'interactif et répond store à toutes les questions" , action
= "store_true" )
160 parser
. add_argument ( '--date' , help = "Se limiter aux transactions après DATE" , type = str , action
= "store" , default
= '1970-01-01' )
161 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' )
162 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" )
164 args
= parser
. parse_args ()
166 con
, cur
= getcursor ()
167 data
= get_data ( cur
, delai
= args
. deltat
, date
= args
. date
)
168 blocks
= sort_by_blocks ( data
)
169 interactive ( blocks
, cur
, args
)