1 .. _reference/workflows:
6 In Odoo, a workflow is a technical artefact to manage a set of "things to
7 do" associated to the records of a model. The workflow provides a higher-level
8 way to organize tasks to perform with or on a record.
10 More specifically, a workflow is a directed graph where the nodes are called
11 "activities" and the arcs are called "transitions".
13 - Activities define work that should be done within the Odoo server, such
14 as changing the state of some records, or sending emails.
15 - Transitions control how the workflow progresses from activity to activity.
17 In the definition of a workflow, one can attach conditions, signals, and
18 triggers to transitions, so that the behavior of the workflow depends on user
19 actions (such as clicking on a button), changes to records, or arbitrary
22 All in all, Odoo's workflow system provides:
24 * a description of the evolution of a record (document) over time
25 * automatic actions based on various and flexible conditions
26 * management of company roles and validation steps
27 * management of interactions between objects
28 * a visual representation of document flows through their lifecycle
30 For instance, a basic order could have the following flow:
32 .. sphinx.ext.graphviz would be nice, but it requires ``dot`` on any machine
33 .. where the doc is compiled... otoh this is a pain in the ass because you
34 .. need 2 compilation steps (dot -> image and rst -> html) every time
36 .. image:: workflow/order_0.*
39 Orders start in the *Draft* state, can be *Confirmed* by a user, and then
40 either shipped (*Closed*) or *Canceled*.
42 A company using Odoo may want to add discount support to orders, where sales
43 staff has discretionary discounting powers up to 15%, but manager validation
44 is required for discounts beyond 15%. The workflow can be altered online to
45 add the relevant steps without editing Python or XML files:
47 .. image:: workflow/order_1.*
50 Because Activities can perform arbitrary actions, the *Validation* can
51 automatically send a validation request to the relevant employee.
53 .. note:: the order view needs to be modified to add an *Accept Discount*
59 Defining a workflow with data files is straightforward: a record "workflow" is
60 given together with records for the activities and the transitions. For
61 instance, here is a simple sequence of two activities defined in XML
65 <record id="test_workflow" model="workflow">
66 <field name="name">test.workflow</field>
67 <field name="osv">test.workflow.model</field>
68 <field name="on_create">True</field>
71 <record id="activity_a" model="workflow.activity">
72 <field name="wkf_id" ref="test_workflow"/>
73 <field name="flow_start">True</field>
74 <field name="name">a</field>
75 <field name="kind">function</field>
76 <field name="action">print_a()</field>
78 <record id="activity_b" model="workflow.activity">
79 <field name="wkf_id" ref="test_workflow"/>
80 <field name="flow_stop">True</field>
81 <field name="name">b</field>
82 <field name="kind">function</field>
83 <field name="action">print_b()</field>
86 <record id="trans_a_b" model="workflow.transition">
87 <field name="act_from" ref="activity_a"/>
88 <field name="act_to" ref="activity_b"/>
91 A worfklow is always defined with respect to a particular model (the model is
92 given by the attribute ``osv`` on the model ``workflow``). Methods specified
93 in the activities or transitions will be called on that model.
95 In the example code above, a workflow called "test_workflow" is created. It is
96 made up of two activies, named "a" and "b", and one transition, going from "a"
99 The first activity has its attribute ``flow_start`` set to ``True`` so that
100 Odoo knows where to start the workflow traversal after it is instanciated.
101 Because ``on_create`` is set to True on the workflow record, the workflow is
102 instanciated for each newly created record. (Otherwise, the workflow should be
103 instanciated by other means, such as from some module Python code.)
105 When the workflow is instanciated, it begins with activity "a". That activity
106 is of kind ``function``, which means that the action ``print_a()`` is a method
107 call on the model ``test.workflow`` (the usual ``cr, uid, ids, context``
108 arguments are passed for you).
110 The transition between "a" and "b" does not specify any condition. This means
111 that the workflow instance immediately goes from "a" to "b" after "a" has been
112 processed, and thus also processes activity "b".
117 While the transitions can be seen as the control structures of the workflows,
118 activities are the places where everything happens, from changing record
119 states to sending email.
121 Different kinds of activities exist: ``Dummy``, ``Function``, ``Subflow``, and
122 ``Stop all``, each doing different things when the activity is processed. In
123 addition to their kind, activies have other properties, detailed in the next
126 Flow start and flow stop
127 ''''''''''''''''''''''''
129 The attribute ``flow_start`` is a boolean value specifying whether the activity
130 is processed when the workflow is instanciated. Multiple activities can have
131 their attribute ``flow_start`` set to ``True``. When instanciating a workflow
132 for a record, Odoo simply processes all of them, and evaluate all their
133 outgoing transitions afterwards.
135 The attribute ``flow_stop`` is a boolean value specifying whether the activity
136 stops the workflow instance. A workflow instance is considered completed when
137 all its activities with the attribute ``flow_stop`` set to ``True`` are
140 It is important for Odoo to know when a workflow instance is completed. A
141 workflow can have an activity that is actually another workflow (called a
142 subflow); that activity is completed when the subflow is completed.
147 An activity can embed a complete workflow, called a subflow (the embedding
148 workflow is called the parent workflow). The workflow to instanciate is
149 specified by attribute ``subflow_id``.
151 .. note:: In the GUI, that attribute can not be set unless the kind of the
152 activity is ``Subflow``.
154 The activity is considered completed (and its outgoing transitions ready to be
155 evaluated) when the subflow is completed (see attribute ``flow_stop`` above).
157 Sending a signal from a subflow
158 '''''''''''''''''''''''''''''''
160 When a workflow is embedded in an activity (as a subflow) of a workflow, the
161 sublow can send a signal from its own activities to the parent workflow by
162 giving a signal name in the attribute ``signal_send``. Odoo processes those
163 activities by sending the value of ``signal_send`` prefixed by "subflow." to
164 the parent workflow instance.
166 In other words, it is possible to react and get transitions in the parent
167 workflow as activities are executed in the sublow.
172 An activity can run a "Server Action" by specifying its ID in the attribute
178 An activity can execute some Python code, given by the attribute ``action``.
179 The evaluation environment is the same as the one explained in the section
185 After an activity has been processed, Odoo evaluates its transition to reach
186 the next activity in the flow.
188 However if an activity has more than one transition, Odoo must decide which
189 activity or activities to follow.
191 .. image:: workflow/split.*
194 This choice is controlled by the ``split_mode`` attribute:
197 By default, Odoo will use the first transition (in ``sequence`` order)
198 whose condition is satisfied. All other transitions are ignored.
200 In ``OR`` mode, all transitions with a satisfied condition are traversed
201 simultanously. Transitions not yet valid will be ignored, even if they
204 In ``AND`` mode, Odoo will wait until *all* transitions are satisfied, and
205 will traverse all of them (much like the ``OR`` mode).
207 Both ``OR`` and ``AND`` mode will lead to activities being active in the same
213 Just like outgoing transition conditions can be combined together to decide
214 whether they can be traversed or not, incoming transitions can be combined
215 together to decide if and when an activity may be processed.
217 .. image:: workflow/join.*
220 The ``join_mode`` attribute controls that behavior:
223 Any incoming transition enables the activity and starts its processing.
225 The activity is enabled and processed only once *all* incoming transitions
231 An activity's kind defines the type of work an activity can perform.
233 Dummy (``dummy``, default)
234 Do nothing at all, or call a server action. Often used as dispatch or
235 gather "hubs" for transitions.
236 Function (``function``)
237 Run some python code, execute a server action.
238 Stop all (``stopall``)
239 Completely stops the workflow instance and marks it as completed.
240 Subflow (``subflow``)
241 Starts executing an other workflow, once that workflow is completed the
242 activity is done processing.
244 By default, the subflow is instanciated for the same record as the parent
245 workflow. It is possible to change that behavior by providing Python code
246 that returns a record ID (of the same data model as the subflow). The
247 embedded subflow instance is then the one of the given record.
253 Transitions provide the control structures to orchestrate a workflow. When an
254 activity is completed, the workflow engine tries to get across transitions
255 departing from the completed activity, towards the next activities. In their
256 simplest form (as in the example above), they link activities sequentially:
257 activities are processed as soon as the activities preceding them are
260 Instead of running all activities in one fell swoop, it is also possible to
261 wait on transitions, going through them only when some criteria are met. The
262 criteria are the conditions, the signals, and the triggers. They are detailed
263 in the following sections.
268 When an activity has been completed, its outgoing transitions are inspected to
269 determine whether it is possible for the workflow instance to proceed through
270 them and reach the next activities. When only a condition is defined (i.e., no
271 signal or trigger is defined), the condition is evaluated by Odoo, and if
272 it evaluates to ``True``, the worklfow instance progresses through the
273 transition. If the condition is not met, it will be reevaluated every time
274 the associated record is modified, or by an explicit method call to do it.
276 By default, the attribute ``condition`` (i.e., the expression to be evaluated)
277 is just "True", which trivially evaluates to ``True``. Note that the condition
278 may be several lines long; in that case, the value of the last one determines
279 whether the transition can be taken.
281 In the condition evaluation environment, several symbols are conveniently
282 defined (in addition to the Odoo ``safe_eval`` environment):
284 - all the model column names, and
285 - all the browse record's attributes.
290 In addition to a condition, a transition can specify a signal name. When such
291 a signal name is present, the transition is not taken directly, even if the
292 condition evaluates to ``True``. Instead the transition blocks, waiting to be
295 In order to wake up a transition with a defined signal name, the signal must
296 be sent to the workflow instance. A common way to send a signal is to use a
297 button in the user interface, using the element ``<button/>`` with the signal
298 name as the attribute ``name`` of the button. Once the button is clicked, the
299 signal is sent to the workflow instance of the current record.
301 .. note:: The condition is still evaluated when the signal is sent to the
307 With conditions that evaluate to ``False``, transitions are not taken (and
308 thus the activity it leads to is not processed immediately). Still, the
309 workflow instance can get new chances to progress across that transition by
310 providing so-called triggers. The idea is that when the condition is not
311 satisfied, triggers are recorded in database. Later, it is possible to wake up
312 specifically the workflow instances that installed those triggers, offering
313 them to reevaluate their transition conditions. This mechanism makes it
314 cheaper to wake up workflow instances by targetting just a few of them (those
315 that have installed the triggers) instead of all of them.
317 Triggers are recorded in database as record IDs (together with the model name)
318 and refer to the workflow instance waiting for those records. The transition
319 definition provides a model name (attribute ``trigger_model``) and a Python
320 expression (attribute ``trigger_expression``) that evaluates to a list of
321 record IDs in the given model. Any of those records can wake up the workflow
322 instance they are associated with.
324 .. note:: triggers are not re-installed whenever the transition is re-tried.