Moteur de workflow¶
Ce que fait le moteur de workflow¶
De nombreux processus dans Jigi ont besoin d'un circuit de validation à plusieurs étapes : une demande de congé validée par le manager, une demande de personnel validée en plusieurs paliers, une lettre d'offre nécessitant une double validation, etc. Plutôt que de réimplémenter cette logique dans chaque module, Jigi utilise un seul moteur de workflow générique et partagé, indépendant du type d'entité concerné.
Un module métier ne modélise donc jamais ses propres colonnes d'approbation (pas de PENDING_L1/L2/L3 ni de table *_approvals propre) : il garde simplement une référence (workflow_instance_id) vers une exécution du moteur, et laisse celui-ci piloter tout le cycle de vie de l'approbation.
Le modèle en 4 tables¶
| Table | Rôle |
|---|---|
workflow_definitions |
Un circuit d'approbation nommé et réutilisable, rattaché à un type d'entité (entity_type). Modèle global (tenant_id NULL) ou personnalisé par tenant. |
workflow_step_definitions |
Les étapes ordonnées d'un circuit. Chaque étape déclare qui doit approuver via un approver_type. |
workflow_instances |
Une exécution concrète d'un circuit pour une entité précise, identifiée par (entity_type, entity_id). |
workflow_step_instances |
L'état de chaque étape d'une exécution donnée. |
Ces quatre tables vivent dans un schéma PostgreSQL dédié (workflow), pensé pour pouvoir être extrait plus tard en service indépendant si besoin.
Comment un module utilise le moteur¶
- Définir un circuit d'approbation une fois (une définition + ses étapes). Par exemple pour les congés, une politique de congé génère la configuration d'approbation sous forme de workflow.
- Démarrer : quand une demande est soumise, le module appelle le moteur avec
(type d'entité, id de l'entité, définition, initiateur). Le moteur crée une instance (statutPENDING) et toutes les étapes associées, puis assigne la première étape à son approbateur. - Référencer : le module stocke l'
workflow_instance_idretourné sur sa propre ligne de données. Le statut métier du module (DRAFT/PENDING/APPROVED/REJECTED/CANCELLED) reste simple et reflète le statut de l'instance de workflow. - Agir : les approbateurs valident ou rejettent une étape. Le moteur fait avancer
current_step, applique la règle définie en cas de rejet, respecte les étapes optionnelles et les délais (due_at→ passage enTIMED_OUT), puis fixe le statut final de l'instance. - Réagir : à la clôture, le moteur déclenche un événement que le module d'origine consomme pour finaliser sa propre donnée (ex. créditer/débiter un solde de congé).
Qui approuve quoi : la résolution d'approbateur¶
Une étape ne référence jamais un utilisateur précis codé en dur (sauf cas explicite) : elle référence un rôle ou une relation organisationnelle, résolue au moment de l'exécution. Cela rend les circuits portables d'une société à l'autre.
| Type d'approbateur | Résolu en pratique vers |
|---|---|
DIRECT_MANAGER |
Le manager direct de l'initiateur (organigramme) |
DEPARTMENT_HEAD |
Le responsable du département de l'initiateur |
HR_MANAGER |
Le(s) responsable(s) RH du tenant |
ROLE |
N'importe quel utilisateur détenant le rôle indiqué |
SPECIFIC_USER |
Un utilisateur précis (exception au principe de portabilité) |
Règles métier appliquées par le moteur¶
- Validation séquentielle stricte : seule l'étape actuellement active peut être approuvée ou rejetée — impossible de « sauter » une étape.
- Anti-auto-approbation : l'initiateur d'une demande ne peut jamais approuver ou rejeter sa propre demande — il doit annuler la demande directement s'il change d'avis.
- En cas de rejet, trois comportements possibles selon la configuration de l'étape :
STOP— le workflow s'arrête, la demande est rejetée définitivement ;RETURN_TO_SUBMITTER— la demande repasse en brouillon pour être corrigée et resoumise ;- (sinon) l'étape est simplement ignorée et le workflow continue.
- Une seule instance ouverte à la fois par entité : impossible de soumettre une nouvelle demande tant qu'une instance
PENDING/IN_PROGRESSexiste déjà pour cette même entité. - Escalade automatique : une tâche planifiée détecte les étapes dépassant leur délai (
due_at) et les marqueTIMED_OUT— une étape optionnelle en retard fait avancer le workflow, une étape obligatoire en retard le rejette. - Délégation : une étape en attente peut être réassignée à un autre approbateur (ex. absence du manager).
- Étapes de notification pure : une étape peut être une simple notification (sans action attendue), automatiquement marquée
NOTIFIEDdès qu'elle est atteinte.
Détails techniques
- Package :
app.jigi.workflow(domain/pour les entités et enums,engine/pour la machine à états :WorkflowEngine,ApproverResolver,WorkflowPathResolver). - Enums clés :
ApproverType(DIRECT_MANAGER,HR_MANAGER,DEPARTMENT_HEAD,ROLE,SPECIFIC_USER),StepStatus(PENDING,APPROVED,REJECTED,SKIPPED,TIMED_OUT,NOTIFIED),WorkflowStatus(PENDING,IN_PROGRESS,APPROVED,REJECTED,CANCELLED,RETURNED),OnRejection(STOP,RETURN_TO_SUBMITTER, autre = passer à l'étape suivante). - Un index unique partiel garantit au plus une instance ouverte (
PENDING/IN_PROGRESS) par(entity_type, entity_id). - Le moteur ne gère aucun canal de notification lui-même : il publie des événements (assignation d'étape, clôture de workflow) que le module
notificationtransforme en emails / notifications in-app — voir Notifications. - Exemples de
entity_typeréels :LEAVE/LEAVE_REQUEST,JOB_REQUISITION,OBJECTIVE,EMPLOYEE_ONBOARDING/OFFBOARDING,PURCHASE_REQUEST/SUPPLY_REQUEST,RESOURCE_BOOKING/BOOKING,OFFER_LETTER. - Administration des circuits :
WorkflowAdminController/WorkflowAdminService— voir Workflows d'approbation pour l'usage fonctionnel côté administrateur RH.
FAQ¶
Un même type de demande peut-il avoir des circuits d'approbation différents selon la société ? Oui — une définition de workflow peut être globale (partagée) ou personnalisée par tenant.
Que se passe-t-il si l'approbateur désigné (ex. le manager direct) quitte l'entreprise en cours de validation ? L'étape en attente peut être déléguée à un autre utilisateur par un administrateur, sans perdre l'historique de la demande.
Un même circuit peut-il mélanger des étapes obligatoires et optionnelles ?
Oui, chaque étape porte son propre indicateur is_optional, qui détermine le comportement en cas de délai dépassé.
Où voit-on l'historique complet d'une demande passée par le workflow ?
Chaque étape (workflow_step_instance) conserve qui a agi, quand, et un commentaire éventuel — cet historique est visible depuis l'écran de suivi de la demande dans le module concerné.