Token导航 LogoToken导航TokenDH.com
待分类需要联网github未标认证来源可访问许可证需确认审计通过

erpnext-impl-clientscriptserpnext impl 客户端脚本

Agent Skill

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

总安装

1,028

周安装

42

GitHub Stars

87

下载量

333
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

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

命令行安装

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

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

简介

判断何时使用客户端脚本及服务器端逻辑,区分 UI 反馈与核心业务处理场景。

  • 适用于 Codex、Claude、Cursor、Gemini CLI 中优化表单交互和数据验证流程。
  • 可参考原始文档了解字段级事件与全局事件的触发顺序和执行上下文。
  • 安装前建议评估网络延迟影响,避免将耗时操作错误地放在客户端执行。
  • erpnext-impl-clientscripts 属于待分类类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

ERPNext Client Scripts - Implementation (EN)

This skill helps you determine HOW to implement client-side features. For exact syntax, see erpnext-syntax-clientscripts.

Version: v14/v15/v16 compatible

Main Decision: Client or Server?

┌─────────────────────────────────────────────────────────┐
│ Must the logic ALWAYS execute?                          │
│ (including imports, API calls, Server Scripts)          │
├─────────────────────────────────────────────────────────┤
│ YES → Server-side (Controller or Server Script)         │
│ NO  → What is the primary goal?                         │
│       ├── UI feedback/UX improvement → Client Script    │
│       ├── Show/hide fields → Client Script              │
│       ├── Link filters → Client Script                  │
│       ├── Data validation → BOTH (client + server)      │
│       └── Calculations → Depends on criticality         │
└─────────────────────────────────────────────────────────┘

Rule of thumb: Client Scripts for UX, Server for integrity.

Decision Tree: Which Event?

WHAT DO YOU WANT TO ACHIEVE?
│
├─► Set link field filters
│   └── setup (once, early in lifecycle)
│
├─► Add custom buttons
│   └── refresh (after each form load/save)
│
├─► Show/hide fields based on condition
│   └── refresh + {fieldname} (both needed)
│
├─► Validation before save
│   └── validate (use frappe.throw on error)
│
├─► Action after successful save
│   └── after_save
│
├─► Calculation on field change
│   └── {fieldname}
│
├─► Child table row added
│   └── {tablename}_add
│
├─► Child table field changed
│   └── Child DocType event: {fieldname}
│
└─► One-time initialization
    └── setup or onload

→ See references/decision-tree.md for complete decision tree.

Implementation Workflows

Workflow 1: Dynamic Field Visibility

Scenario: Show "delivery_date" only when "requires_delivery" is checked.

frappe.ui.form.on('Sales Order', {
    refresh(frm) {
        // Initial state on form load
        frm.trigger('requires_delivery');
    },

    requires_delivery(frm) {
        // Toggle on checkbox change AND refresh
        frm.toggle_display('delivery_date', frm.doc.requires_delivery);
        frm.toggle_reqd('delivery_date', frm.doc.requires_delivery);
    }
});

Why both events?

  • refresh: Sets correct state when form opens
  • {fieldname}: Responds to user interaction

Workflow 2: Cascading Dropdowns

Scenario: Filter "city" based on selected "country".

frappe.ui.form.on('Customer', {
    setup(frm) {
        // Filter MUST be in setup for consistency
        frm.set_query('city', () => ({
            filters: {
                country: frm.doc.country || ''
            }
        }));
    },

    country(frm) {
        // Clear city when country changes
        frm.set_value('city', '');
    }
});

Workflow 3: Automatic Calculations

Scenario: Calculate total in child table with discount.

frappe.ui.form.on('Sales Invoice', {
    discount_percentage(frm) {
        calculate_totals(frm);
    }
});

frappe.ui.form.on('Sales Invoice Item', {
    qty(frm, cdt, cdn) {
        calculate_row_amount(frm, cdt, cdn);
    },

    rate(frm, cdt, cdn) {
        calculate_row_amount(frm, cdt, cdn);
    },

    amount(frm) {
        // Recalculate document total on row change
        calculate_totals(frm);
    }
});

