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.
311 lines
13 KiB
Gherkin
311 lines
13 KiB
Gherkin
# language: fr
|
||
|
||
Fonctionnalité: Sauvegarde et reprise de progression audio-guide
|
||
En tant qu'utilisateur
|
||
Je veux que ma progression soit sauvegardée automatiquement
|
||
Afin de pouvoir reprendre mon audio-guide là où je me suis arrêté
|
||
|
||
Contexte:
|
||
Étant donné que l'application RoadWave est démarrée
|
||
Et que l'utilisateur "jean@example.com" est connecté
|
||
|
||
# 16.5 - Sauvegarde de progression
|
||
|
||
Scénario: Sauvegarde automatique toutes les 10 secondes
|
||
Étant donné qu'un audio-guide "Visite du Louvre" est en cours
|
||
Et que la séquence 3 est à la position 1:24
|
||
Quand 10 secondes s'écoulent
|
||
Alors la progression est sauvegardée automatiquement:
|
||
| donnée | valeur |
|
||
| audio_guide_id | louvre_123 |
|
||
| sequence_actuelle | 3 |
|
||
| position_audio | 1:24 |
|
||
| timestamp | 2026-01-22 14:35:42 |
|
||
| sequences_ecoutees | [1, 2] |
|
||
|
||
Scénario: Sauvegarde locale (SQLite) pour rapidité
|
||
Étant donné qu'une sauvegarde est déclenchée
|
||
Quand la progression est enregistrée
|
||
Alors les données sont écrites en SQLite local
|
||
Et l'écriture prend moins de 50ms
|
||
Et l'application reste fluide
|
||
|
||
Scénario: Synchronisation cloud en arrière-plan
|
||
Étant donné qu'une sauvegarde locale est effectuée
|
||
Quand 30 secondes s'écoulent
|
||
Alors la progression est synchronisée vers PostgreSQL cloud
|
||
Et la synchronisation s'effectue en arrière-plan
|
||
Et elle n'impacte pas les performances
|
||
|
||
Scénario: Sauvegarde immédiate lors de la fermeture
|
||
Étant donné qu'un audio-guide est en cours à la séquence 4 position 2:15
|
||
Quand l'utilisateur ferme l'application
|
||
Alors la progression est sauvegardée immédiatement (local + cloud)
|
||
Et les données sont écrites avant la fermeture complète
|
||
|
||
Scénario: Sauvegarde des séquences complétées
|
||
Étant donné qu'un audio-guide de 12 séquences est en cours
|
||
Et que les séquences 1, 2, 4, 5 ont été écoutées à >80%
|
||
Quand la progression est sauvegardée
|
||
Alors les séquences complétées sont enregistrées:
|
||
"""json
|
||
{
|
||
"audio_guide_id": "louvre_123",
|
||
"completed_sequences": [1, 2, 4, 5],
|
||
"current_sequence": 6,
|
||
"current_position": "0:42",
|
||
"last_played_at": "2026-01-22T14:35:42Z"
|
||
}
|
||
"""
|
||
|
||
Scénario: Historique des écoutes pour statistiques
|
||
Étant donné qu'un utilisateur a écouté 3 séquences d'un audio-guide
|
||
Quand les données sont sauvegardées
|
||
Alors l'historique d'écoute inclut:
|
||
| sequence_id | started_at | completed_at | completion_rate |
|
||
| 1 | 2026-01-22 14:10:00 | 2026-01-22 14:12:15 | 100% |
|
||
| 2 | 2026-01-22 14:12:20 | 2026-01-22 14:14:08 | 100% |
|
||
| 3 | 2026-01-22 14:14:15 | 2026-01-22 14:17:45 | 92% |
|
||
|
||
# 16.6 - Reprise de progression
|
||
|
||
Scénario: Popup de reprise au redémarrage
|
||
Étant donné que l'utilisateur a quitté l'app à la séquence 6 position 2:34
|
||
Quand il rouvre l'audio-guide "Visite du Louvre"
|
||
Alors une popup s'affiche:
|
||
"""
|
||
Continuer où vous vous étiez arrêté ?
|
||
|
||
📍 Séquence 6/12 : "Vénus de Milo"
|
||
⏱️ Position : 2:34 / 4:10
|
||
|
||
[▶️ Reprendre] [🔄 Recommencer]
|
||
"""
|
||
|
||
Scénario: Action "Reprendre" - Position exacte restaurée
|
||
Étant donné qu'une popup de reprise est affichée
|
||
Quand l'utilisateur clique sur "▶️ Reprendre"
|
||
Alors la séquence 6 "Vénus de Milo" se charge
|
||
Et la position exacte 2:34 est restaurée
|
||
Et la lecture démarre automatiquement après 1 seconde
|
||
|
||
Scénario: Action "Recommencer" - Réinitialisation complète
|
||
Étant donné qu'une popup de reprise est affichée
|
||
Quand l'utilisateur clique sur "🔄 Recommencer"
|
||
Alors l'audio-guide redémarre depuis la séquence 1 position 0:00
|
||
Et toutes les séquences sont marquées ⭕ "À écouter"
|
||
Et l'historique d'écoute est réinitialisé pour cette session
|
||
|
||
Scénario: Reprise après 7 jours d'inactivité
|
||
Étant donné qu'un utilisateur a arrêté un audio-guide le 15/01/2026
|
||
Et qu'il le rouvre le 22/01/2026 (7 jours plus tard)
|
||
Quand l'audio-guide se charge
|
||
Alors la popup de reprise s'affiche normalement
|
||
Et toutes les données de progression sont conservées
|
||
|
||
Scénario: Reprise sur un autre appareil (synchronisation cloud)
|
||
Étant donné qu'un utilisateur écoute un audio-guide sur iPhone
|
||
Et qu'il quitte à la séquence 4 position 1:20
|
||
Quand il ouvre le même audio-guide sur iPad
|
||
Alors la popup de reprise s'affiche avec la progression iPhone
|
||
Et il peut reprendre exactement où il s'était arrêté
|
||
|
||
Scénario: Conflit de synchronisation (dernier appareil gagne)
|
||
Étant donné qu'un utilisateur écoute sur iPhone à la séquence 3
|
||
Et simultanément sur iPad à la séquence 7
|
||
Quand les deux appareils synchronisent
|
||
Alors la progression la plus récente (timestamp) est conservée
|
||
Et l'appareil avec ancienne progression affiche une notification:
|
||
"""
|
||
ℹ️ Progression mise à jour
|
||
Une écoute plus récente a été détectée.
|
||
Séquence 7 restaurée.
|
||
"""
|
||
|
||
Scénario: Mode hors-ligne - Sauvegarde locale uniquement
|
||
Étant donné qu'un utilisateur écoute un audio-guide hors connexion
|
||
Et qu'il atteint la séquence 5
|
||
Quand la progression est sauvegardée
|
||
Alors les données sont écrites localement (SQLite)
|
||
Et une icône "☁️ Non synchronisé" s'affiche discrètement
|
||
|
||
Scénario: Synchronisation automatique à la reconnexion
|
||
Étant donné que l'utilisateur a écouté hors ligne jusqu'à la séquence 8
|
||
Et que 5 progressions locales ne sont pas synchronisées
|
||
Quand la connexion réseau est rétablie
|
||
Alors les 5 progressions sont synchronisées automatiquement
|
||
Et un toast s'affiche brièvement: "✅ Progression synchronisée"
|
||
|
||
Scénario: Suppression de la progression (recommencer proprement)
|
||
Étant donné qu'un utilisateur est à la séquence 10/12
|
||
Quand il ouvre les paramètres de l'audio-guide
|
||
Et qu'il clique sur "🔄 Réinitialiser progression"
|
||
Alors une confirmation s'affiche:
|
||
"""
|
||
Réinitialiser cet audio-guide ?
|
||
Toutes les séquences seront marquées comme non écoutées.
|
||
[Annuler] [Réinitialiser]
|
||
"""
|
||
Et si confirmé, la progression est effacée
|
||
|
||
# 16.7 - Statistiques d'écoute
|
||
|
||
Scénario: Taux de complétion global de l'audio-guide
|
||
Étant donné un audio-guide de 12 séquences
|
||
Et que l'utilisateur a écouté complètement 8 séquences
|
||
Et partiellement 1 séquence (45%)
|
||
Quand les statistiques sont calculées
|
||
Alors le taux de complétion affiché est "67%" (8/12)
|
||
|
||
Scénario: Badge "Audio-guide complété" à 100%
|
||
Étant donné un audio-guide de 12 séquences
|
||
Quand l'utilisateur écoute la 12ème séquence à 100%
|
||
Alors un badge "✅ Audio-guide complété" s'affiche
|
||
Et une notification de félicitations est envoyée
|
||
Et le statut "Complété le 22/01/2026" est visible dans l'historique
|
||
|
||
Scénario: Temps total passé sur l'audio-guide
|
||
Étant donné qu'un utilisateur a écouté un audio-guide sur 2 sessions:
|
||
| session | durée |
|
||
| 1 | 25 min |
|
||
| 2 | 18 min |
|
||
Quand les statistiques sont calculées
|
||
Alors le temps total est "43 minutes"
|
||
Et il est affiché dans l'historique personnel
|
||
|
||
Scénario: Liste des audio-guides "En cours" dans le profil
|
||
Étant donné qu'un utilisateur a 3 audio-guides en cours:
|
||
| audio_guide | progression |
|
||
| Visite du Louvre | 6/12 |
|
||
| Safari du Paugre | 3/8 |
|
||
| Circuit Loire à Vélo | 12/15 |
|
||
Quand il consulte son profil "Audio-guides"
|
||
Alors la section "📍 En cours" affiche les 3 audio-guides
|
||
Et chaque élément montre la progression sous forme de barre
|
||
|
||
Scénario: Liste des audio-guides "Complétés" dans le profil
|
||
Étant donné qu'un utilisateur a complété 2 audio-guides:
|
||
| audio_guide | date_completion |
|
||
| Tour de Paris | 2026-01-15 |
|
||
| Découverte de Lyon | 2026-01-20 |
|
||
Quand il consulte son profil "Audio-guides"
|
||
Alors la section "✅ Complétés" affiche les 2 audio-guides
|
||
Et la date de complétion est visible
|
||
|
||
Scénario: Badge "Complétiste" pour 10 audio-guides complétés
|
||
Étant donné qu'un utilisateur complète son 10ème audio-guide
|
||
Quand la complétion est enregistrée
|
||
Alors un badge "🏆 Complétiste" est débloqué
|
||
Et il apparaît sur son profil
|
||
Et une notification est envoyée:
|
||
"""
|
||
🎉 Badge débloqué : Complétiste
|
||
Vous avez complété 10 audio-guides !
|
||
"""
|
||
|
||
Plan du Scénario: Niveaux de badges selon nombre d'audio-guides complétés
|
||
Étant donné qu'un utilisateur complète <nombre> audio-guides
|
||
Quand le badge est attribué
|
||
Alors il reçoit le badge "<badge>"
|
||
|
||
Exemples:
|
||
| nombre | badge |
|
||
| 1 | 🎧 Premier audio-guide |
|
||
| 5 | 🗺️ Explorateur |
|
||
| 10 | 🏆 Complétiste |
|
||
| 25 | 🌟 Expert |
|
||
| 50 | 💎 Maître audio-guideur |
|
||
|
||
# 16.8 - Métriques créateur
|
||
|
||
Scénario: Dashboard créateur - Statistiques par audio-guide
|
||
Étant donné qu'un créateur a publié l'audio-guide "Visite du Louvre"
|
||
Quand il consulte son dashboard
|
||
Alors les métriques suivantes sont affichées:
|
||
| métrique | valeur |
|
||
| Écoutes totales | 1542 |
|
||
| Écoutes complètes (>80%) | 892 |
|
||
| Taux de complétion moyen | 58% |
|
||
| Temps d'écoute total | 423h |
|
||
| Séquence la plus écoutée | Séq. 3 |
|
||
| Séquence la moins écoutée | Séq. 11 |
|
||
|
||
Scénario: Graphique de complétion par séquence
|
||
Étant donné un audio-guide de 12 séquences
|
||
Quand le créateur consulte les statistiques détaillées
|
||
Alors un graphique en barres affiche:
|
||
| séquence | taux_completion |
|
||
| 1 | 100% |
|
||
| 2 | 95% |
|
||
| 3 | 89% |
|
||
| ... | ... |
|
||
| 12 | 58% |
|
||
|
||
Scénario: Détection des points d'abandon
|
||
Étant donné qu'un audio-guide a un taux de complétion de 58%
|
||
Et que 35% des utilisateurs abandonnent à la séquence 7
|
||
Quand le créateur consulte les insights
|
||
Alors un avertissement s'affiche:
|
||
"""
|
||
⚠️ Point d'abandon détecté
|
||
35% des utilisateurs abandonnent à la séquence 7 "Aile Richelieu"
|
||
Durée : 8 min
|
||
Suggestion : Réduire la durée ou rendre plus captivant
|
||
"""
|
||
|
||
Scénario: Heatmap géographique des écoutes
|
||
Étant donné un audio-guide géolocalisé
|
||
Quand le créateur consulte la heatmap
|
||
Alors une carte affiche:
|
||
| élément | description |
|
||
| Densité d'écoutes | Zones rouge/orange/jaune selon écoutes |
|
||
| Points GPS | Marqueurs sur chaque point |
|
||
| Statistiques par point | Nombre d'écoutes par zone |
|
||
|
||
Scénario: Temps moyen par séquence
|
||
Étant donné qu'un créateur analyse son audio-guide
|
||
Quand il consulte les statistiques temporelles
|
||
Alors il voit pour chaque séquence:
|
||
| séquence | durée_audio | temps_ecoute_moyen | ecart |
|
||
| 1 | 2:15 | 2:10 | -5s |
|
||
| 2 | 1:48 | 1:30 | -18s |
|
||
| 3 | 3:42 | 3:40 | -2s |
|
||
|
||
Scénario: Notification créateur pour milestone
|
||
Étant donné qu'un audio-guide atteint 1000 écoutes
|
||
Quand le seuil est franchi
|
||
Alors une notification est envoyée au créateur:
|
||
"""
|
||
🎉 Félicitations !
|
||
Votre audio-guide "Visite du Louvre" a atteint 1000 écoutes !
|
||
Taux de complétion : 58%
|
||
"""
|
||
|
||
# Cas d'erreur et limites
|
||
|
||
Scénario: Corruption de données de sauvegarde
|
||
Étant donné qu'une sauvegarde locale (SQLite) est corrompue
|
||
Quand l'application tente de charger la progression
|
||
Alors une récupération depuis le cloud est tentée
|
||
Et si réussie, les données cloud sont restaurées
|
||
Et la base locale est reconstruite
|
||
|
||
Scénario: Échec de synchronisation cloud
|
||
Étant donné que l'API cloud est indisponible
|
||
Quand une tentative de synchronisation est effectuée
|
||
Alors l'application continue avec sauvegarde locale uniquement
|
||
Et un retry automatique est programmé dans 5 minutes
|
||
Et l'icône "☁️ Non synchronisé" reste affichée
|
||
|
||
Scénario: Suppression accidentelle de progression (récupération)
|
||
Étant donné qu'un utilisateur réinitialise un audio-guide par erreur
|
||
Quand il contacte le support dans les 7 jours
|
||
Alors l'équipe peut restaurer la progression depuis les backups
|
||
Et les données sont récupérables (backup quotidien conservé 30 jours)
|
||
|
||
Scénario: Nettoyage automatique des vieilles progressions
|
||
Étant donné qu'une progression n'a pas été mise à jour depuis 6 mois
|
||
Quand le nettoyage automatique s'exécute
|
||
Alors la progression est archivée (mais pas supprimée)
|
||
Et l'utilisateur peut la restaurer via l'historique
|