Back to list
OpenAEC-Foundation

erpnext-impl-customapp

by OpenAEC-Foundation

28 deterministic Claude AI skills for flawless ERPNext/Frappe v14-16 development. Agent Skills standard compliant.

1🍴 1📅 Jan 23, 2026

SKILL.md


name: erpnext-impl-customapp description: "Implementation workflows for building Frappe/ERPNext custom apps. Covers app structure, module creation, doctype design, fixtures, patches, and deployment. V14/V15/V16 compatible. Triggers: create custom app, new frappe app, bench new-app, app structure, module creation, doctype creation, fixtures, patches."

ERPNext Custom App - Implementation

This skill helps you determine HOW to build and structure Frappe/ERPNext custom apps. For exact syntax, see erpnext-syntax-customapp.

Version: v14/v15/v16 compatible (differences noted)


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                                     │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Decision 1: Do You Need a Custom App?

┌─────────────────────────────────────────────────────────────────────────┐
│ 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.


Decision 2: Extension Strategy

┌─────────────────────────────────────────────────────────────────────────┐
│ 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: references/decision-tree.md for detailed extension patterns.


Decision 3: Patch 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: references/decision-tree.md for patch timing flowchart.


Decision 4: Module Organization

┌─────────────────────────────────────────────────────────────────────────┐
│ 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?


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_app

See: references/workflows.md for detailed steps.

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 production

See: references/workflows.md for patch patterns.

Fixture Workflow

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 migrate

See: references/workflows.md for fixture strategies.


Version-Specific Considerations

Aspectv14v15v16
Build configsetup.pypyproject.tomlpyproject.toml
DocType extensiondoc_eventsdoc_eventsextend_doctype_class preferred
Python minimum3.103.103.11
INI patches
Fixtures formatJSONJSONJSON

v16 Breaking Changes

  • extend_doctype_class hook: Cleaner DocType extension pattern
  • Data masking: Field-level privacy configuration available
  • UUID naming: New naming rule option for DocTypes
  • Chrome PDF: wkhtmltopdf deprecated for PDF generation

Critical Implementation Rules

✅ ALWAYS

  1. Start with bench new-app - Never create structure manually
  2. Define __version__ in __init__.py - Build will fail without it
  3. Test patches on database copy - Never run untested patches on production
  4. Use batch processing - Any patch touching 1000+ records needs batching
  5. Filter fixtures - Never export all records of a DocType
  6. Version your patches - Use v1_0, v2_0 directories for organization

❌ NEVER

  1. Put frappe/erpnext in pyproject dependencies - They're not on PyPI
  2. Include transactional data in fixtures - Only configuration!
  3. Hardcode site-specific values - Use hooks or settings DocTypes
  4. Skip frappe.db.commit() in large patches - Memory will explode
  5. Delete fields without backup patch - Data loss is irreversible
  6. Modify core ERPNext files - Always use hooks or override patterns

Reference Files

FileContents
references/decision-tree.mdComplete decision flowcharts
references/workflows.mdStep-by-step implementation guides
references/examples.mdComplete working examples
references/anti-patterns.mdCommon mistakes to avoid

See Also

  • erpnext-syntax-customapp - Exact syntax reference
  • erpnext-syntax-hooks - Hooks configuration
  • erpnext-impl-hooks - Hook implementation patterns
  • erpnext-database - Database operations for patches

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon