feat(bdd): réorganiser features en catégories api/ui/e2e et créer ADR-024

Résolution des incohérences #10, #11, et #12 de l'analyse d'architecture.

## Phase 1 : Réorganisation Features BDD (Point #10 - RÉSOLU)

- Créer structure features/{api,ui,e2e}
- Déplacer 83 features en 3 catégories via git mv (historique préservé)
  - features/api/ : 53 features (tests API backend)
  - features/ui/ : 22 features (tests UI mobile)
  - features/e2e/ : 8 features (tests end-to-end)

Domaines déplacés :
- API : authentication, recommendation, rgpd-compliance, content-creation,
  moderation, monetisation, premium, radio-live, publicites
- UI : audio-guides, navigation, interest-gauges, mode-offline,
  partage, profil, recherche
- E2E : abonnements, error-handling

## Phase 2 : Mise à jour Documentation

### ADR-007 - Tests BDD
- Ajouter section "Convention de Catégorisation des Features"
- Documenter règles api/ui/e2e avec exemples concrets
- Spécifier step definitions (backend Go, mobile Dart)

### ADR-024 - Stratégie CI/CD Monorepo (NOUVEAU)
- Créer ADR dédié pour stratégie CI/CD avec path filters
- Architecture workflows séparés (backend.yml, mobile.yml, shared.yml)
- Configuration path filters détaillée avec exemples YAML
- Matrice de déclenchement et optimisations (~70% gain temps CI)
- Plan d'implémentation (~2h, reporté jusqu'au développement)

### ADR-016 - Organisation Monorepo
- Simplifier en retirant section CI/CD détaillée
- Ajouter référence vers ADR-024 pour stratégie CI/CD

### INCONSISTENCIES-ANALYSIS.md
- Point #10 (Tests BDD synchronisés) :  RÉSOLU
  - Catégorisation features implémentée
  - ADR-007 mis à jour avec convention complète
- Point #11 (70/30 Split paiements) :  ANNULÉ (faux problème)
  - ADR-009 et Règle 18 parfaitement cohérents
  - Documentation exhaustive existante (formule, SQL, comparaisons)
- Point #12 (Monorepo path filters) : ⏸️ DOCUMENTÉ
  - Architecture CI/CD complète dans ADR-024
  - Implémentation reportée (projet en phase documentation)
- Métriques mises à jour :
  - MODERATE : 6/9 traités (4 résolus + 1 annulé + 1 documenté)
  - ADR à jour : 100% (19/19 avec ADR-024)

## Phase 3 : Validation

- Structure features validée (api/ui/e2e, aucun répertoire restant)
- Historique Git préservé (git mv, renommages détectés)
- 83 features total (API: 53, UI: 22, E2E: 8)

Closes: Point #10 (résolu), Point #11 (annulé), Point #12 (documenté)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
jpgiannetti
2026-02-01 11:31:41 +01:00
parent 841028d1b2
commit 37c62206ad
88 changed files with 625 additions and 67 deletions

View File