function calculate_row_amount(frm, cdt, cdn) {
    let row = frappe.get_doc(cdt, cdn);
    frappe.model.set_value(cdt, cdn, 'amount', row.qty * row.rate);
}

function calculate_totals(frm) {
    let total = 0;
    (frm.doc.items || []).forEach(row => {
        total += row.amount || 0;
    });

    let discount = total * (frm.doc.discount_percentage || 0) / 100;
    frm.set_value('grand_total', total - discount);
}

Workflow 4: Fetching Server Data

Scenario: Populate customer details on customer selection.

frappe.ui.form.on('Sales Order', {
    async customer(frm) {
        if (!frm.doc.customer) {
            // Clear fields if customer cleared
            frm.set_value({
                customer_name: '',
                territory: '',
                credit_limit: 0
            });
            return;
        }

        // Fetch customer details
        let r = await frappe.db.get_value('Customer',
            frm.doc.customer,
            ['customer_name', 'territory', 'credit_limit']
        );

        if (r.message) {
            frm.set_value({
                customer_name: r.message.customer_name,
                territory: r.message.territory,
                credit_limit: r.message.credit_limit
            });
        }
    }
});

Workflow 5: Validation with Server Check

Scenario: Check credit limit before save.

frappe.ui.form.on('Sales Order', {
    async validate(frm) {
        if (frm.doc.customer && frm.doc.grand_total) {
            let r = await frappe.call({
                method: 'myapp.api.check_credit',
                args: {
                    customer: frm.doc.customer,
                    amount: frm.doc.grand_total
                }
            });

            if (r.message && !r.message.allowed) {
                frappe.throw(__('Credit limit exceeded. Available: {0}',
                    [r.message.available]));
            }
        }
    }
});

→ See references/workflows.md for more workflow patterns.

Integration Matrix

Client Script ActionRequires Server-side
Link filtersOptional: custom query
Fetch server datafrappe.db.* or whitelisted method
Call document method@frappe.whitelist() in controller
Complex validationServer Script or controller validation
Create documentfrappe.db.insert or whitelisted method

Client + Server Combination

// CLIENT: frm.call invokes controller method
frm.call('calculate_taxes')
    .then(() => frm.reload_doc());

// SERVER (controller): MUST have @frappe.whitelist
class SalesInvoice(Document):
    @frappe.whitelist()
    def calculate_taxes(self):
        # complex calculation
        self.tax_amount = self.grand_total * 0.21
        self.save()

Checklist: Implementation Steps

New Client Script Feature

  1. [] Determine scope

- UI/UX only? → Client script only - Data integrity? → Also server validation

  1. [] Choose events

- Use decision tree above - Combine refresh + fieldname for visibility

  1. [] Implement basics

- Start with frappe.ui.form.on - Test with console.log first

  1. [] Add error handling

- try/catch around async calls - frappe.throw for validation errors

  1. [] Test edge cases

- New document (frm.is_new()) - Empty field (null checks) - Child table empty/filled

  1. [] Translate strings

- All UI text in __()

Critical Rules

RuleWhy
refresh_field() after child table changeUI synchronization
set_query in setup eventConsistent filter behavior
frappe.throw() for validation, not msgprintStops save action
Async/await for server callsPrevent race conditions
Check frm.is_new() for buttonsPrevent errors on new doc

Related Skills

  • erpnext-syntax-clientscripts — Exact syntax and method signatures
  • erpnext-errors-clientscripts — Error handling patterns
  • erpnext-syntax-whitelisted — Server methods for frm.call
  • erpnext-database — frappe.db.* client-side API

→ See references/examples.md for 10+ complete implementation examples.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

37.79%
按下载量换算126

Claude

32.25%
按下载量换算107

Cursor

17.9%
按下载量换算60

Gemini CLI

9.19%
按下载量换算31

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills