data-xexe/xexe/money_amount.py

46 lines
1.6 KiB
Python
Raw Permalink Normal View History

2024-06-27 17:06:25 +02:00
from decimal import Decimal, InvalidOperation
from typing import Union
from money.currency import Currency
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
2024-06-27 17:06:25 +02:00
2024-06-27 16:56:29 +02:00
class MoneyAmount:
2024-06-27 18:11:22 +02:00
def __init__(
self, amount: Union[int, Decimal, str], currency: Union[str, Currency]
) -> "MoneyAmount":
2024-06-27 17:06:25 +02:00
self.amount = self._parse_amount(amount)
self.currency = self._parse_currency(currency)
2024-06-27 18:11:22 +02:00
def _parse_amount(self, amount: Union[int, Decimal, str]) -> Decimal:
2024-06-27 17:06:25 +02:00
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)}")
2024-06-27 18:11:22 +02:00
def _parse_currency(self, currency: Union[str, Currency]) -> Currency:
2024-06-27 17:06:25 +02:00
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