From f3fb607550832f49b92a82f2562c6eda0f7e7a96 Mon Sep 17 00:00:00 2001 From: Silviana Ghita Date: Tue, 19 Sep 2023 09:13:27 +0300 Subject: [PATCH] Integrated Spot FX endpoints --- mangopay/fields.py | 57 +++++++++++++++++++++- mangopay/resources.py | 63 +++++++++++++++++++++++- mangopay/utils.py | 30 ++++++++++++ tests/test_wallets.py | 110 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 244 insertions(+), 16 deletions(-) diff --git a/mangopay/fields.py b/mangopay/fields.py index 84aee79..fd1cb62 100644 --- a/mangopay/fields.py +++ b/mangopay/fields.py @@ -10,7 +10,7 @@ Reason, ReportTransactionsFilters, ReportWalletsFilters, \ PlatformCategorization, Billing, SecurityInfo, Birthplace, ApplepayPaymentData, GooglepayPaymentData, \ ScopeBlocked, BrowserInfo, Shipping, CurrentState, FallbackReason, InstantPayout, CountryAuthorizationData, \ - PayinsLinked + PayinsLinked, DebitedFunds, CreditedFunds, ConversionRate class FieldDescriptor(object): @@ -858,7 +858,8 @@ def api_value(self, value): class PayinsLinkedField(Field): def python_value(self, value): if value is not None: - return PayinsLinked(payin_capture_id=value['PayinCaptureId'], payin_complement_id=value['PayinComplementId']) + return PayinsLinked(payin_capture_id=value['PayinCaptureId'], + payin_complement_id=value['PayinComplementId']) return value def api_value(self, value): @@ -871,3 +872,55 @@ def api_value(self, value): } return value + + +class DebitedFundsField(Field): + def python_value(self, value): + if value is not None: + return DebitedFunds(currency=value['Currency'], amount=value['Amount']) + return value + + def api_value(self, value): + value = super(DebitedFundsField, self).api_value(value) + + if isinstance(value, DebitedFunds): + value = { + 'Currency': value.currency, + 'Amount': value.amount + } + + return value + +class CreditedFundsField(Field): + def python_value(self, value): + if value is not None: + return CreditedFunds(currency=value['Currency'], amount=value['Amount']) + return value + + def api_value(self, value): + value = super(CreditedFundsField, self).api_value(value) + + if isinstance(value, CreditedFunds): + value = { + 'Currency': value.currency, + 'Amount': value.amount + } + + return value + +class ConversionRateField(Field): + def python_value(self, value): + if value is not None: + return ConversionRate(client_rate=value['ClientRate'], market_rate=value['MarketRate']) + return value + + def api_value(self, value): + value = super(ConversionRateField, self).api_value(value) + + if isinstance(value, ConversionRate): + value = { + 'ClientRate': value.client_rate, + 'MarketRate': value.market_rate + } + + return value diff --git a/mangopay/resources.py b/mangopay/resources.py index 65c4f51..2e6b5ee 100644 --- a/mangopay/resources.py +++ b/mangopay/resources.py @@ -14,7 +14,7 @@ ReportWalletsFiltersField, BillingField, SecurityInfoField, PlatformCategorizationField, BirthplaceField, ApplepayPaymentDataField, GooglepayPaymentDataField, ScopeBlockedField, BrowserInfoField, ShippingField, CurrentStateField, FallbackReasonField, InstantPayoutField, - CountryAuthorizationDataField, PayinsLinkedField) + CountryAuthorizationDataField, PayinsLinkedField, DebitedFundsField, CreditedFundsField, ConversionRateField) from .query import InsertQuery, UpdateQuery, SelectQuery, ActionQuery @@ -264,6 +264,67 @@ def get(cls, *args, **kwargs): return ClientWallet.get(*tuple(args[0].split('_')), **kwargs) return super(Wallet, cls).get(*args, **kwargs) +@python_2_unicode_compatible +class ConversionRate(BaseModel): + debited_currency = CharField(api_name='DebitedCurrency') + credited_currency = CharField(api_name='CreditedCurrency') + client_rate = CharField(api_name='ClientRate') + market_rate = CharField(api_name='MarketRate') + + def get_conversion_rate(self, client_id, *args, **kwargs): + kwargs['id'] = client_id + kwargs['debited_currency'] = self.debited_currency + kwargs['credited_currency'] = self.credited_currency + select = SelectQuery(ConversionRate, *args, **kwargs) + select.identifier = 'GET_CONVERSION_RATE' + return select.all(*args, **kwargs) + + class Meta: + verbose_name = 'conversion_rate' + verbose_name_plural = 'conversion_rates' + url = { + 'GET_CONVERSION_RATE' : '/%(id)s/conversion/rate/%(debited_currency)s/%(credited_currency)s' + } + +@python_2_unicode_compatible +class InstantConversion(BaseModel): + author = ForeignKeyField(User, api_name='AuthorId', required=True) + debited_wallet = ForeignKeyField(Wallet, api_name='DebitedWalletId', required=True) + credited_wallet = ForeignKeyField(Wallet, api_name='CreditedWalletId', required=True) + debited_funds = DebitedFundsField(api_name='DebitedFunds', required=True) + credited_funds = CreditedFundsField(api_name='CreditedFunds', required=True) + conversion_rate = ConversionRateField(api_name='ConversionRate') + type = CharField(api_name='Type', choices=constants.TRANSACTION_TYPE_CHOICES, default=None) + nature = CharField(api_name='Nature', choices=constants.NATURE_CHOICES, default=None) + creation_date = DateTimeField(api_name='CreationDate') + result_code = CharField(api_name='ResultCode') + result_message = CharField(api_name='ResultMessage') + status = CharField(api_name='Status', choices=constants.STATUS_CHOICES, default=None) + execution_date = DateTimeField(api_name='ExecutionDate') + currency = CharField(api_name='Currency') + + def create_instant_conversion(self, client_id, **kwargs): + insert = InsertQuery(self, **kwargs) + insert.insert_query = self.get_field_dict() + insert.insert_query['client_id'] = client_id + insert.identifier = 'CREATE_INSTANT_CONVERSION' + return insert.execute() + + def get_instant_conversion(self, client_id, *args, **kwargs): + kwargs['client_id'] = client_id + kwargs['id'] = self.id + select = SelectQuery(InstantConversion, *args, **kwargs) + select.identifier = 'GET_INSTANT_CONVERSION' + return select.all(*args, **kwargs) + + class Meta: + verbose_name = 'instant_conversion' + verbose_name_plural = 'instant_conversions' + url = { + 'CREATE_INSTANT_CONVERSION' : '/%(client_id)s/instant-conversion', + 'GET_INSTANT_CONVERSION': '/%(client_id)s/instant-conversion/%(id)s' + } + @python_2_unicode_compatible class Transfer(BaseModel): diff --git a/mangopay/utils.py b/mangopay/utils.py index 62a8ee4..0ad4932 100644 --- a/mangopay/utils.py +++ b/mangopay/utils.py @@ -945,3 +945,33 @@ def to_api_json(self): "TaxAmount": self.tax_amount, "Description": self.description } + +@add_camelcase_aliases +class DebitedFunds(object): + def __init__(self, currency=None, amount=None): + self.currency = currency + self.amount = amount + + def __str__(self): + return 'Debited funds: %s' % \ + (self.currency, self.amount) + +@add_camelcase_aliases +class CreditedFunds(object): + def __init__(self, currency=None, amount=None): + self.currency = currency + self.amount = amount + + def __str__(self): + return 'Credited funds: %s' % \ + (self.currency, self.amount) + +@add_camelcase_aliases +class ConversionRate(object): + def __init__(self, client_rate=None, market_rate=None): + self.client_rate = client_rate + self.market_rate = market_rate + + def __str__(self): + return 'Conversion rate: %s' % \ + (self.client_rate, self.market_rate) \ No newline at end of file diff --git a/tests/test_wallets.py b/tests/test_wallets.py index 026e0c2..4085ed9 100644 --- a/tests/test_wallets.py +++ b/tests/test_wallets.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- from tests import settings -from tests.resources import NaturalUser, Wallet, Transfer -from tests.test_base import BaseTest +from tests.resources import NaturalUser, Wallet, Transfer, ConversionRate, InstantConversion +from mangopay.utils import DebitedFunds, CreditedFunds +from tests.test_base import BaseTest, BaseTestLive from datetime import date @@ -17,7 +18,7 @@ def test_create_wallet(self): self.register_mock([ { 'method': responses.POST, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/wallets', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/wallets', 'body': { "Owners": [ "1169419" @@ -36,7 +37,7 @@ def test_create_wallet(self): }, { 'method': responses.GET, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/wallets/1169421', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/wallets/1169421', 'body': { "Owners": [ "1169419" @@ -55,7 +56,7 @@ def test_create_wallet(self): }, { 'method': responses.PUT, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/wallets/1169421', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/wallets/1169421', 'body': { "Owners": [ "1169419" @@ -74,7 +75,7 @@ def test_create_wallet(self): }, { 'method': responses.GET, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/users/1169419/wallets', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/users/1169419/wallets', 'body': [ { "Owners": [ @@ -131,7 +132,7 @@ def test_related_wallet(self): self.register_mock([ { 'method': responses.POST, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/wallets', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/wallets', 'body': { "Owners": [ "1167492" @@ -150,7 +151,7 @@ def test_related_wallet(self): }, { 'method': responses.GET, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/users/natural/1169419', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/users/natural/1169419', 'body': { "FirstName": "Victor", "LastName": "Claver", @@ -160,7 +161,7 @@ def test_related_wallet(self): "City": "City", "Region": "Region", "PostalCode": "11222", - "Country": "FR" + "Country": "FR" }, "Birthday": int(time.mktime(date.today().timetuple())), "Nationality": "FR", @@ -178,7 +179,7 @@ def test_related_wallet(self): }, { 'method': responses.GET, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/users/1169419/wallets', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/users/1169419/wallets', 'body': [ { "Owners": [ @@ -219,7 +220,7 @@ def test_retrieve_wallet_transactions(self): self.register_mock([ { 'method': responses.POST, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/wallets', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/wallets', 'body': { "Owners": [ "1167492" @@ -238,7 +239,7 @@ def test_retrieve_wallet_transactions(self): }, { 'method': responses.POST, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/transfers', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/transfers', 'body': { "Id": "1169434", "Tag": "custom tag", @@ -270,7 +271,7 @@ def test_retrieve_wallet_transactions(self): }, { 'method': responses.GET, - 'url': settings.MANGOPAY_API_SANDBOX_URL+settings.MANGOPAY_CLIENT_ID+'/wallets/1169421/transactions', + 'url': settings.MANGOPAY_API_SANDBOX_URL + settings.MANGOPAY_CLIENT_ID + '/wallets/1169421/transactions', 'body': [ { "Id": "1169215", @@ -327,3 +328,86 @@ def test_retrieve_wallet_transactions(self): self.assertEqual(len(transactions), 1) self.assertEqual(transactions[0].type, 'TRANSFER') + + def test_get_conversion_rate(self): + self.mock_natural_user() + user = BaseTestLive.get_john() + + conversion_rate = ConversionRate() + conversion_rate.debited_currency = 'EUR' + conversion_rate.credited_currency = 'GBP' + + complete_conversion_rate = conversion_rate.get_conversion_rate(user.id) + + self.assertIsNotNone(complete_conversion_rate) + + def test_create_instant_conversion(self): + user = BaseTestLive.get_john() + + credited_wallet = Wallet() + credited_wallet.owners = (user,) + credited_wallet.currency = 'EUR' + credited_wallet.description = 'WALLET IN EUR' + credited_wallet = Wallet(**credited_wallet.save()) + + debited_wallet = Wallet() + debited_wallet.owners = (user,) + debited_wallet.currency = 'GBP' + debited_wallet.description = 'WALLET IN GBP' + debited_wallet = Wallet(**credited_wallet.save()) + + credited_funds = CreditedFunds() + credited_funds.currency = 'EUR' + + debited_funds = DebitedFunds() + debited_funds.currency = 'GBP' + debited_funds.amount = 79 + + instant_conversion = InstantConversion() + instant_conversion.author = user + instant_conversion.credited_wallet = credited_wallet + instant_conversion.debited_wallet = debited_wallet + instant_conversion.credited_funds = credited_funds + instant_conversion.debited_funds = debited_funds + instant_conversion.tag = "instant conversion test" + + instant_conversion_response = instant_conversion.create_instant_conversion(user.id) + + self.assertIsNotNone(instant_conversion_response) + + def test_get_instant_conversion(self): + user = BaseTestLive.get_john() + + credited_wallet = Wallet() + credited_wallet.owners = (user,) + credited_wallet.currency = 'EUR' + credited_wallet.description = 'WALLET IN EUR' + credited_wallet = Wallet(**credited_wallet.save()) + + debited_wallet = Wallet() + debited_wallet.owners = (user,) + debited_wallet.currency = 'GBP' + debited_wallet.description = 'WALLET IN GBP' + debited_wallet = Wallet(**credited_wallet.save()) + + credited_funds = CreditedFunds() + credited_funds.currency = 'EUR' + + debited_funds = DebitedFunds() + debited_funds.currency = 'GBP' + debited_funds.amount = 79 + + instant_conversion = InstantConversion() + instant_conversion.author = user + instant_conversion.credited_wallet = credited_wallet + instant_conversion.debited_wallet = debited_wallet + instant_conversion.credited_funds = credited_funds + instant_conversion.debited_funds = debited_funds + instant_conversion.tag = "instant conversion test" + + instant_conversion_response = instant_conversion.create_instant_conversion(user.id) + returned_conversion_response = instant_conversion_response.get_instant_conversion(user.id) + + self.assertIsNotNone(returned_conversion_response) + +