mcpField
F
frappe-app-development

frappe-app-development

github.com/lubusin開発69303 回インストール12 週間前に更新
リポジトリ

frappe-app-development について

frappe-app-development は、カスタム Frappe アプリを設計・開発する開発者向けのスキルです。初期構成から本番運用の準備まで、レイヤー構成、フック、バックグラウンドジョブ、共通ユーティリティ、バージョン互換性を扱います。

主な機能

  1. 01アプリのひな形作成と構成計画
  2. 02hooks.py とサービス層の設定
  3. 03バックグラウンドジョブと共通ユーティリティ
  4. 04翻訳とバージョン互換性への対応
  5. 05検証とトラブルシューティングの案内

活用シーン

  1. 01カスタム Frappe アプリの新規作成
  2. 02DocType、サービス、業務ロジックの整理
  3. 03フックと非同期処理の追加
  4. 04インストール、マイグレーション、ジョブの問題確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/lubusin/frappe-skills --skill frappe-app-development

インストール後、Claude Code で/frappe-app-developmentを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/mini-app-template/your_app/
api.py
hooks.py
README.md
assets/mini-app-template/your_app/background_jobs/
sample_job.py
assets/mini-app-template/your_app/dashboard/
sample_doc_dashboard.json
assets/mini-app-template/your_app/doctype/sample_doc_item/
sample_doc_item.json
assets/mini-app-template/your_app/doctype/sample_doc/
sample_doc_dynamic_link.json
sample_doc_naming_series.json
sample_doc.js
sample_doc.json
sample_doc.py
assets/mini-app-template/your_app/doctype/sample_single/
sample_single.json
assets/mini-app-template/your_app/doctype/sample_submittable/
sample_submittable.json
assets/mini-app-template/your_app/doctype/sample_tree/
sample_tree.json
assets/mini-app-template/your_app/integrations/
sample_connector.py
assets/mini-app-template/your_app/list_view/
sample_doc_list.js
assets/mini-app-template/your_app/report/sample_report/
sample_report.js
sample_report.json
sample_report.py
assets/mini-app-template/your_app/services/
sample_service.py
assets/mini-app-template/your_app/utils/
cache.py
errors.py
logging.py
permissions.py
validation.py
assets/mini-app-template/your_app/workflow/
sample_doc_workflow.json
references/
app-development.md
translations.md
version-compat.md

詳細

Frappe アプリ開発

本番環境で使えるパターンに基づいて、カスタム Frappe アプリのひな形を作成し、構成・設計します。

使用する場面

  • 新しいカスタム Frappe アプリを一から作成する場合
  • アプリのアーキテクチャ(モジュール、サービス、ユーティリティ)を設定する場合
  • イベント、スケジューラ、オーバーライド用に hooks.py を設定する場合
  • バックグラウンドジョブと非同期処理を実装する場合
  • サービスレイヤーとドメインロジックのパターンを構築する場合
  • キャッシュ、ログ、エラーハンドリングのユーティリティを追加する場合
  • 本番環境へのデプロイに向けてアプリを準備する場合
  • 翻訳、バージョン管理、パッケージ化を行う場合

必要な入力

  • アプリ名と目的
  • 対象の Frappe バージョン(v13+、v15+、v16+)
  • モジュール構成(DocType、API、サービス)
  • 他のアプリのフック/オーバーライドが必要かどうか
  • バックグラウンドジョブの要件
  • 本番環境への対応要件

手順

0) アプリのひな形を作成する
# Create the app
bench new-app my_app

# Install on site
bench --site mysite.local install-app my_app

# Verify developer mode
bench --site mysite.local console
>>> frappe.conf.developer_mode  # Must be True
1) アプリの構成を計画する

ドメインアーキテクチャのパターンに従い、DocType コントローラーは薄く保ち、ビジネスロジックはサービスモジュールに記述します。

