Skip to content

Flows transactionnels config-driven

Périmètre : architecture des 7 flows transactionnels portés par l'orchestrator (P2P, MERCHANT_PAY, CASH_IN, CASH_OUT, MA_CASH_OUT, MA_COMM_COLLECT, MASTER_AGENT_CASH_IN). Source de référence : ticket NEX-438 (Epic 1 à 7). Date : 2026-05-12.


1. Objectif

Centraliser la définition de chaque type de transaction dans une FlowDefinition DSL stockée en base (configuration.transaction_flow_schemas) plutôt que de la dispatcher dans le code via des switch (intent.type).

Bénéfices :

  • Modifier la séquence d'étapes (ex : insérer un risk_evaluation avant le récap) ne nécessite aucun déploiement — seulement une UPDATE en DB + cache invalidation.
  • Les apps mobiles peuvent dérouler le wizard sans coder le séquencement : elles consomment flowSnapshot.steps[] depuis l'intent.
  • Le simulateur CMMS rejoue chaque flow à l'identique à partir du même schéma.

2. Anatomie d'un FlowSchema

jsonc
{
  "transactionType": "P2P",
  "schemaVersion": "1.0.0",
  "isActive": true,
  "schema": {
    "steps": [
      { "kind": "recipient_input", "channel": "phone", "fields": ["phone"] },
      { "kind": "amount_input", "fields": ["amount"] },
      { "kind": "risk_evaluation" },
      { "kind": "review_screen", "labels": ["recipient", "amount", "fees", "total"] },
      { "kind": "pin_challenge" }
    ],
    "postActions": [
      { "kind": "notify_sender", "channel": "sms" },
      { "kind": "notify_receiver", "channel": "sms" },
      { "kind": "emit_receipt" }
    ]
  }
}

2.1 Étapes (steps[])

Les kind actuellement supportés par les renderers (mobile + simulator CMMS) :

kindRôle
recipient_inputSaisie du destinataire (numéro, QR, code marchand, ID agent — pilotée par channel).
amount_inputSaisie du montant.
risk_evaluationPre-flight risk API-gated (cf. Pre-flight risk).
review_screenRécapitulatif sémantique (labels déclaratifs traduits côté UI).
pin_challengeAuthentification PIN du sender.
otp_challengeCode OTP envoyé par SMS / WhatsApp (CASH_OUT uniquement aujourd'hui).
biometric_challengeEmpreinte / Face ID (placeholder V2).

Un step inconnu côté client est rendu par StepUpdateRequired qui demande de mettre à jour l'app — pas de fallback silencieux.

2.2 Post-actions (postActions[])

Déclenchées par PostActionsDispatcherService après le passage en succeeded. Chaque action enqueue un job BullMQ dédié (notification SMS, push, reçu PDF, callback marchand…). Le dispatcher est agnostique du type d'intent : il consomme flowSnapshot.postActions[] posé à la création.


3. Snapshot à la création (flowSnapshot)

Quand un intent est créé :

  1. CreateIntentUseCase résout le FlowSchema actif pour le transactionType via ConfigurationHttpAdapter.
  2. Il copie le schema complet dans intent.flow_snapshot (JSONB).
  3. Toute la suite du cycle de vie (confirm, cancel, dispatch des post-actions) lit le snapshot, jamais le schéma en base.

Pourquoi snapshot ? Si on modifie le schéma en production pendant qu'un intent est en cours, le client doit pouvoir terminer son flow tel qu'il l'a démarré. Le snapshot fige la définition au moment où le user clique sur "Continuer".


4. Strategy Pattern par IntentType

Deux familles de stratégies orchestrent les variations par type de transaction sans toucher au useCase principal :

4.1 IntentCreationStrategy

Responsabilité : résoudre les comptes (sourceAccountId, destAccountId) à partir du payload de création.

IntentTypeStrategy
TRANSFER (P2P)TransferCreationStrategy
MERCHANT_PAYMENTMerchantPaymentCreationStrategy
CASH_INCashInCreationStrategy
CASH_OUTCashOutCreationStrategy
MASTER_AGENT_CASH_IN / MA_CASH_OUT / MA_COMM_COLLECTMasterAgentCreationStrategy (partagée)

4.2 IntentConfirmationStrategy

Responsabilité : calculer les mouvements ledger au confirm (debits/credits, commission agent, frais). Une instance par IntentType (8 stratégies).

Toutes implémentent resolveAccounts(intent) — méthode également invoquée par PreflightRiskUseCase pour résoudre les comptes avant le pipeline risque (cf. Pre-flight risk).


5. Cycle de vie d'un intent


6. Administration & observabilité

  • Page admin CMMS : Configurations > Flows (/configurations/flows) — liste les 7 schémas avec toggle is_active, visualiseur de pipeline, JSON brut en option.
  • Simulateur : Sandbox > Flow (/sandbox/flow) — rejoue n'importe quel flow actif avec impersonation du sender. Sert de référence pour valider une modification de schéma avant rollout. Voir Simulateur Flow (CMMS).
  • Onglet Échecs : /transactions?tab=failed — liste les intents failed / pending_review avec motif humanisé (cf. Pre-flight risk).

7. Limites connues

  • schemaVersion est informatif aujourd'hui — il n'existe pas encore de mécanisme de migration multi-versions actives. Une seule version is_active=true par transaction_type.
  • Les renderers mobiles consomment le snapshot mais n'utilisent pas encore flowSnapshot.steps[].kindVersion pour gérer la rétro-compat fine ; en cas d'écart, StepUpdateRequired est affiché.
  • Les post-actions sont enqueuées en best-effort BullMQ — pas de transaction atomique avec la transition d'état (acceptable : un SMS reçu en double vaut mieux qu'un SMS perdu).

8. Références

  • Endpoint admin : GET /v1/config/transaction-flow-schemas (orchestrator → configuration:3006)
  • Table : configuration.transaction_flow_schemas
  • Code de référence orchestrator : services/orchestrator/src/application/use-cases/intents/
  • Pre-flight risk : /services/risk-engine/preflight

Nex — Plateforme fintech CEMAC