diff --git a/conservancy_beancount/reports/core.py b/conservancy_beancount/reports/core.py index d2baca47dcd33402345b2fef6056672d0de03607..eb32eb97d4c904f3e87872b4776428f285ef694e 100644 --- a/conservancy_beancount/reports/core.py +++ b/conservancy_beancount/reports/core.py @@ -21,6 +21,8 @@ from decimal import Decimal import babel.numbers # type:ignore[import] +from beancount.core import amount as bc_amount + from .. import data from typing import ( @@ -73,6 +75,11 @@ class Balance(Mapping[str, data.Amount]): def __str__(self) -> str: return self.format() + def __abs__(self) -> 'Balance': + return type(self)( + (key, bc_amount.abs(amt)) for key, amt in self.items() + ) + def __eq__(self, other: Any) -> bool: if (self.is_zero() and isinstance(other, Balance) diff --git a/tests/test_reports_balance.py b/tests/test_reports_balance.py index 5855ba35049e5f59fb3f92d81db24a665282d081..876c04bac72224fd53bc200ec0f8cae63790bcf7 100644 --- a/tests/test_reports_balance.py +++ b/tests/test_reports_balance.py @@ -127,6 +127,25 @@ def test_le_zero(balance_map_kwargs, expected): balance = core.Balance(amounts.items()) assert balance.le_zero() == expected +@pytest.mark.parametrize('balance_map_kwargs', [ + {}, + {'USD': 0}, + {'EUR': 10}, + {'JPY': 20, 'BRL': 30}, + {'EUR': -15}, + {'JPY': -25, 'BRL': -35}, + {'JPY': 40, 'USD': 0, 'EUR': -50}, +]) +def test_abs(balance_map_kwargs): + amounts = testutil.balance_map(**balance_map_kwargs) + actual = abs(core.Balance(amounts.items())) + assert set(actual) == set(balance_map_kwargs) + abs_amounts = testutil.balance_map(**{ + key: abs(number) for key, number in balance_map_kwargs.items() + }) + for key in balance_map_kwargs: + assert actual[key] == abs_amounts[key] + @pytest.mark.parametrize('balance_map_kwargs', [ {}, {'USD': 0},