"""Kontostände (in Kontowährung) und Umrechnung in die Hauptwährung. Saldo = Anfangssaldo + Einnahmen - Ausgaben - Transfers-raus + Transfers-rein. Transfers werden in der jeweiligen Kontowährung verrechnet (bei währungsüber- greifenden Transfers am Zielkonto der gutgeschriebene Betrag ``to_amount_cents``). """ from datetime import date from sqlalchemy import func from sqlalchemy.orm import Session from ..models import Account, Transaction, TxnType from . import currency def _sum(query) -> int: return int(query.scalar() or 0) def account_balance_cents(db: Session, account: Account) -> int: income = _sum( db.query(func.sum(Transaction.amount_cents)).filter( Transaction.account_id == account.id, Transaction.type == TxnType.income ) ) expense = _sum( db.query(func.sum(Transaction.amount_cents)).filter( Transaction.account_id == account.id, Transaction.type == TxnType.expense ) ) transfer_out = _sum( db.query(func.sum(Transaction.amount_cents)).filter( Transaction.account_id == account.id, Transaction.type == TxnType.transfer ) ) transfer_in = _sum( db.query( func.sum(func.coalesce(Transaction.to_amount_cents, Transaction.amount_cents)) ).filter( Transaction.to_account_id == account.id, Transaction.type == TxnType.transfer ) ) return account.opening_balance_cents + income - expense - transfer_out + transfer_in def account_balance_base_cents( db: Session, account: Account, base_currency: str, on: date ) -> int: """Saldo in die Hauptwährung umgerechnet (aktueller Kurs). Fällt auf den nativen Wert zurück, wenn kein Kurs verfügbar ist.""" native = account_balance_cents(db, account) if account.currency == base_currency: return native conv = currency.convert(db, native, account.currency, base_currency, on) return conv if conv is not None else native def net_worth_cents(db: Session, accounts: list[Account], base_currency: str, on: date) -> int: return sum( account_balance_base_cents(db, a, base_currency, on) for a in accounts if not a.is_archived )