# Plan d'Implémentation - Dashboard Admin Inscriptions ## 📋 Analyse de l'Existant ### Modèles et Relations - ✅ `Registration` : Relations vers `user`, `event`, `pricingPlan`, `batch`, `payments` - ✅ `RegistrationStatus` enum : 7 statuts (draft, submitted, pending_payment, paid, rejected, cancelled, refunded) - ✅ `RegistrationPolicy` : Existe mais pas de méthodes admin dédiées - ✅ `RegistrationResource` : Existe, à étendre pour admin - ✅ `ExportController::participants()` : Logique export CSV réutilisable ### Indexes DB Existants - ✅ `user_id`, `event_id`, `pricing_plan_id`, `status`, `batch_id` - ⚠️ Manque : `created_at`, `submitted_at`, `country` (si utilisé pour filtres) ### Ce qui manque - ❌ Table d'audit `registration_status_changes` - ❌ Model `RegistrationStatusChange` - ❌ Classe `RegistrationStatusTransitions` (state machine) - ❌ `AdminRegistrationController` - ❌ `AdminRegistrationResource` - ❌ Méthodes admin dans `RegistrationPolicy` --- ## 🎯 Plan d'Implémentation par Phases ### Phase 1 : Backend MVP (Routes + Controller + Resource + Policy) **Objectif** : Liste paginée + détails avec filtres de base **Tâches** : 1. ✅ Migration : Indexes supplémentaires (`created_at`, `submitted_at`, `country`) 2. ✅ Migration : Table `registration_status_changes` (préparer pour Phase 4) 3. ✅ Model : `RegistrationStatusChange` avec relation 4. ✅ Policy : Étendre `RegistrationPolicy` avec méthodes admin 5. ✅ Resource : Créer `AdminRegistrationResource` 6. ✅ Controller : Créer `AdminRegistrationController` (index, show) 7. ✅ Routes : Ajouter routes admin avec middleware 8. ✅ Scopes : Ajouter scopes de filtrage sur `Registration` model 9. ✅ Tests : Feature tests pour index/show avec policies **Détails techniques** : - Filtres : `event_id`, `status[]`, `q` (nom/email/phone), `created_from`, `created_to` - Pagination : 20 par défaut, options 20/50/100 - Eager loading : `event`, `pricingPlan`, `user.roles`, `payments`, `statusChanges` - Recherche `q` : `where` avec `LIKE` sur `first_name`, `last_name`, `email`, `phone` --- ### Phase 2 : Backend Audit (Préparation) **Objectif** : Structure d'audit prête pour Phase 4 **Tâches** : 1. ✅ Migration déjà créée en Phase 1 2. ✅ Model `RegistrationStatusChange` avec relations 3. ✅ Relation `statusChanges()` sur `Registration` 4. ✅ Exposer dans `AdminRegistrationResource` (historique) --- ### Phase 3 : Backend Stats **Objectif** : Endpoint statistiques agrégées **Tâches** : 1. ✅ Méthode `stats()` dans `AdminRegistrationController` 2. ✅ Calculs : total, by_status, by_event, by_plan, timeline 3. ✅ Filtres appliquables (event_id, date range) 4. ✅ Tests : Feature test pour stats **Format réponse** : ```json { "total": 150, "by_status": { "draft": 10, "submitted": 80, ... }, "by_event": { "sommet-2026": 100, ... }, "by_plan": { "A": 40, "B": 35, ... }, "timeline": [{"date": "2026-01-19", "count": 15}, ...] } ``` --- ### Phase 4 : Backend UpdateStatus **Objectif** : Changer statut avec validation stricte + audit **Tâches** : 1. ✅ Classe `RegistrationStatusTransitions` (state machine) 2. ✅ FormRequest : `UpdateRegistrationStatusRequest` 3. ✅ Méthode `updateStatus()` dans controller 4. ✅ Validation transitions (422 si invalide) 5. ✅ Transaction DB (update + audit insert) 6. ✅ Logging action 7. ✅ Tests : Feature tests (policy + validation transitions) **Transitions autorisées** (à définir) : - `draft` → `submitted`, `cancelled` - `submitted` → `pending_payment`, `rejected`, `cancelled` - `pending_payment` → `paid`, `cancelled` - `paid` → `refunded` - `rejected` → (aucune) - `cancelled` → (aucune) - `refunded` → (aucune) --- ### Phase 5 : Backend Export **Objectif** : Export CSV réutilisant logique existante **Tâches** : 1. ✅ Méthode `export()` dans controller 2. ✅ Réutiliser logique `ExportController::participants()` 3. ✅ Appliquer filtres de la requête 4. ✅ Format CSV avec BOM UTF-8 --- ### Phase 6 : Frontend MVP **Objectif** : Dashboard avec table + filtres + détails **Tâches** : 1. ✅ Service API : `adminRegistrations.ts` 2. ✅ Hook : `useAdminRegistrations` 3. ✅ Page : `RegistrationsDashboard` 4. ✅ Composants : `RegistrationsTable`, `RegistrationFilters`, `RegistrationDetailsModal` 5. ✅ Route : `/admin/registrations` (protégée) --- ### Phase 7 : Frontend Stats **Objectif** : Cartes statistiques + graphiques **Tâches** : 1. ✅ Hook : `useAdminRegistrationStats` 2. ✅ Composant : `RegistrationStats` (cartes + charts) 3. ✅ Bibliothèque : Recharts (ou Chart.js si préféré) --- ### Phase 8 : Frontend Actions **Objectif** : Changer statut + export **Tâches** : 1. ✅ Modal/Form : Changer statut (admin only) 2. ✅ Bouton export CSV 3. ✅ Feedback utilisateur (toasts) --- ## 🔐 Sécurité et Permissions ### Policy Structure ```php // RegistrationPolicy public function viewAnyAdmin(User $user): bool { return $user->hasAnyRole(['admin', 'treasurer']); } public function viewAdmin(User $user, Registration $registration): bool { return $user->hasAnyRole(['admin', 'treasurer']); } public function updateStatus(User $user, Registration $registration): bool { return $user->hasRole('admin'); // Seulement admin } public function export(User $user): bool { return $user->hasAnyRole(['admin', 'treasurer']); } ``` ### Middleware Routes ```php Route::middleware(['auth:sanctum'])->prefix('admin/registrations')->group(function () { // Policy enforcement dans controller }); ``` --- ## 📊 Structure de la Table d'Audit ```php Schema::create('registration_status_changes', function (Blueprint $table) { $table->id(); $table->foreignId('registration_id')->constrained()->onDelete('cascade'); $table->foreignId('actor_user_id')->constrained('users')->onDelete('cascade'); $table->string('from_status', 50)->nullable(); // null si création $table->string('to_status', 50); $table->text('notes')->nullable(); $table->timestamps(); $table->index('registration_id'); $table->index('actor_user_id'); $table->index('created_at'); }); ``` --- ## 🚀 Ordre d'Exécution Recommandé 1. **Phase 1 Backend MVP** ← **COMMENCER ICI** 2. Phase 2 Backend Audit (préparation) 3. Phase 3 Backend Stats 4. Phase 4 Backend UpdateStatus 5. Phase 5 Backend Export 6. Phase 6 Frontend MVP 7. Phase 7 Frontend Stats 8. Phase 8 Frontend Actions --- ## ✅ Critères de Validation ### Phase 1 - ✅ Route `GET /admin/registrations` retourne liste paginée - ✅ Filtres fonctionnent (event_id, status[], q, dates) - ✅ Route `GET /admin/registrations/{id}` retourne détails complets - ✅ Policy bloque non-admin/treasurer - ✅ Eager loading évite N+1 - ✅ Tests passent --- **Document créé le** : 2026-01-XX **Statut** : ⏳ Prêt pour implémentation Phase 1