Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions content/en/advanced-reference/architecture/actions/_index.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
---
title: "Actions"
description: "Overview and detailed documentation for the Actions section of FlexiRule."
title: "Action Architecture"
description: "Internal implementation details and class structures for every logic node."
weight: 10
---

# Actions
# Action Architecture

Welcome to the Actions section. This section contains detailed information about actions components and their usage in FlexiRule.
Detailed technical references for the underlying action handlers and execution logic.

## Sub-pages
## Logic Nodes

- **[Condition](condition.md)**
- **[Document Action](document-action.md)**
- **[Entry](entry.md)**
- **[Loop](loop.md)**
- **[Notify](notify.md)**
- **[Query Records](query-records.md)**
- **[Stop](stop.md)**
- **[Check]({{< relref "check.md" >}})**
- **[Set Value]({{< relref "set-value.md" >}})**
- **[Repeat]({{< relref "repeat.md" >}})**
- **[Multi-Path]({{< relref "multi-path.md" >}})**
- **[Advanced Process]({{< relref "advanced-process.md" >}})**
- **[Query Records]({{< relref "query-records.md" >}})**
- **[Update Record]({{< relref "document-action.md" >}})**
- **[Notify]({{< relref "notify.md" >}})**
- **[Wait]({{< relref "wait.md" >}})**
- **[Sub-rule]({{< relref "sub-rule.md" >}})**
- **[Entry]({{< relref "entry.md" >}})**
- **[Stop]({{< relref "stop.md" >}})**
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: 'Advanced Process: Architecture Reference'
description: Internal implementation details for the Process/Advanced Process action.
weight: 110
---

# Advanced Process: Architecture Reference

## Implementation
The **Advanced Process** action (internally `Process`) is handled by `ProcessHandler` in `flexirule/ruleflow/core/action_handlers/process.py`.

## Process Runtime
Processes are registered in the `ProcessRegistry` and executed within a `ProcessRuntime`. They support custom input parameters and can return values to the rule context.
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,5 @@ New operators can be added to the frontend `SimpleCondition.vue` component. Sinc
- **Field Resolver**: `flexirule/ruleflow/utils/field_resolver.py` (Handles nested dot-notation)

## Related Topics
- [Action Documentation]({{< relref "core-actions/condition.md" >}})
- [Action Documentation]({{< relref "core-actions/check.md" >}})
- [Execution Semantics]({{< relref "advanced-reference/reference/execution/condition.md" >}})
Original file line number Diff line number Diff line change
@@ -1,64 +1,20 @@
---
title: 'Document Action: Architecture Reference'
description: Class structure, Resource Mapper internals, and mode dispatch logic for
the Document Action.
title: 'Update Record: Architecture Reference'
description: Internal implementation details for the Document Action.
weight: 30
---

# Document Action: Architecture Reference
# Update Record: Architecture Reference

## Purpose
The **Document Action** implementation abstracts Frappe's CRUD operations into a declarative mapping-based engine. It centralizes document manipulation logic to ensure consistent application of permissions, background enqueuing, and context-aware value resolution.
The **Update Record** block (internally Document Action) implementation abstracts Frappe's CRUD operations into a declarative mapping-based engine. It centralizes document manipulation logic to ensure consistent application of permissions, background enqueuing, and context-aware value resolution.

## Class Structure

### `DocumentActionHandler(ActionHandler)`
- **Responsibility**: The primary singleton handler registered in the `HandlerRegistry`.
- **Key Methods**:
- `execute()`: Orchestrates the overall lifecycle, applies input mappings, and dispatches to mode handlers.
- `_create_new()`: Constructs document payloads and handles `is_async` enqueuing.
- `_update_existing()`: Handles targeted record modification.
- `_apply_table_mappings()`: Implements the recursive row-mapping engine.
- `_get_same_field_mappings()`: Implements field-matching logic between source and target.

## Execution Pipeline

1. **Registry Lookup**: `RuleEngine` identifies the action type and fetches the `DocumentActionHandler` instance.
2. **Mapping Layer**:
- **Scalar Mappings**: Resolved via `_resolve_field_mappings` or `compiled_scalars` (pre-compiled Python dict).
- **Static Values**: Merged last to ensure explicit configuration overrides dynamic discovery.
3. **Table Engine**:
- Iterates over `table_mappings`.
- Resolves the source collection (usually a list of dicts from `doc` or `vars`).
- For each row:
- Creates a `row_context` with `item` (current row) and `loop` metadata.
- Evaluates `condition` (inclusion check) and `filter` (exclusion check).
- Applies field-level assignments to the row payload.
- Appends the result to the parent document via `doc.append()`.
4. **Dispatch**:
- Sync: `frappe.get_doc(data).insert()` / `save()`.
- Async: `frappe.enqueue("..._async_create_doc", doc_data=data)`.
## Field Mapping
Field mapping logic is implemented in `flexirule/ruleflow/utils/mapping.py`. It provides the binding between rule context (doc, vars) and the target document fields.

