diff --git a/conservancy_beancount/reports/fund.py b/conservancy_beancount/reports/fund.py index bee58fe28daf7694c0090be5b1f4460c56788e78..3468bbba153de277d19603f248b5df49d6ad4522 100644 --- a/conservancy_beancount/reports/fund.py +++ b/conservancy_beancount/reports/fund.py @@ -158,8 +158,11 @@ class ODSReport(core.BaseODS[FundPosts, None]): bal_indexes = [0, 1, 2, 4] totals = [core.MutableBalance() for _ in bal_indexes] threshold = Decimal('.5') - for fund, balances in self.balances.items(): - balances = [balances[index] for index in bal_indexes] + for fund, source_bals in self.balances.items(): + balances = [source_bals[index] for index in bal_indexes] + # Incorporate Equity changes to Release from Restrictions. + # Note that using -= mutates the balance in a way we don't want. + balances[2] = balances[2] - source_bals[3] if (not all(bal.clean_copy(threshold).le_zero() for bal in balances) and fund != UNRESTRICTED_FUND): self.write_balances(fund, balances) diff --git a/tests/books/fund.beancount b/tests/books/fund.beancount index 68f7068301ae7de389817ce0d2600d792f7ec2fa..30a3c3b189c2814610980357496e474af61141f5 100644 --- a/tests/books/fund.beancount +++ b/tests/books/fund.beancount @@ -109,7 +109,13 @@ option "inferred_tolerance_default" "USD:0.01" Income:Other -200 USD Assets:Checking 200 USD -2019-12-03 * "Delta income" +2019-09-06 * "Delta income" project: "Delta" Income:Other -4.60 USD Assets:Checking 4.60 USD + +2019-12-03 * "Charlie release from restriction" + Equity:Funds:Restricted 100 USD + project: "Charlie" + Equity:Funds:Unrestricted -100 USD + project: "Conservancy" diff --git a/tests/test_opening_balances.py b/tests/test_opening_balances.py index a13daf2334dbf12969301a41f9efee1413172604..3f45c53d3f45d2e8c24581152b956fd8d827b4d9 100644 --- a/tests/test_opening_balances.py +++ b/tests/test_opening_balances.py @@ -146,7 +146,7 @@ def test_2020_opening(arg): FlatPosting.make(A_EUR, 32, 'EUR', '1.5', '2019-03-03'), FlatPosting.make(A_RESTRICTED, -3064, project='Alpha'), FlatPosting.make(A_RESTRICTED, -2180, project='Bravo'), - FlatPosting.make(A_RESTRICTED, -1000, project='Charlie'), + FlatPosting.make(A_RESTRICTED, -900, project='Charlie'), FlatPosting.make(A_RESTRICTED, -5, project='Delta'), - FlatPosting.make(A_UNRESTRICTED, -4080, project='Conservancy'), + FlatPosting.make(A_UNRESTRICTED, -4180, project='Conservancy'), ] diff --git a/tests/test_reports_fund.py b/tests/test_reports_fund.py index 298ec5740d2c58c32f37b4a15f9870faf2ed762d..42c6ed8ea2973662fad8005e9e1f504b6a680e1f 100644 --- a/tests/test_reports_fund.py +++ b/tests/test_reports_fund.py @@ -60,6 +60,7 @@ BALANCES_BY_YEAR = { ('Conservancy', 2019): [ ('Income:Other', 42), ('Expenses:Other', Decimal('-4.20')), + ('Equity:Funds:Unrestricted', 100), ('Equity:Realized:CurrencyConversion', Decimal('6.20')), ('Assets:Receivable:Accounts', -40), ('Liabilities:Payable:Accounts', -4), @@ -81,6 +82,9 @@ BALANCES_BY_YEAR = { ('Bravo', 2019): [ ('Income:Other', 200), ], + ('Charlie', 2019): [ + ('Equity:Funds:Restricted', -100), + ], ('Delta', 2018): [ ('Income:Other', Decimal('.40')), ], @@ -138,6 +142,8 @@ def check_text_report(output, project, start_date, stop_date): assert open_amt == format_amount(balance_amount) balance_amount += check_text_balances( actual, expected, + 'Equity:Funds:Restricted', + 'Equity:Funds:Unrestricted', 'Equity:Realized:CurrencyConversion', 'Income:Other', 'Expenses:Other', @@ -173,7 +179,7 @@ def check_ods_sheet(sheet, account_balances, *, full): if key != 'Conservancy' and any(v >= .5 for v in balances.values()) } totals = {key: Decimal() for key in - ['opening', 'Income', 'Expenses', 'Equity:Realized']} + ['opening', 'Income', 'Expenses', 'Equity']} for fund, balances in account_bals.items(): for key in totals: totals[key] += balances[key] @@ -190,11 +196,15 @@ def check_ods_sheet(sheet, account_balances, *, full): pytest.fail(f"report included unexpected fund {fund}") check_cell_balance(next(cells), balances['opening']) check_cell_balance(next(cells), balances['Income']) - check_cell_balance(next(cells), -balances['Expenses']) if full: - check_cell_balance(next(cells), balances['Equity:Realized']) + check_cell_balance(next(cells), -balances['Expenses']) + check_cell_balance(next(cells), balances['Equity']) + else: + check_cell_balance( + next(cells), -sum(balances[key] for key in ['Expenses', 'Equity']), + ) check_cell_balance(next(cells), sum(balances[key] for key in [ - 'opening', 'Income', 'Expenses', 'Equity:Realized', + 'opening', 'Income', 'Expenses', 'Equity', ])) if full: check_cell_balance(next(cells), balances['Assets:Receivable']) @@ -209,7 +219,7 @@ def check_ods_report(ods, start_date, stop_date): 'opening': Decimal(amount), 'Income': Decimal(0), 'Expenses': Decimal(0), - 'Equity:Realized': Decimal(0), + 'Equity': Decimal(0), 'Assets:Receivable': Decimal(0), 'Assets:Prepaid': Decimal(0), 'Liabilities:Payable': Decimal(0), @@ -222,8 +232,11 @@ def check_ods_report(ods, start_date, stop_date): pass else: for account, amount in amounts: - if year < start_date.year and account.startswith(EQUITY_ROOT_ACCOUNTS): - acct_key = 'opening' + if account.startswith(EQUITY_ROOT_ACCOUNTS): + if year < start_date.year: + acct_key = 'opening' + else: + acct_key, _, _ = account.partition(':') else: acct_key, _, _ = account.rpartition(':') account_bals[fund][acct_key] += amount