Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Commit

Permalink
Use customer id to match routes
Browse files Browse the repository at this point in the history
In addition to card id
  • Loading branch information
chadwhitacre committed Oct 8, 2015
1 parent 19fbbcb commit e236680
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 37 deletions.
103 changes: 67 additions & 36 deletions backfill-exchanges.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from gratipay import wireup
from decimal import Decimal as D
from pprint import pprint
from gratipay.models.participant import Participant
from gratipay.models.exchange_route import ExchangeRoute

db = wireup.db(wireup.env())
Expand Down Expand Up @@ -47,7 +46,8 @@ def __init__(self):

self.route_in_exchange = 0
self.route_ambiguous = 0
self.route_matched_to_card = 0
self.route_matched_via_card = 0
self.route_matched_via_customer = 0
self.route_ambiguous_customer = 0
self.route_created = 0
self.route_unknown = 0
Expand Down Expand Up @@ -87,7 +87,8 @@ def check(self):
))
nroutes = sum(( self.route_in_exchange
, self.route_ambiguous
, self.route_matched_to_card
, self.route_matched_via_card
, self.route_matched_via_customer
, self.route_ambiguous_customer
, self.route_created
, self.route_unknown
Expand Down Expand Up @@ -153,23 +154,45 @@ def get_exchange_id(cur, transaction, counts, usernames):
raise UnknownExchange(mogrified)


def resolve_ambiguous_route(cur, transaction, counts, u2r):
keys = u2r.keys()
absorption = cur.one("""\
SELECT *
FROM absorptions
WHERE (archived_as=%(one)s AND absorbed_by=%(two)s)
OR (archived_as=%(two)s AND absorbed_by=%(one)s)
""", dict(one=keys[0], two=keys[1]))
if absorption is None:
def resolve_route(cur, transaction, counts, routes, usernames):
log('routes: {routes:<12}'.format(routes=', '.join(str(r.id) for r in routes)))

nroutes = len(routes)
if nroutes == 0: return None
elif nroutes == 1: return routes[0].id
assert nroutes == 2
# Pick the route for the participant that was active at the time of the transaction.

nusernames = len(usernames)
assert nusernames in (1, 2), (usernames, routes)
if nusernames == 1:
counts.route_ambiguous += 1
raise AmbiguousRoute()
if transaction['created_at'] < str(absorption.timestamp).replace('+00:00', 'Z'):
key = absorption.archived_as
else:
assert transaction['created_at'] > str(absorption.timestamp).replace('+00:00', 'Z')
key = absorption.absorbed_by
return u2r[key]
# See if we can assume it's a case of absorption.
user_ids = [r.participant for r in routes]
i2n = dict(cur.all( "SELECT id, username FROM participants WHERE id = ANY(%s)"
, (user_ids,)
))
assert sorted(i2n.values()) == sorted(usernames)
u2r = {i2n[r.participant]: r.id for r in routes}

keys = u2r.keys()
absorption = cur.one("""\
SELECT *
FROM absorptions
WHERE (archived_as=%(one)s AND absorbed_by=%(two)s)
OR (archived_as=%(two)s AND absorbed_by=%(one)s)
""", dict(one=keys[0], two=keys[1]))
if absorption is None:
counts.route_ambiguous += 1
raise AmbiguousRoute()
if transaction['created_at'] < str(absorption.timestamp).replace('+00:00', 'Z'):
key = absorption.archived_as
else:
assert transaction['created_at'] > str(absorption.timestamp).replace('+00:00', 'Z')
key = absorption.absorbed_by
return u2r[key]


def get_route_id(cur, transaction, counts, usernames, exchange_id):
Expand All @@ -178,47 +201,55 @@ def get_route_id(cur, transaction, counts, usernames, exchange_id):
route_id = cur.one("SELECT route FROM exchanges WHERE id=%s", (exchange_id,))
if route_id:
counts.route_in_exchange += 1
log("exchange has a route", 20)
log("exchange has a route", 22)
return route_id

# Second strategy: match on known cards.
if not route_id:
routes = cur.all( "SELECT * FROM exchange_routes "
"WHERE network='balanced-cc' and address='/cards/'||%s"
"WHERE network='balanced-cc' AND address='/cards/'||%s"
, (transaction['links']['source'],)
)
if len(routes) == 1:
route_id = routes[0].id
elif len(routes) > 1:
# Pick the route for the participant that was active at the time of the transaction.
user_ids = [r.participant for r in routes]
i2n = dict(cur.all( "SELECT id, username FROM participants WHERE id = ANY(%s)"
, (user_ids,)
))
assert sorted(i2n.values()) == sorted(usernames)
u2r = {i2n[r.participant]: r.id for r in routes}
route_id = resolve_ambiguous_route(cur, transaction, counts, u2r)
log('routes: {routes:<12}'.format(routes=', '.join(str(r.id) for r in routes)))
route_id = resolve_route(cur, transaction, counts, routes, usernames)
if route_id:
counts.route_matched_via_card += 1
log("card matches {}".format(route_id), 22)
return route_id

# Third strategy: match on usernames.
if not route_id:
routes = cur.all("""\
SELECT *
FROM exchange_routes
WHERE network='balanced-cc' and participant in (
SELECT id
FROM participants
WHERE username=ANY(%s)
)
""", (usernames,))
route_id = resolve_route(cur, transaction, counts, routes, usernames)
if route_id:
counts.route_matched_to_card += 1
log("card matches {}".format(route_id), 20)
counts.route_matched_via_customer += 1
log("customer matches {}".format(route_id), 22)
return route_id

# Third strategy: make a route!
# Fourth strategy: make a route!
if not route_id:
if len(usernames) > 1:
counts.route_ambiguous_customer += 1
raise AmbiguousCustomer()
username = usernames[0]
route = ExchangeRoute.insert( Participant.from_username(username)
participant = cur.one("SELECT participants.*::participants FROM participants "
"WHERE username=%s", (username,))
route = ExchangeRoute.insert( participant
, 'balanced-cc'
, '/cards/'+transaction['links']['source']
, cursor=cur
)
route_id = route.id
if route_id:
counts.route_created += 1
log("created a route", 20)
log("created a route", 22)
return route_id

counts.route_unknown += 1
Expand Down
2 changes: 1 addition & 1 deletion tally-backfill.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def report(*patterns):
report("exchange_id in transaction", "triangulated an exchange", "raise UnknownExchange")

title("Routes")
report("exchange has a route", "card matches", "created a route",
report("exchange has a route", "card matches", "customer matches", "created a route",
"raise AmbiguousRoute", "raise AmbiguousCustomer", "raise UnknownRoute")

title("Check")
Expand Down

0 comments on commit e236680

Please sign in to comment.