Opérateur Console (OP) - PRD + Spécifications Fonctionnelles V1¶
Module : OP - operator-console
Plane : Application
Version cible : V1 (MVP)
Pays : CI (Côte d'Ivoire)
Préfixe story : OP-NNN
Date : 2026-05-19
Statut : Draft
V0 Envelope Scope (ajout 2026-05-21)¶
Lire
docs/prd/prd-v0.md§ 4 (ligne OP) et § 8 avant toute story V0. Ce PRD reste le contrat V1. Le V0 coupe FROM cette spec ; chaque sous-version V0 est additive et empile vers la cible V1.OP dans le V0 (per
prd-v0.md§ 4 + § 8) :
Sous-version Périmètre vs V1 PRD Story IDs [V0.0.0]UI création + envoi campagne (fire-and-forget). Liste contrats read-only (pas d'édition). Moteur campagne simplifié : renewal_window_daysdepuis settings tenant, tous les contrats matching sélectionnés, un envoi par création. Pas de scheduling, pas de segmentation, pas d'A/B, pas de feedback post-envoi. OP appelle NOTIF via API (Spring boundary) ; envoi async via domain events + outbox (D4).OP-001 [V0.0.1]Édition inline pré-envoi (admin cabinet uniquement). Vue de statut post-envoi (read-only). OP-002 [V0.0.2]Routing multi-agence : chaque opérateur d'agence voit uniquement les contrats de son agence ; les opérateurs branche peuvent éditer pré-envoi. OP-003 [V0.0.3]Actions post-envoi : view + revoke + cancel (admin cabinet uniquement). OP-004 [V0.1.0]Hooks d'observabilité (instrumentation pour ARTCI + ops). OP-005 [V1]Spec V1 complète telle qu'écrite ci-dessous (cohort selection avancée, multi-step scheduling, A/B testing, bulk approve, exceptions, approval workflow complet). - Verrouillé V0.0.0 onwards (cf.
prd-v0.md§ 4 ligne OP) : desktop-first, online-first, UI FR-only, polling uniquement (pas de WebSocket, pas de service worker, pas d'offline sync en V0). OP couple LOOSELY à NOTIF + PAY via domain events + APIs (jamais inline send).Note CAMP : le moteur de campagne reste plié dans OP pour tout V0 (pas de prefix
CAMP-NNN). Si V2 fait émerger un vrai rules engine (segmentation, branching, journeys), CAMP redeviendra un module distinct ; aucun travail V0 ne doit baker une assumption qui bloque ce split.
Sommaire¶
- Partie A - Exigences Produit
- Partie B - Spécifications Fonctionnelles
- Partie C - Contraintes et Frontières
Partie A - Exigences Produit¶
A.1 Résumé Exécutif¶
Problème résolu : Sans console opérateur, toute la valeur de la plateforme reste inaccessible. Le module OP est le point de commandement quotidien du cabinet et de ses agences : c'est ici qu'on importe les données, qu'on construit et valide les campagnes de relance, qu'on surveille les envois et les paiements, et qu'on traite les exceptions.
Valeur créée : - Pour le cabinet : visibilité consolidée sur l'ensemble du cycle de relance (import → campagne → envoi → paiement → anomalie) ; traçabilité auditée de chaque action opérateur ; productivité accrue (correction en lot, validation en un clic). - Pour l'opérateur d'agence : liste de travail claire par priorité (urgences ≤ 7 jours, anomalies bloquantes) ; interface simple, sans ERP, calée sur l'export bureau. - Pour le superviseur : dashboard de conversion en temps réel ; export CSV/XLSX pour rapports mensuels.
Position dans le flux V1 : OP est le pivot de l'application plane. Il consomme ING (données), déclenche NOTIF (envois), observe PAY (paiements), écrit dans AUDIT (traçabilité) et obtient son contexte de TENANT (cabinet / agence / profil pays). ING, PAY et NOTIF sont des services headless (API uniquement) - OP héberge l'intégralité de l'interface back-office.
A.2 Personas¶
Opérateur d'agence (agency_operator)¶
- Exemple : Kouassi Brou, chargé de recouvrement - Agence Plateau, Cabinet Acme CI
- Tâches quotidiennes : consulter la liste des campagnes, corriger les anomalies, valider et envoyer les campagnes, surveiller les statuts de notification/paiement, gérer les exceptions (hors-plateforme, renvoi de lien).
- Portée de données : uniquement son agence (
agency_id). - Ne peut pas : gérer les utilisateurs, modifier les paramètres cabinet, exporter des rapports, voir d'autres agences.
Administrateur cabinet (cabinet_admin)¶
- Exemple : Marie Koné, directrice - Cabinet Acme CI
- Tâches : provisionner les utilisateurs, configurer la fenêtre de détection, renseigner les informations légales CIMA, consulter toutes les agences.
- Portée de données : toutes les agences du cabinet/tenant.
- Peut faire : tout (CRUD, gestion utilisateurs, paramètres, export).
Superviseur (supervisor)¶
- Exemple : Directeur commercial - Cabinet Acme CI
- Tâches : consulter les dashboards de conversion, suivre les campagnes multi-agences, exporter les rapports mensuels.
- Portée de données : toutes les agences (lecture seule).
- Ne peut pas : modifier des données, créer/envoyer des campagnes, gérer des utilisateurs.
Rappel modèle : Cabinet = tenant = entité juridique (ex. Cabinet Acme CI). Agence = sous-unité opérationnelle du même cabinet (ex. Agence Plateau, Agence Cocody). Un opérateur est affecté à une agence ; un cabinet_admin ou supervisor a une vue transversale.
A.3 User Stories¶
US-OP-01 [V1][OPERATOR] - Importer un fichier de contrats¶
En tant qu' opérateur d'agence,
je veux uploader un fichier CSV/XLSX sur un écran dédié,
afin de ingérer les contrats exportés depuis notre outil de gestion, sans intervention technique.
- AC1 : Étant donné que je suis sur l'écran « Importer un fichier », quand je glisse ou sélectionne un fichier, alors une barre de progression affiche l'avancement pendant que ING le traite.
- AC2 : Quand ING termine le traitement, alors un écran de résultats affiche : X contrats valides, Y erreurs bloquantes, Z anomalies non-bloquantes, avec un lien vers chaque catégorie.
- AC3 : Quand des erreurs bloquantes existent, si je clique sur une ligne d'erreur, alors je suis dirigé vers la fiche anomalie correspondante.
- AC4 : Si le même fichier (même hash SHA-256) a déjà été importé, alors le système affiche un avertissement « Ce fichier a déjà été importé le {date}. Continuer quand même ? » avant de permettre l'import.
US-OP-02 [V1][OPERATOR] - Consulter la liste des campagnes¶
En tant qu' opérateur d'agence,
je veux voir la liste des campagnes de mon agence avec leurs statuts,
afin de savoir ce qui requiert mon action aujourd'hui.
- AC1 : La liste est triée par date de création décroissante et affiche pour chaque campagne : nom auto-généré, date, agence, nombre de contrats, statut (pill coloré : Brouillon / Envoyée / Clôturée / Annulée).
- AC2 : Je peux filtrer par statut, par date (période), et par branche produit.
- AC3 : En tant que cabinet_admin ou supervisor, je vois les campagnes de toutes les agences avec une colonne « Agence », et je peux filtrer par agence.
US-OP-03 [V1][OPERATOR] - Créer une campagne ad hoc¶
En tant qu' opérateur d'agence,
je veux sélectionner des contrats éligibles et créer une campagne ad hoc,
afin de cibler un sous-ensemble spécifique en dehors de la cohort planifiée.
- AC1 : Dans « Nouvelle campagne », je vois un sélecteur de contrats affichant les contrats éligibles (dans la fenêtre de détection, non actifs dans une autre campagne), filtrables par branche produit, plage de montant, plage de date d'échéance.
- AC2 : Quand je sélectionne N contrats et clique « Créer la campagne », la campagne est créée avec le nom auto-généré « Campagne YYYY-MM-DD - {Agence} » et le statut Brouillon.
- AC3 : Un contrat déjà actif dans une autre campagne est grisé et non sélectionnable, avec un tooltip : « Déjà dans la campagne {nom} ».
US-OP-04 [V1][OPERATOR] - Corriger et valider une campagne avant envoi¶
En tant qu' opérateur d'agence,
je veux réviser les contrats d'une campagne en Brouillon, corriger les anomalies, exclure des contrats, puis valider l'envoi,
afin d' assurer la qualité des données avant toute notification client.
- AC1 : Le détail de campagne affiche pour chaque contrat : nom client (DOB masqué
**/**/YYYYen liste), téléphone, branche produit, montant, date d'échéance, nombre d'anomalies (badge rouge si bloquante). - AC2 : Si un contrat a une anomalie bloquante non résolue (statut INCLUS), le bouton « Valider et Envoyer » est désactivé avec le message : « {N} contrat(s) avec des anomalies bloquantes. Corrigez ou excluez avant envoi. »
- AC3 : En cliquant sur un contrat, je peux modifier uniquement : numéro de téléphone, montant, date d'échéance. Chaque modification est journalisée dans l'audit log (champ modifié, ancienne valeur, nouvelle valeur, opérateur, timestamp).
- AC4 : Je peux sélectionner N contrats et cliquer « Exclure » pour les retirer de la campagne en une action (bulk exclude).
- AC5 : Quand toutes les anomalies bloquantes sont résolues ou exclues et que je clique « Valider et Envoyer », une modale de confirmation s'affiche : « Envoyer à {N} client(s) ? [Confirmer / Annuler] ». Sur confirmation, la campagne passe à Envoyée et NOTIF est déclenché.
US-OP-05 [V1][OPERATOR] - Surveiller une campagne envoyée¶
En tant qu' opérateur d'agence,
je veux suivre en quasi-temps-réel les statuts de notification et de paiement de chaque contrat,
afin de détecter les échecs et agir rapidement.
- AC1 : Le détail de campagne affiche des compteurs agrégés mis à jour via SSE/WS (latence < 5 s) : total envoyé, livré (NOTIF), payé, échoué, % conversion.
- AC2 : Les contrats dont l'échéance est ≤ 7 jours et dont le paiement est non-terminal sont marqués d'un badge « URGENT » (rouge).
- AC3 : En cliquant sur un contrat, je vois : statut NOTIF (livré / échoué / en attente), statut paiement (non initié / initié / payé / échoué / hors-plateforme), expiration du lien signé, historique des actions opérateur sur ce contrat.
- AC4 : Je peux cliquer « Envoyer un rappel » sur un contrat non payé ; si le lien est expiré, un nouveau lien signé est généré (72h, ancien lien invalidé) et NOTIF envoie une nouvelle notification.
US-OP-06 [V1][OPERATOR] - Marquer un contrat comme réglé hors-plateforme¶
En tant qu' opérateur d'agence,
je veux enregistrer un paiement effectué en dehors de la plateforme,
afin que la réconciliation soit exacte même pour les paiements en cash ou par virement.
- AC1 : Sur la fiche d'un contrat en campagne Envoyée (statut non terminal), le bouton « Régler hors-plateforme » ouvre une modale avec : méthode de paiement (select : mobile money / cash / chèque / virement), date de paiement, montant payé, référence (optionnel).
- AC2 : À la validation, le statut du contrat passe à RÉGLÉ_HORS_PLATEFORME et un événement d'audit
HORS_PLATEFORME_MARKEDest créé avec l'identité de l'opérateur, la méthode, la date et le montant. - AC3 : Si le contrat est déjà PAYÉ via la plateforme, le bouton « Régler hors-plateforme » est désactivé.
US-OP-07 [V1][OPERATOR] - Annuler une campagne¶
En tant qu' opérateur d'agence,
je veux pouvoir annuler une campagne à tout moment (même après envoi),
afin de stopper immédiatement un lot envoyé par erreur.
- AC1 : Pour toute campagne non terminale, le bouton « Annuler la campagne » affiche une modale : « {X} lien(s) seront révoqués. Annuler quand même ? [Oui / Non] »
- AC2 : Sur confirmation : les envois NOTIF encore en queue sont annulés ; tous les liens signés des contrats non terminaux sont révoqués via AUTH ; la campagne passe à ANNULÉE ; les contrats non terminaux passent à LIEN_RÉVOQUÉ ; l'événement
CAMPAIGN_CANCELLEDest journalisé. - AC3 : Un client qui clique un lien révoqué voit : « Ce lien n'est plus valide. Veuillez contacter votre cabinet. » [CUSTOMER]
US-OP-08 [V1][OPERATOR] - Gérer les anomalies¶
En tant qu' opérateur d'agence,
je veux voir et résoudre les anomalies de données de mon agence,
afin qu' aucun contrat avec des données erronées ne parte en campagne sans correction préalable.
- AC1 : La vue Anomalies affiche la queue des anomalies ouvertes de mon agence, filtrables par type (bloquante / non-bloquante / surveillance), par contrat, et par statut.
- AC2 : En cliquant sur une anomalie, je vois la fiche contrat avec le champ défectueux mis en évidence et le contrôle d'édition activé pour téléphone / montant / date d'échéance uniquement.
- AC3 : Quand le champ est corrigé, je peux cliquer « Marquer comme résolu » ; l'anomalie passe à RÉSOLUE et un événement d'audit
ANOMALY_RESOLVEDest enregistré. - AC4 : Pour une anomalie de surveillance (ex. paiement en attente prolongée), « Marquer comme résolu » exige un champ note obligatoire.
US-OP-09 [V1][OPERATOR][ADMIN] - Dashboard opérationnel¶
En tant que superviseur, opérateur ou cabinet_admin,
je veux un dashboard de démarrage qui affiche l'état de santé opérationnel en un coup d'œil,
afin de prioriser mes actions sans naviguer dans tous les écrans.
- AC1 : Le dashboard affiche 4 widgets : (a) Contrats urgents - contrats à échéance ≤ 7 j non payés ; (b) Pipeline campagnes - compteurs par statut (Brouillon / Envoyée / Clôturée / Annulée) ; (c) Tunnel paiement - envoyé / payé / échoué + % conversion sur 30 j glissants ; (d) Anomalies bloquantes - nb non résolues + lien direct vers la vue anomalies.
- AC2 : Un
agency_operatorvoit uniquement les données de son agence. - AC3 : Un
supervisoroucabinet_adminvoit les agrégats cross-agences avec un filtre par agence.
US-OP-10 [V1][OPERATOR] - Rechercher un contrat ou un client¶
En tant qu' opérateur d'agence,
je veux trouver rapidement un contrat par nom client, téléphone ou référence contrat,
afin de répondre à un appel entrant sans naviguer dans les campagnes.
- AC1 : Une barre de recherche globale (accessible depuis n'importe quel écran) filtre en temps réel (debounced 300 ms) sur : nom client, numéro de téléphone (partiel), référence contrat - dans la portée agence/tenant.
- AC2 : Un clic sur un résultat ouvre la fiche contrat.
- AC3 : Seuls les contrats présents dans la base ingérée de la plateforme apparaissent dans les résultats (portée = données importées via ING pour ce tenant).
US-OP-11 [V1][ADMIN] - Exporter un rapport campagne / paiement¶
En tant que supervisor ou cabinet_admin,
je veux exporter les données d'une campagne ou de paiements filtrées en CSV/XLSX,
afin de produire les réconciliations et rapports mensuels.
- AC1 : Sur la liste des campagnes ou la vue paiements, après avoir appliqué mes filtres (agence, période, statut), je peux cliquer « Exporter ».
- AC2 : Si l'export dépasse 10 000 lignes, le système avertit et tronque le fichier avec une note en en-tête
[TRONQUÉ : {N} lignes sur {total}]. - AC3 : Un
agency_operatorne voit pas le bouton « Exporter ».
US-OP-12 [V1][ADMIN] - Configurer les paramètres cabinet¶
En tant que cabinet_admin,
je veux configurer la fenêtre de détection et les champs légaux CIMA,
afin d' adapter la plateforme à mon cabinet sans dépendre du support technique.
- AC1 : Le champ « Fenêtre de détection (jours) » accepte une valeur entière entre 7 et 90, avec une valeur par défaut de 30. Sur sauvegarde, le prochain batch de cohort utilise la nouvelle valeur et la modification est auditée (
SETTINGS_CHANGED). - AC2 : La section « Informations légales CIMA » permet de renseigner : nom du cabinet, adresse, numéro d'agrément CIMA. Ces champs alimentent les mentions légales dans le portail client. La structure des paragraphes CIMA obligatoires est gérée par la plateforme - le cabinet ne peut pas les supprimer.
US-OP-13 [V1][ADMIN] - Gérer les utilisateurs du cabinet¶
En tant que cabinet_admin,
je veux créer, modifier, désactiver et réinitialiser les mots de passe de mes collaborateurs,
afin de maintenir des accès nominatifs, justes et révocables.
- AC1 : Le formulaire « Nouvel utilisateur » requiert : prénom/nom, email, rôle (
agency_operator/supervisor/cabinet_admin), agence (obligatoire pouragency_operator). Sur sauvegarde, Keycloak crée le compte et envoie un email d'invitation. - AC2 : Modifier le rôle ou l'agence d'un utilisateur prend effet immédiatement ; un événement d'audit
OP_USER_ROLE_CHANGEDest enregistré. - AC3 : Désactiver un utilisateur lui retire l'accès immédiatement ; son historique d'audit est conservé ; son statut affiche « Désactivé ».
- AC4 : « Réinitialiser le mot de passe » déclenche un email de réinitialisation via Keycloak.
US-OP-14 [V1][OPERATOR] - Ajouter un contrat à une campagne envoyée¶
En tant qu' opérateur d'agence,
je veux ajouter un contrat manqué à une campagne déjà envoyée et le notifier immédiatement,
afin de ne pas créer une nouvelle campagne pour un cas isolé.
- AC1 : Sur le détail d'une campagne Envoyée, un bouton « Ajouter un contrat » ouvre un sélecteur de contrats éligibles (non actifs dans une autre campagne active).
- AC2 : Sur sélection d'un contrat, une modale de confirmation s'affiche : « Ajouter et notifier ce contrat ? [Confirmer / Annuler] ».
- AC3 : Sur confirmation, le contrat est ajouté à la campagne et NOTIF envoie immédiatement une notification. Un événement d'audit
CONTRACT_ADDED_TO_CAMPAIGNest enregistré.
A.4 Exigences Non-Fonctionnelles¶
| Catégorie | Exigence | Cible V1 |
|---|---|---|
| Interface | Desktop-first | Optimisé 1280 px, utilisable ≥ 1024 px |
| Interface | Langue | Français uniquement ; toutes les chaînes via i18n |
| Interface | Dates | DD/MM/YYYY ; heures HH:mm (24h) ; timezone UTC+0 (CI) |
| Interface | Montants | XOF entier, espace séparateur milliers, 0 décimale |
| Performance | Chargement initial | ≤ 2 s (réseau bureau) |
| Performance | Transitions entre écrans | ≤ 300 ms (navigation client-side) |
| Performance | Actions d'écriture | ≤ 3 s (validation campagne, exclusion, correction) |
| Performance | Latence temps réel (SSE/WS) | < 5 s pour mises à jour de statuts |
| Performance | Pagination campagnes | 25 par page |
| Performance | Pagination contrats (détail) | 50 par page |
| Performance | Export max | 10 000 lignes |
| Connectivité | Mode offline | Lecture listes chargées + notes localStorage |
| Sécurité | Déconnexion auto | 30 min d'inactivité (Keycloak) |
| Sécurité | Isolation tenant | Toute requête filtrée sur tenant_id |
| Sécurité | Scoping agence | Middleware ajoute agency_id pour agency_operator |
A.5 Périmètre MVP V1¶
Inclus en V1 : - Interface back-office complète (tous les écrans §21 PRD V1) hébergée dans OP - Campaign engine : cohort planifiée (≥ 2×/semaine) + campagnes ad hoc - Correction workshop (téléphone, montant, date d'échéance uniquement) - Exclusion en lot (bulk exclude) - Surveillance post-envoi SSE/WebSocket (< 5 s) - Rappels manuels + renvoi de lien avec nouveau lien signé - Marquage hors-plateforme (méthode, date, montant, référence optionnelle) - Annulation de campagne avec révocation totale des liens signés - Dashboard 4 widgets - Recherche globale dans les données ingérées - Export CSV/XLSX (supervisor + cabinet_admin uniquement) - Gestion utilisateurs Keycloak (créer, modifier, désactiver, reset mot de passe) - Paramètres cabinet (fenêtre détection 7–90 j + identité légale CIMA) - Vue anomalies + résolution inline + marquage résolu - Offline minimum : lecture last-synced + notes localStorage synchronisées
Reporté :
| Fonctionnalité | Version |
|---|---|
| Rappels automatiques planifiés par campagne | V2 |
| Personnalisation templates notification par cabinet | V3 |
| Canal de notification configurable par tenant | V3 |
| Fenêtre de validité de lien configurable par tenant | V3 |
| Analytics avancées et dashboards segmentés | V2 |
| Gestion des quotas SMS/WhatsApp in-app | V2 |
| Workflow d'approbation Meta templates WhatsApp dans OP | V2 |
| Assignment et suivi d'anomalies par opérateur | V2 |
| Export multi-entités / consolidation groupe | V2 |
| API publique OP pour intégration ERP | V3 |
| Campagnes multi-step / scénarios branchés | V3 |
| Mode multilingue | V2+ |
A.6 Questions Ouvertes¶
| ID | Question | Module(s) |
|---|---|---|
| OQ-01 | Le quota de messages SMS/WhatsApp inclus dans l'abonnement tenant doit-il déclencher un avertissement in-app dans OP (ex. « 80 % du quota mensuel utilisé ») ? | OP + BILL |
| OQ-02 | La validation des templates WhatsApp (pré-approbation Meta) est gérée out-of-band en V1. Faut-il afficher un statut de template (approuvé / en attente / rejeté) dans les paramètres cabinet ? | OP + NOTIF |
| OQ-03 | Les numéros de téléphone doivent-ils être partiellement masqués dans les vues liste (ex. +225 XX XX ** **) au titre de la minimisation ARTCI, en complément du masquage DOB ? |
OP |
| OQ-04 | La génération de cohort planifiée : calendrier global ou per-tenant avec timezone ? En V1 CI (UTC+0) la question est mineure, mais doit être tranchée avant V2 multi-pays. | OP + TENANT |
| OQ-05 | Champ renewal_policy dans le schéma d'import ING : quel est le nom exact et le format ? (entier = mois, ou enum ?) À aligner avec le PRD ING. |
OP + ING |
| OQ-06 | Un cabinet_admin peut-il se désactiver lui-même ou désactiver le seul cabinet_admin du tenant ? Ou doit-il toujours exister ≥ 1 cabinet_admin actif par tenant ? | OP + TENANT |
A.7 Hypothèses Temporairement Validées¶
| ID | Hypothèse | Statut |
|---|---|---|
| TV-01 | L'approche « textes CIMA gérés par la plateforme, cabinet renseigne ses données d'identité » est supposée suffisante pour les obligations d'information de CIMA 01-24. | PRÉLIMINAIRE - [LEGAL-REVIEW] avant production |
| TV-02 | La fenêtre de validité de lien signé à 72h est supposée compatible avec les délais d'offre acceptables en renouvellement d'assurance selon CIMA. | PRÉLIMINAIRE - [LEGAL-REVIEW] avant production |
| TV-03 | Les fonctionnalités utilisant WhatsApp et le traitement des numéros de téléphone sont développées sans restriction fonctionnelle en V1. La mise en conformité ARTCI (§B10, §B5 du mémo) est traitée hors code applicatif par l'équipe Papillon. | PRÉLIMINAIRE - validé fondateur (2026-05-19) |
Partie B - Spécifications Fonctionnelles¶
B.1 Règles Fonctionnelles¶
FR-OP-01 - Génération de cohort [V1][BACKEND]¶
SI contract.due_date ∈ [today, today + cabinet_settings.renewal_detection_window_days]
ET aucun campaign_contract actif n'existe pour ce contrat (pas de ligne avec campaign.status NOT IN ('CLÔTURÉE','ANNULÉE') ET campaign_contract.status NOT IN ('EXCLU','PAYÉ','RÉGLÉ_HORS_PLATEFORME','LIEN_EXPIRÉ','LIEN_RÉVOQUÉ'))
ET le contrat n'est pas marqué « déjà traité » dans la même période de renouvellement
ALORS le contrat est éligible pour la cohort.
- Génération planifiée : au moins 2 fois par semaine (job backend, heure configurable au niveau plateforme, non exposée en V1).
- Résultat : création d'une
Campaign(type =SCHEDULED, statut =BROUILLON) avec les contrats éligibles enCampaignContract(statut =INCLUS). - Si aucun contrat éligible : aucune campagne n'est créée.
FR-OP-02 - Garde de validation de campagne [V1][OPERATOR]¶
SI un contrat campaign_contract.status = INCLUS a ≥ 1 anomalie de type BLOQUANTE à l'état OUVERTE ou EN_COURS
ALORS la campagne ne peut pas passer à ENVOYÉE.
Message bloquant : « {N} contrat(s) présentent des anomalies bloquantes. Corrigez les données ou excluez les contrats avant d'envoyer. »
Anomalies NON_BLOQUANTES et SURVEILLANCE : n'empêchent pas la validation, affichent un badge orange + compteur sur le bouton « Valider ».
FR-OP-03 - Nommage de campagne [V1][BACKEND]¶
- Format :
"Campagne {YYYY-MM-DD} - {nom_agence}"(date de création, timezone tenant = UTC+0 pour CI). - Calculé à la création, stocké, non modifiable.
- Doublon même jour/même agence :
"Campagne {YYYY-MM-DD} - {nom_agence} ({n})"(n incrémental démarrant à 2).
FR-OP-04 - Déduplication de cohort [V1][BACKEND]¶
Avant d'ajouter un contrat à une campagne (planifiée ou ad hoc) :
EXISTS (
SELECT 1 FROM campaign_contracts cc
JOIN campaigns c ON c.id = cc.campaign_id
WHERE cc.contract_id = :contractId
AND c.tenant_id = :tenantId
AND c.status NOT IN ('CLÔTURÉE', 'ANNULÉE')
AND cc.status NOT IN ('EXCLU','PAYÉ','RÉGLÉ_HORS_PLATEFORME','LIEN_EXPIRÉ','LIEN_RÉVOQUÉ')
)
Si vrai → contrat inéligible. Dans le sélecteur ad hoc : grisé avec tooltip "Déjà dans la campagne {nom_campagne}".
FR-OP-05 - Annulation de campagne [V1][OPERATOR]¶
- Modale :
"{X} lien(s) seront révoqués. Annuler quand même ? [Oui / Non]"(X = contrats non terminaux). - Sur confirmation :
campaign.status → ANNULÉE;cancelled_at,cancelled_byenregistrés.- Appel NOTIF : annuler les envois en queue pour cette campagne.
- Appel AUTH : révoquer les liens signés de tous les contrats non terminaux (
PAYÉ,RÉGLÉ_HORS_PLATEFORMEexclus). campaign_contract.status → LIEN_RÉVOQUÉpour les contrats non terminaux.- Audit event :
CAMPAIGN_CANCELLED { campaignId, cancelledBy, linksRevokedCount, timestamp }.
FR-OP-06 - Masquage de la date de naissance [V1][OPERATOR]¶
| Vue | Affichage DOB |
|---|---|
| Vues liste / tableaux (campagne, anomalie, recherche) | **/**/YYYY |
| Fiche contrat individuelle | DD/MM/YYYY (clair) |
Règle s'applique à tous les rôles dans les vues liste.
FR-OP-07 - Champs modifiables dans le correction workshop [V1][OPERATOR]¶
Éditables : phone_number, amount (XOF entier), due_date.
Lecture seule : tous les autres champs (branche produit, politique renouvellement, identifiants source).
amount: entier positif > 0, jamais float.- Chaque modification → audit event
FIELD_CORRECTED { contractId, campaignId, fieldName, oldValue, newValue, operatorId, timestamp }.
FR-OP-08 - Marquage hors-plateforme [V1][OPERATOR]¶
Précondition : campaign.status = ENVOYÉE ET campaign_contract.status NOT IN ('PAYÉ','LIEN_RÉVOQUÉ','EXCLU').
Champs requis : payment_method (MOBILE_MONEY | CASH | CHEQUE | VIREMENT), payment_date (≤ today), amount_paid (XOF entier > 0).
Champ optionnel : reference (varchar 200).
Effet : campaign_contract.status → RÉGLÉ_HORS_PLATEFORME.
Audit event : HORS_PLATEFORME_MARKED { contractId, campaignId, method, amount, date, reference?, operatorId, timestamp }.
FR-OP-09 - Renvoi de lien / rappel [V1][OPERATOR]¶
SI campaign.status = ENVOYÉE
ET campaign_contract.status ∈ { NOTIF_LIVRÉ, NOTIF_ÉCHOUÉ, LIEN_EXPIRÉ, PAIEMENT_ÉCHOUÉ }
ALORS bouton « Envoyer un rappel » actif.
Mécanisme :
1. AUTH → nouveau lien signé 72h ; ancien lien invalidé.
2. NOTIF → nouvelle notification (WhatsApp d'abord, SMS fallback).
3. campaign_contract.status → NOTIF_EN_ATTENTE.
4. Audit event : NOTIFICATION_RESENT { contractId, campaignId, operatorId, newLinkExpiry, timestamp }.
FR-OP-10 - Politique de renouvellement (read-only) [V1][BACKEND]¶
renewal_policyimportée avec le contrat via ING (champ optionnel dans le fichier d'import).- Si absent → valeur par défaut de
product_branch_renewal_defaults(table seedée par la plateforme). - OP affiche en lecture seule sur la fiche contrat. Modification hors périmètre OP.
FR-OP-11 - Template de notification (géré plateforme) [V1][BACKEND]¶
Template générique unique par canal (WhatsApp, SMS), géré plateforme, non exposé en édition dans OP V1.
Champs de fusion rendus à l'envoi :
| Champ | Source |
|---|---|
{{nom_client}} |
customer.full_name |
{{montant}} |
montant en XOF (ex. 15 000 XOF) |
{{date_echeance}} |
contract.due_date au format DD/MM/YYYY |
{{lien}} |
URL lien signé (AUTH) |
{{nom_cabinet}} |
cabinet_settings.cima_legal_name |
{{type_contrat}} |
contract.product_branch |
{{numero_contrat}} |
contract.source_contract_id |
La pré-approbation des templates WhatsApp (Meta Business API) est gérée hors-bande par l'équipe Papillon en V1.
FR-OP-12 - Paramètres cabinet [V1][ADMIN]¶
renewal_detection_window_days: entier ∈ [7, 90], default 30. Chaque modification → audit eventSETTINGS_CHANGED.cima_legal_name(varchar 200),cima_legal_address(text),cima_license_number(varchar 50) : alimentent les mentions légales du portail client.- Constantes plateforme non modifiables en V1 : canal de notification (WhatsApp → SMS), validité du lien signé (72h).
FR-OP-13 - Gestion des utilisateurs [V1][ADMIN]¶
- Un
cabinet_adminne gère que les utilisateurs de son propre tenant. - Hiérarchie :
cabinet_admin > supervisor > agency_operator. - Il doit toujours exister ≥ 1
cabinet_adminactif par tenant (voir OQ-06). - Le premier
cabinet_adminest provisionné par TENANT lors de l'onboarding. - OP appelle l'API Admin Keycloak pour créer / modifier / désactiver les utilisateurs.
FR-OP-14 - Export de données [V1][ADMIN]¶
- Accessible aux rôles
supervisoretcabinet_adminuniquement. - Portée : données filtrées, scoped
tenant_id(+agency_idsi filtre par agence). - Formats : CSV (primaire), XLSX (secondaire).
- Limite 10 000 lignes ; si dépassé : avertissement + note en-tête dans le fichier.
- URLs de téléchargement : liens signés à usage unique, validité 10 min, générés côté serveur.
- Audit event :
DATA_EXPORTED { exportType, filters, rowCount, exportedBy, timestamp }.
FR-OP-15 - Notes locales offline [V1][OPERATOR]¶
- Stockées en
localStorage:{ entityType, entityId, content, localTimestamp, synced: false }. - À la reconnexion : OP POST les notes non synchronisées vers
POST /operator-notes. - En cas de conflit (note locale vs. note serveur sur le même
entityId) : les deux sont conservées.
B.2 Machines à États¶
Campagne¶
stateDiagram-v2
[*] --> BROUILLON : Cohort générée (planifiée ou ad hoc)
BROUILLON --> ENVOYÉE : Opérateur valide & confirme\n(0 anomalie bloquante non résolue)
ENVOYÉE --> CLÔTURÉE : Opérateur clôture\nOU tous contrats en état terminal
BROUILLON --> ANNULÉE : Opérateur annule
ENVOYÉE --> ANNULÉE : Opérateur annule (liens révoqués)
CLÔTURÉE --> [*]
ANNULÉE --> [*]
Contrat dans une campagne (CampaignContract)¶
stateDiagram-v2
[*] --> INCLUS : Ajouté à la campagne
INCLUS --> EXCLU : Opérateur exclut
INCLUS --> NOTIF_EN_ATTENTE : Campagne validée - NOTIF en queue
NOTIF_EN_ATTENTE --> NOTIF_LIVRÉ : Delivery confirmée
NOTIF_EN_ATTENTE --> NOTIF_ÉCHOUÉ : Delivery échouée (retries épuisés)
NOTIF_LIVRÉ --> LIEN_OUVERT : Client ouvre le lien (événement CP)
LIEN_OUVERT --> PAYÉ : Paiement confirmé (événement PAY)
LIEN_OUVERT --> PAIEMENT_ÉCHOUÉ : Paiement échoué (événement PAY)
NOTIF_LIVRÉ --> LIEN_EXPIRÉ : 72h sans paiement
LIEN_OUVERT --> LIEN_EXPIRÉ : 72h sans paiement
PAIEMENT_ÉCHOUÉ --> NOTIF_EN_ATTENTE : Opérateur envoie rappel
LIEN_EXPIRÉ --> NOTIF_EN_ATTENTE : Opérateur envoie rappel (nouveau lien)
NOTIF_ÉCHOUÉ --> NOTIF_EN_ATTENTE : Opérateur envoie rappel
NOTIF_LIVRÉ --> RÉGLÉ_HORS_PLATEFORME : Opérateur marque
NOTIF_ÉCHOUÉ --> RÉGLÉ_HORS_PLATEFORME : Opérateur marque
LIEN_EXPIRÉ --> RÉGLÉ_HORS_PLATEFORME : Opérateur marque
INCLUS --> LIEN_RÉVOQUÉ : Campagne annulée
NOTIF_EN_ATTENTE --> LIEN_RÉVOQUÉ : Campagne annulée
NOTIF_LIVRÉ --> LIEN_RÉVOQUÉ : Campagne annulée
NOTIF_ÉCHOUÉ --> LIEN_RÉVOQUÉ : Campagne annulée
LIEN_OUVERT --> LIEN_RÉVOQUÉ : Campagne annulée
LIEN_EXPIRÉ --> LIEN_RÉVOQUÉ : Campagne annulée
PAIEMENT_ÉCHOUÉ --> LIEN_RÉVOQUÉ : Campagne annulée
États terminaux : PAYÉ, RÉGLÉ_HORS_PLATEFORME, EXCLU, LIEN_RÉVOQUÉ
Anomalie¶
stateDiagram-v2
[*] --> OUVERTE : Détectée par ING (import) ou job de monitoring
OUVERTE --> EN_COURS : Opérateur ouvre la fiche
EN_COURS --> RÉSOLUE : Opérateur corrige + marque résolu
EN_COURS --> IGNORÉE : Contrat exclu de la campagne
OUVERTE --> IGNORÉE : Contrat exclu de la campagne
RÉSOLUE --> [*]
IGNORÉE --> [*]
B.3 Tables de Décision¶
TD-1 - Garde de validation campagne¶
| Anomalies BLOQUANTES (contrats INCLUS) | Anomalies NON_BLOQUANTES | Envoi autorisé ? | Affichage |
|---|---|---|---|
| 0 | N'importe | OUI | Bouton « Valider et Envoyer » actif |
| > 0 | N'importe | NON | Badge rouge + message bloquant + lien vue anomalies |
Anomalies NON_BLOQUANTES et SURVEILLANCE : badge orange sur le contrat + compteur non bloquant - n'empêchent pas l'envoi.
TD-2 - Badge d'urgence sur un contrat¶
| Jours avant échéance | Statut paiement | Badge |
|---|---|---|
| ≤ 7 jours | Non-terminal | 🔴 URGENT |
| > 7 jours | Non-terminal | (aucun) |
| N'importe | Terminal | (aucun) |
TD-3 - Actions disponibles par statut CampaignContract¶
| Statut | Envoyer rappel | Régler hors-plateforme | Exclure | Ajout autre campagne |
|---|---|---|---|---|
| INCLUS | - | - | ✅ | ❌ |
| NOTIF_EN_ATTENTE | - | ✅ | ✅ | ❌ |
| NOTIF_LIVRÉ | ✅ | ✅ | - | ❌ |
| NOTIF_ÉCHOUÉ | ✅ | ✅ | - | ❌ |
| LIEN_OUVERT | ✅ | ✅ | - | ❌ |
| LIEN_EXPIRÉ | ✅ | ✅ | - | ❌ |
| PAIEMENT_ÉCHOUÉ | ✅ | ✅ | - | ❌ |
| PAYÉ | - | - | - | ❌ |
| RÉGLÉ_HORS_PLATEFORME | - | - | - | ❌ |
| EXCLU | - | - | - | ✅ |
| LIEN_RÉVOQUÉ | - | - | - | ✅ |
B.4 Modèle de Données¶
Entités appartenant à OP¶
CREATE TABLE campaigns (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id),
agency_id UUID NOT NULL REFERENCES agencies(id),
name VARCHAR(200) NOT NULL,
type VARCHAR(20) NOT NULL DEFAULT 'SCHEDULED'
CHECK (type IN ('SCHEDULED', 'AD_HOC')),
status VARCHAR(30) NOT NULL DEFAULT 'BROUILLON'
CHECK (status IN ('BROUILLON','ENVOYÉE','CLÔTURÉE','ANNULÉE')),
created_by UUID NOT NULL REFERENCES users(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
sent_at TIMESTAMPTZ,
closed_at TIMESTAMPTZ,
cancelled_at TIMESTAMPTZ,
cancelled_by UUID REFERENCES users(id),
cohort_params JSONB
);
-- Index : (tenant_id, agency_id, status), (tenant_id, created_at DESC)
CREATE TABLE campaign_contracts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id),
campaign_id UUID NOT NULL REFERENCES campaigns(id),
contract_id UUID NOT NULL REFERENCES contracts(id),
status VARCHAR(40) NOT NULL DEFAULT 'INCLUS'
CHECK (status IN (
'INCLUS','EXCLU',
'NOTIF_EN_ATTENTE','NOTIF_LIVRÉ','NOTIF_ÉCHOUÉ',
'LIEN_OUVERT','PAYÉ','PAIEMENT_ÉCHOUÉ',
'RÉGLÉ_HORS_PLATEFORME','LIEN_EXPIRÉ','LIEN_RÉVOQUÉ'
)),
excluded_by UUID REFERENCES users(id),
excluded_at TIMESTAMPTZ,
exclusion_reason VARCHAR(500),
hp_method VARCHAR(20)
CHECK (hp_method IN ('MOBILE_MONEY','CASH','CHEQUE','VIREMENT')),
hp_date DATE,
hp_amount BIGINT,
hp_reference VARCHAR(200),
hp_marked_by UUID REFERENCES users(id),
hp_marked_at TIMESTAMPTZ,
UNIQUE (campaign_id, contract_id)
);
-- Index : (tenant_id, campaign_id), (tenant_id, contract_id, status)
CREATE TABLE operator_notes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
agency_id UUID NOT NULL,
entity_type VARCHAR(20) NOT NULL CHECK (entity_type IN ('CONTRACT','CAMPAIGN')),
entity_id UUID NOT NULL,
content TEXT NOT NULL,
created_by UUID NOT NULL REFERENCES users(id),
created_at TIMESTAMPTZ NOT NULL,
synced_at TIMESTAMPTZ,
device_local_id VARCHAR(100)
);
CREATE TABLE cabinet_settings (
tenant_id UUID PRIMARY KEY REFERENCES tenants(id),
renewal_detection_window_days SMALLINT NOT NULL DEFAULT 30
CHECK (renewal_detection_window_days BETWEEN 7 AND 90),
cima_legal_name VARCHAR(200),
cima_legal_address TEXT,
cima_license_number VARCHAR(50),
updated_by UUID REFERENCES users(id),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
Entités lues depuis d'autres modules¶
| Entité | Module propriétaire | Accès OP |
|---|---|---|
contracts, customers, deadlines |
ING | Lecture via API REST |
anomalies |
ING (détection) / OP (résolution) | Lecture + PATCH statut résolution |
notifications |
NOTIF | Lecture statut ; POST send via API |
payments |
PAY | Lecture statut uniquement |
tenants, agencies |
TENANT | Lecture via API |
users (Keycloak) |
AUTH | CRUD via API Admin Keycloak |
audit_events |
AUDIT | POST uniquement |
B.5 Implications Multi-Tenant¶
- Isolation stricte : toute requête DB filtrée sur
tenant_id. Aucune jointure cross-tenant possible. - Agency scoping : pour
agency_operator, un middleware Spring ajoute automatiquementAND agency_id = :currentUserAgencyIdà toutes les requêtes de lecture et d'écriture. - Profil BYO-DB : les 4 tables OP (
campaigns,campaign_contracts,operator_notes,cabinet_settings) résident dans la base du tenant si profil BYO-DB. Le résolveur de datasource multitenante route automatiquement. - Cohort scheduling : s'exécute séquentiellement pour chaque tenant actif. En V1 CI-seul (UTC+0), pas d'ambiguïté de timezone. En V2+ multi-pays, le job devra tenir compte du
country_codedu tenant. - V2 readiness : aucune contrainte
UNIQUEsurcampaigns.namesanstenant_id. Schéma compatible N agences sans migration.
B.6 Dépendances Cross-Module¶
APIs consommées par OP¶
| Module | Endpoint | Usage |
|---|---|---|
| ING | GET /contracts?agencyId=&cohortWindow= |
Génération cohort + sélecteur ad hoc |
| ING | GET /contracts/{id} |
Fiche contrat individuelle |
| ING | POST /imports |
Déclenchement import |
| ING | GET /imports/{id} |
Résultat import |
| ING | GET /anomalies?agencyId=&status= |
Vue anomalies |
| ING | PATCH /anomalies/{id} |
Résolution anomalie |
| NOTIF | POST /notifications/batch |
Envoi campagne |
| NOTIF | DELETE /notifications?campaignId= |
Annulation envois en queue |
| NOTIF | POST /notifications/single |
Rappel individuel / renvoi lien |
| NOTIF | GET /notifications/status?contractId= |
Statut notification |
| PAY | GET /payments?contractId= |
Statut paiement |
| AUTH | POST /links/generate |
Nouveau lien signé (rappel) |
| AUTH | POST /links/revoke |
Révocation liens (annulation campagne) |
| AUTH | Admin Keycloak API | CRUD utilisateurs |
| AUDIT | POST /events |
Journalisation toutes actions |
| TENANT | GET /cabinets/{id} |
Profil cabinet + agences + country_code |
Événements publiés par OP¶
| Événement | Déclencheur | Consommateurs |
|---|---|---|
OP_CAMPAIGN_VALIDATED |
Validation + confirmation | AUDIT, NOTIF |
CAMPAIGN_CANCELLED |
Annulation | AUDIT, AUTH, NOTIF |
CONTRACT_EXCLUDED |
Exclusion | AUDIT |
CONTRACT_ADDED_TO_CAMPAIGN |
Ajout post-envoi | AUDIT, NOTIF |
FIELD_CORRECTED |
Correction workshop | AUDIT |
HORS_PLATEFORME_MARKED |
Marquage hors-plateforme | AUDIT, PAY |
NOTIFICATION_RESENT |
Renvoi lien / rappel | AUDIT |
ANOMALY_RESOLVED |
Résolution anomalie | AUDIT |
OP_USER_CREATED |
Création utilisateur | AUDIT |
OP_USER_ROLE_CHANGED |
Modification rôle/agence | AUDIT |
OP_USER_DEACTIVATED |
Désactivation | AUDIT |
SETTINGS_CHANGED |
Modification paramètres cabinet | AUDIT |
DATA_EXPORTED |
Export CSV/XLSX | AUDIT |
IMPORT_TRIGGERED |
Déclenchement import | AUDIT, ING |
Événements reçus par OP (mise à jour statuts via SSE/WS)¶
| Événement | Source | Effet dans OP |
|---|---|---|
NOTIF_SENT |
NOTIF | campaign_contract.status → NOTIF_LIVRÉ |
NOTIF_FAILURE |
NOTIF | campaign_contract.status → NOTIF_ÉCHOUÉ |
CP_LINK_OPENED |
CP | campaign_contract.status → LIEN_OUVERT |
PAY_CONFIRMED |
PAY | campaign_contract.status → PAYÉ |
PAY_FAILED |
PAY | campaign_contract.status → PAIEMENT_ÉCHOUÉ |
AUTH_LINK_REJECTED_EXPIRED |
AUTH | campaign_contract.status → LIEN_EXPIRÉ |
Partie C - Contraintes et Frontières¶
C.1 Conformité Réglementaire¶
CIMA Régulation 01-24¶
- La plateforme est positionnée comme prestataire de service technique agissant pour le compte de cabinets et compagnies d'assurance. Aucun écran OP ne présente Papillon comme un distributeur d'assurance indépendant.
[VÉRIFIÉ] - Les informations légales affichées sur le portail client sont co-gérées : la plateforme fournit la structure des paragraphes obligatoires, le cabinet renseigne ses données d'identité (nom, adresse, numéro d'agrément).
[TV-01 - PRÉLIMINAIRE - LEGAL-REVIEW avant production] - Le module OP génère une piste d'audit suffisante pour reconstituer la chronologie complète de tout cycle de relance (import → campagne → notification → authentification → paiement), conformément au §16.5 du PRD V1.
[VÉRIFIÉ]
ARTCI / Loi n°2013-450¶
- Minimisation des données : la date de naissance est masquée dans toutes les vues liste (
**/**/YYYY). Seule la fiche contrat individuelle l'expose en clair. - Traçabilité des accès : tout accès à une fiche contrat est journalisé dans AUDIT (opérateur + timestamp).
- Sous-traitance : le traitement des données clients par la plateforme pour le compte des cabinets est encadré par les clauses DPA des contrats B2B. OP lit uniquement les données ingérées par ING.
[PRÉLIMINAIRE - LEGAL-REVIEW]: L'utilisation de WhatsApp Cloud API (Meta) implique un transfert de données hors CI. La mise en conformité ARTCI (§B10 du mémo) est traitée hors code applicatif - cf. TV-03.
C.2 Localisation¶
- Interface entièrement en français. Zéro chaîne en dur dans le code - toutes via i18n.
- Dates : DD/MM/YYYY. Heures : HH:mm (24h). Timezone CI : UTC+0.
- Montants : XOF uniquement en V1. Format :
15 000 XOF(espace séparateur milliers, 0 décimale). Stockage : entier XOF, jamais float. - Téléphones : format CI
+225 XX XX XX XX. - Termes métier : prime, échéance, assuré, souscripteur, quittance, cabinet de courtage, agence.
- Messages d'erreur : description claire + action recommandée. Jamais « Une erreur s'est produite » seul.
C.3 Sécurité¶
- Isolation tenant : middleware Spring vérifie la correspondance entre le
tenant_iddu JWT et letenant_idde chaque ressource. Aucune requête cross-tenant possible. - Agency scoping : pour
agency_operator, le middleware ajouteagency_idautomatiquement à toutes les requêtes. - Session Keycloak : access token 15 min, refresh 30 min d'inactivité. Déconnexion automatique après 30 min.
- Audit log synchrone : les événements listés en B.6 sont écrits de façon synchrone - un échec d'écriture d'audit bloque l'action métier.
- SSE/WS : connexions authentifiées par token Keycloak, scoped
tenant_id+agency_id. - URLs d'export : liens signés à usage unique, validité 10 min, générés côté serveur.
- Révocation de liens signés : lors d'une annulation de campagne, AUTH invalide tous les tokens des contrats non terminaux de façon synchrone avant que la campagne ne passe à ANNULÉE.
C.4 Connectivité¶
- OP est desktop-first, online-first. Cible : connexion bureau stable (4G/fibre).
- Bandeau offline : si la connexion est perdue, bandeau
« Connexion perdue. Certaines fonctions sont indisponibles. »+ blocage des actions d'écriture. - Données déjà chargées : listes déjà en mémoire React restent consultables hors-ligne (read-only), sans service worker.
- Notes locales : écrites en
localStorage, synchronisées àPOST /operator-notesà la reconnexion (FR-OP-15). - Dégradation gracieuse : si ING, NOTIF ou PAY ne répondent pas, OP affiche un indicateur de chargement (timeout 10 s) +
« Erreur : impossible de charger les données. [Réessayer] ». Aucune action silencieuse. - Fallback SSE/WS → polling : si le canal temps réel est indisponible, OP bascule sur un polling toutes les 30 s avec reconnexion SSE/WS en back-off exponentiel.
C.5 Hors Périmètre V1¶
| Fonctionnalité | Version cible | Raison |
|---|---|---|
| Rappels automatiques planifiés par campagne | V2 | Moteur de règles requis ; V1 = humain-in-the-loop |
| Personnalisation templates notification par cabinet | V3 | Contrainte Meta pré-approbation + UX |
| Canal de notification configurable par tenant | V3 | Décision produit |
| Fenêtre de validité de lien configurable par tenant | V3 | 72h fixe en V1 |
| Analytics avancées et dashboards segmentés | V2 | Hors périmètre MVP |
| Gestion des quotas SMS/WhatsApp in-app | V2 | Dépend de BILL |
| Workflow d'approbation Meta templates WhatsApp dans OP | V2 | Out-of-band en V1 |
| Assignment d'anomalies par opérateur | V2 | Queue partagée en V1 |
| Export multi-entités / consolidation groupe | V2 | Architecture groupe = V2 |
| API publique OP pour intégration ERP | V3 | API-first = V3 |
| Campagnes multi-step / scénarios branchés | V3 | Orchestration V3 |
| Mode multilingue | V2+ | V1 = français uniquement |