Ejemplo n.º 1
0
    def net_worth(self, interval):
        """Compute net worth.

        Args:
            interval: A string for the interval.

        Returns:
            A list of dicts for all ends of the given interval containing the
            net worth (Assets + Liabilities) separately converted to all
            operating currencies.
        """
        transactions = (entry for entry in self.ledger.entries
                        if (isinstance(entry, Transaction)
                            and entry.flag != flags.FLAG_UNREALIZED))

        types = (
            self.ledger.options["name_assets"],
            self.ledger.options["name_liabilities"],
        )

        txn = next(transactions, None)
        inventory = CounterInventory()

        for end_date_exclusive in self.ledger.interval_ends(interval):
            end_date_inclusive = end_date_exclusive - datetime.timedelta(
                days=1)
            while txn and txn.date < end_date_exclusive:
                for posting in filter(lambda p: p.account.startswith(types),
                                      txn.postings):
                    inventory.add_position(posting)
                txn = next(transactions, None)
            yield {
                "date": end_date_exclusive,
                "balance": cost_or_value(inventory, end_date_inclusive),
            }
Ejemplo n.º 2
0
 def __init__(self, name):
     #: str: Account name.
     self.name = name
     #: A list of :class:`.TreeNode`, its children.
     self.children = []
     #: :class:`.CounterInventory`: The cumulative account balance.
     self.balance_children = CounterInventory()
     #: :class:`.CounterInventory`: The account balance.
     self.balance = CounterInventory()
     #: bool: True if the account has any transactions.
     self.has_txns = False
Ejemplo n.º 3
0
 def __init__(self, name: str) -> None:
     #: Account name.
     self.name: str = name
     #: A list of :class:`.TreeNode`, its children.
     self.children: List["TreeNode"] = []
     #: The cumulative account balance.
     self.balance_children = CounterInventory()
     #: The account balance.
     self.balance = CounterInventory()
     #: Whether the account has any transactions.
     self.has_txns = False
Ejemplo n.º 4
0
def test_render_diff_and_number(app, snapshot) -> None:
    with app.test_request_context("/long-example/"):
        app.preprocess_request()
        macro = get_template_attribute(TREE_TABLE_PATH,
                                       "render_diff_and_number")

        for invert in [False, True]:
            balance = CounterInventory({"EUR": Decimal(12)})
            cost = CounterInventory({"EUR": Decimal(10)})
            snapshot(macro(balance, cost, "EUR", invert))
        for invert in [False, True]:
            balance = CounterInventory({"EUR": Decimal(10)})
            cost = CounterInventory({"EUR": Decimal(12)})
            snapshot(macro(balance, cost, "EUR", invert))
Ejemplo n.º 5
0
    def net_worth(self, interval):
        """Compute net worth.

        Args:
            interval: A string for the interval.

        Returns:
            A list of dicts for all ends of the given interval containing the
            net worth (Assets + Liabilities) separately converted to all
            operating currencies.
        """
        transactions = (entry for entry in self.ledger.entries
                        if (isinstance(entry, Transaction)
                            and entry.flag != flags.FLAG_UNREALIZED))

        types = (
            self.ledger.options['name_assets'],
            self.ledger.options['name_liabilities'],
        )

        txn = next(transactions, None)
        inventory = CounterInventory()

        for date in self.ledger.interval_ends(interval):
            while txn and txn.date < date:
                for posting in filter(lambda p: p.account.startswith(types),
                                      txn.postings):
                    # Since we will be reducing the inventory to the operating
                    # currencies, pre-aggregate the positions to reduce the
                    # number of elements in the inventory.
                    inventory.add_amount(
                        posting.units,
                        Cost(ZERO, posting.cost.currency, None, None)
                        if posting.cost else None,
                    )
                txn = next(transactions, None)
            yield {
                'date': date,
                'balance': {
                    currency: inventory.reduce(
                        convert.convert_position,
                        currency,
                        self.ledger.price_map,
                        date,
                    ).get(currency)
                    for currency in self.ledger.options['operating_currency']
                },
            }
