data-xexe/xexe/rate_fetching.py
2024-06-13 15:56:57 +02:00

85 lines
2.4 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,
)
def build_rate_fetcher(rates_source: str, rate_sources_mapping):
return rate_sources_mapping[rates_source]()