feat: Buchungen serverseitig nach Spalte sortierbar (A11-T5)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -75,6 +75,38 @@ def _apply_transaction_filters(
|
||||
return stmt
|
||||
|
||||
|
||||
# Serverseitige Sortierung der Buchungsliste (Ausbaustufe 11): Whitelist
|
||||
# URL-Schlüssel -> Sortierausdruck. Textspalten über lower(), damit SQLite
|
||||
# (Tests) und Postgres gleich (case-insensitiv) sortieren.
|
||||
SORT_COLUMNS = {
|
||||
"datum": Transaction.booking_date,
|
||||
"konto": func.lower(Account.name),
|
||||
"zweck": func.lower(Transaction.purpose),
|
||||
"empfaenger": func.lower(Transaction.counterparty),
|
||||
"betrag": Transaction.amount,
|
||||
"kategorie": func.lower(Category.name),
|
||||
}
|
||||
|
||||
|
||||
def normalize_sort(sort: str | None, dir: str | None) -> tuple[str, str]:
|
||||
"""Unbekannte Werte fallen still auf den Standard (datum/asc) zurück -
|
||||
kein 422 für manipulierte oder veraltete Links."""
|
||||
return (sort if sort in SORT_COLUMNS else "datum",
|
||||
dir if dir in ("asc", "desc") else "asc")
|
||||
|
||||
|
||||
def _apply_sort(stmt, sort: str | None, dir: str | None):
|
||||
sort, dir = normalize_sort(sort, dir)
|
||||
if sort == "konto":
|
||||
stmt = stmt.outerjoin(Account, Account.id == Transaction.account_id)
|
||||
elif sort == "kategorie":
|
||||
stmt = stmt.outerjoin(Category, Category.id == Transaction.category_id)
|
||||
col = SORT_COLUMNS[sort]
|
||||
if dir == "desc":
|
||||
return stmt.order_by(col.desc().nulls_last(), Transaction.id.desc())
|
||||
return stmt.order_by(col.asc().nulls_last(), Transaction.id.asc())
|
||||
|
||||
|
||||
@router.get("", response_model=list[TransactionOut])
|
||||
def list_transactions(
|
||||
account_id: int | None = None,
|
||||
@@ -83,6 +115,8 @@ def list_transactions(
|
||||
category_id: int | None = None,
|
||||
q: str | None = None,
|
||||
status: str = "confirmed",
|
||||
sort: str = "datum",
|
||||
dir: str = "asc",
|
||||
limit: int = 200,
|
||||
offset: int = 0,
|
||||
session: Session = Depends(get_session),
|
||||
@@ -91,7 +125,7 @@ def list_transactions(
|
||||
select(Transaction), account_id=account_id, date_from=date_from,
|
||||
date_to=date_to, category_id=category_id, q=q, status=status,
|
||||
)
|
||||
stmt = stmt.order_by(Transaction.booking_date, Transaction.id).offset(offset).limit(limit)
|
||||
stmt = _apply_sort(stmt, sort, dir).offset(offset).limit(limit)
|
||||
return [TransactionOut.model_validate(t) for t in session.execute(stmt).scalars()]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user