自动化流程中的操作表按从上到下的顺序列出了每次运行所执行的步骤。每一行都有一个步骤类型,对于操作步骤,还有一个操作类型及其参数。
步骤类型
| 步骤类型 | 作用 |
|---|---|
| 操作 | 执行一个操作,例如设置字段或发送邮件 |
| 等待 | 将运行暂停一段固定时间,然后继续执行下一步 |
| 等待事件 | 将运行暂停,直到某个应用发出匹配的事件,或超时 |
| 条件判断 | 评估一个条件,只运行匹配分支中的步骤 |
等待
将参数设置为一个时长:
{"value": 2, "unit": "Days"}
unit 是 Seconds、Minutes、Hours 或 Days 之一。暂停期间,运行显示为等待中。恢复时,文档会重新加载,因此后续步骤能看到等待期间所做的任何更改。
等待事件
暂停直到某个应用发出带有匹配关联键的事件:
{
"event_name": "crm.email_replied",
"correlation_key": "{{ doc.name }}",
"timeout_value": 3,
"timeout_unit": "Days"
}
关联键在到达该步骤时渲染,当应用以相同的事件和键调用 emit() 时,运行会恢复。如果超时先到,运行也会恢复。等待之后的步骤可以从 context.event 读取它是如何结束的:outcome 是 Matched 或 Timed Out,而 payload 保存事件的数据。
一个典型用例:只有在客户未回复时才发送跟进,方法是在等待之后添加一个条件判断步骤,条件为 context["event"]["outcome"] == "Timed Out"。
条件判断
条件判断步骤需要一个步骤条件。属于它的步骤要将父步骤设置为该条件判断行的编号,并将分支设置为 If(条件为真时运行)或 Else(条件为假时运行)。没有父步骤的步骤始终运行。
| # | 步骤类型 | 操作 | 父步骤 | 分支 |
|---|---|---|---|---|
| 1 | 条件判断 | 条件 doc.grand_total > 10000 | ||
| 2 | 操作 | 分配给用户:manager@example.com |
1 | 条件为真 |
| 3 | 操作 | 分配给用户:sales@example.com |
1 | 条件为假 |
| 4 | 操作 | 发送通知 |
条件判断步骤可以嵌套。分支在运行首次到达条件判断步骤时决定一次,之后在等待之后不会重新评估。
步骤条件
任何步骤都可以有一个步骤条件,这是一个 Python 表达式,必须为真该步骤才会运行。否则该步骤会被记录为已跳过,运行继续。该表达式可以读取:
doc:触发运行的文档target:该步骤所操作的记录context:运行的状态,包括context["steps"],即按步骤键索引的先前步骤的输出
操作
这些是作为核心框架操作提供的操作。其他应用可以通过 hooks.py 扩展这些操作,参见扩展自动化。
| 操作类型 | 作用 | 关键参数 |
|---|---|---|
| 设置字段值 | 在目标上设置一个或多个字段并保存 | field + value,或作为映射的 values |
| 递增字段值 | 向数值字段加一个数 | field、amount(负数表示减去) |
| 创建文档 | 插入任意类型的新文档 | doctype、values |
| 发送通知 | 发送邮件或系统通知 | channel(Email 或 System)、recipients、subject 和 message,或 email_template |
| 分配给用户 | 将目标分配给一个或多个用户 | assign_to、description |
| 调用 Webhook | 发送 HTTP 请求 | url、method、headers、payload、timeout |
| 运行脚本 | 运行 Python 代码 | server_script(一个 API 服务器脚本),或内联 script |
示例
一次设置两个字段:
{"values": {"status": "Replied", "priority": "High"}}
创建一个跟进待办事项:
{
"doctype": "ToDo",
"values": {
"description": "Call {{ doc.lead_name }}",
"reference_type": "{{ doc.doctype }}",
"reference_name": "{{ doc.name }}",
"allocated_to": "{{ doc.lead_owner }}"
}
}
给文档所有者和被分配人发送邮件:
{
"channel": "Email",
"recipients": ["@owner", "@assignees", "team@example.com"],
"subject": "{{ doc.name }} was closed",
"message": "
<p>{{ doc.name }} was closed on {{ frappe.utils.nowdate() }}.</p>"
}
@owner 和 @assignees 在步骤运行时针对文档解析。它们读取的是运行开始时(或最后一次等待之后)加载的文档,因此同一次运行中先前步骤所做的分配还不会包含在内。
模板
文本参数接受 Jinja。可用变量:
doc/target:该步骤所操作的记录trigger:启动本次运行的文档payload:来自自定义事件或计划任务的数据context:本次运行的状态,包括用于存放前面步骤输出的context.steps.<step_key></step_key>
对其他记录执行操作
默认情况下,步骤作用于触发文档。若要对关联记录执行操作,请在 Relationships 下声明一个命名别名,并将步骤的 Target 设置为该别名:
[{"alias": "customer", "relationship": "customer"}]
Link、Dynamic Link 和子表链接字段会自动以其字段名提供。反向链接命名为 <doctype>_via_<field></field></doctype>,例如 crm_deal_via_lead。应用可以注册更多(参见 Extending Automations)。
Create Document 步骤还可以设置 Output Alias。之后的步骤便可以以它创建的文档为目标。
错误处理
- Stop on Error(默认开启):第一个失败的步骤会停止本次运行,运行被标记为 Failed。关闭它可继续执行;此时运行被标记为 Partially Failed。
- 每个步骤都在自己的保存点内运行,因此失败步骤的数据库更改会被回滚,而不会撤销之前的步骤。
- Call Webhook 和 Run Script 可以访问数据库外部。一旦其中之一运行过,本次运行就绝不会从头重放,因此 webhook 不会被发送两次。
- Call Webhook 会拒绝私有和内部网络地址,并且最多跟随五次重定向。响应状态为 400 或以上会导致该步骤失败。
- Run Script 需要启用 Server Scripts(
bench set-config -g server_script_enabled 1),并且只有 System Manager 才能编写内联脚本。脚本可以读取doc、target、trigger、payload和context,并可以在result上设置键,以将输出发布给后续步骤。它不能调用frappe.db.commit()。
测试运行
在已保存的流程上点击 Test Run,然后选择一个文档。流程会针对它真实运行,随后 所有更改都会被回滚。结果会列出每个步骤的状态、消息以及它读取到的条件值。
在测试运行期间,Wait 步骤会被模拟,Call Webhook 会报告它将会发送的请求,但不会实际发送。