[IMP] doc: add some diagrams to workflow doc

Also move transitions to the bottom of the document, and try to clarify the
documentation for split, join and activity kinds.
This commit is contained in:
Xavier Morel 2014-11-03 14:53:38 +01:00
parent 786077d675
commit a332dec4c2
14 changed files with 423 additions and 155 deletions

View File

@ -0,0 +1,20 @@
DOTFILES:=$(wildcard *.dot)
SVGFILES:=$(patsubst %.dot,%.svg,$(DOTFILES))
PNGFILES:=$(patsubst %.dot,%.png,$(DOTFILES))
# try to disable implicit rules
.SUFFIXES:
.PHONY: all clean
all: $(SVGFILES) $(PNGFILES)
# must -f to ignore errors when running clean multiple times in a row
clean:
rm -f *.png *.svg
%.svg: %.dot
dot -Tsvg $< > $@
%.png: %.dot
dot -Tpng $< > $@

View File

@ -0,0 +1,10 @@
digraph join {
// dummy sources as support for edges, make invisible and height 0
a [style=invis height=0 fontsize=0]
b [style=invis height=0 fontsize=0]
c [style=invis height=0 fontsize=0]
a -> Activity
b -> Activity
c -> Activity
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: join Pages: 1 -->
<svg width="206pt" height="93pt"
viewBox="0.00 0.00 206.00 92.73" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 88.7279)">
<title>join</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-88.7279 202,-88.7279 202,4 -4,4"/>
<!-- a -->
<!-- Activity -->
<g id="node4" class="node"><title>Activity</title>
<ellipse fill="none" stroke="black" cx="99" cy="-18" rx="40.0939" ry="18"/>
<text text-anchor="middle" x="99" y="-14.3" font-family="Times,serif" font-size="14.00">Activity</text>
</g>
<!-- a&#45;&gt;Activity -->
<g id="edge1" class="edge"><title>a&#45;&gt;Activity</title>
<path fill="none" stroke="black" d="M33.6445,-71.9778C42.4332,-64.8537 58.4442,-51.875 72.4186,-40.5472"/>
<polygon fill="black" stroke="black" points="74.7768,-43.1411 80.3411,-34.1251 70.3688,-37.7033 74.7768,-43.1411"/>
</g>
<!-- b -->
<!-- b&#45;&gt;Activity -->
<g id="edge2" class="edge"><title>b&#45;&gt;Activity</title>
<path fill="none" stroke="black" d="M99,-71.9778C99,-66.0508 99,-56.0715 99,-46.3619"/>
<polygon fill="black" stroke="black" points="102.5,-46.1364 99,-36.1364 95.5001,-46.1365 102.5,-46.1364"/>
</g>
<!-- c -->
<!-- c&#45;&gt;Activity -->
<g id="edge3" class="edge"><title>c&#45;&gt;Activity</title>
<path fill="none" stroke="black" d="M164.355,-71.9778C155.567,-64.8537 139.556,-51.875 125.581,-40.5472"/>
<polygon fill="black" stroke="black" points="127.631,-37.7033 117.659,-34.1251 123.223,-43.1411 127.631,-37.7033"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,9 @@
digraph order {
Draft [style=filled fillcolor="#73fa79"]
Closed [style=filled fillcolor="#98c7df"]
Canceled [style=filled fillcolor="#98c7df"]
Draft -> Confirmed
Confirmed -> Closed
Confirmed -> Canceled
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: order Pages: 1 -->
<svg width="188pt" height="188pt"
viewBox="0.00 0.00 188.24 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<title>order</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-184 184.243,-184 184.243,4 -4,4"/>
<!-- Draft -->
<g id="node1" class="node"><title>Draft</title>
<ellipse fill="#73fa79" stroke="black" cx="85.3968" cy="-162" rx="30.5947" ry="18"/>
<text text-anchor="middle" x="85.3968" y="-158.3" font-family="Times,serif" font-size="14.00">Draft</text>
</g>
<!-- Confirmed -->
<g id="node4" class="node"><title>Confirmed</title>
<ellipse fill="none" stroke="black" cx="85.3968" cy="-90" rx="51.9908" ry="18"/>
<text text-anchor="middle" x="85.3968" y="-86.3" font-family="Times,serif" font-size="14.00">Confirmed</text>
</g>
<!-- Draft&#45;&gt;Confirmed -->
<g id="edge1" class="edge"><title>Draft&#45;&gt;Confirmed</title>
<path fill="none" stroke="black" d="M85.3968,-143.697C85.3968,-135.983 85.3968,-126.712 85.3968,-118.112"/>
<polygon fill="black" stroke="black" points="88.8969,-118.104 85.3968,-108.104 81.8969,-118.104 88.8969,-118.104"/>
</g>
<!-- Closed -->
<g id="node2" class="node"><title>Closed</title>
<ellipse fill="#98c7df" stroke="black" cx="36.3968" cy="-18" rx="36.2938" ry="18"/>
<text text-anchor="middle" x="36.3968" y="-14.3" font-family="Times,serif" font-size="14.00">Closed</text>
</g>
<!-- Canceled -->
<g id="node3" class="node"><title>Canceled</title>
<ellipse fill="#98c7df" stroke="black" cx="135.397" cy="-18" rx="44.6926" ry="18"/>
<text text-anchor="middle" x="135.397" y="-14.3" font-family="Times,serif" font-size="14.00">Canceled</text>
</g>
<!-- Confirmed&#45;&gt;Closed -->
<g id="edge2" class="edge"><title>Confirmed&#45;&gt;Closed</title>
<path fill="none" stroke="black" d="M73.7845,-72.411C67.8042,-63.8677 60.3917,-53.2785 53.7479,-43.7874"/>
<polygon fill="black" stroke="black" points="56.5277,-41.6552 47.9257,-35.4699 50.7931,-45.6694 56.5277,-41.6552"/>
</g>
<!-- Confirmed&#45;&gt;Canceled -->
<g id="edge3" class="edge"><title>Confirmed&#45;&gt;Canceled</title>
<path fill="none" stroke="black" d="M97.2461,-72.411C103.348,-63.8677 110.912,-53.2785 117.692,-43.7874"/>
<polygon fill="black" stroke="black" points="120.668,-45.6416 123.633,-35.4699 114.972,-41.573 120.668,-45.6416"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,11 @@
digraph order {
Draft [style=filled fillcolor="#73fa79"]
Closed [style=filled fillcolor="#98c7df"]
Canceled [style=filled fillcolor="#98c7df"]
Draft -> Confirmed [label="discount <= 15%"]
Draft -> Validation [label="discount > 15%"]
Validation -> Confirmed [label="Accept"]
Confirmed -> Closed
Confirmed -> Canceled
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: order Pages: 1 -->
<svg width="260pt" height="291pt"
viewBox="0.00 0.00 259.79 291.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 287)">
<title>order</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-287 255.792,-287 255.792,4 -4,4"/>
<!-- Draft -->
<g id="node1" class="node"><title>Draft</title>
<ellipse fill="#73fa79" stroke="black" cx="85.3968" cy="-265" rx="30.5947" ry="18"/>
<text text-anchor="middle" x="85.3968" y="-261.3" font-family="Times,serif" font-size="14.00">Draft</text>
</g>
<!-- Confirmed -->
<g id="node4" class="node"><title>Confirmed</title>
<ellipse fill="none" stroke="black" cx="85.3968" cy="-91" rx="51.9908" ry="18"/>
<text text-anchor="middle" x="85.3968" y="-87.3" font-family="Times,serif" font-size="14.00">Confirmed</text>
</g>
<!-- Draft&#45;&gt;Confirmed -->
<g id="edge1" class="edge"><title>Draft&#45;&gt;Confirmed</title>
<path fill="none" stroke="black" d="M72.5816,-248.399C62.7132,-235.312 49.8641,-215.656 44.3968,-196 40.1092,-180.585 40.1092,-175.415 44.3968,-160 48.7071,-144.503 57.6054,-129.007 66.0142,-116.73"/>
<polygon fill="black" stroke="black" points="68.9995,-118.572 71.9779,-108.405 63.3089,-114.496 68.9995,-118.572"/>
<text text-anchor="middle" x="94.3968" y="-174.3" font-family="Times,serif" font-size="14.00">discount &lt;= 15%</text>
</g>
<!-- Validation -->
<g id="node5" class="node"><title>Validation</title>
<ellipse fill="none" stroke="black" cx="202.397" cy="-178" rx="49.2915" ry="18"/>
<text text-anchor="middle" x="202.397" y="-174.3" font-family="Times,serif" font-size="14.00">Validation</text>
</g>
<!-- Draft&#45;&gt;Validation -->
<g id="edge2" class="edge"><title>Draft&#45;&gt;Validation</title>
<path fill="none" stroke="black" d="M103.936,-250.531C122.48,-237.059 151.286,-216.131 172.959,-200.386"/>
<polygon fill="black" stroke="black" points="175.139,-203.129 181.172,-194.42 171.024,-197.466 175.139,-203.129"/>
<text text-anchor="middle" x="195.897" y="-217.8" font-family="Times,serif" font-size="14.00">discount &gt; 15%</text>
</g>
<!-- Closed -->
<g id="node2" class="node"><title>Closed</title>
<ellipse fill="#98c7df" stroke="black" cx="36.3968" cy="-18" rx="36.2938" ry="18"/>
<text text-anchor="middle" x="36.3968" y="-14.3" font-family="Times,serif" font-size="14.00">Closed</text>
</g>
<!-- Canceled -->
<g id="node3" class="node"><title>Canceled</title>
<ellipse fill="#98c7df" stroke="black" cx="135.397" cy="-18" rx="44.6926" ry="18"/>
<text text-anchor="middle" x="135.397" y="-14.3" font-family="Times,serif" font-size="14.00">Canceled</text>
</g>
<!-- Confirmed&#45;&gt;Closed -->
<g id="edge4" class="edge"><title>Confirmed&#45;&gt;Closed</title>
<path fill="none" stroke="black" d="M73.7845,-73.174C67.7175,-64.3831 60.1766,-53.4564 53.4596,-43.7236"/>
<polygon fill="black" stroke="black" points="56.1491,-41.4588 47.5884,-35.2165 50.3879,-45.4348 56.1491,-41.4588"/>
</g>
<!-- Confirmed&#45;&gt;Canceled -->
<g id="edge5" class="edge"><title>Confirmed&#45;&gt;Canceled</title>
<path fill="none" stroke="black" d="M97.2461,-73.174C103.348,-64.5087 110.912,-53.7682 117.692,-44.1415"/>
<polygon fill="black" stroke="black" points="120.736,-45.8965 123.633,-35.7052 115.013,-41.8661 120.736,-45.8965"/>
</g>
<!-- Validation&#45;&gt;Confirmed -->
<g id="edge3" class="edge"><title>Validation&#45;&gt;Confirmed</title>
<path fill="none" stroke="black" d="M181.209,-161.607C162.688,-148.152 135.604,-128.475 114.953,-113.472"/>
<polygon fill="black" stroke="black" points="116.97,-110.612 106.822,-107.566 112.856,-116.275 116.97,-110.612"/>
<text text-anchor="middle" x="170.397" y="-130.8" font-family="Times,serif" font-size="14.00">Accept</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,10 @@
digraph split {
// dummy destinations as support for edges, make invisible and height 0
a [style=invis height=0 fontsize=0]
b [style=invis height=0 fontsize=0]
c [style=invis height=0 fontsize=0]
Activity -> a
Activity -> b
Activity -> c
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: split Pages: 1 -->
<svg width="206pt" height="93pt"
viewBox="0.00 0.00 206.00 92.73" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 88.7279)">
<title>split</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-88.7279 202,-88.7279 202,4 -4,4"/>
<!-- a -->
<!-- b -->
<!-- c -->
<!-- Activity -->
<g id="node4" class="node"><title>Activity</title>
<ellipse fill="none" stroke="black" cx="99" cy="-66.7279" rx="40.0939" ry="18"/>
<text text-anchor="middle" x="99" y="-63.0279" font-family="Times,serif" font-size="14.00">Activity</text>
</g>
<!-- Activity&#45;&gt;a -->
<g id="edge1" class="edge"><title>Activity&#45;&gt;a</title>
<path fill="none" stroke="black" d="M80.4582,-50.6978C68.3594,-40.8903 52.7894,-28.2691 41.577,-19.1802"/>
<polygon fill="black" stroke="black" points="43.641,-16.3478 33.6687,-12.7696 39.233,-21.7857 43.641,-16.3478"/>
</g>
<!-- Activity&#45;&gt;b -->
<g id="edge2" class="edge"><title>Activity&#45;&gt;b</title>
<path fill="none" stroke="black" d="M99,-48.5325C99,-40.494 99,-30.9869 99,-23.1351"/>
<polygon fill="black" stroke="black" points="102.5,-22.8941 99,-12.8941 95.5001,-22.8942 102.5,-22.8941"/>
</g>
<!-- Activity&#45;&gt;c -->
<g id="edge3" class="edge"><title>Activity&#45;&gt;c</title>
<path fill="none" stroke="black" d="M117.542,-50.6978C129.641,-40.8903 145.211,-28.2691 156.423,-19.1802"/>
<polygon fill="black" stroke="black" points="158.767,-21.7857 164.331,-12.7696 154.359,-16.3478 158.767,-21.7857"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -3,14 +3,14 @@
Workflows
=========
In OpenERP, a workflow is a technical artefact to manage a set of "things to
do" associated to the records of some data model. The workflow provides a
higher- level way to organize the things to do on a record.
In Odoo, a workflow is a technical artefact to manage a set of "things to
do" associated to the records of a model. The workflow provides a higher-level
way to organize tasks to perform with or on a record.
More specifically, a workflow is a directed graph where the nodes are called
"activities" and the arcs are called "transitions".
- Activities define work that should be done within the OpenERP server, such
- Activities define work that should be done within the Odoo server, such
as changing the state of some records, or sending emails.
- Transitions control how the workflow progresses from activity to activity.
@ -19,6 +19,40 @@ triggers to transitions, so that the behavior of the workflow depends on user
actions (such as clicking on a button), changes to records, or arbitrary
Python code.
All in all, Odoo's workflow system provides:
* a description of the evolution of a record (document) over time
* automatic actions based on various and flexible conditions
* management of company roles and validation steps
* management of interactions between objects
* a visual representation of document flows through their lifecycle
For instance, a basic order could have the following flow:
.. sphinx.ext.graphviz would be nice, but it requires ``dot`` on any machine
.. where the doc is compiled... otoh this is a pain in the ass because you
.. need 2 compilation steps (dot -> image and rst -> html) every time
.. image:: workflow/order_0.*
:align: center
Orders start in the *Draft* state, can be *Confirmed* by a user, and then
either shipped (*Closed*) or *Canceled*.
A company using Odoo may want to add discount support to orders, where sales
staff has discretionary discounting powers up to 15%, but manager validation
is required for discounts beyond 15%. The workflow can be altered online to
add the relevant steps without editing Python or XML files:
.. image:: workflow/order_1.*
:align: center
Because Activities can perform arbitrary actions, the *Validation* can
automatically send a validation request to the relevant employee.
.. note:: the order view needs to be modified to add an *Accept Discount*
button for managers
Basics
------
@ -63,7 +97,7 @@ made up of two activies, named "a" and "b", and one transition, going from "a"
to "b".
The first activity has its attribute ``flow_start`` set to ``True`` so that
OpenERP knows where to start the workflow traversal after it is instanciated.
Odoo knows where to start the workflow traversal after it is instanciated.
Because ``on_create`` is set to True on the workflow record, the workflow is
instanciated for each newly created record. (Otherwise, the workflow should be
instanciated by other means, such as from some module Python code.)
@ -77,6 +111,142 @@ The transition between "a" and "b" does not specify any condition. This means
that the workflow instance immediately goes from "a" to "b" after "a" has been
processed, and thus also processes activity "b".
Activities
----------
While the transitions can be seen as the control structures of the workflows,
activities are the places where everything happens, from changing record
states to sending email.
Different kinds of activities exist: ``Dummy``, ``Function``, ``Subflow``, and
``Stop all``, each doing different things when the activity is processed. In
addition to their kind, activies have other properties, detailed in the next
sections.
Flow start and flow stop
''''''''''''''''''''''''
The attribute ``flow_start`` is a boolean value specifying whether the activity
is processed when the workflow is instanciated. Multiple activities can have
their attribute ``flow_start`` set to ``True``. When instanciating a workflow
for a record, Odoo simply processes all of them, and evaluate all their
outgoing transitions afterwards.
The attribute ``flow_stop`` is a boolean value specifying whether the activity
stops the workflow instance. A workflow instance is considered completed when
all its activities with the attribute ``flow_stop`` set to ``True`` are
completed.
It is important for Odoo to know when a workflow instance is completed. A
workflow can have an activity that is actually another workflow (called a
subflow); that activity is completed when the subflow is completed.
Subflow
'''''''
An activity can embed a complete workflow, called a subflow (the embedding
workflow is called the parent workflow). The workflow to instanciate is
specified by attribute ``subflow_id``.
.. note:: In the GUI, that attribute can not be set unless the kind of the
activity is ``Subflow``.
The activity is considered completed (and its outgoing transitions ready to be
evaluated) when the subflow is completed (see attribute ``flow_stop`` above).
Sending a signal from a subflow
'''''''''''''''''''''''''''''''
When a workflow is embedded in an activity (as a subflow) of a workflow, the
sublow can send a signal from its own activities to the parent workflow by
giving a signal name in the attribute ``signal_send``. Odoo processes those
activities by sending the value of ``signal_send`` prefixed by "subflow." to
the parent workflow instance.
In other words, it is possible to react and get transitions in the parent
workflow as activities are executed in the sublow.
Server actions
''''''''''''''
An activity can run a "Server Action" by specifying its ID in the attribute
``action_id``.
Python action
'''''''''''''
An activity can execute some Python code, given by the attribute ``action``.
The evaluation environment is the same as the one explained in the section
`Conditions`_.
Split mode
''''''''''
After an activity has been processed, Odoo evaluates its transition to reach
the next activity in the flow.
However if an activity has more than one transition, Odoo must decide which
activity or activities to follow.
.. image:: workflow/split.*
:align: center
This choice is controlled by the ``split_mode`` attribute:
``XOR`` (default)
By default, Odoo will use the first transition (in ``sequence`` order)
whose condition is satisfied. All other transitions are ignored.
``OR``
In ``OR`` mode, all transitions with a satisfied condition are traversed
simultanously. Transitions not yet valid will be ignored, even if they
become valid later.
``AND``
In ``AND`` mode, Odoo will wait until *all* transitions are satisfied, and
will traverse all of them (much like the ``OR`` mode).
Both ``OR`` and ``AND`` mode will lead to activities being active in the same
workflow.
Join mode
'''''''''
Just like outgoing transition conditions can be combined together to decide
whether they can be traversed or not, incoming transitions can be combined
together to decide if and when an activity may be processed.
.. image:: workflow/join.*
:align: center
The ``join_mode`` attribute controls that behavior:
``XOR`` (default)
Any incoming transition enables the activity and starts its processing.
``AND``
The activity is enabled and processed only once *all* incoming transitions
have been traversed.
Kinds
'''''
An activity's kind defines the type of work an activity can perform.
Dummy (``dummy``, default)
Do nothing at all, or call a server action. Often used as dispatch or
gather "hubs" for transitions.
Function (``function``)
Run some python code, execute a server action.
Stop all (``stopall``)
Completely stops the workflow instance and marks it as completed.
Subflow (``subflow``)
Starts executing an other workflow, once that workflow is completed the
activity is done processing.
By default, the subflow is instanciated for the same record as the parent
workflow. It is possible to change that behavior by providing Python code
that returns a record ID (of the same data model as the subflow). The
embedded subflow instance is then the one of the given record.
Transitions
-----------
@ -98,7 +268,7 @@ Conditions
When an activity has been completed, its outgoing transitions are inspected to
determine whether it is possible for the workflow instance to proceed through
them and reach the next activities. When only a condition is defined (i.e., no
signal or trigger is defined), the condition is evaluated by OpenERP, and if
signal or trigger is defined), the condition is evaluated by Odoo, and if
it evaluates to ``True``, the worklfow instance progresses through the
transition. If the condition is not met, it will be reevaluated every time
the associated record is modified, or by an explicit method call to do it.
@ -109,7 +279,7 @@ may be several lines long; in that case, the value of the last one determines
whether the transition can be taken.
In the condition evaluation environment, several symbols are conveniently
defined (in addition to the OpenERP ``safe_eval`` environment):
defined (in addition to the Odoo ``safe_eval`` environment):
- all the model column names, and
- all the browse record's attributes.
@ -152,151 +322,3 @@ record IDs in the given model. Any of those records can wake up the workflow
instance they are associated with.
.. note:: triggers are not re-installed whenever the transition is re-tried.
Splitting and joining transitions
'''''''''''''''''''''''''''''''''
When multiple transitions leave the same activity, or lead to the same
activity, OpenERP provides some control over which transitions are actually
taken, or how the reached activity will be processed. The attributes
``split_mode`` and ``join_mode`` on the activity are used for such
control. The possible values of those attributes are explained below.
Activities
----------
While the transitions can be seen as the control structures of the workflows,
activities are the places where everything happens, from changing record
states to sending email.
Different kinds of activities exist: ``Dummy``, ``Function``, ``Subflow``, and
``Stop all``, each doing different things when the activity is processed. In
addition to their kind, activies have other properties, detailed in the next
sections.
Flow start and flow stop
''''''''''''''''''''''''
The attribute ``flow_start`` is a boolean value specifying whether the activity
is processed when the workflow is instanciated. Multiple activities can have
their attribute ``flow_start`` set to ``True``. When instanciating a workflow
for a record, OpenERP simply processes all of them, and evaluate all their
outgoing transitions afterwards.
The attribute ``flow_stop`` is a boolean value specifying whether the activity
stops the workflow instance. A workflow instance is considered completed when
all its activities with the attribute ``flow_stop`` set to ``True`` are
completed.
It is important for OpenERP to know when a workflow instance is completed. A
workflow can have an activity that is actually another workflow (called a
subflow); that activity is completed when the subflow is completed.
Subflow
'''''''
An activity can embed a complete workflow, called a subflow (the embedding
workflow is called the parent workflow). The workflow to instanciate is
specified by attribute ``subflow_id``.
.. note:: In the GUI, that attribute can not be set unless the kind of the
activity is ``Subflow``.
The activity is considered completed (and its outgoing transitions ready to be
evaluated) when the subflow is completed (see attribute ``flow_stop`` above).
Sending a signal from a subflow
'''''''''''''''''''''''''''''''
When a workflow is embedded in an activity (as a subflow) of a workflow, the
sublow can send a signal from its own activities to the parent workflow by
giving a signal name in the attribute ``signal_send``. OpenERP processes those
activities by sending the value of ``signal_send`` prefixed by "subflow." to
the parent workflow instance.
In other words, it is possible to react and get transitions in the parent
workflow as activities are executed in the sublow.
Server actions
''''''''''''''
An activity can run a "Server Action" by specifying its ID in the attribute
``action_id``.
Python action
'''''''''''''
An activity can execute some Python code, given by the attribute ``action``.
The evaluation environment is the same as the one explained in the section
`Conditions`_.
Split mode
''''''''''
After an activity has been processed, its outgoing transitions are evaluated.
Normally, if a transition can be taken, OpenERP traverses it and proceed to
the activity the transition leads to.
Actually, when more than a single transition is leaving an activity, OpenERP
may proceed or not, depending on the other transitions. That is, the
conditions on the transitions can be combined together, and the combined
result instructs OpenERP to traverse zero, one, or all the transitions. The
way they are combined is controlled by the attribute ``split_mode``.
There are three possible split modes: ``XOR``, ``OR`` and ``AND``.
``XOR``
When the transitions are combined with a ``XOR`` split mode, as soon as a
transition has a satisfied condition, the transition is traversed and the
others are skipped.
``OR``
With the ``OR`` mode, all the transitions with a satisfied condition are
traversed. The remaining transitions will not be evaluated later.
``AND``
With the ``AND`` mode, OpenERP will wait for all outgoing transition
conditions to be satisfied, then traverse all of them at once.
Join mode
'''''''''
Just like outgoing transition conditions can be combined together to decide
whether they can be traversed or not, incoming transitions can be combined
together to decide if and when an activity may be processed. The attribute
``join_mode`` controls that behavior.
There are two possible join modes: ``XOR`` and ``AND``.
``XOR``
With the ``XOR`` mode, an incoming transition with a satisfied condition
is traversed immediately, and enables the processing of the activity.
``AND``
With the ``AND`` mode, OpenERP will wait until all incoming transitions
have been traversed before enabling the processing of the activity.
Kinds
'''''
Activities can be of different kinds: ``dummy``, ``function``, ``subflow``, or
``stopall``. The kind defines what type of work an activity can do.
Dummy
The ``dummy`` kind is for activities that do nothing, or for activities
that only call a server action. Activities that do nothing can be used as
hubs to gather/dispatch transitions.
Function
The ``function`` kind is for activities that only need to run some Python
code, and possibly a server action.
Stop all
The ``stopall`` kind is for activities that will completely stop the
workflow instance and mark it as completed. In addition they can also run
some Python code.
Subflow
When the kind of the activity is ``subflow``, the activity embeds another
workflow instance. When the subflow is completed, the activity is also
considered completed.
By default, the subflow is instanciated for the same record as the parent
workflow. It is possible to change that behavior by providing Python code
that returns a record ID (of the same data model as the subflow). The
embedded subflow instance is then the one of the given record.