关于 frappe-core-workflow
面向 Frappe 开发者的工作流引擎参考指南,说明如何用状态、转换和角色权限管理文档生命周期,并涵盖条件判断、审批及文档状态规则。
主要功能
- 01按状态与角色控制转换
- 02按条件筛选可用操作
- 03配置状态字段更新与邮件通知
- 04管理审批及自我审批规则
- 05说明文档状态转换限制
- 06列出常见工作流错误
适用场景
- 01为 DocType 配置审批流程
- 02按角色限制文档操作
- 03依据文档字段设置条件转换
- 04排查状态或权限转换错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ impertio-studio/ frappe_claude_skill_package --skill frappe-core-workflow安装后在 Claude Code 中输入/frappe-core-workflow确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/.gitkeepanti-patterns.mdapi-reference.mdexamples.md详细介绍
工作流引擎
Frappe 工作流引擎是一种状态机,通过可配置的状态、转换和基于角色的权限来控制文档生命周期。它决定文档何时以及如何更改状态、谁可以执行操作,以及每次转换会产生哪些副作用。
快速参考
Workflow DocType → Defines the state machine for a specific DocType
├── states (child table) → Workflow Document State rows
│ ├── state → Link to Workflow State
│ ├── doc_status → 0 (Draft), 1 (Submitted), 2 (Cancelled)
│ ├── allow_edit → Role that can edit in this state
│ ├── update_field → Field to update when entering state
│ ├── update_value → Value to set (literal or expression)
│ └── next_action_email_template → Email Template link
└── transitions (child table) → Workflow Transition rows
├── state → Source state (Link to Workflow State)
├── action → Link to Workflow Action Master
├── next_state → Target state (Link to Workflow State)
├── allowed → Role that can perform this action
├── allow_self_approval → Check (default: 1)
├── condition → Python expression (optional)
└── transition_tasks → Link to Workflow Transition Tasks
Workflow DocType 的关键字段
| 字段 | 类型 | 用途 |
|---|---|---|
workflow_name | Data | 唯一标识符 |
document_type | Link → DocType | 目标 DocType |
is_active | Check | 每个 DocType 只能有一个工作流处于启用状态 |
workflow_state_field | Data | 默认值:workflow_state |
override_status | Check | 防止工作流覆盖列表视图状态 |
send_email_alert | Check | 发送包含下一步可用操作的电子邮件通知 |
引擎的工作方式
1. 激活和字段创建
当保存的 Workflow 满足 is_active = 1 时:
- 同一 DocType 的所有其他工作流都会自动停用
- 如果目标 DocType 上不存在隐藏的自定义字段(
workflow_state_field,默认值为workflow_state),则会创建该字段 - 字段类型为指向
Workflow State的Link,并设置hidden=1、allow_on_submit=1、no_copy=1 - 工作流状态为空的现有文档会根据其当前
docstatus设置状态
2. 状态解析
工作流中的每个文档都有一个 workflow_state 字段。引擎通过以下方式解析可用转换:
- 从文档读取当前的
workflow_state - 筛选
workflow.transitions中满足transition.state == current_state的项 - 根据用户角色筛选:
transition.allowed in frappe.get_roles() - 使用
frappe.safe_eval()计算transition.condition(如果已设置) - 将匹配的转换作为可用操作返回
3. 应用转换
调用 apply_workflow(doc, action) 时:
- 从数据库加载文档(重新读取最新数据)
- 获取当前用户可用的转换
- 查找与请求的
action匹配的转换 - 检查自行审批:当
allow_self_approval=0且用户是文档所有者时,阻止操作 - 将
workflow_state_field设置为transition.next_state - 如果目标状态设置了
update_field,则更新该字段 - 执行转换任务(先同步执行,再通过
frappe.enqueue异步执行) - 根据源状态和目标状态的
doc_status值处理 docstatus 变更 - 相应地保存、提交或取消文档
- 添加工作流评论
工作流与 DocStatus 的交互
重要:工作流引擎负责控制 docstatus 转换。对于由工作流控制的文档,绝不能直接调用 doc.submit() 或 doc.cancel()。这些操作由工作流执行。
DocStatus 转换规则
| 源 doc_status | 目标 doc_status | 引擎操作 | 有效? |
|---|---|---|---|
| 0(草稿) | 0(草稿) | doc.save() | 是 |
| 0(草稿) | 1(已提交) | doc.submit() | 是 |
| 1(已提交) | 1(已提交) | doc.save() | 是 |
| 1(已提交) | 2(已取消) | doc.cancel() | 是 |
| 2(已取消) | 任意 | 阻止 | 否 |
| 1(已提交) | 0(草稿) | 阻止 | 否 |
| 0(草稿) | 2(已取消) | 阻止 | 否 |
始终将状态定义为 docstatus 只能向前推进:0→0、0→1、1→1、1→2。
绝不要创建从已取消状态发起的转换,也不要创建从已提交状态退回草稿状态的转换。
不可提交的 DocType
如果目标 DocType 不可提交,则所有状态的 doc_status 必须为 0。引擎会验证这一点;如果不可提交的 DocType 有任何状态的 doc_status 为 1 或 2,则会抛出错误。
工作流状态
Workflow State 是一个独立的 DocType,用作主列表。每个状态包含:
| 字段 | 用途 |
|---|---|
state | 状态的显示名称 |
style | 徽章显示所用的 CSS 类(Primary、Success、Warning、Danger、Info、Inverse) |
icon | Font Awesome 图标类 |
状态行字段(工作流文档状态)
| 字段 | 用途 |
|---|---|
state | 链接到工作流状态 |
doc_status | 选择:0、1 或 2 |
allow_edit | 链接到角色——只有此角色可以在此状态下编辑文档 |
update_field | 文档进入此状态时要更新的字段 |
update_value | 要设置的值(字符串;如果 evaluate_as_expression=1,则为 Python 表达式) |
is_optional_state | 勾选——在 get_next_possible_transitions 中跳过可选状态 |
send_email | 勾选(默认值为 1)——进入此状态时发送电子邮件通知 |
next_action_email_template | 链接到电子邮件模板 |
message | 电子邮件通知的文本消息 |
工作流转换
每一行转换定义一个可能的操作:
| 字段 | 用途 |
|---|---|
state | 源状态(必须存在于状态表中) |
action | 链接到工作流操作主表(例如,“批准”、“拒绝”、“审核”) |
next_state | 目标状态(必须存在于状态表中) |
allowed | 链接到角色——只有具有此角色的用户才能看到此操作 |
allow_self_approval | 勾选(默认值为 1)——如果为 0,文档所有者不能执行此操作 |
condition | 使用 frappe.safe_eval() 求值的 Python 表达式 |
transition_tasks | 链接到工作流转换任务(v15+) |
条件表达式
条件是在沙盒环境中求值的 Python 表达式。可用的全局变量:
# Available in condition expressions:
frappe.db.get_value(doctype, name, fieldname)
frappe.db.get_list(doctype, filters, fields)
frappe.session.user
frappe.session.roles # NOT available — use frappe.get_roles() outside conditions
frappe.utils.now_datetime()
frappe.utils.add_to_date(date, **kwargs)
frappe.utils.get_datetime(datetime_str)
frappe.utils.now()
doc.fieldname # Access any field on the document (as dict)
条件示例:
doc.grand_total > 50000
doc.department == "HR"
doc.grand_total > 50000 and doc.department != "Finance"
工作流操作
工作流操作主表
简单的 DocType,仅包含 workflow_action_name 字段。常见操作:批准、拒绝、审核、退回、取消。定义转换前,请先创建这些操作。
工作流操作 DocType
跟踪用户待处理的操作。文档进入具有后续转换的状态时会自动创建。
| 字段 | 用途 |
|---|---|
status | 开放或已完成 |
reference_doctype | 文档的 DocType |
reference_name | 文档名称 |
workflow_state | 当前工作流状态 |
user | 被分配的用户 |
permitted_roles | 可执行操作的角色的表格多选字段 |
completed_by | 完成操作的用户 |
completed_by_role | 用于完成操作的角色 |
工作流操作会显示在用户的“工作流操作”列表中,也可以通过电子邮件链接执行。
自我审批控制
def has_approval_access(user, doc, transition):
return (user == "Administrator"
or transition.get("allow_self_approval")
or user != doc.get("owner"))
- 管理员始终拥有审批权限,不受设置影响
- 如果
allow_self_approval = 1(默认值):文档所有者可以审批 - 如果
allow_self_approval = 0:文档所有者不能审批自己的文档
决策树
Need workflow on a DocType?
├── Is DocType submittable?
│ ├── YES → States can use doc_status 0, 1, 2
│ └── NO → ALL states MUST have doc_status = 0
├── Define states → Create Workflow State records first
├── Define transitions → Need Workflow Action Master records first
├── Who can edit in each state? → Set allow_edit per state
├── Need conditional transitions?
│ └── Use Python expressions with doc.field access
├── Need to block self-approval?
│ └── Set allow_self_approval = 0 on specific transitions
└── Need email notifications?
└── Set send_email_alert on Workflow + email templates on states
常见错误
| 错误 | 原因 | 修复方法 |
|---|---|---|
WorkflowStateError | 文档未设置 workflow_state | 确保工作流在创建时设置初始状态 |
WorkflowTransitionError | 当前状态或角色下操作无效 | 验证转换表涵盖所有所需路径 |
WorkflowPermissionError | 用户缺少执行转换所需的角色,或自我审批被阻止 | 检查 allowed 角色和 allow_self_approval |
| “非法文档状态” | docstatus 转换无效(例如,0→2) | 修正状态的 doc_status 值 |
| “提交前无法取消” | 从草稿(0)转换到已取消(2) | 添加中间的已提交(1)状态 |