mayan/apps/document_states/ — moteur de workflows pour les documents. Permet de définir des processus métier (validation, archivage, révision…) que les documents traversent automatiquement ou manuellement.
Un workflow dans Mayan est un graphe d'états attaché à un ou plusieurs types de documents. Chaque document concerné possède une instance de ce workflow qui suit sa progression.
Workflow (template)
├── WorkflowState × N ← les nœuds du graphe
│ ├── WorkflowStateAction × N ← actions automatiques à l'entrée/sortie
│ └── WorkflowStateEscalation × N ← transition automatique après délai
└── WorkflowTransition × N ← les arêtes du graphe
├── WorkflowTransitionField × N ← champs à saisir lors de la transition
└── WorkflowTransitionTriggerEvent × N ← déclencheurs automatiques
WorkflowInstance (runtime, 1 par document × workflow)
├── state_active → WorkflowState
├── context (JSON)
└── WorkflowInstanceLogEntry × N ← historique des transitions
Workflow — le gabarit| Champ | Rôle |
|---|---|
label |
Nom du workflow (ex : "Processus de validation") |
internal_name |
Identifiant Python-safe, référencé par d'autres apps |
document_types |
M2M vers DocumentType — quels types de documents sont concernés |
auto_launch |
Lance automatiquement le workflow à la création du document |
ignore_completed |
Ignore les instances en état final (ne les traite plus) |
WorkflowRuntimeProxy est un proxy de Workflow qui ajoute les méthodes d'exécution runtime (lancer des instances, statistiques, etc.).
WorkflowState — un état du workflow| Champ | Rôle |
|---|---|
workflow |
FK → Workflow |
label |
Nom de l'état (ex : "En attente d'approbation") |
initial |
True → point de départ. Un seul état initial par workflow |
final |
True → état terminal. Un seul état final par workflow |
completion |
Pourcentage de progression (0-100) affiché dans l'interface |
Quand un état est sauvegardé avec initial=True, tous les autres états du workflow sont automatiquement mis à initial=False (même logique pour final).
WorkflowTransition — une transition entre étatsWorkflowState "Soumis" ──[Approuver]──► WorkflowState "Approuvé"
WorkflowState "Soumis" ──[Rejeter]────► WorkflowState "Rejeté"
| Champ | Rôle |
|---|---|
origin_state |
FK → état de départ |
destination_state |
FK → état d'arrivée |
label |
Nom de la transition (ex : "Approuver") |
condition |
Template Jinja2 — si vide ou falsy, la transition est désactivée |
La condition est évaluée à chaque vérification des transitions disponibles pour l'utilisateur. Elle reçoit {{ workflow_instance }} dans son contexte.
WorkflowTransitionField — champs à saisir lors d'une transitionPermet de collecter des informations au moment où un utilisateur exécute une transition (ex : commentaire d'approbation, date de révision…).
| Champ | Rôle |
|---|---|
transition |
FK → WorkflowTransition |
name |
Identifiant interne (stocké dans le contexte de l'instance) |
label |
Libellé affiché à l'utilisateur |
field_type |
Type de champ (texte, entier, date, choix…) |
required |
Obligatoire ou optionnel |
default |
Valeur par défaut (peut être un template) |
lookup |
Template rendant une liste CSV → transformé en champ <select> |
widget |
Widget Django optionnel pour personnaliser la présentation |
Les valeurs saisies sont stockées dans le context JSON de WorkflowInstance et accessibles dans les actions et templates via {{ workflow_instance.context }}.
WorkflowTransitionTriggerEvent — déclencheur automatiquePermet à une transition de se déclencher automatiquement quand un événement Mayan survient.
# Ex : déclencher "Archiver" quand un nouveau fichier est uploadé
WorkflowTransitionTriggerEvent(
transition=transition_archiver,
event_type=event_document_file_created
)
Le système d'événements Mayan appelle la vérification des triggers après chaque événement. Si les conditions de la transition sont remplies, elle s'exécute sans intervention humaine.
WorkflowStateAction — action automatique sur un étatUne action s'exécute automatiquement quand une instance entre ou sort d'un état.
| Champ | Rôle |
|---|---|
state |
FK → WorkflowState |
label |
Nom de l'action |
enabled |
Activée ou non |
when |
ON_ENTRY (à l'entrée) ou ON_EXIT (à la sortie) |
condition |
Template — l'action est sautée si falsy |
backend_path |
Chemin Python vers la classe WorkflowAction |
Les actions sont exécutées par ordre alphabétique de label.
workflow_actions.py)| Classe | Ce qu'elle fait |
|---|---|
DocumentPropertiesEditAction |
Modifie le label et/ou la description du document via template |
DocumentWorkflowLaunchAction |
Lance d'autres workflows sur le même document |
HTTPAction |
Fait une requête HTTP (GET, POST, PUT…) vers une URL externe |
D'autres apps fournissent leurs propres WorkflowAction : document_states_mailing (envoi d'email), document_indexing (mise à jour d'index), etc. Chaque action est découverte automatiquement via _loader_module_name = 'workflow_actions'.
WorkflowStateEscalation — transition automatique après délaiSi un document reste bloqué trop longtemps dans un état, une escalade peut le faire progresser automatiquement.
| Champ | Rôle |
|---|---|
state |
FK → état dans lequel attendre |
transition |
FK → transition à déclencher |
amount + unit |
Délai (ex : 3 jours, 1 heure) |
priority |
Ordre d'évaluation (plus petit = prioritaire) |
comment |
Commentaire ajouté au log lors du déclenchement |
condition |
Template — l'escalade est sautée si falsy |
La tâche périodique task_workflow_escalation vérifie toutes les instances en cours et déclenche les escalades expirées.
WorkflowInstance — l'exécution par documentUn WorkflowInstance est créé pour chaque couple (document, workflow). C'est l'objet runtime.
| Champ | Rôle |
|---|---|
workflow |
FK → Workflow |
document |
FK → Document |
state_active |
FK → WorkflowState courant |
context |
JSON — données accumulées au fil des transitions |
datetime |
Date de création de l'instance |
À la création, state_active est automatiquement positionné sur l'état initial=True du workflow.
do_transition(transition, comment, extra_data, user)Exécute une transition :
context avec extra_dataWorkflowInstanceLogEntryevent_workflow_instance_transitionedorigin_state.do_active_unset() → exécute les ON_EXIT actionsdestination_state.do_active_set() → met à jour state_active, exécute les ON_ENTRY actionsdo_check_escalation()Appelé par la tâche périodique. Vérifie si le délai de chaque escalade est dépassé et déclenche la transition si oui.
WorkflowInstanceLogEntry — historique| Champ | Rôle |
|---|---|
workflow_instance |
FK → instance |
transition |
Transition effectuée |
user |
Utilisateur ayant déclenché (null si automatique) |
datetime |
Horodatage |
comment |
Commentaire saisi |
extra_data |
JSON — valeurs des WorkflowTransitionField |
L'instance maintient un context JSON qui s'enrichit au fil des transitions. Il est accessible dans tous les templates Jinja2 (conditions, actions, fields) via {{ workflow_instance }}.
# Accéder au contexte dans une action
context['workflow_instance'].document # le document
context['workflow_instance'].get_context() # dict du contexte courant
Le contexte peut stocker les réponses HTTP (HTTPAction avec response_store=True), les données saisies dans les champs de transition, et les valeurs injectées par les actions.
DocumentStateHelper — accès raccourciInjecté sur Document via PropertyHelper :
# Accéder à l'instance du workflow "validation" d'un document
document.workflow.get(workflow__internal_name='validation')
# équivalent à
document.workflows.get(workflow__internal_name='validation')
Document créé (type "Facture")
└── auto_launch=True sur le workflow "Validation factures"
└── WorkflowInstance créée
└── state_active = état initial "Soumis"
└── actions ON_ENTRY exécutées
Utilisateur clique "Approuver"
└── do_transition(transition="Approuver", user=marie)
├── condition de la transition évaluée → True
├── WorkflowInstanceLogEntry créé
├── "Soumis".do_active_unset() → actions ON_EXIT
└── "Approuvé".do_active_set()
├── state_active = "Approuvé"
└── actions ON_ENTRY exécutées
ex: HTTPAction → POST vers système comptable
Après 3 jours sans changement (escalade)
└── task_workflow_escalation → do_check_escalation()
└── do_transition(transition="Archiver automatiquement")
| Fichier | Contenu |
|---|---|
models/workflow_models.py |
Workflow, WorkflowRuntimeProxy |
models/workflow_state_models.py |
WorkflowState, WorkflowStateRuntimeProxy |
models/workflow_transition_models.py |
WorkflowTransition |
models/workflow_transition_field_models.py |
WorkflowTransitionField |
models/workflow_transition_trigger_models.py |
WorkflowTransitionTriggerEvent |
models/workflow_state_action_models.py |
WorkflowStateAction |
models/workflow_state_escalation_models.py |
WorkflowStateEscalation |
models/workflow_instance_models.py |
WorkflowInstance, WorkflowInstanceLogEntry |
classes.py |
WorkflowAction (base des actions) |
workflow_actions.py |
DocumentPropertiesEditAction, HTTPAction, DocumentWorkflowLaunchAction |
tasks.py |
Tâches Celery (escalades, lancement de workflows) |
permissions.py |
Permissions workflow |
events.py |
Événements workflow |