@@ -0,0 +1,457 @@
# language: fr
Fonctionnalité: Gestion abonnement Premium
En tant qu'utilisateur
Je veux gérer facilement mon abonnement Premium
Afin de souscrire, renouveler ou annuler en toute transparence
Contexte:
Étant donné que je suis connecté à l'application RoadWave
# ===== SOUSCRIPTION =====
Scénario: Souscription via Web (desktop/mobile) avec Mangopay
Étant donné que je consulte la page Premium sur le site web
Quand je clique sur "S'abonner - Mensuel 4.99"
Alors je suis redirigé vers le formulaire de paiement Mangopay
Et je saisis mes informations de carte bancaire
Et le paiement de 4.99 est prélevé immédiatement
Et la commission Mangopay est de 1.8% + 0.18 = 0.27
Et RoadWave reçoit 4.72 net
Scénario: Calcul commission Mangopay
Étant donné qu'un utilisateur paie 4.99 via Mangopay
Quand la commission est calculée
Alors la commission est : 4.99 × 1.8% + 0.18 = 0.09 + 0.18 = 0.27
Et RoadWave reçoit : 4.99 - 0.27 = 4.72
Et la commission représente 5.4% du prix
Scénario: Souscription via iOS App avec Apple IAP
Étant donné que j'utilise l'app iOS
Quand je clique sur "S'abonner - Mensuel 5.99"
Alors je suis redirigé vers l'interface Apple In-App Purchase
Et le prix affiché est 5.99 (majoré de 20%)
Et le paiement est effectué via mon compte Apple
Et Apple prend 30% de commission = 1.80
Et RoadWave reçoit 4.19 net
Scénario: Souscription via Android App avec Google Play Billing
Étant donné que j'utilise l'app Android
Quand je clique sur "S'abonner - Mensuel 5.99"
Alors je suis redirigé vers l'interface Google Play Billing
Et le prix affiché est 5.99 (majoré de 20%)
Et le paiement est effectué via mon compte Google
Et Google prend 30% de commission = 1.80
Et RoadWave reçoit 4.19 net
Scénario: Majoration 20% sur mobile pour compenser commission 30%
Étant donné que Apple/Google prennent 30% de commission
Quand RoadWave fixe le prix mobile
Alors le prix web est 4.99 (commission Mangopay 5.4%)
Et le prix mobile est 5.99 (commission Apple/Google 30%)
Et la majoration est de 1 (+20%)
Et cela compense partiellement la commission excessive
Scénario: Email incitation souscription web moins chère
Étant donné que je consulte Premium depuis l'app mobile
Quand je vois le prix 5.99
Alors je vois aussi un message:
"""
💡 Astuce : Abonnez-vous sur roadwave.com pour seulement 4.99/mois
Économisez 12/an en évitant les frais Apple/Google !
"""
Et un lien vers le site web est fourni
Scénario: Calcul économie souscription web vs mobile
Étant donné que le prix web est 4.99/mois
Et que le prix mobile est 5.99/mois
Quand je calcule l'économie annuelle
Alors web : 4.99 × 12 = 59.88/an
Et mobile : 5.99 × 12 = 71.88/an
Et économie : 12/an (soit 20% d'économie)
Scénario: Activation immédiate après paiement réussi
Étant donné que je viens de payer mon abonnement Premium
Quand le paiement est confirmé
Alors mon statut passe immédiatement à "Premium"
Et je peux accéder aux avantages Premium dès maintenant
Et je reçois un email de confirmation
Scénario: Email confirmation souscription
Étant donné que j'ai souscrit à Premium
Quand la souscription est confirmée
Alors je reçois un email:
"""
🎉 Bienvenue Premium !
Votre abonnement Premium est actif.
Formule: Mensuel 4.99/mois
Prochain renouvellement: 15 juillet 2025
Vos avantages:
0 publicité
Contenus exclusifs
Qualité audio 64 kbps
Téléchargements illimités
Historique illimité
Profitez pleinement de RoadWave !
Gérer mon abonnement: [Lien]
"""
# ===== RENOUVELLEMENT AUTOMATIQUE =====
Scénario: Email rappel 7 jours avant renouvellement
Étant donné que mon abonnement mensuel se renouvelle le 15 juillet
Quand le 8 juillet arrive (7 jours avant)
Alors je reçois un email de rappel:
"""
📅 Votre abonnement Premium se renouvelle dans 7 jours
Formule: Mensuel 4.99/mois
Date de renouvellement: 15 juillet 2025
Montant: 4.99
Votre carte bancaire sera débitée automatiquement.
Vous souhaitez annuler ? [Gérer mon abonnement]
"""
Scénario: Renouvellement automatique réussi
Étant donné que mon abonnement mensuel arrive à échéance le 15 juillet
Quand le 15 juillet arrive
Alors Mangopay/Apple/Google prélève automatiquement 4.99 (ou 5.99)
Et mon abonnement est renouvelé pour 1 mois supplémentaire
Et je reçois un email de confirmation
Scénario: Email confirmation renouvellement
Étant donné que mon abonnement vient d'être renouvelé
Quand le paiement est confirmé
Alors je reçois un email:
"""
Abonnement Premium renouvelé
Votre abonnement a été renouvelé avec succès.
Montant débité: 4.99
Prochaine échéance: 15 août 2025
Merci de continuer à soutenir RoadWave et ses créateurs !
Gérer mon abonnement: [Lien]
"""
Scénario: Échec paiement renouvellement - Tentative 1
Étant donné que mon abonnement doit se renouveler le 15 juillet
Mais que ma carte bancaire est expirée ou sans fonds
Quand le prélèvement échoue
Alors je reçois un email:
"""
Échec renouvellement abonnement Premium
Le paiement de votre abonnement a échoué.
Raison: Carte bancaire expirée
Nous allons réessayer automatiquement dans 3 jours.
Veuillez mettre à jour vos informations de paiement: [Lien]
Votre accès Premium reste actif jusqu'au 22 juillet (7 jours).
"""
Scénario: Retry automatique paiement après 3 jours
Étant donné que le paiement a échoué le 15 juillet
Quand le 18 juillet arrive (J+3)
Alors Mangopay/Apple/Google tente automatiquement un nouveau prélèvement
Et si le paiement réussit, l'abonnement est renouvelé normalement
Et si le paiement échoue encore, un 2ème retry est programmé
Scénario: Retry automatique paiement après 7 jours
Étant donné que 2 tentatives ont échoué (15 juillet et 18 juillet)
Quand le 22 juillet arrive (J+7)
Alors une 3ème et dernière tentative est effectuée
Et si le paiement réussit, l'abonnement est sauvé
Et si le paiement échoue, l'abonnement est annulé automatiquement
Scénario: Annulation automatique après 3 échecs paiement
Étant donné que les 3 tentatives de renouvellement ont échoué (J+0, J+3, J+7)
Quand la 3ème tentative échoue
Alors mon abonnement Premium est annulé automatiquement
Et mon statut repasse à "Gratuit"
Et je perds accès aux avantages Premium
Et je reçois un email d'annulation
Scénario: Email annulation automatique pour impayé
Étant donné que mon abonnement a été annulé pour échec paiement
Quand l'annulation devient effective
Alors je reçois un email:
"""
Abonnement Premium annulé
Votre abonnement a été annulé suite à 3 échecs de paiement.
Vous repassez en mode gratuit et perdez l'accès à:
Contenus Premium exclusifs
Qualité audio supérieure
Téléchargements illimités
Pour réactiver Premium, mettez à jour vos informations de paiement: [Lien]
"""
# ===== ANNULATION =====
Scénario: Annulation self-service dans Settings
Étant donné que je veux annuler mon abonnement
Quand j'accède à "Paramètres > Abonnement"
Alors je vois un bouton "Annuler l'abonnement"
Et je peux annuler en 2 clics sans contacter le support
Scénario: Confirmation avant annulation
Étant donné que je clique sur "Annuler l'abonnement"
Quand une popup de confirmation apparaît
Alors je vois:
"""
😢 Vous allez annuler votre abonnement Premium
Vous perdrez l'accès à:
0 publicité
Contenus Premium exclusifs
Qualité audio supérieure
Téléchargements illimités
Accès maintenu jusqu'au: 15 juillet 2025 (fin période payée)
Pas de remboursement prorata.
[Confirmer l'annulation] [Rester Premium]
```
Scénario: Accès Premium maintenu jusqu'à fin période payée
Étant donné que j'ai annulé mon abonnement le 1er juillet
Et que mon abonnement mensuel était valable jusqu'au 15 juillet
Quand l'annulation est confirmée
Alors je garde l'accès Premium jusqu'au 15 juillet
Et à partir du 16 juillet, je repasse en gratuit
Et je ne suis pas remboursé pour les 14 jours restants
Scénario: Justification pas de remboursement prorata
Étant donné que l'industrie (Spotify, Netflix, YouTube) ne rembourse pas prorata
Quand RoadWave applique la même règle
Alors c'est le standard accepté par les utilisateurs
Et cela simplifie la gestion comptable
Et évite les abus (souscription puis annulation immédiate pour remboursement)
Scénario: Email confirmation annulation
Étant donné que j'ai annulé mon abonnement
Quand l'annulation est enregistrée
Alors je reçois un email:
"""
Annulation confirmée
Votre abonnement Premium a été annulé.
Accès Premium maintenu jusqu'au: 15 juillet 2025
Après cette date, vous repasserez en mode gratuit.
Pas de remboursement pour la période restante (standard industrie).
Vous pouvez vous réabonner à tout moment !
Nous espérons vous revoir bientôt.
Réabonner: [Lien]
"""
Scénario: Pas de renouvellement après annulation
Étant donné que j'ai annulé mon abonnement le 1er juillet
Quand le 15 juillet arrive (date de renouvellement prévue)
Alors aucun prélèvement n'est effectué
Et mon statut passe automatiquement à "Gratuit"
Et je ne reçois pas d'email de renouvellement
# ===== RÉABONNEMENT =====
Scénario: Réabonnement possible immédiatement
Étant donné que j'ai annulé mon abonnement il y a 5 jours
Quand j'accède à la page Premium
Alors je peux me réabonner immédiatement
Et le processus de paiement est le même que la première fois
Scénario: Pas de nouvelle période d'essai au réabonnement
Étant donné que j'ai annulé mon abonnement il y a 3 mois
Quand je me réabonne
Alors je paie immédiatement 4.99 (pas d'essai gratuit)
Car RoadWave ne propose jamais d'essai gratuit (ni première fois ni réabonnement)
Scénario: Offre win-back pour utilisateurs ayant annulé
Étant donné que j'ai annulé mon abonnement il y a 1 mois
Quand je reçois un email de win-back
Alors je vois une offre spéciale:
"""
🎁 On vous a manqué ?
Revenez en Premium avec une offre exclusive:
-30% sur les 3 premiers mois (3.49/mois au lieu de 4.99)
Offre valable jusqu'au 31 juillet.
[Réactiver Premium]
```
# ===== ARCHITECTURE DONNÉES =====
Scénario: Table subscriptions en base PostgreSQL
Étant donné qu'un utilisateur souscrit à Premium
Quand les données sont enregistrées
Alors la table subscriptions contient:
```sql
CREATE TABLE subscriptions (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id) UNIQUE,
mangopay_recurring_payin_id VARCHAR(255), -- Null si IAP
mangopay_user_id VARCHAR(255), -- Null si IAP
apple_transaction_id VARCHAR(255), -- Null si Mangopay
google_purchase_token VARCHAR(255), -- Null si Mangopay
status VARCHAR(50) NOT NULL, -- 'active', 'cancelled', 'expired', 'past_due'
plan VARCHAR(50) NOT NULL, -- 'monthly', 'yearly'
current_period_start TIMESTAMP NOT NULL,
current_period_end TIMESTAMP NOT NULL,
cancelled_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
```
Scénario: Statuts possibles dans subscription.status
Étant donné qu'un abonnement peut avoir différents statuts
Quand le statut est stocké en base
Alors les valeurs possibles sont:
| statut | description |
| active | Abonnement actif et payé |
| cancelled | Annulé par utilisateur (accès jusqu'à fin période) |
| expired | Période terminée, pas renouvelé |
| past_due | Échec paiement, en retry automatique |
Scénario: Cache Redis pour vérification Premium temps réel
Étant donné qu'un utilisateur lance un contenu
Quand l'app vérifie s'il est Premium
Alors une clé Redis est consultée:
```
Key: premium:{user_id}
Value: true/false
TTL: 1 heure
```
Et si la clé n'existe pas, elle est recalculée depuis PostgreSQL
Et cela garantit des performances <10ms
Scénario: Refresh cache Redis via webhooks
Étant donné qu'un paiement est confirmé par Mangopay/Apple/Google
Quand un webhook est reçu par RoadWave
Alors le cache Redis premium:{user_id} est mis à jour immédiatement
Et l'utilisateur voit son statut Premium activé sans délai
Scénario: Webhooks Mangopay - PAYIN_NORMAL_SUCCEEDED
Étant donné qu'un paiement Mangopay réussit
Quand Mangopay envoie le webhook PAYIN_NORMAL_SUCCEEDED
Alors RoadWave met à jour subscriptions.status = 'active'
Et met à jour current_period_end = NOW() + 1 mois
Et refresh le cache Redis premium:{user_id} = true
Scénario: Webhooks Mangopay - PAYIN_NORMAL_FAILED
Étant donné qu'un paiement Mangopay échoue
Quand Mangopay envoie le webhook PAYIN_NORMAL_FAILED
Alors RoadWave met à jour subscriptions.status = 'past_due'
Et programme un retry automatique dans 3 jours
Et envoie un email à l'utilisateur
Scénario: Webhooks Apple - App Store Server Notifications
Étant donné qu'un paiement Apple IAP change de statut
Quand Apple envoie une notification serveur
Alors RoadWave parse la notification (JSON)
Et met à jour la subscription en conséquence
Et refresh le cache Redis
Scénario: Webhooks Google - Real-time Developer Notifications
Étant donné qu'un paiement Google Play change de statut
Quand Google envoie une notification temps réel
Alors RoadWave parse la notification (JSON)
Et met à jour la subscription en conséquence
Et refresh le cache Redis
# ===== STATISTIQUES ET MONITORING =====
Scénario: Dashboard admin - Métriques abonnements
Étant donné qu'un admin consulte les métriques Premium
Quand il accède au dashboard
Alors il voit:
| métrique | valeur |
| Abonnés actifs | 12,547 |
| Nouveaux abonnements ce mois | 1,234 |
| Annulations ce mois | 287 (2.3%) |
| Churn rate mensuel | 2.3% |
| MRR (Revenus mensuels récurrents) | 58,890€ |
| Taux conversion gratuit → Premium | 8.5% |
Scénario: Calcul churn rate mensuel
Étant donné que 287 utilisateurs ont annulé ce mois
Et qu'il y avait 12,547 abonnés au début du mois
Quand le churn rate est calculé
Alors churn = 287 / 12,547 = 2.3%
Et un churn <5% est considéré comme excellent
Et RoadWave surveille cette métrique de près
Scénario: Alerte si churn rate >5%
Étant donné que le churn rate mensuel dépasse 5%
Quand le système détecte cette anomalie
Alors une alerte est envoyée à l'équipe:
"""
Churn rate anormal: 6.2%
Nombre annulations ce mois: 778
Causes principales:
- Prix jugé trop élevé: 42%
- Utilisation faible: 28%
- Concurrent moins cher: 18%
- Autre: 12%
Action recommandée: Enquête satisfaction + offres win-back
"""
Scénario: Enquête satisfaction à l'annulation
Étant donné que je viens d'annuler mon abonnement
Quand l'annulation est confirmée
Alors je vois un questionnaire rapide:
"""
Pourquoi annulez-vous Premium ?
Prix trop élevé
Je n'utilise pas assez RoadWave
Pas assez de contenus exclusifs
Problèmes techniques
J'ai trouvé une alternative moins chère
Autre: [Texte libre]
[Envoyer] [Ignorer]
```
Et les réponses aident à améliorer l'offre Premium
Scénario: Répartition canaux souscription
Étant donné qu'un admin analyse les canaux de souscription
Quand il consulte les statistiques
Alors il voit:
| canal | abonnés | % total | revenus/mois |
| Web (Mangopay) | 8,234 | 65.6% | 41,088 |
| iOS (Apple) | 2,845 | 22.7% | 17,042 |
| Android (Google)| 1,468 | 11.7% | 8,793 |
Et cela aide à orienter les efforts marketing (inciter web = moins de commission)
Scénario: Performance vérification Premium <10ms
Étant donné que 100 000 utilisateurs consultent des contenus simultanément
Quand chaque requête vérifie le statut Premium via Redis
Alors le temps de réponse moyen est <10ms
Et Redis gère facilement 100 000 requêtes/seconde
Et l'expérience utilisateur est fluide
Scénario: Backup données abonnements
Étant donné que les données d'abonnements sont critiques
Quand un backup est effectué
Alors PostgreSQL est répliqué en temps réel sur un replica
Et un snapshot quotidien est stocké sur S3
Et en cas de crash, les données peuvent être restaurées <5 minutes