def test_payin_pays_in(self, sale, sfs, fch): fch.return_value = {} team = self.make_team('Gratiteam', is_approved=True) self.obama.set_payment_instruction(team, MINIMUM_CHARGE) # >= MINIMUM_CHARGE txn_attrs = { 'amount': MINIMUM_CHARGE, 'tax_amount': 0, 'status': 'authorized', 'custom_fields': {'participant_id': self.obama.id}, 'credit_card': {'token': self.obama_route.address}, 'id': 'dummy_id' } submitted_txn_attrs = txn_attrs.copy() submitted_txn_attrs.update(status='submitted_for_settlement') authorized_txn = braintree.Transaction(None, txn_attrs) submitted_txn = braintree.Transaction(None, submitted_txn_attrs) sale.return_value.transaction = authorized_txn sale.return_value.is_success = True sfs.return_value.transaction = submitted_txn sfs.return_value.is_success = True Payday.start().payin() payments = self.db.all("SELECT amount, direction FROM payments") assert payments == [(MINIMUM_CHARGE, 'to-team'), (MINIMUM_CHARGE, 'to-participant')]
def test_update_cached_amounts(self): team = self.make_participant('team', claimed_time='now', number='plural') alice = self.make_participant('alice', claimed_time='now', last_bill_result='') bob = self.make_participant('bob', claimed_time='now', last_bill_result=None) carl = self.make_participant('carl', claimed_time='now', last_bill_result="Fail!") dana = self.make_participant('dana', claimed_time='now') emma = self.make_participant('emma') roy = self.make_participant('roy', is_locked=True) alice.set_tip_to(dana, '3.00') alice.set_tip_to(bob, '6.00') alice.set_tip_to(emma, '1.00') alice.set_tip_to(team, '4.00') alice.set_tip_to(roy, '10.00') bob.set_tip_to(alice, '5.00') team.add_member(bob) team.set_take_for(bob, D('1.00'), bob) bob.set_tip_to(dana, '2.00') # funded by bob's take bob.set_tip_to(emma, '7.00') # not funded, insufficient receiving carl.set_tip_to(dana, '2.08') # not funded, failing card def check(): alice = Participant.from_username('alice') bob = Participant.from_username('bob') carl = Participant.from_username('carl') dana = Participant.from_username('dana') emma = Participant.from_username('emma') assert alice.giving == D('13.00') assert alice.pledging == D('1.00') assert alice.receiving == D('5.00') assert bob.giving == D('7.00') assert bob.receiving == D('7.00') assert bob.taking == D('1.00') assert carl.giving == D('0.00') assert carl.receiving == D('0.00') assert dana.receiving == D('5.00') assert dana.npatrons == 2 assert emma.receiving == D('1.00') assert emma.npatrons == 1 funded_tips = self.db.all("SELECT amount FROM tips WHERE is_funded ORDER BY id") assert funded_tips == [3, 6, 1, 4, 10, 5, 2] # Pre-test check check() # Check that update_cached_amounts doesn't mess anything up Payday.start().update_cached_amounts() check() # Check that update_cached_amounts actually updates amounts self.db.run(""" UPDATE tips SET is_funded = false; UPDATE participants SET giving = 0 , npatrons = 0 , pledging = 0 , receiving = 0 , taking = 0; """) Payday.start().update_cached_amounts() check()
def test_card_hold_error(self, tfh, fch): self.janet.set_tip_to(self.homer, 17) tfh.side_effect = Foobar fch.return_value = {} Payday.start().payin() payday = self.fetch_payday() assert payday['ncc_failing'] == 1
def payday(): # Wire things up. # =============== env = wireup.env() db = wireup.db(env) wireup.billing(env) wireup.nanswers(env) # Lazily import the billing module. # ================================= # This dodges a problem where db in billing is None if we import it from # gratipay before calling wireup.billing. from gratipay.billing.exchanges import sync_with_balanced from gratipay.billing.payday import Payday try: sync_with_balanced(db) Payday.start().run() except KeyboardInterrupt: pass except: import aspen import traceback aspen.log(traceback.format_exc())
def test_payin_doesnt_try_failed_cards(self, sale): team = self.make_team('Gratiteam', is_approved=True) self.obama_route.update_error('error') self.obama.set_payment_instruction(team, 1) Payday.start().payin() assert not sale.called
def test_update_cached_amounts_depth(self): alice = self.make_participant('alice', claimed_time='now', last_bill_result='') usernames = ('bob', 'carl', 'dana', 'emma', 'fred', 'greg') users = [ self.make_participant(username, claimed_time='now') for username in usernames ] prev = alice for user in reversed(users): prev.set_tip_to(user, '1.00') prev = user def check(): for username in reversed(usernames[1:]): user = Participant.from_username(username) assert user.giving == D('1.00') assert user.receiving == D('1.00') assert user.npatrons == 1 funded_tips = self.db.all( "SELECT id FROM tips WHERE is_funded ORDER BY id") assert len(funded_tips) == 6 check() Payday.start().update_cached_amounts() check()
def test_paydays_json_gives_paydays(self): Payday.start() self.make_participant("alice") response = self.client.GET("/about/paydays.json") paydays = json.loads(response.body) assert paydays[0]['ntippers'] == 0
def test_payout_skips_unreviewed(self, log): self.make_participant('alice', claimed_time='now', is_suspicious=None, balance=20, balanced_customer_href='foo', last_ach_result='') self.make_team(owner='alice', is_approved=True) Payday.start().payout() log.assert_any_call('UNREVIEWED: alice')
def test_payday_moves_money_cumulative_above_min_charge(self, fch): Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, '5.00') # < MINIMUM_CHARGE # simulate already due amount self.db.run(""" UPDATE payment_instructions ppi SET due = '5.00' WHERE ppi.participant = 'obama' AND ppi.team = 'TheEnterprise' """) assert self.obama.get_due('TheEnterprise') == D('5.00') fch.return_value = {} Payday.start().run() obama = Participant.from_username('obama') picard = Participant.from_username('picard') assert picard.balance == D('10.00') assert obama.balance == D('0.00') assert obama.get_due('TheEnterprise') == D('0.00')
def test_payin_doesnt_try_failed_cards(self, sale): team = self.make_team('Gratiteam', is_approved=True) self.obama_route.update_error('error') self.obama.set_subscription_to(team, 1) Payday.start().payin() assert not sale.called
def test_payin_pays_in(self, sale, sfs, fch): fch.return_value = {} team = self.make_team('Gratiteam', is_approved=True) self.obama.set_subscription_to(team, 1) txn_attrs = { 'amount': 1, 'tax_amount': 0, 'status': 'authorized', 'custom_fields': { 'participant_id': self.obama.id }, 'credit_card': { 'token': self.obama_route.address }, 'id': 'dummy_id' } submitted_txn_attrs = txn_attrs.copy() submitted_txn_attrs.update(status='submitted_for_settlement') authorized_txn = braintree.Transaction(None, txn_attrs) submitted_txn = braintree.Transaction(None, submitted_txn_attrs) sale.return_value.transaction = authorized_txn sale.return_value.is_success = True sfs.return_value.transaction = submitted_txn sfs.return_value.is_success = True Payday.start().payin() payments = self.db.all("SELECT amount, direction FROM payments") assert payments == [(1, 'to-team'), (1, 'to-participant')]
def test_card_hold_error(self, Customer, fch): self.janet.set_tip_to(self.homer, 17) Customer.side_effect = Foobar fch.return_value = {} Payday.start().payin() payday = self.fetch_payday() assert payday['ncc_failing'] == 1
def payday(): # Wire things up. # =============== env = wireup.env() db = wireup.db(env) wireup.billing(env) # Lazily import the billing module. # ================================= # This dodges a problem where db in billing is None if we import it from # gratipay before calling wireup.billing. from gratipay.billing.exchanges import sync_with_balanced from gratipay.billing.payday import Payday try: sync_with_balanced(db) Payday.start().run() except KeyboardInterrupt: pass except: import aspen import traceback aspen.log(traceback.format_exc())
def test_payin_doesnt_make_null_payments(self): team = self.make_team('Gratiteam', is_approved=True) alice = self.make_participant('alice', claimed_time='now') alice.set_payment_instruction(team, 1) alice.set_payment_instruction(team, 0) Payday.start().payin() payments = self.db.all("SELECT * FROM payments WHERE amount = 0") assert not payments
def test_update_receiving_amounts_updates_receiving_amounts(self): A = self.make_participant('A') B = self.make_participant('B', claimed_time='now', last_bill_result='') B.set_tip_to(A, D('10.00'), update_tippee=False) assert Participant.from_username('A').receiving == 0 Payday.start().update_receiving_amounts() assert Participant.from_username('A').receiving == 10
def test_card_hold_error(self, bt_sale, fch): team = self.make_team(owner=self.homer, is_approved=True) self.obama.set_subscription_to(team, '17.00') bt_sale.side_effect = Foobar fch.return_value = {} Payday.start().payin() payday = self.fetch_payday() assert payday['ncc_failing'] == 1
def test_card_hold_error(self, tfh, fch): team = self.make_team(owner=self.homer, is_approved=True) self.janet.set_subscription_to(team, '17.00') tfh.side_effect = Foobar fch.return_value = {} Payday.start().payin() payday = self.fetch_payday() assert payday['ncc_failing'] == 1
def test_payout_ach_error(self, ach_credit): self.make_participant('alice', claimed_time='now', is_suspicious=False, balance=20, balanced_customer_href='foo', last_ach_result='') ach_credit.return_value = 'some error' Payday.start().payout() payday = self.fetch_payday() assert payday['nach_failing'] == 1
def test_card_hold_error(self, bt_sale, fch): team = self.make_team(owner=self.homer, is_approved=True) self.obama.set_payment_instruction(team, '17.00') bt_sale.side_effect = Foobar fch.return_value = {} Payday.start().payin() payday = self.fetch_payday() assert payday['ncc_failing'] == 1
def test_update_cached_amounts(self): team = self.make_participant('team', claimed_time='now', number='plural') alice = self.make_participant('alice', claimed_time='now', last_bill_result='') bob = self.make_participant('bob', claimed_time='now', last_bill_result=None) carl = self.make_participant('carl', claimed_time='now', last_bill_result="Fail!") dana = self.make_participant('dana', claimed_time='now') emma = self.make_participant('emma') alice.set_tip_to(dana, '3.00') alice.set_tip_to(bob, '6.00') alice.set_tip_to(emma, '1.00') alice.set_tip_to(team, '4.00') bob.set_tip_to(alice, '5.00') team.add_member(bob) team.set_take_for(bob, D('1.00'), bob) bob.set_tip_to(dana, '2.00') # funded by bob's take bob.set_tip_to(emma, '7.00') # not funded, insufficient receiving carl.set_tip_to(dana, '2.08') # not funded, failing card def check(): alice = Participant.from_username('alice') bob = Participant.from_username('bob') carl = Participant.from_username('carl') dana = Participant.from_username('dana') emma = Participant.from_username('emma') assert alice.giving == D('13.00') assert alice.pledging == D('1.00') assert alice.receiving == D('5.00') assert bob.giving == D('7.00') assert bob.receiving == D('7.00') assert bob.taking == D('1.00') assert carl.giving == D('0.00') assert carl.receiving == D('0.00') assert dana.receiving == D('5.00') assert dana.npatrons == 2 assert emma.receiving == D('1.00') assert emma.npatrons == 1 funded_tips = self.db.all("SELECT amount FROM tips WHERE is_funded ORDER BY id") assert funded_tips == [3, 6, 1, 4, 5, 2] # Pre-test check check() # Check that update_cached_amounts doesn't mess anything up Payday.start().update_cached_amounts() check() # Check that update_cached_amounts actually updates amounts self.db.run(""" UPDATE tips SET is_funded = false; UPDATE participants SET giving = 0 , npatrons = 0 , pledging = 0 , receiving = 0 , taking = 0; """) Payday.start().update_cached_amounts() check()
def test_payin_doesnt_make_null_transfers(self): alice = self.make_participant('alice', claimed_time='now') alice.set_tip_to(self.homer, 1) alice.set_tip_to(self.homer, 0) a_team = self.make_participant('a_team', claimed_time='now', number='plural') a_team.add_member(alice) Payday.start().payin() transfers0 = self.db.all("SELECT * FROM transfers WHERE amount = 0") assert not transfers0
def test_payout_unreviewed(self, log): self.make_participant('alice', claimed_time='now', is_suspicious=None, balance=20, balanced_customer_href='foo', last_ach_result='') Payday.start().payout() log.assert_any_call('UNREVIEWED: alice')
def test_paying_out_sets_1_0_status_to_resolved(self, credit): alice = self.make_participant('alice', claimed_time='now', is_suspicious=False, balanced_customer_href='foo', last_ach_result='', balance=0, status_of_1_0_balance='pending-payout') self.make_exchange('balanced-cc', 20, 0, alice) # sets balance, and satisfies self_check Payday.start().payout() alice = Participant.from_username('alice') assert alice.status_of_1_0_balance == 'resolved' assert alice.balance == 0
def test_payout_pays_out_Gratipay_1_0_balance(self, ach): alice = self.make_participant('alice', claimed_time='now', is_suspicious=False, balanced_customer_href='foo', last_ach_result='', balance=20, status_of_1_0_balance='pending-payout') Payday.start().payout() assert ach.call_count == 1 assert ach.call_args_list[0][0][1].id == alice.id assert ach.call_args_list[0][0][2] == 0
def test_iter_payday_events(self): now = datetime.now() Payday().start().run() Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, '10.00') # >= MINIMUM_CHARGE! for i in range(2): with patch.object(Payday, 'fetch_card_holds') as fch: fch.return_value = {} Payday.start().run() self.db.run(""" UPDATE paydays SET ts_start = ts_start - interval '1 week' , ts_end = ts_end - interval '1 week'; UPDATE payments SET timestamp = "timestamp" - interval '1 week'; UPDATE transfers SET timestamp = "timestamp" - interval '1 week'; """) obama = Participant.from_username('obama') picard = Participant.from_username('picard') assert obama.balance == D('0.00') assert picard.balance == D('20.00') Payday().start() # to demonstrate that we ignore any open payday? # Make all events in the same year. delta = '%s days' % (364 - (now - datetime(now.year, 1, 1)).days) self.db.run( """ UPDATE paydays SET ts_start = ts_start + interval %(delta)s , ts_end = ts_end + interval %(delta)s; UPDATE payments SET timestamp = "timestamp" + interval %(delta)s; UPDATE transfers SET timestamp = "timestamp" + interval %(delta)s; """, dict(delta=delta)) events = list(iter_payday_events(self.db, picard, now.year)) assert len(events) == 7 assert events[0]['kind'] == 'totals' assert events[0]['given'] == 0 assert events[0]['received'] == 20 assert events[1]['kind'] == 'day-open' assert events[1]['payday_number'] == 2 assert events[2]['balance'] == 20 assert events[-1]['kind'] == 'day-close' assert events[-1]['balance'] == 0 events = list(iter_payday_events(self.db, obama)) assert events[0]['given'] == 20 assert len(events) == 11
def test_iter_payday_events(self): Payday.start().run() team = self.make_participant('team', number='plural', claimed_time='now') alice = self.make_participant('alice', claimed_time='now') self.make_exchange('bill', 10000, 0, team) self.make_exchange('bill', 10000, 0, alice) self.make_exchange('bill', -5000, 0, alice) self.db.run(""" UPDATE transfers SET timestamp = "timestamp" - interval '1 month' """) bob = self.make_participant('bob', claimed_time='now') carl = self.make_participant('carl', claimed_time='now') team.add_member(bob) team.set_take_for(bob, Decimal('1.00'), team) alice.set_tip_to(bob, Decimal('5.00')) assert bob.balance == 0 for i in range(2): with patch.object(Payday, 'fetch_card_holds') as fch: fch.return_value = {} Payday.start().run() self.db.run(""" UPDATE paydays SET ts_start = ts_start - interval '1 week' , ts_end = ts_end - interval '1 week'; UPDATE transfers SET timestamp = "timestamp" - interval '1 week'; """) bob = Participant.from_id(bob.id) assert bob.balance == 12 Payday().start() events = list(iter_payday_events(self.db, bob)) assert len(events) == 9 assert events[0]['kind'] == 'totals' assert events[0]['given'] == 0 assert events[0]['received'] == 12 assert events[1]['kind'] == 'day-open' assert events[1]['payday_number'] == 2 assert events[2]['balance'] == 12 assert events[-1]['kind'] == 'day-close' assert events[-1]['balance'] == '0.00' alice = Participant.from_id(alice.id) assert alice.balance == 4990 events = list(iter_payday_events(self.db, alice)) assert events[0]['given'] == 10 assert len(events) == 11 carl = Participant.from_id(carl.id) assert carl.balance == 0 events = list(iter_payday_events(self.db, carl)) assert len(events) == 0
def test_payday_moves_money(self, fch): self.janet.set_tip_to(self.homer, '6.00') # under $10! fch.return_value = {} Payday.start().run() janet = Participant.from_username('janet') homer = Participant.from_username('homer') assert homer.balance == D('6.00') assert janet.balance == D('3.41')
def test_nusers_includes_dues(self, fch): Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, '6.00') # below MINIMUM_CHARGE fch.return_value = {} Payday.start().run() assert self.obama.get_due(Enterprise) == D('6.00') nusers = self.db.one("SELECT nusers FROM paydays") assert nusers == 1
def test_payin_doesnt_make_null_payments(self): team = self.make_team('Gratiteam', is_approved=True) alice = self.make_participant('alice', claimed_time='now') alice.set_subscription_to(team, 1) alice.set_subscription_to(team, 0) a_team = self.make_participant('a_team', claimed_time='now', number='plural') a_team.add_member(alice) Payday.start().payin() payments = self.db.all("SELECT * FROM payments WHERE amount = 0") assert not payments
def test_iter_payday_events(self): now = datetime.now() Payday().start().run() Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, '10.00') # >= MINIMUM_CHARGE! for i in range(2): with patch.object(Payday, 'fetch_card_holds') as fch: fch.return_value = {} Payday.start().run() self.db.run(""" UPDATE paydays SET ts_start = ts_start - interval '1 week' , ts_end = ts_end - interval '1 week'; UPDATE payments SET timestamp = "timestamp" - interval '1 week'; UPDATE transfers SET timestamp = "timestamp" - interval '1 week'; """) obama = P('obama') picard = P('picard') assert obama.balance == D('0.00') assert picard.balance == D('20.00') Payday().start() # to demonstrate that we ignore any open payday? # Make all events in the same year. delta = '%s days' % (364 - (now - datetime(now.year, 1, 1)).days) self.db.run(""" UPDATE paydays SET ts_start = ts_start + interval %(delta)s , ts_end = ts_end + interval %(delta)s; UPDATE payments SET timestamp = "timestamp" + interval %(delta)s; UPDATE transfers SET timestamp = "timestamp" + interval %(delta)s; """, dict(delta=delta)) events = list(iter_payday_events(self.db, picard, now.year)) assert len(events) == 7 assert events[0]['kind'] == 'totals' assert events[0]['given'] == 0 assert events[0]['received'] == 20 assert events[1]['kind'] == 'day-open' assert events[1]['payday_number'] == 2 assert events[2]['balance'] == 20 assert events[-1]['kind'] == 'day-close' assert events[-1]['balance'] == 0 events = list(iter_payday_events(self.db, obama)) assert events[0]['given'] == 20 assert len(events) == 11
def test_iter_payday_events(self): Payday.start().run() team = self.make_participant('team', number='plural', claimed_time='now') alice = self.make_participant('alice', claimed_time='now') self.make_exchange('balanced-cc', 10000, 0, team) self.make_exchange('balanced-cc', 10000, 0, alice) self.make_exchange('balanced-cc', -5000, 0, alice) self.db.run(""" UPDATE transfers SET timestamp = "timestamp" - interval '1 month' """) bob = self.make_participant('bob', claimed_time='now') carl = self.make_participant('carl', claimed_time='now') team.add_member(bob) team.set_take_for(bob, Decimal('1.00'), team) alice.set_tip_to(bob, Decimal('5.00')) assert bob.balance == 0 for i in range(2): with patch.object(Payday, 'fetch_card_holds') as fch: fch.return_value = {} Payday.start().run() self.db.run(""" UPDATE paydays SET ts_start = ts_start - interval '1 week' , ts_end = ts_end - interval '1 week'; UPDATE transfers SET timestamp = "timestamp" - interval '1 week'; """) bob = Participant.from_id(bob.id) assert bob.balance == 12 Payday().start() events = list(iter_payday_events(self.db, bob)) assert len(events) == 9 assert events[0]['kind'] == 'totals' assert events[0]['given'] == 0 assert events[0]['received'] == 12 assert events[1]['kind'] == 'day-open' assert events[1]['payday_number'] == 2 assert events[2]['balance'] == 12 assert events[-1]['kind'] == 'day-close' assert events[-1]['balance'] == 0 alice = Participant.from_id(alice.id) assert alice.balance == 4990 events = list(iter_payday_events(self.db, alice)) assert events[0]['given'] == 10 assert len(events) == 11 carl = Participant.from_id(carl.id) assert carl.balance == 0 events = list(iter_payday_events(self.db, carl)) assert len(events) == 0
def test_payin_dumps_transfers_for_debugging(self, cch, fch): self.janet.set_tip_to(self.homer, 10) fake_hold = mock.MagicMock() fake_hold.amount = 1500 fch.return_value = {self.janet.id: fake_hold} cch.side_effect = Foobar open = mock.MagicMock() with mock.patch.dict(__builtins__, {'open': open}): with self.assertRaises(Foobar): Payday.start().payin() assert open.call_count == 1
def test_payout_can_pay_out(self, ach): alice = self.make_participant('alice', claimed_time='now', is_suspicious=False, balanced_customer_href='foo', last_ach_result='') self.make_exchange('balanced-cc', 20, 0, alice) self.make_team(owner='alice', is_approved=True) Payday.start().payout() assert ach.call_count == 1 assert ach.call_args_list[0][0][1].id == alice.id assert ach.call_args_list[0][0][2] == 0
def test_payday_moves_money(self, fch): A = self.make_team(is_approved=True) self.obama.set_subscription_to(A, '6.00') # under $10! fch.return_value = {} Payday.start().run() obama = Participant.from_username('obama') hannibal = Participant.from_username('hannibal') assert hannibal.balance == D('6.00') assert obama.balance == D('3.41')
def test_payday_does_not_move_money_below_min_charge(self, fch): Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, '6.00') # not enough to reach MINIMUM_CHARGE fch.return_value = {} Payday.start().run() obama = P('obama') picard = P('picard') assert picard.balance == D('0.00') assert obama.balance == D('0.00') assert obama.get_due(Enterprise) == D('6.00')
def test_transfer_takes_doesnt_make_negative_transfers(self, fch): hold = balanced.CardHold(amount=1500, meta={'participant_id': self.janet.id}) hold.capture = lambda *a, **kw: None hold.save = lambda *a, **kw: None fch.return_value = {self.janet.id: hold} self.janet.update_number('plural') self.janet.set_tip_to(self.homer, 10) self.janet.add_member(self.david) Payday.start().payin() assert Participant.from_id(self.david.id).balance == 0 assert Participant.from_id(self.homer.id).balance == 10 assert Participant.from_id(self.janet.id).balance == 0
def test_payin_cancels_uncaptured_holds(self, log): self.janet.set_tip_to(self.homer, 42) alice = self.make_participant('alice', claimed_time='now', is_suspicious=False) self.make_exchange('balanced-cc', 50, 0, alice) alice.set_tip_to(self.janet, 50) Payday.start().payin() assert log.call_args_list[-3][0] == ("Captured 0 card holds.",) assert log.call_args_list[-2][0] == ("Canceled 1 card holds.",) assert Participant.from_id(alice.id).balance == 0 assert Participant.from_id(self.janet.id).balance == 8 assert Participant.from_id(self.homer.id).balance == 42
def test_payday_does_not_move_money_below_min_charge(self, fch): Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, '6.00') # not enough to reach MINIMUM_CHARGE fch.return_value = {} Payday.start().run() obama = Participant.from_username('obama') picard = Participant.from_username('picard') assert picard.balance == D('0.00') assert obama.balance == D('0.00') assert obama.get_due('TheEnterprise') == D('6.00')
def test_payout_ignores_unresolved(self, credit): bob = self.make_participant('bob', claimed_time='now', is_suspicious=False, balanced_customer_href='foo', last_ach_result='', balance=13, status_of_1_0_balance='unresolved') alice = self.make_participant('alice', claimed_time='now', is_suspicious=False, balanced_customer_href='foo', last_ach_result='', balance=0, status_of_1_0_balance='pending-payout') self.make_exchange('balanced-cc', 20, 0, alice) Payday.start().payout() bob = Participant.from_username('bob') assert bob.status_of_1_0_balance == 'unresolved' assert bob.balance == 13
def test_payday_moves_money(self): Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, '6.00') # under $10! with mock.patch.object(Payday, 'fetch_card_holds') as fch: fch.return_value = {} Payday.start().run() obama = Participant.from_username('obama') picard = Participant.from_username('picard') assert picard.balance == D('6.00') assert obama.balance == D('3.41')
def test_payday_moves_money(self): A = self.make_team(is_approved=True) self.obama.set_payment_instruction(A, '6.00') # under $10! with mock.patch.object(Payday, 'fetch_card_holds') as fch: fch.return_value = {} Payday.start().run() obama = Participant.from_username('obama') hannibal = Participant.from_username('hannibal') assert hannibal.balance == D('6.00') assert obama.balance == D('3.41')
def test_payin_cancels_uncaptured_holds(self, log): self.janet.set_tip_to(self.homer, 42) alice = self.make_participant('alice', claimed_time='now', is_suspicious=False) self.make_exchange('bill', 50, 0, alice) alice.set_tip_to(self.janet, 50) Payday.start().payin() assert log.call_args_list[-3][0] == ("Captured 0 card holds.",) assert log.call_args_list[-2][0] == ("Canceled 1 card holds.",) assert Participant.from_id(alice.id).balance == 0 assert Participant.from_id(self.janet.id).balance == 8 assert Participant.from_id(self.homer.id).balance == 42
def test_payday_moves_money_above_min_charge(self): Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, MINIMUM_CHARGE) # must be >= MINIMUM_CHARGE with mock.patch.object(Payday, 'fetch_card_holds') as fch: fch.return_value = {} Payday.start().run() obama = Participant.from_username('obama') picard = Participant.from_username('picard') assert picard.balance == D(MINIMUM_CHARGE) assert obama.balance == D('0.00') assert obama.get_due('TheEnterprise') == D('0.00')
def test_payday_moves_money_above_min_charge(self, fch): Enterprise = self.make_team(is_approved=True) self.obama.set_payment_instruction(Enterprise, MINIMUM_CHARGE) # must be >= MINIMUM_CHARGE fch.return_value = {} Payday.start().run() obama = P('obama') picard = P('picard') assert picard.balance == D(MINIMUM_CHARGE) assert obama.balance == D('0.00') assert obama.get_due(Enterprise) == D('0.00')
def test_payin_dumps_transfers_for_debugging(self, cch, fch): self.janet.set_tip_to(self.homer, 10) fake_hold = mock.MagicMock() fake_hold.amount = 1500 fch.return_value = {self.janet.id: fake_hold} cch.side_effect = Foobar open_ = mock.MagicMock() open_.side_effect = open with mock.patch.dict(__builtins__, {'open': open_}): with self.assertRaises(Foobar): Payday.start().payin() filename = open_.call_args_list[-1][0][0] assert filename.endswith('_transfers.csv') os.unlink(filename)
def test_payin_dumps_transfers_for_debugging(self, cch, fch): team = self.make_team(owner=self.homer, is_approved=True) self.obama.set_subscription_to(team, '10.00') fake_hold = mock.MagicMock() fake_hold.amount = 1500 fch.return_value = {self.obama.id: fake_hold} cch.side_effect = Foobar open_ = mock.MagicMock() open_.side_effect = open with mock.patch.dict(__builtins__, {'open': open_}): with self.assertRaises(Foobar): Payday.start().payin() filename = open_.call_args_list[-1][0][0] assert filename.endswith('_payments.csv') os.unlink(filename)
def test_payday_doesnt_move_money_to_a_suspicious_account(self, fch): self.db.run(""" UPDATE participants SET is_suspicious = true WHERE username = '******' """) self.janet.set_tip_to(self.homer, '6.00') # under $10! fch.return_value = {} Payday.start().run() janet = Participant.from_username('janet') homer = Participant.from_username('homer') assert janet.balance == D('0.00') assert homer.balance == D('0.00')
def test_start_prepare(self, log): self.clear_tables() self.make_participant('bob', balance=10, claimed_time=None) self.make_participant('carl', balance=10, claimed_time='now') payday = Payday.start() ts_start = payday.ts_start get_participants = lambda c: c.all("SELECT * FROM payday_participants") with self.db.get_cursor() as cursor: payday.prepare(cursor, ts_start) participants = get_participants(cursor) expected_logging_call_args = [ ('Starting a new payday.'), ('Payday started at {}.'.format(ts_start)), ('Prepared the DB.'), ] expected_logging_call_args.reverse() for args, _ in log.call_args_list: assert args[0] == expected_logging_call_args.pop() log.reset_mock() # run a second time, we should see it pick up the existing payday payday = Payday.start() second_ts_start = payday.ts_start with self.db.get_cursor() as cursor: payday.prepare(cursor, second_ts_start) second_participants = get_participants(cursor) assert ts_start == second_ts_start participants = list(participants) second_participants = list(second_participants) # carl is the only valid participant as he has a claimed time assert len(participants) == 1 assert participants == second_participants expected_logging_call_args = [ ('Picking up with an existing payday.'), ('Payday started at {}.'.format(second_ts_start)), ('Prepared the DB.'), ] expected_logging_call_args.reverse() for args, _ in log.call_args_list: assert args[0] == expected_logging_call_args.pop()