Skip to main content

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:

  • LIST Mode: Renders the dashboard of existing workflows grouped by module.
  • DESIGNER Mode: Unmounts the list and mounts the WorkflowDesigner canvas.

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:

  1. Generates a Trigger Node based on the module code (e.g., EMPLOYEE_EXPENSE Submitted).
  2. Iterates over the legacy steps array, converting each step into an Approval Node, spaced vertically 250px apart on the canvas.
  3. Automatically draws Approve edges connecting each step sequentially.
  4. Generates terminal Status Nodes (APPROVED and REJECTED) 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:

  1. It prioritizes tracing the approve paths first.
  2. It then traces secondary paths (like condition-failed or custom transitions).
  3. As it visits Approval Nodes, it pushes them into an orderedApprovalNodes array, mathematically deriving the true step_order for the backend engine.

Edge to Transition Mapping

The visual lines (edges) drawn between nodes are translated into routing rules.

  • The engine checks the sourceHandle of an edge (e.g., reject, return).
  • It looks up the target node. If the target is a Status Node (e.g., terminal APPROVED), the targetStatus is updated.
  • If the target is another Approval Node, it records the nextStepId and forces the document status to stay PENDING.

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:

  1. It checks the has_active_instances flag.
  2. If there are documents currently pending approval in this workflow, deletion is outright blocked.
  3. Instead of deleting, it mounts a LockDialog warning the user that the workflow cannot be destroyed while documents are still in transit, preventing orphaned database records.