Exemplo n.º 1
0
    def serialise(
        self,
        conversion: str,
        ledger: "FavaLedger",
        end: Optional[datetime.date],
    ) -> SerialisedTreeNode:
        """Serialise the account.

        Args:
            end: A date to use for cost conversions.
        """
        price_map = ledger.price_map
        children = [
            child.serialise(conversion, ledger, end)
            for child in self.children
        ]
        return {
            "account": self.name,
            "label": self.label_or_name(ledger),
            "balance_children": cost_or_value(
                self.balance_children, conversion, price_map, end
            ),
            "balance": cost_or_value(self.balance, conversion, price_map, end),
            "children": children,
        }
Exemplo n.º 2
0
    def serialise(
        self,
        conversion: str,
        price_map: PriceMap,
        end: Optional[datetime.date],
    ) -> SerialisedTreeNode:
        """Serialise the account.

        Args:
            end: A date to use for cost conversions.
        """
        children = [
            child.serialise(conversion, price_map, end)
            for child in self.children
        ]
        return {
            "account":
            self.name,
            "balance_children":
            cost_or_value(self.balance_children, conversion, price_map, end),
            "balance":
            cost_or_value(self.balance, conversion, price_map, end),
            "children":
            children,
        }
Exemplo n.º 3
0
    def interval_totals(
        self,
        filtered: FilteredLedger,
        interval: Interval,
        accounts: str | tuple[str],
        conversion: str,
        invert: bool = False,
    ) -> Generator[DateAndBalanceWithBudget, None, None]:
        """Renders totals for account (or accounts) in the intervals.

        Args:
            interval: An interval.
            accounts: A single account (str) or a tuple of accounts.
            conversion: The conversion to use.
            invert: invert all numbers.
        """
        # pylint: disable=too-many-locals
        price_map = self.ledger.price_map
        for begin, end in pairwise(filtered.interval_ends(interval)):
            inventory = Inventory()
            entries = iter_entry_dates(filtered.entries, begin, end)
            account_inventories = {}
            for entry in (e for e in entries if isinstance(e, Transaction)):
                for posting in entry.postings:
                    if posting.account.startswith(accounts):
                        if posting.account not in account_inventories:
                            account_inventories[posting.account] = Inventory()
                        account_inventories[posting.account].add_position(
                            posting)
                        inventory.add_position(posting)
            balance = cost_or_value(inventory, conversion, price_map,
                                    end - ONE_DAY)
            account_balances = {}
            for account, acct_value in account_inventories.items():
                account_balances[account] = cost_or_value(
                    acct_value,
                    conversion,
                    price_map,
                    end - ONE_DAY,
                )
            budgets = {}
            if isinstance(accounts, str):
                budgets = self.ledger.budgets.calculate_children(
                    accounts, begin, end)

            if invert:
                # pylint: disable=invalid-unary-operand-type
                balance = -balance
                budgets = {k: -v for k, v in budgets.items()}
                account_balances = {k: -v for k, v in account_balances.items()}

            yield DateAndBalanceWithBudget(
                begin,
                balance,
                account_balances,
                budgets,
            )
Exemplo n.º 4
0
    def interval_totals(
        self,
        interval: Interval,
        accounts: Union[str, Tuple[str]],
        conversion: str,
    ):
        """Renders totals for account (or accounts) in the intervals.

        Args:
            interval: An interval.
            accounts: A single account (str) or a tuple of accounts.
            conversion: The conversion to use.
        """
        price_map = self.ledger.price_map
        for begin, end in pairwise(self.ledger.interval_ends(interval)):
            inventory = Inventory()
            entries = iter_entry_dates(self.ledger.entries, begin, end)
            for entry in (e for e in entries if isinstance(e, Transaction)):
                for posting in entry.postings:
                    if posting.account.startswith(accounts):
                        inventory.add_position(posting)

            yield {
                "date":
                begin,
                "balance":
                cost_or_value(inventory, conversion, price_map, end - ONE_DAY),
                "budgets":
                self.ledger.budgets.calculate_children(accounts, begin, end),
            }
