This guide demonstrates how to use the workflow simulation and management features introduced in the wortel branch.
The ObjReportWorkflowSim report provides an interactive workflow testing interface without triggering actual production runs.
Add a workflow simulation report to your page:
from ObjReportWorkflowSim import ObjReportWorkflowSim
# Create the report
report = ObjReportWorkflowSim()
html = report.Render(
"my_workflow_name", # Param1: workflow name (required)
"Test My Workflow", # Param2: custom header (optional)
"scheduler,form,webhook" # Param3: simulation modes (optional)
)
The report supports three simulation modes:
If Param3 is not provided, all three modes are enabled by default.
The simulation form reads field definitions from resource.modules/config/workflow.yaml:
module: workflow
workflows:
- name: user_registration
method: none
table: ''
package: $package$
fields:
Username:
label: Username
type: text
required: true
Email:
label: Email Address
type: email
required: true
Password:
label: Password
type: password
required: true
AcceptTerms:
label: Accept Terms and Conditions
type: checkbox
required: false
The report loads field definitions in this order:
resource.modules/config/*.yaml where module: workflow (preferred)ObjWorkflowEdit using input_avro if presentparam1, param2, param3) if no source is availableThe simulation report includes an embedded MQTT event flow viewer that shows:
Use the {export_workflow} macro to add an export button:
{export_workflow:my_workflow:Export Configuration:/doc/workflow:Download YAML:Optional help text}
Parameters:
Use the {import_workflow} macro to add an import form:
{import_workflow:my_workflow:Import Configuration:/doc/:Import YAML:Optional help text}
Parameters:
Exported workflows contain:
WorkflowName: my_workflow
Workflow:
WorkflowName: my_workflow
Package: homechoice
Description: Workflow description
UserGroup: ALL
# ... other workflow properties
Nodes:
- Name: node1
Type: START
Rank: 1
# ... node properties
- Name: node2
Type: CALC
Rank: 2
# ... node properties
Calculations:
calculation_group_name:
- Name: calc1
Rank: 1
# ... calculation properties
The {create:...} macro provides reusable modal forms for creating objects:
{create:<object_type>[:<button_label>[:<modal_title>[:<submit_label>[:<report_code>[:<refresh_report>]]]]]}
{create:workflow:+ New Workflow:Create New Workflow:Save:EditWorkflow:workflows}
This creates:
ObjTextCreate.yaml under create.workflowcreate:
workflow:
report_code: EditWorkflow
table: def_workflow
title_field: WorkflowName
fields:
WorkflowName:
label: Workflow Name
type: text
required: true
placeholder: Enter workflow name
Description:
label: Description
type: textarea
required: false
rows: 3
UserGroup:
label: User Group
type: select
required: true
options:
- ALL
- ADMIN
- USER
When refresh_report parameter is provided, the modal automatically:
getlist on the specified reportThe ObjTextMenu processor generates dynamic menus from configuration:
from ObjTextMenu import ObjProcessText
menu_processor = ObjProcessText()
html = menu_processor.Process(
param1="main_menu", # Menu configuration name
param2="horizontal", # Layout: horizontal/vertical
param3="", # Additional CSS classes
param4="", # Reserved
param5="", # Reserved
param6="", # Reserved
param7="", # Reserved
param8="" # Reserved
)
Debug messages are automatically logged to MQTT when DO_MQTT = True:
DO_MQTT: bool = True # Enable MQTT logging
# In your code
self.debug("Processing workflow", workflow_name)
# Automatically logged to MQTT with:
# - Log level (debug/warning/error)
# - Function and module context
# - User, usergroups, company, package
Log levels map to:
logging.ERROR → "error"logging.WARNING → "warning"Workflows now track event sequences for better traceability:
# Event sequence based on transition count
run_context["event_seq"] = run_context.get("transition_count", 0)
# Logged with each event
self.log_event(
f"WORKFLOW_{workflow_code}_TRANSIT",
f"{node_type}_{name}",
latency,
param8=run_context.get("event_seq", 0), # Event sequence number
param9=guid
)
This enables:
Store workflow field definitions in YAML for maintainability:
Use workflow simulation to:
Use workflow export/import for:
Configure MQTT logging appropriately:
DO_MQTT = TrueDO_MQTT = FalseLeverage event sequencing for:
resource.modules/config/workflow.yaml existsmodule: workflow is set in YAMLDO_MQTT = True in relevant moduleslog_mqtt_event method is availableObjTextCreate.yaml# resource.modules/config/workflow.yaml
module: workflow
workflows:
- name: customer_onboarding
method: none
table: ''
package: $package$
fields:
CustomerName:
label: Customer Name
type: text
required: true
Email:
label: Email
type: email
required: true
Phone:
label: Phone Number
type: tel
required: false
AccountType:
label: Account Type
type: select
required: true
options:
- Basic
- Premium
- Enterprise
StartDate:
label: Start Date
type: date
required: true
<!-- Export workflow -->
<div class="workflow-tools">
{export_workflow:customer_onboarding:Export Workflow:/doc/workflow:Download}
</div>
<!-- Import workflow -->
<div class="workflow-tools">
{import_workflow::Import Workflow:/doc/:Upload YAML:Upload a workflow configuration file}
</div>
<!-- Add to workflows list page -->
<div class="toolbar">
{create:workflow:+ Create Workflow:New Workflow:Create:EditWorkflow:workflows}
</div>
factory.report/package.core/ObjReportWorkflowSim.md - Full report documentationfactory.text/package.core/ObjTextCreate.md - Create modal documentationfactory.workflow/ObjWorkflowEdit.yaml - SQL queries for workflow managementresource.modules/config/workflow.yaml - Workflow configuration format