my_app/
├── my_app/
│   ├── __init__.py
│   ├── hooks.py              # App hooks and configuration
│   ├── api.py                # Public API surface (RPC endpoints)
│   ├── services/             # Business logic modules
│   │   └── billing.py
│   ├── utils/                # Cross-cutting utilities
│   │   ├── cache.py
│   │   ├── errors.py
│   │   ├── logging.py
│   │   ├── permissions.py
│   │   └── validation.py
│   ├── background_jobs/      # Async job handlers
│   │   └── export_job.py
│   ├── integrations/         # External system connectors
│   │   └── payment_gateway.py
│   ├── my_module/
│   │   ├── doctype/
│   │   │   └── my_doc/
│   │   │       ├── my_doc.json
│   │   │       ├── my_doc.py
│   │   │       ├── my_doc.js
│   │   │       └── test_my_doc.py
│   │   ├── report/
│   │   └── dashboard/
│   └── translations/
│       ├── en.csv
│       └── fr.csv
├── setup.py
└── README.md

出発点として、assets/mini-app-template/ の mini-app-template を使用します。

2) hooks.py を設定する
# hooks.py

app_name = "my_app"
app_title = "My App"
app_publisher = "My Company"

# DocType lifecycle events
doc_events = {
    "Sales Order": {
        "on_submit": "my_app.services.billing.on_order_submit",
        "on_cancel": "my_app.services.billing.on_order_cancel",
    },
    "*": {
        "after_insert": "my_app.utils.logging.log_creation",
    }
}

# Scheduled tasks
scheduler_events = {
    "daily": [
        "my_app.background_jobs.cleanup.run_daily_cleanup"
    ],
    "cron": {
        "0 */6 * * *": [
            "my_app.background_jobs.sync.sync_external_data"
        ]
    }
}

# Client-side script injection
doctype_js = {
    "Sales Order": "public/js/sales_order.js"
}

doctype_list_js = {
    "Sales Order": "public/js/sales_order_list.js"
}

# Override another app's controller (use sparingly)
# override_doctype_class = {
#     "ToDo": "my_app.overrides.custom_todo.CustomToDo"
# }

# Extend controller without full replacement (v16+, preferred)
# extend_doctype_class = {
#     "ToDo": "my_app.overrides.todo_extension.TodoExtension"
# }

# Override whitelisted methods
# override_whitelisted_methods = {
#     "frappe.client.get_list": "my_app.overrides.custom_get_list"
# }
3) サービスレイヤーを実装する

DocType コントローラーは薄く保ち、ビジネスロジックをサービスに委譲します。

# my_app/services/billing.py
import frappe

def on_order_submit(doc, method):
    """Handle order submission — called via doc_events hook."""
    if doc.grand_total > 10000:
        create_approval_request(doc)
    generate_invoice(doc)

def generate_invoice(order):
    """Create invoice from submitted order."""
    invoice = frappe.get_doc({
        "doctype": "Sales Invoice",
        "customer": order.customer,
        "items": [
            {"item_code": i.item_code, "qty": i.qty, "rate": i.rate}
            for i in order.items
        ]
    })
    invoice.insert()
    invoice.submit()
    return invoice
4) バックグラウンドジョブを設定する
# my_app/background_jobs/export_job.py
import frappe

def enqueue_export(filters):
    """Enqueue a long-running export job."""
    frappe.enqueue(
        "my_app.background_jobs.export_job.run_export",
        filters=filters,
        queue="long",
        timeout=600,
        is_async=True
    )

def run_export(filters):
    """Execute the export — runs in background worker."""
    data = frappe.get_all("Sales Order", filters=filters, fields=["*"])
    # Process data...
    frappe.publish_realtime("export_complete", {"count": len(data)})
5) 横断的なユーティリティを追加する
# my_app/utils/cache.py
import frappe

def get_cached_settings(key):
    """Cache expensive settings lookups."""
    value = frappe.cache().get_value(f"my_app:{key}")
    if value is None:
        value = frappe.db.get_single_value("My Settings", key)
        frappe.cache().set_value(f"my_app:{key}", value)
    return value

def invalidate_cache(key):
    frappe.cache().delete_value(f"my_app:{key}")
# my_app/utils/errors.py
import frappe

def api_error(message, status_code=400, exc=None):
    """Consistent error response for API endpoints."""
    frappe.local.response["http_status_code"] = status_code
    frappe.throw(message, exc or frappe.ValidationError)
6) 翻訳に対応する
# In Python code
frappe._("Hello World")   # Mark string for translation

# In JavaScript
__("Hello World")         # Mark string for translation
# Translation CSV files go in my_app/translations/
# e.g., my_app/translations/fr.csv:
# Hello World,Bonjour le monde
7) バージョン互換性
機能最小バージョン
extend_doctype_classFrappe v16+
REST API v2(/api/v2/)Frappe v15+
トークンベース認証Frappe v11.0.3+

