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:
@@ -0,0 +1,221 @@
|
||||
# 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é
|
||||
Reference in New Issue
Block a user