Skill125 estrellas del repoactualizado 2mo ago
frappe-impl-customapp
>
Instalar en Claude Code
Copiargit clone --depth 1 https://github.com/Impertio-Studio/Frappe_Claude_Skill_Package /tmp/frappe-impl-customapp && cp -r /tmp/frappe-impl-customapp/skills/source/impl/frappe-impl-customapp ~/.claude/skills/frappe-impl-customappDespués abre una sesión nueva de Claude Code; el skill carga automáticamente.
Definición
SKILL.md
# Frappe Custom App - Implementation
Workflow for building a custom Frappe app from scratch. For exact syntax, see `frappe-syntax-customapp`.
**Version**: v14/v15/v16 compatible
---
## Main Decision: Do You Need a Custom App?
```
WHAT CHANGES DO YOU NEED?
|
+-- Add fields to existing DocType?
| +-- NO APP NEEDED: Custom Field + Property Setter
|
+-- Simple automation/validation (<50 lines)?
| +-- NO APP NEEDED: Server Script or Client Script
|
+-- Complex business logic, new DocTypes, or Python code?
| +-- YES: Create custom app
|
+-- Integration with external system (needs imports)?
| +-- YES: Custom app REQUIRED (Server Scripts block imports)
|
+-- Custom reports with complex queries?
| +-- Script Report (no app) vs Query Report (app optional)
```
**Rule**: ALWAYS start with the simplest solution. Server Scripts + Custom Fields solve 70% of needs without a custom app.
---
## Step 1: Create App Structure
```bash
cd ~/frappe-bench
bench new-app my_app
# Prompts: Title, Description, Publisher, Email, License
```
ALWAYS verify immediately:
```python
# my_app/my_app/__init__.py MUST have:
__version__ = "0.0.1"
```
---
## Step 2: Configure pyproject.toml (v15+)
```toml
[build-system]
requires = ["flit_core >=3.4,<4"]
build-backend = "flit_core.buildapi"
[project]
name = "my_app"
authors = [{ name = "Your Company", email = "dev@example.com" }]
description = "Your app description"
requires-python = ">=3.10"
readme = "README.md"
dynamic = ["version"]
dependencies = [
"requests>=2.28.0" # Only PyPI packages here
]
[tool.bench.frappe-dependencies]
frappe = ">=15.0.0,<16.0.0"
# erpnext = ">=15.0.0,<16.0.0" # Only if needed
```
**Rule**: NEVER put frappe or erpnext in `[project].dependencies` -- they are NOT on PyPI.
---
## Step 3: Configure hooks.py
```python
app_name = "my_app"
app_title = "My App"
app_publisher = "Your Company"
app_description = "Description"
app_email = "dev@example.com"
app_license = "MIT"
required_apps = ["frappe"] # Or ["frappe", "erpnext"]
fixtures = [] # Configured later
```
**Rule**: ALWAYS declare `required_apps` with all dependencies.
---
## Step 4: Define Modules
```text
# my_app/my_app/modules.txt
My App
```
| App Size | Module Strategy |
|----------|----------------|
| 1-5 DocTypes | ONE module with app name |
| 6-15 DocTypes | 2-4 modules by functional area |
| 15+ DocTypes | Modules by business domain |
**Rule**: Each DocType belongs to EXACTLY one module. Module name in `modules.txt` maps to directory: `My Custom App` --> `my_custom_app/`.
### Adding a Module
```bash
mkdir -p my_app/my_app/new_module/doctype
touch my_app/my_app/new_module/__init__.py
# Add "New Module" to modules.txt
bench --site mysite migrate
```
---
## Step 5: Install and Create DocTypes
```bash
# Install app on site
bench --site mysite install-app my_app
# Create DocType (via UI recommended, or CLI)
bench --site mysite new-doctype "My Document" --module "My App"
```
This creates:
```
my_app/my_app/doctype/my_document/
+-- my_document.json # DocType definition
+-- my_document.py # Controller
+-- my_document.js # Client script
+-- test_my_document.py # Tests
```
---
## Step 6: Add Hooks
### doc_events (v14/v15/v16)
```python
doc_events = {
"Sales Invoice": {
"validate": "my_app.events.sales_invoice.validate",
"on_submit": "my_app.events.sales_invoice.on_submit"
}
}
```
### extend_doctype_class (v16 ONLY -- preferred)
```python
extend_doctype_class = {
"Sales Invoice": "my_app.overrides.sales_invoice.CustomSalesInvoice"
}
```
**Rule**: ALWAYS call `super().method()` when overriding lifecycle methods in v16.
### Scheduler Events
```python
scheduler_events = {
"daily": ["my_app.tasks.daily_cleanup"],
"cron": {"0 9 * * 1-5": ["my_app.tasks.morning_report"]}
}
```
See `frappe-impl-hooks` and `frappe-impl-scheduler` for complete patterns.
---
## Step 7: Add Patches
### Create Patch File
```bash
mkdir -p my_app/my_app/patches/v1_0
touch my_app/my_app/patches/__init__.py
touch my_app/my_app/patches/v1_0/__init__.py
```
```python
# my_app/my_app/patches/v1_0/populate_defaults.py
import frappe
def execute():
if not frappe.db.has_column("My DocType", "target_field"):
return # Skip if not applicable
batch_size = 1000
offset = 0
while True:
records = frappe.get_all("My DocType",
limit_page_length=batch_size, limit_start=offset)
if not records:
break
for r in records:
frappe.db.set_value("My DocType", r.name,
"target_field", "default", update_modified=False)
frappe.db.commit()
offset += batch_size
```
### Register in patches.txt
```ini
[pre_model_sync]
# Patches that run BEFORE schema changes (backup data from deleted fields)
[post_model_sync]
# Patches that run AFTER schema changes (populate new fields)
my_app.patches.v1_0.populate_defaults
```
**Rules**:
- ALWAYS check if patch is needed (guard clause)
- ALWAYS batch process 1000+ records
- ALWAYS commit after each batch
- NEVER run untested patches on production
---
## Step 8: Fixtures Management
### Configure in hooks.py
```python
fixtures = [
{"dt": "Custom Field", "filters": [["module", "=", "My App"]]},
{"dt": "Property Setter", "filters": [["module", "=", "My App"]]},
{"dt": "Role", "filters": [["name", "in", ["My App User", "My App Manager"]]]},
{"dt": "Workflow", "filters": [["document_type", "=", "My DocType"]]},
"My Category", # All records of your own config DocType
]
```
### Export and Verify
```bash
bench --site mysite export-fixtures --app my_app
ls my_app/my_app/fixtures/
# custom_field.json, property_setter.json, etc.
```
**Rules**:
- ALWAYS filter fixtures to YOUR app's customizations
- NEVER include transactional data (invoices, orders)
- NEVER export without filters for shared DocTypes (Custom Field, Workflow)
- Fixtures auto-import during `bench migrate`
---
## Step 9: Developmen