Exemplo n.º 5
0
    def serialise(self, conversion, price_map, end: datetime.date):
        """Serialise the account.

        Args:
            end: A date to use for cost conversions.
        """
        children = [
            child.serialise(conversion, price_map, end)
            for child in self.children
        ]
        return {
            "account":
            self.name,
            "balance_children":
            cost_or_value(self.balance_children, conversion, price_map, end),
            "balance":
            cost_or_value(self.balance, conversion, price_map, end),
            "children":
            children,
        }
Exemplo n.º 6
0
Arquivo: tree.py Projeto: yegle/fava
    def serialise(
        self,
        conversion: str,
        price_map: PriceMap,
        end: datetime.date | None,
    ) -> SerialisedTreeNode:
        """Serialise the account.

        Args:
            end: A date to use for cost conversions.
        """
        children = [
            child.serialise(conversion, price_map, end)
            for child in self.children
        ]
        return SerialisedTreeNode(
            self.name,
            cost_or_value(self.balance, conversion, price_map, end),
            cost_or_value(self.balance_children, conversion, price_map, end),
            children,
        )
Exemplo n.º 7
0
    def net_worth(
        self, interval: Interval, conversion: str
    ) -> Generator[DateAndBalance, None, None]:
        """Compute net worth.

        Args:
            interval: A string for the interval.
            conversion: The conversion to use.

        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 != FLAG_UNREALIZED
            )
        )

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

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

        price_map = self.ledger.price_map
        for end_date in self.ledger.interval_ends(interval):
            while txn and txn.date < end_date:
                for posting in txn.postings:
                    if posting.account.startswith(types):
                        inventory.add_position(posting)
                txn = next(transactions, None)
            yield {
                "date": end_date,
                "balance": cost_or_value(
                    inventory, conversion, price_map, end_date - ONE_DAY
                ),
            }
Exemplo n.º 8
0
    def linechart(
        self, account_name: str, conversion: str
    ) -> Generator[DateAndBalance, None, None]:
        """The balance of an account.

        Args:
            account_name: A string.
            conversion: The conversion to use.

        Returns:
            A list of dicts for all dates on which the balance of the given
            account has changed containing the balance (in units) of the
            account at that date.
        """
        real_account = realization.get_or_create(
            self.ledger.root_account, account_name
        )
        postings = realization.get_postings(real_account)
        journal = realization.iterate_with_balance(postings)

        # When the balance for a commodity just went to zero, it will be
        # missing from the 'balance' so keep track of currencies that last had
        # a balance.
        last_currencies = None

        price_map = self.ledger.price_map
        for entry, _, change, balance_inventory in journal:
            if change.is_empty():
                continue

            balance = inv_to_dict(
                cost_or_value(
                    balance_inventory, conversion, price_map, entry.date
                )
            )

            currencies = set(balance.keys())
            if last_currencies:
                for currency in last_currencies - currencies:
                    balance[currency] = 0
            last_currencies = currencies

            yield {"date": entry.date, "balance": balance}
Exemplo n.º 9
0
    def interval_totals(
        self,
        interval: Interval,
        accounts: Union[str, Tuple[str]],
        conversion: str,
        invert: bool = False,
    ) -> Generator[DateAndBalanceWithBudget, None, None]:
        """Renders totals for account (or accounts) in the intervals.

        Args:
            interval: An interval.
            accounts: A single account (str) or a tuple of accounts.
            conversion: The conversion to use.
        """
        price_map = self.ledger.price_map
        for begin, end in pairwise(self.ledger.interval_ends(interval)):
            inventory = Inventory()
            entries = iter_entry_dates(self.ledger.entries, begin, end)
            for entry in (e for e in entries if isinstance(e, Transaction)):
                for posting in entry.postings:
                    if posting.account.startswith(accounts):
                        inventory.add_position(posting)

            balance = cost_or_value(
                inventory, conversion, price_map, end - ONE_DAY
            )
            budgets = {}
            if isinstance(accounts, str):
                budgets = self.ledger.budgets.calculate_children(
                    accounts, begin, end
                )

            if invert:
                # pylint: disable=invalid-unary-operand-type
                balance = -balance
                budgets = {k: -v for k, v in budgets.items()}

            yield {
                "date": begin,
                "balance": balance,
                "budgets": budgets,
            }