Files
@ 5a8da108b983
Branch filter:
Location: NPO-Accounting/conservancy_beancount/tests/test_reports_balances.py
5a8da108b983
4.4 KiB
text/x-python
statement_reconciler: Add initial Chase bank CSV statement matching
We currently don't have many examples to work with, so haven't done any
significant testing of the matching accuracy between statement and books.
We currently don't have many examples to work with, so haven't done any
significant testing of the matching accuracy between statement and books.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | """test_reports_balances.py - Unit tests for Balances class"""
# Copyright © 2020 Brett Smith
# License: AGPLv3-or-later WITH Beancount-Plugin-Additional-Permission-1.0
#
# Full copyright and licensing details can be found at toplevel file
# LICENSE.txt in the repository.
import datetime
import itertools
import pytest
from . import testutil
from beancount.core.data import Open
from conservancy_beancount import data
from conservancy_beancount.reports import core
Fund = core.Fund
Period = core.Period
clean_account_meta = pytest.fixture(scope='module')(testutil.clean_account_meta)
@pytest.fixture(scope='module')
def income_expense_entries():
txns = []
prior_date = datetime.date(2019, 2, 2)
period_date = datetime.date(2019, 4, 4)
for (acct, post_meta), fund in itertools.product([
('Income:Donations', 'Donations'),
('Income:Sales', 'RBI'),
('Expenses:Postage', 'fundraising'),
('Expenses:Postage', 'management'),
('Expenses:Postage', 'program'),
('Expenses:Services', 'fundraising'),
('Expenses:Services', 'program'),
], ['Conservancy', 'Alpha']):
root_acct, _, classification = acct.partition(':')
try:
data.Account(acct).meta
except KeyError:
data.Account.load_opening(Open(
{'classification': classification},
datetime.date(2000, 1, 1),
acct, None, None,
))
meta = {
'project': fund,
f'{root_acct.lower().rstrip("s")}-type': post_meta,
}
sign = '' if root_acct == 'Expenses' else '-'
txns.append(testutil.Transaction(date=prior_date, postings=[
(acct, f'{sign}2.40', meta),
]))
txns.append(testutil.Transaction(date=period_date, postings=[
(acct, f'{sign}2.60', meta),
]))
return txns
@pytest.fixture(scope='module')
def expense_balances(income_expense_entries):
return core.Balances(
data.Posting.from_entries(income_expense_entries),
datetime.date(2019, 3, 1),
datetime.date(2020, 3, 1),
'expense-type',
)
@pytest.fixture(scope='module')
def income_balances(income_expense_entries):
return core.Balances(
data.Posting.from_entries(income_expense_entries),
datetime.date(2019, 3, 1),
datetime.date(2020, 3, 1),
'income-type',
)
@pytest.mark.parametrize('kwargs,expected', [
({'account': 'Income:Donations'}, -10),
({'account': 'Income'}, -20),
({'account': 'Income:Nonexistent'}, None),
({'classification': 'Postage'}, 30),
({'classification': 'Services'}, 20),
({'classification': 'Nonexistent'}, None),
({'period': Period.PRIOR, 'account': 'Income'}, '-9.60'),
({'period': Period.PERIOD, 'account': 'Expenses'}, 26),
({'fund': Fund.RESTRICTED, 'account': 'Income'}, -10),
({'fund': Fund.UNRESTRICTED, 'account': 'Expenses'}, 25),
({'post_meta': 'fundraising'}, 20),
({'post_meta': 'management'}, 10),
({'post_meta': 'Donations'}, None),
({'post_meta': 'RBI'}, None),
({'period': Period.PRIOR, 'post_meta': 'fundraising'}, '9.60'),
({'fund': Fund.RESTRICTED, 'post_meta': 'program'}, 10),
({'period': Period.PRIOR, 'fund': Fund.RESTRICTED, 'post_meta': 'program'}, '4.80'),
({'period': Period.PERIOD, 'fund': Fund.RESTRICTED, 'post_meta': 'ø'}, None),
({'account': ('Income', 'Expenses')}, 30),
({'account': ('Income', 'Expenses'), 'fund': Fund.UNRESTRICTED}, 15),
])
def test_expense_balance_total(expense_balances, kwargs, expected):
actual = expense_balances.total(**kwargs)
if expected is None:
assert not actual
else:
assert actual == {'USD': testutil.Amount(expected)}
@pytest.mark.parametrize('kwargs,expected', [
({'post_meta': 'fundraising'}, None),
({'post_meta': 'management'}, None),
({'post_meta': 'Donations'}, -10),
({'post_meta': 'RBI'}, -10),
({'period': Period.PRIOR, 'post_meta': 'Donations'}, '-4.80'),
({'fund': Fund.RESTRICTED, 'post_meta': 'RBI'}, -5),
({'period': Period.PRIOR, 'fund': Fund.RESTRICTED, 'post_meta': 'Donations'}, '-2.40'),
({'period': Period.PERIOD, 'fund': Fund.RESTRICTED, 'post_meta': 'ø'}, None),
])
def test_income_balance_total(income_balances, kwargs, expected):
actual = income_balances.total(**kwargs)
if expected is None:
assert not actual
else:
assert actual == {'USD': testutil.Amount(expected)}
|