diff --git a/xexe/constants.py b/xexe/constants.py index c7ec3d4..759b24d 100644 --- a/xexe/constants.py +++ b/xexe/constants.py @@ -1,5 +1,6 @@ import pathlib from dataclasses import dataclass +from decimal import Decimal from money.currency import Currency @@ -7,6 +8,8 @@ from xexe.rate_fetching import MockRateFetcher, XERateFetcher DEFAULT_CURRENCIES = {Currency("EUR"), Currency("GBP"), Currency("USD")} +DEFAULT_MAX_DECIMALS = Decimal("0.00000001") + RATES_SOURCES = {"mock": MockRateFetcher, "xe": XERateFetcher} DWH_SCHEMA = "sync_xedotcom_currency_rates" diff --git a/xexe/money_amount.py b/xexe/money_amount.py index 0cba52d..aaaace8 100644 --- a/xexe/money_amount.py +++ b/xexe/money_amount.py @@ -1,2 +1,40 @@ +from decimal import Decimal, InvalidOperation +from typing import Union + +from money.currency import Currency + +from xexe.constants import DEFAULT_MAX_DECIMALS + +DEFAULT_MONEY_PRECISION = DEFAULT_MAX_DECIMALS + + class MoneyAmount: - pass + def __init__(self, amount, currency): + self.amount = self._parse_amount(amount) + self.currency = self._parse_currency(currency) + + def _parse_amount(self, amount: Union[int, Decimal, str]): + if isinstance(amount, (int, Decimal)): + return Decimal(amount).quantize(DEFAULT_MONEY_PRECISION) + elif isinstance(amount, str): + try: + return Decimal(amount).quantize(DEFAULT_MONEY_PRECISION) + except InvalidOperation: + raise ValueError(f"Invalid amount: {amount}") + else: + raise TypeError(f"Amount must be int, Decimal, or str, not {type(amount)}") + + def _parse_currency(self, currency): + if isinstance(currency, Currency): + return currency + if isinstance(currency, str): + return Currency[currency] + + raise TypeError( + f"Currency must be a Currency object or str, not {type(currency)}" + ) + + def __eq__(self, other): + if isinstance(other, MoneyAmount): + return self.amount == other.amount and self.currency == other.currency + return False