erpnext-code-validator
27
总安装量
9
周安装量
#13725
全站排名
安装命令
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-code-validator
Agent 安装分布
claude-code
7
opencode
5
github-copilot
5
codex
5
amp
5
Skill 文档
ERPNext Code Validator Agent
This agent validates ERPNext/Frappe code against established patterns, common pitfalls, and version compatibility requirements.
Purpose: Catch errors BEFORE deployment, not after
When to Use This Agent
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â CODE VALIDATION TRIGGERS â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â ⺠Code has been generated and needs review â
â "Check this Server Script before I save it" â
â âââ USE THIS AGENT â
â â
â ⺠Code is causing errors â
â "Why isn't this working?" â
â âââ USE THIS AGENT â
â â
â ⺠Pre-deployment validation â
â "Is this production-ready?" â
â âââ USE THIS AGENT â
â â
â ⺠Code review for best practices â
â "Can this be improved?" â
â âââ USE THIS AGENT â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Validation Workflow
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â CODE VALIDATOR WORKFLOW â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â STEP 1: IDENTIFY CODE TYPE â
â ââââââââââââââââââââââââââ â
â ⢠Client Script (JavaScript) â
â ⢠Server Script (Python sandbox) â
â ⢠Controller (Python full) â
â ⢠hooks.py configuration â
â ⢠Jinja template â
â ⢠Whitelisted method â
â â
â STEP 2: RUN TYPE-SPECIFIC CHECKS â
â âââââââââââââââââââââââââââââââââ â
â ⢠Apply checklist for identified code type â
â ⢠Check syntax patterns â
â ⢠Verify API usage â
â â
â STEP 3: CHECK UNIVERSAL RULES â
â ââââââââââââââââââââââââââââââ â
â ⢠Error handling present â
â ⢠User feedback appropriate â
â ⢠Security considerations â
â ⢠Performance implications â
â â
â STEP 4: VERIFY VERSION COMPATIBILITY â
â ââââââââââââââââââââââââââââââââââââ â
â ⢠v14/v15/v16 specific features â
â ⢠Deprecated patterns â
â ⢠Version-specific behaviors â
â â
â STEP 5: GENERATE VALIDATION REPORT â
â ââââââââââââââââââââââââââââââââââ â
â ⢠Critical errors (must fix) â
â ⢠Warnings (should fix) â
â ⢠Suggestions (nice to have) â
â ⢠Corrected code (if errors found) â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â See references/workflow.md for detailed validation steps.
Critical Checks by Code Type
Server Script Checks
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â â ï¸ SERVER SCRIPT CRITICAL CHECKS â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â [FATAL] Import statements â
â âââââââââââââââââââââââââââ â
â â import json â Use frappe.parse_json() â
â â from frappe.utils import X â Use frappe.utils.X() â
â â import requests â IMPOSSIBLE in Server Script â
â â
â [FATAL] Undefined variables â
â ââââââââââââââââââââââââââââ â
â â self.field â Use doc.field â
â â document.field â Use doc.field â
â â
â [FATAL] Wrong event handling â
â âââââââââââââââââââââââââââââââ â
â â try/except for validation â Just frappe.throw() â
â â
â [ERROR] Event name mismatch â
â âââââââââââââââââââââââââââ â
â â Event "Before Save" code in "After Save" script â
â â
â [WARNING] Missing validation â
â âââââââââââââââââââââââââââââââ â
â â ï¸ No null/empty checks before operations â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Client Script Checks
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â CLIENT SCRIPT CRITICAL CHECKS â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â [FATAL] Wrong API usage â
â âââââââââââââââââââââââââ â
â â frappe.db.get_value() â Server-side only! â
â â frappe.get_doc() â Server-side only! â
â â frappe.call() for server data â
â â
â [FATAL] Missing async handling â
â ââââââââââââââââââââââââââââââ â
â â let result = frappe.call() â Returns undefined â
â â frappe.call({callback: fn}) â Use callback â
â â await frappe.call({async:false}) â Or async/await â
â â
â [ERROR] Field refresh issues â
â ââââââââââââââââââââââââââââ â
â â frm.set_value() without refresh â
â â frm.set_value() then frm.refresh_field() â
â â
â [WARNING] Form state checks â
â âââââââââââââââââââââââââââ â
â â ï¸ Not checking frm.doc.__islocal for new docs â
â â ï¸ Not checking frm.doc.docstatus for submitted docs â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Controller Checks
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â CONTROLLER CRITICAL CHECKS â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â [FATAL] Wrong lifecycle usage â
â âââââââââââââââââââââââââââââ â
â â Modifying self.field in on_update â Changes NOT saved! â
â â Use frappe.db.set_value() in on_update â
â â
â [FATAL] Missing super() call â
â ââââââââââââââââââââââââââââ â
â â def validate(self): pass â Breaks parent validation â
â â def validate(self): super().validate() â
â â
â [ERROR] Transaction assumptions â
â âââââââââââââââââââââââââââââââ â
â â Assuming rollback on error in on_update â
â (only validate and before_* roll back on error) â
â â
â [ERROR] Circular save â
â ââââââââââââââââââââââ â
â â self.save() inside lifecycle hooks â
â â doc.save() for same document in hooks â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â See references/checklists.md for complete checklists.
Validation Report Format
## Code Validation Report
### Code Type: [Server Script / Client Script / Controller / etc.]
### Target DocType: [DocType name]
### Event/Trigger: [Event name]
---
### ð´ CRITICAL ERRORS (Must Fix)
| Line | Issue | Fix |
|------|-------|-----|
| 3 | Import statement in Server Script | Use frappe.utils.X() directly |
### ð¡ WARNINGS (Should Fix)
| Line | Issue | Recommendation |
|------|-------|----------------|
| 12 | No null check before .lower() | Add: if value: value.lower() |
### ðµ SUGGESTIONS (Nice to Have)
| Line | Suggestion |
|------|------------|
| 8 | Consider using frappe.db.get_value for single field |
---
### Corrected Code
```python
# [Corrected version with all critical errors fixed]
Version Compatibility
| Version | Status |
|---|---|
| v14 | â Compatible |
| v15 | â Compatible |
| v16 | â Compatible |
## Universal Validation Rules
These apply to ALL code types:
### Security Checks
| Check | Severity | Description |
|-------|----------|-------------|
| SQL Injection | CRITICAL | Raw user input in SQL queries |
| Permission bypass | CRITICAL | Missing permission checks before operations |
| XSS vulnerability | HIGH | Unescaped user input in HTML |
| Sensitive data exposure | HIGH | Logging passwords/tokens |
### Error Handling Checks
| Check | Severity | Description |
|-------|----------|-------------|
| Silent failures | HIGH | Catching exceptions without handling |
| Missing user feedback | MEDIUM | Errors not communicated to user |
| Generic error messages | LOW | "An error occurred" without details |
### Performance Checks
| Check | Severity | Description |
|-------|----------|-------------|
| Query in loop | HIGH | frappe.db.* inside for loop |
| Unbounded query | MEDIUM | SELECT without LIMIT |
| Unnecessary get_doc | LOW | get_doc when get_value suffices |
â See [references/examples.md](references/examples.md) for validation examples.
## Version-Specific Validations
### v16 Features (Fail on v14/v15)
```python
# These ONLY work on v16+
extend_doctype_class = {} # hooks.py - v16 only
naming_rule = "UUID" # DocType - v16 only
pdf_renderer = "chrome" # Print Format - v16 only
Deprecated Patterns (Warn)
# DEPRECATED - still works but should update
frappe.bean() # Use frappe.get_doc()
frappe.msgprint(raise_exception=True) # Use frappe.throw()
job_name parameter # Use job_id (v15+)
Version-Specific Behaviors
| Behavior | v14 | v15/v16 |
|---|---|---|
| Scheduler tick | 240s | 60s |
| Background job dedup | job_name | job_id |
Quick Validation Commands
Server Script Quick Check
- â Any
importstatements? â FATAL - â Any
self.references? â FATAL (usedoc.) - â Any
try/except? â WARNING (usually wrong) - â
Uses
frappe.throw()for validation errors? â GOOD - â
Uses
doc.fieldfor document access? â GOOD
Client Script Quick Check
- â Any
frappe.db.*calls? â FATAL (server-side only) - â Any
frappe.get_doc()calls? â FATAL (server-side only) - â
frappe.call()without callback? â FATAL (async issue) - â
Uses
frm.doc.fieldfor field access? â GOOD - â
Uses
frm.refresh_field()after changes? â GOOD
Controller Quick Check
- â Modifying
self.*inon_update? â ERROR (won’t save) - â Missing
super().method()calls? â WARNING - â
self.save()in lifecycle hook? â FATAL (circular) - â Imports at top of file? â GOOD (controllers allow imports)
- â Error handling with try/except? â GOOD (controllers allow this)
Integration with Other Skills
This validator uses knowledge from:
| Skill | What It Provides |
|---|---|
erpnext-syntax-* |
Correct syntax patterns |
erpnext-impl-* |
Correct implementation patterns |
erpnext-errors-* |
Error handling patterns |
erpnext-database |
Query patterns and pitfalls |
erpnext-permissions |
Permission check patterns |
erpnext-api-patterns |
API response patterns |
Validation Depth Levels
| Level | Checks | Use When |
|---|---|---|
| Quick | Fatal errors only | Initial scan |
| Standard | + Warnings | Pre-deployment |
| Deep | + Suggestions + Optimization | Production review |
Default: Standard level for most validations.