UX: paginate booking operations

This commit is contained in:
NuklearRabbit
2026-08-10 01:47:35 +02:00
parent 2648cef8e3
commit 0ef4a6fa98
4 changed files with 98 additions and 68 deletions
+37 -5
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
from fastapi import APIRouter, Depends, Header, HTTPException, Query, Response
from sqlalchemy import select
from sqlalchemy import func, or_, select
from sqlalchemy.orm import Session
from app.api.deps import get_current_user, get_db
@@ -10,6 +10,7 @@ from app.models.customer import Customer
from app.models.vehicle import Vehicle
from app.schemas import (
BookingOut,
BookingPageOut,
CurrentUser,
NextBookingRisk,
RegisterReturnRequest,
@@ -35,13 +36,16 @@ def _to_out(booking: Booking, customer: Customer, vehicle: Vehicle) -> BookingOu
)
@router.get("", response_model=list[BookingOut])
@router.get("", response_model=list[BookingOut] | BookingPageOut)
def list_bookings(
status: str | None = Query(default=None),
vehicle_ref: str | None = Query(default=None),
query: str | None = Query(default=None, min_length=1, max_length=100),
page: int | None = Query(default=None, ge=1),
page_size: int = Query(default=25, ge=1, le=25),
db: Session = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
) -> list[BookingOut]:
) -> list[BookingOut] | BookingPageOut:
stmt = select(Booking).order_by(Booking.starts_at.desc())
if status:
stmt = stmt.where(Booking.status == status)
@@ -50,10 +54,38 @@ def list_bookings(
if vehicle is None:
return []
stmt = stmt.where(Booking.vehicle_id == vehicle.id)
bookings = db.scalars(stmt).all()
if query:
term = f"%{query.strip()}%"
stmt = (
stmt.join(Customer, Booking.customer_id == Customer.id)
.join(Vehicle, Booking.vehicle_id == Vehicle.id)
.where(
or_(
Booking.public_ref.ilike(term),
Customer.first_name.ilike(term),
Customer.last_name.ilike(term),
Vehicle.public_ref.ilike(term),
)
)
)
total = db.scalar(select(func.count()).select_from(stmt.subquery())) or 0
page_number = page or 1
bookings = db.scalars(
stmt if page is None else stmt.offset((page_number - 1) * page_size).limit(page_size)
).all()
customers = {c.id: c for c in db.scalars(select(Customer)).all()}
vehicles = {v.id: v for v in db.scalars(select(Vehicle)).all()}
return [_to_out(b, customers[b.customer_id], vehicles[b.vehicle_id]) for b in bookings]
items = [_to_out(b, customers[b.customer_id], vehicles[b.vehicle_id]) for b in bookings]
if page is None:
return items
total_pages = max(1, (total + page_size - 1) // page_size)
return BookingPageOut(
items=items,
page=min(page_number, total_pages),
page_size=page_size,
total=total,
total_pages=total_pages,
)
@router.get("/{public_ref}", response_model=BookingOut)