erpnext-impl-customapp
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseERPNext Custom App - Implementation
ERPNext自定义应用 - 实施指南
This skill helps you determine HOW to build and structure Frappe/ERPNext custom apps. For exact syntax, see .
erpnext-syntax-customappVersion: v14/v15/v16 compatible (differences noted)
本技能将帮助你确定如何构建和规划Frappe/ERPNext自定义应用的结构。如需具体语法参考,请查看。
erpnext-syntax-customapp版本:兼容v14/v15/v16版本(版本差异已标注)
Main Decision: What Are You Building?
核心决策:你要构建什么?
┌─────────────────────────────────────────────────────────────────────────┐
│ WHAT DO YOU WANT TO CREATE? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ► Completely new Frappe/ERPNext app? │
│ └─► See: NEW APP WORKFLOW │
│ │
│ ► Extend existing ERPNext functionality? │
│ └─► See: EXTENSION DECISION │
│ │
│ ► Migrate data between fields/DocTypes? │
│ └─► See: PATCH vs FIXTURE DECISION │
│ │
│ ► Export configuration for deployment? │
│ └─► See: FIXTURE WORKFLOW │
│ │
│ ► Update existing app to newer Frappe version? │
│ └─► See: VERSION UPGRADE WORKFLOW │
│ │
└─────────────────────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────────────────────┐
│ 你想要创建什么? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ► 全新的Frappe/ERPNext应用? │
│ └─► 参考:新应用工作流 │
│ │
│ ► 扩展现有ERPNext功能? │
│ └─► 参考:扩展方案决策 │
│ │
│ ► 在不同字段/DocType之间迁移数据? │
│ └─► 参考:补丁与Fixture决策 │
│ │
│ ► 导出配置用于部署? │
│ └─► 参考:Fixture工作流 │
│ │
│ ► 将现有应用升级到更高版本的Frappe? │
│ └─► 参考:版本升级工作流 │
│ │
└─────────────────────────────────────────────────────────────────────────┘Decision 1: Do You Need a Custom App?
决策1:你是否需要自定义应用?
┌─────────────────────────────────────────────────────────────────────────┐
│ DO YOU ACTUALLY NEED A CUSTOM APP? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ What changes do you need? │
│ │
│ ► Add fields to existing DocType? │
│ └─► NO APP NEEDED: Use Custom Field + Property Setter │
│ (Can be exported as fixtures from ANY app) │
│ │
│ ► Simple automation/validation? │
│ └─► NO APP NEEDED: Server Script or Client Script │
│ (Stored in database, no deployment needed) │
│ │
│ ► Complex business logic, new DocTypes, or Python code? │
│ └─► YES, CREATE APP: You need controllers, models, and deployment │
│ │
│ ► Integration with external system? │
│ └─► USUALLY YES: APIs need whitelisted methods, scheduled sync │
│ │
│ ► Custom reports with complex queries? │
│ └─► DEPENDS: Script Report (no app) vs Query Report (app optional) │
│ │
└─────────────────────────────────────────────────────────────────────────┘Rule: Start with the SIMPLEST solution. Server Scripts + Custom Fields solve 70% of customization needs without a custom app.
┌─────────────────────────────────────────────────────────────────────────┐
│ 你真的需要自定义应用吗? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 你需要进行哪些更改? │
│ │
│ ► 为现有DocType添加字段? │
│ └─► 无需应用:使用Custom Field + Property Setter │
│ (可从任意应用导出为fixtures) │
│ │
│ ► 简单的自动化/验证? │
│ └─► 无需应用:使用Server Script或Client Script │
│ (存储在数据库中,无需部署) │
│ │
│ ► 复杂业务逻辑、新DocType或Python代码? │
│ └─► 需要创建应用:你需要控制器、模型和部署流程 │
│ │
│ ► 与外部系统集成? │
│ └─► 通常需要:API需要白名单方法、定时同步 │
│ │
│ ► 包含复杂查询的自定义报表? │
│ └─► 视情况而定:Script Report(无需应用) vs Query Report(可选应用) │
│ │
└─────────────────────────────────────────────────────────────────────────┘原则:从最简单的解决方案入手。Server Script和Custom Fields无需自定义应用即可解决70%的定制需求。
Decision 2: Extension Strategy
决策2:扩展策略
┌─────────────────────────────────────────────────────────────────────────┐
│ HOW TO EXTEND ERPNext? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ► Add fields to existing DocType (e.g., Sales Invoice)? │
│ └─► Custom Field (via UI or fixtures) │
│ └─► Property Setter for behavior changes │
│ │
│ ► Modify DocType behavior/logic? │
│ ├─► v16: Use `extend_doctype_class` hook (PREFERRED) │
│ └─► v14/v15: Use `doc_events` hooks in hooks.py │
│ │
│ ► Override Jinja template? │
│ └─► Copy template to your app's templates/ folder │
│ └─► Register via `jinja.override_template` in hooks.py │
│ │
│ ► Add new DocType related to existing? │
│ └─► Create in your app's module │
│ └─► Link via Link field or Dynamic Link │
│ │
│ ► Add new workspace/menu items? │
│ └─► Create Workspace DocType in your app │
│ └─► Or use `standard_portal_menu_items` hook │
│ │
└─────────────────────────────────────────────────────────────────────────┘See:for detailed extension patterns.references/decision-tree.md
┌─────────────────────────────────────────────────────────────────────────┐
│ 如何扩展ERPNext? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ► 为现有DocType添加字段(如销售发票)? │
│ └─► Custom Field(通过UI或fixtures) │
│ └─► 使用Property Setter修改行为 │
│ │
│ ► 修改DocType的行为/逻辑? │
│ ├─► v16:使用`extend_doctype_class`钩子(推荐) │
│ └─► v14/v15:在hooks.py中使用`doc_events`钩子 │
│ │
│ ► 覆盖Jinja模板? │
│ └─► 将模板复制到你的应用templates/目录中 │
│ └─► 在hooks.py中通过`jinja.override_template`注册 │
│ │
│ ► 创建与现有功能关联的新DocType? │
│ └─► 在你的应用模块中创建 │
│ └─► 通过Link字段或Dynamic Link关联 │
│ │
│ ► 添加新的工作区/菜单项? │
│ └─► 在你的应用中创建Workspace DocType │
│ └─► 或使用`standard_portal_menu_items`钩子 │
│ │
└─────────────────────────────────────────────────────────────────────────┘参考:包含详细的扩展模式。references/decision-tree.md
Decision 3: Patch vs Fixture
决策3:补丁 vs Fixture
┌─────────────────────────────────────────────────────────────────────────┐
│ SHOULD THIS BE A PATCH OR A FIXTURE? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Is it CONFIGURATION that should be the same everywhere? │
│ (Custom Fields, Roles, Workflows, Property Setters) │
│ └─► USE FIXTURE │
│ │
│ Is it a ONE-TIME data transformation? │
│ (Migrate old field values, cleanup bad data, populate defaults) │
│ └─► USE PATCH │
│ │
│ Does it need to run BEFORE schema changes? │
│ (Backup data from field that will be deleted) │
│ └─► USE PATCH with [pre_model_sync] │
│ │
│ Does it need to run AFTER schema changes? │
│ (Populate newly added field with calculated values) │
│ └─► USE PATCH with [post_model_sync] │
│ │
│ Is it master data / lookup tables? │
│ (Categories, Status options, Configuration records) │
│ └─► USE FIXTURE for initial, PATCH for updates │
│ │
└─────────────────────────────────────────────────────────────────────────┘See:for patch timing flowchart.references/decision-tree.md
┌─────────────────────────────────────────────────────────────────────────┐
│ 应该使用补丁还是Fixture? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 是否是需要在所有环境中保持一致的配置? │
│ (Custom Fields、角色、工作流、Property Setters) │
│ └─► 使用Fixture │
│ │
│ 是否是一次性的数据转换? │
│ (迁移旧字段值、清理无效数据、填充默认值) │
│ └─► 使用补丁 │
│ │
│ 是否需要在架构变更前运行? │
│ (备份即将被删除的字段中的数据) │
│ └─► 使用带有[pre_model_sync]的补丁 │
│ │
│ 是否需要在架构变更后运行? │
│ (用计算值填充新增字段) │
│ └─► 使用带有[post_model_sync]的补丁 │
│ │
│ 是否是主数据/查找表? │
│ (分类、状态选项、配置记录) │
│ └─► 初始设置使用Fixture,更新时使用补丁 │
│ │
└─────────────────────────────────────────────────────────────────────────┘参考:包含补丁时机流程图。references/decision-tree.md
Decision 4: Module Organization
决策4:模块组织
┌─────────────────────────────────────────────────────────────────────────┐
│ HOW MANY MODULES DO YOU NEED? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Small app (1-5 DocTypes, single purpose)? │
│ └─► ONE MODULE with app name │
│ Example: my_app/my_app/ (module "My App") │
│ │
│ Medium app (6-15 DocTypes, multiple areas)? │
│ └─► 2-4 MODULES by functional area │
│ Example: core/, settings/, integrations/ │
│ │
│ Large app (15+ DocTypes, complex domain)? │
│ └─► MODULES by business domain │
│ Example: inventory/, sales/, purchasing/, settings/ │
│ │
│ Multi-tenant or vertical solution? │
│ └─► Consider MULTIPLE APPS instead │
│ Base app + vertical-specific apps │
│ │
└─────────────────────────────────────────────────────────────────────────┘Rule: Each DocType belongs to EXACTLY one module. Choose module = where would a user look for this DocType?
┌─────────────────────────────────────────────────────────────────────────┐
│ 你需要多少个模块? │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 小型应用(1-5个DocType,单一用途)? │
│ └─► 一个与应用同名的模块 │
│ 示例:my_app/my_app/(模块名为"My App") │
│ │
│ 中型应用(6-15个DocType,多个业务领域)? │
│ └─► 按功能领域划分2-4个模块 │
│ 示例:core/、settings/、integrations/ │
│ │
│ 大型应用(15个以上DocType,复杂业务领域)? │
│ └─► 按业务领域划分模块 │
│ 示例:inventory/、sales/、purchasing/、settings/ │
│ │
│ 多租户或垂直行业解决方案? │
│ └─► 考虑使用多个应用 │
│ 基础应用 + 垂直行业专属应用 │
│ │
└─────────────────────────────────────────────────────────────────────────┘原则:每个DocType必须属于且仅属于一个模块。选择模块的标准是:用户会在哪里查找这个DocType?
Quick Implementation Workflows
快速实施工作流
New App Workflow
新应用工作流
1. Create app structure → bench new-app my_app
2. Configure pyproject → Edit pyproject.toml (v15+) or setup.py (v14)
3. Define modules → Edit modules.txt
4. Create DocTypes → bench --site mysite new-doctype MyDocType
5. Write controllers → my_app/doctype/my_doctype/my_doctype.py
6. Configure hooks → hooks.py for integration
7. Export fixtures → bench --site mysite export-fixtures
8. Test installation → bench --site testsite install-app my_appSee:for detailed steps.references/workflows.md
1. 创建应用结构 → bench new-app my_app
2. 配置pyproject → 编辑pyproject.toml(v15+)或setup.py(v14)
3. 定义模块 → 编辑modules.txt
4. 创建DocTypes → bench --site mysite new-doctype MyDocType
5. 编写控制器 → my_app/doctype/my_doctype/my_doctype.py
6. 配置钩子 → hooks.py用于集成
7. 导出fixtures → bench --site mysite export-fixtures
8. 测试安装 → bench --site testsite install-app my_app参考:包含详细步骤。references/workflows.md
Patch Workflow
补丁工作流
1. Plan the migration → What data moves where?
2. Choose timing → [pre_model_sync] or [post_model_sync]
3. Write patch file → myapp/patches/v1_0/description.py
4. Add to patches.txt → Under correct section
5. Test locally → bench --site testsite migrate
6. Handle errors → Add rollback logic if needed
7. Test on copy of prod → ALWAYS before productionSee:for patch patterns.references/workflows.md
1. 规划迁移 → 数据需要从哪里迁移到哪里?
2. 选择执行时机 → [pre_model_sync] 或 [post_model_sync]
3. 编写补丁文件 → myapp/patches/v1_0/description.py
4. 添加到patches.txt → 在正确的章节下添加
5. 本地测试 → bench --site testsite migrate
6. 处理错误 → 如有需要添加回滚逻辑
7. 在生产环境副本上测试 → 务必在生产环境前测试参考:包含补丁模式。references/workflows.md
Fixture Workflow
Fixture工作流
1. Configure hooks.py → Define fixtures list with filters
2. Make changes via UI → Custom Fields, Property Setters, etc.
3. Export fixtures → bench --site mysite export-fixtures --app my_app
4. Verify JSON files → Check my_app/fixtures/*.json
5. Commit to version control
6. Test import → bench --site newsite migrateSee:for fixture strategies.references/workflows.md
1. 配置hooks.py → 定义带有过滤器的fixtures列表
2. 通过UI进行更改 → Custom Fields、Property Setters等
3. 导出fixtures → bench --site mysite export-fixtures --app my_app
4. 验证JSON文件 → 检查my_app/fixtures/*.json
5. 提交到版本控制
6. 测试导入 → bench --site newsite migrate参考:包含Fixture策略。references/workflows.md
Version-Specific Considerations
版本特定注意事项
| Aspect | v14 | v15 | v16 |
|---|---|---|---|
| Build config | setup.py | pyproject.toml | pyproject.toml |
| DocType extension | doc_events | doc_events | |
| Python minimum | 3.10 | 3.10 | 3.11 |
| INI patches | ✅ | ✅ | ✅ |
| Fixtures format | JSON | JSON | JSON |
| 方面 | v14 | v15 | v16 |
|---|---|---|---|
| 构建配置 | setup.py | pyproject.toml | pyproject.toml |
| DocType扩展 | doc_events | doc_events | 推荐使用 |
| Python最低版本 | 3.10 | 3.10 | 3.11 |
| INI补丁 | ✅ | ✅ | ✅ |
| Fixtures格式 | JSON | JSON | JSON |
v16 Breaking Changes
v16重大变更
- hook: Cleaner DocType extension pattern
extend_doctype_class - Data masking: Field-level privacy configuration available
- UUID naming: New naming rule option for DocTypes
- Chrome PDF: wkhtmltopdf deprecated for PDF generation
- ****钩子:更简洁的DocType扩展模式
extend_doctype_class - 数据掩码:支持字段级隐私配置
- UUID命名:DocType新增命名规则选项
- Chrome PDF:wkhtmltopdf已被弃用,改用Chrome生成PDF
Critical Implementation Rules
关键实施规则
✅ ALWAYS
✅ 必须遵守
- Start with - Never create structure manually
bench new-app - Define in
__version__- Build will fail without it__init__.py - Test patches on database copy - Never run untested patches on production
- Use batch processing - Any patch touching 1000+ records needs batching
- Filter fixtures - Never export all records of a DocType
- Version your patches - Use v1_0, v2_0 directories for organization
- 始终从开始 - 切勿手动创建应用结构
bench new-app - 在中定义
__init__.py- 缺少此项构建会失败__version__ - 在数据库副本上测试补丁 - 切勿在生产环境运行未测试的补丁
- 使用批量处理 - 任何涉及1000条以上记录的补丁都需要批量处理
- 过滤fixtures - 切勿导出某个DocType的所有记录
- 为补丁版本化 - 使用v1_0、v2_0目录进行组织
❌ NEVER
❌ 切勿执行
- Put frappe/erpnext in pyproject dependencies - They're not on PyPI
- Include transactional data in fixtures - Only configuration!
- Hardcode site-specific values - Use hooks or settings DocTypes
- Skip in large patches - Memory will explode
frappe.db.commit() - Delete fields without backup patch - Data loss is irreversible
- Modify core ERPNext files - Always use hooks or override patterns
- 在pyproject依赖中添加frappe/erpnext - 它们不在PyPI上
- 在fixtures中包含交易数据 - 仅包含配置数据!
- 硬编码特定站点的值 - 使用钩子或配置DocType
- 在大型补丁中跳过- 会导致内存溢出
frappe.db.commit() - 不做备份补丁就删除字段 - 数据丢失不可恢复
- 修改ERPNext核心文件 - 始终使用钩子或覆盖模式
Reference Files
参考文件
| File | Contents |
|---|---|
| Complete decision flowcharts |
| Step-by-step implementation guides |
| Complete working examples |
| Common mistakes to avoid |
| 文件 | 内容 |
|---|---|
| 完整的决策流程图 |
| 分步实施指南 |
| 完整的工作示例 |
| 需要避免的常见错误 |
See Also
另请参阅
- - Exact syntax reference
erpnext-syntax-customapp - - Hooks configuration
erpnext-syntax-hooks - - Hook implementation patterns
erpnext-impl-hooks - - Database operations for patches
erpnext-database
- - 具体语法参考
erpnext-syntax-customapp - - 钩子配置
erpnext-syntax-hooks - - 钩子实施模式
erpnext-impl-hooks - - 补丁相关的数据库操作
erpnext-database