import datetime import os from abc import ABC, abstractmethod from money.currency import Currency from money.money import Money from xecd_rates_client import XecdClient class ExchangeRate: def __init__( self, from_currency: Currency, to_currency: Currency, rate: Money, rate_date: datetime.date = None, ) -> None: self.from_currency self.to_currency self.rate self.rate_date class RateFetcher(ABC): @abstractmethod def fetch_rate( self, from_currency: Currency, to_currency: Currency, rate_date: datetime.date ) -> ExchangeRate: pass class MockRateFetcher(RateFetcher): def __init__(self) -> None: super().__init__() def fetch_rate( self, from_currency: Currency, to_currency: Currency, rate_date: datetime.date ) -> ExchangeRate: return ExchangeRate( from_currency=from_currency, to_currency=to_currency, rate=Money("42.0", to_currency), rate_date=rate_date, ) class XERateFetcher(RateFetcher): def __init__(self) -> None: super().__init__() self.xe_client = XecdClient( account_id=os.environ["XE_ACCOUNT_ID"], api_key=os.environ["XE_API_KEY"], ) def fetch_rate( self, from_currency: Currency, to_currency: Currency, rate_date: datetime.date ) -> ExchangeRate: response = self.xe_client.historic_rate( rate_date.strftime("%Y-%m-%d"), "12:00", from_currency.value, # .value will access the ISO 4217 str code of the currency to_currency.value, 1, # always 1, because the rate we want is how much of to_curr does # 1 unit of from_curr get us. ) # handle response into proper object