refactor(docs): réorganiser la documentation selon principes DDD

Réorganise la documentation du projet selon les principes du Domain-Driven Design (DDD) pour améliorer la cohésion, la maintenabilité et l'alignement avec l'architecture modulaire du backend.

**Structure cible:**
```
docs/domains/
├── README.md (Context Map)
├── _shared/ (Core Domain)
├── recommendation/ (Supporting Subdomain)
├── content/ (Supporting Subdomain)
├── moderation/ (Supporting Subdomain)
├── advertising/ (Generic Subdomain)
├── premium/ (Generic Subdomain)
└── monetization/ (Generic Subdomain)
```

**Changements effectués:**

Phase 1: Création de l'arborescence des 7 bounded contexts
Phase 2: Déplacement des règles métier (01-19) vers domains/*/rules/
Phase 3: Déplacement des diagrammes d'entités vers domains/*/entities/
Phase 4: Déplacement des diagrammes flux/états/séquences vers domains/*/
Phase 5: Création des README.md pour chaque domaine
Phase 6: Déplacement des features Gherkin vers domains/*/features/
Phase 7: Création du Context Map (domains/README.md)
Phase 8: Mise à jour de mkdocs.yml pour la nouvelle navigation
Phase 9: Correction automatique des liens internes (script fix-markdown-links.sh)
Phase 10: Nettoyage de l'ancienne structure (regles-metier/, diagrammes/, features/)

