feat: Kontostand von der Bank – die eigene Rechnung wird geprueft
Certain rechnet den Saldo bisher ausschliesslich selbst aus: Anfangsbestand plus alle Buchungen. Stimmt eine Buchung nicht, faellt das erst auf, wenn man von Hand mit dem Auszug vergleicht. Der von der Bank gemeldete Saldo wird jetzt mitgefuehrt und danebengestellt. Weicht er ab, fehlt oder doppelt eine Buchung – und man sieht es auf der Kontenseite und in den Einstellungen sofort, statt es zu suchen. Banken melden mehrere Saldi nebeneinander; ausgewaehlt wird der gebuchte, denn nur der ist mit Certains Rechnung vergleichbar. Ein verfuegbarer Saldo enthaelt Vorgemerktes oder einen Ueberziehungsrahmen. Die Saldi kommen auch fuer noch nicht zugeordnete Konten: Bei mehreren Revolut-Pockets ist der Betrag oft das Einzige, woran man sie unterscheidet. Ein Fehler bei einem Konto beendet den Durchlauf nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,15 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from ..database import get_db
|
||||
from ..deps import get_current_user, get_owned
|
||||
from ..models import Account, AccountIdentifier, IdentifierKind, Transaction, TxnType, User
|
||||
from ..models import (
|
||||
Account,
|
||||
AccountIdentifier,
|
||||
BankAccountLink,
|
||||
IdentifierKind,
|
||||
Transaction,
|
||||
TxnType,
|
||||
User,
|
||||
)
|
||||
from ..schemas import AccountCreate, AccountIdentifierOut, AccountOrder, AccountOut, AccountUpdate
|
||||
from ..services import balances, currency
|
||||
from ..services.csv_import import normalize_text
|
||||
@@ -29,7 +37,25 @@ def base_currency(db: Session, user: User) -> str:
|
||||
return get_user_setting(db, user, BASE_CURRENCY_KEY) or "EUR"
|
||||
|
||||
|
||||
def to_out(db: Session, acc: Account, base: str, on: date) -> AccountOut:
|
||||
def _bank_saldi(db: Session, user: User) -> dict:
|
||||
"""Bank-Saldo je Konto, einmal nachgeschlagen.
|
||||
|
||||
Als Sammelabfrage und nicht je Konto: Die Kontenliste wird auf jeder Seite
|
||||
geladen, eine Abfrage pro Zeile summierte sich schnell.
|
||||
"""
|
||||
return {
|
||||
v.account_id: v
|
||||
for v in db.query(BankAccountLink).filter(
|
||||
BankAccountLink.owner_id == user.id,
|
||||
BankAccountLink.account_id.isnot(None),
|
||||
BankAccountLink.balance_cents.isnot(None),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
def to_out(db: Session, acc: Account, base: str, on: date,
|
||||
bank_saldi: dict | None = None) -> AccountOut:
|
||||
bank = (bank_saldi or {}).get(acc.id)
|
||||
return AccountOut(
|
||||
id=acc.id,
|
||||
name=acc.name,
|
||||
@@ -46,6 +72,8 @@ def to_out(db: Session, acc: Account, base: str, on: date) -> AccountOut:
|
||||
],
|
||||
balance_cents=balances.account_balance_cents(db, acc),
|
||||
balance_base_cents=balances.account_balance_base_cents(db, acc, base, on),
|
||||
bank_balance_cents=bank.balance_cents if bank else None,
|
||||
bank_balance_at=bank.balance_at if bank else None,
|
||||
)
|
||||
|
||||
|
||||
@@ -87,7 +115,8 @@ def list_accounts(db: Session = Depends(get_db), user: User = Depends(get_curren
|
||||
.order_by(Account.position, Account.name)
|
||||
.all()
|
||||
)
|
||||
return [to_out(db, a, base, today) for a in accounts]
|
||||
saldi = _bank_saldi(db, user)
|
||||
return [to_out(db, a, base, today, saldi) for a in accounts]
|
||||
|
||||
|
||||
@router.post("", response_model=AccountOut, status_code=status.HTTP_201_CREATED)
|
||||
@@ -115,7 +144,8 @@ def create_account(
|
||||
db.add(acc)
|
||||
db.commit()
|
||||
db.refresh(acc)
|
||||
return to_out(db, acc, base_currency(db, user), date.today())
|
||||
return to_out(db, acc, base_currency(db, user), date.today(),
|
||||
_bank_saldi(db, user))
|
||||
|
||||
|
||||
@router.get("/{account_id}", response_model=AccountOut)
|
||||
@@ -123,7 +153,8 @@ def get_account(
|
||||
account_id: int, db: Session = Depends(get_db), user: User = Depends(get_current_user)
|
||||
):
|
||||
acc = get_owned(db, Account, account_id, user)
|
||||
return to_out(db, acc, base_currency(db, user), date.today())
|
||||
return to_out(db, acc, base_currency(db, user), date.today(),
|
||||
_bank_saldi(db, user))
|
||||
|
||||
|
||||
@router.patch("/{account_id}", response_model=AccountOut)
|
||||
@@ -143,7 +174,8 @@ def update_account(
|
||||
_set_identifiers(acc, payload.identifiers)
|
||||
db.commit()
|
||||
db.refresh(acc)
|
||||
return to_out(db, acc, base_currency(db, user), date.today())
|
||||
return to_out(db, acc, base_currency(db, user), date.today(),
|
||||
_bank_saldi(db, user))
|
||||
|
||||
|
||||
@router.put("/order", status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
Reference in New Issue
Block a user