Changeset - 07757e7717a5
[Not reviewed]
0 2 0
Brett Smith - 4 years ago 2020-08-17 21:09:31
brettcsmith@brettcsmith.org
balance_sheet: Add cash flows report.

With this, the balance sheet report has all the reports from the audit.
2 files changed with 112 insertions and 5 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/reports/balance_sheet.py
Show inline comments
...
 
@@ -181,9 +181,11 @@ class Balances:
 

	
 

	
 
class Report(core.BaseODS[Sequence[None], None]):
 
    C_CASH = 'Cash'
 
    C_SATISFIED = 'Satisfaction of program restrictions'
 
    EQUITY_ACCOUNTS = ['Equity', 'Income', 'Expenses']
 
    EQUITY_ACCOUNTS = frozenset(['Equity', 'Income', 'Expenses'])
 
    NO_BALANCE = core.Balance()
 
    SPACE = ' ' * 4
 

	
 
    def __init__(self,
 
                 balances: Balances,
...
 
@@ -219,6 +221,7 @@ class Report(core.BaseODS[Sequence[None], None]):
 
        self.write_financial_position()
 
        self.write_activities()
 
        self.write_functional_expenses()
 
        self.write_cash_flows()
 

	
 
    def walk_classifications(self, cseq: Iterable[data.Account]) \
 
        -> Iterator[Tuple[str, Optional[data.Account]]]:
...
 
@@ -226,11 +229,11 @@ class Report(core.BaseODS[Sequence[None], None]):
 
        for classification in cseq:
 
            parts = classification.split(':')
 
            tail = parts.pop()
 
            tabs = ' ' * 4 * len(parts)
 
            space = self.SPACE * len(parts)
 
            if parts != last_prefix:
 
                yield f'{tabs[4:]}{parts[-1]}', None
 
                yield f'{space[len(self.SPACE):]}{parts[-1]}', None
 
                last_prefix = parts
 
            yield f'{tabs}{tail}', classification
 
            yield f'{space}{tail}', classification
 

	
 
    def walk_classifications_by_account(
 
            self,
...
 
@@ -549,6 +552,7 @@ class Report(core.BaseODS[Sequence[None], None]):
 
        for text, classification in self.walk_classifications_by_account('Expenses'):
 
            text_cell = self.string_cell(text)
 
            if classification is None:
 
                self.add_row(text_cell)
 
                if not text[0].isspace():
 
                    self.add_row()
 
                self.add_row(text_cell)
...
 
@@ -576,6 +580,109 @@ class Report(core.BaseODS[Sequence[None], None]):
 
              for tot_bal in totals),
 
        )
 

	
 
    def write_cash_flows(self) -> None:
 
        self.use_sheet("Cash Flows")
 
        bal_kwargs: Sequence[Dict[str, Any]] = [
 
            {'period': Period.PERIOD},
 
            {'period': Period.PRIOR},
 
        ]
 
        col_count = len(bal_kwargs) + 1
 
        for index in range(col_count):
 
            col_style = self.column_style(1.5 if index else 3)
 
            self.sheet.addElement(odf.table.TableColumn(stylename=col_style))
 
        self.add_row(
 
            self.multiline_cell([
 
                "DRAFT Statement of Cash Flows",
 
                self.period_name,
 
            ], numbercolumnsspanned=col_count, stylename=self.style_header)
 
        )
 
        self.add_row()
 
        self.add_row(
 
            odf.table.TableCell(),
 
            self.string_cell(self.period_name, stylename=self.style_huline),
 
            self.string_cell(self.opening_name, stylename=self.style_huline),
 
        )
 
        self.add_row()
 
        self.add_row(self.string_cell(
 
            "Cash Flows from Operating Activities",
 
            stylename=self.style_bold,
 
        ))
 
        self.add_row()
 

	
 
        totals = [
 
            -sum((self.balances.total(account=account, **kwargs)
 
                  for account in self.EQUITY_ACCOUNTS), core.MutableBalance())
 
            for kwargs in bal_kwargs
 
        ]
 
        self.add_row(
 
            self.string_cell("Change in Net Assets"),
 
            *(self.balance_cell(bal) for bal in totals),
 
        )
 
        self.add_row(self.string_cell(
 
            "(Increase) decrease in operating assets:",
 
        ))
 
        for text, classification in self.walk_classifications_by_account('Assets'):
 
            text_cell = self.string_cell(self.SPACE + text)
 
            if classification is None:
 
                self.add_row(text_cell)
 
            elif classification == self.C_CASH:
 
                continue
 
            else:
 
                balances = [
 
                    -self.balances.total(classification=classification, **kwargs)
 
                    for kwargs in bal_kwargs
 
                ]
 
                self.add_row(
 
                    text_cell,
 
                    *(self.balance_cell(bal) for bal in balances),
 
                )
 
                for total, bal in zip(totals, balances):
 
                    total += bal
 
        self.add_row(self.string_cell(
 
            "Increase (decrease) in operating liabilities:",
 
        ))
 
        for text, classification in self.walk_classifications_by_account('Liabilities'):
 
            text_cell = self.string_cell(self.SPACE + text)
 
            if classification is None:
 
                self.add_row(text_cell)
 
            else:
 
                balances = [
 
                    -self.balances.total(classification=classification, **kwargs)
 
                    for kwargs in bal_kwargs
 
                ]
 
                self.add_row(
 
                    text_cell,
 
                    *(self.balance_cell(bal) for bal in balances),
 
                )
 
                for total, bal in zip(totals, balances):
 
                    total += bal
 
        self.add_row(
 
            self.string_cell("Net cash provided by operating activites"),
 
            *(self.balance_cell(tot_bal, stylename=self.style_totline)
 
              for tot_bal in totals),
 
        )
 
        self.add_row()
 

	
 
        self.add_row(
 
            self.string_cell("Net Increase in Cash"),
 
            *(self.balance_cell(tot_bal) for tot_bal in totals),
 
        )
 
        self.add_row()
 
        balances = [
 
            self.balances.total(classification=self.C_CASH, period=period)
 
            for period in [Period.BEFORE_PERIOD, Period.OPENING]
 
        ]
 
        self.add_row(
 
            self.string_cell("Beginning Cash"),
 
            *(self.balance_cell(bal) for bal in balances),
 
        )
 
        self.add_row()
 
        self.add_row(
 
            self.string_cell("Ending Cash"),
 
            *(self.balance_cell(tot + bal, stylename=self.style_bottomline)
 
              for tot, bal in zip(totals, balances)),
 
        )
 

	
 

	
 
def parse_arguments(arglist: Optional[Sequence[str]]=None) -> argparse.Namespace:
 
    parser = argparse.ArgumentParser(prog=PROGNAME)
setup.py
Show inline comments
...
 
@@ -5,7 +5,7 @@ from setuptools import setup
 
setup(
 
    name='conservancy_beancount',
 
    description="Plugin, library, and reports for reading Conservancy's books",
 
    version='1.7.4',
 
    version='1.8.0',
 
    author='Software Freedom Conservancy',
 
    author_email='info@sfconservancy.org',
 
    license='GNU AGPLv3+',
0 comments (0 inline, 0 general)