在Odoo中,工作流是管理与模型记录相关联的一组“要做的事情”的技术组件。 工作流提供了更高级别的方式来组织要在记录上执行的任务。
更具体地,工作流是有向图,其中节点被称为“活动”,并且弧被称为“转换”。
- 活动定义应在Odoo服务器内完成的工作,例如更改某些记录的状态或发送电子邮件。
- 转换控制工作流如何从活动到活动。
在工作流的定义中,可以向转换附加条件,信号和触发器,以便工作流的行为取决于用户操作(例如单击按钮), 更改记录或任意Python代码。
总而言之,Odoo的工作流系统提供:
- 记录(文档)随时间的演变的描述
- 基于各种灵活条件的自动操作
- 管理公司角色和验证步骤
- 管理对象之间的交互
- 通过其生命周期形成可视化的文档流表示
例如,基本订单可以具有以下流程:
订单以 Draft 状态开始,可以由用户 确认 ,然后发货( 关闭 )或 取消 。
使用Odoo的公司可能希望为订单添加折扣支持,其中销售人员可自由折扣高达15%的折扣, 但是需要管理员验证获得超过15%的折扣。 可以在线更改工作流以添加相关步骤, 而无需编辑Python或XML文件:
因为活动可以执行任意操作, 验证 可以自动发送验证请求到相关员工。
注解
需要为经理修改订单视图添加 接受折扣 按钮
Basics
使用数据文件定义工作流非常简单:记录“工作流”由活动和转换的记录一起提供。 例如,这里是在XML中定义的两个活动的简单序列
<record id="test_workflow" model="workflow">
<field name="name">test.workflow</field>
<field name="osv">test.workflow.model</field>
<field name="on_create">True</field>
</record>
<record id="activity_a" model="workflow.activity">
<field name="wkf_id" ref="test_workflow"/>
<field name="flow_start">True</field>
<field name="name">a</field>
<field name="kind">function</field>
<field name="action">print_a()</field>
</record>
<record id="activity_b" model="workflow.activity">
<field name="wkf_id" ref="test_workflow"/>
<field name="flow_stop">True</field>
<field name="name">b</field>
<field name="kind">function</field>
<field name="action">print_b()</field>
</record>
<record id="trans_a_b" model="workflow.transition">
<field name="act_from" ref="activity_a"/>
<field name="act_to" ref="activity_b"/>
<field name="signal">signal_goto_b</signal>
</record>
一个工作流总是相对于一个特定的模型定义的(该模型由模型“工作流”上的属性“osv”给出)。 将在该模型上调用在活动或转换中指定的方法。
在上面的示例代码中,创建了一个名为“test_workflow”的工作流。 它由两个名为“a”和“b”的活动 和一个从“a”到“b”的转换组成。
第一个活动的属性 flow_start
设置为 True
,以便Odoo在实例化后知道在哪里启动工作流遍历。
因为工作流记录上的 on_create
设置为True,所以为每个新创建的记录创建工作流。
(否则,工作流应该通过其他方式来实现,例如从某些模块Python代码)。
当工作流被实例化时,它从活动“a”开始。 那个活动是一个 function
,这意味着动作 print_a()
是一个对模型 test.workflow
(通常是 cr,uid,ids,
参数传递给你)。
“a”和“b”之间的转换指定信号,但不指定任何条件。这意味着当信号 signal_goto_b
被接收
并且因此处理活动“b”的动作 print_b()
时,工作流实例将立即从“a”转变到“b”。
活动
虽然转换可以看作是工作流的控制结构,但活动是从改变记录状态到发送电子邮件的一切地方都发生的。
存在不同类型的活动: Dummy
, Function
, Subflow
和 Stop all
,
每个在处理活动时做不同的事情。 除了他们的种类,活动有其他属性,详细在下面的部分。
流程启动和流程停止
属性 flow_start
是一个布尔值,指定当工作流被实例化时是否处理活动。
多个活动可以将其属性 flow_start
设置为“True”。 当为一个记录指定工作流时,
Odoo只是处理所有的记录,然后评估所有的转移输出。
属性 flow_stop
是一个布尔值,指定活动是否停止工作流实例。 当属性 flow_stop
设置为“True”的所有活动都完成时,工作流实例被认为已完成。
Odoo知道工作流实例何时完成很重要。 工作流可以实际上是另一工作流(称为子流)的活动; 当子流完成时该活动完成。
子流
活动可以嵌入一个称为子流的完整工作流(嵌入工作流称为父工作流)。
实例化的工作流由属性 subflow_id
指定。
注解
在GUI中,除非活动的类型是 Subflow
,否则不能设置该属性。
当子流完成时,活动被认为已完成(并且其传出转换准备好被评估)(见上面的属性 flow_stop
)。
从子流发送信号
当工作流嵌入工作流的活动(作为子流)时,子流可以通过在属性 signal_send
中给出信号名称,
从其自己的活动向父工作流发送信号。 Odoo通过发送以 "subflow" 为前缀的 signal_send
的值来处理这些活动到父工作流实例。
换句话说,当在子流中执行活动时,可以在父工作流中进行反应和获得转换。
Server actions
活动可以通过在属性 action_id
中指定其ID来运行“server action”。
Python action
活动可以执行一些Python代码,由属性“action”给出。 评估环境与 条件 一节中是相同的说明。
Split mode
处理活动后,Odoo评估其转换以到达流中的下一个活动。
然而,如果一个活动有多个转换,Odoo必须决定要跟踪哪个或哪些活动。
这个选择由 split_mode
属性控制:
XOR
(默认)- 默认情况下,Odoo将使用满足条件的第一个转换(按
sequence
顺序)。 所有其他转换将被忽略。 OR
- 在“OR”模式下,满足条件的所有转换都会同时遍历。 尚未生效的转换将被忽略,即使它们以后有效。
AND
- 在
AND
模式下,Odoo将等待直到 所有 转换满足,并且将遍历所有这些(很像OR
模式)。
OR
和 AND
模式都将导致活动在同一个活动工作流。
Join mode
就像输出转换条件可以组合在一起以决定它们是否可以遍历,输入转换可以组合在一起以决定是否和何时可以处理活动。
join_mode
属性控制该行为:
XOR
(默认)- 任何传入转换启用活动并开始其处理。
AND
- 仅在遍历 所有 传入转换后才启用和处理该活动。
种类
活动的种类定义活动可以执行的工作类型。
- Dummy (
dummy
, default) - 根本不做任何事情,或调用server action。 通常用作调度或收集“hubs”用于过渡。
- Function (
function
) - 运行一些python代码,执行server action。
- Stop all (
stopall
) - 完全停止工作流实例并将其标记为已完成。
- Subflow (
subflow
) 开始执行其他工作流,一旦工作流完成,活动完成处理。
默认情况下,子流是为与父工作流相同的记录实例化的。 可以通过提供返回记录ID(与子流相同的数据模型) 的Python代码来更改该行为。 嵌入式子流实例是给定记录之一。
翻译
转换提供了控制结构来编排工作流。 当活动完成时,工作流引擎尝试跨越从完成的活动到下一活动的转移。 在它们最简单的形式(如上例)中,它们按顺序链接活动:活动在其前面的活动完成后立即被处理。
而不是一次性运行所有活动,也可以等待转换,只有当满足一些标准时通过它们。 标准是条件,信号和触发器。 它们将在以下部分中详细介绍。
条件
当活动已完成时,检查其传出转换以确定工作流实例是否可能通过它们继续并到达下一个活动。 当只定义一个条件(即没有定义信号或触发器)时,条件由Odoo计算,如果计算结果为“True”, worklfow实例将通过转换进行。 如果条件不满足,它将在每次修改相关联的记录时重新评估, 或通过显式方法调用来重新评估。
默认情况下,属性 condition
(即被求值的表达式)只是“True”,简单地计算为 True
。
注意,条件可以是几行长; 在这种情况下,最后一个的值确定是否可以进行转换。
在条件评估环境中,方便地定义了几个符号(除了Odoo safe_eval
环境):
- 所有模型列名称和
- 所有浏览记录的属性。
信号
除了条件之外,转换可以指定信号名称。 当存在这样的信号名时,即使条件的计算结果为“True”,也不会直接进行转换。 相反,转换阻止,等待被唤醒。
为了唤醒具有定义的信号名称的转换,必须将信号发送到工作流实例。 发送信号的一种常见方法是在用户界面中使用按钮,
使用元素 <button />
,信号名称作为属性 name
。 一旦该按钮被点击,该信号被发送到当前记录的工作流实例。
注解
当信号发送到工作流实例时,仍会评估条件。
触发器
对于判断为 False
的条件,不会执行转换(因此不会立即处理它所导致的活动)。
尽管如此,工作流实例可以通过提供所谓的触发器来获得跨越该转换的新机会。
这个想法是,当条件不满足时,触发器被记录在数据库中。 稍后,可以特别唤醒安装了这些触发器的工作流实例,
让它们重新评估其转换条件。 此机制通过仅定位其中几个(安装了触发器的那些)
而不是所有这些触发器来唤醒工作流实例成本更低。
触发器作为记录ID(与模型名称一起)记录在数据库中,并引用等待这些记录的工作流实例。
转换定义提供了一个模型名称(属性 trigger_model
)和一个Python表达式(属性 trigger_expression
),
它在给定模型中的记录ID列表。 任何这些记录都可以唤醒与其相关联的工作流实例。
注解
每当重新尝试转换时,不会重新安装触发器。