swap Money for MoneyAmount, fix a couple of things along the way

This commit is contained in:
Pablo Martin 2024-06-27 17:18:43 +02:00
parent ab2ac1ec6a
commit 0947b34ebf
6 changed files with 26 additions and 27 deletions

View file

@ -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 # Check that all rows have the expected rate of 42, 1/42 or 1 and the correct dates
for row in rows: for row in rows:
assert row["rate"] in ( assert row["rate"] in (
"42", "42.00000000",
"0.024", "0.02380952",
"0.02", "0.00000000",
"0", "1.00000000",
"1",
), f"Expected rate to be 42, 1/42 or 1, but got {row['rate']}" ), f"Expected rate to be 42, 1/42 or 1, but got {row['rate']}"
assert row["rate_date"] in [ assert row["rate_date"] in [
(some_random_date + datetime.timedelta(days=i)).strftime("%Y-%m-%d") (some_random_date + datetime.timedelta(days=i)).strftime("%Y-%m-%d")

View file

@ -3,7 +3,7 @@ from decimal import Decimal
import pytest import pytest
from money.currency import Currency 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(): 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(): def test_money_amount_takes_decimal_amounts():
an_amount = MoneyAmount(amount=Decimal(10.5), currency=Currency.USD) 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(): def test_money_amount_takes_proper_strings_amounts():
an_amount = MoneyAmount(amount="10.55", currency=Currency.USD) 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(): 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(): def test_money_amount_works_with_8_decimal_positions():
an_amount = MoneyAmount(amount="1.12345678", currency="USD") 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)

View file

@ -1,6 +1,5 @@
import pathlib import pathlib
from dataclasses import dataclass from dataclasses import dataclass
from decimal import Decimal
from money.currency import Currency 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_CURRENCIES = {Currency("EUR"), Currency("GBP"), Currency("USD")}
DEFAULT_MAX_DECIMALS = Decimal("0.00000001")
RATES_SOURCES = {"mock": MockRateFetcher, "xe": XERateFetcher} RATES_SOURCES = {"mock": MockRateFetcher, "xe": XERateFetcher}
DWH_SCHEMA = "sync_xedotcom_currency_rates" DWH_SCHEMA = "sync_xedotcom_currency_rates"

View file

@ -3,8 +3,9 @@ from decimal import Decimal
from numbers import Number from numbers import Number
from typing import Iterable, Set, Union from typing import Iterable, Set, Union
from money.currency import Currency, CurrencyHelper from money.currency import Currency
from money.money import Money
from xexe.money_amount import DEFAULT_MONEY_PRECISION_POSITIONS, MoneyAmount
class ExchangeRate: class ExchangeRate:
@ -13,13 +14,13 @@ class ExchangeRate:
self, self,
from_currency: Currency, from_currency: Currency,
to_currency: Currency, to_currency: Currency,
rate: Union[Money, Number, str], rate: Union[MoneyAmount, Number, str],
rate_date: datetime.date, rate_date: datetime.date,
) -> None: ) -> None:
self.from_currency = from_currency self.from_currency = from_currency
self.to_currency = to_currency self.to_currency = to_currency
if not isinstance(rate, Money): if not isinstance(rate, MoneyAmount):
rate = Money(rate, to_currency) rate = MoneyAmount(amount=rate, currency=to_currency)
self.rate = rate self.rate = rate
self.rate_date = rate_date self.rate_date = rate_date
@ -100,7 +101,7 @@ def add_equal_rates(rates: ExchangeRates, overwrite: bool = False) -> ExchangeRa
new_rate = ExchangeRate( new_rate = ExchangeRate(
from_currency=currency, from_currency=currency,
to_currency=currency, to_currency=currency,
rate=Money(1, currency), rate=MoneyAmount(1, currency),
rate_date=date, rate_date=date,
) )
if new_rate in rates and not overwrite: if new_rate in rates and not overwrite:
@ -122,7 +123,7 @@ def add_inverse_rates(rates: ExchangeRates) -> ExchangeRates:
from_currency=rate.to_currency, from_currency=rate.to_currency,
to_currency=rate.from_currency, to_currency=rate.from_currency,
rate_date=rate.rate_date, 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) rates.add_rate(inverse_rate)

View file

@ -3,9 +3,12 @@ from typing import Union
from money.currency import Currency from money.currency import Currency
from xexe.constants import DEFAULT_MAX_DECIMALS DEFAULT_MONEY_PRECISION_POSITIONS = 8
DEFAULT_MONEY_PRECISION = Decimal(
DEFAULT_MONEY_PRECISION = DEFAULT_MAX_DECIMALS "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: class MoneyAmount:

View file

@ -1,13 +1,12 @@
import datetime import datetime
import os import os
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from decimal import Decimal
from money.currency import Currency, CurrencyHelper from money.currency import Currency
from money.money import Money
from xecd_rates_client import XecdClient from xecd_rates_client import XecdClient
from xexe.exchange_rates import ExchangeRate from xexe.exchange_rates import ExchangeRate
from xexe.money_amount import DEFAULT_MONEY_PRECISION_POSITIONS, MoneyAmount
class RateFetcher(ABC): class RateFetcher(ABC):
@ -35,7 +34,7 @@ class MockRateFetcher(RateFetcher):
return ExchangeRate( return ExchangeRate(
from_currency=from_currency, from_currency=from_currency,
to_currency=to_currency, to_currency=to_currency,
rate=Money(42, to_currency), rate=MoneyAmount(42, to_currency),
rate_date=rate_date, rate_date=rate_date,
) )
@ -71,7 +70,7 @@ class XERateFetcher(RateFetcher):
"Z", "+00:00" "Z", "+00:00"
) # Funny replace is necessary because of API response format ) # Funny replace is necessary because of API response format
).date() ).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( return ExchangeRate(
from_currency=from_currency, from_currency=from_currency,