Most Powerful Open Source ERP

How To Use and Define Interaction Workflows

showing how to use and define interaction workflows defining interactions on objects.
  • Last Update:2016-02-11
  • Version:001
  • Language:en

Note: This how-to is work in progress, written mostly by inexperienced developer, needs review

Normal workflows are used to implement effects of user interaction - validating of objects, ordering, planning and confirming of orders, etc.

Table of Contents

Interaction Workflows

By interaction workflows it is possible to define interactions on objects - in other words catching some methods invocations and defining actions, which shall happen on object. You can think of it as something similar to a "trigger" in relation database, a "hook", or a "side effect" of other actions. In other words, you can add some behaviour to an object without altering the object (class) itself.

For example, you may want to set a generated Title on new created objects like T0001, T0002, ... To gain such possibility, it's possible to use interaction workflow.

Examples of interaction workflow are in business templates - very interesting usage is in trade_model_line_interaction_workflow.

Example

We want to set titles on Purchase Order and Sale Order objects.

Go to Contents tab of workflow tool, create custom_title_setter_sale_order_interaction_workflow, choose interaction workflow.

Now go to Workflows tab of workflow tool and associate custom_title_seter_sale_order_interaction_workflow with Purchase Order Module and Sale Order Module portal types, then return to defining of interaction workflow.

Create scripts: PurchaseOrder_titleSetter and SaleOrder_titleSetter.

## Script (Python) "PurchaseOrder_titleSetter"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=state_change
##title=
##
module = state_change['object']
# get the new created object
new_created_object = state_change['kwargs']['workflow_method_result']

# id group si used to define what will define your counter
id_group = ('title', new_created_object.getPortalType())
default = 1
title = module.portal_ids.generateNewLengthId(id_group=id_group, default=default)
new_created_object.setTitle('T%04d' % title)

So now we have to define interaction for our portal types. Go to Interactions tab, and create PurchaseOrder_titleSetInteraction. Edit it, and for set fields to:

  • Filter : Purchase Order Module
  • Trigger Method Id(s) : newContent
  • Script (after) : PurchaseOrder_titleSetter

Create interaction SaleOrder_titleSetInteraction and set fields properly. As exercise base definitions of above values.

Now create Purchase or Sale order and watch what happens. Titles looking like T0001, T0002, ... should be used

Most important part in interaction definition is Trigger Method Id(s). To catch all typical invocations. You can use method like newContent, but also edit and _edit you can also catch workflow transition like cancel, validate. And last, but not least, you can catch relating order with source/destination section we have to add _setDestinationValue, _setDestinationSectionValue, _setSourceValue, _setSourceSectionValue.

Reference documentation

Creating interaction workflows

To create interaction workflow navigate to workflow tool Contents tab add new workflow, type its Id and choose Type interaction_workflow.

Proposed Id grammar is someprefix[_portal_or_meta_type][_description_]interaction_workflow, eg:

  • custom_packing_list_interaction_workflow
  • custom_order_line_title_setter_interaction_workflow

Interaction workflows can be organised in various ways - per portal type (one interaction workflow for each portal type which needs it), or per function (aspect), or something else. For example, some developers find it convenient to create one security_update_interaction_workflow which is then used for every portal type which requires a security update upon certain actions.

Properties

Same as in normal workflows.

Interactions

List of possible interactions, which every can have additional constraints:

  • Filter: interaction will be invoked only on chosen portal types ((!) this list will be filled after association interaction workflows with portal types)
  • Trigger type:
    • Automatic - TODO
    • Initiated by WorkflowMethod - TODO
  • Trigger Method Id(s): list of methods, which will trigger workflows. You can catch many things
    • edit and _edit (though think twice, this would be triggered very often)
    • normal workflow actions (like stop, cancel, confirm)
    • low level methods (manage_afterClone)
    • category setters (_setResourceValue,_setDestinationValue)
    • property setters (use _set[PropertyName].* to catch all invocations of the setter)
  • Script (before), Script (after) and Activities (later) - list of script which will be invoked before action happens, after action happens and which will be invoked in activities. /!\ Experiment with other scripts which are invoked by those actions.
  • Guard - which guards applies to this interaction, same as in normal workflows

Note: It is quite good idea to define methods (scripts) before defining interactions.

Variables

Todo

Scripts

Every script in you interaction workflows definition shall have argument called (by convention) state_change. To access changed object use:

changed_object = state_change['object']

Don't do state_change.object - it usually works but sometimes causes security problems. Scripts can be invoked:

  • before - ran immediately; if triggered by a setter uses the old value of a property
  • after - ran immediately; if triggered by a setter uses the new value of a property
  • later - executed a bit later, usually a few seconds but can be much longer

QUESTION: what to do if an interaction has to compare the old value to the new one? Is there a way to access them both at the same time (other then request lookup)?

List of usable Trigger methods

When editing using the standard ERP5 interface, edit method will be called. Then for each modified property, when you have for example a field "my_foo", the corresponding accessor _setFoo will be called. If _setFoo does not exists, setFoo will be called instead. If setFoo does not exist either, setProperty('foo', value) will be called.

There is an exception for RelationFields. When a RelationField is modified, either the field defines a "Relation Update Method" that will be called, either the default _set${base_category}Value (or _set${base_category}ValueList when setting a multiple relation) accessor will be called, where ${base_category} is the capitalized name of the base category used for this accessor.

Here is a summary of methods that can be used:

  • edit: this method shall trigger on when object is edited, but see below
  • _setResourceValue: this method will be triggered on when relation defined on resource category will be changed. /!\ Such change will NOT be triggered by edit method
  • _set.*: you may use regular expressions to trigger on more then one method - it is quite usefull in case of relation setting methods
  • manage_afterAdd: trigger on while adding object
  • manage_afterClone: trigger on while pasting copied or cut object. Also note that you can use _afterClone TypeBasedMethod.
  • manager_beforeDelete: trigger on before deleting object

Questions and Answers

How can I redirect from an interaction workflow script?
You can't.

Related Articles