Avec 119 articles en base et limit=50, les articles en fin de liste
alphabétique (Îles flottantes, Éponge…) n'apparaissaient pas dans
le bottom sheet. Limite portée à 500 côté backend ET frontend.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend :
- Migration 004 : last_purchased_at (DATE) + avg_interval_days (NUMERIC)
sur shopping.products
- update_item : met à jour les stats au premier cochage d'un article
lié à un produit (moyenne mobile exp. 70/30)
- ProductResponse expose les deux nouveaux champs
Frontend :
- ItemRow : long press 500ms → onEdit() (mobile) ; crayon + croix (laptop)
- ShoppingPage : modal édition quantité/unité, état editingItem
- api/shopping.ts : Product inclut last_purchased_at + avg_interval_days
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- UX : vue par défaut = liste en cours, landing si pas de liste (+ vert +
baguette magique), suppression des vues "listes" et "mode magasin" séparés
- Articles cochés barrés et déplacés en bas, tri alphabétique par section
- Nom de liste auto avec numéro de semaine ISO (S21 2026)
- Wake lock activé dès qu'une liste est ouverte
- CRUD boutiques : POST/PATCH/DELETE /stores + modal Boutiques
- CRUD articles : POST/PATCH/DELETE /products + modal Catalogue
- Champs enrichis produits : description, prix, quantité/unité, boutique défaut
- Champs enrichis boutiques : url, store_type (alimentaire, bricolage…)
- Migration 003 : nouveaux champs en base
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ajoute POST /api/shopping/lists/generate qui calcule un score retard/intervalle
par article (achats_with_lag CTE pour contourner la limite PostgreSQL sur
AVG+LAG imbriqués) et génère une liste draft avec les articles >= 0.7.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ajoute backend/app/api/shopping.py avec les routes :
- GET/POST /api/shopping/lists
- GET/PATCH/DELETE /api/shopping/lists/{id}
- POST/PATCH/DELETE /api/shopping/lists/{id}/items
- GET /api/shopping/stores
- GET /api/shopping/products
- POST /api/shopping/lists/{id}/finish (report des articles non cochés)
Enregistre le router dans main.py avec le prefix /api/shopping.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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 <noreply@anthropic.com>
Ajoute les 5 endpoints REST (list, create, update, delete, postpone),
enregistre le routeur sur /api/todos, et corrige l'isolation des sessions
de test via NullPool + dependency_overrides dans conftest.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implémentation TDD : test écrit en premier (phase rouge), puis
app.main, app.api.health et app.api.media créés pour le faire passer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>