Token导航 LogoToken导航

Agent Skill · 待分类

erpnext-syntax-controllers(erpnext 语法控制器)

erpnext-syntax-controllers 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

erpnext-syntax-controllers 是待分类类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描有提醒项,按安装量在待分类类的 11,209 个 Skill 里排第 3,335。

总安装 1,053周安装 43GitHub Stars 87下载 341核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:erpnext-syntax-controllers(erpnext 语法控制器)
来源仓库:https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package
仓库路径:skills/erpnext-syntax-controllers
安装命令:
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-syntax-controllers
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-syntax-controllers

这个 Skill 是做什么的

这个 Skill 的分类还没最终确定,用法以来源仓库的说明为准。

规定 Document Controller 的 Python 类结构与生命周期方法命名约定。适用于 Codex、Claude、Cursor、Gemini CLI 中编写健壮的服务器端业务逻辑。强调 validate、on_update 等方法的执行时机与 self 对象的不可保存性。

使用前应核对继承基类与属性定义,确保与目标 DocType 结构一致。erpnext-syntax-controllers 属于待分类类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/erpnext-syntax-controllers

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_de…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

erpnext-syntax-controllers 怎么安装?

在终端执行 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

erpnext-syntax-controllers 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

erpnext-syntax-controllers 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

erpnext-syntax-controllers 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

erpnext-syntax-controllers 用的人多吗?

公开数据是累计安装 1,053 次,近一周安装 43 次,下载 341 次,GitHub 87 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

erpnext-syntax-controllers 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理待分类类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

待分类类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
infsh-cli

infsh CLI · Codex、Claude

4,374,576382权限未标注未明确未收录
ai-video-generation

AI 视频生成 · Codex、Claude

4,313,376382调用外部服务未明确有提醒
lark-openapi-explorer

云雀 OpenAPI 浏览器 · Codex、Claude

2,064,1209,011需要联网未明确有提醒
lark-workflow-standup-report

Lark 工作流程站立报告 · Codex、Claude

2,041,6328,978需要联网未明确通过
use-my-browser

使用我的浏览器 · Codex、Claude

1,848,49140操作浏览器未明确未通过
erpnext-syntax-controllers

erpnext 语法控制器 · 本页

1,05387需要联网未明确有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

ERPNext Syntax: Document Controllers

Document Controllers are Python classes that implement the server-side logic of a DocType.

Quick Reference

Controller Basic Structure

import frappe
from frappe.model.document import Document

class SalesOrder(Document):
    def validate(self):
        """Main validation - runs on every save."""
        if not self.items:
            frappe.throw(_("Items are required"))
        self.total = sum(item.amount for item in self.items)

    def on_update(self):
        """After save - changes to self are NOT saved."""
        self.update_linked_docs()

Location and Naming

DocTypeClassFile
Sales OrderSalesOrderselling/doctype/sales_order/sales_order.py
Custom DocCustomDocmodule/doctype/custom_doc/custom_doc.py

Rule: DocType name → PascalCase (remove spaces) → snake_case filename


Most Used Hooks

HookWhenTypical Use
validateBefore every saveValidation, calculations
on_updateAfter every saveNotifications, linked docs
after_insertAfter new docCreation-only actions
on_submitAfter submitLedger entries, stock
on_cancelAfter cancelReverse ledger entries
on_trashBefore deleteCleanup related data
autonameOn namingCustom document name

Complete list and execution order: See lifecycle-methods.md


Hook Selection Decision Tree

What do you want to do?
│
├─► Validate or calculate fields?
│   └─► validate
│
├─► Action after save (emails, linked docs)?
│   └─► on_update
│
├─► Only for NEW docs?
│   └─► after_insert
│
├─► On SUBMIT?
│   ├─► Check beforehand? → before_submit
│   └─► Action afterwards? → on_submit
│
├─► On CANCEL?
│   ├─► Check beforehand? → before_cancel
│   └─► Cleanup? → on_cancel
│
├─► Custom document name?
│   └─► autoname
│
└─► Cleanup before delete?
    └─► on_trash

Critical Rules

1. Changes after on_update are NOT saved

# ❌ WRONG - change is lost
def on_update(self):
    self.status = "Completed"  # NOT saved

# ✅ CORRECT - use db_set
def on_update(self):
    frappe.db.set_value(self.doctype, self.name, "status", "Completed")

2. No commits in controllers

# ❌ WRONG - Frappe handles commits
def on_update(self):
    frappe.db.commit()  # DON'T DO THIS

# ✅ CORRECT - no commit needed
def on_update(self):
    self.update_related()  # Frappe commits automatically

3. Always call super() when overriding

# ❌ WRONG - parent logic is skipped
def validate(self):
    self.custom_check()

# ✅ CORRECT - parent logic is preserved
def validate(self):
    super().validate()
    self.custom_check()

4. Use flags for recursion prevention

def on_update(self):
    if self.flags.get('from_linked_doc'):
        return

    linked = frappe.get_doc("Linked Doc", self.linked_doc)
    linked.flags.from_linked_doc = True
    linked.save()

Document Naming (autoname)

Available Naming Options

