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.
222 lines
12 KiB
Gherkin
222 lines
12 KiB
Gherkin
# language: fr
|
|
|
|
@api @audio-guides @advertising @pedestrian @mvp
|
|
Fonctionnalité: Auto-play publicités en mode piéton uniquement
|
|
|
|
En tant qu'utilisateur piéton
|
|
Je peux recevoir des publicités audio en auto-play à proximité de commerces
|
|
Afin que les commerçants puissent promouvoir leurs offres de manière contextualisée
|
|
|
|
Contexte:
|
|
Étant donné que le système de publicité respecte les règles suivantes:
|
|
| Règle | Valeur |
|
|
| Auto-play autorisé uniquement en mode | Piéton |
|
|
| Durée max d'une publicité | 30 secondes |
|
|
| Fréquence max par commerce | 1 par jour |
|
|
| Distance min entre 2 pubs différentes | 200 mètres |
|
|
| Nombre max de pubs par heure | 3 |
|
|
| Possibilité de skip après | 5 secondes |
|
|
|
|
Scénario: Déclenchement automatique d'une publicité en mode piéton
|
|
Étant donné un utilisateur "alice@roadwave.fr" en mode piéton
|
|
Et elle marche dans la rue avec l'application active
|
|
Quand elle passe à 30 mètres du café "Le Parisien" avec publicité active
|
|
Alors la publicité audio "Café Le Parisien - 10% de réduction" démarre automatiquement
|
|
Et une notification visuelle s'affiche:
|
|
| Élément | Contenu |
|
|
| Icône | Logo du café |
|
|
| Titre | Publicité - Le Parisien |
|
|
| Distance | À 30m de vous |
|
|
| Action | [Passer] disponible après 5s |
|
|
| Durée | 0:25 |
|
|
Et l'audio en cours (si existant) est mis en pause
|
|
Et un événement "AD_AUTOPLAY_TRIGGERED" est enregistré
|
|
Et la métrique "ads.autoplay.triggered" est incrémentée
|
|
|
|
Scénario: Aucun auto-play en mode voiture
|
|
Étant donné un utilisateur "bob@roadwave.fr" en mode voiture
|
|
Et il roule à 40 km/h avec l'application active
|
|
Quand il passe à 30 mètres d'un commerce avec publicité active
|
|
Alors aucune publicité n'est déclenchée automatiquement
|
|
Et la publicité peut être affichée dans la liste "Publicités à proximité"
|
|
Et l'utilisateur peut choisir manuellement de l'écouter
|
|
Et un événement "AD_SKIPPED_CAR_MODE" est enregistré
|
|
Et la métrique "ads.skipped.car_mode" est incrémentée
|
|
|
|
Scénario: Aucun auto-play en mode vélo
|
|
Étant donné un utilisateur "charlie@roadwave.fr" en mode vélo
|
|
Et il roule à 15 km/h avec l'application active
|
|
Quand il passe à 30 mètres d'un commerce avec publicité active
|
|
Alors aucune publicité n'est déclenchée automatiquement
|
|
Et la sécurité de l'utilisateur à vélo est préservée
|
|
Et un événement "AD_SKIPPED_CYCLING_MODE" est enregistré
|
|
Et la métrique "ads.skipped.cycling_mode" est incrémentée
|
|
|
|
Scénario: Skip d'une publicité après 5 secondes
|
|
Étant donné un utilisateur "david@roadwave.fr" en mode piéton
|
|
Et une publicité a démarré automatiquement il y a 6 secondes
|
|
Quand l'utilisateur clique sur le bouton "Passer"
|
|
Alors la publicité s'arrête immédiatement
|
|
Et l'audio en cours précédent reprend (si existant)
|
|
Et un événement "AD_SKIPPED_BY_USER" est enregistré avec temps_ecoute: 6s
|
|
Et la métrique "ads.skipped.by_user" est incrémentée
|
|
Et le commerçant est facturé pour 6 secondes d'écoute seulement
|
|
|
|
Scénario: Bouton "Passer" désactivé pendant les 5 premières secondes
|
|
Étant donné un utilisateur "eve@roadwave.fr" en mode piéton
|
|
Et une publicité vient de démarrer
|
|
Quand l'utilisateur clique sur le bouton "Passer" à T+2 secondes
|
|
Alors le bouton est grisé et non cliquable
|
|
Et un message s'affiche: "Disponible dans 3 secondes"
|
|
Et un compteur à rebours est visible: 3... 2... 1...
|
|
Alors à T+5 secondes, le bouton devient actif
|
|
Et un événement "AD_SKIP_ATTEMPTED_TOO_EARLY" est enregistré
|
|
Et la métrique "ads.skip.too_early" est incrémentée
|
|
|
|
Scénario: Publicité écoutée en entier
|
|
Étant donné un utilisateur "frank@roadwave.fr" en mode piéton
|
|
Et une publicité de 25 secondes a démarré automatiquement
|
|
Quand l'utilisateur écoute la publicité jusqu'à la fin sans cliquer sur "Passer"
|
|
Alors la publicité se termine naturellement
|
|
Et l'audio en cours précédent reprend automatiquement
|
|
Et un événement "AD_COMPLETED" est enregistré avec temps_ecoute: 25s
|
|
Et la métrique "ads.completed" est incrémentée
|
|
Et le commerçant est facturé pour la publicité complète (tarif plein)
|
|
|
|
Scénario: Limitation à 3 publicités par heure
|
|
Étant donné un utilisateur "grace@roadwave.fr" en mode piéton
|
|
Et elle a déjà écouté 3 publicités dans la dernière heure:
|
|
| Commerce | Temps écoulé |
|
|
| Café Le Parisien | Il y a 10min |
|
|
| Boulangerie Paul | Il y a 30min |
|
|
| Restaurant Tokyo | Il y a 50min |
|
|
Quand elle passe à 30 mètres d'un 4ème commerce avec publicité
|
|
Alors aucune publicité n'est déclenchée automatiquement
|
|
Et un compteur s'affiche discrètement: "Prochaine pub disponible dans 10 min"
|
|
Et un événement "AD_RATE_LIMITED" est enregistré
|
|
Et la métrique "ads.rate_limited" est incrémentée
|
|
|
|
Scénario: Limitation à 1 publicité par commerce par jour
|
|
Étant donné un utilisateur "henry@roadwave.fr" en mode piéton
|
|
Et il a déjà écouté la publicité du "Café Le Parisien" ce matin à 10h
|
|
Quand il repasse devant le même café à 16h
|
|
Alors aucune publicité n'est déclenchée automatiquement
|
|
Et le café n'apparaît pas dans la liste "Publicités à proximité"
|
|
Et un événement "AD_ALREADY_SHOWN_TODAY" est enregistré
|
|
Et la métrique "ads.deduplication.same_day" est incrémentée
|
|
|
|
Scénario: Distance minimale de 200m entre 2 publicités différentes
|
|
Étant donné un utilisateur "iris@roadwave.fr" en mode piéton
|
|
Et elle vient d'écouter une publicité du "Café Le Parisien" il y a 1 minute
|
|
Quand elle marche et passe à 50 mètres de la "Boulangerie Paul" (150m du café)
|
|
Alors aucune publicité n'est déclenchée automatiquement
|
|
Et un événement "AD_TOO_CLOSE_TO_PREVIOUS" est enregistré
|
|
Et la métrique "ads.skipped.too_close" est incrémentée
|
|
Quand elle continue et passe à 250 mètres de la "Librairie Gibert" (250m du café)
|
|
Alors la publicité de la librairie peut être déclenchée
|
|
|
|
Scénario: Désactivation complète des publicités (utilisateur Premium)
|
|
Étant donné un utilisateur "jack@roadwave.fr" Premium en mode piéton
|
|
Et il a désactivé les publicités dans ses paramètres
|
|
Quand il passe à 30 mètres de commerces avec publicités actives
|
|
Alors aucune publicité n'est jamais déclenchée
|
|
Et aucune publicité n'apparaît dans la liste "Publicités à proximité"
|
|
Et un événement "AD_BLOCKED_PREMIUM" est enregistré
|
|
Et la métrique "ads.blocked.premium" est incrémentée
|
|
|
|
Scénario: Mise en pause de l'audio en cours lors du déclenchement d'une pub
|
|
Étant donné un utilisateur "kate@roadwave.fr" en mode piéton
|
|
Et elle écoute un podcast "Histoire de Paris" à la position 12min 30s
|
|
Quand une publicité se déclenche automatiquement
|
|
Alors le podcast est mis en pause immédiatement
|
|
Et la position de lecture est sauvegardée: 12min 30s
|
|
Et la publicité démarre
|
|
Quand la publicité se termine (skip ou écoute complète)
|
|
Alors le podcast reprend automatiquement à la position 12min 30s
|
|
Et un événement "AD_CONTENT_PAUSED_RESUMED" est enregistré
|
|
Et la métrique "ads.content.paused_resumed" est incrémentée
|
|
|
|
Scénario: Ciblage géographique précis de la publicité
|
|
Étant donné un commerçant "Le Parisien" avec publicité active
|
|
Et il a configuré un rayon de déclenchement de 50 mètres
|
|
Et un utilisateur "luke@roadwave.fr" en mode piéton
|
|
Quand l'utilisateur est à 60 mètres du commerce
|
|
Alors aucune publicité n'est déclenchée
|
|
Quand l'utilisateur marche et arrive à 45 mètres du commerce
|
|
Alors la publicité se déclenche automatiquement
|
|
Et un événement "AD_GEO_TRIGGERED" est enregistré avec distance: 45m
|
|
Et la métrique "ads.geo.triggered" est incrémentée
|
|
|
|
Scénario: Publicité contextuelle basée sur les intérêts de l'utilisateur
|
|
Étant donné un utilisateur "mary@roadwave.fr" en mode piéton
|
|
Et ses jauges d'intérêts sont:
|
|
| Catégorie | Niveau |
|
|
| Gastronomie | 85% |
|
|
| Culture | 60% |
|
|
| Sport | 20% |
|
|
Et deux commerces ont des publicités actives à proximité:
|
|
| Commerce | Catégorie | Distance |
|
|
| Restaurant Le Gourmet | Gastronomie | 40m |
|
|
| Salle de sport FitClub| Sport | 35m |
|
|
Quand l'utilisateur passe à proximité des deux commerces
|
|
Alors la publicité du restaurant est priorisée et déclenchée
|
|
Et la publicité de la salle de sport est ignorée (faible intérêt)
|
|
Et un événement "AD_INTEREST_MATCHED" est enregistré avec categorie: "gastronomie", score: 85
|
|
Et la métrique "ads.interest_matching.applied" est incrémentée
|
|
|
|
Scénario: Affichage d'informations complémentaires pendant la publicité
|
|
Étant donné un utilisateur "nathan@roadwave.fr" en mode piéton
|
|
Et une publicité du "Café Le Parisien" est en cours de lecture
|
|
Quand l'utilisateur consulte l'écran
|
|
Alors il voit les informations suivantes:
|
|
| Élément | Contenu |
|
|
| Logo du commerce | [Image] |
|
|
| Nom du commerce | Café Le Parisien |
|
|
| Type d'établissement | Café-Brasserie |
|
|
| Distance | À 30m de vous |
|
|
| Itinéraire | [Bouton "Y aller"] |
|
|
| Offre spéciale | 10% de réduction avec ce code: ROADWAVE10|
|
|
| Horaires | Ouvert maintenant - Ferme à 22h |
|
|
| Note | 4.5/5 (230 avis) |
|
|
Et l'utilisateur peut cliquer sur "Y aller" pour lancer la navigation
|
|
Et un événement "AD_INFO_DISPLAYED" est enregistré
|
|
|
|
Scénario: Tracking de la conversion (visite effective du commerce)
|
|
Étant donné un utilisateur "olive@roadwave.fr" en mode piéton
|
|
Et elle a écouté la publicité du "Café Le Parisien" il y a 5 minutes
|
|
Quand elle clique sur "Y aller" et se rend au café
|
|
Et entre dans un rayon de 10 mètres du café
|
|
Alors un événement "AD_CONVERSION_VISIT" est enregistré
|
|
Et la métrique "ads.conversions.visits" est incrémentée
|
|
Et le commerçant voit cette conversion dans ses statistiques
|
|
Et une notification discrète s'affiche: "Profitez de votre réduction avec le code ROADWAVE10"
|
|
|
|
Scénario: Métriques de performance des publicités pour les commerçants
|
|
Étant donné un commerçant "Le Parisien" avec publicité active depuis 7 jours
|
|
Quand le commerçant consulte ses statistiques
|
|
Alors il voit les métriques suivantes:
|
|
| Métrique | Valeur |
|
|
| Nombre d'impressions (déclenchements)| 450 |
|
|
| Taux d'écoute complète | 35% |
|
|
| Taux de skip moyen | 65% |
|
|
| Durée moyenne d'écoute | 12s |
|
|
| Nombre de clics "Y aller" | 25 |
|
|
| Nombre de visites confirmées | 18 |
|
|
| Taux de conversion | 4% |
|
|
| Coût total | 45€ |
|
|
| Coût par visite | 2.50€ |
|
|
Et les métriques sont mises à jour en temps réel
|
|
|
|
Scénario: A/B testing des publicités pour optimisation
|
|
Étant donné un commerçant "Le Parisien" avec 2 versions de publicité:
|
|
| Version | Description | Durée |
|
|
| A | Voix masculine, tonalité formelle | 25s |
|
|
| B | Voix féminine, tonalité décontractée | 25s |
|
|
Quand le système diffuse aléatoirement les 2 versions (50/50)
|
|
Alors les métriques sont collectées séparément:
|
|
| Métrique | Version A | Version B |
|
|
| Taux d'écoute complète | 32% | 42% |
|
|
| Taux de conversion | 3.5% | 5.2% |
|
|
Et le commerçant peut choisir de diffuser uniquement la version B
|
|
Et un événement "AD_AB_TEST_COMPLETED" est enregistré
|