# language: fr Fonctionnalité: API - Création et gestion d'audio-guides multi-séquences En tant que système backend Je veux exposer des endpoints pour créer et gérer les audio-guides Afin de permettre aux créateurs de publier des expériences guidées Contexte: Étant donné que l'API RoadWave est démarrée Et que le créateur "guide@example.com" est authentifié avec un token JWT valide Et que son compte est vérifié (email_verified: true) # 16.1.2 - Endpoints de création Scénario: POST /api/v1/audio-guides - Création d'un audio-guide Étant donné la requête suivante: """json { "title": "Safari du Paugre", "description": "Découvrez les animaux du parc en voiture sur un circuit de 5km", "mode": "voiture", "vitesse_recommandee": "30-50 km/h", "tags": ["nature", "animaux", "famille"], "classification_age": "tout_public", "zone_diffusion": { "type": "polygon", "coordinates": [[2.5678, 43.1234], [2.5690, 43.1245], [2.5700, 43.1250]] } } """ Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est 201 Et le corps de réponse contient: | champ | valeur | | id | UUID généré | | status | draft | | creator_id | ID du créateur | | sequences_count | 0 | | created_at | Timestamp actuel | Scénario: Validation du titre (longueur 5-100 caractères) Étant donné la requête avec titre "ABC" Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est 400 Et le message d'erreur est "title: doit contenir entre 5 et 100 caractères" Scénario: Validation de la description (longueur 10-500 caractères) Étant donné la requête avec description de 8 caractères Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est 400 Et le message d'erreur est "description: doit contenir entre 10 et 500 caractères" Plan du Scénario: Validation du mode de déplacement Étant donné la requête avec mode "" Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est Exemples: | mode | code | | pieton | 201 | | voiture | 201 | | velo | 201 | | transport | 201 | | avion | 400 | | invalid | 400 | Scénario: Validation tags (1-3 tags obligatoires) Étant donné la requête avec 0 tags Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est 400 Et le message d'erreur est "tags: minimum 1 tag requis, maximum 3" Scénario: Validation classification âge Étant donné la requête avec classification_age "invalide" Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est 400 Et le message d'erreur contient "classification_age: valeurs autorisées [tout_public, 13+, 16+, 18+]" # Ajout de séquences Scénario: POST /api/v1/audio-guides/{id}/sequences - Ajout première séquence Étant donné un audio-guide draft avec ID "ag_123" Et la requête suivante: """json { "order": 1, "title": "Introduction - Point d'accueil", "audio_file": "base64_encoded_mp3_data", "gps_point": { "latitude": 43.1234, "longitude": 2.5678 }, "rayon_declenchement": 30 } """ Quand je fais un POST sur "/api/v1/audio-guides/ag_123/sequences" Alors le code HTTP de réponse est 201 Et la séquence est créée avec: | champ | valeur | | sequence_id | UUID généré | | order | 1 | | duration | Calculée depuis audio | | status | uploaded | Scénario: Validation format audio (MP3, AAC, M4A uniquement) Étant donné un audio-guide draft Et un fichier audio au format WAV Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences" Alors le code HTTP de réponse est 400 Et le message d'erreur est "audio_file: format non supporté. Formats acceptés: MP3, AAC, M4A" Scénario: Validation taille audio (max 200 MB) Étant donné un audio-guide draft Et un fichier audio de 250 MB Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences" Alors le code HTTP de réponse 413 Et le message d'erreur est "audio_file: taille maximale 200 MB dépassée" Scénario: Validation durée audio (max 15 minutes) Étant donné un audio-guide draft Et un fichier audio de 18 minutes Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences" Alors le code HTTP de réponse est 400 Et le message d'erreur est "audio_file: durée maximale 15 minutes dépassée" Scénario: Point GPS obligatoire sauf mode piéton Étant donné un audio-guide en mode "voiture" Et une séquence sans gps_point Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences" Alors le code HTTP de réponse est 400 Et le message d'erreur est "gps_point: obligatoire pour mode voiture" Scénario: Point GPS optionnel en mode piéton Étant donné un audio-guide en mode "pieton" Et une séquence sans gps_point Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences" Alors le code HTTP de réponse est 201 Et la séquence est créée sans point GPS Plan du Scénario: Rayon de déclenchement par défaut selon mode Étant donné un audio-guide en mode "" Et une séquence sans rayon_declenchement spécifié Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences" Alors le rayon par défaut appliqué est Exemples: | mode | rayon | | voiture | 30 | | velo | 50 | | transport | 100 | Scénario: Validation rayon configurable (10-200m) Étant donné un audio-guide Et une séquence avec rayon_declenchement 250 Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences" Alors le code HTTP de réponse est 400 Et le message d'erreur est "rayon_declenchement: doit être entre 10 et 200 mètres" Scénario: Nombre maximum de séquences (50) Étant donné un audio-guide avec 50 séquences Quand je tente d'ajouter une 51ème séquence Alors le code HTTP de réponse est 400 Et le message d'erreur est "Maximum 50 séquences par audio-guide atteint" # Modification et réordonnancement Scénario: PATCH /api/v1/audio-guides/{id}/sequences/{seq_id} - Modification séquence Étant donné une séquence existante "seq_456" Et la requête suivante: """json { "title": "Introduction - Point d'accueil (édité)", "rayon_declenchement": 40 } """ Quand je fais un PATCH sur "/api/v1/audio-guides/ag_123/sequences/seq_456" Alors le code HTTP de réponse est 200 Et les champs modifiés sont mis à jour Et updated_at est mis à jour Scénario: PUT /api/v1/audio-guides/{id}/sequences/reorder - Réordonnancement Étant donné un audio-guide avec 5 séquences Et la requête suivante: """json { "sequence_orders": [ {"sequence_id": "seq_1", "order": 1}, {"sequence_id": "seq_4", "order": 2}, {"sequence_id": "seq_2", "order": 3}, {"sequence_id": "seq_3", "order": 4}, {"sequence_id": "seq_5", "order": 5} ] } """ Quand je fais un PUT sur "/api/v1/audio-guides/ag_123/sequences/reorder" Alors le code HTTP de réponse est 200 Et l'ordre des séquences est mis à jour en base Scénario: DELETE /api/v1/audio-guides/{id}/sequences/{seq_id} - Suppression séquence Étant donné un audio-guide avec 3 séquences Quand je fais un DELETE sur "/api/v1/audio-guides/ag_123/sequences/seq_2" Alors le code HTTP de réponse est 204 Et la séquence est supprimée Et l'ordre des séquences restantes est réajusté (1, 2) # Publication et validation Scénario: POST /api/v1/audio-guides/{id}/publish - Publication (nouveau créateur) Étant donné un audio-guide draft avec 3 séquences complètes Et que c'est le 2ème audio-guide du créateur Quand je fais un POST sur "/api/v1/audio-guides/ag_123/publish" Alors le code HTTP de réponse est 200 Et le status passe à "pending_moderation" Et moderation_required est true Et le corps de réponse contient: """json { "status": "pending_moderation", "message": "Votre audio-guide est en cours de validation. Notre équipe le vérifiera sous 24-48h.", "estimated_validation": "2026-01-24T14:00:00Z" } """ Scénario: Publication directe pour créateur expérimenté (>5 audio-guides validés) Étant donné un audio-guide draft avec 5 séquences Et que le créateur a publié 8 audio-guides validés Et qu'il n'a aucun strike actif Quand je fais un POST sur "/api/v1/audio-guides/ag_456/publish" Alors le code HTTP de réponse est 200 Et le status passe à "published" Et moderation_required est false Et l'audio-guide est immédiatement visible Scénario: Validation nombre minimum de séquences (2) Étant donné un audio-guide draft avec 1 seule séquence Quand je fais un POST sur "/api/v1/audio-guides/ag_123/publish" Alors le code HTTP de réponse est 400 Et le message d'erreur est "Minimum 2 séquences requis pour publication" Scénario: Alerte cohérence - Points GPS trop éloignés Étant donné un audio-guide en mode "pieton" Et une séquence au Louvre (Paris) Et une séquence à Lyon (465 km de distance) Quand je fais un POST sur "/api/v1/audio-guides/ag_123/publish" Alors le code HTTP de réponse est 200 Et un warning est retourné: """json { "status": "pending_moderation", "warnings": [ { "type": "distance_incohérence", "message": "Distance importante entre points (465 km). Vérifiez que le mode 'pieton' est approprié.", "severity": "warning" } ] } """ # Gestion des brouillons Scénario: Sauvegarde automatique brouillon Étant donné un audio-guide draft non sauvegardé depuis 5 minutes Quand une modification est apportée via PATCH Alors le champ updated_at est mis à jour automatiquement Et le brouillon est sauvegardé en base Scénario: GET /api/v1/audio-guides/drafts - Liste des brouillons Étant donné que le créateur a 2 brouillons: | id | title | sequences_count | updated_at | | ag_111 | Safari du Paugre | 3 | 2026-01-20 10:00:00 | | ag_222 | Visite du Louvre | 1 | 2026-01-15 14:30:00 | Quand je fais un GET sur "/api/v1/audio-guides/drafts" Alors le code HTTP de réponse est 200 Et le corps de réponse contient les 2 brouillons Et ils sont triés par updated_at décroissant Scénario: DELETE /api/v1/audio-guides/{id} - Suppression brouillon Étant donné un audio-guide draft "ag_123" Quand je fais un DELETE sur "/api/v1/audio-guides/ag_123" Alors le code HTTP de réponse est 204 Et l'audio-guide et toutes ses séquences sont supprimés Et les fichiers audio associés sont marqués pour suppression S3 # Modification audio-guide publié Scénario: PATCH /api/v1/audio-guides/{id} - Modification métadonnées (publié) Étant donné un audio-guide publié "ag_789" Et la requête suivante: """json { "title": "Safari du Paugre - Version 2", "description": "Nouvelle description améliorée", "tags": ["nature", "animaux", "enfants"] } """ Quand je fais un PATCH sur "/api/v1/audio-guides/ag_789" Alors le code HTTP de réponse est 200 Et les métadonnées sont mises à jour Et le status reste "published" (pas de revalidation) Scénario: Interdiction modification mode après publication Étant donné un audio-guide publié en mode "voiture" Et la requête avec mode "pieton" Quand je fais un PATCH sur "/api/v1/audio-guides/{id}" Alors le code HTTP de réponse est 400 Et le message d'erreur est "mode: impossible de modifier le mode après publication" Scénario: Interdiction modification GPS après publication Étant donné un audio-guide publié avec points GPS Et une tentative de modification des coordonnées GPS Quand je fais un PATCH sur "/api/v1/audio-guides/{id}/sequences/{seq_id}" Alors le code HTTP de réponse est 400 Et le message d'erreur est "gps_point: impossible de modifier après publication. Créez une nouvelle version." # Duplication Scénario: POST /api/v1/audio-guides/{id}/duplicate - Duplication audio-guide Étant donné un audio-guide publié "ag_999" avec 12 séquences Quand je fais un POST sur "/api/v1/audio-guides/ag_999/duplicate" Alors le code HTTP de réponse est 201 Et un nouvel audio-guide draft est créé Et le titre est "Safari du Paugre (copie)" Et toutes les séquences sont copiées avec les mêmes métadonnées Et les fichiers audio sont référencés (pas de duplication S3) # Statistiques Scénario: GET /api/v1/audio-guides/{id}/stats - Statistiques parcours Étant donné un audio-guide avec les séquences suivantes: | sequence | duration | gps_point | distance_to_next | | 1 | 2:15 | (43.1234, 2.5678) | 150m | | 2 | 3:42 | (43.1245, 2.5690) | 200m | | 3 | 4:10 | (43.1250, 2.5700) | null | Quand je fais un GET sur "/api/v1/audio-guides/ag_123/stats" Alors le code HTTP de réponse est 200 Et le corps de réponse contient: """json { "sequences_count": 3, "total_duration": "10:07", "total_distance": "350m", "avg_sequence_duration": "3:22" } """ # Gestion zone diffusion Scénario: Validation zone diffusion (polygon géographique) Étant donné une zone diffusion de type "polygon" Et les coordonnées forment un polygon valide (min 3 points) Quand je fais un POST sur "/api/v1/audio-guides" Alors la zone est validée avec PostGIS ST_IsValid Et stockée en type geography Scénario: Zone diffusion via API Nominatim (ville) Étant donné une zone diffusion de type "city" Et la valeur "Paris" Quand je fais un POST sur "/api/v1/audio-guides" Alors l'API interroge Nominatim pour récupérer le polygon de Paris Et le polygon est stocké en base # Cas d'erreur Scénario: Authentification requise Étant donné une requête sans token JWT Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est 401 Et le message d'erreur est "Authentification requise" Scénario: Compte non vérifié Étant donné un créateur avec email_verified: false Quand je fais un POST sur "/api/v1/audio-guides" Alors le code HTTP de réponse est 403 Et le message d'erreur est "Vérification email requise pour créer des audio-guides" Scénario: Modification audio-guide d'un autre créateur (interdite) Étant donné un audio-guide appartenant au créateur "creator_A" Et une requête authentifiée par "creator_B" Quand je fais un PATCH sur "/api/v1/audio-guides/{id}" Alors le code HTTP de réponse est 403 Et le message d'erreur est "Vous n'êtes pas autorisé à modifier cet audio-guide" Scénario: Audio-guide inexistant Quand je fais un GET sur "/api/v1/audio-guides/ag_nonexistant" Alors le code HTTP de réponse est 404 Et le message d'erreur est "Audio-guide non trouvé" Scénario: Séquence inexistante Étant donné un audio-guide "ag_123" Quand je fais un DELETE sur "/api/v1/audio-guides/ag_123/sequences/seq_nonexistant" Alors le code HTTP de réponse est 404 Et le message d'erreur est "Séquence non trouvée" Scénario: Suppression audio-guide avec utilisateurs actifs Étant donné un audio-guide publié "ag_456" Et 20 utilisateurs ont une progression active Quand je fais un DELETE sur "/api/v1/audio-guides/ag_456" Alors le code HTTP de réponse est 200 Et l'audio-guide est marqué "deleted" (soft delete) Et les progressions utilisateurs sont archivées pendant 30 jours Et un warning est retourné: "20 utilisateurs actifs. Progressions archivées 30 jours."