## Context Mutation Model
- **Direct Memory Mutation**: For `Update Existing`, the handler performs `doc.set(field, value)` on a loaded object.
- **Persistence Strategy**: Mutations are not committed to the database until the explicit `.insert()` or `.save()` call at the end of the mode handler.
- **Context Injection**: The resulting document (post-save) is returned to the engine and injected into the `execution_context` (e.g., `vars.my_result`) using `apply_output_mapping`.
## Asynchronous Execution
When `is_async` is enabled, the action is enqueued using `frappe.enqueue`. The engine logs the background job ID and continues execution if there are no immediate dependencies on the result.

## Dependencies
- **Rule Engine Core**: Relies on `HandlerRegistry` for registration.
- **Value Resolver**: Uses `_safe_eval` (inheriting from `ActionHandler`) for Python expression evaluation.
- **Permissions**: Depends on `flexirule.ruleflow.core.permissions.can_skip_permissions` for role-based security bypassing.
- **Utils**: Uses `flexirule.ruleflow.utils.mapping.apply_input_mapping` for pre-execution config hydration.

## Extension Points
- **Action Policies**: Developers can override operation-level policies (like `required_config_keys`) in `flexirule/ruleflow/core/contracts.py`.
- **Custom Resolvers**: Custom Jinja filters or Python locals can be added to `_build_template_context` in the base `ActionHandler` to make them available to Document Action mappings.

## Internal Events
- **Background Task**: Triggers a `frappe.enqueue` event for asynchronous creation.
- **Standard Hooks**: Indirectly triggers all Frappe document lifecycle hooks (`before_insert`, `after_save`, etc.) for the target DocType.

## Source Files
- **Backend**: `flexirule/ruleflow/core/action_handlers/create_doc.py`
- **Frontend**: `flexirule/public/js/flexirule/rule_builder/components/rule_config/types/DocumentActionConfig.vue`
- **Contract**: `flexirule/ruleflow/core/contracts.py`
## Class Structure
- **Handler Class**: `DocumentActionHandler`
- **Source File**: `flexirule/ruleflow/core/action_handlers/create_doc.py`
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ The Entry Action uses **Implicit Initialization**. It does not perform explicit
## Extension Points
The Entry Action is considered a "Closed Core" component. Developers should not override the `EntryActionHandler` as it would break the fundamental graph-traversal guarantees of the engine.

If customization is needed for "initialization" logic, it is recommended to use an [Assignment]({{< relref "core-actions/assignment" >}}) node immediately following the Entry Action.
If customization is needed for "initialization" logic, it is recommended to use an [Assignment]({{< relref "core-actions/set-value" >}}) node immediately following the Entry Action.

## Internal Events
- **`rule_execution_start`**: Fired by the `RuleEngine` immediately before the Entry Action is processed.
Expand Down
16 changes: 16 additions & 0 deletions content/en/advanced-reference/architecture/actions/multi-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: 'Multi-Path: Architecture Reference'
description: Internal implementation details for the Switch/Multi-Path action.
weight: 70
---

# Multi-Path: Architecture Reference

## Implementation
The **Multi-Path** action (internally `Switch`) is handled by `SwitchHandler` in `flexirule/ruleflow/core/action_handlers/switch.py`.

## Execution Logic
1. Resolves the value of the target field or expression.
2. Iterates through the defined cases to find a match.
3. If a match is found, returns the corresponding `next_step_id`.
4. If no match is found, returns the `default_next_step_id`.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ The **Query Records** action is implemented as a core Action Handler within the

---

## Dynamic Date Formulas
The Query Records action includes a specialized evaluator for temporal logic. It supports rolling time windows (e.g., "Last 7 Days") by translating user-friendly formulas into standard SQL/Frappe database queries. This is handled by the `DateFormulaResolver` in the backend.

---

## 1. Class Structure

- **Handler Class**: `QueryRecordsHandler`
Expand Down
13 changes: 13 additions & 0 deletions content/en/advanced-reference/architecture/actions/repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: 'Repeat: Architecture Reference'
description: Internal implementation details for the Loop/Repeat action.
weight: 60
---

