def shuffle(self): with self.db.get_cursor() as cursor: self.prepare(cursor, self.ts_start) self.transfer_virtually(cursor, self.ts_start) transfers = cursor.all(""" SELECT t.* , p.mangopay_user_id AS tipper_mango_id , p2.mangopay_user_id AS tippee_mango_id , p.mangopay_wallet_id AS tipper_wallet_id , p2.mangopay_wallet_id AS tippee_wallet_id FROM payday_transfers t JOIN participants p ON p.id = t.tipper JOIN participants p2 ON p2.id = t.tippee """) try: self.check_balances(cursor) self.transfer_for_real(transfers) check_db(cursor) except: # Dump transfers for debugging import csv from time import time with open('%s_transfers.csv' % time(), 'wb') as f: csv.writer(f).writerows(transfers) raise # Clean up leftover functions self.db.run(""" DROP FUNCTION process_take(); DROP FUNCTION process_tip(); DROP FUNCTION settle_tip_graph(); DROP FUNCTION transfer(bigint, bigint, numeric, transfer_context); """)
def sync_with_mangopay(db): """We can get out of sync with MangoPay if record_exchange_result wasn't completed. This is where we fix that. """ check_db(db) exchanges = db.all(""" SELECT *, (e.timestamp < current_timestamp - interval '1 day') AS is_old FROM exchanges e WHERE e.status = 'pre' """) for e in exchanges: p = Participant.from_id(e.participant) transactions = [ x for x in User(id=p.mangopay_user_id).transactions.all( Sort='CreationDate:DESC', Type=('PAYIN' if e.amount > 0 else 'PAYOUT')) if x.Tag == str(e.id) ] assert len(transactions) < 2 if transactions: t = transactions[0] error = repr_error(t) status = t.Status.lower() assert (not error) ^ (status == 'failed') record_exchange_result(db, e.id, t.Id, status, error, p) elif e.is_old: # The exchange didn't happen, mark it as failed record_exchange_result(db, e.id, '', 'failed', 'interrupted', p) transfers = db.all(""" SELECT *, (t.timestamp < current_timestamp - interval '1 day') AS is_old FROM transfers t WHERE t.status = 'pre' """) for t in transfers: tipper = Participant.from_id(t.tipper) transactions = [ x for x in User(id=tipper.mangopay_user_id).transactions.all( Sort='CreationDate:DESC', Type='TRANSFER') if x.Tag == str(t.id) ] assert len(transactions) < 2 if transactions: record_transfer_result(db, t.id, transactions[0]) elif t.is_old: # The transfer didn't happen, mark it as failed _record_transfer_result(db, t.id, 'failed', 'interrupted') check_db(db)
def sync_with_mangopay(db): """We can get out of sync with MangoPay if record_exchange_result wasn't completed. This is where we fix that. """ print("Syncing with Mangopay...") check_db(db) exchanges = db.all(""" SELECT *, (e.timestamp < current_timestamp - interval '1 day') AS is_old FROM exchanges e WHERE e.status = 'pre' """) for e in exchanges: p = Participant.from_id(e.participant) transactions = [x for x in User(id=p.mangopay_user_id).transactions.all( Sort='CreationDate:DESC', Type=('PAYIN' if e.amount > 0 else 'PAYOUT') ) if x.Tag == str(e.id)] assert len(transactions) < 2 if transactions: t = transactions[0] error = repr_error(t) status = t.Status.lower() assert (not error) ^ (status == 'failed') record_exchange_result(db, e.id, t.Id, status, error, p) elif e.is_old: # The exchange didn't happen, mark it as failed record_exchange_result(db, e.id, '', 'failed', 'interrupted', p) transfers = db.all(""" SELECT *, (t.timestamp < current_timestamp - interval '1 day') AS is_old FROM transfers t WHERE t.status = 'pre' """) for t in transfers: tipper = Participant.from_id(t.tipper) transactions = [x for x in User(id=tipper.mangopay_user_id).transactions.all( Sort='CreationDate:DESC', Type='TRANSFER' ) if x.Tag == str(t.id)] assert len(transactions) < 2 if transactions: record_transfer_result(db, t.id, transactions[0]) elif t.is_old: # The transfer didn't happen, mark it as failed _record_transfer_result(db, t.id, 'failed', 'interrupted') check_db(db)
def sync_with_mangopay(db): """We can get out of sync with MangoPay if record_exchange_result wasn't completed. This is where we fix that. """ check_db(db) exchanges = db.all("SELECT * FROM exchanges WHERE status = 'pre'") for e in exchanges: p = Participant.from_id(e.participant) transactions = mangoapi.users.GetTransactions(p.mangopay_user_id) transactions = [x for x in transactions if x.Tag == str(e.id)] assert len(transactions) < 2 if transactions: t = transactions[0] error = repr_error(t) status = t.Status.lower() assert (not error) ^ (status == 'failed') record_exchange_result(db, e.id, status, error, p) else: # The exchange didn't happen if e.amount < 0: # Mark it as failed if it was a credit record_exchange_result(db, e.id, 'failed', 'interrupted', p) else: # Otherwise forget about it db.run("DELETE FROM exchanges WHERE id=%s", (e.id, )) transfers = db.all("SELECT * FROM transfers WHERE status = 'pre'") for t in transfers: tipper = Participant.from_id(t.tipper) transactions = mangoapi.wallets.GetTransactions( tipper.mangopay_wallet_id) transactions = [ x for x in transactions if x.Type == 'TRANSFER' and x.Tag == str(t.id) ] assert len(transactions) < 2 if transactions: record_transfer_result(db, t.id, transactions[0]) else: # The transfer didn't happen, remove it db.run("DELETE FROM transfers WHERE id = %s", (t.id, )) check_db(db)
def sync_with_mangopay(db): """We can get out of sync with MangoPay if record_exchange_result wasn't completed. This is where we fix that. """ check_db(db) exchanges = db.all("SELECT * FROM exchanges WHERE status = 'pre'") for e in exchanges: p = Participant.from_id(e.participant) transactions = mangoapi.users.GetTransactions(p.mangopay_user_id) transactions = [x for x in transactions if x.Tag == str(e.id)] assert len(transactions) < 2 if transactions: t = transactions[0] error = repr_error(t) status = t.Status.lower() assert (not error) ^ (status == 'failed') record_exchange_result(db, e.id, status, error, p) else: # The exchange didn't happen, remove it db.run("DELETE FROM exchanges WHERE id=%s", (e.id,)) # and restore the participant's balance if it was a credit if e.amount < 0: db.run(""" UPDATE participants SET balance=(balance + %s) WHERE id=%s """, (-e.amount + e.fee, p.id)) transfers = db.all("SELECT * FROM transfers WHERE status = 'pre'") for t in transfers: tipper = Participant.from_id(t.tipper) transactions = mangoapi.wallets.GetTransactions(tipper.mangopay_wallet_id) transactions = [x for x in transactions if x.Type == 'TRANSFER' and x.Tag == str(t.id)] assert len(transactions) < 2 if transactions: record_transfer_result(db, t.id, t.tipper, t.tippee, t.amount, transactions[0]) else: # The transfer didn't happen, remove it db.run("DELETE FROM transfers WHERE id = %s", (t.id,)) check_db(db)
def main(): db = wireup.db(wireup.env()) populate_db(db) check_db(db)
def main(): db = wireup.db(wireup.env()) prep_db(db) populate_db(db) clean_db(db) check_db(db)