Ejemplo n.º 6
0
    def cap(self, options, unrealized_account):
        """Transfer Income and Expenses, add conversions and unrealized gains.

        Args:
            options: The Beancount options.
            unrealized_account: The name of the account to post unrealized
                gains to (as a subaccount of Equity).
        """
        equity = options['name_equity']
        conversions = CounterInventory({
            (currency, None): -number
            for currency, number in self.get('').balance_children.reduce(
                convert.get_cost).items()
        })

        # Add conversions
        self.insert(equity + ':' + options['account_current_conversions'],
                    conversions)

        # Insert unrealized gains.
        self.insert(equity + ':' + unrealized_account,
                    -self.get('').balance_children)

        # Transfer Income and Expenses
        self.insert(equity + ':' + options['account_current_earnings'],
                    self.get(options['name_income']).balance_children)
        self.insert(equity + ':' + options['account_current_earnings'],
                    self.get(options['name_expenses']).balance_children)
Ejemplo n.º 7
0
def test_add() -> None:
    inv = CounterInventory()
    key = ("KEY", None)
    inv.add(key, D(10))
    assert len(inv) == 1
    inv.add(key, D(-10))
    assert inv.is_empty()
Ejemplo n.º 8
0
def test_add():
    inv = CounterInventory()
    key = "KEY"
    inv.add(key, 10)
    assert len(inv) == 1
    inv.add(key, -10)
    assert inv.is_empty()
Ejemplo n.º 9
0
    def net_worth(self, interval):
        """Compute net worth.

        Args:
            interval: A string for the interval.

        Returns:
            A list of dicts for all ends of the given interval containing the
            net worth (Assets + Liabilities) separately converted to all
            operating currencies.
        """
        transactions = (entry for entry in self.ledger.entries
                        if (isinstance(entry, Transaction) and entry.flag !=
                            flags.FLAG_UNREALIZED))

        types = (self.ledger.options['name_assets'],
                 self.ledger.options['name_liabilities'])

        txn = next(transactions, None)
        inventory = CounterInventory()

        for date in self.ledger.interval_ends(interval):
            while txn and txn.date < date:
                for posting in filter(lambda p: p.account.startswith(types),
                                      txn.postings):
                    # Since we will be reducing the inventory to the operating
                    # currencies, pre-aggregate the positions to reduce the
                    # number of elements in the inventory.
                    inventory.add_amount(
                        posting.units,
                        Cost(ZERO, posting.cost.currency, None, None)
                        if posting.cost else None)
                txn = next(transactions, None)
            yield {
                'date': date,
                'balance': {
                    currency:
                    inventory.reduce(convert.convert_position, currency,
                                     self.ledger.price_map,
                                     date).get(currency)
                    for currency in self.ledger.options['operating_currency']
                }
            }
Ejemplo n.º 10
0
    def interval_totals(self, interval, accounts):
        """Renders totals for account (or accounts) in the intervals.

        Args:
            interval: An interval.
            accounts: A single account (str) or a tuple of accounts.
        """
        for begin, end in pairwise(self.ledger.interval_ends(interval)):
            inventory = CounterInventory()
            entries = iter_entry_dates(self.ledger.entries, begin, end)
            for entry in filter_type(entries, Transaction):
                for posting in entry.postings:
                    if posting.account.startswith(accounts):
                        inventory.add_position(posting)

            yield {
                'date': begin,
                'balance': cost_or_value(inventory, end),
                'budgets':
                self.ledger.budgets.calculate_children(accounts, begin, end),
            }
Ejemplo n.º 11
0
def test_add():
    inv = CounterInventory()
    key = 'KEY'
    inv.add(key, 10)
    assert len(inv) == 1
    inv.add(key, -10)
    assert inv.is_empty()
Ejemplo n.º 12
0
    def interval_totals(self, interval, accounts):
        """Renders totals for account (or accounts) in the intervals.

        Args:
            interval: An interval.
            accounts: A single account (str) or a tuple of accounts.
        """
        for begin, end in pairwise(self.ledger.interval_ends(interval)):
            inventory = CounterInventory()
            entries = iter_entry_dates(self.ledger.entries, begin, end)
            for entry in filter_type(entries, Transaction):
                for posting in entry.postings:
                    if posting.account.startswith(accounts):
                        inventory.add_position(posting)

            yield {
                "date": begin,
                "balance": cost_or_value(inventory, end),
                "budgets": self.ledger.budgets.calculate_children(
                    accounts, begin, end
                ),
            }
Ejemplo n.º 13
0
def test_should_show(app: Flask) -> None:
    with app.test_request_context("/long-example/"):
        app.preprocess_request()
        assert should_show(g.filtered.root_tree.get("")) is True
        assert should_show(g.filtered.root_tree.get("Expenses")) is True

        account = TreeNode("name")
        assert should_show(account) is False
        account.balance_children = CounterInventory({("USD", None): D("9")})
        assert should_show(account) is True
    with app.test_request_context("/long-example/income_statement/?time=2100"):
        app.preprocess_request()
        assert not g.ledger.fava_options.show_accounts_with_zero_balance
        assert should_show(g.filtered.root_tree.get("")) is True
        assert should_show(g.filtered.root_tree.get("Expenses")) is False
