def create(self): # mpu = Saver.objects.get(self.author) ba = MangoBankAccount.objects.get(owner=self.saver.mid) po = BankWirePayOut(author=self.saver.mid, debited_funds=Money(amount=self.amount, currency=self.currency), debited_wallet=self.dwid, bank_account=ba.bid, bank_wire_ref=self.bank_wire_ref) po.save() self.poid = po.get_pk() # get other stuff from the api call and add accordingly self.save()
def status_update(self): payout = BankWirePayOut.get(Id=self.poid) if self.status == payout.status: return self.status self.status = payout.status self.execution_date = payout['ExecutionDate'] self.save() return self.status
def payout(db, route, amount, ignore_high_fee=False): """Withdraw money to the specified bank account (`route`). """ assert amount > 0 assert route assert route.network == 'mango-ba' participant = route.participant if participant.is_suspended: raise AccountSuspended() payday = db.one("SELECT * FROM paydays WHERE ts_start > ts_end") if payday: raise PaydayIsRunning ba = BankAccount.get(route.address, user_id=participant.mangopay_user_id) # Do final calculations amount = Money(amount, 'EUR') if isinstance(amount, Decimal) else amount credit_amount, fee, vat = skim_credit(amount, ba) if credit_amount <= 0 and fee > 0: raise FeeExceedsAmount fee_percent = fee / amount if fee_percent > FEE_PAYOUT_WARN and not ignore_high_fee: raise TransactionFeeTooHigh(fee_percent, fee, amount) # Try to dance with MangoPay e_id = record_exchange(db, route, -credit_amount, fee, vat, participant, 'pre').id payout = BankWirePayOut() payout.AuthorId = participant.mangopay_user_id payout.DebitedFunds = Money_to_cents(amount) payout.DebitedWalletId = participant.get_current_wallet(amount.currency).remote_id payout.Fees = Money_to_cents(fee) payout.BankAccountId = route.address payout.BankWireRef = str(e_id) payout.Tag = str(e_id) try: test_hook() payout.save() return record_exchange_result( db, e_id, payout.Id, payout.Status.lower(), repr_error(payout), participant ) except Exception as e: error = repr_exception(e) return record_exchange_result(db, e_id, '', 'failed', error, participant)
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_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 create(self, user): # call the _check here mid = MangoUser.objects.get(user=user).mid bid = MangoBankAccount.objects.get(mid=mid) dwid = MangoWallet.objects.get(mid=mid) payout = BankWirePayOut(AuthorId=mid, DebitedFunds=Money(self.amount, self.currency), Fees=Money(self.fees, self.currency), BankAccountId=bid, DebitedWalletId=dwid, BankWireRef=self.reference) payout.save() self.poid = payout.get_pk() self.author_id = mid self.bid = bid self.dwid = dwid self.creation_date = payout['CreationDate'] # is this form ok? self.save()
def get_pay_out(self): author = self.mangopay_user.get_user() bank_account = self.mangopay_bank_account.get_bank_account() return BankWirePayOut(id=self.mangopay_id, author=author, debited_funds=python_money_to_mangopay_money( self.debited_funds), fees=python_money_to_mangopay_money(self.fees), debited_wallet=self.mangopay_wallet, bank_account=bank_account, bank_wire_ref="John Doe's trousers")
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_create_payout(self): account = BaseTestLive.get_client_bank_account() payout = BankWirePayOut() wallets = ClientWallet.all() payout.debited_funds = Money() payout.debited_funds.currency = 'EUR' payout.debited_funds.amount = 12 payout.bank_account = account payout.debited_wallet = wallets[0] payout.bank_wire_ref = 'invoice 7282' created_payout = BankWirePayOut(**payout.create_client_payout()) self.assertIsNotNone(created_payout) self.assertIsNotNone(created_payout.id)
def record_payout_refund(db, payout_refund): orig_payout = BankWirePayOut.get(payout_refund.InitialTransactionId) e_origin = db.one("SELECT * FROM exchanges WHERE id = %s" % (orig_payout.Tag,)) e_refund_id = db.one("SELECT id FROM exchanges WHERE refund_ref = %s", (e_origin.id,)) if e_refund_id: # Already recorded return e_refund_id amount, fee, vat = -e_origin.amount, -e_origin.fee, -e_origin.vat assert payout_refund.DebitedFunds == Money(int(amount * 100), 'EUR') assert payout_refund.Fees == Money(int(fee * 100), 'EUR') route = ExchangeRoute.from_id(e_origin.route) participant = Participant.from_id(e_origin.participant) return db.one(""" INSERT INTO exchanges (amount, fee, vat, participant, status, route, note, refund_ref) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) RETURNING id """, (amount, fee, vat, participant.id, 'created', route.id, None, e_origin.id))
def record_payout_refund(db, payout_refund): orig_payout = BankWirePayOut.get(payout_refund.InitialTransactionId) e_origin = db.one("SELECT * FROM exchanges WHERE id = %s", (orig_payout.Tag,)) e_refund_id = db.one("SELECT id FROM exchanges WHERE refund_ref = %s", (e_origin.id,)) if e_refund_id: # Already recorded return e_refund_id amount, fee, vat = -e_origin.amount, -e_origin.fee, -e_origin.vat assert payout_refund.DebitedFunds / 100 == amount assert payout_refund.Fees / 100 == fee participant = Participant.from_id(e_origin.participant) route = ExchangeRoute.from_id(participant, e_origin.route) remote_id = payout_refund.Id wallet_id = e_origin.wallet_id return db.one(""" INSERT INTO exchanges (amount, fee, vat, participant, status, route, note, refund_ref, remote_id, wallet_id) VALUES (%s, %s, %s, %s, 'created', %s, NULL, %s, %s, %s) RETURNING id """, (amount, fee, vat, participant.id, route.id, e_origin.id, remote_id, wallet_id))
def record_payout_refund(db, payout_refund): orig_payout = BankWirePayOut.get(payout_refund.InitialTransactionId) e_origin = db.one("SELECT * FROM exchanges WHERE id = %s", (orig_payout.Tag,)) e_refund_id = db.one("SELECT id FROM exchanges WHERE refund_ref = %s", (e_origin.id,)) if e_refund_id: # Already recorded return e_refund_id amount, fee, vat = -e_origin.amount, -e_origin.fee, -e_origin.vat assert payout_refund.DebitedFunds / 100 == amount assert payout_refund.Fees / 100 == fee route = ExchangeRoute.from_id(e_origin.route) participant = Participant.from_id(e_origin.participant) remote_id = payout_refund.Id wallet_id = e_origin.wallet_id return db.one(""" INSERT INTO exchanges (amount, fee, vat, participant, status, route, note, refund_ref, remote_id, wallet_id) VALUES (%s, %s, %s, %s, 'created', %s, NULL, %s, %s, %s) RETURNING id """, (amount, fee, vat, participant.id, route.id, e_origin.id, remote_id, wallet_id))
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 payout(db, participant, amount, ignore_high_fee=False): assert amount > 0 if participant.is_suspended: raise AccountSuspended() payday = db.one("SELECT * FROM paydays WHERE ts_start > ts_end") if payday: raise PaydayIsRunning route = ExchangeRoute.from_network(participant, 'mango-ba') assert route ba = BankAccount.get(route.address, user_id=participant.mangopay_user_id) # Do final calculations credit_amount, fee, vat = skim_credit(amount, ba) if credit_amount <= 0 and fee > 0: raise FeeExceedsAmount fee_percent = fee / amount if fee_percent > FEE_PAYOUT_WARN and not ignore_high_fee: raise TransactionFeeTooHigh(fee_percent, fee, amount) # Try to dance with MangoPay e_id = record_exchange(db, route, -credit_amount, fee, vat, participant, 'pre') payout = BankWirePayOut() payout.AuthorId = participant.mangopay_user_id payout.DebitedFunds = Money(int(amount * 100), 'EUR') payout.DebitedWalletId = participant.mangopay_wallet_id payout.Fees = Money(int(fee * 100), 'EUR') payout.BankAccountId = route.address payout.BankWireRef = str(e_id) payout.Tag = str(e_id) try: test_hook() payout.save() return record_exchange_result(db, e_id, payout.Status.lower(), repr_error(payout), participant) except Exception as e: error = repr_exception(e) return record_exchange_result(db, e_id, 'failed', error, participant)
def Get(self, pay_out_id): pay_out = BankWirePayOut() pay_out.Id = pay_out_id pay_out.ExecutionDate = 12312312 pay_out.Status = "CREATED" return pay_out
def payout(db, route, amount, ignore_high_fee=False): """Withdraw money to the specified bank account (`route`). """ assert amount > 0 assert route assert route.network == 'mango-ba' participant = route.participant if participant.is_suspended: raise AccountSuspended() payday = db.one("SELECT * FROM paydays WHERE ts_start > ts_end") if payday: raise PaydayIsRunning ba = BankAccount.get(route.address, user_id=participant.mangopay_user_id) # Do final calculations amount = Money(amount, 'EUR') if isinstance(amount, Decimal) else amount credit_amount, fee, vat = skim_credit(amount, ba) if credit_amount <= 0 and fee > 0: raise FeeExceedsAmount fee_percent = fee / amount if fee_percent > FEE_PAYOUT_WARN and not ignore_high_fee: raise TransactionFeeTooHigh(fee_percent, fee, amount) # Try to dance with MangoPay e_id = record_exchange(db, route, -credit_amount, fee, vat, participant, 'pre').id payout = BankWirePayOut() payout.AuthorId = participant.mangopay_user_id payout.DebitedFunds = amount.int() payout.DebitedWalletId = participant.get_current_wallet(amount.currency).remote_id payout.Fees = fee.int() payout.BankAccountId = route.address payout.BankWireRef = str(e_id) payout.Tag = str(e_id) try: test_hook() payout.save() return record_exchange_result( db, e_id, payout.Id, payout.Status.lower(), repr_error(payout), participant ) except Exception as e: error = repr_exception(e) return record_exchange_result(db, e_id, '', 'failed', error, participant)
def test_Idempotency(self): key = str(int(time.time())) + 'abcdefg' pay_out = None #create bankwire try: pay_out_post = BankWirePayOut() pay_out_post.author = BaseTestLive.get_john() pay_out_post.debited_wallet = BaseTestLive.get_johns_wallet() debited_funds = Money() debited_funds.amount = 10 debited_funds.currency = 'EUR' pay_out_post.debited_funds = debited_funds fees = Money() fees.amount = 5 fees.currency = 'EUR' pay_out_post.fees = fees pay_out_post.bank_account = BaseTestLive.get_johns_account() pay_out_post.bank_wire_ref = "Johns bank wire ref" pay_out_post.tag = "DefaultTag" pay_out_post.credited_user = BaseTestLive.get_john() pay_out = pay_out_post.save(idempotency_key=key) except Exception as e: self.assertFalse(True, str(e)) self.assertIsNotNone(pay_out) #test existing key result = None try: result = IdempotencyResponse.get(key) except Exception as e: self.assertFalse(True, str(e)) self.assertIsNotNone(result) #test non existing key try: IdempotencyResponse.get(key+'_no') #expecting a APIError to be thrown self.assertFalse(True, 'Api Error should have been thrown') except APIError as e: self.assertEqual(e.content['Type'], 'correlationid_not_found') self.assertTrue(e.code == 400) except Exception as ex: self.assertFalse(True, str(ex))