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.
227 lines
11 KiB
Gherkin
227 lines
11 KiB
Gherkin
# language: fr
|
|
|
|
@api @navigation @anti-spam @mvp
|
|
Fonctionnalité: Quota et cooldown pour contenus géolocalisés
|
|
|
|
En tant que système de navigation
|
|
Je veux limiter les notifications géolocalisées à 6 par heure
|
|
Et appliquer un cooldown de 10 minutes après refus
|
|
Afin d'éviter le spam et préserver l'expérience utilisateur
|
|
|
|
Contexte:
|
|
Étant donné un utilisateur authentifié en mode voiture
|
|
Et la géolocalisation est activée
|
|
|
|
# ============================================================================
|
|
# QUOTA 6 NOTIFICATIONS / HEURE (fenêtre glissante)
|
|
# ============================================================================
|
|
|
|
Scénario: Première notification de l'heure sans quota atteint
|
|
Étant donné l'utilisateur n'a reçu aucune notification géolocalisée dans les 60 dernières minutes
|
|
Et un contenu géolocalisé déclenche une notification (ETA = 7s)
|
|
Quand la notification est envoyée
|
|
Alors le compteur de quota doit être incrémenté à 1/6
|
|
Et un timestamp doit être enregistré pour cette notification
|
|
Et la notification doit être affichée normalement
|
|
|
|
Scénario: Notifications multiples sous le quota
|
|
Étant donné l'utilisateur a reçu 3 notifications dans les 60 dernières minutes :
|
|
| timestamp | contenu_id |
|
|
| 2026-02-03 14:10:00 | content-1 |
|
|
| 2026-02-03 14:25:00 | content-2 |
|
|
| 2026-02-03 14:40:00 | content-3 |
|
|
Et il est maintenant 14:50:00
|
|
Et un nouveau contenu géolocalisé déclenche une notification
|
|
Quand la notification est évaluée
|
|
Alors le compteur doit afficher 4/6
|
|
Et la notification doit être envoyée normalement
|
|
|
|
Scénario: 6ème notification - dernière autorisée
|
|
Étant donné l'utilisateur a reçu 5 notifications dans l'heure
|
|
Et un nouveau contenu géolocalisé déclenche une notification
|
|
Quand la notification est envoyée
|
|
Alors le compteur doit afficher 6/6
|
|
Et la notification doit être affichée normalement
|
|
Et un flag "quota_limit_reached" doit être ajouté aux métriques
|
|
|
|
Scénario: 7ème notification - quota dépassé
|
|
Étant donné l'utilisateur a reçu 6 notifications dans les 60 dernières minutes
|
|
Et un nouveau contenu géolocalisé déclenche une notification
|
|
Quand le système évalue le quota
|
|
Alors la notification ne doit PAS être envoyée
|
|
Et le contenu doit être ajouté silencieusement à la file d'attente
|
|
Et un événement "notification_blocked_quota" doit être loggé
|
|
Et l'utilisateur ne doit voir aucun indicateur visuel de blocage
|
|
|
|
Scénario: Fenêtre glissante - libération progressive du quota
|
|
Étant donné l'utilisateur a reçu 6 notifications :
|
|
| timestamp | contenu_id |
|
|
| 2026-02-03 13:00:00 | content-1 |
|
|
| 2026-02-03 13:15:00 | content-2 |
|
|
| 2026-02-03 13:30:00 | content-3 |
|
|
| 2026-02-03 13:45:00 | content-4 |
|
|
| 2026-02-03 14:00:00 | content-5 |
|
|
| 2026-02-03 14:10:00 | content-6 |
|
|
Et il est maintenant 14:05:00 (la 1ère notification a >60 min)
|
|
Et un nouveau contenu déclenche une notification
|
|
Quand le système calcule le quota sur les 60 dernières minutes
|
|
Alors seules 5 notifications doivent être comptées (13:15 à 14:10)
|
|
Et le compteur doit afficher 6/6 (5 + nouvelle = 6)
|
|
Et la notification doit être envoyée
|
|
|
|
Scénario: Reset complet après 60 minutes sans notification
|
|
Étant donné l'utilisateur a reçu 6 notifications entre 12:00 et 12:50
|
|
Et il est maintenant 13:55 (>60 min après la dernière)
|
|
Quand un nouveau contenu déclenche une notification
|
|
Alors le compteur doit être reset à 1/6
|
|
Et la notification doit être envoyée normalement
|
|
|
|
# ============================================================================
|
|
# EXCEPTION AUDIO-GUIDES (1 quota = toutes les séquences)
|
|
# ============================================================================
|
|
|
|
Scénario: Audio-guide multi-séquences compte pour 1 seul quota
|
|
Étant donné l'utilisateur a reçu 5 notifications normales dans l'heure
|
|
Et l'utilisateur démarre un audio-guide avec 8 séquences géolocalisées
|
|
Quand la 1ère séquence de l'audio-guide déclenche une notification
|
|
Alors le quota doit être incrémenté à 6/6
|
|
Quand les 7 séquences suivantes déclenchent des notifications
|
|
Alors le quota doit rester à 6/6
|
|
Et toutes les notifications d'audio-guide doivent être envoyées
|
|
Et un flag "audio_guide_exception" doit être loggé
|
|
|
|
Scénario: Audio-guide suivi de contenus normaux bloqués
|
|
Étant donné l'utilisateur a reçu 5 notifications normales
|
|
Et l'utilisateur a terminé un audio-guide de 6 séquences (compte pour 1 quota)
|
|
Et le quota est maintenant 6/6
|
|
Quand un contenu normal déclenche une notification
|
|
Alors la notification doit être bloquée (quota dépassé)
|
|
Et le contenu doit être ajouté à la file d'attente
|
|
|
|
Scénario: Plusieurs audio-guides dans l'heure
|
|
Étant donné l'utilisateur a démarré 3 audio-guides dans l'heure :
|
|
| timestamp | audio_guide_id | sequences |
|
|
| 2026-02-03 13:00:00 | guide-1 | 5 |
|
|
| 2026-02-03 13:30:00 | guide-2 | 8 |
|
|
| 2026-02-03 14:00:00 | guide-3 | 4 |
|
|
Quand le système calcule le quota
|
|
Alors chaque audio-guide doit compter pour 1 quota
|
|
Et le compteur doit afficher 3/6
|
|
Et 3 contenus normaux supplémentaires peuvent être notifiés
|
|
|
|
# ============================================================================
|
|
# COOLDOWN 10 MINUTES APRÈS REFUS
|
|
# ============================================================================
|
|
|
|
Scénario: Notification ignorée déclenche cooldown de 10 minutes
|
|
Étant donné une notification géolocalisée est affichée à 14:00:00
|
|
Et le compteur de 7 secondes se termine sans action utilisateur
|
|
Quand le délai de 7 secondes expire
|
|
Alors un cooldown de 10 minutes doit être activé
|
|
Et un timestamp "cooldown_until: 14:10:00" doit être enregistré
|
|
Et la notification doit disparaître
|
|
|
|
Scénario: Notifications bloquées pendant le cooldown
|
|
Étant donné un cooldown est actif jusqu'à 14:10:00
|
|
Et il est maintenant 14:05:00
|
|
Et 3 contenus géolocalisés déclenchent des notifications
|
|
Quand le système évalue les conditions
|
|
Alors aucune notification ne doit être affichée
|
|
Et les 3 contenus doivent être ajoutés silencieusement à la file d'attente
|
|
Et un événement "notification_blocked_cooldown" doit être loggé pour chacun
|
|
|
|
Scénario: Fin du cooldown - reprise normale
|
|
Étant donné un cooldown actif jusqu'à 14:10:00
|
|
Et il est maintenant 14:10:05 (cooldown expiré)
|
|
Et un contenu géolocalisé déclenche une notification
|
|
Quand le système évalue les conditions
|
|
Alors le cooldown doit être considéré comme expiré
|
|
Et la notification doit être envoyée normalement
|
|
Et le flag "post_cooldown" doit être ajouté aux métriques
|
|
|
|
Scénario: Validation notification pendant le countdown annule le cooldown
|
|
Étant donné une notification affichée avec compteur à 4 secondes restantes
|
|
Quand l'utilisateur appuie sur "Écouter maintenant"
|
|
Alors le contenu doit démarrer
|
|
Et aucun cooldown ne doit être appliqué
|
|
Et la prochaine notification peut être envoyée normalement (sous réserve du quota)
|
|
|
|
Scénario: Cooldown + Quota simultanés
|
|
Étant donné l'utilisateur a reçu 6 notifications dans l'heure (quota atteint)
|
|
Et la dernière notification a été ignorée (cooldown actif pour 10 min)
|
|
Et il est maintenant 5 minutes plus tard
|
|
Quand un nouveau contenu déclenche une notification
|
|
Alors la notification doit être bloquée pour les 2 raisons :
|
|
| raison | statut |
|
|
| quota_exceeded | true |
|
|
| cooldown_active | true |
|
|
Et le contenu doit être ajouté à la file d'attente
|
|
Et les deux raisons doivent être loggées
|
|
|
|
# ============================================================================
|
|
# CAS LIMITES & EDGE CASES
|
|
# ============================================================================
|
|
|
|
Scénario: Cooldown ne s'applique pas en mode piéton
|
|
Étant donné l'utilisateur est en mode piéton
|
|
Et une notification push géolocalisée est ignorée
|
|
Quand la notification expire
|
|
Alors aucun cooldown ne doit être appliqué
|
|
Car en mode piéton les notifications sont opt-in et moins intrusives
|
|
|
|
Scénario: Changement de mode pendant cooldown (voiture → piéton)
|
|
Étant donné un cooldown actif en mode voiture jusqu'à 14:20:00
|
|
Et il est maintenant 14:12:00 (cooldown encore actif)
|
|
Quand l'utilisateur bascule en mode piéton
|
|
Alors le cooldown doit être immédiatement annulé
|
|
Et les notifications piéton doivent être activées normalement
|
|
|
|
Scénario: Déconnexion/reconnexion pendant cooldown
|
|
Étant donné un cooldown actif jusqu'à 15:30:00
|
|
Quand l'utilisateur se déconnecte puis se reconnecte à 15:20:00
|
|
Alors le cooldown doit être persisté (Redis ou DB)
|
|
Et le cooldown doit toujours être actif jusqu'à 15:30:00
|
|
Et les notifications doivent rester bloquées
|
|
|
|
Scénario: Quota reset à minuit vs fenêtre glissante
|
|
Étant donné le système utilise une fenêtre glissante de 60 minutes
|
|
Et l'utilisateur a reçu 6 notifications entre 23:30 et 23:55
|
|
Quand minuit passe et il est 00:05
|
|
Alors le quota doit toujours être calculé sur les 60 dernières minutes
|
|
Et les 6 notifications doivent encore être comptées
|
|
Et aucune notification supplémentaire ne peut être envoyée avant 00:30
|
|
|
|
# ============================================================================
|
|
# MÉTRIQUES & ANALYTICS
|
|
# ============================================================================
|
|
|
|
Scénario: Logging des blocages quota pour optimisation
|
|
Étant donné le quota est atteint (6/6)
|
|
Et 5 contenus tentent de déclencher une notification dans l'heure suivante
|
|
Quand ces notifications sont bloquées
|
|
Alors un événement analytics doit être loggé pour chacune :
|
|
| event_type | notification_blocked_quota |
|
|
| content_id | content-xyz |
|
|
| user_quota_current | 6 |
|
|
| user_quota_max | 6 |
|
|
| timestamp_blocked | 2026-02-03 14:30:00 |
|
|
| added_to_queue | true |
|
|
Et ces métriques doivent alimenter le dashboard de monitoring
|
|
|
|
Scénario: Métriques de cooldown par utilisateur
|
|
Étant donné un utilisateur ignore 3 notifications dans la journée
|
|
Quand le système analyse le comportement
|
|
Alors les métriques suivantes doivent être calculées :
|
|
| cooldowns_triggered_today | 3 |
|
|
| avg_cooldown_per_user | 2.1 |
|
|
| ignore_rate | 50% |
|
|
Et ces données doivent être utilisées pour ajuster l'algorithme de recommandation
|
|
|
|
Scénario: A/B testing - quota 6 vs 8 vs 10 par heure
|
|
Étant donné l'utilisateur est dans le groupe de test "quota_8"
|
|
Et le système teste différentes valeurs de quota
|
|
Quand le système évalue les notifications
|
|
Alors le quota max doit être de 8 au lieu de 6
|
|
Et le groupe de test doit être loggé dans les événements
|
|
Et les métriques d'engagement doivent être comparées entre groupes
|