複数のバージョンを対象にする場合は、バージョン固有の機能を条件分岐で保護します。

import frappe

if hasattr(frappe, 'extend_doctype_class'):
    # v16+ pattern
    pass
else:
    # Fallback for older versions
    pass

検証

  • アプリがエラーなしでインストールできる:bench --site <site> install-app my_app
  • フックが正しく実行される(スケジューラーログ、ドキュメントイベントを確認)
  • バックグラウンドジョブがキューに登録され、完了する
  • bench --site <site> migrate が成功する
  • テストが成功する:bench --site <site> run-tests --app my_app

失敗パターン/デバッグ

  • アプリが見つからない:apps.txt と sites/<site>/site_config.json を確認します
  • フックが実行されない:hooks.py の構文を確認し、bench を再起動します
  • バックグラウンドジョブが停止している:bench doctor でワーカーの状態を確認し、Redis を検証します
  • インポートエラー:hooks 内のモジュールパスが実際の Python パスと一致していることを確認します
  • 開発者モードがオフ:DocType の変更がファイルにエクスポートされません

エスカレーション

  • DocType 作成の詳細 → frappe-doctype-development
  • API エンドポイントのパターン → frappe-api-development
  • Desk UI のカスタマイズ → frappe-desk-customization
  • Frappe UI フロントエンド → frappe-frontend-development
  • 印刷フォーマットと Jinja → frappe-printing-templates
  • レポート → frappe-reports
  • Web フォーム → frappe-web-forms
  • テスト → frappe-testing
  • エンタープライズアーキテクチャ → frappe-enterprise-patterns
  • Docker/FM 環境 → frappe-manager

参考資料

相互参照(専門スキルが担当)
  • hooks.py と拡張ポイント → frappe-doctype-development(hooks-extensions.md)
  • Python API リファレンス → frappe-api-development(python-api.md)

ガードレール

  • カスタムフロントエンドには Frappe UI を使用してください:Vanilla JS、jQuery、カスタムフレームワークは使用しないでください。Frappe UI(Vue 3 + TailwindCSS)はエコシステムの標準です。セットアップについては frappe-frontend-development を参照してください。
  • CRUD アプリには CRM/Helpdesk のパターンに従ってください:公式の Frappe アプリをもとにしたアプリシェル、ナビゲーション、リストビュー、フォームレイアウトには、frappe-ui-patterns スキルを使用してください。
  • 命名規則に従ってください:アプリ名は小文字とアンダースコアのみを使用し、有効な Python 識別子にしてください。
  • 連携には hooks.py を使用してください:モンキーパッチは使用せず、doc_events、scheduler_events、boot_session フックを使用してください。
  • hooks.py をクリーンに保ってください:設定のみを記述し、ロジックは記述しないでください。モジュールからインポートしてください。
  • 後方互換性を維持してください:複数バージョンに対応するには、frappe.version によるチェックを使用してください。
  • フィクスチャを適切にエクスポートしてください:アプリと同期する必要があるデータには、hooks.py の fixtures を使用してください。

よくある間違い

間違い失敗する理由修正方法
installed_apps にアプリがないアプリのコードが読み込まれないbench --site <site> install-app my_app を実行してください
hooks のモジュールパスが間違っているイベントが発火しないパスが実際の my_app/module/file.py の構造と一致していることを確認してください
フックの登録が重複しているイベントが複数回発火するhooks.py に重複がないか確認し、キーを繰り返すのではなくリストを使用してください
再起動せずに hooks.py を編集する変更が反映されないhooks.py の変更後に bench restart を実行してください
__init__.py ファイルが不足しているモジュールのインポートエラーが発生するすべてのディレクトリに __init__.py があることを確認してください
hooks.py にロジックを記述するテストが難しくなり、インポートエラーが発生するロジックを別のモジュールに移し、フック内でインポートしてください
Vanilla JS/jQuery でフロントエンドを構築するエコシステムとの一貫性がなくなるFrappe UI(Vue 3)を使用してください。frappe-frontend-development を参照してください
CRUD アプリにカスタムアプリシェルを使用するUX に一貫性がなくなるナビゲーションとレイアウトには CRM/Helpdesk のパターンに従ってください

コメント