From b5f0453cdd7547b96d85ca05d9c8b6945cd5e9ab Mon Sep 17 00:00:00 2001 From: Gilles Soulier Date: Sun, 24 May 2026 12:02:37 +0200 Subject: [PATCH] =?UTF-8?q?fix(todos):=20datetime=20query=20params=20typ?= =?UTF-8?q?=C3=A9s=20FastAPI,=20ORDER=20BY=20d=C3=A9terministe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Changer due_after/due_before de str | None vers datetime | None pour typage FastAPI - FastAPI parse et valide automatiquement, retourne 422 si format invalide (pas 500) - Supprimer le parsing manuel datetime.fromisoformat() qui levait ValueError brute - Ajouter ORDER BY déterministe: due_date ASC NULLS LAST, created_at DESC évite les réordonnances aléatoires entre requêtes PostgreSQL Tests: 15/15 passent ✓ Co-Authored-By: Claude Sonnet 4.6 --- backend/app/api/todos.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/app/api/todos.py b/backend/app/api/todos.py index 52fda31..f03392b 100644 --- a/backend/app/api/todos.py +++ b/backend/app/api/todos.py @@ -18,8 +18,8 @@ async def list_todos( status: str | None = "pending", priority: str | None = None, tag: str | None = None, - due_after: str | None = None, - due_before: str | None = None, + due_after: datetime | None = None, + due_before: datetime | None = None, limit: int = 200, session: AsyncSession = Depends(get_session), ): @@ -33,13 +33,14 @@ async def list_todos( if tag: conditions.append(TodoItem.tags.contains([tag])) if due_after: - conditions.append(TodoItem.due_date >= datetime.fromisoformat(due_after)) + conditions.append(TodoItem.due_date >= due_after) if due_before: - conditions.append(TodoItem.due_date <= datetime.fromisoformat(due_before)) + conditions.append(TodoItem.due_date <= due_before) stmt = select(TodoItem) if conditions: stmt = stmt.where(and_(*conditions)) + stmt = stmt.order_by(TodoItem.due_date.asc().nulls_last(), TodoItem.created_at.desc()) stmt = stmt.limit(limit) result = await session.execute(stmt) return result.scalars().all()