education-cloud-multi-campus-configure について
Salesforce 管理者向けに、Education Cloud の組織階層を作成・保守するスキルです。入力から構造を解析し、更新時は既存の Account と比較して、確認済みの変更だけを適用・検証します。
主な機能
- 01PDF、URL、CSV、テキストから階層を解析
- 02任意の深さの組織ツリーに対応
- 03Account の親子関係を作成・調整
- 04各階層に Business Profile を作成
- 05変更を事前表示して関係を検証
- 06余分なノードを報告し自動削除しない
活用シーン
- 01新しい複数キャンパス階層の構築
- 02組織再編後の既存階層の調整
- 03適用前に Account の変更案を確認
MCP 対応
Salesforce の Account と BusinessProfile の読み書きには、headless-360 MCP トランスポートを優先します。利用できない場合は、別の Salesforce MCP サーバーまたは認証済みの sf CLI を使用できます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill education-cloud-multi-campus-configureインストール後、Claude Code で/education-cloud-multi-campus-configureを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/hierarchy_visualization.mdoutput_examples.mdsample_hierarchy_input_edgecases.csvsample_hierarchy_input.csvreferences/account_recordtype_prerequisite.mddelta_computation.mderror_handling.mdfoundation_prerequisites.mdgotchas.mdhierarchy_parsing_rules.mdmcp-invocation.md詳細
Education Cloud マルチキャンパスの組織階層の設定
Salesforce 管理者向けに、組織階層の初期作成から継続的な保守まで、ライフサイクル全体を説明します。ドキュメント、URL、CSV、またはテキストから組織構造を解析し、階層をゼロから構築するか、組織内にすでに存在する構造と照合して差分のみを作成します。入力に基づいて、任意の数の階層レベル(例:システム → キャンパス → カレッジ → 学科、またはシステム → 地域 → キャンパス → 部門 → 学科)に対応します。親子関係を設定した Account レコードと、各レベルの Business Profile を作成または更新し、セマンティックナビゲーションのためのマテリアライズドパスをその場で導出して、結果を検証します。
仕組み
すべての Account/BusinessProfile の読み取りまたは書き込みでは、まず headless-360 を試してください。読み取りには dispatch_readonly、書き込みには dispatch を使用します(呼び出し形式、レスポンスエンベロープ、ステップごとの呼び出しについては references/mcp-invocation.md を参照してください)。最初の呼び出しの前に GET /services/data/vXX.0/limits を試してください。2xx の場合は、すべての処理をこの経路で行います。利用できない場合、または 4xx/5xx の場合は、同じ読み取りを使って、利用可能な別のトランスポート(別の Salesforce MCP サーバー、または認証済みの sf CLI)を試し、最初に正常に動作したものを使用して、使用中のトランスポートをユーザーに伝えてください。正常に動作するものがない場合は停止し、ユーザーに接続を依頼してください。結果を捏造してはいけません。
対象範囲
- 対象:任意の数の階層レベル(2 以上)を持つ組織構造を PDF/URL/テキスト/CSV から解析すること、新規設定(階層全体を作成)、更新/照合(希望する構造を組織内の現在の階層と比較し、差分のみを適用 — ノードの追加、ノード名の変更、別の親の下へのノードの移動)、ParentId による親子関係を使った Account 階層の作成、すべてのレベルの Business Profile の生成、親の連鎖からの必要に応じたマテリアライズドパスの導出、親子関係の検証、一括作成/更新中の API エラーへの対応
- 対象外:Account または Business Profile レコードの削除(破壊的操作 — 余分なレコードを報告し、ステップ 7 でユーザーが明示的に確認しない限り削除しない)、単一レベルのフラットな構造(親子関係なし)、Education Cloud 以外の Account 管理、階層ノード間のフィールドデータの移行
必須入力
作業を進める前に、以下の情報を収集するか推定してください。
- 組織構造のソース(希望する構造):PDF ドキュメントのパス、Web サイトの URL、CSV、またはプレーンテキストの説明
- システム名:最上位の組織システム名(例:「Riverside Community College System」)
- 階層レベル:存在するすべての組織レベル(キャンパス、カレッジ、学科、部門、地域など) — 解析から推定し、固定された 4 レベルの構造を想定しないでください
- モードのヒント(任意):初回の構築か、既存の階層の更新か。明記されていない場合は、ステップ 4 で判定してください。
- 既存のルート(更新モードのみ):現在の階層をたどるための System(ルート)Account Id。このスキルを以前に実行した場合は、サマリーにこの Id が表示されます(ステップ 10)。
特に指定がない場合のデフォルト:
- すべての Account のレコードタイプ:組織から解決し、ハードコードしないでください — ステップ 3.5 を参照
- Business Profile の作成:Business Profile がないすべての階層レベルで有効
- マテリアライズドパス:保存フィールドではありません — パスを表示する際に、Account の ParentId の連鎖を System ルートまでたどってその場で導出
- 命名規則:単語間のスペースを保ったタイトルケース
- 削除:自動では行いません — 組織内の余分なノードは報告し、削除しません
ユーザーが階層の完全な説明またはドキュメントを提供した場合は、レコードを作成または変更する前に構造を解析し、確認してください。
ワークフロー
すべてのステップは順番に実行してください。スキップしたり、順序を入れ替えたりしないでください。作業が妨げられた場合は停止し、不足している情報をユーザーに確認してください。
0. 基盤の前提条件を確認する — references/foundation_prerequisites.md に従います。組織エディション、Lightning Experience、Education Cloud ライセンス、実行ユーザーに割り当てられた Full Access、Education Cloud Foundation が有効であることを確認します(無効の場合は、確認してから有効化する手順で自己修復します)。すべての確認に合格するまで、ステップ 1 に進まないでください。
-
入力形式を確認する
- 組織構造のソースをユーザーに尋ねます。PDF のパス、URL、CSV、またはテキストの説明から選択できます。
- PDF の場合:Read ツールを使用してテキストを抽出します。
- CSV の場合:列
Name,LevelType,Level,ParentNameを読み込みます(想定される形式についてはexamples/sample_hierarchy_input.csvを、重複した名前、省略形、親参照の欠落例についてはexamples/sample_hierarchy_input_edgecases.csvを参照してください)。 - URL の場合:信頼できる構造化データセット(JSON/CSV)を優先する入力としてユーザーに推奨します。Web クロールの結果は不完全、不正確、または古い可能性があり、クロールをブロックする機関のサイトもあります。URL がブロックされていなければ、そのまま使用できます。その後、HTML を取得して解析し、階層情報を抽出します。
- URL の取得がブロックされた場合、または失敗した場合:別のソース(Wikipedia や他のサードパーティーサイトから情報を収集する検索/調査エージェントなど)で、ユーザーに知らせずに代用してはいけません。処理を止め、代わりのソースとして、PDF、CSV、または機関の公式サイトから貼り付けたテキストをユーザーに求めます。階層の構築に実際に使用されたソースを、顧客が把握できないままにしてはいけません。
- テキストの場合:ユーザーのメッセージから直接解析します。
-
希望する階層構造を解析する
- システム名(最上位)を抽出します。
- 存在する階層レベルをすべて特定します(例:Campus、College、Department、Division、Region など)。
- ソース内の入れ子構造/インデントに基づいて、各ノードの親子関係を構築します。
- 希望する構造をツリーとして保存します。各ノードには Name、Level、ParentNode 参照があります。
- 構造が曖昧な場合は、判断ロジックについて
references/hierarchy_parsing_rules.mdを参照します。 - 固定のレベル名を想定してはいけません — ソースに記載されているレベル名をそのまま使用します(Campus/Location/Site は同等、College/School/Faculty は同等、Department/Division/Program は同等です)。
-
希望する構造をユーザーに確認する
- 抽出した階層を入れ子の箇条書きで表示します。ボックス描画テンプレートと書式ルールについては
examples/hierarchy_visualization.mdを参照してください。 - 次のように尋ねます:「この構造で正しいですか?」(はい/変更する/いいえ)
- 「変更する」の場合:修正内容を確認し、再度表示します。
- 「いいえ」の場合:ワークフローを停止します。
- 抽出した階層を入れ子の箇条書きで表示します。ボックス描画テンプレートと書式ルールについては
3.5. 組織から Account RecordType を解決する
- RecordType Id や DeveloperName をハードコードしてはいけません。describe を使って、実行時に組織の実際の Account RecordType を解決します(
developerName/availableなどの RecordType メタデータは、通常の Account SOQL クエリでは公開されません。describe が正しい取得元です)。dispatch_readonlyを介してGET /services/data/v68.0/sobjects/Account/describeを実行します(references/mcp-invocation.mdを参照)。bodyからrecordTypeInfos配列を読み込みます。各エントリにはdeveloperName、name、recordTypeId、available、defaultRecordTypeMappingが含まれています。
developerNameに基づいて組織の機関/ビジネス用 RecordType を選択します(組織によって異なります。例:Business、Business_Accounts)。Masterエントリ(developerName = "Master")は選択不可のため無視します。- 選択ロジック:
available:trueの Master 以外の RecordType がちょうど 1 つの場合:それを使用します。- 候補が複数ある場合:どの
developerNameを使用するかユーザーに尋ねます。 - Master 以外の RecordType が存在しない場合:前提条件の不足であり、行き止まりではありません(このスキルが先行する EDU 設定スキルなしで単独実行された場合によく発生します)。
references/account_recordtype_prerequisite.mdに従い、ラベルをユーザーに求めるか確認し、作成前に確認を取り、Tooling API で作成してから、available:trueであることをコールド検証します。
- そのエントリの
recordTypeIdをランタイム変数recordTypeIdに格納します(これは今回の組織の describe 応答から解決した値であり、スキル内にリテラルとしてコピーしてはいけません)。ステップ 6 で Account を作成するたびにrecordTypeIdを使用します。
-
モードの判定:新規セットアップか更新か
- 組織にこの階層がすでにあるかどうかを判定します。
- ユーザーが初回の構築だと述べている場合、または System(ルート)Account が存在しない場合 → ケース 1(新規セットアップ)。
- ユーザーが更新/再編だと述べている場合、または既存の System(ルート)Account Id を提示している場合 → ケース 2(更新/照合)。
- 不明な場合は、次のように尋ねます。「この階層はまったく新しく作成するものですか、それとも組織内の既存階層を更新するものですか? 既存の場合は、System(ルート)Account Id(前回の実行時のサマリーに表示されたもの)を教えてください。」
- ケース 1 → 空の
existingTree(希望するノードはすべて新規)を使い、ステップ 6 に進みます。 - ケース 2 → ステップ 5 に進みます。
- 組織にこの階層がすでにあるかどうかを判定します。
-
(更新モード)現在の階層を読み込み、差分を算出する
- System Account Id から現在のツリーをたどり(
ChildAccountsを使って子を階層ごとに取得し、必要に応じて SOQL にフォールバックします)、兄弟グループ内で Name によって希望する構造と現在の構造を照合し、各ノードを再利用/CREATE/EXTRA/RENAME/MOVE に分類します。照合と循環の拒否に関する完全なアルゴリズムはreferences/delta_computation.mdを参照してください。 - 結果:CREATE/RENAME/MOVE アクションの差分リストと、EXTRA のレポート(余分なノードは報告するだけで、削除はしません)。差分がなく、名前変更や移動の要求もない場合は、組織の構造が希望する構造とすでに一致していることをユーザーに伝え、ステップ 9(検証)に進みます。
- System Account Id から現在のツリーをたどり(
-
書き込みの前にプレビューする
- レコードを書き込む前に、サマリーを表示します。新規セットアップではレベルごとの件数と RecordType を表示し、更新/照合では差分(作成/名前変更/移動/変更なし/余分なノード)を明示します。どちらのテンプレートも
examples/output_examples.mdを参照してください。 - EXTRA ノードがあり、ユーザーが削除を希望する場合、その削除は破壊的操作です。ステップ 7 でノードごとに明示的な確認を求めます。デフォルトでは残します。
- 「これらの変更を適用しますか?」と尋ねます(はい/いいえ)。「いいえ」の場合はワークフローを停止します。
- レコードを書き込む前に、サマリーを表示します。新規セットアップではレベルごとの件数と RecordType を表示し、更新/照合では差分(作成/名前変更/移動/変更なし/余分なノード)を明示します。どちらのテンプレートも
-
変更を適用する(作成/名前変更/移動)
- ユーザーがステップ 6 で確認したら、Mechanism で解決したトランスポートを介して差分を適用します。作成/名前変更/移動/削除の呼び出し形式は
references/mcp-invocation.mdのステップ 7 を参照してください。作成した各 Account について、返された Id を記録します。「保留中」/「適用予定の差分」の計画を示して終了してはいけません。確認を受けたら実行します。 - 順序が重要です:CREATE アクションは深さ優先で処理し、親を子より先に作成します。MOVE と RENAME は、親 Id が解決した後に適用します。
- 作成:リクエスト本文では
RecordTypeId(Data API の sObject POST が受け付けるフィールド)を使用します。sObject 作成エンドポイントが拒否する、ネストされたRecordType/DeveloperNameオブジェクトは使用しません。値には、ステップ 3.5 の describe から解決したrecordTypeId変数を使います。18 文字の Id をハードコードしてはいけません。System(最上位、新規セットアップのみ)の場合は、ParentIdを完全に省略します(nullを送信しないでください)。返された Account ID を保存します:accountMap[NodeId] = response.body.id - 名前変更:
Nameのみをパッチします。移動:ParentIdのみをパッチします(循環はステップ 5 ですでに拒否されています)。 - 削除(ステップ 6 でユーザーが EXTRA ノードの削除を明示的に確認した場合のみ):対象ノードをもう一度確認してから削除します。デフォルトではスキップします。
- 各レベル/アクションの後に進捗を出力します:
[action] applied: [count] Accounts ([level name]) - API エラーは
references/error_handling.mdに従って処理します。 - すべてのレベルで繰り返します。レベル数やレベル名をハードコードしないでください。
- ユーザーがステップ 6 で確認したら、Mechanism で解決したトランスポートを介して差分を適用します。作成/名前変更/移動/削除の呼び出し形式は
-
ビジネスプロフィールを作成する(新規作成/変更した Account のみ)
- Step 7 で作成した各 Account に、まだビジネスプロフィールがない場合:
{AccountId}を本文としてPOST /services/data/v68.0/sobjects/BusinessProfileを実行します(references/mcp-invocation.mdを参照)- (Name フィールドは Account から自動入力されるため、設定しないでください)
- すでにビジネスプロフィールがある Account(更新モードで再利用したノード)には、重複するビジネスプロフィールを作成しないでください。BusinessProfile と Account は 1 対 1 です。
InstitutionTypeに関する警告:ユーザーからビジネスプロフィールのInstitutionTypeを設定するよう求められた場合、これは管理対象の制限付き選択リスト(通常はPublic/Private/Charterのみで、拡張不可)であることを伝えてください。この K-12/高等教育の分類体系に当てはまらない教育機関(例:職業訓練校/専門学校、関連医療分野、サテライト/エクステンションキャンパス)には、適切な値がありません。推測したり、最も近い値を黙って選んだりせず、事前にユーザーへ伝え、このニュアンスを記録するために利用できる唯一の回避策としてDescriptionを提案してください。これは正式な分類フィールドの代わりにはなりません。- 出力:
[Total N] 件のビジネスプロフィールを作成し、リンクしました references/error_handling.mdに従って API のレート制限に対処します(指数バックオフで再試行)
- Step 7 で作成した各 Account に、まだビジネスプロフィールがない場合:
-
階層を検証する(コールド検証)
- 書き込み時の
success:trueは証明になりません。影響を受けた各 Account(作成、名前変更、移動したもの、およびその親)に対して、dispatch_readonly経由でコールドGET /services/data/v68.0/sobjects/Account/[Account Id]を実行し、Name、ParentId、RecordTypeIdを読み取ります。ParentIdが想定される親を参照していること(System のParentIdはnullで、孤立ノードがないこと)、RecordTypeIdが Step 3.5 で解決した値と一致すること、RENAME/MOVE が正しく反映されていることを確認します。 - 最低限、最も深いリーフ(System までの完全な経路)、トップレベルの各ブランチにつき 1 ノード、および名前変更/移動したすべてのノードをスポットチェックします。
- 出力:
階層の検証が完了しました — [N] 件の Account、親チェーンは有効、孤立ノード 0 件
- 書き込み時の
-
構造の概要を返す(完了レポート)
- このレポートでは、計画ではなく実際に作成/変更した内容を過去形で説明します。成功を示す見出しから始めてください。例:更新実行では
# Institutional Hierarchy Expanded Successfully、新規セットアップでは# Institutional Hierarchy Created Successfully。出力先が指定されている場合は、ファイル書き込みツールを呼び出して、実際にレポートをreport.mdとして書き込む必要があります。レポート本文をチャットに表示するだけで、保存したと主張しないでください。説明しただけで実際に書き込まれていないファイルは存在しません。それ以外の場合は、レポートを表示します。 - 階層の可視化を表示します(Step 3 の入れ子になった箇条書き形式。
examples/hierarchy_visualization.mdを参照) - レベルごとの合計件数を表示します:System(1)、レベル 1 の名前(N)、レベル 2 の名前(N)など。
- 更新モードでは、変更内容を作成、名前変更、移動、変更なし、未処理の追加項目に分けて表示します。
- System(ルート)Account ID を出力し、今後の更新実行で参照できるようにします。
- スポットチェックを提案します:「特定のノードまでの完全なパスを表示するか、Account を検証しましょうか?」
- ユーザーがスポットチェックを依頼した場合は、対象の Account を GET した後、
ParentIdチェーンをたどって System ルートまで各祖先を GET し、それらの Name を/でつないで、マテリアライズされたパスを表示します(保存済みのパスフィールドはなく、その場で導出します)
- このレポートでは、計画ではなく実際に作成/変更した内容を過去形で説明します。成功を示す見出しから始めてください。例:更新実行では
ルール/制約事項
| 制約事項 | 理由 |
|---|---|
| 更新モードでは差分のみを変更します。既存の Account を再利用し、再作成しません | 再作成すると重複や孤立した Business Profile が発生します。調整が適切なメンテナンス方法です |
| 削除は自動では行いません。余分な項目を報告し、ノードごとにユーザーが明示的に確認した場合にのみ削除します | Account を削除すると、その Business Profile と子要素も連鎖的に削除されます。破壊的で取り消しできません |
| System Account に ParentId はありません | 最上位の Account は親を参照できません |
| 子の ParentId は、直近の親 Account を参照する必要があります | ツリー構造の整合性を保つためです。子は祖先ではなく、直接の親にリンクします |
| CREATE は深さ優先順で処理し、作成後に MOVE/RENAME を適用します | 親がまだ存在しないと、ParentId の参照に失敗します |
| ノードを自身の子孫の下に移動する MOVE は拒否します | 循環するとツリーが破損し、Salesforce も CIRCULAR_DEPENDENCY をスローします |
| BusinessProfile は AccountId を介して、必ず 1 つの Account のみにリンクする必要があります(1:1) | Education Cloud で必須です。既存の Account に対して 2 つ目のプロファイルを作成してはいけません |
| すべての Account 名は、同じ兄弟グループ内で一意である必要があります | 差分の照合では親内の名前をキーにします。重複があると調整が曖昧になります |
Account RecordType は実行時に Account の describe から解決し、ハードコードしません。recordTypeInfos から recordTypeId を取得し、POST では RecordTypeId を使用します(ネストした RecordType/DeveloperName は使用しません) | Id/DeveloperName をハードコードすると、他の組織で誤って一致しても気づかない可能性があります。describe が RecordType メタデータの信頼できる情報源です |
| API のレート制限が発生した場合は、Business Profile の作成を再試行します | 一括作成ではレート制限に達することがよくあります。再試行で成功します |
| マテリアライズドパスは保存済みフィールドから読み込まず、その場で導出します(ParentId のチェーンをルートまでたどります) | Account にはパス列がありません。パスが要求されたときに、祖先の Name を / でつないで算出します |
| 任意の数の階層レベル(2 以上)をサポートします | レベル数をハードコードせず、ソースに含まれる構造をそのまま解析します |
すべての Account/BusinessProfile の読み取り/書き込みでは、headless-360 をデフォルトのトランスポートとして使用します。設定されていない場合に限り、利用可能な別の MCP または認証済みの sf CLI にフォールバックし、使用中のトランスポートを明示します | 利用可能な場合は、組織の認証にセッションにバインドされた OAuth JWT を使用できます。黙ってフォールバックすると、実際に変更を行った認証情報/トランスポートが分からなくなります |
| 要求された URL がブロックされた場合に、別のデータソースへ黙って置き換えてはいけません | 顧客は、実際に何をもとに階層が構築されたかを知る必要があります。代替として PDF/CSV の提供、または内容の貼り付けを依頼してください |
BusinessProfile の InstitutionType は、管理対象の制限付きピックリストです。分類体系に含まれない機関については値を推測せず、その旨を伝えてください | 値を推測したり、最も近いものを無理に選んだりすると、機関の実際のカテゴリを誤って表現することになります |
注意事項
既知の失敗ケースとその解決方法(名前変更/削除の曖昧さ、更新の重複実行、ページング、レート制限、曖昧な解析、Education Cloud のプロビジョニング不足など)については、references/gotchas.md を参照してください。
出力要件
成果物(新規セットアップ):
- Account レコード:System 1 件+Campus N 件+College N 件+Department N 件(すべて組織で解決された Account RecordType を使用)
- BusinessProfile レコード:Account ごとに 1 件。
AccountIdフィールドを介してリンク - 階層の可視化:完全な構造を示すネストされた箇条書き形式
- 検証の概要:すべての親子関係が有効であることの確認(マテリアライズドパスは ParentId のチェーンから必要に応じて導出し、永続化しません)
- System(ルート)Account Id:今後の更新実行で再利用できるように出力
成果物(更新/調整):差分のみ。作成、名前変更、移動、変更なしの Account 数、変更されていない余分な項目、新しい Account に追加された Business Profile、および同じ検証の概要を含めます。
新規セットアップおよび更新/調整の出力例については、examples/output_examples.md を参照してください。
リファレンスファイル一覧
| ファイル | 読むタイミング |
|---|---|
references/foundation_prerequisites.md | ステップ 0 — 組織のエディション、Lightning Experience、EDU ライセンス、権限セットの割り当て、Education Cloud Foundation の有効化。単独で実行する場合は毎回、ステップ 1 の前に実行します |
references/mcp-invocation.md | ステップ 3.5、5、7〜9 — すべての Account/BusinessProfile の読み取り/書き込みにおける、正確な dispatch/dispatch_readonly の呼び出し形式とレスポンスエンベロープ |
references/account_recordtype_prerequisite.md | ステップ 3.5 — 組織に Master 以外の Account RecordType が存在しない場合に、自己解決可能な前提条件として、その作成を確認または依頼します |
references/hierarchy_parsing_rules.md | ステップ 2 — 解析した構造が曖昧な場合(例:明示的なキャンパスの親がなく、大学名が表示されている場合) |
references/delta_computation.md | ステップ 5 — 望ましい階層と現在の階層を照合するための正確なマッチングアルゴリズム(再利用/CREATE/EXTRA/RENAME/MOVE)。循環の拒否を含みます |
references/error_handling.md | ステップ 7〜8 — Account の作成/パッチ適用中、または Business Profile の作成中に API エラーが発生した場合 |
references/gotchas.md | すべてのステップ — 既知の失敗要因とその解決策 |
examples/hierarchy_visualization.md | ステップ 3、10 — ユーザー向けの階層構造の要約を整形する場合 |
examples/output_examples.md | ステップ 6、10 — 書き込み前のプレビュー用テンプレート、および新規設定と更新/照合の完了レポート出力例 |
examples/sample_hierarchy_input.csv | ステップ 1 — CSV 入力の参考形式(Name,LevelType,Level,ParentName) |
examples/sample_hierarchy_input_edgecases.csv | ステップ 1 — CSV のエッジケース:重複する兄弟名、省略形、孤立した親参照 |