Aller au contenu principal

UC-09 — Détection d'anomalies

Acteur : Système (jobs automatisés) But : Détecter automatiquement les anomalies (soldes bas, écarts de stock, produits périmés)

Trigger​

Plusieurs jobs planifiés analysent les données et créent des anomalies.

Préconditions​

  • Un seuil d'anomalie configuré par organisation (default_anomaly_threshold_cents)
  • Les jobs planifiés actifs

Postconditions​

  • Les anomalies sont enregistrées avec un kind, une severity et un status = open
  • Les anomalies balance_low déclenchent une notification email (anti-spam 8 jours)

Jobs de détection​

Type (kind)JobFréquenceSévérité
balance_lowextract_anomalies06:00selon écart
stock_inconsistencyreconcile_stock6 hhigh
expired_productcheck_expiry1 hmedium

Endpoints​

1. Configurer le seuil​

PUT /api/v1/admin/system/organizations/{id}
Content-Type: application/json

{
"default_anomaly_threshold_cents": 30000
}

2. Lister les anomalies​

GET /api/v1/admin/org/anomalies?status=open&severity=medium

3. Acquitter / résoudre​

POST /api/v1/admin/org/anomalies/{id}/acknowledge
POST /api/v1/admin/org/anomalies/{id}/resolve

Flow​

sequenceDiagram
participant Job as Job (06:00)
participant API
participant DB
participant Outbox
participant Admin

Job->>DB: Pour chaque org active
Job->>DB: SELECT cards WHERE balance < seuil<br/>ET non notifiée depuis 8 jours
Job->>DB: INSERT anomaly (kind: balance_low)
Job->>Outbox: Emit AnomalyDetected
Outbox->>DB: INSERT notification (template anomaly_alert, email)

Note over Admin: Plus tard...

Admin->>API: GET /admin/org/anomalies
API-->>Admin: {items: [anomaly], total}
Admin->>API: POST /admin/org/anomalies/{id}/resolve
API->>DB: UPDATE status = resolved
API-->>Admin: {status: "resolved"}

Exemple de réponse (liste)​

{
"items": [
{
"id": "uuid",
"kind": "balance_low",
"severity": "medium",
"status": "open",
"message": "La carte #123456 a un solde de 500 XOF sous le seuil de 3000 XOF",
"details": { "balance_cents": 500, "threshold_cents": 3000 },
"card_id": "uuid",
"holder_name": "Fatou Diallo",
"detected_at": "2025-06-01T06:00:00Z",
"acknowledged_at": null,
"resolved_at": null,
"resolved_by": null,
"created_at": "2025-06-01T06:00:00Z"
}
],
"total": 5
}

Permissions​

PermissionDescription
anomaly.manageConsulter, acquitter, résoudre
anomaly.threshold.configureConfigurer le seuil

La détection est automatique (aucune permission utilisateur requise).

Erreurs​

error_codeDescription
NotFoundAnomalie introuvable
ForbiddenPermission insuffisante

Voir Anomalies et Jobs.