from decimal import Decimal from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel, ConfigDict, field_validator from sqlalchemy import select from sqlalchemy.orm import Session from app.auth import require_auth from app.db import get_session from app.models.tables import Account from app.services.balances import account_balance router = APIRouter(prefix="/api/accounts", tags=["accounts"], dependencies=[Depends(require_auth)]) class AccountIn(BaseModel): bank: str iban: str name: str type: str = "giro" class AccountOut(AccountIn): model_config = ConfigDict(from_attributes=True) id: int balance: Decimal = Decimal("0") class AccountPatch(BaseModel): name: str @field_validator("name") @classmethod def name_not_blank(cls, v: str) -> str: v = v.strip() if not v or len(v) > 100: raise ValueError("Name muss 1–100 Zeichen lang sein") return v @router.get("", response_model=list[AccountOut]) def list_accounts(session: Session = Depends(get_session)): out = [] for acc in session.execute(select(Account)).scalars(): item = AccountOut.model_validate(acc) item.balance = account_balance(session, acc) out.append(item) return out @router.get("/{account_id}", response_model=AccountOut) def get_account(account_id: int, session: Session = Depends(get_session)): acc = session.get(Account, account_id) if acc is None: raise HTTPException(404, "Konto nicht gefunden") item = AccountOut.model_validate(acc) item.balance = account_balance(session, acc) return item @router.post("", response_model=AccountOut, status_code=201) def create_account(data: AccountIn, session: Session = Depends(get_session)): if session.execute(select(Account).where(Account.iban == data.iban)).scalar(): raise HTTPException(409, "IBAN existiert bereits") acc = Account(**data.model_dump()) session.add(acc) session.commit() session.refresh(acc) return AccountOut.model_validate(acc) @router.patch("/{account_id}", response_model=AccountOut) def patch_account(account_id: int, data: AccountPatch, session: Session = Depends(get_session)): acc = session.get(Account, account_id) if acc is None: raise HTTPException(404, "Konto nicht gefunden") acc.name = data.name session.commit() session.refresh(acc) item = AccountOut.model_validate(acc) item.balance = account_balance(session, acc) return item