Ejemplo n.º 14
0
def test_should_show(app):
    with app.test_request_context("/long-example/"):
        app.preprocess_request()
        assert should_show(g.ledger.root_tree.get("")) is True
        assert should_show(g.ledger.root_tree.get("Expenses")) is True

        account = TreeNode("name")
        assert should_show(account) is False
        account.balance_children = CounterInventory({("USD", None): 9})
        assert should_show(account) is True
    with app.test_request_context("/long-example/income_statement/?time=2100"):
        app.preprocess_request()
        assert not g.ledger.fava_options["show-accounts-with-zero-balance"]
        assert should_show(g.ledger.root_tree.get("")) is True
        assert should_show(g.ledger.root_tree.get("Expenses")) is False
Ejemplo n.º 15
0
def test_should_show(app):
    with app.test_request_context('/'):
        app.preprocess_request()
        assert should_show(g.ledger.root_tree.get('')) is True
        assert should_show(g.ledger.root_tree.get('Expenses')) is True

        account = TreeNode('name')
        assert should_show(account) is False
        account.balance_children = CounterInventory({('USD', None): 9})
        assert should_show(account) is True
    with app.test_request_context('/?time=2100'):
        app.preprocess_request()
        assert not g.ledger.fava_options['show-accounts-with-zero-balance']
        assert should_show(g.ledger.root_tree.get('')) is True
        assert should_show(g.ledger.root_tree.get('Expenses')) is False
Ejemplo n.º 16
0
def test_CounterInventory_add_inventory():
    inv = CounterInventory()
    inv2 = CounterInventory()
    inv3 = CounterInventory()
    inv.add_amount(A('10 USD'))
    inv2.add_amount(A('30 USD'))
    inv3.add_amount(A('-40 USD'))
    inv.add_inventory(inv2)
    assert len(inv) == 1
    inv.add_inventory(inv3)
    assert inv.is_empty()
    inv = CounterInventory()
    inv.add_inventory(inv2)
    assert len(inv) == 1
Ejemplo n.º 17
0
def test_add_inventory():
    inv = CounterInventory()
    inv2 = CounterInventory()
    inv3 = CounterInventory()
    inv.add_amount(A("10 USD"))
    inv2.add_amount(A("30 USD"))
    inv3.add_amount(A("-40 USD"))
    inv.add_inventory(inv2)
    assert len(inv) == 1
    inv.add_inventory(inv3)
    assert inv.is_empty()
    inv = CounterInventory()
    inv.add_inventory(inv2)
    assert len(inv) == 1
Ejemplo n.º 18
0
def test_add_amount():
    inv = CounterInventory()
    inv.add_amount(A("10 USD"))
    inv.add_amount(A("30 USD"))
    assert len(inv) == 1
    inv.add_amount(A("-40 USD"))
    assert inv.is_empty()

    inv.add_amount(A("10 USD"))
    inv.add_amount(A("20 CAD"))
    inv.add_amount(A("10 USD"))
    assert len(inv) == 2
    inv.add_amount(A("-20 CAD"))
    assert len(inv) == 1
Ejemplo n.º 19
0
def test_add_amount():
    inv = CounterInventory()
    inv.add_amount(A('10 USD'))
    inv.add_amount(A('30 USD'))
    assert len(inv) == 1
    inv.add_amount(A('-40 USD'))
    assert inv.is_empty()

    inv.add_amount(A('10 USD'))
    inv.add_amount(A('20 CAD'))
    inv.add_amount(A('10 USD'))
    assert len(inv) == 2
    inv.add_amount(A('-20 CAD'))
    assert len(inv) == 1
Ejemplo n.º 20
0
def test_add_inventory():
    inv = CounterInventory()
    inv2 = CounterInventory()
    inv3 = CounterInventory()
    inv.add_amount(A('10 USD'))
    inv2.add_amount(A('30 USD'))
    inv3.add_amount(A('-40 USD'))
    inv.add_inventory(inv2)
    assert len(inv) == 1
    inv.add_inventory(inv3)
    assert inv.is_empty()
    inv = CounterInventory()
    inv.add_inventory(inv2)
    assert len(inv) == 1