refactor(backend): extract pagination utilities

Issue #4: Pagination logic was repeated across multiple routes.

Changes:
- Add pagination.py with reusable utilities:
  - calculate_total_pages: computes page count from total/per_page
  - calculate_offset: computes offset for given page
  - create_paginated_response: builds PaginatedResponse with metadata
- Update routes/audit.py to use pagination utilities
- Update routes/booking.py to use pagination utilities
- Update routes/invites.py to use pagination utilities

The utilities handle the common pagination math while routes
still manage their own query logic (filters, joins, ordering).
This commit is contained in:
counterweight 2025-12-22 00:00:24 +01:00
parent 09560296aa
commit 0dd84e90a5
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
4 changed files with 63 additions and 37 deletions

View file

@ -12,6 +12,7 @@ from sqlalchemy.orm import joinedload
from auth import require_permission
from database import get_db
from models import Appointment, AppointmentStatus, Availability, Permission, User
from pagination import calculate_offset, create_paginated_response
from schemas import (
AppointmentResponse,
AvailableSlotsResponse,
@ -325,10 +326,9 @@ async def get_all_appointments(
# Get total count
count_result = await db.execute(select(func.count(Appointment.id)))
total = count_result.scalar() or 0
total_pages = (total + per_page - 1) // per_page if total > 0 else 1
# Get paginated appointments with explicit eager loading of user relationship
offset = (page - 1) * per_page
offset = calculate_offset(page, per_page)
result = await db.execute(
select(Appointment)
.options(joinedload(Appointment.user))
@ -344,13 +344,7 @@ async def get_all_appointments(
for apt in appointments
]
return PaginatedAppointments(
records=records,
total=total,
page=page,
per_page=per_page,
total_pages=total_pages,
)
return create_paginated_response(records, total, page, per_page)
@admin_appointments_router.post(