mcpField
E
enterprise-patterns

enterprise-patterns

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

enterprise-patterns について

本番向け Frappe アプリの設計スキルです。CRM、Helpdesk、HRMS など複数のエンティティを扱うシステムを開発する人向けに、ワークフロー、権限、監査履歴、SLA、割り当てキュー、通知、外部連携の設計パターンを解説します。

主な機能

  1. 01DocType とリンクによるエンティティ設計
  2. 02ワークフローと状態遷移の設計
  3. 03ロール・行単位の権限制御
  4. 04活動履歴と監査ログの記録
  5. 05SLA とエスカレーションの実装
  6. 06割り当てキューと外部連携の管理

活用シーン

  1. 01CRM や Helpdesk のデータモデル設計
  2. 02ロール別のワークフロー遷移設定
  3. 03変更や SLA 超過の追跡
  4. 04レコード割り当てと外部同期の調整

インストール

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

$npx skills add https://github.com/lubusin/frappe-skills --skill enterprise-patterns

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

同梱ファイル

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

references/
advanced-permissions.md
enterprise-patterns.md
integration-patterns.md
queue-patterns.md
sla-implementation.md
workflow-patterns.md

詳細

Frappe エンタープライズパターン

本番環境向けのエンタープライズアプリケーションを構築するためのアーキテクチャパターンです。

使用する場面

  • CRM、ヘルプデスク、HRMS、または同様の複数エンティティを扱うシステムを構築する場合
  • SLA に基づくワークフローを設計する場合
  • 割り当てとキュー管理を実装する場合
  • 監査証跡とアクティビティログを構築する場合
  • 外部システム(メール、テレフォニー、CRM)と連携する場合

必要な入力

  • システムの種類(CRM/ヘルプデスク/カスタム)
  • コアエンティティとリレーションシップ
  • SLA 要件
  • ワークフローの状態と遷移
  • 連携ポイント

手順

0) データモデルを設計する

明確で正規化された DocType から始めます。

Ticket (parent)
├── customer (Link: Customer)
├── assigned_to (Link: User)
├── status (Select: Open, In Progress, Resolved, Closed)
├── priority (Link: Priority)
├── sla (Link: SLA)
├── activities (Table: Ticket Activity)
└── response_by, resolution_by (Datetime)

主なパターン:

  • リレーションシップには Link フィールドを使用します
  • アクティビティ、タイムライン、明細項目には子テーブルを使用します
  • 対象 DocType が変わる場合は Dynamic Link を使用します
1) ステートマシンを実装する

オプション A:Workflow DocType

  • 状態とロールベースの遷移を設定した Workflow を作成します
  • 対象の DocType にリンクします

オプション B:送信フローに docstatus を使用する

docstatus意味
0下書き
1送信済み
2取消済み

オプション C:検証付きのカスタムステータスフィールド

def validate(self):
    allowed = self.get_allowed_transitions()
    if self.status not in allowed:
        frappe.throw(f"Cannot transition to {self.status}")
2) 権限を設定する

行レベルのフィルタリング:

  • User Permissions を使用してエンティティごとに制限します
  • Role Permissions と組み合わせます

RPC メソッドでは必ず再確認します:

@frappe.whitelist()
def update_ticket(name, status):
    doc = frappe.get_doc("Ticket", name)
    if not frappe.has_permission("Ticket", "write", doc):
        frappe.throw("Not permitted", frappe.PermissionError)
    doc.status = status
    doc.save()
3) アクティビティの履歴を構築する

Activity Log またはカスタム子テーブルを使用して変更を追跡します。

def on_update(self):
    if self.has_value_changed("status"):
        self.append("activities", {
            "action": "Status Change",
            "old_value": self._doc_before_save.status,
            "new_value": self.status,
            "timestamp": frappe.utils.now()
        })
4) SLA を実装する

SLA DocType:

SLA
├── entity_type (Link: DocType)
├── response_time (Duration)
├── resolution_time (Duration)
└── escalation_rules (Table: Escalation Rule)

作成時に SLA を適用する:

def after_insert(self):
    sla = get_applicable_sla(self)
    if sla:
        self.response_by = add_to_date(self.creation, hours=sla.response_time)
        self.resolution_by = add_to_date(self.creation, hours=sla.resolution_time)
        self.db_update()

違反を監視する(スケジュールジョブ):

