> ## Documentation Index
> Fetch the complete documentation index at: https://docs.solya.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Moteur de règles métier

> Le modèle technique derrière l'évaluation des règles : hooks, mise en œuvre, paradigmes, phases, la couche opérations et audit.

Ceci est le compagnon technique de [Règles & jeux de règles](/fr/intelligence-layer/rules-and-rulesets).

## Énumérations principales

* **Mode de mise en œuvre** — `BLOCK` (rejeter), `WARN` (procéder + surface), `LOG` (audit silencieux).
* **Niveau de vérification** — `SHOP`, `BRAND`, `PRODUCT`, `VARIANT`, `INVENTORY_ITEM`, `PLAN`,
  `PLAN_ITEM`.
* **Catégorie** — `CAPACITY`, `ASSORTMENT`, `ORDERING`, `TRANSFER`, `PRICING`,
  `DISTRIBUTION`, `COMPLIANCE`.
* **Famille d'action** — `RESTOCK_PLAN`, `REBALANCE_PLAN`, `MARKDOWN_PLAN`,
  `PRE_SEASON_PLAN`, `SUPPLIER_RETURN_PLAN`, `SUPPLIER_EXCHANGE_PLAN`, `RECOMMENDATION`,
  `WORKFLOW`.
* **Point d'évaluation** — `PRE_PLAN_ITEM_ADD`, `PRE_PLAN_VALIDATE`,
  `RECOMMENDATION_GENERATION`, `WORKFLOW_EXECUTION`, `MANUAL_CHECK`.

### Hooks de validation

Les hooks exacts auxquels les règles s'attachent :

```
RESTOCK_PRE_ADD_ITEM, RESTOCK_PRE_VALIDATE_ITEM, RESTOCK_PRE_CHANGE_STATUS,
REBALANCE_PRE_ADD_ITEM, REBALANCE_PRE_VALIDATE_ITEM, REBALANCE_PRE_CHANGE_STATUS,
MARKDOWN_PRE_ADD_ITEM, MARKDOWN_PRE_VALIDATE_ITEM,
PRE_SEASON_PRE_ADD_ITEM, PRE_SEASON_PRE_VALIDATE_ITEM, PRE_SEASON_PRE_CHANGE_STATUS,
SUPPLIER_RETURN_PRE_ADD_ITEM, SUPPLIER_RETURN_PRE_CHANGE_STATUS,
SUPPLIER_EXCHANGE_PRE_ADD_ITEM, SUPPLIER_EXCHANGE_PRE_CHANGE_STATUS,
RECOMMENDATION_PRE_GENERATE, MANUAL_CHECK
```

### Paradigme & phase

* **Paradigme** — les règles `VALIDATION` sont appliquées par l'application au moment du hook (bloquer/alerter) ;
  les règles `DECISION_SHAPING` ne sont appliquées que par la couche de décision Databricks et sont
  **ignorées** par l'évaluateur de l'application.
* **Phase** — `SCORING`, `SIZING`, `SOURCING`, `APPROVAL` : un axe orthogonal utilisé par la
  couche de décision pour limiter l'évaluation à une étape de planification (nullable pour la rétrocompatibilité).

## Évaluation

`evaluateBusinessRules(organizationId, hook, contexts)` résout les règles applicables et
retourne, par contexte, les **blocages** et les **avertissements**. Les mutations multi-magasins (rééquilibrage,
échange fournisseur) évaluent **une fois par magasin** et agrègent. La condition de chaque règle est alimentée
par les **enrichisseurs de contexte** — de petits résolveurs qui récupèrent les signaux en direct (totaux de plan, stock actuel,
part de vente, OTB restant, déviation de courbe de tailles, écart de quantité minimale fournisseur, marge de démarque, …) ;
il y a des dizaines de types d'enrichisseur. Le catalogue de **modèles** de règles mappe
chaque modèle à une catégorie, les familles applicables, le niveau de vérification par défaut et la
condition par défaut.

## Couche opérations

Pour les mutations qui ont besoin de **résolution de contexte asynchrone** (p. ex. charger les deux magasins pour un
rééquilibrage) ou qui ont **plusieurs points d'entrée** (action + workflow + API), la logique
se trouve dans une **couche opérations** construite avec `defineMutation`. Une opération :

1. Optionnellement **ignore** les règles avec un explicite, auditable `bypassRules: { reason }`.
2. Résout `EvaluationContext[]` (asynchrone).
3. Évalue les règles ; les **blocages** abandonnent avant la persistance (les avertissements se surfacent quand même).
4. Exécute un pur **handler** (persistance).
5. Écrit l'entrée **audit** (meilleur effort).

```mermaid theme={null}
flowchart TD
  Start(["Mutation de plan invoquée"]) --> CheckBypass{Ignorer les règles<br/>demandé?}
  CheckBypass -->|Non| ResolveCtx["Résoudre EvaluationContext[]"]
  CheckBypass -->|Oui - règles ignorées| Handler
  ResolveCtx --> EvalRules["Évaluer les règles"]
  EvalRules --> HasBlocks{Blocages?}
  HasBlocks -->|Oui| ReturnFail["Retourner l'échec<br/>abandonner la mutation"]
  HasBlocks -->|Non| Handler["Exécuter handler<br/>persistance"]
  Handler --> Audit["Écrire l'entrée audit<br/>meilleur effort"]
  Audit --> ReturnSuccess["Retourner le succès<br/>+ avertissements"]
  ReturnFail --> End(["Terminé"])
  ReturnSuccess --> End
```

Ceci est un pilote ; les mutations représentatives migrées incluent ajouter un article de rééquilibrage et
ajouter/valider un article de démarque. Les mutations sans contexte de règle asynchrone continuent d'utiliser
le chemin standard action → service.

## Audit

Chaque mutation de plan est enregistrée dans un journal d'audit ajout-seul. Les **types d'événement** incluent
`PLAN_CREATED`, `PLAN_VALIDATED`, `PLAN_STATUS_CHANGED`, `PLAN_CLOSED`, `PLAN_DELETED`,
le cycle de vie d'approbation (`PLAN_APPROVAL_REQUESTED`, `PLAN_APPROVED`, `PLAN_REJECTED`,
`PLAN_APPROVAL_EXPIRED`), les événements d'article (`ITEM_ADDED`, `ITEM_UPDATED`, `ITEM_REMOVED`,
`ITEM_STATUS_CHANGED`) et les événements de configuration (`RULESET_CHANGED`,
`PLAN_HEADER_UPDATED`). Chaque ligne enregistre l'**acteur** (`USER`, `WORKFLOW`,
`SCENARIO_GENERATOR`, `SYSTEM`, `API_TOKEN`), la **source**, une raison optionnelle, les
règles appliquées et — pour les articles — une **attribution** (`MANUAL`, `DECISION_VECTOR`,
`WORKFLOW_FALLBACK`). Quand les règles étaient ignorées, la raison est stockée dans l'entrée.

<Note>
  Les libellés lisibles par l'homme (variante, magasin, noms d'utilisateur) sont résolus au moment de la
  **lecture**, pas stockés — donc le journal d'audit reste exact même à mesure que les données de catalogue changent.
</Note>
