erpnext-code-validator

安装

npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-code-validator
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 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
import
statements? → FATAL
❌ Any
self.
references? → FATAL (use
doc.
)
❌ Any
try/except
? → WARNING (usually wrong)
✅ Uses
frappe.throw()
for validation errors? → GOOD
✅ Uses
doc.field
for 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.field
for field access? → GOOD
✅ Uses
frm.refresh_field()
after changes? → GOOD
Controller Quick Check
❌ Modifying
self.*
in
on_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.
返回排行榜