def check_sla_breaches():
    tickets = frappe.get_all("Ticket", 
        filters={"status": ["not in", ["Resolved", "Closed"]]},
        fields=["name", "resolution_by"]
    )
    for t in tickets:
        if frappe.utils.now_datetime() > t.resolution_by:
            mark_sla_breached(t.name)
5) 割り当てとキュー

ラウンドロビン方式の割り当て:

def assign_next_agent(queue):
    agents = frappe.get_all("Queue Member",
        filters={"queue": queue, "available": 1},
        fields=["user", "current_load"],
        order_by="current_load asc"
    )
    if agents:
        return agents[0].user
    return None

自動割り当てには Assignment Rules DocType を使用します。

6) 通知とエスカレーション

次の通知用に Notification DocType を設定します:

  • SLA 違反が迫っている場合
  • 割り当てが変更された場合
  • ステータスが遷移した場合
  • 顧客から返信があった場合

エスカレーションチェーン:

Level 1 (0h): Notify assigned agent
Level 2 (4h): Notify team lead
Level 3 (8h): Notify manager
Level 4 (24h): Notify department head
7) 外部連携

integrations/ モジュールに集約します:

# my_app/integrations/email_connector.py
def sync_emails():
    # Fetch from Email Account
    # Create Communications
    # Link to Tickets

同期にはバックグラウンドジョブを使用します:

frappe.enqueue(
    "my_app.integrations.email_connector.sync_emails",
    queue="long",
    timeout=600
)

検証

  • すべてのロールでワークフローの遷移が機能する
  • API レベルで権限が適用される
  • アクティビティログにすべての変更が記録される
  • SLA の計算が正しい
  • 通知が適切に送信される
  • 連携の同期がエラーなく実行される

障害パターン/デバッグ

  • 権限の迂回:RPC メソッドに明示的な権限チェックがあることを確認します
  • SLA が適用されない:スケジュールジョブが実行されていることを確認します
  • アクティビティが記録されない:has_value_changed の使用方法を確認します
  • 通知が送信されない:Notification のルールとメールキューを確認します

エスカレーション

参考資料

ガードレール

  • CRM/ヘルプデスクの UI パターンに従います:CRUD アプリでは、公式 Frappe アプリのアプリシェル、ナビゲーション、リストビュー、フォームパターンを説明している ui-patterns スキルに従います。これにはサイドバーのレイアウト、クイックフィルター、カンバンビュー、詳細パネルが含まれます。
  • フロントエンドには Frappe UI を使用します:すべてのカスタムエンタープライズフロントエンドで Frappe UI(Vue 3 + TailwindCSS)を使用します。バニラ JS や jQuery は使用しません
  • ワークフローを慎重に設計します:実装前にすべての状態と遷移を整理し、ロールバック経路を考慮します
  • エッジケースに対応します:ワークフローで取消済み、一時停止、例外の状態を考慮します
  • 早期にパフォーマンスをテストします:大量データを扱う DocType や複雑なクエリの負荷テストを実施します
  • 負荷の高い処理にはバックグラウンドジョブを使用します:実行時間の長いタスクでウェブリクエストをブロックしないでください
  • 重要な処理をログに記録します:監査可能性を確保するために frappe.log_error() とアクティビティログを使用します

よくある間違い

間違い失敗する理由修正方法
複雑すぎるワークフロー保守が難しく、ユーザーが混乱します可能な限りワークフローを直線的に保ち、複雑なフローは分割します
インテグレーションでのエラー処理の欠如エラーが表面化せず、データの不整合が発生します外部呼び出しを try/except で囲み、エラーを記録し、再試行ロジックを実装します
ドキュメント更新時の競合状態データが破損しますロックには frappe.db.get_value(..., for_update=True) を使用します
タイムゾーンを考慮しない SLA世界各地のユーザーに対して計算が誤りますUTC で保存・比較し、frappe.utils.convert_utc_to_timezone を使用します
一括操作でキューを使用しないタイムアウトやメモリの問題が発生します多数のレコードを操作する場合は frappe.enqueue() を使用します
ロール名のハードコードロールの変更時に動作しなくなりますロール名には定数または設定を使用します
独自の UI パターンUX に一貫性がなくなり、ユーザーが混乱しますCRM/Helpdesk のアプリシェルを調査し、それに従います
フロントエンドにバニラ JS/jQuery を使用保守の負担が増え、エコシステムとの不整合が生じます必ず Vue 3 を使用した Frappe UI を使用します

コメント