Implement Conditional Logic

Guides: Implement Conditional Logic (inclusionCondition)

Real-world business processes often have branches – steps or documents that are only included if certain conditions are met. SignStack handles this using the inclusionCondition property, a powerful feature that makes your Blueprints dynamic and adaptive.

This guide explains how to use inclusionCondition with JSONata expressions to control your workflow's path based on your Entities data.

The inclusionCondition Property

The inclusionCondition is an optional property you can add to:

  • BlueprintDocument: To conditionally include a document in the workflow.

  • BlueprintStep: To conditionally include a step (and all its children) in the workflow.

How it Works:

  1. JSONata Expression: You provide a JSONata expression string as the value for inclusionCondition.

  2. Context: This expression is evaluated against the current EntityContext at the moment the workflow engine is deciding whether to include the document or start the step.

  3. Boolean Result: The expression must evaluate to a boolean (true or false).

    • If true, the document or step is included/executed.

    • If false, the document or step is skipped entirely.

Example 1: Conditionally Including a Document

Let's modify our "SaaS Subscription Agreement" Blueprint. We only want to include the SLAAddendum document if the customer is on the "Enterprise" plan.

Blueprint (documents array):

  "documents": [
    {
      "key": "mainAgreement",
      "displayName": "SaaS Subscription Agreement",
      "docTemplateKey": "saasAgreementTplV1",
      // ... roleMapping, entityMapping ...
    },
    {
      "key": "slaAddendum",
      "displayName": "Service Level Agreement Addendum",
      "docTemplateKey": "slaAddendumTplV1",
      // ... roleMapping, entityMapping ...
      "inclusionCondition": "entities.subscriptionPlan.planName = 'Enterprise'" // <-- THE CONDITION
    }
  ],
  • Logic: When a Workflow is created from this Blueprint, the engine evaluates the inclusionCondition. If the planName property within the subscriptionPlan entity (provided in the entityData) is exactly "Enterprise", the slaAddendum document will be included. Otherwise, it will be omitted.

Example 2: Conditionally Including an Approval Step (Using Multiple Entities)

Let's enhance a sales contract workflow. An extra "VP Approval" step is only required if the deal value is high and the client has a high internal risk score. This demonstrates combining data from multiple entities.

Blueprint (steps array - simplified sequential):

"steps": [
  {
    "key": "root",
    "stepType": "CONTAINER",
    "executionMode": "SEQUENTIAL",
    "children": ["salesRepStep", "managerApprovalStep", "vpApprovalStep", "finalStep"]
  },
  {
    "key": "salesRepStep",
    // ... config ...
  },
  {
    "key": "managerApprovalStep",
    // ... config ...
    // Assume this step might update clientInfo.riskScore
  },
  {
    "key": "vpApprovalStep",
    "stepType": "PARTICIPANT_TASK",
    "name": "VP Final Approval",
    "roleKey": "vpRole",
    // This condition uses data from TWO entities: dealInfo and clientInfo
    "inclusionCondition": "entities.dealInfo.value > 100000 and entities.clientInfo.riskScore = 'HIGH'", // <-- THE CONDITION
    "links": [ /* Links for VP signature */ ]
  },
  {
    "key": "finalStep",
    // ... config ...
  }
]
  • Logic: After the managerApprovalStep completes, the engine evaluates the inclusionCondition for vpApprovalStep. It checks both the value in the dealInfo entity and the riskScore in the clientInfo entity. Only if the deal is over $100,000 AND the client's risk score is marked as 'HIGH' will the vpApprovalStep run. Otherwise, it will be skipped, and the workflow will proceed directly to finalStep.

Best Practices

  • Keep it Simple: While JSONata is powerful, aim for clear and focused conditions.

  • Encapsulate Complexity with Functions: If your condition involves complex logic or needs to be reused across multiple steps or Blueprints, consider encapsulating that logic within a Custom Function. This keeps your inclusionCondition clean and readable (e.g., $should_vp_approve(entities.dealInfo, entities.clientInfo)).

  • Ensure Data Exists: Verify the entity data needed for your condition is available in the EntityContext before the condition is evaluated. Use rootEntitySlotKeys or ensure preceding steps gather the required data via onCompleteMappers.

  • Test Thoroughly: Use Scenarios with different data sets to confirm your conditional logic behaves correctly in all branches.

The inclusionCondition is fundamental for creating dynamic, intelligent Blueprints that adapt to the specific data of each transaction.

➡️ Next: Guides: Map Data with onCompleteMappers