[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.
|
@ -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 $< > $@
|
|
@ -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
|
||||
}
|
After Width: | Height: | Size: 6.7 KiB |
|
@ -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->Activity -->
|
||||
<g id="edge1" class="edge"><title>a->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->Activity -->
|
||||
<g id="edge2" class="edge"><title>b->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->Activity -->
|
||||
<g id="edge3" class="edge"><title>c->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 |
|
@ -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
|
||||
}
|
After Width: | Height: | Size: 17 KiB |
|
@ -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->Confirmed -->
|
||||
<g id="edge1" class="edge"><title>Draft->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->Closed -->
|
||||
<g id="edge2" class="edge"><title>Confirmed->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->Canceled -->
|
||||
<g id="edge3" class="edge"><title>Confirmed->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 |
|
@ -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
|
||||
}
|
After Width: | Height: | Size: 28 KiB |
|
@ -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->Confirmed -->
|
||||
<g id="edge1" class="edge"><title>Draft->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 <= 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->Validation -->
|
||||
<g id="edge2" class="edge"><title>Draft->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 > 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->Closed -->
|
||||
<g id="edge4" class="edge"><title>Confirmed->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->Canceled -->
|
||||
<g id="edge5" class="edge"><title>Confirmed->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->Confirmed -->
|
||||
<g id="edge3" class="edge"><title>Validation->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 |
|
@ -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
|
||||
}
|
After Width: | Height: | Size: 6.8 KiB |
|
@ -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->a -->
|
||||
<g id="edge1" class="edge"><title>Activity->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->b -->
|
||||
<g id="edge2" class="edge"><title>Activity->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->c -->
|
||||
<g id="edge3" class="edge"><title>Activity->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 |
|
@ -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.
|
||||
|
|