reports: Add RelatedPostings.balance_at_cost() method.

This makes it easy to get results similar to `ledger -V`.
This commit is contained in:
Brett Smith 2020-05-27 22:29:45 -04:00
parent 52fa66bba1
commit 81d216f282
2 changed files with 65 additions and 0 deletions

View file

@ -199,6 +199,16 @@ class RelatedPostings(Sequence[data.Posting]):
except NameError:
return Balance()
def balance_at_cost(self) -> Balance:
balance = MutableBalance()
for post in self:
if post.cost is None:
balance.add_amount(post.units)
else:
number = post.units.number * post.cost.number
balance.add_amount(data.Amount(number, post.cost.currency))
return balance
def meta_values(self,
key: MetaKey,
default: Optional[MetaValue]=None,

View file

@ -135,6 +135,61 @@ def test_iter_with_balance_credit_card(credit_card_cycle):
def test_iter_with_balance_two_acccruals(two_accruals_three_payments):
check_iter_with_balance(two_accruals_three_payments)
def test_balance_at_cost_mixed():
txn = testutil.Transaction(postings=[
('Expenses:Other', '22'),
('Expenses:Other', '30', 'EUR', ('1.1',)),
('Expenses:Other', '40', 'EUR'),
('Expenses:Other', '50', 'USD', ('1.1', 'EUR')),
])
related = core.RelatedPostings(data.Posting.from_txn(txn))
balance = related.balance_at_cost()
amounts = set(balance.values())
assert amounts == {testutil.Amount(55, 'USD'), testutil.Amount(95, 'EUR')}
def test_balance_at_single_currency_cost():
txn = testutil.Transaction(postings=[
('Expenses:Other', '22'),
('Expenses:Other', '30', 'EUR', ('1.1',)),
('Expenses:Other', '40', 'GBP', ('1.1',)),
])
related = core.RelatedPostings(data.Posting.from_txn(txn))
balance = related.balance_at_cost()
amounts = set(balance.values())
assert amounts == {testutil.Amount(99)}
def test_balance_at_cost_zeroed_out():
txn = testutil.Transaction(postings=[
('Income:Other', '-22'),
('Assets:Receivable:Accounts', '20', 'EUR', ('1.1',)),
])
related = core.RelatedPostings(data.Posting.from_txn(txn))
balance = related.balance_at_cost()
assert balance.is_zero()
def test_balance_at_cost_singleton():
txn = testutil.Transaction(postings=[
('Assets:Receivable:Accounts', '20', 'EUR', ('1.1',)),
])
related = core.RelatedPostings(data.Posting.from_txn(txn))
balance = related.balance_at_cost()
amounts = set(balance.values())
assert amounts == {testutil.Amount(22)}
def test_balance_at_cost_singleton_without_cost():
txn = testutil.Transaction(postings=[
('Assets:Receivable:Accounts', '20'),
])
related = core.RelatedPostings(data.Posting.from_txn(txn))
balance = related.balance_at_cost()
amounts = set(balance.values())
assert amounts == {testutil.Amount(20)}
def test_balance_at_cost_empty():
related = core.RelatedPostings()
balance = related.balance_at_cost()
assert balance.is_zero()
def test_meta_values_empty():
related = core.RelatedPostings()
assert related.meta_values('key') == set()