from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from typing import List, Literal, TypedDict from app.core.database import get_db from app.core.auth import get_current_user, requires_role from app.models.user import User from app.models.topup import Topup from app.models.booking import Booking router = APIRouter(prefix="/transactions", tags=["transactions"]) class TransactionOut(TypedDict): id: str type: Literal["topup", "booking"] amount_cents: int created_at: str # ISO @router.get("/me") def list_my_transactions( limit: int = Query(100, ge=1, le=1000), offset: int = Query(0, ge=0), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """ Kombiniert Topups (+) und Buchungen (−) des aktuellen Users. """ topups = ( db.query(Topup) .filter(Topup.user_id == current_user.id) .order_by(Topup.id.desc()) .limit(limit) .offset(offset) .all() ) bookings = ( db.query(Booking) .filter(Booking.user_id == current_user.id) .order_by(Booking.id.desc()) .limit(limit) .offset(offset) .all() ) tx: List[TransactionOut] = [] for t in topups: tx.append( { "id": f"topup-{t.id}", "type": "topup", "amount_cents": int(t.amount_cents or 0), "created_at": t.created_at.isoformat() if hasattr(t, "created_at") and t.created_at else "", } ) for b in bookings: # Wenn du Booking.total_cents hast, nutze das. Sonst product.price_cents * amount. total = getattr(b, "total_cents", None) if total is None: price = getattr(b, "price_cents", None) if price is None and hasattr(b, "product") and b.product: price = getattr(b.product, "price_cents", 0) total = (price or 0) * (getattr(b, "amount", 1) or 1) tx.append( { "id": f"booking-{b.id}", "type": "booking", "amount_cents": -int(total or 0), # Buchungen als negative Beträge "created_at": b.created_at.isoformat() if hasattr(b, "created_at") and b.created_at else "", } ) # Absteigend nach Datum tx.sort(key=lambda x: x["created_at"], reverse=True) # einfache Paginierung nach Sortierung (optional): tx = tx[offset:offset+limit] return tx @router.get("/", dependencies=[Depends(requires_role("manager", "admin"))]) def list_all_transactions_admin( limit: int = Query(200, ge=1, le=2000), offset: int = Query(0, ge=0), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """ Admin/Manager: kombinierte Übersicht (einfach, nicht performant für große Datenmengen). """ topups = ( db.query(Topup).order_by(Topup.id.desc()).limit(limit).offset(offset).all() ) bookings = ( db.query(Booking).order_by(Booking.id.desc()).limit(limit).offset(offset).all() ) tx: List[TransactionOut] = [] for t in topups: tx.append( { "id": f"topup-{t.id}", "type": "topup", "amount_cents": int(t.amount_cents or 0), "created_at": t.created_at.isoformat() if hasattr(t, "created_at") and t.created_at else "", } ) for b in bookings: total = getattr(b, "total_cents", None) if total is None: price = getattr(b, "price_cents", None) if price is None and hasattr(b, "product") and b.product: price = getattr(b.product, "price_cents", 0) total = (price or 0) * (getattr(b, "amount", 1) or 1) tx.append( { "id": f"booking-{b.id}", "type": "booking", "amount_cents": -int(total or 0), "created_at": b.created_at.isoformat() if hasattr(b, "created_at") and b.created_at else "", } ) tx.sort(key=lambda x: x["created_at"], reverse=True) return tx