用途:帮助判断如何实现服务端 DocType 逻辑(若需精确语法另见 erpnext-syntax-controllers),兼容 v14/v15/v16。
核心决策:需要导入外部库、带回滚的多单据事务、完整 Python 能力(try/except、类、生成器)或覆写标准 DocType 时用 Controller;仅需快速验证、简单自动填充或计算且无自定义应用时用 Server Script。覆写标准 DocType 通过 hooks.py 的 override_doctype_class 实现。
钩子选择:保存前验证或计算字段用 validate(对 self 的改动会被保存);保存后动作(邮件、关联单据、日志)用 on_update(对 self 的改动不会被保存,需用 db_set);仅新单据用 after_insert;提交相关用 before_submit/on_submit;取消相关用 before_cancel/on_cancel;删除前用 on_trash;自定义命名用 autoname;检测任意变更(含 db_set)用 on_change。
可提交单据流程:草稿保存走 validate→on_update;提交走 validate→before_submit→写库 docstatus=1→on_update→on_submit;取消走 before_cancel→写库 docstatus=2→on_cancel→check_no_back_links。
控制器覆写有两种方式:完整覆写(override_doctype_class,子类中务必调用 super());更安全的是事件处理器 doc_events,将 validate 等映射到函数。v16 新增 extend_doctype_class,只声明需新增或覆写的方法。
flags 机制:可用 ignore_permissions、ignore_validate、ignore_mandatory,也可自定义 flags 在钩子间传递状态。
执行顺序:新建为 before_insert→before_naming→autoname→before_validate→validate→before_save→DB INSERT→after_insert→on_update→on_change;保存为 before_validate→validate→before_save→DB UPDATE→on_update→on_change;提交为 validate→before_submit→DB docstatus=1→on_update→on_submit→on_change。
限制与反模式:on_update 中直接 self.x=y 无效;钩子内调用 frappe.db.commit() 应交给框架;validate 中避免重操作,应在 on_update 用 frappe.enqueue();on_update 中调用 self.save() 会造成死循环;不要假设跨单据的钩子顺序。
资料来源另提供 decision-tree.md、workflows.md、examples.md、anti-patterns.md 等参考。未提供收费、价格与平台信息。