fund: Text output readability improvements.

Make it look more like the spreadsheets:

* Don't normalize Expenses negative.

* Consistent account order: Income, then Expenses, then Equity.

* Include a bottom line divider for each fund.
This commit is contained in:
Brett Smith 2020-08-22 09:49:19 -04:00
parent cc1767a09d
commit 58954aab23
2 changed files with 21 additions and 11 deletions

View file

@ -82,7 +82,7 @@ from .. import data
AccountsMap = Mapping[data.Account, core.PeriodPostings]
FundPosts = Tuple[MetaValue, AccountsMap]
EQUITY_ACCOUNTS = ['Equity', 'Income', 'Expenses']
EQUITY_ACCOUNTS = ['Income', 'Expenses', 'Equity']
INFO_ACCOUNTS = [
'Assets:Receivable',
'Assets:Prepaid',
@ -106,7 +106,7 @@ class ODSReport(core.BaseODS[FundPosts, None]):
headers = [["Fund"], ["Balance as of", self.start_date.isoformat()]]
if expanded:
sheet_name = "With Breakdowns"
headers += [["Income"], ["Expenses"], ["Equity"]]
headers.extend([acct] for acct in EQUITY_ACCOUNTS)
else:
sheet_name = "Fund Report"
headers += [["Additions"], ["Releases from", "Restrictions"]]
@ -176,10 +176,9 @@ class ODSReport(core.BaseODS[FundPosts, None]):
self.sheet = start_sheet
def _row_balances(self, accounts_map: AccountsMap) -> Iterator[core.Balance]:
acct_order = ['Income', 'Expenses', 'Equity']
key_order = [core.OPENING_BALANCE_NAME, *acct_order, core.ENDING_BALANCE_NAME]
key_order = [core.OPENING_BALANCE_NAME, *EQUITY_ACCOUNTS, core.ENDING_BALANCE_NAME]
balances: Dict[str, core.Balance] = {key: core.MutableBalance() for key in key_order}
for acct_s, balance in core.account_balances(accounts_map, acct_order):
for acct_s, balance in core.account_balances(accounts_map, EQUITY_ACCOUNTS):
if acct_s in balances:
balances[acct_s] = balance
else:
@ -242,7 +241,9 @@ class TextReport:
acct_s = total_fmt.format(self.start_date.isoformat())
elif acct_s is core.ENDING_BALANCE_NAME:
acct_s = total_fmt.format(self.stop_date.isoformat())
yield acct_s, (-balance).format(None, sep='\0').split('\0')
if not acct_s.startswith('Expenses:'):
balance = -balance
yield acct_s, balance.format(None, sep='\0').split('\0')
for _, account in core.sort_and_filter_accounts(account_map, INFO_ACCOUNTS):
balance = account_map[account].stop_bal
if not balance.is_zero():
@ -262,14 +263,19 @@ class TextReport:
print(line_fmt.replace('{:>', '{:^').format("ACCOUNT", "BALANCE"),
file=self.out_file)
fund_start = f' balance as of {self.start_date.isoformat()}'
fund_end = f' balance as of {self.stop_date.isoformat()}'
for acct_s, bal_seq in output:
if acct_s.endswith(fund_start):
print(line_fmt.format('' * acct_width, '' * bal_width),
is_end_bal = acct_s.endswith(fund_end)
if is_end_bal or acct_s.endswith(fund_start):
print(line_fmt.format('' * acct_width, '' * bal_width),
file=self.out_file)
bal_iter = iter(bal_seq)
print(line_fmt.format(acct_s, next(bal_iter)), file=self.out_file)
for bal_s in bal_iter:
print(line_fmt.format('', bal_s), file=self.out_file)
if is_end_bal:
print(line_fmt.format('' * acct_width, '' * bal_width),
file=self.out_file)
class ReportType(enum.Enum):

View file

@ -111,11 +111,13 @@ def check_text_balances(actual, expected, *expect_accounts):
balance = Decimal()
for expect_account in expect_accounts:
expect_amount = expected[expect_account]
balance += expect_amount
if expect_account.startswith('Expenses:'):
expect_amount *= -1
if expect_amount:
actual_account, actual_amount = next(actual)
assert actual_account == expect_account
assert actual_amount == format_amount(expect_amount)
balance += expect_amount
return balance
def check_text_report(output, project, start_date, stop_date):
@ -142,17 +144,19 @@ def check_text_report(output, project, start_date, stop_date):
assert open_amt == format_amount(balance_amount)
balance_amount += check_text_balances(
actual, expected,
'Income:Other',
'Expenses:Other',
'Equity:Funds:Restricted',
'Equity:Funds:Unrestricted',
'Equity:Realized:CurrencyConversion',
'Income:Other',
'Expenses:Other',
)
next(actual)
end_acct, end_amt = next(actual)
assert end_acct == "{} balance as of {}".format(
project, stop_date.isoformat(),
)
assert end_amt == format_amount(balance_amount)
next(actual)
balance_amount += check_text_balances(
actual, expected,
'Assets:Receivable:Accounts',