43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
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
|
|
|
|
|
|
class MoneyAmount:
|
|
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
|