Workflow Query Reference

Developer guide for the Enezaframework workflow engine. Part of the Workflow series.

Table of Contents

  1. Overview
  2. Files and Changes
  3. SavedQuery API
  4. parse_annotations() API
  5. get_aggregate_options() API
  6. View Query Parameters
  7. Edge Cases
  8. Out of Scope
  9. Related Guides

Overview

Condensed reference for the workflow query enhancements. For behavior, see Workflow Query Architecture.


Files and Changes

File Purpose
enezaworkflowengine/utils.py AGGREGATE_FUNCTION_MAP (:180), parse_annotations() (:189), _validate_relationship() (:245).
enezaworkflowengine/models/querybuilder.py SavedQuery.get_queryset(object_id=None) (:31), execute (:62), execute_new_format (:69).
enezaworkflowengine/views/mixin.py QueryBuilderMixin.get_aggregate_options() (:152).
enezaworkflowengine/views/querybuilder.py BuildQueryView (:55), SaveQueryView.post() (:79), SaveQueryDetailView (:180).
enezaworkflowengine/services/condition_step.py evaluate_condition_for_document() (:16).
enezaworkflowengine/services/step_handlers.py ConditionStepHandler._evaluate_and_route() (:233).
enezaworkflowengine/tasks/workflow_tasks.py evaluate_condition_step() (:216) delegates auto-extraction.

SavedQuery API

Method Signature Notes
get_queryset() get_queryset(object_id=None) Applies annotations, filters, then optional object_id.
execute() execute(object_id=None) Alias for get_queryset().
execute_new_format() execute_new_format(object_id=None) Groups-format parser; also supports annotations.

SavedQuery is defined in enezaworkflowengine/models/querybuilder.py:16 and inherits EnezaGeneral.


parse_annotations() API

python
parse_annotations(model_class, annotations_list) -> Dict[str, Aggregate]
Parameter Type Description
model_class Model Django model class used to validate relationships.
annotations_list List[Dict] Annotation dicts with function, field, related_model, alias.
Returns Dict[str, Aggregate] Dict suitable for queryset.annotate(**result).

Raises ValueError for missing keys, unsupported functions, or invalid relationships.


get_aggregate_options() API

python
QueryBuilderMixin.get_aggregate_options(model_config) -> Dict[str, Any]
Parameter Type Description
model_config Dict Model config from get_allowed_models(); uses its relationships list.
Returns Dict[str, Any] {'related_models': [{'field_name', 'label', 'fields'}], 'functions': [{'name', 'label'}]}.

The return value is hierarchical, not a flat option list. See Workflow Aggregate Metadata API.


View Query Parameters

View Parameter Description
BuildQueryView ?workflow_name=X Loads the allowed models for a workflow.
SaveQueryDetailView ?execute=1 Executes the saved query.
SaveQueryDetailView ?object_id=<uuid> Filters results to a single document.
SaveQueryDetailView ?edit=1 Loads the edit template with builder context.
SaveQueryListView ?workflow=X Filters the saved-query list by workflow.

Routes are mounted under /workflow/ with the URL namespace enezaworkflowengine (enezaworkflowengine/urls.py:47). Example: enezaworkflowengine:savedquery_detail.


Edge Cases

Scenario Behavior
object_id is None No filtering (backward compatible).
annotations key missing No aggregation (backward compatible).
annotations is [] No aggregation.
Annotation references a nonexistent related_model ValueError with a descriptive message.
Annotation uses an unsupported function ValueError listing the supported functions.
Multiple annotations share an alias Last one wins (dict overwrite).
Rule references an undefined alias Django raises FieldError.
object_id type mismatches the PK Django raises ValueError; the detail view captures it.
count annotation with no field Uses Count(related_model).
Model config omits relationships get_aggregate_options() returns an empty related_models; declare relationships to surface aggregates.

Out of Scope

  • Aggregate values in query result output.
  • Nested aggregates (aggregate over aggregate).
  • Custom or expression-based annotations beyond the five standard functions.
  • UI/template changes for the aggregate selector (handled as a frontend task).