# Repeat: Architecture Reference

## Implementation
The **Repeat** action (internally `Loop`) is handled by `LoopHandler` in `flexirule/ruleflow/core/action_handlers/loop.py`.

## Iteration Logic
It manages an internal pointer to the current list item and re-executes the connected sub-graph for each item.
21 changes: 21 additions & 0 deletions content/en/advanced-reference/architecture/actions/set-value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: 'Set Value: Architecture Reference'
description: Internal implementation details for the Assignment/Set Value action.
weight: 50
---

# Set Value: Architecture Reference

## Implementation
The **Set Value** action (internally `Assignment`) is handled by `AssignmentHandler` in `flexirule/ruleflow/core/action_handlers/assignment.py`.

## Features

### Batch Assignments
Allows multiple mutations in a single node execution. Assignments are processed sequentially.

### Normalization Value Resolver
A core feature for cleaning and transforming data. It uses pipelines and profiles to apply transformations (like `trim`, `upper`, `lower`) before setting the value.

### Context Variables
Assignments can target the global `vars` dictionary in the `ContextManager`, allowing state to be shared across nodes without persisting to the database.
13 changes: 13 additions & 0 deletions content/en/advanced-reference/architecture/actions/sub-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: 'Sub-rule: Architecture Reference'
description: Internal implementation details for the Sub-rule action.
weight: 90
---

# Sub-rule: Architecture Reference

## Implementation
The **Sub-rule** action is handled by `SubRuleHandler` in `flexirule/ruleflow/core/action_handlers/sub_rule.py`.

## Recursion and Context
It invokes the `RuleEngine` recursively. It manages context isolation, ensuring that the sub-rule has access to the necessary data while preventing unintended side effects in the parent rule.
13 changes: 13 additions & 0 deletions content/en/advanced-reference/architecture/actions/wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: 'Wait: Architecture Reference'
description: Internal implementation details for the Wait action.
weight: 80
---

# Wait: Architecture Reference

## Implementation
The **Wait** action is handled by `WaitHandler` in `flexirule/ruleflow/core/action_handlers/simple_actions.py`.

## Mechanism
It uses Python's `time.sleep()` for short durations or schedules a background task for longer waits, depending on the rule's execution mode.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The **Condition Builder** is a recursive Vue 3 interface that allows users to co
- **Input**: User interactions (drag-and-drop, field selection, operator picking).
- **Output**: A standardized **JSON AST (Abstract Syntax Tree)**.
- **Key Files**: `ConditionBuilder.vue`, `ConditionNode.vue`, `SimpleCondition.vue`.
- **Detailed Guide**: [Condition Builder Frontend]({{< relref "core-actions/condition.md" >}})
- **Detailed Guide**: [Condition Builder Frontend]({{< relref "core-actions/check.md" >}})

### 2. The Condition Compiler (Backend - Save-Time)

Expand Down
4 changes: 2 additions & 2 deletions content/en/advanced-reference/concepts/ai-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,5 @@ sequenceDiagram
## Related Topics

- [Execution Engine]({{< relref "advanced-reference/architecture/engine/execution-engine.md" >}})
- [Variables]({{< relref "core-actions/assignment#context-variables-vars" >}})
- [Condition Builder]({{< relref "core-actions/condition.md" >}})
- [Variables]({{< relref "core-actions/set-value.md#context-variables-vars" >}})
- [Condition Builder]({{< relref "core-actions/check.md" >}})
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,6 @@ By using the Normalization Value Resolver, business users can:

## Where to find it?
The Normalization Value Resolver is integrated into:
- [Assignment Action]({{< relref "core-actions/assignment/" >}})
- [Condition Nodes]({{< relref "core-actions/condition/" >}})
- [Assignment Action]({{< relref "core-actions/set-value/" >}})
- [Condition Nodes]({{< relref "core-actions/check/" >}})
- Any configuration panel requiring data mapping.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ However, they serve very different purposes.

## Quick Summary

| Use Case | Rule Entry Condition | [Condition Action]({{< relref "core-actions/condition.md" >}}) |
| Use Case | Rule Entry Condition | [Condition Action]({{< relref "core-actions/check.md" >}}) |
| :--- | :---: | :---: |
| Decide whether the rule should run at all | ✅ Yes | ❌ No |
| Create branching logic inside a rule | ❌ No | ✅ Yes |
Expand Down Expand Up @@ -108,7 +108,7 @@ Condition: Customer is VIP?

