balance_sheet: Add chart of accounts.
This commit is contained in:
parent
6159870681
commit
ee40b5b5c2
2 changed files with 52 additions and 2 deletions
|
@ -189,6 +189,15 @@ class Balances:
|
||||||
return prefix, -max_bal
|
return prefix, -max_bal
|
||||||
return sorted(class_bals, key=sortkey)
|
return sorted(class_bals, key=sortkey)
|
||||||
|
|
||||||
|
def iter_accounts(self, root: str) -> Iterable[data.Account]:
|
||||||
|
start_date = self.period_range.start
|
||||||
|
stop_date = self.period_range.stop
|
||||||
|
for account in data.Account.iter_accounts(root):
|
||||||
|
meta = account.meta
|
||||||
|
if (meta.open_date < stop_date
|
||||||
|
and (meta.close_date is None or meta.close_date > start_date)):
|
||||||
|
yield account
|
||||||
|
|
||||||
|
|
||||||
class Report(core.BaseODS[Sequence[None], None]):
|
class Report(core.BaseODS[Sequence[None], None]):
|
||||||
C_CASH = 'Cash'
|
C_CASH = 'Cash'
|
||||||
|
@ -233,6 +242,7 @@ class Report(core.BaseODS[Sequence[None], None]):
|
||||||
self.write_activities()
|
self.write_activities()
|
||||||
self.write_functional_expenses()
|
self.write_functional_expenses()
|
||||||
self.write_cash_flows()
|
self.write_cash_flows()
|
||||||
|
self.write_chart_of_accounts()
|
||||||
|
|
||||||
def walk_classifications(self, cseq: Iterable[data.Account]) \
|
def walk_classifications(self, cseq: Iterable[data.Account]) \
|
||||||
-> Iterator[Tuple[str, Optional[data.Account]]]:
|
-> Iterator[Tuple[str, Optional[data.Account]]]:
|
||||||
|
@ -261,6 +271,7 @@ class Report(core.BaseODS[Sequence[None], None]):
|
||||||
totals_prefix: Sequence[str]=(),
|
totals_prefix: Sequence[str]=(),
|
||||||
first_width: Union[float, str]=3,
|
first_width: Union[float, str]=3,
|
||||||
width: Union[float, str]=1.5,
|
width: Union[float, str]=1.5,
|
||||||
|
title_fmt: str="DRAFT Statement of {sheet_name}",
|
||||||
) -> None:
|
) -> None:
|
||||||
header_cells: Sequence[odf.table.TableCell] = [
|
header_cells: Sequence[odf.table.TableCell] = [
|
||||||
odf.table.TableCell(),
|
odf.table.TableCell(),
|
||||||
|
@ -277,7 +288,7 @@ class Report(core.BaseODS[Sequence[None], None]):
|
||||||
start_date = self.balances.period_range.start.strftime(self.date_fmt)
|
start_date = self.balances.period_range.start.strftime(self.date_fmt)
|
||||||
self.add_row(
|
self.add_row(
|
||||||
self.multiline_cell([
|
self.multiline_cell([
|
||||||
f"DRAFT Statement of {sheet_name}",
|
title_fmt.format(sheet_name=sheet_name),
|
||||||
f"{start_date}—{self.period_name}",
|
f"{start_date}—{self.period_name}",
|
||||||
], numbercolumnsspanned=self.col_count, stylename=self.style_header)
|
], numbercolumnsspanned=self.col_count, stylename=self.style_header)
|
||||||
)
|
)
|
||||||
|
@ -554,6 +565,45 @@ class Report(core.BaseODS[Sequence[None], None]):
|
||||||
stylename=self.style_bottomline,
|
stylename=self.style_bottomline,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def write_chart_of_accounts(self) -> None:
|
||||||
|
self.start_sheet(
|
||||||
|
"Chart of Accounts",
|
||||||
|
["Account Name"], ["Classification"],
|
||||||
|
totals_prefix=["Change During", "Year Ending"],
|
||||||
|
title_fmt="{sheet_name}",
|
||||||
|
)
|
||||||
|
# Widen text columns
|
||||||
|
col_style = self.column_style(3.5)
|
||||||
|
for col in self.sheet.childNodes[:2]:
|
||||||
|
col.setAttribute('stylename', col_style)
|
||||||
|
# Patch up header row text
|
||||||
|
header_row = self.sheet.lastChild
|
||||||
|
header_row.removeChild(header_row.firstChild)
|
||||||
|
header_row.addElement(self.multiline_cell(
|
||||||
|
["Balance Ending", self.period_name],
|
||||||
|
stylename=header_row.lastChild.getAttribute('stylename'),
|
||||||
|
))
|
||||||
|
|
||||||
|
for acct_root in ['Assets', 'Liabilities', 'Income', 'Expenses', 'Equity']:
|
||||||
|
norm_func = core.normalize_amount_func(f'{acct_root}:Dummy')
|
||||||
|
want_balance = acct_root not in EQUITY_ACCOUNTS
|
||||||
|
self.add_row()
|
||||||
|
for account in self.balances.iter_accounts(acct_root):
|
||||||
|
period_bal = self.balances.total(account=account, period=Period.PERIOD)
|
||||||
|
prior_bal = self.balances.total(account=account, period=Period.PRIOR)
|
||||||
|
if want_balance:
|
||||||
|
total_bal = self.balances.total(account=account)
|
||||||
|
total_cell = self.balance_cell(norm_func(total_bal))
|
||||||
|
else:
|
||||||
|
total_cell = odf.table.TableCell()
|
||||||
|
self.add_row(
|
||||||
|
self.string_cell(account),
|
||||||
|
self.string_cell(account.meta.get('classification', '')),
|
||||||
|
self.balance_cell(norm_func(period_bal)),
|
||||||
|
self.balance_cell(norm_func(prior_bal)),
|
||||||
|
total_cell,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_arguments(arglist: Optional[Sequence[str]]=None) -> argparse.Namespace:
|
def parse_arguments(arglist: Optional[Sequence[str]]=None) -> argparse.Namespace:
|
||||||
parser = argparse.ArgumentParser(prog=PROGNAME)
|
parser = argparse.ArgumentParser(prog=PROGNAME)
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -5,7 +5,7 @@ from setuptools import setup
|
||||||
setup(
|
setup(
|
||||||
name='conservancy_beancount',
|
name='conservancy_beancount',
|
||||||
description="Plugin, library, and reports for reading Conservancy's books",
|
description="Plugin, library, and reports for reading Conservancy's books",
|
||||||
version='1.8.0',
|
version='1.8.1',
|
||||||
author='Software Freedom Conservancy',
|
author='Software Freedom Conservancy',
|
||||||
author_email='info@sfconservancy.org',
|
author_email='info@sfconservancy.org',
|
||||||
license='GNU AGPLv3+',
|
license='GNU AGPLv3+',
|
||||||
|
|
Loading…
Reference in a new issue