def setUp(self): Harness.setUp(self) self.david = self.make_participant( "david", is_suspicious=False, mangopay_user_id=self.david_id, mangopay_wallet_id=self.david_wallet_id, email="*****@*****.**", ) self.janet = self.make_participant( "janet", is_suspicious=False, mangopay_user_id=self.janet_id, mangopay_wallet_id=self.janet_wallet_id, email="*****@*****.**", ) self.janet_route = ExchangeRoute.insert(self.janet, "mango-cc", self.card_id) self.homer = self.make_participant( "homer", is_suspicious=False, mangopay_user_id=self.homer_id, mangopay_wallet_id=self.homer_wallet_id, email="*****@*****.**", ) self.homer_route = ExchangeRoute.insert(self.homer, "mango-ba", self.bank_account.Id)
def setUp(self): Harness.setUp(self) self.david = self.make_participant( 'david', mangopay_user_id=self.david_id, mangopay_wallet_id=self.david_wallet_id, email='*****@*****.**') self.janet = self.make_participant( 'janet', mangopay_user_id=self.janet_id, mangopay_wallet_id=self.janet_wallet_id, email='*****@*****.**') self.janet_route = ExchangeRoute.insert(self.janet, 'mango-cc', self.card_id, 'chargeable', currency='EUR') self.homer = self.make_participant( 'homer', mangopay_user_id=self.homer_id, mangopay_wallet_id=self.homer_wallet_id, email='*****@*****.**') self.homer_route = ExchangeRoute.insert(self.homer, 'mango-ba', self.bank_account.Id, 'chargeable')
def make_participant(self, username, **kw): platform = kw.pop('elsewhere', 'github') domain = kw.pop('domain', '') kw2 = {} for key in ('last_bill_result', 'balance', 'mangopay_wallet_id'): if key in kw: kw2[key] = kw.pop(key) kind = kw.setdefault('kind', 'individual') if kind not in ('group', 'community'): kw.setdefault('password', 'x') kw.setdefault('session_token', username) i = next(self.seq) kw.setdefault('mangopay_user_id', -i) kw.setdefault('status', 'active') if username: kw['username'] = username if 'join_time' not in kw: kw['join_time'] = utcnow() cols, vals = zip(*kw.items()) cols = ', '.join(cols) placeholders = ', '.join(['%s']*len(vals)) participant = self.db.one(""" INSERT INTO participants ({0}) VALUES ({1}) RETURNING participants.*::participants """.format(cols, placeholders), vals) self.db.run(""" INSERT INTO elsewhere (platform, user_id, user_name, participant, domain) VALUES (%s,%s,%s,%s,%s) """, (platform, participant.id, username, participant.id, domain)) if kind not in ('group', 'community') and participant.mangopay_user_id: wallet_id = kw2.get('mangopay_wallet_id', -participant.id) zero = ZERO[participant.main_currency] self.db.run(""" INSERT INTO wallets (remote_id, balance, owner, remote_owner_id) VALUES (%s, %s, %s, %s) """, (wallet_id, zero, participant.id, participant.mangopay_user_id)) if 'email' in kw: self.db.run(""" INSERT INTO emails (participant, address, verified, verified_time) VALUES (%s, %s, true, now()) """, (participant.id, kw['email'])) if 'last_bill_result' in kw2: ExchangeRoute.insert( participant, 'mango-cc', '-1', kw2['last_bill_result'], currency=participant.main_currency ) if 'balance' in kw2 and kw2['balance'] != 0: self.make_exchange('mango-cc', kw2['balance'], 0, participant) return participant
def test_get_tip_distribution_ignores_bad_cc(self): bad_cc = self.make_participant('bad_cc') ExchangeRoute.insert(bad_cc, 'mango-cc', '-1', 'failed', currency='EUR') self.alice.set_tip_to(self.bob, EUR('1.00')) self.make_payin_and_transfer(self.alice_card, self.bob, EUR('25.00')) bad_cc.set_tip_to(self.bob, EUR('3.00')) expected = ([[EUR('1.00'), 1, EUR('1.00'), EUR('1.00'), 1, Decimal('1')]], 1, EUR('1.00')) actual = self.bob.get_tip_distribution() assert actual == expected
def _test_payin_bank_wire_callback_amount_mismatch(self, Get, fee): homer = self.homer route = ExchangeRoute.insert(homer, 'mango-bw', 'x') e_id = record_exchange(self.db, route, 11, 0, 0, homer, 'pre') assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYIN_NORMAL_SUCCEEDED&RessourceId=123456790" payin = BankWirePayIn() payin.Status = 'SUCCEEDED' payin.ResultCode = '000000' payin.ResultMessage = None payin.AuthorId = homer.mangopay_user_id payin.PaymentType = 'BANK_WIRE' payin.DeclaredDebitedFunds = Money(4500, 'EUR') payin.DeclaredFees = Money(100, 'EUR') payin.DebitedFunds = Money(302, 'EUR') payin.Fees = Money(fee, 'EUR') payin.CreditedFunds = Money(302 - fee, 'EUR') payin.Tag = str(e_id) Get.return_value = payin r = self.callback(qs) assert r.code == 200, r.text e = self.db.one("SELECT * FROM exchanges WHERE id = %s", (e_id, )) assert e.amount == D(payin.CreditedFunds.Amount) / D(100) assert e.fee == D(fee) / D(100) assert e.vat == D('0.01') assert e.status == 'succeeded' homer = homer.refetch() assert homer.balance == e.amount assert homer.status == 'active' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert 'succ' in emails[0]['subject']
def setUp(self): Harness.setUp(self) self.david = self.make_participant( 'david', mangopay_user_id=self.david_id, mangopay_wallet_id=self.david_wallet_id, email='*****@*****.**' ) self.janet = self.make_participant( 'janet', mangopay_user_id=self.janet_id, mangopay_wallet_id=self.janet_wallet_id, email='*****@*****.**' ) self.janet_route = ExchangeRoute.insert(self.janet, 'mango-cc', self.card_id) self.homer = self.make_participant( 'homer', mangopay_user_id=self.homer_id, mangopay_wallet_id=self.homer_wallet_id, email='*****@*****.**' ) self.homer_route = ExchangeRoute.insert(self.homer, 'mango-ba', self.bank_account.Id)
def test_payout_amount_under_minimum(self, gba): usd_user = self.make_participant('usd_user', main_currency='USD') route = ExchangeRoute.insert(usd_user, 'mango-ba', 'fake ID', 'chargeable') self.make_exchange('mango-cc', USD(8), 0, usd_user) gba.return_value = self.bank_account_outside_sepa with self.assertRaises(FeeExceedsAmount): payout(self.db, route, USD('0.10'))
def make_exchange(self, route, amount, fee, participant, status='succeeded', error='', vat=0): amount = amount if isinstance(amount, Money) else Money(amount, 'EUR') fee = fee if isinstance(fee, Money) else Money(fee, amount.currency) vat = vat if isinstance(vat, Money) else Money(vat, fee.currency) if not isinstance(route, ExchangeRoute): network = route currency = amount.currency if network == 'mango-cc' else None routes = ExchangeRoute.from_network(participant, network, currency=currency) if routes: route = routes[0] else: from .mangopay import MangopayHarness address = MangopayHarness.card_id if network == 'mango-cc' else -participant.id route = ExchangeRoute.insert(participant, network, address, 'chargeable', currency=currency) assert route e_id = record_exchange(self.db, route, amount, fee, vat, participant, 'pre').id record_exchange_result(self.db, e_id, -e_id, status, error, participant) return e_id
def test_negative_paid_in_advance(self): team = self.make_participant('team', kind='group') alice = self.make_participant('alice') team.set_take_for(alice, EUR('1.00'), team) stripe_account_alice = self.add_payment_account(alice, 'stripe') donor = self.make_participant('donor') donor.set_tip_to(team, EUR('5')) donor_card = ExchangeRoute.insert(donor, 'stripe-card', 'x', 'chargeable', remote_user_id='x') payin, pt = self.make_payin_and_transfer(donor_card, team, EUR('10'), 'stripe') assert pt.destination == stripe_account_alice.pk self.db.run("UPDATE takes SET paid_in_advance = -paid_in_advance") Payday.start().run() transfers = self.db.all("SELECT * FROM transfers ORDER BY id") assert len(transfers) == 0
def test_takes_paid_in_advance(self): team = self.make_participant( 'team', kind='group', accepted_currencies='EUR,USD' ) alice = self.make_participant('alice', main_currency='EUR', accepted_currencies='EUR,USD') team.set_take_for(alice, EUR('1.00'), team) bob = self.make_participant('bob', main_currency='USD', accepted_currencies='EUR,USD') team.set_take_for(bob, EUR('1.00'), team) stripe_account_alice = self.add_payment_account(alice, 'stripe', default_currency='EUR') self.add_payment_account(bob, 'stripe', default_currency='USD') carl = self.make_participant('carl') carl.set_tip_to(team, EUR('10')) carl_card = ExchangeRoute.insert( carl, 'stripe-card', 'x', 'chargeable', remote_user_id='x' ) payin, pt = self.make_payin_and_transfer(carl_card, team, EUR('10')) assert pt.destination == stripe_account_alice.pk Payday.start().run() transfers = self.db.all("SELECT * FROM transfers ORDER BY id") assert len(transfers) == 1 assert transfers[0].virtual is True assert transfers[0].tipper == carl.id assert transfers[0].tippee == alice.id assert transfers[0].amount == EUR('1')
def test_takes_paid_in_advance(self): team = self.make_participant( 'team', kind='group', accepted_currencies='EUR,USD' ) alice = self.make_participant('alice', main_currency='EUR', accepted_currencies='EUR,USD') team.set_take_for(alice, EUR('1.00'), team) bob = self.make_participant('bob', main_currency='USD', accepted_currencies='EUR,USD') team.set_take_for(bob, EUR('1.00'), team) stripe_account_alice = self.add_payment_account(alice, 'stripe', default_currency='EUR') self.add_payment_account(bob, 'stripe', country='US', default_currency='USD') carl = self.make_participant('carl') carl.set_tip_to(team, EUR('10')) carl_card = ExchangeRoute.insert( carl, 'stripe-card', 'x', 'chargeable', remote_user_id='x' ) payin, pt = self.make_payin_and_transfer(carl_card, team, EUR('10')) assert pt.destination == stripe_account_alice.pk Payday.start().run() transfers = self.db.all("SELECT * FROM transfers ORDER BY id") assert len(transfers) == 1 assert transfers[0].virtual is True assert transfers[0].tipper == carl.id assert transfers[0].tippee == alice.id assert transfers[0].amount == EUR('1')
def test_payout_amount_under_minimum(self, gba): usd_user = self.make_participant('usd_user', main_currency='USD') route = ExchangeRoute.insert(usd_user, 'mango-ba', 'fake ID') self.make_exchange('mango-cc', USD(8), 0, usd_user) gba.return_value = self.bank_account_outside_sepa with self.assertRaises(FeeExceedsAmount): payout(self.db, route, USD('0.10'))
def test_identity_form(self): janeway = self.make_participant( 'janeway', email='*****@*****.**', mangopay_user_id=None, ) assert janeway.mangopay_user_id is None # Create a mangopay natural user data = dict(user_data, terms='agree') kw = dict(auth_as=janeway, raise_immediately=False, xhr=True) r = self.client.POST('/janeway/identity', data, **kw) assert r.code == 200, r.text janeway = janeway.refetch() assert janeway.mangopay_user_id # Test the rendering of the identity page r = self.client.GET('/janeway/identity.html', auth_as=janeway) assert r.code == 200, r.text assert user_data['FirstName'] in r.text # Edit the natural user data2 = dict(data, FirstName='Kathryn', Nationality='US', Birthday='1970-01-01') r = self.client.POST('/janeway/identity', data2, **kw) assert r.code == 200, r.text janeway2 = janeway.refetch() assert janeway2.mangopay_user_id == janeway.mangopay_user_id # Add some money for the next test create_wallet(self.db, janeway, 'EUR') cr = create_card(janeway.mangopay_user_id) route = ExchangeRoute.insert(janeway, 'mango-cc', cr.CardId, 'chargeable', currency='EUR') charge(self.db, route, EUR('20.00'), 'http://127.0.0.1/') # Switch to a legal user data = dict(data2) data['organization'] = 'yes' data['LegalPersonType'] = 'BUSINESS' data['Name'] = 'Starfleet' data['confirmed'] = 'yes' r = self.client.POST('/janeway/identity', data, **kw) assert r.code == 200, r.text janeway = janeway.refetch() assert janeway.mangopay_user_id != janeway2.mangopay_user_id assert janeway.kind == 'organization' self.db.self_check() # Edit the legal user data2 = dict(data, LegalPersonType='ORGANIZATION') r = self.client.POST('/janeway/identity', data2, **kw) assert r.code == 200, r.text janeway2 = janeway.refetch() assert janeway2.mangopay_user_id == janeway.mangopay_user_id
def payin_bank_wire(db, participant, debit_amount): """Prepare to receive a bank wire payin. The amount should be how much the user intends to send, not how much will arrive in the wallet. """ route = ExchangeRoute.from_network(participant, 'mango-bw') if not route: route = ExchangeRoute.insert(participant, 'mango-bw', 'x') amount, fee, vat = skim_bank_wire(debit_amount) e_id = record_exchange(db, route, amount, fee, vat, participant, 'pre') payin = BankWirePayIn() payin.AuthorId = participant.mangopay_user_id if not participant.mangopay_wallet_id: create_wallet(db, participant) payin.CreditedWalletId = participant.mangopay_wallet_id payin.DeclaredDebitedFunds = Money(int(debit_amount * 100), 'EUR') payin.DeclaredFees = Money(int(fee * 100), 'EUR') payin.Tag = str(e_id) try: test_hook() payin.save() except Exception as e: error = repr_exception(e) return None, record_exchange_result(db, e_id, 'failed', error, participant) e = record_exchange_result(db, e_id, payin.Status.lower(), repr_error(payin), participant) return payin, e
def payin_bank_wire(db, participant, debit_amount): """Prepare to receive a bank wire payin. The amount should be how much the user intends to send, not how much will arrive in the wallet. """ route = ExchangeRoute.from_network(participant, 'mango-bw') if not route: route = ExchangeRoute.insert(participant, 'mango-bw', 'x') amount, fee, vat = skim_amount(debit_amount, FEE_PAYIN_BANK_WIRE) e_id = record_exchange(db, route, amount, fee, vat, participant, 'pre') payin = PayIn() payin.AuthorId = participant.mangopay_user_id if not participant.mangopay_wallet_id: create_wallet(db, participant) payin.CreditedWalletId = participant.mangopay_wallet_id payin.ExecutionDetails = PayInExecutionDetailsDirect() payin.PaymentDetails = PayInPaymentDetailsBankWire( DeclaredDebitedFunds=Money(int(debit_amount * 100), 'EUR'), DeclaredFees=Money(int(fee * 100), 'EUR'), ) payin.Tag = str(e_id) try: test_hook() payin = mangoapi.payIns.Create(payin) except Exception as e: error = repr_exception(e) return None, record_exchange_result(db, e_id, 'failed', error, participant) e = record_exchange_result(db, e_id, payin.Status.lower(), repr_error(payin), participant) return payin, e
def test_payin_bank_wire_callback(self, Get): homer = self.homer route = ExchangeRoute.insert(homer, 'mango-bw', 'x') for status in ('failed', 'succeeded'): status_up = status.upper() error = 'FOO' if status == 'failed' else None e_id = record_exchange(self.db, route, 11, 0, 0, homer, 'pre') assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYIN_NORMAL_"+status_up+"&RessourceId=123456790" payin = PayIn() payin.Status = status_up payin.ResultCode = '000001' if error else '000000' payin.ResultMessage = error payin.AuthorId = homer.mangopay_user_id payin.PaymentType = 'BANK_WIRE' payin.Tag = str(e_id) Get.return_value = payin r = self.callback(qs) assert r.code == 200, r.text homer = homer.refetch() if status == 'succeeded': assert homer.balance == 11 assert homer.status == 'active' else: assert homer.balance == 0 assert homer.status == 'closed' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert status[:4] in emails[0]['subject'] homer.update_status('active') # reset for next loop run
def test_charge_invalidated_card(self): bob = self.make_participant('bob') route = ExchangeRoute.insert(bob, 'mango-cc', '-1', 'canceled', currency='EUR') with self.assertRaises(AssertionError): charge(self.db, route, EUR('10.00'), 'http://localhost/')
def make_participant(self, username, **kw): platform = kw.pop('elsewhere', 'github') kw2 = {} for key in ('last_bill_result', 'balance'): if key in kw: kw2[key] = kw.pop(key) kind = kw.setdefault('kind', 'individual') if kind not in ('group', 'community'): kw.setdefault('password', 'x') kw.setdefault('session_token', username) i = next(self.seq) kw.setdefault('mangopay_user_id', -i) kw.setdefault('mangopay_wallet_id', -i) kw.setdefault('status', 'active') if not 'join_time' in kw: kw['join_time'] = utcnow() cols, vals = zip(*kw.items()) cols = ', '.join(cols) placeholders = ', '.join(['%s'] * len(vals)) participant = self.db.one( """ INSERT INTO participants (username, {0}) VALUES (%s, {1}) RETURNING participants.*::participants """.format(cols, placeholders), (username, ) + vals) self.db.run( """ INSERT INTO elsewhere (platform, user_id, user_name, participant) VALUES (%s,%s,%s,%s) """, (platform, participant.id, username, participant.id)) if 'last_bill_result' in kw2: ExchangeRoute.insert(participant, 'mango-cc', '-1', kw2['last_bill_result']) if 'balance' in kw2 and kw2['balance'] != 0: self.make_exchange('mango-cc', kw2['balance'], 0, participant) return participant
def make_exchange(self, route, amount, fee, participant, status='succeeded', error='', vat=0): if not isinstance(route, ExchangeRoute): network = route route = ExchangeRoute.from_network(participant, network) if not route: from .mangopay import MangopayHarness route = ExchangeRoute.insert(participant, network, MangopayHarness.card_id) assert route e_id = record_exchange(self.db, route, amount, fee, vat, participant, 'pre') record_exchange_result(self.db, e_id, status, error, participant) return e_id
def make_exchange(self, route, amount, fee, participant, status='succeeded', error='', vat=0): if not isinstance(route, ExchangeRoute): network = route route = ExchangeRoute.from_network(participant, network) if not route: from .mangopay import MangopayHarness route = ExchangeRoute.insert(participant, network, MangopayHarness.card_id) assert route e_id = record_exchange(self.db, route, amount, fee, vat, participant, 'pre') record_exchange_result(self.db, e_id, status, error, participant) return e_id
def make_participant(self, username, **kw): platform = kw.pop('elsewhere', 'github') kw2 = {} for key in ('last_bill_result', 'balance'): if key in kw: kw2[key] = kw.pop(key) kind = kw.setdefault('kind', 'individual') if kind != 'group': kw.setdefault('password', 'x') kw.setdefault('session_token', username) kw.setdefault('status', 'active') if not 'join_time' in kw: kw['join_time'] = utcnow() i = next(self.seq) kw.setdefault('mangopay_user_id', -i) kw.setdefault('mangopay_wallet_id', -i) cols, vals = zip(*kw.items()) cols = ', '.join(cols) placeholders = ', '.join(['%s']*len(vals)) participant = self.db.one(""" INSERT INTO participants (username, {0}) VALUES (%s, {1}) RETURNING participants.*::participants """.format(cols, placeholders), (username,)+vals) self.db.run(""" INSERT INTO elsewhere (platform, user_id, user_name, participant) VALUES (%s,%s,%s,%s) """, (platform, participant.id, username, participant.id)) if 'last_bill_result' in kw2: ExchangeRoute.insert(participant, 'mango-cc', '-1', kw2['last_bill_result']) if 'balance' in kw2: self.make_exchange('mango-cc', kw2['balance'], 0, participant) return participant
def test_identity_form(self): janeway = self.make_participant( 'janeway', email='*****@*****.**', mangopay_user_id=None, ) assert janeway.mangopay_user_id is None # Create a mangopay natural user data = dict(user_data, terms='agree') kw = dict(auth_as=janeway, raise_immediately=False, xhr=True) r = self.client.POST('/janeway/identity-v1', data, **kw) assert r.code == 200, r.text janeway = janeway.refetch() assert janeway.mangopay_user_id # Test the rendering of the identity page r = self.client.GET('/janeway/identity-v1.html', auth_as=janeway) assert r.code == 200, r.text assert user_data['FirstName'] in r.text # Edit the natural user data2 = dict(data, FirstName='Kathryn', Nationality='US', Birthday='1970-01-01') r = self.client.POST('/janeway/identity-v1', data2, **kw) assert r.code == 200, r.text janeway2 = janeway.refetch() assert janeway2.mangopay_user_id == janeway.mangopay_user_id # Add some money for the next test create_wallet(self.db, janeway, 'EUR') cr = create_card(janeway.mangopay_user_id) route = ExchangeRoute.insert(janeway, 'mango-cc', cr.CardId, 'chargeable', currency='EUR') charge(self.db, route, EUR('20.00'), 'http://127.0.0.1/') # Switch to a legal user data = dict(data2) data['organization'] = 'yes' data['LegalPersonType'] = 'BUSINESS' data['Name'] = 'Starfleet' data['confirmed'] = 'yes' r = self.client.POST('/janeway/identity-v1', data, **kw) assert r.code == 200, r.text janeway = janeway.refetch() assert janeway.mangopay_user_id != janeway2.mangopay_user_id assert janeway.kind == 'organization' self.db.self_check() # Edit the legal user data2 = dict(data, LegalPersonType='ORGANIZATION') r = self.client.POST('/janeway/identity-v1', data2, **kw) assert r.code == 200, r.text janeway2 = janeway.refetch() assert janeway2.mangopay_user_id == janeway.mangopay_user_id
def test_user_page_shows_pledges(self, get_user_info): alice = self.make_elsewhere('github', 1, 'alice').participant bob = self.make_participant('bob') carl = self.make_participant('carl') # bob needs to be an active donor for his pledge to be counted bob.set_tip_to(carl, EUR('1.00')) bob_card = ExchangeRoute.insert( bob, 'stripe-card', 'x', 'chargeable', remote_user_id='x' ) self.add_payment_account(carl, 'stripe') self.make_payin_and_transfer(bob_card, carl, EUR('1.00')) Payday.start().run() # okay, let's check amount = EUR('14.97') bob.set_tip_to(alice, amount) assert alice.receiving == amount r = self.client.GET('/on/github/alice/') assert str(amount.amount) in r.text, r.text
def test_user_page_shows_pledges(self, get_user_info): alice = self.make_elsewhere('github', 1, 'alice').participant bob = self.make_participant('bob') carl = self.make_participant('carl') # bob needs to be an active donor for his pledge to be counted bob.set_tip_to(carl, EUR('1.00')) bob_card = ExchangeRoute.insert( bob, 'stripe-card', 'x', 'chargeable', remote_user_id='x' ) self.add_payment_account(carl, 'stripe') self.make_payin_and_transfer(bob_card, carl, EUR('1.00')) Payday.start().run() # okay, let's check amount = EUR('14.97') bob.set_tip_to(alice, amount) assert alice.receiving == amount r = self.client.GET('/on/github/alice/') assert str(amount.amount) in r.text, r.text
def make_exchange(self, route, amount, fee, participant, status='succeeded', error='', vat=0): amount = amount if isinstance(amount, Money) else Money(amount, 'EUR') fee = fee if isinstance(fee, Money) else Money(fee, amount.currency) vat = vat if isinstance(vat, Money) else Money(vat, fee.currency) if not isinstance(route, ExchangeRoute): network = route currency = amount.currency if network == 'mango-cc' else None routes = ExchangeRoute.from_network(participant, network, currency=currency) if routes: route = routes[0] else: from .mangopay import MangopayHarness address = MangopayHarness.card_id if network == 'mango-cc' else -participant.id route = ExchangeRoute.insert(participant, network, address, currency=currency) assert route e_id = record_exchange(self.db, route, amount, fee, vat, participant, 'pre').id record_exchange_result(self.db, e_id, -e_id, status, error, participant) return e_id
def test_payin_bank_wire_callback(self, Get): homer = self.homer route = ExchangeRoute.insert(homer, 'mango-bw', 'x', 'chargeable') cases = ( ('failed', '000001', 'FOO'), ('failed', '101109', 'The payment period has expired'), ('succeeded', '000000', None), ) for status, result_code, error in cases: status_up = status.upper() e_id = record_exchange(self.db, route, EUR(11), EUR(0), EUR(0), homer, 'pre').id assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYIN_NORMAL_" + status_up + "&RessourceId=123456790" payin = BankWirePayIn(Id=-1) payin.Status = status_up payin.ResultCode = result_code payin.ResultMessage = error payin.AuthorId = homer.mangopay_user_id payin.PaymentType = 'BANK_WIRE' payin.DeclaredDebitedFunds = Money(1100, 'EUR') payin.DeclaredFees = Money(0, 'EUR') payin.CreditedFunds = Money(0, 'XXX') if error else Money( 1100, 'EUR') payin.Tag = str(e_id) Get.return_value = payin r = self.callback(qs) assert r.code == 200, r.text homer = homer.refetch() if status == 'succeeded': assert homer.balance == 11 assert homer.status == 'active' else: assert homer.balance == 0 assert homer.status == 'closed' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email expected = 'expired' if result_code == '101109' else status[:4] assert expected in emails[0]['subject'] self.db.self_check() homer.update_status('active') # reset for next loop run
def test_payin_bank_wire_callback(self, Get): homer = self.homer route = ExchangeRoute.insert(homer, 'mango-bw', 'x') cases = ( ('failed', '000001', 'FOO'), ('failed', '101109', 'The payment period has expired'), ('succeeded', '000000', None), ) for status, result_code, error in cases: status_up = status.upper() e_id = record_exchange(self.db, route, EUR(11), EUR(0), EUR(0), homer, 'pre').id assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYIN_NORMAL_"+status_up+"&RessourceId=123456790" payin = BankWirePayIn(Id=-1) payin.Status = status_up payin.ResultCode = result_code payin.ResultMessage = error payin.AuthorId = homer.mangopay_user_id payin.PaymentType = 'BANK_WIRE' payin.DeclaredDebitedFunds = Money(1100, 'EUR') payin.DeclaredFees = Money(0, 'EUR') payin.CreditedFunds = Money(0, 'XXX') if error else Money(1100, 'EUR') payin.Tag = str(e_id) Get.return_value = payin r = self.callback(qs) assert r.code == 200, r.text homer = homer.refetch() if status == 'succeeded': assert homer.balance == 11 assert homer.status == 'active' else: assert homer.balance == 0 assert homer.status == 'closed' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email expected = 'expired' if result_code == '101109' else status[:4] assert expected in emails[0]['subject'] self.db.self_check() homer.update_status('active') # reset for next loop run
def test_negative_paid_in_advance(self): team = self.make_participant('team', kind='group') alice = self.make_participant('alice') team.set_take_for(alice, EUR('1.00'), team) stripe_account_alice = self.add_payment_account(alice, 'stripe') donor = self.make_participant('donor') donor.set_tip_to(team, EUR('5')) donor_card = ExchangeRoute.insert( donor, 'stripe-card', 'x', 'chargeable', remote_user_id='x' ) payin, pt = self.make_payin_and_transfer(donor_card, team, EUR('10')) assert pt.destination == stripe_account_alice.pk self.db.run("UPDATE takes SET paid_in_advance = -paid_in_advance") Payday.start().run() transfers = self.db.all("SELECT * FROM transfers ORDER BY id") assert len(transfers) == 0
def test_payin_bank_wire_callback(self, Get): homer = self.homer route = ExchangeRoute.insert(homer, 'mango-bw', 'x') for status in ('failed', 'succeeded'): status_up = status.upper() error = 'FOO' if status == 'failed' else None e_id = record_exchange(self.db, route, 11, 0, 0, homer, 'pre') assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYIN_NORMAL_" + status_up + "&RessourceId=123456790" payin = PayIn() payin.Status = status_up payin.ResultCode = '000001' if error else '000000' payin.ResultMessage = error payin.AuthorId = homer.mangopay_user_id payin.PaymentType = 'BANK_WIRE' pd = payin.PaymentDetails = PayInPaymentDetailsBankWire() pd.DeclaredDebitedFunds = Money(1100, 'EUR').__dict__ pd.DeclaredFees = Money(0, 'EUR').__dict__ payin.CreditedFunds = Money(1100, 'EUR') payin.Tag = str(e_id) Get.return_value = payin r = self.callback(qs) assert r.code == 200, r.text homer = homer.refetch() if status == 'succeeded': assert homer.balance == 11 assert homer.status == 'active' else: assert homer.balance == 0 assert homer.status == 'closed' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert status[:4] in emails[0]['subject'] homer.update_status('active') # reset for next loop run
def _test_payin_bank_wire_callback_amount_mismatch(self, Get, fee): homer = self.homer route = ExchangeRoute.insert(homer, 'mango-bw', 'x') e_id = record_exchange(self.db, route, EUR(11), EUR(0), EUR(0), homer, 'pre').id assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYIN_NORMAL_SUCCEEDED&RessourceId=123456790" payin = BankWirePayIn(Id=-1) payin.Status = 'SUCCEEDED' payin.ResultCode = '000000' payin.ResultMessage = None payin.AuthorId = homer.mangopay_user_id payin.PaymentType = 'BANK_WIRE' payin.DeclaredDebitedFunds = Money(4500, 'EUR') payin.DeclaredFees = Money(100, 'EUR') payin.DebitedFunds = Money(302, 'EUR') payin.Fees = Money(fee, 'EUR') payin.CreditedFunds = Money(302 - fee, 'EUR') payin.Tag = str(e_id) Get.return_value = payin r = self.callback(qs) assert r.code == 200, r.text e = self.db.one("SELECT * FROM exchanges WHERE id = %s", (e_id,)) assert e.amount == D(payin.CreditedFunds.Amount) / D(100) assert e.fee == D(fee) / D(100) assert e.vat == D('0.01') assert e.status == 'succeeded' homer = homer.refetch() assert homer.balance == e.amount assert homer.status == 'active' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert 'succ' in emails[0]['subject'] self.db.self_check()
def test_resolve_destination(self): alice = self.make_participant('alice') bob = self.make_participant('bob') carl = self.make_participant('carl') team = self.make_participant('team', kind='group') alice.set_tip_to(team, EUR('10')) # Test without payment account team.add_member(bob) with self.assertRaises(MissingPaymentAccount): resolve_destination(self.db, team, 'stripe', alice, 'FR', EUR('10')) # Test without payment account at the requested provider stripe_account_bob = self.add_payment_account(bob, 'stripe') with self.assertRaises(MissingPaymentAccount): resolve_destination(self.db, team, 'paypal', alice, 'US', EUR('10')) # Test with a single member and the take at zero account = resolve_destination(self.db, team, 'stripe', alice, 'GB', EUR('7')) assert account == stripe_account_bob # Test with two members but only one payment account team.add_member(carl) account = resolve_destination(self.db, team, 'stripe', alice, 'CH', EUR('8')) assert account == stripe_account_bob # Test with two members but only one payment account at the requested provider paypal_account_carl = self.add_payment_account(carl, 'paypal') account = resolve_destination(self.db, team, 'stripe', alice, 'BE', EUR('42')) assert account == stripe_account_bob # Test with two members and both takes at zero stripe_account_carl = self.add_payment_account(carl, 'stripe') account = resolve_destination(self.db, team, 'stripe', alice, 'PL', EUR('5.46')) assert account == stripe_account_bob account = resolve_destination(self.db, team, 'paypal', alice, 'PL', EUR('99.9')) assert account == paypal_account_carl # Test with two members and one non-zero take team.set_take_for(bob, EUR('1'), bob) account = resolve_destination(self.db, team, 'stripe', alice, 'RU', EUR('50.02')) assert account == stripe_account_bob account = resolve_destination(self.db, team, 'paypal', alice, 'RU', EUR('33')) assert account == paypal_account_carl # Test with two members and two different non-zero takes team.set_take_for(carl, EUR('2'), carl) account = resolve_destination(self.db, team, 'stripe', alice, 'BR', EUR('10')) assert account == stripe_account_carl account = resolve_destination(self.db, team, 'stripe', alice, 'BR', EUR('1')) assert account == stripe_account_carl account = resolve_destination(self.db, team, 'paypal', alice, 'BR', EUR('5')) assert account == paypal_account_carl # Check that members are cycled through alice_card = ExchangeRoute.insert( alice, 'stripe-card', 'x', 'chargeable', remote_user_id='x' ) payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('2')) assert pt.destination == stripe_account_carl.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('1')) assert pt.destination == stripe_account_bob.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('4')) assert pt.destination == stripe_account_carl.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('10')) assert pt.destination == stripe_account_carl.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('2')) assert pt.destination == stripe_account_bob.pk
def test_takes_paid_in_advance_to_now_inactive_members(self): team = self.make_participant('team', kind='group', accepted_currencies=None) alice = self.make_participant('alice', main_currency='EUR', accepted_currencies=None) team.set_take_for(alice, EUR('1.00'), team) bob = self.make_participant('bob', main_currency='USD', accepted_currencies=None) team.set_take_for(bob, USD('1.00'), team) stripe_account_alice = self.add_payment_account( alice, 'stripe', default_currency='EUR' ) stripe_account_bob = self.add_payment_account( bob, 'stripe', country='US', default_currency='USD' ) carl = self.make_participant('carl') carl.set_tip_to(team, JPY('250')) carl_card = ExchangeRoute.insert( carl, 'stripe-card', 'x', 'chargeable', remote_user_id='x' ) payin, pt = self.make_payin_and_transfer(carl_card, team, JPY('1250')) assert pt.destination == stripe_account_alice.pk payin, pt = self.make_payin_and_transfer(carl_card, team, JPY('1250')) assert pt.destination == stripe_account_bob.pk team.set_take_for(alice, EUR('0.00'), team) team.set_take_for(bob, None, team) takes = dict(self.db.all(""" SELECT DISTINCT ON (member) member, paid_in_advance FROM takes ORDER BY member, mtime DESC """)) assert takes == { alice.id: EUR('10.00'), bob.id: USD('12.00'), } Payday.start().run() transfers = self.db.all("SELECT * FROM transfers ORDER BY id") assert len(transfers) == 2 assert transfers[0].virtual is True assert transfers[0].tipper == carl.id assert transfers[0].tippee == alice.id assert transfers[0].amount == JPY('125') assert transfers[1].virtual is True assert transfers[1].tipper == carl.id assert transfers[1].tippee == bob.id assert transfers[1].amount == JPY('125') takes = dict(self.db.all(""" SELECT DISTINCT ON (member) member, paid_in_advance FROM takes ORDER BY member, mtime DESC """)) assert takes == { alice.id: EUR('9.00'), bob.id: USD('10.80'), } notifications = self.db.all("SELECT * FROM notifications") assert len(notifications) == 0 leftovers = dict(self.db.all("SELECT username, leftover FROM participants")) assert leftovers == { 'team': MoneyBasket(JPY('250.00')), 'alice': None, 'bob': None, 'carl': None, }
def test_charge_invalidated_card(self): bob = self.make_participant('bob') route = ExchangeRoute.insert(bob, 'mango-cc', '-1', error='invalidated', currency='EUR') with self.assertRaises(AssertionError): charge(self.db, route, D('10.00'), 'http://localhost/')
def test_resolve_destination(self): alice = self.make_participant('alice') bob = self.make_participant('bob') carl = self.make_participant('carl') team = self.make_participant('team', kind='group') alice.set_tip_to(team, EUR('10')) # Test without payment account team.add_member(bob) with self.assertRaises(MissingPaymentAccount): resolve_destination(self.db, team, 'stripe', alice, 'FR', EUR('10')) # Test without payment account at the requested provider stripe_account_bob = self.add_payment_account(bob, 'stripe') with self.assertRaises(MissingPaymentAccount): resolve_destination(self.db, team, 'paypal', alice, 'US', EUR('10')) # Test with a single member and the take at zero account = resolve_destination(self.db, team, 'stripe', alice, 'GB', EUR('7')) assert account == stripe_account_bob # Test with two members but only one payment account team.add_member(carl) account = resolve_destination(self.db, team, 'stripe', alice, 'CH', EUR('8')) assert account == stripe_account_bob # Test with two members but only one payment account at the requested provider paypal_account_carl = self.add_payment_account(carl, 'paypal') account = resolve_destination(self.db, team, 'stripe', alice, 'BE', EUR('42')) assert account == stripe_account_bob # Test with two members and both takes at zero stripe_account_carl = self.add_payment_account(carl, 'stripe') account = resolve_destination(self.db, team, 'stripe', alice, 'PL', EUR('5.46')) assert account == stripe_account_bob account = resolve_destination(self.db, team, 'paypal', alice, 'PL', EUR('99.9')) assert account == paypal_account_carl # Test with two members and one non-zero take team.set_take_for(bob, EUR('1'), bob) account = resolve_destination(self.db, team, 'stripe', alice, 'RU', EUR('50.02')) assert account == stripe_account_bob account = resolve_destination(self.db, team, 'paypal', alice, 'RU', EUR('33')) assert account == paypal_account_carl # Test with two members and two different non-zero takes team.set_take_for(carl, EUR('2'), carl) account = resolve_destination(self.db, team, 'stripe', alice, 'BR', EUR('10')) assert account == stripe_account_carl account = resolve_destination(self.db, team, 'stripe', alice, 'BR', EUR('1')) assert account == stripe_account_carl account = resolve_destination(self.db, team, 'paypal', alice, 'BR', EUR('5')) assert account == paypal_account_carl # Check that members are cycled through alice_card = ExchangeRoute.insert(alice, 'stripe-card', 'x', 'chargeable', remote_user_id='x') payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('2')) assert pt.destination == stripe_account_carl.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('1')) assert pt.destination == stripe_account_bob.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('4')) assert pt.destination == stripe_account_carl.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('10')) assert pt.destination == stripe_account_carl.pk payin, pt = self.make_payin_and_transfer(alice_card, team, EUR('2')) assert pt.destination == stripe_account_bob.pk