用途:指导如何在 Frappe/ERPNext 中构建与组织自定义应用,解决“该不该建自定义应用、如何扩展、用 patch 还是 fixture、模块怎么划分”等实施决策。语法细节另见 erpnext-syntax-customapp。兼容 v14/v15/v16,差异有标注。
主要决策:1) 是否需要自定义应用——仅加字段用 Custom Field + Property Setter,简单自动化用 Server/Client Script,复杂逻辑、新 DocType、Python 代码或外部集成才建应用。原则是先选最简单方案,Server Script 加 Custom Field 可解决约七成定制需求。2) 扩展策略——加字段用 Custom Field、改行为用 Property Setter,改 DocType 逻辑 v16 优先 extend_doctype_class,v14/v15 用 doc_events,覆盖模板用 jinja.override_template,新增关联 DocType、Workspace 菜单等。3) patch 与 fixture 选择——全局一致的配置(自定义字段、角色、工作流、属性设置)用 fixture,一次性数据转换用 patch,需在架构变更前执行用 [pre_model_sync],之后用 [post_model_sync],主数据/查找表初始用 fixture、更新用 patch。4) 模块组织——小应用单模块,中型 2-4 个按功能划分,大型按业务域划分,多租户可拆成多个应用;每个 DocType 只属于一个模块。
工作流:新建应用执行 bench new-app my_app,配置 pyproject.toml(v15+)或 setup.py(v14),编辑 modules.txt,执行 bench --site mysite new-doctype MyDocType,编写控制器,配置 hooks,执行 bench --site mysite export-fixtures,再 bench --site testsite install-app my_app 测试。patch 流程为写 myapp/patches/v1_0/description.py 并登记 patches.txt,用 bench --site testsite migrate 验证。fixture 流程为在 hooks.py 定义 fixtures 列表与过滤条件,UI 修改后执行 bench --site mysite export-fixtures --app my_app,提交版本控制。
版本差异:v14 用 setup.py、doc_events、Python 3.10;v15 用 pyproject.toml、doc_events、Python 3.10;v16 用 pyproject.toml、优先 extend_doctype_class、Python 3.11,并引入数据脱敏、UUID 命名等变化。
限制与要点:不要在依赖中放 frappe/erpnext;fixtures 只放配置不放事务数据;不硬编码站点特定值;大 patch 用批处理并 frappe.db.commit();删字段前先备份;不改核心文件。参考资料含 decision-tree.md、workflows.md、examples.md、anti-patterns.md。