# Story 4.4: Implémenter la gestion des limites de prédictions Status: review ## Acceptance Criteria **Given** un utilisateur gratuit consulte une prédiction **When** il accède à une prédiction **Then** le système vérifie son quota quotidien (1-2 prédictions/jour) **And** si le quota n'est pas dépassé, la prédiction est affichée **And** le compteur de prédictions consultées est incrémenté **Given** un utilisateur gratuit a atteint sa limite **When** il tente de consulter une prédiction supplémentaire **Then** un message indique qu'il a atteint sa limite **And** une option pour passer à Premium est proposée **And** la prédiction n'est pas affichée **Given** un utilisateur premium consulte des prédictions **When** il accède à des prédictions **Then** aucune limite n'est appliquée **And** toutes les prédictions sont accessibles ## Tasks / Subtasks - [x] Mettre à jour le schéma utilisateur pour le tracking des limites (AC: #1) - [x] Ajouter la colonne `daily_predictions_count` à `users` - [x] Ajouter la colonne `last_prediction_date` à `users` - [x] Générer et appliquer les migrations - [x] Mettre à jour les types TypeScript - [x] Créer le service de vérification des limites (AC: #1) - [x] Créer `src/services/limitService.ts` - [x] Implémenter `checkFreeUserLimit(userId)` - [x] Implémenter `incrementDailyCount(userId)` - [x] Implémenter `resetDailyCount()` (cron ou à minuit) - [x] Retourner `allowed`, `remaining`, `limit` - [x] Créer le middleware de limitation (AC: #1, #2) - [x] Créer `src/middleware/rateLimit.ts` - [x] Vérifier le statut premium - [x] Vérifier le quota quotidien pour les utilisateurs gratuits - [x] Bloquer l'accès si limite atteinte - [x] Retourner 429 si limite atteinte - [x] Créer un composant de limite atteinte (AC: #2) - [x] Créer `src/components/limits/LimitReached.tsx` - [x] Afficher le message: "Limite de prédictions atteinte" - [x] Afficher le compteur (ex: "1/2 prédictions utilisées") - [x] Ajouter bouton "Passer à Premium" - [x] Utiliser shadcn/ui components - [x] Créer le composant de compteur de prédictions (AC: #1) - [x] Créer `src/components/limits/PredictionCounter.tsx` - [x] Afficher les prédictions restantes - [x] Afficher le quota (ex: "1/2") - [x] Mettre à jour en temps réel - [x] Ne pas afficher pour les utilisateurs premium - [x] Configurer le reset quotidien des limites (AC: #1) - [x] Créer un cron job ou endpoint `/api/limits/reset` - [x] Réinitialiser `daily_predictions_count` à 0 - [x] Mettre à jour `last_prediction_date` - [x] Logger les resets - [x] Tester le reset à minuit - [x] Tester la gestion des limites (AC: #1, #2, #3) - [x] Tester avec utilisateur gratuit (1-2 prédictions) - [x] Tester quand la limite est atteinte - [x] Tester avec utilisateur premium (illimité) - [x] Vérifier que le reset quotidien fonctionne - [x] Vérifier que le compteur est mis à jour ## Dev Notes ### Stack Technique - **Limites:** 1-2 prédictions/jour (free), illimité (premium) - **Cron:** Vercel Cron ou node-cron - **State:** Zustand + React Query ### File Structure ``` src/ ├── services/ │ └── limitService.ts ├── middleware/ │ └── rateLimit.ts ├── components/ │ └── limits/ │ ├── LimitReached.tsx │ └── PredictionCounter.tsx └── app/ └── api/ └── limits/ └── reset/route.ts ``` ### References - [Source: _bmad-output/planning-artifacts/epics.md#Story-4.4] ## Dev Agent Record ### Agent Model Used GLM-4.7 ### Completion Notes List - Schéma utilisateur mis à jour avec colonnes daily_predictions_count et last_prediction_date - Migration générée (0003_cheerful_true_believers.sql) et appliquée à la base de données - Types TypeScript automatiquement mis à jour par Drizzle ORM - Service de vérification des limites créé avec checkFreeUserLimit(), incrementDailyCount(), resetDailyCount() - Middleware de limitation implémenté avec vérification du statut premium et du quota quotidien - Composant LimitReached créé avec design shadcn/ui, affichage du compteur et bouton "Passer à Premium" - Composant PredictionCounter créé, affiche les prédictions restantes, ne s'affiche pas pour les utilisateurs premium - API endpoint /api/limits/reset créé pour réinitialiser les limites quotidiennes - Tests complets: 50 tests passants pour la gestion des limites (schéma, service, middleware, composants, API, intégration) ### File List - `src/db/schema.ts` - Schéma utilisateur mis à jour avec daily_predictions_count et last_prediction_date - `drizzle/migrations/0003_cheerful_true_believers.sql` - Migration générée - `src/services/limitService.ts` - Service de vérification des limites - `src/middleware/rateLimit.ts` - Middleware de limitation des prédictions - `src/components/limits/LimitReached.tsx` - Composant de limite atteinte - `src/components/limits/PredictionCounter.tsx` - Composant de compteur de prédictions - `src/app/api/limits/reset/route.ts` - API endpoint pour reset quotidien - `src/tests/limits-schema.test.ts` - Tests du schéma (8 tests) - `src/tests/limit-service-real.test.ts` - Tests du service (8 tests) - `src/tests/rate-limit-middleware.test.ts` - Tests du middleware (6 tests) - `src/tests/limit-reached.test.tsx` - Tests du composant LimitReached (6 tests) - `src/tests/prediction-counter.test.tsx` - Tests du composant PredictionCounter (6 tests) - `src/tests/limits-reset-api.test.ts` - Tests de l'API reset (5 tests) - `src/tests/limits-integration.test.ts` - Tests d'intégration (11 tests) ## Change Log - 2026-01-17: Implémentation complète de la gestion des limites de prédictions - Ajouté les colonnes daily_predictions_count et last_prediction_date au schéma utilisateur - Créé le service limitService.ts avec les fonctions checkFreeUserLimit, incrementDailyCount, resetDailyCount - Créé le middleware rateLimit.ts pour vérifier et bloquer les utilisateurs gratuits - Créé les composants LimitReached.tsx et PredictionCounter.tsx - Créé l'endpoint /api/limits/reset pour le reset quotidien - 50 tests d'unité et d'intégration écrits et passants - Tous les critères d'acceptation satisfaits - Aucune régression détectée