Spaces:
Running
Running
| """ | |
| Transactions router — paginated transaction history with filtering. | |
| """ | |
| from typing import Optional | |
| from fastapi import APIRouter, Depends, Query | |
| from sqlalchemy.orm import Session | |
| from sqlalchemy import desc | |
| from app.database.database import get_db | |
| from app.database.models import User, Account, Transaction | |
| router = APIRouter(prefix="/api/transactions", tags=["Transactions"]) | |
| def _resolve_user(db: Session, user_id: Optional[str]) -> str: | |
| if user_id: | |
| return user_id | |
| user = db.query(User).first() | |
| if not user: | |
| from fastapi import HTTPException | |
| raise HTTPException(status_code=404, detail="No users found.") | |
| return user.id | |
| def get_transactions( | |
| user_id: Optional[str] = None, | |
| page: int = Query(default=1, ge=1), | |
| limit: int = Query(default=20, ge=1, le=100), | |
| category: Optional[str] = None, | |
| type: Optional[str] = None, | |
| db: Session = Depends(get_db), | |
| ): | |
| uid = _resolve_user(db, user_id) | |
| account_ids = [a.id for a in db.query(Account).filter(Account.user_id == uid).all()] | |
| query = db.query(Transaction).filter(Transaction.account_id.in_(account_ids)) | |
| if category: | |
| query = query.filter(Transaction.category == category) | |
| if type: | |
| query = query.filter(Transaction.type == type) | |
| total = query.count() | |
| transactions = query.order_by(desc(Transaction.timestamp)).offset((page - 1) * limit).limit(limit).all() | |
| return { | |
| "transactions": [ | |
| { | |
| "id": t.id, | |
| "merchant": t.merchant or "Unknown", | |
| "category": t.category or "Other", | |
| "amount": t.amount if t.type == "credit" else -abs(t.amount), | |
| "type": t.type, | |
| "timestamp": t.timestamp.isoformat() if t.timestamp else None, | |
| "tags": t.tags or [], | |
| } | |
| for t in transactions | |
| ], | |
| "total": total, | |
| "page": page, | |
| "pages": (total + limit - 1) // limit, | |
| } | |