**Configuration des tests:**
- Makefile: godog run docs/domains/*/features/
- scripts/generate-bdd-docs.py: features_dir → docs/domains

**Avantages:**
 Cohésion forte: toute la doc d'un domaine au même endroit
 Couplage faible: domaines indépendants, dépendances explicites
 Navigabilité améliorée: README par domaine = entrée claire
 Alignement code/docs: miroir de backend/internal/
 Onboarding facilité: exploration domaine par domaine
 Tests BDD intégrés: features au plus près des règles métier

Voir docs/REFACTOR-DDD.md pour le plan complet.
This commit is contained in:
jpgiannetti
2026-02-07 17:15:02 +01:00
parent 78422bb2c0
commit 5e5fcf4714
227 changed files with 1413 additions and 1967 deletions

View File

@@ -0,0 +1,254 @@
# language: fr
Fonctionnalité: Création de campagnes publicitaires
En tant que publicitaire
Je veux créer des campagnes avec ciblage précis et maîtrise du budget
Afin d'optimiser mes investissements publicitaires
Contexte:
Étant donné que l'API RoadWave est disponible
Et qu'un compte publicitaire est créé et vérifié
Scénario: Création d'une campagne publicitaire complète
Étant donné que je suis connecté en tant que publicitaire
Quand je crée une nouvelle campagne avec les paramètres:
| Paramètre | Valeur |
| Budget total | 300 |
| Date début | 2026-02-01 |
| Date fin | 2026-02-14 |
| Zone géographique | Département du Var |
| Plages horaires | 7h-9h, 17h-19h |
| Tags ciblés | Automobile, Voyage |
| Tranche d'âge | 18+ |
Alors la campagne est créée avec succès
Et le budget quotidien calculé est de 21.43/jour
Et les diffusions estimées sont de ~430 écoutes complètes
Et un statut "En attente de validation" est assigné
Scénario: Budget minimum 50€ requis
Étant donné que je crée une nouvelle campagne
Quand je définis un budget de 40
Alors une erreur s'affiche: "Budget minimum requis: 50"
Et la campagne n'est pas créée
Scénario: Budget de 50€ exactement accepté
Étant donné que je crée une nouvelle campagne
Quand je définis un budget de 50
Alors la campagne est créée avec succès
Et aucune erreur n'est affichée
Scénario: Calcul automatique du budget quotidien
Étant donné une campagne avec:
| Budget total | 300 |
| Durée | 14 j |
Quand le système calcule le budget quotidien
Alors le budget/jour est de 21.43
Et le nombre estimé de diffusions/jour est de 430 (à 0.05/écoute)
Scénario: Ciblage géographique point GPS précis
Étant donné que je crée une campagne
Quand je sélectionne "Point GPS" avec coordonnées (43.1234, 5.9234)
Et que je définis un rayon de 5km
Alors la campagne cible uniquement les utilisateurs dans ce rayon
Et la zone est représentée par un cercle sur la carte
Scénario: Ciblage géographique ville
Étant donné que je crée une campagne
Quand je sélectionne "Ville" et choisis "Marseille"
Alors la campagne cible tous les utilisateurs dans la commune de Marseille
Et les limites administratives sont affichées sur la carte
Scénario: Ciblage géographique département
Étant donné que je crée une campagne
Quand je sélectionne "Département" et choisis "Var (83)"
Alors la campagne cible tout le département du Var
Et une estimation de population cible est affichée
Scénario: Ciblage géographique région
Étant donné que je crée une campagne
Quand je sélectionne "Région" et choisis "Provence-Alpes-Côte d'Azur"
Alors la campagne cible toute la région PACA
Et l'estimation de population cible est mise à jour
Scénario: Ciblage géographique national
Étant donné que je crée une campagne
Quand je sélectionne "National"
Alors la campagne cible tous les utilisateurs en France
Et aucune limite géographique n'est appliquée
Scénario: Ciblage horaire plages multiples
Étant donné que je crée une campagne
Quand je définis les plages horaires:
| Plage |
| 7h-9h |
| 12h-14h |
| 17h-19h |
Alors la publicité est diffusée uniquement pendant ces plages
Et elle n'est jamais diffusée en dehors (ex: 10h, 15h, 20h)
Scénario: Ciblage horaire toute la journée
Étant donné que je crée une campagne
Quand je ne définis aucune plage horaire spécifique
Alors la publicité est diffusée 24h/24
Et aucune restriction horaire n'est appliquée
Scénario: Ciblage par centres d'intérêt
Étant donné que je crée une campagne pour un garage automobile
Quand je sélectionne les tags:
| Tag |
| Automobile |
| Mécanique |
| Sport |
Alors la publicité est prioritaire pour les utilisateurs avec jauges élevées sur ces tags
Et elle peut quand même être diffusée à d'autres utilisateurs (ciblage non exclusif)
Scénario: Classification d'âge obligatoire
Étant donné que je crée une campagne
Quand j'essaie de valider sans sélectionner une tranche d'âge
Alors une erreur s'affiche: "Classification d'âge obligatoire"
Et les options proposées sont:
| Option |
| Tout public |
| 13+ |
| 16+ |
| 18+ |
Scénario: Upload audio publicitaire formats acceptés
Étant donné que je crée une campagne
Quand j'upload un fichier audio format MP3
Alors le fichier est accepté
Quand j'upload un fichier audio format AAC (.aac ou .m4a)
Alors le fichier est accepté
Quand j'upload un fichier audio format WAV
Alors une erreur s'affiche: "Format non supporté. Utilisez MP3 ou AAC"
Scénario: Durée audio publicitaire validée
Étant donné que je crée une campagne
Quand j'upload un audio de 8 secondes
Alors une erreur s'affiche: "Durée minimale: 10 secondes"
Quand j'upload un audio de 65 secondes
Alors une erreur s'affiche: "Durée maximale: 60 secondes"
Quand j'upload un audio de 30 secondes
Alors le fichier est accepté
Scénario: Prépaiement obligatoire via Mangopay
Étant donné que j'ai configuré une campagne à 300
Quand j'arrive à l'étape de paiement
Alors je dois payer les 300 avant validation
Et le paiement est traité via Mangopay
Et seule la carte bancaire est acceptée
Scénario: Recharge automatique optionnelle
Étant donné que j'ai une campagne active
Quand je configure la recharge automatique à 10% du budget
Alors si le budget restant passe sous 30 (10% de 300)
Et que la campagne recharge automatiquement 100
Et ma carte bancaire est débitée de 100
Et le budget total passe à 130
Scénario: Désactivation recharge automatique
Étant donné que j'ai activé la recharge automatique
Quand je désactive cette option
Alors aucune recharge ne se produit automatiquement
Et la campagne s'arrête quand le budget atteint 0
Scénario: Étalement budget sur période longue
Étant donné une campagne avec:
| Budget total | 1000 |
| Durée | 30 j |
Quand le système calcule l'étalement
Alors le budget/jour est de 33.33
Et si le budget se consomme plus vite (ex: 50/jour)
Alors une alerte "Budget épuisé dans 10 jours" est envoyée
Scénario: Estimation population cible selon zone
Étant donné que je sélectionne la zone "Marseille"
Quand le système calcule la population cible
Alors l'estimation affichée est "~15 000 utilisateurs potentiels"
Et un message "Estimation basée sur utilisateurs actifs dans la zone" s'affiche
Scénario: Campagne avec date de début différée
Étant donné que je crée une campagne
Quand je définis la date de début au 2026-03-01 (dans 1 mois)
Alors la campagne a le statut "Programmée"
Et elle démarre automatiquement le 2026-03-01 à 00h00
Et le budget n'est pas consommé avant cette date
Scénario: Interface self-service accessible
Étant donné que je suis un publicitaire
Quand j'accède à l'interface publicitaire
Alors je peux créer une campagne sans contact commercial RoadWave
Et toutes les options sont configurables en autonomie
Et un tutoriel guidé est disponible (première utilisation)
Scénario: Aperçu zone ciblée sur carte interactive
Étant donné que je configure une zone géographique
Quand je sélectionne "Département du Var"
Alors une carte Leaflet affiche les limites du département en surbrillance
Et un compteur "~50 000 utilisateurs actifs" est affiché
Et je peux zoomer/dézoomer pour visualiser la zone
Scénario: Tags multiples pour ciblage affiné
Étant donné que je crée une campagne pour un restaurant
Quand je sélectionne les tags:
| Tag |
| Gastronomie |
| Tourisme |
| Famille |
Alors la publicité est prioritaire pour utilisateurs intéressés par ces 3 thèmes
Et le score de ciblage combine les 3 jauges d'intérêt
Scénario: Validation des dates de campagne
Étant donné que je crée une campagne
Quand je définis une date de début postérieure à la date de fin
Alors une erreur s'affiche: "Date de fin doit être après date de début"
Et la campagne n'est pas créée
Scénario: Durée minimale de campagne
Étant donné que je crée une campagne
Quand je définis une durée de moins de 24 heures
Alors une erreur s'affiche: "Durée minimale: 1 jour"
Et je dois ajuster les dates
Scénario: Durée maximale de campagne
Étant donné que je crée une campagne
Quand je définis une durée de plus de 90 jours
Alors une erreur s'affiche: "Durée maximale: 90 jours"
Et je dois ajuster les dates ou créer plusieurs campagnes
Plan du Scénario: Calcul budget quotidien selon durée
Étant donné une campagne avec un budget de <budget>
Quand la durée est de <duree> jours
Alors le budget quotidien est de <budget_jour>/jour
Exemples:
| budget | duree | budget_jour |
| 100 | 10 | 10.00 |
| 300 | 14 | 21.43 |
| 500 | 30 | 16.67 |
| 1000 | 60 | 16.67 |
Plan du Scénario: Estimation diffusions selon budget
Étant donné un budget quotidien de <budget_jour>
Quand le coût par écoute complète est 0.05
Alors le nombre estimé de diffusions/jour est <diffusions>
Exemples:
| budget_jour | diffusions |
| 10.00 | 200 |
| 21.43 | 429 |
| 50.00 | 1000 |
| 100.00 | 2000 |
Plan du Scénario: Formats audio acceptés/rejetés
Étant donné que j'upload un fichier <fichier>
Quand le format est <format>
Alors le résultat est <resultat>
Exemples:
| fichier | format | resultat |
| pub.mp3 | MP3 | accepté |
| pub.aac | AAC | accepté |
| pub.m4a | AAC | accepté |
| pub.wav | WAV | rejeté |
| pub.ogg | OGG | rejeté |
| pub.flac | FLAC | rejeté |

View File

@@ -0,0 +1,288 @@
# language: fr
Fonctionnalité: Caractéristiques et facturation des publicités
En tant que système RoadWave
Je veux appliquer des règles précises de durée, skippabilité et facturation
Afin d'équilibrer expérience utilisateur et rentabilité publicitaire
Contexte:
Étant donné que l'API RoadWave est disponible
Et qu'un utilisateur gratuit écoute du contenu
Scénario: Durée minimale 10 secondes
Étant donné qu'un publicitaire uploade une publicité de 8 secondes
Quand le système valide la durée
Alors une erreur s'affiche: "Durée minimale: 10 secondes"
Et l'upload est rejeté
Scénario: Durée maximale 60 secondes
Étant donné qu'un publicitaire uploade une publicité de 65 secondes
Quand le système valide la durée
Alors une erreur s'affiche: "Durée maximale: 60 secondes"
Et l'upload est rejeté
Scénario: Durée recommandée 15-30 secondes
Étant donné qu'un publicitaire crée une campagne
Quand il voit les recommandations
Alors un message s'affiche:
"""
💡 Durée recommandée: 15-30 secondes
Les publicités de cette durée ont:
- Taux d'écoute complète: 45% (vs 35% pour 60s)
- Meilleur engagement utilisateur
- Coût par écoute optimisé
"""
Scénario: Publicité de 10 secondes acceptée
Étant donné qu'un publicitaire uploade une publicité de 10 secondes
Quand le système valide la durée
Alors le fichier est accepté
Et aucune erreur n'est affichée
Scénario: Publicité de 60 secondes acceptée
Étant donné qu'un publicitaire uploade une publicité de 60 secondes
Quand le système valide la durée
Alors le fichier est accepté
Et un avertissement s'affiche: " Durée longue: taux de skip potentiellement élevé"
Scénario: Délai minimum skippable 5 secondes par défaut
Étant donné qu'une publicité de 30 secondes démarre
Et que le délai minimal est configuré à 5 secondes
Quand j'écoute pendant 3 secondes
Alors le bouton "Passer" n'est pas visible
Et je dois attendre 2 secondes supplémentaires
Quand j'atteins 5 secondes d'écoute
Alors le bouton "Passer" apparaît
Et je peux cliquer pour passer au contenu suivant
Scénario: Délai minimum paramétrable admin (3 secondes)
Étant donné que l'admin configure le délai à 3 secondes
Et qu'une publicité démarre
Quand j'écoute pendant 3 secondes
Alors le bouton "Passer" apparaît immédiatement
Et je peux skipper
Scénario: Délai minimum paramétrable admin (10 secondes)
Étant donné que l'admin configure le délai à 10 secondes
Et qu'une publicité démarre
Quand j'écoute pendant 9 secondes
Alors le bouton "Passer" n'est toujours pas visible
Quand j'atteins 10 secondes
Alors le bouton "Passer" apparaît
Scénario: Facturation écoute complète (>80%) - 0.05€
Étant donné qu'une publicité de 30 secondes est diffusée
Quand j'écoute pendant 25 secondes (83%)
Alors l'écoute est considérée comme "complète"
Et le publicitaire est facturé 0.05
Et le compteur "écoutes complètes" s'incrémente
Scénario: Facturation écoute complète exactement 80%
Étant donné qu'une publicité de 30 secondes est diffusée
Quand j'écoute pendant exactement 24 secondes (80%)
Alors l'écoute est considérée comme "complète"
Et le publicitaire est facturé 0.05
Scénario: Facturation skip après délai minimal - 0.02€
Étant donné qu'une publicité de 30 secondes est diffusée
Et que le délai minimal est 5 secondes
Quand j'écoute pendant 10 secondes (33%)
Et que je clique sur "Passer"
Alors l'écoute est considérée comme "partielle"
Et le publicitaire est facturé 0.02
Car il y a eu une exposition partielle
Scénario: Facturation skip immédiat (<5s) - 0€
Étant donné qu'une publicité de 30 secondes est diffusée
Et que le délai minimal est 5 secondes
Quand j'écoute pendant 3 secondes
Et que je clique sur "Suivant" (pas de bouton skip encore)
Alors l'écoute est considérée comme "non engagée"
Et le publicitaire n'est PAS facturé (0)
Car l'exposition est trop courte
Scénario: Comptabilisation écoute complète à 79%
Étant donné qu'une publicité de 30 secondes est diffusée
Quand j'écoute pendant 23 secondes (77%)
Alors l'écoute est considérée comme "partielle" (pas complète)
Et le publicitaire est facturé 0.02
Car le seuil 80% n'est pas atteint
Scénario: Comptabilisation écoute complète à 100%
Étant donné qu'une publicité de 30 secondes est diffusée
Quand j'écoute les 30 secondes complètes (100%)
Alors l'écoute est considérée comme "complète"
Et le publicitaire est facturé 0.05
Scénario: Budget consommé selon mix écoutes
Étant donné qu'une campagne à 300 a généré:
| Type écoute | Nombre | Coût unitaire | Total |
| Complète (>80%) | 4000 | 0.05 | 200 |
| Partielle (5-80%) | 2000 | 0.02 | 40 |
| Skip immédiat | 1000 | 0 | 0 |
Quand je calcule le budget consommé
Alors le total est 240
Et il reste 60 de budget disponible
Scénario: Affichage compteur secondes restantes
Étant donné qu'une publicité de 30s démarre
Et que le délai minimal est 5s
Quand j'écoute pendant 2 secondes
Alors un compteur s'affiche: "Passer dans 3s..."
Quand j'atteins 5 secondes
Alors le compteur disparaît
Et le bouton "Passer la publicité" s'affiche
Scénario: Progress bar publicité visible
Étant donné qu'une publicité de 30s est en lecture
Quand 10 secondes se sont écoulées
Alors la progress bar affiche 33% (10/30)
Et l'indicateur temporel affiche "0:10 / 0:30"
Et l'utilisateur visualise la progression
Scénario: Message "Publicité" clairement affiché
Étant donné qu'une publicité démarre
Quand l'audio commence
Alors un badge "Publicité" est affiché en haut de l'écran
Et la durée totale est indiquée: "Publicité (30s)"
Et la transparence est maximale (utilisateur sait que c'est une pub)
Scénario: Transition fluide après publicité
Étant donné qu'une publicité de 30s se termine
Quand la lecture atteint 30 secondes
Alors le délai de transition de 2s démarre
Et le contenu normal suivant est annoncé
Et l'enchaînement est naturel (même UX que entre contenus)
Scénario: Like autorisé sur publicité
Étant donné qu'une publicité est en lecture
Et que le véhicule est à l'arrêt
Quand je clique sur le bouton cœur
Alors un like explicite (+2%) est enregistré
Et mes jauges d'intérêt sont mises à jour selon les tags de la pub
Et le publicitaire voit un compteur "Likes" incrémenté
Scénario: Abonnement autorisé sur publicité
Étant donné qu'une publicité est diffusée par un créateur
Et que le véhicule est à l'arrêt
Quand je clique sur "S'abonner"
Alors l'abonnement est enregistré (+5% jauges)
Et le publicitaire bénéficie de l'engagement fort
Et cela compte comme une conversion majeure
Scénario: Bouton skip visible et accessible
Étant donné qu'une publicité a dépassé le délai minimal
Quand le bouton "Passer" s'affiche
Alors il est positionné en bas à droite de l'écran
Et il a une taille de clic confortable (44×44px minimum iOS)
Et il est clairement visible (contraste élevé)
Scénario: Analytics tracking précis par type
Étant donné qu'une publicité est diffusée
Quand un événement se produit
Alors il est tracké en temps réel:
| Événement | Données enregistrées |
| Impression | timestamp, user_id, pub_id, zone_geo |
| Écoute complète | durée_ecoutee, pourcentage, coût (0.05) |
| Skip après délai | durée_ecoutee, pourcentage, coût (0.02) |
| Skip immédiat | durée_ecoutee, pourcentage, coût (0) |
| Like | timestamp, tags impactés |
| Abonnement | timestamp, creator_id |
Scénario: Recommandation sweet spot 15-30s
Étant donné les statistiques RoadWave globales:
| Durée pub | Taux complétion moyen |
| 10s | 65% |
| 15s | 55% |
| 30s | 45% |
| 45s | 30% |
| 60s | 20% |
Quand un publicitaire consulte les recommandations
Alors le sweet spot affiché est "15-30 secondes"
Et l'explication est "Meilleur compromis engagement/message"
Scénario: Optimisation durée selon taux de skip campagne
Étant donné qu'une campagne de 60s a un taux de skip de 85%
Quand le publicitaire consulte les recommandations
Alors le système suggère:
"""
Taux de skip élevé (85%)
Recommandation: Réduire la durée à 30s maximum
Impact estimé: Taux de skip attendu 55% (-30%)
"""
Scénario: Coût effectif moyen (CEM) calculé
Étant donné une campagne avec:
| Type écoute | Nombre | Coût unitaire | Total |
| Complète | 2000 | 0.05 | 100 |
| Partielle | 3000 | 0.02 | 60 |
| Skip immédiat | 1000 | 0 | 0 |
Quand je calcule le coût effectif moyen
Alors CEM = 160 / 6000 impressions = 0.027/impression
Et cette métrique aide à comparer avec CPM industrie
Scénario: Publicité non skippable interdite
Étant donné qu'un publicitaire demande "Publicité non skippable"
Quand il configure sa campagne
Alors cette option n'existe pas
Et toutes les publicités sont obligatoirement skippables après 5s minimum
Car l'expérience utilisateur est prioritaire
Scénario: Délai minimal jamais <3 secondes
Étant donné qu'un admin essaie de configurer le délai à 2 secondes
Quand il valide le paramètre
Alors une erreur s'affiche: "Délai minimal: 3 secondes minimum"
Car un délai trop court dégrade trop l'expérience
Scénario: Délai minimal jamais >10 secondes
Étant donné qu'un admin essaie de configurer le délai à 15 secondes
Quand il valide le paramètre
Alors une erreur s'affiche: "Délai maximal: 10 secondes maximum"
Car un délai trop long réduit les revenus publicitaires
Plan du Scénario: Facturation selon durée écoutée
Étant donné qu'une publicité de 30s est diffusée
Quand j'écoute pendant <duree>s (<pourcentage>%)
Alors le type d'écoute est <type>
Et le coût facturé est <cout>
Exemples:
| duree | pourcentage | type | cout |
| 3 | 10 | skip immédiat| 0 |
| 5 | 17 | partielle | 0.02 |
| 10 | 33 | partielle | 0.02 |
| 20 | 67 | partielle | 0.02 |
| 24 | 80 | complète | 0.05 |
| 27 | 90 | complète | 0.05 |
| 30 | 100 | complète | 0.05 |
Plan du Scénario: Budget consommé selon distribution écoutes
Étant donné <completes> écoutes complètes à 0.05
Et <partielles> écoutes partielles à 0.02
Et <skips> skips immédiats à 0
Quand je calcule le budget total consommé
Alors le résultat est <budget_total>
Exemples:
| completes | partielles | skips | budget_total |
| 1000 | 500 | 100 | 60 |
| 2000 | 1000 | 500 | 120 |
| 5000 | 2000 | 1000 | 290 |
| 0 | 1000 | 0 | 20 |
| 1000 | 0 | 0 | 50 |
Plan du Scénario: Apparition bouton skip selon délai configuré
Étant donné que le délai minimal est configuré à <delai>s
Quand j'écoute pendant <temps_ecoute>s
Alors le bouton "Passer" est <visible>
Exemples:
| delai | temps_ecoute | visible |
| 5 | 3 | non visible |
| 5 | 5 | visible |
| 5 | 10 | visible |
| 10 | 8 | non visible |
| 10 | 10 | visible |
| 3 | 2 | non visible |
| 3 | 3 | visible |

View File

@@ -0,0 +1,238 @@
# language: fr
Fonctionnalité: Ciblage horaire publicités et gestion fuseaux horaires
En tant que publicitaire
Je veux cibler mes publicités sur des plages horaires en heure locale utilisateur
Afin d'optimiser mes campagnes selon les moments de la journée (rush matin/soir)
Contexte:
Étant donné qu'un publicitaire crée une campagne publicitaire
# Règle 1 : Ciblage horaire = Heure locale utilisateur
Scénario: Campagne "7h-9h" diffuse selon heure locale de chaque utilisateur
Étant donné qu'une campagne est configurée avec plage horaire "7h-9h"
Et que nous sommes le 7 février 2026 à 8h00 UTC
Quand le système vérifie la diffusion pour différents utilisateurs:
| utilisateur | localisation | fuseau horaire | heure locale | diffusion ? |
| User Marseille | Marseille | Europe/Paris | 9h00 | Oui |
| User Guadeloupe | Pointe-à-Pitre | America/Guadeloupe | 4h00 | Non |
| User Réunion | Saint-Denis | Indian/Reunion | 12h00 | Non |
| User Lyon | Lyon | Europe/Paris | 9h00 | Oui |
Alors la pub est diffusée uniquement aux utilisateurs dans la plage 7h-9h leur heure locale
Scénario: Campagne "17h-19h" (rush soir) - Heure locale de chaque utilisateur
Étant donné qu'une campagne est configurée avec plage horaire "17h-19h"
Et que nous sommes le 7 février 2026 à 17h30 UTC
Quand le système vérifie la diffusion pour:
| utilisateur | fuseau horaire | heure locale | diffusion ? |
| User Paris | Europe/Paris | 18h30 | Oui |
| User Martinique | America/Martinique | 13h30 | Non |
| User Réunion | Indian/Reunion | 21h30 | Non |
Alors la pub est diffusée uniquement à User Paris (18h30 dans 17h-19h)
Scénario: Campagne 24/7 (toute la journée) - Pas de restriction horaire
Étant donné qu'une campagne n'a AUCUNE restriction horaire
Quand le système vérifie la diffusion
Alors la pub est diffusée à tout moment (0h-23h)
Et tous les utilisateurs sont éligibles quelle que soit l'heure locale
# Détection fuseau horaire utilisateur
Scénario: Détection fuseau via GPS (méthode primaire)
Étant donné qu'un utilisateur a le GPS activé
Et que sa position GPS est (latitude: 48.8566, longitude: 2.3522)
Quand le système détecte le fuseau horaire
Alors le fuseau horaire déterminé est "Europe/Paris"
Et l'heure locale est calculée avec ce fuseau
Scénario: Détection fuseau via paramètres device (si GPS désactivé)
Étant donné qu'un utilisateur a le GPS désactivé
Mais que les paramètres OS indiquent fuseau "America/Guadeloupe"
Quand le système détecte le fuseau horaire
Alors le fuseau horaire utilisé est "America/Guadeloupe"
Et l'heure locale est calculée avec ce fuseau
Scénario: Fallback IP geolocation (si GPS désactivé ET paramètres indisponibles)
Étant donné qu'un utilisateur a le GPS désactivé
Et que les paramètres device ne sont pas accessibles
Mais que l'IP est géolocalisée à La Réunion
Quand le système détecte le fuseau horaire
Alors le fuseau horaire approximatif est "Indian/Reunion"
Et l'heure locale est calculée avec ce fuseau
# Règle 2 : Ciblage "France" = Métropole + DOM
Scénario: Ciblage "France entière" inclut Métropole + DOM
Étant donné qu'une campagne cible "France (nationale)"
Quand le système vérifie les utilisateurs éligibles
Alors les utilisateurs inclus sont:
| zone | départements / territoires |
| France métropolitaine | 96 départements (01 à 95, 2A, 2B, etc.) |
| Guadeloupe | 971 |
| Martinique | 972 |
| Guyane | 973 |
| Réunion | 974 |
| Mayotte | 976 |
Scénario: Publicitaire affine ciblage "Région Provence-Alpes-Côte d'Azur"
Étant donné qu'une campagne cible "Région Provence-Alpes-Côte d'Azur"
Quand le système vérifie les utilisateurs éligibles
Alors seuls les utilisateurs en Métropole dans cette région sont ciblés
Et les utilisateurs DOM (Guadeloupe, Réunion, etc.) ne sont PAS ciblés
Scénario: Publicitaire affine ciblage "Département 971 (Guadeloupe)"
Étant donné qu'une campagne cible "Département 971"
Quand le système vérifie les utilisateurs éligibles
Alors seuls les utilisateurs en Guadeloupe sont ciblés
Et les utilisateurs Métropole ne sont PAS ciblés
Scénario: Publicitaire affine ciblage "Ville Pointe-à-Pitre"
Étant donné qu'une campagne cible "Ville Pointe-à-Pitre"
Quand le système vérifie les utilisateurs éligibles
Alors seuls les utilisateurs à Pointe-à-Pitre (Guadeloupe) sont ciblés
# Interface publicitaire
Scénario: Interface création campagne - Note explicite sur inclusion DOM
Étant donné qu'un publicitaire accède au formulaire de création campagne
Quand il sélectionne "National (France entière)"
Alors une note informative s'affiche:
"""
Note : "National (France entière)" inclut les DOM
(Guadeloupe, Martinique, Réunion, Guyane, Mayotte)
"""
Scénario: Interface - Liste déroulante ciblage géographique
Étant donné qu'un publicitaire configure le ciblage géographique
Quand il consulte la liste déroulante
Alors les options disponibles sont:
| option | description |
| National (France entière) | Métropole + DOM |
| Région | Ex: Provence-Alpes-Côte d'Azur (Métropole)|
| Département | Ex: 13 (Métropole) ou 971 (Guadeloupe) |
| Ville | Ex: Marseille, Pointe-à-Pitre |
| Point GPS + rayon | Latitude/Longitude + rayon en km |
# Cas d'usage publicitaire
Scénario: Restaurant local Guadeloupe - Ciblage département 971 + horaires 12h-14h
Étant donné qu'un restaurant à Pointe-à-Pitre crée une campagne
Et que le ciblage est "Département 971 (Guadeloupe)"
Et que les horaires sont "12h-14h" (rush déjeuner)
Quand le système diffuse les pubs à 12h30
Alors les utilisateurs Guadeloupe à 12h30 heure locale reçoivent la pub
Et les utilisateurs Métropole ne reçoivent PAS la pub (hors zone géo)
Et les utilisateurs Martinique ne reçoivent PAS la pub (hors zone géo)
Scénario: Assureur national - Ciblage France + horaires 7h-9h + 17h-19h
Étant donné qu'un assureur national crée une campagne
Et que le ciblage est "France (nationale)"
Et que les horaires sont "7h-9h" et "17h-19h" (rush matin/soir)
Quand le système diffuse les pubs
Alors à 8h locale Marseille, User Marseille reçoit la pub
Et à 8h locale Réunion, User Réunion reçoit la pub
Et User Réunion reçoit la pub à 8h locale (= 5h métropole, mais c'est son rush matin)
Scénario: Utilisateur en vacances change de fuseau horaire
Étant donné qu'un utilisateur habite Paris (Europe/Paris)
Et qu'il part en vacances à La Réunion
Et qu'il télécharge 50 contenus + pubs avant de partir
Quand l'utilisateur écoute à 8h locale Réunion (device détecte fuseau)
Alors le filtrage des pubs utilise l'heure locale Réunion (8h)
Et les pubs ciblées "7h-9h" sont diffusées normalement
# Implémentation technique
Scénario: Calcul heure locale via PostgreSQL AT TIME ZONE
Étant donné qu'une campagne a une plage horaire "7h-9h"
Et qu'un utilisateur a le fuseau "Indian/Reunion" (UTC+4)
Quand le backend vérifie l'éligibilité à 08h00 UTC
Alors la requête SQL utilise:
"""sql
SELECT
EXTRACT(HOUR FROM NOW() AT TIME ZONE 'Indian/Reunion') AS local_hour
-- Résultat: 12 (8h UTC + 4h = 12h locale)
"""
Et local_hour = 12 n'est PAS dans [7, 8, 9], donc pas de diffusion
Scénario: Base IANA Time Zone pour conversion GPS → fuseau
Étant donné qu'un utilisateur a GPS (48.8566, 2.3522)
Quand le système convertit GPS fuseau horaire
Alors la base IANA Time Zone est utilisée
Et le fuseau déterminé est "Europe/Paris"
Et la base est mise à jour régulièrement (changements DST, fuseaux)
# Justification
Scénario: Comparaison avec standard industrie - Google Ads, Facebook Ads
Étant donné qu'on compare avec Google Ads et Facebook Ads
Quand on évalue le comportement du ciblage horaire
Alors RoadWave suit le standard:
| plateforme | ciblage horaire | référence temporelle | norme |
| Google Ads | 7h-9h | Heure locale user | Standard |
| Facebook Ads | 7h-9h | Heure locale user | Standard |
| RoadWave | 7h-9h | Heure locale user | Standard |
Scénario: Avantages UX intuitive pour publicitaires
Étant donné qu'un publicitaire configure "7h-9h"
Quand il pense "rush matin"
Alors il n'a pas besoin de comprendre UTC
Et "7h-9h" signifie "matin partout en France"
Et l'UX est intuitive:
| avantage | description |
| UX intuitive publicitaires | "7h-9h" = matin partout, pas UTC compliqué |
| Équité géographique | Pas de discrimination DOM-TOM |
| Simplicité technique | Détection automatique fuseau (GPS/device) |
| Standard industrie | Même comportement Google/Facebook |
# Cas limites
Scénario: Utilisateur change de fuseau pendant campagne active
Étant donné qu'un utilisateur écoute des pubs en métropole (Europe/Paris)
Et qu'une campagne cible "7h-9h"
Quand l'utilisateur part en vacances Réunion (Indian/Reunion)
Alors le système détecte le nouveau fuseau horaire automatiquement
Et les pubs "7h-9h" sont filtrées selon l'heure locale Réunion
Et l'utilisateur reçoit les pubs à 7h-9h heure locale Réunion
Scénario: Changement heure d'été/hiver (DST) - Gestion automatique
Étant donné qu'une campagne cible "7h-9h" en Europe/Paris
Et que le changement heure d'été arrive (dernier dimanche mars)
Quand l'heure passe de 2h à 3h (UTC+1 UTC+2)
Alors le système utilise automatiquement le nouveau décalage UTC
Et les pubs "7h-9h" continuent de se diffuser à 7h-9h heure locale
Et PostgreSQL AT TIME ZONE gère automatiquement le DST
# Métriques dashboard publicitaire
Scénario: Dashboard publicitaire - Répartition géographique diffusions
Étant donné qu'une campagne "France (nationale)" + "7h-9h" est active
Quand le publicitaire consulte le dashboard
Alors la répartition géographique affiche:
| zone | impressions | % total |
| Île-de-France | 45,000 | 60% |
| Provence-Alpes | 15,000 | 20% |
| Guadeloupe | 3,000 | 4% |
| Réunion | 4,500 | 6% |
| Autres | 7,500 | 10% |
Scénario: Dashboard publicitaire - Répartition horaire diffusions
Étant donné qu'une campagne "7h-9h" est active
Quand le publicitaire consulte le dashboard
Alors un graphique horaire affiche:
| heure locale | impressions |
| 7h | 12,000 |
| 8h | 18,000 |
| 9h | 5,000 |
Et les impressions hors plage (autres heures) = 0
Scénario: Validation création campagne - Cohérence géo + horaires
Étant donné qu'un publicitaire crée une campagne
Et qu'il sélectionne "Département 971 (Guadeloupe)"
Et qu'il configure horaires "7h-9h"
Quand il valide la campagne
Alors le système confirme:
"""
Votre campagne sera diffusée à 7h-9h heure locale Guadeloupe (UTC-4).
Estimation: 2,500 impressions/jour.
"""

View File

@@ -0,0 +1,361 @@
# language: fr
Fonctionnalité: Gestion du budget et alertes publicitaires
En tant que publicitaire
Je veux suivre en temps réel mon budget et recevoir des alertes
Afin de maîtriser mes dépenses et optimiser mes campagnes
Contexte:
Étant donné que l'API RoadWave est disponible
Et qu'un compte publicitaire est connecté
Et qu'une campagne active est en cours
Scénario: Dashboard budget temps réel
Étant donné que ma campagne a un budget de 300
Et que j'ai consommé 220
Quand je consulte le dashboard budget
Alors je vois:
| Métrique | Valeur |
| Budget total | 300 |
| Budget consommé | 220 |
| Budget restant | 80 |
| Pourcentage | 73% consommé |
Scénario: Jauge visuelle budget consommé
Étant donné que j'ai consommé 220 sur 300
Quand je consulte le dashboard
Alors une jauge de progression affiche 73%
Et la couleur est orange (seuil 50-80%)
Et un indicateur "80 restants" est affiché clairement
Scénario: Couleur jauge selon seuil
Étant donné un budget de 300
Quand j'ai consommé 150 (50%)
Alors la jauge est verte
Quand j'ai consommé 240 (80%)
Alors la jauge est orange
Quand j'ai consommé 285 (95%)
Alors la jauge est rouge
Et un message "Budget presque épuisé" s'affiche
Scénario: Projection épuisement budget
Étant donné que j'ai consommé 220 en 10 jours
Et qu'il reste 4 jours de campagne
Quand le système calcule la projection
Alors la consommation quotidienne moyenne est 22/jour
Et la projection affiche "Budget épuisé dans 3.6 jours"
Et un avertissement "Campagne s'arrêtera avant la fin prévue" s'affiche
Scénario: Projection avec budget suffisant
Étant donné que j'ai consommé 100 en 10 jours
Et qu'il reste 4 jours de campagne
Et que le budget total est 300
Quand le système calcule la projection
Alors la consommation quotidienne moyenne est 10/jour
Et la projection affiche "Budget suffisant pour toute la campagne"
Et le budget restant estimé à la fin est 160
Scénario: Alerte 80% budget consommé
Étant donné que mon budget est de 300
Quand je consomme 240 (80%)
Alors je reçois immédiatement un email:
"""
Alerte Budget - 80% consommé
Campagne: [Nom]
Budget consommé: 240 / 300
Budget restant: 60
À ce rythme, votre budget sera épuisé dans X jours.
Recommandation: Envisagez une recharge pour maintenir la diffusion.
"""
Et une notification push est envoyée
Et une notification in-app s'affiche
Scénario: Alerte 90% budget consommé
Étant donné que mon budget est de 300
Quand je consomme 270 (90%)
Alors je reçois immédiatement un email:
"""
🚨 Alerte Budget - 90% consommé
Campagne: [Nom]
Budget consommé: 270 / 300
Budget restant: 30
ATTENTION: Votre campagne s'arrêtera sous peu.
Actions possibles:
- Recharger le budget
- Laisser la campagne se terminer
"""
Scénario: Alerte budget épuisé (100%)
Étant donné que mon budget est de 300
Quand je consomme les 300 (100%)
Alors je reçois immédiatement un email:
"""
Campagne terminée - Budget épuisé
Campagne: [Nom]
Budget consommé: 300
Durée effective: 12 jours (sur 14 prévus)
Métriques finales:
- Impressions: 6000
- Écoutes complètes: 4000 (67%)
- Coût par écoute: 0.05
Voir le rapport complet: [Lien]
Créer une nouvelle campagne: [Lien]
"""
Et la campagne est automatiquement mise en pause
Et plus aucune diffusion ne se produit
Scénario: Pause manuelle de campagne
Étant donné que ma campagne est active
Et qu'il reste 150 de budget
Quand je clique sur "Mettre en pause"
Alors le statut passe à "En pause"
Et les diffusions s'arrêtent immédiatement
Et le budget de 150 est conservé
Et je peux réactiver la campagne plus tard
Scénario: Reprise campagne pausée
Étant donné que ma campagne est en pause
Et qu'il reste 150 de budget
Quand je clique sur "Reprendre la campagne"
Alors le statut passe à "Active"
Et les diffusions reprennent immédiatement
Et le budget restant de 150 continue de se consommer
Scénario: Prolongation campagne avec recharge
Étant donné que ma campagne se termine dans 2 jours
Et qu'il reste 20 de budget
Quand je clique sur "Prolonger la campagne"
Et que j'ajoute 200 supplémentaires
Alors le budget total passe à 220
Et la date de fin peut être prolongée de 10 jours
Et un nouveau paiement Mangopay de 200 est traité
Scénario: Recharge automatique activée
Étant donné que j'ai configuré la recharge automatique
Et que le seuil est fixé à 10% (30 sur budget 300)
Et que le montant de recharge est 100
Quand le budget restant passe sous 30
Alors une recharge automatique de 100 est déclenchée
Et ma carte bancaire est débitée via Mangopay
Et le budget total passe à budget_restant + 100
Et je reçois un email de confirmation
Scénario: Échec recharge automatique (carte expirée)
Étant donné que la recharge automatique est activée
Et que ma carte bancaire a expiré
Quand le budget passe sous le seuil de 10%
Alors la recharge automatique échoue
Et je reçois un email urgent:
"""
Échec recharge automatique
Votre carte bancaire a été refusée.
Raison probable: carte expirée ou fonds insuffisants
Action requise: Mettez à jour vos informations de paiement
Campagne en pause si budget épuisé: [Lien]
"""
Et la campagne continue jusqu'à épuisement du budget restant
Scénario: Modification ciblage si budget <50% consommé
Étant donné que j'ai consommé 120 sur 300 (40%)
Quand j'essaie de modifier le ciblage géographique
Alors la modification est autorisée
Et le ciblage est mis à jour immédiatement
Et les nouvelles diffusions utilisent le nouveau ciblage
Scénario: Blocage modification ciblage si budget >50% consommé
Étant donné que j'ai consommé 180 sur 300 (60%)
Quand j'essaie de modifier le ciblage géographique
Alors une erreur s'affiche:
"""
Modification bloquée - Budget >50% consommé
Les modifications de ciblage ne sont autorisées que si moins de 50% du budget est consommé.
Raison: Cohérence des métriques et analytics.
Options:
- Créer une nouvelle campagne avec le nouveau ciblage
- Laisser cette campagne se terminer
"""
Scénario: Modification audio nécessite nouvelle validation
Étant donné que ma campagne est active
Quand je veux modifier le fichier audio
Alors un message s'affiche:
"""
Modification audio = Nouvelle validation
Changer l'audio nécessite une nouvelle validation manuelle (24-48h).
Votre campagne sera mise en pause pendant la validation.
Recommandation: Créer une nouvelle campagne pour tester un nouveau créatif.
"""
Scénario: Modification plages horaires autorisée
Étant donné que ma campagne cible 7h-9h et 17h-19h
Quand je modifie pour cibler 12h-14h aussi
Alors la modification est appliquée immédiatement
Et les diffusions suivantes incluent la nouvelle plage
Et aucune re-validation n'est nécessaire
Scénario: Historique consommation budget jour par jour
Étant donné que ma campagne a duré 10 jours
Quand je consulte l'historique
Alors je vois un graphique avec:
| Jour | Consommation | Cumulé |
| 1 | 22 | 22 |
| 2 | 25 | 47 |
| 3 | 20 | 67 |
| ... | ... | ... |
| 10 | 18 | 220 |
Et je peux identifier les pics de consommation
Scénario: Notification fin de campagne programmée
Étant donné que ma campagne se termine le 14/02
Quand la date de fin est atteinte
Alors je reçois un email:
"""
Campagne terminée - Date de fin atteinte
Campagne: [Nom]
Durée: 14 jours (comme prévu)
Budget consommé: 280 / 300
Budget non utilisé: 20
Métriques finales:
- Impressions: 5600
- Écoutes complètes: 3800 (68%)
- ROI: [Calcul si applicable]
Le budget non utilisé (20) sera remboursé sous 5-7 jours.
"""
Scénario: Remboursement budget non utilisé
Étant donné que ma campagne avait 300 de budget
Et qu'elle s'est terminée avec 280 consommés
Quand la campagne se termine (date ou épuisement)
Alors un remboursement de 20 est initié via Mangopay
Et le délai est de 5-7 jours ouvrés
Et je reçois une notification de confirmation
Scénario: Aucun remboursement si budget entièrement consommé
Étant donné que ma campagne avait 300 de budget
Et qu'elle s'est terminée avec 300 consommés
Quand la campagne se termine
Alors aucun remboursement n'est initié
Et le message final indique "Budget entièrement utilisé"
Scénario: Statistiques comparatives budget vs objectif
Étant donné que j'avais défini un objectif de 5000 impressions
Et que mon budget était 300
Quand je consulte les statistiques finales
Alors je vois:
| Métrique | Objectif | Réalisé | Écart |
| Impressions | 5000 | 6000 | +20% |
| Budget | 300 | 280 | -7% |
| Coût/impression | 0.06 | 0.047 | -22% |
Et une analyse " Objectifs dépassés avec budget optimisé"
Scénario: Export rapport financier détaillé
Étant donné que je veux analyser mes dépenses
Quand je clique sur "Exporter rapport financier"
Alors je télécharge un CSV avec:
| Colonne |
| Date/Heure |
| Type écoute |
| Coût unitaire |
| Zone géographique |
| Utilisateur (anonyme)|
| Durée écoutée |
Et je peux l'importer dans Excel pour analyses
Scénario: Tableau de bord multi-campagnes
Étant donné que j'ai 3 campagnes actives
Quand je consulte la vue d'ensemble
Alors je vois un tableau récapitulatif:
| Campagne | Budget | Consommé | % | Jours restants | Projection |
| A | 300 | 220 | 73| 4j | Suffisant |
| B | 500 | 480 | 96| 10j | Épuisé 2j |
| C | 200 | 50 | 25| 20j | Suffisant |
Et un badge alerte rouge sur la campagne B
Scénario: Alerte consolidée multi-campagnes
Étant donné que j'ai 5 campagnes actives
Et que 2 campagnes ont >80% budget consommé
Quand je reçois les notifications
Alors un email consolidé unique est envoyé:
"""
Alerte Budget - 2 campagnes nécessitent attention
Campagne A: 85% consommé, épuisement dans 2j
Campagne C: 92% consommé, épuisement dans 1j
Actions recommandées: [Liens]
"""
Et je ne reçois pas 2 emails séparés (évite spam)
Scénario: Configuration seuils alertes personnalisés
Étant donné que je configure mes préférences d'alerte
Quand je définis les seuils:
| Seuil | Valeur |
| Alerte 1 | 70% |
| Alerte 2 | 85% |
| Alerte 3 | 95% |
Alors je reçois des alertes à 70%, 85% et 95%
Et non aux seuils par défaut 80%, 90%, 100%
Scénario: Désactivation alertes email
Étant donné que je préfère uniquement les notifications in-app
Quand je désactive les alertes email dans mes préférences
Alors je ne reçois plus d'emails d'alerte budget
Mais les notifications in-app continuent
Et les alertes critiques (échec paiement) sont toujours envoyées par email
Plan du Scénario: Couleur jauge selon pourcentage consommé
Étant donné un budget de 300
Quand j'ai consommé <montant> (<pourcentage>%)
Alors la couleur de la jauge est <couleur>
Exemples:
| montant | pourcentage | couleur |
| 100 | 33 | verte |
| 150 | 50 | verte |
| 180 | 60 | orange |
| 240 | 80 | orange |
| 270 | 90 | rouge |
| 285 | 95 | rouge |
| 300 | 100 | rouge |
Plan du Scénario: Projection épuisement selon consommation
Étant donné un budget de 300
Et une consommation actuelle de <consomme>
Et une durée écoulée de <jours_ecoules> jours
Quand je calcule la consommation quotidienne moyenne
Alors elle est de <conso_jour>/jour
Et le budget sera épuisé dans <jours_restants> jours
Exemples:
| consomme | jours_ecoules | conso_jour | jours_restants |
| 100 | 5 | 20 | 10 |
| 200 | 10 | 20 | 5 |
| 150 | 10 | 15 | 10 |
| 270 | 12 | 22.5 | 1.3 |
Plan du Scénario: Alertes envoyées selon seuils
Étant donné un budget de 500
Quand je consomme <montant> (<pourcentage>%)
Alors je reçois une alerte <niveau>
Exemples:
| montant | pourcentage | niveau |
| 350 | 70 | aucune |
| 400 | 80 | alerte 80% |
| 450 | 90 | alerte 90% |
| 500 | 100 | budget épuisé|

View File

@@ -0,0 +1,271 @@
# language: fr
Fonctionnalité: Insertion et fréquence des publicités
En tant que système RoadWave
Je veux insérer les publicités de manière équilibrée et non intrusive
Afin de préserver l'expérience utilisateur tout en monétisant
Contexte:
Étant donné que l'API RoadWave est disponible
Et qu'un utilisateur gratuit est connecté
Scénario: Fréquence par défaut 1 pub / 5 contenus
Étant donné que la fréquence par défaut est configurée à 1/5
Et que je suis un utilisateur gratuit
Quand j'écoute 5 contenus
Alors 1 publicité est insérée après le 5ème contenu
Quand j'écoute 10 contenus
Alors 2 publicités sont insérées (après les contenus 5 et 10)
Scénario: Aucune publicité pour utilisateurs Premium
Étant donné que je suis un utilisateur Premium
Quand j'écoute 100 contenus
Alors aucune publicité n'est insérée
Et je bénéficie d'une expérience sans interruption publicitaire
Scénario: Fréquence paramétrable par admin (1/3)
Étant donné que l'admin configure la fréquence à 1/3
Et que je suis un utilisateur gratuit
Quand j'écoute 6 contenus
Alors 2 publicités sont insérées (après contenus 3 et 6)
Scénario: Fréquence paramétrable par admin (1/10)
Étant donné que l'admin configure la fréquence à 1/10
Et que je suis un utilisateur gratuit
Quand j'écoute 20 contenus
Alors 2 publicités sont insérées (après contenus 10 et 20)
Scénario: Jamais d'interruption d'un contenu en cours
Étant donné que j'écoute un contenu de 10 minutes
Et que je suis à 5 minutes de lecture
Et qu'une publicité devrait être insérée selon la fréquence
Quand le système vérifie l'insertion
Alors la publicité attend la fin du contenu actuel
Et elle s'insère pendant le délai de transition (2s)
Et le contenu n'est jamais interrompu
Scénario: Insertion entre deux contenus uniquement
Étant donné que le contenu "A" se termine
Et que le délai de transition de 2s démarre
Quand le système détecte qu'une publicité doit être insérée
Alors le message "Publicité (30s)" s'affiche
Et la publicité démarre après les 2 secondes
Et l'enchaînement est naturel et fluide
Scénario: Rotation limite 3 fois/jour par utilisateur
Étant donné qu'un utilisateur a entendu la publicité "A" 3 fois aujourd'hui
Quand le système sélectionne une nouvelle publicité à diffuser
Alors la publicité "A" n'est plus éligible pour cet utilisateur aujourd'hui
Et une autre publicité "B" est sélectionnée
Et cela évite la saturation publicitaire
Scénario: Compteur de diffusions par pub et par utilisateur
Étant donné qu'un utilisateur écoute la pub "RestaurantX"
Quand la diffusion se termine
Alors un compteur Redis "pub:RestaurantX:user:123:count" s'incrémente
Et le TTL est de 24h (reset à minuit)
Quand le compteur atteint 3
Alors la pub "RestaurantX" est exclue des prochaines sélections aujourd'hui
Scénario: Limite max 6 pubs/heure par utilisateur
Étant donné qu'un utilisateur a entendu 6 publicités dans la dernière heure
Quand le système devrait insérer une 7ème pub
Alors l'insertion est reportée à l'heure suivante
Et un compteur horaire Redis "pub:user:123:hourly" est vérifié
Et cela évite le spam publicitaire
Scénario: Ciblage géographique prioritaire - Point GPS
Étant donné qu'une publicité cible un point GPS à 2km de ma position
Et qu'une autre publicité cible ma ville entière
Quand le système sélectionne une publicité
Alors la publicité point GPS est priorisée (score géo plus élevé)
Et le ciblage précis est favorisé
Scénario: Ciblage géographique prioritaire - Hiérarchie
Étant donné que 4 publicités sont éligibles:
| Publicité | Zone | Distance |
| A | Point GPS | 1km |
| B | Ville | 0km |
| C | Département | 0km |
| D | National | N/A |
Quand le système sélectionne selon priorité géographique
Alors l'ordre de priorité est: A > B > C > D
Et la publicité A (Point GPS, la plus précise) est diffusée
Scénario: Ciblage centres d'intérêt secondaire
Étant donné que 2 publicités ciblent ma zone géographique:
| Publicité | Tags | Mes jauges |
| A | Automobile | 80% |
| B | Voyage | 40% |
Quand le système applique le score centres d'intérêt
Alors la publicité A est favorisée (meilleur match jauges)
Et le ciblage thématique affine la sélection
Scénario: Ciblage horaire strict
Étant donné qu'une campagne cible uniquement 7h-9h
Et qu'il est 10h30
Quand le système sélectionne une publicité
Alors cette campagne n'est PAS éligible
Et seules les campagnes "toute la journée" ou avec plage horaire actuelle sont considérées
Scénario: Ciblage horaire pendant plage active
Étant donné qu'une campagne cible 7h-9h et 17h-19h
Et qu'il est 8h15
Quand le système sélectionne une publicité
Alors cette campagne est éligible
Et elle peut être diffusée
Scénario: Normalisation volume audio -14 LUFS
Étant donné qu'une publicité est uploadée avec volume trop élevé (-6 LUFS)
Quand le système encode l'audio via FFmpeg
Alors le volume est normalisé automatiquement à -14 LUFS
Et le publicitaire reçoit une notification "Volume audio ajusté pour conformité"
Et cela évite l'effet "pub trop forte" frustrant
Scénario: Validation volume audio lors encodage
Étant donné qu'une publicité est soumise
Quand FFmpeg encode le fichier
Alors une commande loudnorm est appliquée:
```
ffmpeg -i input.mp3 -filter:a loudnorm=I=-14:LRA=11:TP=-1 output.mp3
```
Et le fichier final respecte le standard broadcast -14 LUFS
Scénario: Sélection aléatoire si critères équivalents
Étant donné que 3 publicités ont le même score géo
Et qu'elles ont toutes des jauges centres d'intérêt équivalentes
Et qu'aucune n'a été diffusée 3 fois aujourd'hui
Quand le système sélectionne une publicité
Alors une sélection aléatoire équitable est faite
Et chaque campagne a 33% de chances d'être diffusée
Scénario: Exclusion publicités avec budget épuisé
Étant donné qu'une campagne "A" a épuisé son budget
Et qu'une campagne "B" a encore du budget disponible
Quand le système sélectionne une publicité
Alors seule la campagne "B" est éligible
Et la campagne "A" est automatiquement exclue
Scénario: Exclusion publicités hors dates de campagne
Étant donné qu'une campagne "A" est programmée du 01/02 au 14/02
Et que nous sommes le 20/01
Quand le système sélectionne une publicité
Alors la campagne "A" n'est pas éligible
Et seules les campagnes actives aujourd'hui sont considérées
Scénario: Publicité visible uniquement dans zone géographique
Étant donné qu'une publicité cible "Marseille uniquement"
Et que je suis à Lyon
Quand le système sélectionne une publicité
Alors cette publicité n'est jamais éligible pour moi
Et je ne la verrai jamais tant que je reste à Lyon
Scénario: Tracking compteur horaire avec TTL
Étant donné qu'un utilisateur entend une pub à 10h05
Quand le compteur horaire est incrémenté
Alors la clé Redis "pub:user:123:hourly:2026012110" est créée
Et le TTL est de 1 heure (expire à 11h05)
Et le système compte les pubs dans la fenêtre glissante d'1h
Scénario: Reset compteur quotidien à minuit
Étant donné qu'un utilisateur a entendu la pub "A" 3 fois le 20/01
Quand minuit passe et on est le 21/01
Alors le compteur "pub:A:user:123:count" est expiré (TTL 24h)
Et l'utilisateur peut à nouveau entendre la pub "A" jusqu'à 3 fois
Scénario: Aucune pub si aucune campagne éligible
Étant donné qu'aucune campagne n'a de budget disponible
Ou que toutes les campagnes ont déjà été diffusées 3 fois aujourd'hui
Quand le système devrait insérer une publicité
Alors aucune pub n'est insérée
Et l'enchaînement de contenus continue normalement
Et le prochain contenu démarre directement
Scénario: Priorisation campagnes avec budget important restant
Étant donné que 2 campagnes sont éligibles:
| Campagne | Budget restant | Jours restants |
| A | 500 | 2j |
| B | 50 | 10j |
Quand le système applique la priorisation budgétaire
Alors la campagne A est légèrement favorisée (urgence dépense)
Et cela aide à épuiser les budgets avant fin de campagne
Scénario: Log des sélections pour analytics
Étant donné qu'une publicité "RestaurantX" est sélectionnée
Quand elle est diffusée à l'utilisateur "123"
Alors un événement est loggé en base:
| Champ | Valeur |
| pub_id | RestaurantX |
| user_id | 123 |
| timestamp | 2026-01-21 10:30 |
| zone_geo | Marseille |
| score_geo | 0.85 |
| score_interet | 0.70 |
Et cela permet l'analytics publicitaire
Scénario: Détection changement statut utilisateur (gratuit → premium)
Étant donné que je suis un utilisateur gratuit
Et que j'entends des publicités
Quand je souscris à Premium
Alors le système détecte le changement de statut immédiatement
Et plus aucune publicité n'est insérée dès le prochain contenu
Et mon expérience devient sans pub instantanément
Scénario: Interface admin pour ajuster fréquence globale
Étant donné que je suis admin RoadWave
Quand j'accède aux paramètres publicitaires
Alors je peux ajuster le curseur de fréquence:
| Option | Fréquence |
| 1/3 | Haute (agressif) |
| 1/5 | Standard (défaut)|
| 1/7 | Modérée |
| 1/10 | Faible |
Et le changement s'applique en temps réel à tous les utilisateurs
Scénario: A/B testing fréquence sur cohortes utilisateurs
Étant donné que l'admin active un test A/B
Quand 50% des utilisateurs ont fréquence 1/5
Et 50% des utilisateurs ont fréquence 1/7
Alors les métriques sont trackées séparément:
| Cohorte | Fréquence | Taux désabonnement | Revenus/user |
| A | 1/5 | 2.5% | 0.50 |
| B | 1/7 | 1.8% | 0.40 |
Et l'admin peut identifier la fréquence optimale
Plan du Scénario: Insertion publicité selon fréquence
Étant donné que la fréquence est <frequence>
Quand j'écoute <contenus> contenus
Alors <pubs> publicités sont insérées
Exemples:
| frequence | contenus | pubs |
| 1/3 | 9 | 3 |
| 1/5 | 10 | 2 |
| 1/5 | 25 | 5 |
| 1/7 | 14 | 2 |
| 1/10 | 30 | 3 |
Plan du Scénario: Priorité géographique selon type zone
Étant donné qu'une publicité cible <type_zone>
Quand le système calcule le score géographique
Alors la priorité est <score>
Exemples:
| type_zone | score |
| Point GPS | 1.0 |
| Ville | 0.8 |
| Département | 0.6 |
| Région | 0.4 |
| National | 0.2 |
Plan du Scénario: Exclusion publicité selon compteur quotidien
Étant donné qu'une publicité a été entendue <fois> fois aujourd'hui
Quand le système vérifie l'éligibilité
Alors la publicité est <eligible>
Exemples:
| fois | eligible |
| 0 | éligible |
| 1 | éligible |
| 2 | éligible |
| 3 | non éligible |
| 4 | non éligible |

View File

@@ -0,0 +1,299 @@
# language: fr
Fonctionnalité: Métriques d'engagement et dashboard publicitaire
En tant que publicitaire
Je veux consulter des métriques détaillées en temps réel
Afin d'optimiser mes campagnes et mesurer leur ROI
Contexte:
Étant donné que l'API RoadWave est disponible
Et qu'un compte publicitaire est connecté
Et qu'une campagne active est en cours
Scénario: Dashboard temps réel avec métriques essentielles
Étant donné que ma campagne a généré 1000 diffusions
Quand je consulte le dashboard
Alors je vois les métriques suivantes mises à jour en temps réel:
| Métrique | Valeur |
| Impressions | 1000 |
| Écoutes complètes (>80%)| 400 |
| Taux d'écoute complète | 40% |
| Taux de skip | 60% |
| Durée moyenne d'écoute | 18s |
| Likes | 25 |
| Abonnements | 5 |
| Coût par écoute | 0.05 |
Scénario: Calcul impressions totales
Étant donné que ma publicité a été diffusée 2500 fois
Quand je consulte le dashboard
Alors le compteur "Impressions" affiche 2500
Et il s'incrémente en temps réel à chaque nouvelle diffusion
Scénario: Calcul écoutes complètes (>80%)
Étant donné que ma publicité de 30s a été:
| Durée écoutée | Nombre |
| 25s (83%) | 300 |
| 20s (67%) | 200 |
| 10s (33%) | 150 |
| 5s (17%) | 50 |
Quand je consulte les écoutes complètes
Alors le compteur affiche 300 (uniquement 80%)
Et le taux d'écoute complète est de 43% (300/700)
Scénario: Calcul taux de skip
Étant donné 1000 diffusions totales
Et 400 écoutes complètes
Quand je consulte le taux de skip
Alors il affiche 60% ((1000-400)/1000)
Et il est calculé comme (total - complètes) / total
Scénario: Durée moyenne d'écoute calculée
Étant donné que ma publicité de 30s a été écoutée:
| Durée | Nombre d'utilisateurs |
| 30s | 400 |
| 20s | 300 |
| 10s | 200 |
| 5s | 100 |
Quand je consulte la durée moyenne
Alors le calcul est: (30×400 + 20×300 + 10×200 + 5×100) / 1000
Et le résultat affiché est 21s
Scénario: Métriques de likes sur publicité
Étant donné que 50 utilisateurs ont liké ma publicité
Quand je consulte le dashboard
Alors le compteur "Likes" affiche 50
Et un taux de like de 5% est calculé (50/1000 impressions)
Et cela indique une forte appréciation du contenu
Scénario: Métriques d'abonnements générés
Étant donné que 10 utilisateurs se sont abonnés après avoir entendu ma pub
Quand je consulte le dashboard
Alors le compteur "Abonnements" affiche 10
Et un taux de conversion de 1% est calculé (10/1000)
Et cela représente un engagement très fort
Scénario: Calcul coût par écoute (CPE)
Étant donné que j'ai dépensé 200
Et obtenu 4000 écoutes complètes
Quand je consulte le coût par écoute
Alors le CPE affiché est 0.05 (200/4000)
Et il correspond au tarif standard RoadWave
Scénario: Répartition géographique avec heatmap
Étant donné que ma campagne cible le département du Var
Et que j'ai 1000 diffusions réparties:
| Zone | Diffusions | Pourcentage |
| Toulon | 400 | 40% |
| Hyères | 250 | 25% |
| Fréjus | 200 | 20% |
| Autres | 150 | 15% |
Quand je consulte la heatmap géographique
Alors une carte Leaflet affiche les zones avec intensité proportionnelle
Et Toulon apparaît en rouge foncé (forte concentration)
Et les autres villes en dégradé orange/jaune
Scénario: Répartition horaire avec graphique
Étant donné que ma campagne cible les plages 7h-9h et 17h-19h
Et que j'ai 1000 diffusions:
| Plage horaire | Diffusions |
| 7h-8h | 300 |
| 8h-9h | 250 |
| 17h-18h | 280 |
| 18h-19h | 170 |
Quand je consulte le graphique horaire
Alors un histogramme Chart.js affiche les 4 barres
Et je peux identifier que 7h-8h est le pic d'écoute
Et optimiser mes futures campagnes sur cette plage
Scénario: Taux de complétion par tranche d'âge
Étant donné que ma campagne est Tout Public
Et que j'ai des écoutes sur différentes tranches:
| Tranche d'âge | Écoutes complètes | Total diffusions | Taux |
| 18-24 ans | 120 | 400 | 30% |
| 25-34 ans | 200 | 400 | 50% |
| 35-44 ans | 80 | 200 | 40% |
Quand je consulte l'analyse par âge
Alors je vois que les 25-34 ans ont le meilleur taux (50%)
Et je peux cibler cette tranche pour mes prochaines campagnes
Scénario: Comparatif de campagnes A/B testing
Étant donné que j'ai 2 campagnes actives:
| Campagne | Budget | Écoutes complètes | Taux | CPE |
| A | 300 | 4000 | 40% | 0.075|
| B | 300 | 6000 | 60% | 0.05 |
Quand je consulte le comparatif
Alors je vois que la campagne B performe mieux
Et le tableau recommande "Campagne B: +50% écoutes, -33% CPE"
Et je peux allouer plus de budget à la campagne B
Scénario: Export données CSV pour analyse externe
Étant donné que je veux analyser mes données dans Excel
Quand je clique sur "Exporter CSV"
Alors je télécharge un fichier avec les colonnes:
| Colonne |
| Date |
| Heure |
| Zone géographique |
| Tranche d'âge |
| Durée écoute |
| Skip (Oui/Non) |
| Like (Oui/Non) |
| Abonnement (Oui/Non) |
Et je peux faire des analyses personnalisées
Scénario: Export graphiques interactifs
Étant donné que je consulte le dashboard
Quand je clique sur un graphique Chart.js
Alors je peux zoomer/filtrer interactivement
Et je peux exporter le graphique en PNG
Et l'image est en haute résolution pour présentations
Scénario: Rapport PDF automatique fin de campagne
Étant donné que ma campagne de 14 jours se termine
Quand la date de fin est atteinte
Alors un rapport PDF est généré automatiquement
Et il contient:
| Section |
| Résumé exécutif |
| Métriques clés |
| Graphiques de performance |
| Heatmap géographique |
| Répartition horaire |
| Analyse tranches d'âge |
| Recommandations optimisation |
Et je reçois un email avec le PDF en pièce jointe
Scénario: Métriques temps réel rafraîchies automatiquement
Étant donné que je consulte le dashboard à 10h00
Quand une nouvelle diffusion se produit à 10h01
Alors les métriques sont rafraîchies automatiquement (polling 30s)
Et je vois les nouveaux chiffres sans recharger la page
Et un badge "Mis à jour il y a 15s" s'affiche
Scénario: Alertes performance personnalisées
Étant donné que je configure une alerte "Taux de skip >70%"
Et que ma campagne atteint 72% de skip
Quand le seuil est dépassé
Alors je reçois un email d'alerte:
"""
Alerte Performance - Taux de skip élevé
Votre campagne a un taux de skip de 72%.
Recommandations:
- Réduire la durée de la publicité
- Améliorer l'accroche des 5 premières secondes
- Vérifier le ciblage (audience pertinente?)
"""
Scénario: Benchmark vs moyennes RoadWave
Étant donné que ma campagne a 45% d'écoutes complètes
Quand je consulte le benchmark
Alors je vois "Votre taux: 45% | Moyenne RoadWave: 40%"
Et un badge "📊 Performance: +12% vs moyenne" s'affiche
Et je sais que ma campagne performe au-dessus de la moyenne
Scénario: Coût total consommé vs budget
Étant donné que j'ai un budget de 300
Et que j'ai consommé 220
Quand je consulte le dashboard
Alors je vois une jauge "Budget consommé: 73%" (220/300)
Et le montant restant "80 restants"
Et une projection "Épuisé dans 3 jours à ce rythme"
Scénario: Répartition coûts par type d'écoute
Étant donné que j'ai dépensé 200 avec:
| Type d'écoute | Nombre | Coût unitaire | Total |
| Écoute complète | 3000 | 0.05 | 150 |
| Skip après 5s | 2000 | 0.02 | 40 |
| Skip immédiat | 500 | 0 | 0 |
Quand je consulte la répartition
Alors un graphique camembert affiche:
| Segment | Pourcentage |
| Écoutes complètes | 75% (150) |
| Skips partiels | 20% (40) |
| Skips immédiats | 5% (0) |
Scénario: Évolution performance dans le temps
Étant donné une campagne de 30 jours
Quand je consulte le graphique d'évolution
Alors je vois une courbe Chart.js avec:
| Axe | Donnée |
| X | Jours (1-30) |
| Y | Taux d'écoute complète (%) |
Et je peux identifier les tendances (amélioration/dégradation)
Et les jours avec pics d'engagement
Scénario: Métriques avancées - Taux de réécoute
Étant donné qu'un utilisateur a entendu ma pub 3 fois
Et qu'il l'a écoutée complètement les 3 fois
Quand je consulte les métriques avancées
Alors le "Taux de réécoute" affiche 100%
Et cela indique que le contenu n'est pas perçu comme spam
Et les utilisateurs tolèrent bien la répétition
Scénario: Recommandations automatiques d'optimisation
Étant donné que ma campagne a un taux de skip de 75%
Et que la durée moyenne d'écoute est de 8s sur 30s
Quand je consulte les recommandations
Alors le système suggère:
"""
🔍 Analyse de votre campagne
Problème identifié: Perte d'attention après 8 secondes
Recommandations:
1. Placer votre message clé dans les 5 premières secondes
2. Réduire la durée totale à 15-20 secondes
3. Ajouter un appel à l'action plus tôt
4. Tester un nouveau créatif avec accroche différente
"""
Scénario: Suivi multi-campagnes avec vue consolidée
Étant donné que j'ai 3 campagnes actives simultanément
Quand je consulte la vue consolidée
Alors je vois un tableau récapitulatif:
| Campagne | Budget | Dépensé | Diffusions | Taux complète | CPE |
| A | 300 | 220 | 4000 | 40% | 0.05 |
| B | 500 | 150 | 3000 | 60% | 0.05 |
| C | 200 | 180 | 3600 | 35% | 0.05 |
Et je peux comparer les performances d'un coup d'œil
Plan du Scénario: Calcul taux d'écoute complète
Étant donné <total> diffusions totales
Et <completes> écoutes complètes (80%)
Quand je calcule le taux
Alors le résultat est <taux>%
Exemples:
| total | completes | taux |
| 1000 | 400 | 40 |
| 2000 | 1200 | 60 |
| 500 | 100 | 20 |
| 1000 | 850 | 85 |
Plan du Scénario: Calcul coût par écoute (CPE)
Étant donné un budget dépensé de <depense>
Et <ecoutes> écoutes complètes
Quand je calcule le CPE
Alors le résultat est <cpe>
Exemples:
| depense | ecoutes | cpe |
| 100 | 2000 | 0.05 |
| 300 | 6000 | 0.05 |
| 50 | 1000 | 0.05 |
| 500 | 10000 | 0.05 |
Plan du Scénario: Classification performance vs benchmark
Étant donné un taux d'écoute complète de <taux>%
Et une moyenne RoadWave de 40%
Quand je compare à la moyenne
Alors la performance est <classification>
Exemples:
| taux | classification |
| 60 | Excellente (+50%) |
| 50 | Bonne (+25%) |
| 40 | Moyenne |
| 30 | Faible (-25%) |
| 20 | Très faible (-50%)|

View File

@@ -0,0 +1,261 @@
# language: fr
Fonctionnalité: Validation et modération des publicités
En tant que modérateur RoadWave
Je veux valider manuellement toutes les publicités avant diffusion
Afin de garantir la qualité et la légalité des contenus publicitaires
Contexte:
Étant donné que l'API RoadWave est disponible
Et qu'un modérateur RoadWave est connecté
Scénario: Validation manuelle obligatoire avant diffusion
Étant donné qu'un publicitaire a créé une campagne
Et que le paiement de 300 a été effectué
Quand la campagne est soumise
Alors elle passe en statut "En attente de validation"
Et elle est ajoutée à la file d'attente des modérateurs
Et la diffusion ne démarre PAS avant validation manuelle
Et le publicitaire reçoit un email "Votre campagne est en cours de validation (24-48h)"
Scénario: Délai de validation 24-48h ouvrées
Étant donné qu'une campagne est soumise le lundi 10h
Quand le modérateur la valide le mardi 15h
Alors le délai est de 29h (dans les 48h ouvrées)
Et le publicitaire reçoit une notification "Votre campagne est approuvée"
Scénario: Validation dépassant 48h avec notification
Étant donné qu'une campagne est soumise le lundi 10h
Quand 48h ouvrées se sont écoulées
Et que la campagne n'est toujours pas validée
Alors le publicitaire reçoit un email automatique:
"""
Validation en cours - Délai prolongé
Votre campagne nécessite une analyse approfondie.
Nous vous contacterons sous 24h supplémentaires.
"""
Et un modérateur senior est assigné automatiquement
Scénario: Acceptation de campagne publicitaire
Étant donné qu'une campagne est en attente de validation
Et que l'audio respecte toutes les règles
Quand le modérateur clique sur "Approuver"
Alors le statut passe à "Approuvée"
Et la campagne démarre à la date programmée
Et le publicitaire reçoit un email de confirmation
Et le budget commence à être consommé dès le début
Scénario: Refus de campagne avec motif détaillé
Étant donné qu'une campagne contient du contenu alcool
Quand le modérateur clique sur "Refuser"
Et qu'il sélectionne le motif "Contenu interdit: Alcool"
Et qu'il ajoute le commentaire "La publicité pour l'alcool est interdite en France"
Alors le statut passe à "Refusée"
Et le publicitaire reçoit un email détaillé avec:
| Champ | Valeur |
| Motif | Contenu interdit: Alcool |
| Commentaire | La publicité pour l'alcool est interdite en France |
| Action requise | Modifier votre contenu et soumettre à nouveau |
Et un remboursement automatique de 300 est déclenché
Scénario: Remboursement automatique après refus
Étant donné qu'une campagne à 500 est refusée
Quand le statut passe à "Refusée"
Alors un remboursement Mangopay de 500 est initié automatiquement
Et le délai de remboursement est de 5-7 jours ouvrés
Et le publicitaire reçoit un email "Remboursement en cours"
Scénario: Contenus interdits - Alcool
Étant donné qu'une publicité mentionne "Whisky premium 40°"
Quand le modérateur écoute l'audio
Alors il doit refuser la campagne
Et sélectionner le motif "Contenu interdit: Alcool"
Car la publicité pour l'alcool est interdite en France
Scénario: Contenus interdits - Tabac
Étant donné qu'une publicité mentionne "Cigarettes électroniques"
Quand le modérateur écoute l'audio
Alors il doit refuser la campagne
Et sélectionner le motif "Contenu interdit: Tabac/Vape"
Car la publicité pour le tabac et dérivés est interdite
Scénario: Contenus interdits - Jeux d'argent
Étant donné qu'une publicité mentionne "Gagnez 10 000 - Paris sportifs"
Quand le modérateur écoute l'audio
Alors il doit refuser la campagne
Et sélectionner le motif "Contenu interdit: Jeux d'argent"
Car la publicité pour les jeux d'argent est soumise à régulation stricte
Scénario: Contenus interdits - Politique pendant campagne électorale
Étant donné qu'une publicité politique est soumise
Et que nous sommes en période de campagne électorale officielle
Quand le modérateur écoute l'audio
Alors il doit refuser la campagne
Et sélectionner le motif "Contenu interdit: Publicité politique (période électorale)"
Scénario: Contenus interdits - Contenu sexuel
Étant donné qu'une publicité contient des propos sexuellement explicites
Quand le modérateur écoute l'audio
Alors il doit refuser la campagne
Et sélectionner le motif "Contenu interdit: Contenu sexuel"
Scénario: Contenus interdits - Violence
Étant donné qu'une publicité contient des descriptions violentes
Quand le modérateur écoute l'audio
Alors il doit refuser la campagne
Et sélectionner le motif "Contenu interdit: Violence"
Scénario: Contenu légal autorisé - Commerce local
Étant donné qu'une publicité pour un restaurant local dit "Découvrez notre menu du jour"
Quand le modérateur écoute l'audio
Alors il doit approuver la campagne
Car le contenu est légal et conforme
Scénario: Contenu légal autorisé - Service professionnel
Étant donné qu'une publicité pour un garage dit "Révision complète à partir de 99"
Quand le modérateur écoute l'audio
Alors il doit approuver la campagne
Car le contenu est légal et informatif
Scénario: Critères de validation - Qualité audio
Étant donné qu'une publicité a une qualité audio très basse (bruits, saturation)
Quand le modérateur écoute l'audio
Alors il peut refuser avec le motif "Qualité audio insuffisante"
Et recommander "Veuillez soumettre un fichier audio de meilleure qualité"
Scénario: Critères de validation - Classification d'âge correcte
Étant donné qu'une publicité contient du langage familier
Et qu'elle est classée "Tout public"
Quand le modérateur écoute l'audio
Alors il peut refuser avec le motif "Classification d'âge incorrecte"
Et recommander "Reclasser en 13+ minimum"
Scénario: Critères de validation - Respect réglementation française
Étant donné qu'une publicité fait des promesses mensongères "Perdez 10kg en 1 semaine"
Quand le modérateur écoute l'audio
Alors il doit refuser avec le motif "Non-conformité réglementaire: Publicité mensongère"
Car cela viole la réglementation sur la publicité trompeuse
Scénario: File d'attente modération priorisée
Étant donné que 10 campagnes sont en attente de validation
Et que la campagne A a été soumise il y a 40h
Et que la campagne B a été soumise il y a 2h
Quand le modérateur consulte sa file
Alors la campagne A apparaît en premier (priorité temporelle)
Et un badge "Urgente - >40h" est affiché
Scénario: Dashboard modération - Vue d'ensemble
Étant donné que je suis modérateur
Quand j'accède au dashboard modération publicités
Alors je vois:
| Métrique | Exemple valeur |
| Campagnes en attente | 5 |
| Délai moyen de validation | 28h |
| Campagnes validées aujourd'hui | 12 |
| Campagnes refusées aujourd'hui | 3 |
| Taux d'acceptation | 80% |
Scénario: Transcription automatique pour aide modération
Étant donné qu'une publicité audio est soumise
Quand le système traite l'audio
Alors une transcription automatique est générée via Whisper
Et elle est affichée au modérateur pour faciliter la revue
Et elle permet une recherche par mots-clés (alcool, tabac, etc.)
Scénario: Détection automatique mots-clés interdits
Étant donné qu'une publicité audio est soumise
Quand la transcription contient "whisky" ou "vodka"
Alors un flag automatique " Alcool détecté" est ajouté
Et la campagne est priorisée pour validation manuelle rapide
Et le modérateur est alerté du contenu potentiellement interdit
Scénario: Historique modération publicitaire
Étant donné qu'un publicitaire a eu 2 campagnes refusées
Quand il soumet une 3ème campagne
Alors le modérateur voit l'historique:
| Date | Statut | Motif |
| 2026-01-15 | Refusée | Contenu interdit: Alcool |
| 2026-01-20 | Refusée | Qualité audio faible |
Et il peut en tenir compte dans sa décision
Scénario: Appel possible après refus
Étant donné que ma campagne a été refusée pour "Classification incorrecte"
Quand je conteste la décision via le formulaire d'appel
Alors un modérateur senior revoit la campagne
Et il peut approuver si la classification est en fait correcte
Et le délai de réponse est de 48-72h
Scénario: Notification temps réel pour modérateurs
Étant donné que je suis modérateur connecté
Quand une nouvelle campagne est soumise
Alors je reçois une notification in-app
Et le compteur "Campagnes en attente" s'incrémente en temps réel
Et je peux cliquer pour consulter immédiatement
Scénario: Statistiques conformité par catégorie
Étant donné que je suis admin modération
Quand je consulte les statistiques mensuelles
Alors je vois les motifs de refus:
| Motif | Nombre | Pourcentage |
| Alcool | 15 | 30% |
| Qualité audio | 12 | 24% |
| Classification erronée | 10 | 20% |
| Publicité mensongère | 8 | 16% |
| Autres | 5 | 10% |
Scénario: Export rapport modération
Étant donné que je suis modérateur senior
Quand j'exporte le rapport mensuel
Alors je reçois un fichier CSV avec:
| Colonne |
| Campagne ID |
| Publicitaire |
| Date soumission |
| Date décision |
| Statut |
| Motif (si refus) |
| Modérateur |
Et je peux l'analyser dans Excel
Scénario: Validation partielle avec demande modification
Étant donné qu'une campagne a un contenu acceptable
Mais que la classification d'âge est incorrecte
Quand le modérateur clique sur "Demander modification"
Alors le publicitaire reçoit un email:
"""
Modification requise
Votre campagne nécessite un ajustement:
- Reclasser de "Tout public" à "13+"
Veuillez modifier et soumettre à nouveau.
Budget conservé, pas de remboursement.
"""
Et le statut devient "Modification requise"
Et le publicitaire peut modifier sans repayer
Plan du Scénario: Contenus interdits automatiquement détectés
Étant donné qu'une publicité contient le mot <mot_cle>
Quand la transcription automatique est analysée
Alors un flag <flag> est ajouté
Et le motif de refus suggéré est <motif>
Exemples:
| mot_cle | flag | motif |
| whisky | Alcool | Contenu interdit: Alcool |
| vodka | Alcool | Contenu interdit: Alcool |
| cigarette | Tabac | Contenu interdit: Tabac |
| casino | Jeux argent | Contenu interdit: Jeux |
| paris sportifs | Jeux argent | Contenu interdit: Jeux |
Plan du Scénario: Délais de validation selon soumission
Étant donné qu'une campagne est soumise <jour> à <heure>
Quand elle est validée <delai> heures plus tard
Alors le statut est <conformite>
Exemples:
| jour | heure | delai | conformite |
| Lundi | 10h | 24 | Dans les délais (24h) |
| Lundi | 10h | 48 | Dans les délais (48h) |
| Lundi | 10h | 50 | Hors délais (>48h) |
| Vendredi| 16h | 72 | Dans les délais (we) |