Approval Chains

What. Reusable sign-off workflows. A chain has ordered steps; each step names an approver (a specific user, a department head, or a role). A chain is assigned to one or more entities (a process, a department, or a document type) - when a version of that entity is submitted, the chain is materialized into approvals rows. Where. /approval-chains.

Why approval chains exist

Without chains, every document and process would need a hard-coded approval list. Chains let you say:

"For everything in DG Office, the head approves first, then the Compliance officer, then the DG."

…and apply that policy to 50 documents and 200 processes in one place.

The model

ApprovalChain (id, name)
  ├─ ChainStep (order, approver_type, approver_user_id|null, mode, sla)
  ├─ ChainStep (order=2, …)
  └─ ChainAssignment (target_type=process|department|document_type, target_id)

When a version is submitted:

  1. Resolve the applicable chain by looking up assignments. Specificity ranking: process > department > document_type.
  2. Materialize - for each step, create an approvals row with entity_type='process_version'|'document_version', entity_id, order_index=step.order, approver_user_id resolved from the step, decision='pending'.
  3. Approvers see the row in My Workspace + on the entity detail page.

Create a chain

  1. Side nav → Approval ChainsNew Chain.
  2. Fill Name (e.g. DG Office process approval) + optional description.
  3. Add Steps in order:
    • Approver type = User (specific person), Department head (resolved at materialize-time), or Role.
    • For User: pick the user from the dropdown.
    • Mode = All must approve or Any one approves.
    • SLA hours - soft target for completion (UI hint).
  4. Add Assignments - what this chain applies to:
    • Target type = Process / Department / Document Type
    • Target = the actual row (e.g. department DG Office)
    • Priority - when multiple chains match, higher priority wins
  5. Click Save → redirects to the chain list with a snackbar "Approval chain saved".

Edit a chain

Open the chain → fields are editable. Save replaces all steps and assignments atomically (no orphan rows).

Already-materialized approvals are not retroactively re-materialized when you edit a chain. The version you submitted yesterday keeps the old chain's structure. Only new submissions pick up the change.

Resolution rules

When a process is submitted, the resolver runs:

  1. Look up chain assignments where target_type='process' and target_id = process.id. If found, that's the chain (most specific).
  2. Else look up target_type='department' and target_id = process.department_id. (For docs, also fall back to target_type='document_type' and target_id = doc.doc_type.)
  3. Tie-break by priority (higher wins).
  4. If nothing matches, submission fails with "No approval chain assigned to this process or its department."

Approver-type details

Test it

← Back to CompStack