### Recommended Uses

Use a [Condition Action]({{< relref "core-actions/condition.md" >}}) when you need:
Use a [Condition Action]({{< relref "core-actions/check.md" >}}) when you need:
- **If / Else logic**: Branching into different paths.
- **Guarded Sequences**: Executing specific actions only under certain conditions within a larger flow.
- **Decision Trees**: Handling complex business logic after the rule has been triggered.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ FlexiRule uses a 3-layer architecture for action documentation:

### Cross-Linking Convention
- **Hugo `relref`**: All internal links must use the `relref` shortcode pointing to the `.md` file path.
- **Format**: `{{</* relref "core-actions/assignment.md" */>}}`
- **Format**: `{{</* relref "core-actions/set-value.md" */>}}`
- **Why**: This ensures link stability across refactors and URL changes.

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ Since the action is read-only and operates on the local execution context, it is
- **Memory**: The action has a negligible memory footprint as it does not store large datasets.

## Related Topics
- [Action Documentation]({{< relref "core-actions/condition.md" >}})
- [Action Documentation]({{< relref "core-actions/check.md" >}})
- [Architecture Reference]({{< relref "advanced-reference/architecture/actions/condition.md" >}})
- [Condition Builder Guide]({{< relref "core-actions/condition.md" >}})
- [Condition Builder Guide]({{< relref "core-actions/check.md" >}})
2 changes: 1 addition & 1 deletion content/en/advanced-reference/reference/execution/stop.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ The Stop action has read-only access to:
The transaction behavior of the Stop action depends entirely on its mode:

- **Success**: The action has no impact on the current database transaction. The transaction continues as normal and will commit when the overall rule execution (and any other triggered rules) finishes successfully.
- **Error**: Raising a `frappe.ValidationError` triggers a standard database **Rollback**. Any changes made by previous nodes in the same rule flow (e.g., [Assignment]({{< relref "core-actions/assignment" >}}) updates to `doc`) will be reverted.
- **Error**: Raising a `frappe.ValidationError` triggers a standard database **Rollback**. Any changes made by previous nodes in the same rule flow (e.g., [Assignment]({{< relref "core-actions/set-value" >}}) updates to `doc`) will be reverted.

## Failure Behavior
If the Jinja template in the error message fails to render, the engine will raise a secondary rendering error. However, since the intent was already to stop with an error, the result is still a termination of the flow and a rollback of the transaction.
Expand Down
23 changes: 23 additions & 0 deletions content/en/core-actions/advanced-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: Advanced Process
description: Execute complex custom logic or background tasks.
weight: 110
aliases:
- /docs/actions/process/
---

# Advanced Process

The **Advanced Process** block is used for special logic that goes beyond standard record updates or notifications. These processes are usually predefined by a developer.

## When to Use
- **Custom Logic**: Run a specific Python or JavaScript process.
- **Calculations**: Perform heavy math or data processing.
- **Integrations**: Send data to or receive data from other systems via an API.

## How to Configure
1. **Select Process**: Pick the predefined process you want to run.
2. **Provide Inputs**: Fill in any required information the process needs.
3. **Use Results**: Use any values the process returns in your following logic blocks.

> **Note**: If you need a new process created, contact your system administrator or developer.
28 changes: 0 additions & 28 deletions content/en/core-actions/assignment.md

This file was deleted.

30 changes: 30 additions & 0 deletions content/en/core-actions/check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: Check
description: Branch your rule logic based on true/false evaluations.
weight: 40
aliases:
- /docs/actions/condition/
---

# Check

The **Check** block (internally called Condition) allows you to create branches in your logic. It evaluates a set of rules and directs the flow down either a **True** or **False** path.

## How to Configure

### 1. Build Your Logic
Use the guided builder to define what you want to check.
- **Field**: Select a field or variable (e.g., "Grand Total").
- **Operator**: Choose how to compare (e.g., "is greater than", "contains").
- **Value**: The value you are checking against.

### 2. Combine Rules (And/Or)
- **AND**: Every rule in the group must be true for the flow to take the True path.
- **OR**: If at least one rule is true, the flow takes the True path.

## Example
**Scenario**: Send a notification only for large orders.
1. Add a **Check** block.
2. Rule: `grand_total` is greater than `5000`.
3. Connect the **True** path to a [Notify]({{< relref "notify-action" >}}) block.
4. Leave the **False** path empty to do nothing for smaller orders.
Loading
Loading