def test_record_exchange_doesnt_update_balance_for_positive_amounts(self): record_exchange( self.db, self.janet_route, amount=EUR("0.59"), fee=EUR("0.41"), vat=EUR("0.00"), participant=self.janet, status='pre', ) janet = Participant.from_username('janet') assert self.janet.balance == janet.balance == EUR('0.00')
def test_record_exchange_doesnt_update_balance_for_positive_amounts(self): record_exchange( self.db, self.janet_route, amount=EUR("0.59"), fee=EUR("0.41"), vat=EUR("0.00"), participant=self.janet, status='pre', ) janet = Participant.from_username('janet') assert self.janet.balance == janet.balance == D('0.00')
def test_record_exchange_updates_balance_for_negative_amounts(self): self.make_exchange('mango-cc', 50, 0, self.homer) record_exchange( self.db, self.homer_route, amount=EUR('-35.84'), fee=EUR('0.75'), vat=EUR('0.00'), participant=self.homer, status='pre', ) homer = Participant.from_username('homer') assert homer.balance == EUR('13.41')
def test_record_exchange_updates_balance_for_negative_amounts(self): self.make_exchange('mango-cc', 50, 0, self.homer) record_exchange( self.db, self.homer_route, amount=EUR('-35.84'), fee=EUR('0.75'), vat=EUR('0.00'), participant=self.homer, status='pre', ) homer = Participant.from_username('homer') assert homer.balance == D('13.41')
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_payout_callback(self, Get): homer, ba = self.homer, self.homer_route for status in ('succeeded', 'failed'): status_up = status.upper() error = 'FOO' if status == 'failed' else None self.make_exchange('mango-cc', 10, 0, homer) e_id = record_exchange(self.db, ba, EUR(-10), EUR(0), EUR(0), homer, 'pre').id assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYOUT_NORMAL_" + status_up + "&RessourceId=123456790" payout = BankWirePayOut(Id=-1) payout.Status = status_up payout.ResultCode = '000001' if error else '000000' payout.ResultMessage = error payout.AuthorId = homer.mangopay_user_id payout.Tag = str(e_id) Get.return_value = payout r = self.callback(qs) assert CSRF_TOKEN not in r.headers.cookie assert r.code == 200, r.text homer = homer.refetch() if status == 'succeeded': assert homer.balance == 0 assert homer.status == 'closed' else: assert homer.balance == 10 assert homer.status == 'active' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert 'fail' in emails[0]['subject'] self.db.self_check() homer.update_status('active') # reset for next loop run
def test_payout_callback(self, Get): homer, ba = self.homer, self.homer_route for status in ('succeeded', 'failed'): status_up = status.upper() error = 'FOO' if status == 'failed' else None self.make_exchange('mango-cc', 10, 0, homer) e_id = record_exchange(self.db, ba, EUR(-10), EUR(0), EUR(0), homer, 'pre').id assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' qs = "EventType=PAYOUT_NORMAL_"+status_up+"&RessourceId=123456790" payout = BankWirePayOut(Id=-1) payout.Status = status_up payout.ResultCode = '000001' if error else '000000' payout.ResultMessage = error payout.AuthorId = homer.mangopay_user_id payout.Tag = str(e_id) Get.return_value = payout r = self.callback(qs) assert CSRF_TOKEN not in r.headers.cookie assert r.code == 200, r.text homer = homer.refetch() if status == 'succeeded': assert homer.balance == 0 assert homer.status == 'closed' else: assert homer.balance == 10 assert homer.status == 'active' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert 'fail' in emails[0]['subject'] self.db.self_check() homer.update_status('active') # reset for next loop run
def test_record_exchange_result_restores_balance_on_error(self): homer, ba = self.homer, self.homer_route self.make_exchange('mango-cc', 30, 0, homer) e_id = record_exchange(self.db, ba, EUR('-27.06'), EUR('0.81'), EUR(0), homer, 'pre').id assert homer.balance == EUR('02.13') record_exchange_result(self.db, e_id, -e_id, 'failed', 'SOME ERROR', homer) homer = Participant.from_username('homer') assert homer.balance == EUR('30.00')
def test_record_exchange_result_doesnt_restore_balance_on_success(self): homer, ba = self.homer, self.homer_route self.make_exchange('mango-cc', 50, 0, homer) e_id = record_exchange(self.db, ba, EUR('-43.98'), EUR('1.60'), EUR(0), homer, 'pre').id assert homer.balance == EUR('4.42') record_exchange_result(self.db, e_id, -e_id, 'succeeded', None, homer) homer = Participant.from_username('homer') assert homer.balance == EUR('4.42')
def test_record_exchange_result_updates_balance_for_positive_amounts(self): janet, cc = self.janet, self.janet_route self.make_exchange('mango-cc', 4, 0, janet) e_id = record_exchange(self.db, cc, EUR('31.59'), EUR('0.01'), EUR(0), janet, 'pre').id assert janet.balance == EUR('4.00') record_exchange_result(self.db, e_id, -e_id, 'succeeded', None, janet) janet = Participant.from_username('janet') assert janet.balance == EUR('35.59')
def test_record_exchange_result_updates_balance_for_positive_amounts(self): janet, cc = self.janet, self.janet_route self.make_exchange('mango-cc', 4, 0, janet) e_id = record_exchange(self.db, cc, EUR('31.59'), EUR('0.01'), EUR(0), janet, 'pre').id assert janet.balance == D('4.00') record_exchange_result(self.db, e_id, -e_id, 'succeeded', None, janet) janet = Participant.from_username('janet') assert janet.balance == D('35.59')
def test_record_exchange_result_doesnt_restore_balance_on_success(self): homer, ba = self.homer, self.homer_route self.make_exchange('mango-cc', 50, 0, homer) e_id = record_exchange(self.db, ba, EUR('-43.98'), EUR('1.60'), EUR(0), homer, 'pre').id assert homer.balance == D('4.42') record_exchange_result(self.db, e_id, -e_id, 'succeeded', None, homer) homer = Participant.from_username('homer') assert homer.balance == D('4.42')
def test_record_exchange_result_restores_balance_on_error(self): homer, ba = self.homer, self.homer_route self.make_exchange('mango-cc', 30, 0, homer) e_id = record_exchange(self.db, ba, EUR('-27.06'), EUR('0.81'), EUR(0), homer, 'pre').id assert homer.balance == D('02.13') record_exchange_result(self.db, e_id, -e_id, 'failed', 'SOME ERROR', homer) homer = Participant.from_username('homer') assert homer.balance == D('30.00')
def test_record_exchange_result_restores_balance_on_error_with_invalidated_route(self): homer, ba = self.homer, self.homer_route self.make_exchange('mango-cc', 37, 0, homer) e_id = record_exchange(self.db, ba, EUR('-32.45'), EUR('0.86'), EUR(0), homer, 'pre').id assert homer.balance == D('3.69') ba.update_error('invalidated') record_exchange_result(self.db, e_id, -e_id, 'failed', 'oops', homer) homer = Participant.from_username('homer') assert homer.balance == D('37.00') assert ba.error == 'invalidated'
def test_record_exchange_result_restores_balance_on_error_with_invalidated_route(self): homer, ba = self.homer, self.homer_route self.make_exchange('mango-cc', 37, 0, homer) e_id = record_exchange(self.db, ba, EUR('-32.45'), EUR('0.86'), EUR(0), homer, 'pre').id assert homer.balance == EUR('3.69') ba.update_error('invalidated') record_exchange_result(self.db, e_id, -e_id, 'failed', 'oops', homer) homer = Participant.from_username('homer') assert homer.balance == EUR('37.00') assert ba.error == 'invalidated'
def test_payout_refund_callback(self, R_Get, PO_Get): homer, ba = self.homer, self.homer_route for status in ('failed', 'succeeded'): # Create the payout self.make_exchange('mango-cc', 10, 0, homer) e_id = record_exchange(self.db, ba, EUR(-9), EUR(1), EUR(0), homer, 'pre').id assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' payout = BankWirePayOut(Id=-1) payout.Status = 'SUCCEEDED' payout.ResultCode = '000000' payout.AuthorId = homer.mangopay_user_id payout.Tag = str(e_id) PO_Get.return_value = payout # Create the refund status_up = status.upper() error = 'FOO' if status == 'failed' else None refund = Refund(Id=-1) refund.DebitedFunds = Money(900, 'EUR') refund.Fees = Money(-100, 'EUR') refund.Status = status_up refund.ResultCode = '000001' if error else '000000' refund.ResultMessage = error refund.RefundReason = Reason(message='BECAUSE 42') refund.AuthorId = homer.mangopay_user_id R_Get.return_value = refund # Call back qs = "EventType=PAYOUT_REFUND_" + status_up + "&RessourceId=123456790" r = self.callback(qs) assert r.code == 200, r.text homer = homer.refetch() if status == 'failed': assert homer.balance == 0 assert homer.status == 'closed' else: assert homer.balance == 10 assert homer.status == 'active' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert 'fail' in emails[0]['subject'] assert 'BECAUSE 42' in emails[0]['text'] self.db.self_check() homer.update_status('active') # reset for next loop run
def test_payout_refund_callback(self, R_Get, PO_Get): homer, ba = self.homer, self.homer_route for status in ('failed', 'succeeded'): # Create the payout self.make_exchange('mango-cc', 10, 0, homer) e_id = record_exchange(self.db, ba, EUR(-9), EUR(1), EUR(0), homer, 'pre').id assert homer.balance == 0 homer.close(None) assert homer.status == 'closed' payout = BankWirePayOut(Id=-1) payout.Status = 'SUCCEEDED' payout.ResultCode = '000000' payout.AuthorId = homer.mangopay_user_id payout.Tag = str(e_id) PO_Get.return_value = payout # Create the refund status_up = status.upper() error = 'FOO' if status == 'failed' else None refund = Refund(Id=-1) refund.DebitedFunds = Money(900, 'EUR') refund.Fees = Money(-100, 'EUR') refund.Status = status_up refund.ResultCode = '000001' if error else '000000' refund.ResultMessage = error refund.RefundReason = Reason(message='BECAUSE 42') refund.AuthorId = homer.mangopay_user_id R_Get.return_value = refund # Call back qs = "EventType=PAYOUT_REFUND_"+status_up+"&RessourceId=123456790" r = self.callback(qs) assert r.code == 200, r.text homer = homer.refetch() if status == 'failed': assert homer.balance == 0 assert homer.status == 'closed' else: assert homer.balance == 10 assert homer.status == 'active' emails = self.get_emails() assert len(emails) == 1 assert emails[0]['to'][0] == 'homer <%s>' % homer.email assert 'fail' in emails[0]['subject'] assert 'BECAUSE 42' in emails[0]['text'] self.db.self_check() homer.update_status('active') # reset for next loop run
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 make_exchange(self, route, amount, fee, participant, status='succeeded', error='', vat=0): if not isinstance(route, ExchangeRoute): network = route routes = ExchangeRoute.from_network(participant, network) if routes: route = routes[0] else: 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').id record_exchange_result(self.db, e_id, -e_id, status, error, participant) return e_id
def _test_payin_bank_wire_callback_amount_mismatch(self, Get, fee): homer = self.homer route = ExchangeRoute.insert(homer, 'mango-bw', 'x', 'chargeable') 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 == payin.CreditedFunds / 100 assert e.fee == EUR(fee) / 100 assert e.vat == EUR('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_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_record_exchange_fails_if_negative_balance(self): with pytest.raises(NegativeBalance): record_exchange(self.db, self.homer_route, EUR("-10.00"), EUR("0.41"), EUR(0), self.homer, 'pre')
def test_record_exchange_fails_if_negative_balance(self): with pytest.raises(NegativeBalance): record_exchange(self.db, self.homer_route, EUR("-10.00"), EUR("0.41"), EUR(0), self.homer, 'pre')