OptionExampleResultVersion
field:fieldnamefield:customer_nameABC CompanyAll
naming_series:naming_series:SO-2024-00001All
format:PREFIX-{##}format:INV-{YYYY}-{####}INV-2024-0001All
hashhasha1b2c3d4e5All
PromptPromptUser enters nameAll
UUIDUUID01948d5f-...v16+
Custom methodController autoname()Any patternAll

UUID Naming (v16+)

New in v16: UUID-based naming for globally unique identifiers.

{
  "doctype": "DocType",
  "autoname": "UUID"
}

Benefits:

  • Globally unique across systems
  • Better data integrity and traceability
  • Reduced database storage
  • Faster bulk record creation
  • Link fields store UUID in native format

Implementation:

# Frappe automatically generates UUID7
# In naming.py:
if meta.autoname == "UUID":
    doc.name = str(uuid_utils.uuid7())

Validation:

# UUID names are validated on import
from uuid import UUID
try:
    UUID(doc.name)
except ValueError:
    frappe.throw(_("Invalid UUID: {}").format(doc.name))

Custom autoname Method

from frappe.model.naming import getseries

class Project(Document):
    def autoname(self):
        # Custom naming based on customer
        prefix = f"P-{self.customer}-"
        self.name = getseries(prefix, 3)
        # Result: P-ACME-001, P-ACME-002, etc.

Format Patterns

PatternDescriptionExample
{#}Counter1, 2, 3
{##}Zero-padded counter01, 02, 03
{####}4-digit counter0001, 0002
{YYYY}Full year2024
{YY}2-digit year24
{MM}Month01-12
{DD}Day01-31
{fieldname}Field value(value)

Controller Override

Via hooks.py (override_doctype_class)

# hooks.py
override_doctype_class = {
    "Sales Order": "custom_app.overrides.CustomSalesOrder"
}

# custom_app/overrides.py
from erpnext.selling.doctype.sales_order.sales_order import SalesOrder

class CustomSalesOrder(SalesOrder):
    def validate(self):
        super().validate()
        self.custom_validation()

Via doc_events (hooks.py)

# hooks.py
doc_events = {
    "Sales Order": {
        "validate": "custom_app.events.validate_sales_order",
        "on_submit": "custom_app.events.on_submit_sales_order"
    }
}

# custom_app/events.py
def validate_sales_order(doc, method):
    if doc.total > 100000:
        doc.requires_approval = 1

Choice: override_doctype_class for full control, doc_events for individual hooks.


Submittable Documents

Documents with is_submittable = 1 have a docstatus lifecycle:

docstatusStatusEditableCan go to
0Draft✅ Yes1 (Submit)
1Submitted❌ No2 (Cancel)
2Cancelled❌ No-
class StockEntry(Document):
    def on_submit(self):
        """After submit - create stock ledger entries."""
        self.update_stock_ledger()

    def on_cancel(self):
        """After cancel - reverse the entries."""
        self.reverse_stock_ledger()

Virtual DocTypes

For external data sources (no database table):

class ExternalCustomer(Document):
    @staticmethod
    def get_list(args):
        return external_api.get_customers(args.get("filters"))

    @staticmethod
    def get_count(args):
        return external_api.count_customers(args.get("filters"))

    @staticmethod
    def get_stats(args):
        return {}

Inheritance Patterns

Standard Controller

from frappe.model.document import Document

class MyDocType(Document):
    pass

Tree DocType

from frappe.utils.nestedset import NestedSet

class Department(NestedSet):
    pass

Extend Existing Controller

from erpnext.selling.doctype.sales_order.sales_order import SalesOrder

class CustomSalesOrder(SalesOrder):
    def validate(self):
        super().validate()
        self.custom_validation()

Type Annotations (v15+)

class Person(Document):
    if TYPE_CHECKING:
        from frappe.types import DF
        first_name: DF.Data
        last_name: DF.Data
        birth_date: DF.Date

Enable in hooks.py:

export_python_type_annotations = True

Reference Files

FileContents
lifecycle-methods.mdAll hooks, execution order, examples
methods.mdAll doc.* methods with signatures
flags.mdFlags system documentation
examples.mdComplete working controller examples
anti-patterns.mdCommon mistakes and corrections

Version Differences

Featurev14v15v16
Type annotations❌✅ Auto-generated✅
before_discard hook❌✅✅
on_discard hook❌✅✅
flags.notify_update❌✅✅
UUID autoname❌❌✅
UUID in Link fields (native)❌❌✅

v16-Specific Notes

UUID Naming:

  • Set autoname = "UUID" in DocType definition
  • Uses uuid7() for time-ordered UUIDs
  • Link fields store UUIDs in native format (not text)
  • Improves performance for bulk operations

Choosing UUID vs Traditional Naming:

When to use UUID:
├── Cross-system data synchronization
├── Bulk record creation
├── Global uniqueness required
└── No human-readable name needed

When to use traditional naming:
├── User-facing document references (SO-00001)
├── Sequential numbering required
├── Auditing requires readable names
└── Integration with legacy systems

Anti-Patterns

❌ Direct field change after on_update

def on_update(self):
    self.status = "Done"  # Will be lost!

❌ frappe.db.commit() in controller

def validate(self):
    frappe.db.commit()  # Breaks transaction!

❌ Forgetting to call super()

def validate(self):
    self.my_check()  # Parent validate is skipped

→ See anti-patterns.md for complete list.


Related Skills

  • erpnext-syntax-serverscripts – Server Scripts (sandbox alternative)
  • erpnext-syntax-hooks – hooks.py configuration
  • erpnext-impl-controllers – Implementation workflows

平台分布

Codex

33.09%
按下载量换算113

Claude

31.68%
按下载量换算108

Cursor

18.31%
按下载量换算62

Gemini CLI

9.43%
按下载量换算32

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills