Approval Workflows Tab Architecture
The /org/settings?tab=approval_workflows route is powered by the ApprovalWorkflowsTab.tsx component. It serves as the primary controller for the entire Approval Workflow ecosystem, acting as the bridge between the backend database, the Module State Management (MSM) engine, and the visual WorkflowDesigner.
This document provides a technical deep-dive into how the tab manages state, serializes data, and protects workflow integrity.
1. View Mode Management
The tab operates as a Single Page Application (SPA) wrapper that toggles between two primary states:
LISTMode: Renders the dashboard of existing workflows grouped by module.DESIGNERMode: Unmounts the list and mounts theWorkflowDesignercanvas.
When the view mode changes, the tab injects the active mode back up to the parent OrganizationSettings layout to adjust sidebars and headers appropriately.
2. The Legacy Graph Generator (Upward Compatibility)
A critical feature of ApprovalWorkflowsTab.tsx is its ability to handle legacy data. Before the visual graph designer existed, workflows were just linear arrays of steps in the database.
When you open an older workflow, the tab runs generateDefaultGraph(). This algorithm:
- Generates a Trigger Node based on the module code (e.g.,
EMPLOYEE_EXPENSE Submitted). - Iterates over the legacy
stepsarray, converting each step into an Approval Node, spaced vertically 250px apart on the canvas. - Automatically draws Approve edges connecting each step sequentially.
- Generates terminal Status Nodes (
APPROVEDandREJECTED) and connects the final step to them.
This ensures seamless backwards compatibility; legacy workflows instantly become visual graphs without manual migration.
3. The Graph Serialization Engine
When a user clicks "Save" in the designer, the handleSaveFromDesigner function executes a complex serialization process to convert the visual ReactFlow canvas back into relational database tables.
Traversal & Step Ordering
Because users can place nodes anywhere on the visual canvas, the visual order doesn't guarantee logical order. The serialization engine performs a Depth-First Search (DFS) Traversal starting from the Trigger Node:
- It prioritizes tracing the
approvepaths first. - It then traces secondary paths (like
condition-failedor custom transitions). - As it visits Approval Nodes, it pushes them into an
orderedApprovalNodesarray, mathematically deriving the truestep_orderfor the backend engine.
Edge to Transition Mapping
The visual lines (edges) drawn between nodes are translated into routing rules.
- The engine checks the
sourceHandleof an edge (e.g.,reject,return). - It looks up the target node. If the target is a Status Node (e.g., terminal
APPROVED), thetargetStatusis updated. - If the target is another Approval Node, it records the
nextStepIdand forces the document status to stayPENDING.
The STEP_APPROVE Injection
During this serialization, the engine actively intercepts the transition data. If an edge originates from an "Approve" action but points to another Approval Node, the code forcibly overrides the action code:
if (actionCode === 'APPROVE' && targetNode?.type === 'approval') {
actionCode = 'STEP_APPROVE';
}
This is where the "Phantom Action" logic happens! It ensures intermediate approvals do not trigger final completion workflows.
4. Deletion Safety & Workflow Locks
The tab enforces strict referential integrity. When a user attempts to delete a workflow via handleDeleteClick:
- It checks the
has_active_instancesflag. - If there are documents currently pending approval in this workflow, deletion is outright blocked.
- Instead of deleting, it mounts a
LockDialogwarning the user that the workflow cannot be destroyed while documents are still in transit, preventing orphaned database records.