81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
import datetime
|
|
import os
|
|
from abc import ABC, abstractmethod
|
|
from decimal import Decimal
|
|
|
|
from money.currency import Currency, CurrencyHelper
|
|
from money.money import Money
|
|
from xecd_rates_client import XecdClient
|
|
|
|
from xexe.exchange_rates import ExchangeRate
|
|
|
|
|
|
class RateFetcher(ABC):
|
|
|
|
is_production_grade = False
|
|
|
|
@abstractmethod
|
|
def fetch_rate(
|
|
self, from_currency: Currency, to_currency: Currency, rate_date: datetime.date
|
|
) -> ExchangeRate:
|
|
pass
|
|
|
|
|
|
class MockRateFetcher(RateFetcher):
|
|
|
|
is_production_grade = False
|
|
|
|
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, to_currency),
|
|
rate_date=rate_date,
|
|
)
|
|
|
|
|
|
class XERateFetcher(RateFetcher):
|
|
|
|
is_production_grade = True
|
|
|
|
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.
|
|
)
|
|
|
|
from_currency = Currency(response["from"])
|
|
to_currency = Currency(response["to"][0]["quotecurrency"])
|
|
rate_date = datetime.datetime.fromisoformat(
|
|
response["timestamp"].replace(
|
|
"Z", "+00:00"
|
|
) # Funny replace is necessary because of API response format
|
|
).date()
|
|
rate = f"""{response["to"][0]["mid"]:.{CurrencyHelper.decimal_precision_for_currency(to_currency)}f}"""
|
|
|
|
return ExchangeRate(
|
|
from_currency=from_currency,
|
|
to_currency=to_currency,
|
|
rate_date=rate_date,
|
|
rate=rate,
|
|
)
|