diff --git a/tests/tests_integration/test_get_rates.py b/tests/tests_integration/test_get_rates.py index c41ec72..126d69a 100644 --- a/tests/tests_integration/test_get_rates.py +++ b/tests/tests_integration/test_get_rates.py @@ -108,11 +108,10 @@ def test_get_rates_dry_run_always_returns_42_as_rates(): # Check that all rows have the expected rate of 42, 1/42 or 1 and the correct dates for row in rows: assert row["rate"] in ( - "42", - "0.024", - "0.02", - "0", - "1", + "42.00000000", + "0.02380952", + "0.00000000", + "1.00000000", ), f"Expected rate to be 42, 1/42 or 1, but got {row['rate']}" assert row["rate_date"] in [ (some_random_date + datetime.timedelta(days=i)).strftime("%Y-%m-%d") diff --git a/tests/tests_unit/test_money_amount.py b/tests/tests_unit/test_money_amount.py index 33b17fa..5089cca 100644 --- a/tests/tests_unit/test_money_amount.py +++ b/tests/tests_unit/test_money_amount.py @@ -3,7 +3,7 @@ from decimal import Decimal import pytest from money.currency import Currency -from xexe.money_amount import DEFAULT_MAX_DECIMALS, MoneyAmount +from xexe.money_amount import DEFAULT_MONEY_PRECISION, MoneyAmount def test_money_amount_simple_creation_works(): @@ -23,13 +23,13 @@ def test_money_amount_takes_integer_amounts(): def test_money_amount_takes_decimal_amounts(): an_amount = MoneyAmount(amount=Decimal(10.5), currency=Currency.USD) - assert an_amount.amount == Decimal(10.5).quantize(DEFAULT_MAX_DECIMALS) + assert an_amount.amount == Decimal(10.5).quantize(DEFAULT_MONEY_PRECISION) def test_money_amount_takes_proper_strings_amounts(): an_amount = MoneyAmount(amount="10.55", currency=Currency.USD) - assert an_amount.amount == Decimal(10.55).quantize(DEFAULT_MAX_DECIMALS) + assert an_amount.amount == Decimal(10.55).quantize(DEFAULT_MONEY_PRECISION) def test_money_amount_fails_with_ugly_strings(): @@ -46,4 +46,4 @@ def test_money_amount_takes_string_for_currency(): def test_money_amount_works_with_8_decimal_positions(): an_amount = MoneyAmount(amount="1.12345678", currency="USD") - assert an_amount.amount == Decimal(1.12345678).quantize(DEFAULT_MAX_DECIMALS) + assert an_amount.amount == Decimal(1.12345678).quantize(DEFAULT_MONEY_PRECISION) diff --git a/xexe/constants.py b/xexe/constants.py index 759b24d..c7ec3d4 100644 --- a/xexe/constants.py +++ b/xexe/constants.py @@ -1,6 +1,5 @@ import pathlib from dataclasses import dataclass -from decimal import Decimal from money.currency import Currency @@ -8,8 +7,6 @@ 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/exchange_rates.py b/xexe/exchange_rates.py index 209acf7..ecbc9b3 100644 --- a/xexe/exchange_rates.py +++ b/xexe/exchange_rates.py @@ -3,8 +3,9 @@ from decimal import Decimal from numbers import Number from typing import Iterable, Set, Union -from money.currency import Currency, CurrencyHelper -from money.money import Money +from money.currency import Currency + +from xexe.money_amount import DEFAULT_MONEY_PRECISION_POSITIONS, MoneyAmount class ExchangeRate: @@ -13,13 +14,13 @@ class ExchangeRate: self, from_currency: Currency, to_currency: Currency, - rate: Union[Money, Number, str], + rate: Union[MoneyAmount, Number, str], rate_date: datetime.date, ) -> None: self.from_currency = from_currency self.to_currency = to_currency - if not isinstance(rate, Money): - rate = Money(rate, to_currency) + if not isinstance(rate, MoneyAmount): + rate = MoneyAmount(amount=rate, currency=to_currency) self.rate = rate self.rate_date = rate_date @@ -100,7 +101,7 @@ def add_equal_rates(rates: ExchangeRates, overwrite: bool = False) -> ExchangeRa new_rate = ExchangeRate( from_currency=currency, to_currency=currency, - rate=Money(1, currency), + rate=MoneyAmount(1, currency), rate_date=date, ) if new_rate in rates and not overwrite: @@ -122,7 +123,7 @@ def add_inverse_rates(rates: ExchangeRates) -> ExchangeRates: from_currency=rate.to_currency, to_currency=rate.from_currency, rate_date=rate.rate_date, - rate=f"{1 / rate.amount:.{CurrencyHelper.decimal_precision_for_currency(rate.from_currency)}f}", + rate=f"{1 / rate.amount:.{DEFAULT_MONEY_PRECISION_POSITIONS}f}", ) rates.add_rate(inverse_rate) diff --git a/xexe/money_amount.py b/xexe/money_amount.py index aaaace8..2976315 100644 --- a/xexe/money_amount.py +++ b/xexe/money_amount.py @@ -3,9 +3,12 @@ from typing import Union from money.currency import Currency -from xexe.constants import DEFAULT_MAX_DECIMALS - -DEFAULT_MONEY_PRECISION = DEFAULT_MAX_DECIMALS +DEFAULT_MONEY_PRECISION_POSITIONS = 8 +DEFAULT_MONEY_PRECISION = Decimal( + "0." + ("0" * (DEFAULT_MONEY_PRECISION_POSITIONS - 1)) + "1" +) +# If we have X decimal positions, we want 7 zeros and 1 one +# i.e. 0. 000 000 01 class MoneyAmount: diff --git a/xexe/rate_fetching.py b/xexe/rate_fetching.py index 705f0f0..37076d5 100644 --- a/xexe/rate_fetching.py +++ b/xexe/rate_fetching.py @@ -1,13 +1,12 @@ 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 money.currency import Currency from xecd_rates_client import XecdClient from xexe.exchange_rates import ExchangeRate +from xexe.money_amount import DEFAULT_MONEY_PRECISION_POSITIONS, MoneyAmount class RateFetcher(ABC): @@ -35,7 +34,7 @@ class MockRateFetcher(RateFetcher): return ExchangeRate( from_currency=from_currency, to_currency=to_currency, - rate=Money(42, to_currency), + rate=MoneyAmount(42, to_currency), rate_date=rate_date, ) @@ -71,7 +70,7 @@ class XERateFetcher(RateFetcher): "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}""" + rate = f"""{response["to"][0]["mid"]:.{DEFAULT_MONEY_PRECISION_POSITIONS}f}""" return ExchangeRate( from_currency=from_currency,