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,238 @@
|
||||
# language: fr
|
||||
Fonctionnalité: Ciblage horaire publicités et gestion fuseaux horaires
|
||||
En tant que publicitaire
|
||||
Je veux cibler mes publicités sur des plages horaires en heure locale utilisateur
|
||||
Afin d'optimiser mes campagnes selon les moments de la journée (rush matin/soir)
|
||||
|
||||
Contexte:
|
||||
Étant donné qu'un publicitaire crée une campagne publicitaire
|
||||
|
||||
# Règle 1 : Ciblage horaire = Heure locale utilisateur
|
||||
|
||||
Scénario: Campagne "7h-9h" diffuse selon heure locale de chaque utilisateur
|
||||
Étant donné qu'une campagne est configurée avec plage horaire "7h-9h"
|
||||
Et que nous sommes le 7 février 2026 à 8h00 UTC
|
||||
Quand le système vérifie la diffusion pour différents utilisateurs:
|
||||
| utilisateur | localisation | fuseau horaire | heure locale | diffusion ? |
|
||||
| User Marseille | Marseille | Europe/Paris | 9h00 | ✅ Oui |
|
||||
| User Guadeloupe | Pointe-à-Pitre | America/Guadeloupe | 4h00 | ❌ Non |
|
||||
| User Réunion | Saint-Denis | Indian/Reunion | 12h00 | ❌ Non |
|
||||
| User Lyon | Lyon | Europe/Paris | 9h00 | ✅ Oui |
|
||||
Alors la pub est diffusée uniquement aux utilisateurs dans la plage 7h-9h leur heure locale
|
||||
|
||||
Scénario: Campagne "17h-19h" (rush soir) - Heure locale de chaque utilisateur
|
||||
Étant donné qu'une campagne est configurée avec plage horaire "17h-19h"
|
||||
Et que nous sommes le 7 février 2026 à 17h30 UTC
|
||||
Quand le système vérifie la diffusion pour:
|
||||
| utilisateur | fuseau horaire | heure locale | diffusion ? |
|
||||
| User Paris | Europe/Paris | 18h30 | ✅ Oui |
|
||||
| User Martinique | America/Martinique | 13h30 | ❌ Non |
|
||||
| User Réunion | Indian/Reunion | 21h30 | ❌ Non |
|
||||
Alors la pub est diffusée uniquement à User Paris (18h30 dans 17h-19h)
|
||||
|
||||
Scénario: Campagne 24/7 (toute la journée) - Pas de restriction horaire
|
||||
Étant donné qu'une campagne n'a AUCUNE restriction horaire
|
||||
Quand le système vérifie la diffusion
|
||||
Alors la pub est diffusée à tout moment (0h-23h)
|
||||
Et tous les utilisateurs sont éligibles quelle que soit l'heure locale
|
||||
|
||||
# Détection fuseau horaire utilisateur
|
||||
|
||||
Scénario: Détection fuseau via GPS (méthode primaire)
|
||||
Étant donné qu'un utilisateur a le GPS activé
|
||||
Et que sa position GPS est (latitude: 48.8566, longitude: 2.3522)
|
||||
Quand le système détecte le fuseau horaire
|
||||
Alors le fuseau horaire déterminé est "Europe/Paris"
|
||||
Et l'heure locale est calculée avec ce fuseau
|
||||
|
||||
Scénario: Détection fuseau via paramètres device (si GPS désactivé)
|
||||
Étant donné qu'un utilisateur a le GPS désactivé
|
||||
Mais que les paramètres OS indiquent fuseau "America/Guadeloupe"
|
||||
Quand le système détecte le fuseau horaire
|
||||
Alors le fuseau horaire utilisé est "America/Guadeloupe"
|
||||
Et l'heure locale est calculée avec ce fuseau
|
||||
|
||||
Scénario: Fallback IP geolocation (si GPS désactivé ET paramètres indisponibles)
|
||||
Étant donné qu'un utilisateur a le GPS désactivé
|
||||
Et que les paramètres device ne sont pas accessibles
|
||||
Mais que l'IP est géolocalisée à La Réunion
|
||||
Quand le système détecte le fuseau horaire
|
||||
Alors le fuseau horaire approximatif est "Indian/Reunion"
|
||||
Et l'heure locale est calculée avec ce fuseau
|
||||
|
||||
# Règle 2 : Ciblage "France" = Métropole + DOM
|
||||
|
||||
Scénario: Ciblage "France entière" inclut Métropole + DOM
|
||||
Étant donné qu'une campagne cible "France (nationale)"
|
||||
Quand le système vérifie les utilisateurs éligibles
|
||||
Alors les utilisateurs inclus sont:
|
||||
| zone | départements / territoires |
|
||||
| France métropolitaine | 96 départements (01 à 95, 2A, 2B, etc.) |
|
||||
| Guadeloupe | 971 |
|
||||
| Martinique | 972 |
|
||||
| Guyane | 973 |
|
||||
| Réunion | 974 |
|
||||
| Mayotte | 976 |
|
||||
|
||||
Scénario: Publicitaire affine ciblage "Région Provence-Alpes-Côte d'Azur"
|
||||
Étant donné qu'une campagne cible "Région Provence-Alpes-Côte d'Azur"
|
||||
Quand le système vérifie les utilisateurs éligibles
|
||||
Alors seuls les utilisateurs en Métropole dans cette région sont ciblés
|
||||
Et les utilisateurs DOM (Guadeloupe, Réunion, etc.) ne sont PAS ciblés
|
||||
|
||||
Scénario: Publicitaire affine ciblage "Département 971 (Guadeloupe)"
|
||||
Étant donné qu'une campagne cible "Département 971"
|
||||
Quand le système vérifie les utilisateurs éligibles
|
||||
Alors seuls les utilisateurs en Guadeloupe sont ciblés
|
||||
Et les utilisateurs Métropole ne sont PAS ciblés
|
||||
|
||||
Scénario: Publicitaire affine ciblage "Ville Pointe-à-Pitre"
|
||||
Étant donné qu'une campagne cible "Ville Pointe-à-Pitre"
|
||||
Quand le système vérifie les utilisateurs éligibles
|
||||
Alors seuls les utilisateurs à Pointe-à-Pitre (Guadeloupe) sont ciblés
|
||||
|
||||
# Interface publicitaire
|
||||
|
||||
Scénario: Interface création campagne - Note explicite sur inclusion DOM
|
||||
Étant donné qu'un publicitaire accède au formulaire de création campagne
|
||||
Quand il sélectionne "National (France entière)"
|
||||
Alors une note informative s'affiche:
|
||||
"""
|
||||
ℹ️ Note : "National (France entière)" inclut les DOM
|
||||
(Guadeloupe, Martinique, Réunion, Guyane, Mayotte)
|
||||
"""
|
||||
|
||||
Scénario: Interface - Liste déroulante ciblage géographique
|
||||
Étant donné qu'un publicitaire configure le ciblage géographique
|
||||
Quand il consulte la liste déroulante
|
||||
Alors les options disponibles sont:
|
||||
| option | description |
|
||||
| National (France entière) | Métropole + DOM |
|
||||
| Région | Ex: Provence-Alpes-Côte d'Azur (Métropole)|
|
||||
| Département | Ex: 13 (Métropole) ou 971 (Guadeloupe) |
|
||||
| Ville | Ex: Marseille, Pointe-à-Pitre |
|
||||
| Point GPS + rayon | Latitude/Longitude + rayon en km |
|
||||
|
||||
# Cas d'usage publicitaire
|
||||
|
||||
Scénario: Restaurant local Guadeloupe - Ciblage département 971 + horaires 12h-14h
|
||||
Étant donné qu'un restaurant à Pointe-à-Pitre crée une campagne
|
||||
Et que le ciblage est "Département 971 (Guadeloupe)"
|
||||
Et que les horaires sont "12h-14h" (rush déjeuner)
|
||||
Quand le système diffuse les pubs à 12h30
|
||||
Alors les utilisateurs Guadeloupe à 12h30 heure locale reçoivent la pub
|
||||
Et les utilisateurs Métropole ne reçoivent PAS la pub (hors zone géo)
|
||||
Et les utilisateurs Martinique ne reçoivent PAS la pub (hors zone géo)
|
||||
|
||||
Scénario: Assureur national - Ciblage France + horaires 7h-9h + 17h-19h
|
||||
Étant donné qu'un assureur national crée une campagne
|
||||
Et que le ciblage est "France (nationale)"
|
||||
Et que les horaires sont "7h-9h" et "17h-19h" (rush matin/soir)
|
||||
Quand le système diffuse les pubs
|
||||
Alors à 8h locale Marseille, User Marseille reçoit la pub
|
||||
Et à 8h locale Réunion, User Réunion reçoit la pub
|
||||
Et User Réunion reçoit la pub à 8h locale (= 5h métropole, mais c'est son rush matin)
|
||||
|
||||
Scénario: Utilisateur en vacances change de fuseau horaire
|
||||
Étant donné qu'un utilisateur habite Paris (Europe/Paris)
|
||||
Et qu'il part en vacances à La Réunion
|
||||
Et qu'il télécharge 50 contenus + pubs avant de partir
|
||||
Quand l'utilisateur écoute à 8h locale Réunion (device détecte fuseau)
|
||||
Alors le filtrage des pubs utilise l'heure locale Réunion (8h)
|
||||
Et les pubs ciblées "7h-9h" sont diffusées normalement
|
||||
|
||||
# Implémentation technique
|
||||
|
||||
Scénario: Calcul heure locale via PostgreSQL AT TIME ZONE
|
||||
Étant donné qu'une campagne a une plage horaire "7h-9h"
|
||||
Et qu'un utilisateur a le fuseau "Indian/Reunion" (UTC+4)
|
||||
Quand le backend vérifie l'éligibilité à 08h00 UTC
|
||||
Alors la requête SQL utilise:
|
||||
"""sql
|
||||
SELECT
|
||||
EXTRACT(HOUR FROM NOW() AT TIME ZONE 'Indian/Reunion') AS local_hour
|
||||
-- Résultat: 12 (8h UTC + 4h = 12h locale)
|
||||
"""
|
||||
Et local_hour = 12 n'est PAS dans [7, 8, 9], donc pas de diffusion
|
||||
|
||||
Scénario: Base IANA Time Zone pour conversion GPS → fuseau
|
||||
Étant donné qu'un utilisateur a GPS (48.8566, 2.3522)
|
||||
Quand le système convertit GPS → fuseau horaire
|
||||
Alors la base IANA Time Zone est utilisée
|
||||
Et le fuseau déterminé est "Europe/Paris"
|
||||
Et la base est mise à jour régulièrement (changements DST, fuseaux)
|
||||
|
||||
# Justification
|
||||
|
||||
Scénario: Comparaison avec standard industrie - Google Ads, Facebook Ads
|
||||
Étant donné qu'on compare avec Google Ads et Facebook Ads
|
||||
Quand on évalue le comportement du ciblage horaire
|
||||
Alors RoadWave suit le standard:
|
||||
| plateforme | ciblage horaire | référence temporelle | norme |
|
||||
| Google Ads | 7h-9h | Heure locale user | ✅ Standard |
|
||||
| Facebook Ads | 7h-9h | Heure locale user | ✅ Standard |
|
||||
| RoadWave | 7h-9h | Heure locale user | ✅ Standard |
|
||||
|
||||
Scénario: Avantages UX intuitive pour publicitaires
|
||||
Étant donné qu'un publicitaire configure "7h-9h"
|
||||
Quand il pense "rush matin"
|
||||
Alors il n'a pas besoin de comprendre UTC
|
||||
Et "7h-9h" signifie "matin partout en France"
|
||||
Et l'UX est intuitive:
|
||||
| avantage | description |
|
||||
| UX intuitive publicitaires | "7h-9h" = matin partout, pas UTC compliqué |
|
||||
| Équité géographique | Pas de discrimination DOM-TOM |
|
||||
| Simplicité technique | Détection automatique fuseau (GPS/device) |
|
||||
| Standard industrie | Même comportement Google/Facebook |
|
||||
|
||||
# Cas limites
|
||||
|
||||
Scénario: Utilisateur change de fuseau pendant campagne active
|
||||
Étant donné qu'un utilisateur écoute des pubs en métropole (Europe/Paris)
|
||||
Et qu'une campagne cible "7h-9h"
|
||||
Quand l'utilisateur part en vacances Réunion (Indian/Reunion)
|
||||
Alors le système détecte le nouveau fuseau horaire automatiquement
|
||||
Et les pubs "7h-9h" sont filtrées selon l'heure locale Réunion
|
||||
Et l'utilisateur reçoit les pubs à 7h-9h heure locale Réunion
|
||||
|
||||
Scénario: Changement heure d'été/hiver (DST) - Gestion automatique
|
||||
Étant donné qu'une campagne cible "7h-9h" en Europe/Paris
|
||||
Et que le changement heure d'été arrive (dernier dimanche mars)
|
||||
Quand l'heure passe de 2h à 3h (UTC+1 → UTC+2)
|
||||
Alors le système utilise automatiquement le nouveau décalage UTC
|
||||
Et les pubs "7h-9h" continuent de se diffuser à 7h-9h heure locale
|
||||
Et PostgreSQL AT TIME ZONE gère automatiquement le DST
|
||||
|
||||
# Métriques dashboard publicitaire
|
||||
|
||||
Scénario: Dashboard publicitaire - Répartition géographique diffusions
|
||||
Étant donné qu'une campagne "France (nationale)" + "7h-9h" est active
|
||||
Quand le publicitaire consulte le dashboard
|
||||
Alors la répartition géographique affiche:
|
||||
| zone | impressions | % total |
|
||||
| Île-de-France | 45,000 | 60% |
|
||||
| Provence-Alpes | 15,000 | 20% |
|
||||
| Guadeloupe | 3,000 | 4% |
|
||||
| Réunion | 4,500 | 6% |
|
||||
| Autres | 7,500 | 10% |
|
||||
|
||||
Scénario: Dashboard publicitaire - Répartition horaire diffusions
|
||||
Étant donné qu'une campagne "7h-9h" est active
|
||||
Quand le publicitaire consulte le dashboard
|
||||
Alors un graphique horaire affiche:
|
||||
| heure locale | impressions |
|
||||
| 7h | 12,000 |
|
||||
| 8h | 18,000 |
|
||||
| 9h | 5,000 |
|
||||
Et les impressions hors plage (autres heures) = 0
|
||||
|
||||
Scénario: Validation création campagne - Cohérence géo + horaires
|
||||
Étant donné qu'un publicitaire crée une campagne
|
||||
Et qu'il sélectionne "Département 971 (Guadeloupe)"
|
||||
Et qu'il configure horaires "7h-9h"
|
||||
Quand il valide la campagne
|
||||
Alors le système confirme:
|
||||
"""
|
||||
Votre campagne sera diffusée à 7h-9h heure locale Guadeloupe (UTC-4).
|
||||
Estimation: 2,500 impressions/jour.
|
||||
"""
|
||||
Reference in New Issue
Block a user