关于 education-cloud-multi-campus-configure
面向 Salesforce 管理员的 Education Cloud 机构层级配置技能,可从输入内容解析结构,并创建或维护层级。更新时会对比现有 Account,仅应用确认的变更并验证结果。
主要功能
- 01从 PDF、URL、CSV 或文本解析层级
- 02支持任意深度的组织树
- 03创建并协调 Account 关系
- 04为各层级创建 Business Profile
- 05预览变更并验证层级关系
- 06报告额外节点但不自动删除
适用场景
- 01建立新的多校区层级
- 02重组后协调现有层级
- 03应用前审查拟议的 Account 变更
MCP 相关
该技能优先使用 headless-360 MCP 传输方式读取和写入 Salesforce Account 与 BusinessProfile。若不可用,可使用其他 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),使用同一读取操作进行探测,并选择第一个正常工作的方式,同时告知用户当前使用的传输方式。若没有任何方式可用,则停止并请用户连接一种;切勿编造结果。
范围
- 范围内:从 PDF/URL/文本/CSV 中解析包含任意数量层级(2 个或更多)的机构结构;新建(创建完整层级);更新/协调(将目标结构与组织当前层级进行比较,仅应用差异——添加新节点、重命名节点、将节点移动到其他父级下);通过 ParentId 创建具有父子关系的 Account 层级;为所有层级生成 Business Profile;根据父级链按需推导物化路径;验证父子关系;处理批量创建/更新期间的 API 错误
- 范围外:删除 Account 或 Business Profile 记录(具有破坏性——报告多余项;除非用户在步骤 7 中明确确认,否则不要删除);单层平面结构(无父子关系);非 Education Cloud 的账户管理;在层级节点之间迁移字段数据
所需输入
继续操作前,收集或推断以下信息:
- 组织结构来源(目标结构):PDF 文档路径、网站 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)作为输入——网页抓取结果可能不完整、不准确或已过时,而且部分机构网站会阻止抓取。如果 URL 未被阻止,仍可使用。然后获取并解析 HTML,提取层级信息
- 如果 URL 获取被阻止或失败:不要悄悄替换为其他来源(例如让搜索/研究 Agent 从 Wikipedia 或其他第三方网站获取信息)。停止并请用户提供替代内容——PDF、CSV,或从该机构自有网站粘贴的文本。客户必须始终清楚其层级结构实际依据的来源
- 如果是文本:直接解析用户消息
-
解析所需的层级结构
- 提取 System 名称(顶层)
- 确定所有现有层级(例如 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")——它不可用于记录。 - 选择逻辑:
- 如果恰好有一个非 Master 的
available:trueRecordType → 使用该条目。 - 如果有多个候选项 → 询问用户要使用哪个
developerName。 - 如果不存在非 Master RecordType → 这是缺失的前提条件,而非无解的情况(此技能独立运行时,如果之前未运行 EDU 设置技能,常会出现这种情况)。按照
references/account_recordtype_prerequisite.md操作:请用户提供/确认一个 Label,在创建前征得确认,通过 Tooling API 创建,并通过 cold-verify 验证available:true。
- 如果恰好有一个非 Master 的
- 将该条目的
recordTypeId保存到运行时变量recordTypeId中(此值必须从本组织的 describe 响应中解析得出,绝不能直接从技能中复制字面值)。步骤 6 中创建每个 Account 时都使用recordTypeId。
-
确定模式:全新设置还是更新
- 判断组织是否已有此层级结构:
- 如果用户表示这是首次构建,或不存在 System(根)Account → Case 1(全新设置)。
- 如果用户表示这是更新/重组,或提供了现有的 System(根)Account Id → Case 2(更新/对账)。
- 如果不明确,请询问:“这是全新的层级结构,还是对组织中现有结构的更新?如果已存在,请提供 System(根)Account Id(由上次运行的摘要打印)。”
- Case 1 → 跳至步骤 6,使用空的
existingTree(每个目标节点都是新建的)。 - Case 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 已解析。
- 新建:body 使用
RecordTypeId(Data API sObject POST 接受的字段)——不能使用嵌套的RecordType/DeveloperName对象,因为 sObject 新建端点会拒绝。值为步骤 3.5 中通过 describe 解析的recordTypeId变量 — 绝不能使用硬编码的 18 字符 Id。对于 System(仅限全新设置的顶层),完全省略ParentId(不要发送null)。存储返回的 Account ID:accountMap[NodeId] = response.body.id - 重命名:仅 patch
Name。移动:仅 patchParentId(步骤 5 中已拒绝循环)。 - 删除(仅当用户在步骤 6 中明确确认要移除 EXTRA 节点时):再次确认具体节点,然后删除。默认跳过。
- 每个级别/操作后打印进度:
[action] applied: [count] Accounts ([level name]) - 按照
references/error_handling.md处理 API 错误 - 重复处理所有级别 — 不要对级别数量或名称进行硬编码
- 用户在步骤 6 确认后,通过 Mechanism 中解析出的传输方式应用差异 — 新建/重命名/移动/删除的调用格式见
-
创建业务档案(仅限新建/已变更的 Account)
- 对于第 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] Business Profiles created and linked - 按照
references/error_handling.md处理 API 速率限制(使用指数退避重试)
- 对于第 7 步中创建且尚无业务档案的每个 Account:
-
验证层级结构(冷验证)
- 写入操作返回
success:true并不能证明成功。对每个受影响的 Account(已创建、已重命名、已移动及其父级),通过dispatch_readonly冷调用GET /services/data/v68.0/sobjects/Account/[Account Id];读取Name、ParentId、RecordTypeId。确认:ParentId指向预期的父级(System 的ParentId: null,且没有孤立节点);RecordTypeId与第 3.5 步解析出的值一致;RENAME/MOVE 已正确持久化。 - 至少抽查:最深层的叶节点(完整追溯至 System)+ 每个顶层分支中的一个节点 + 每个已重命名/移动的节点。
- 输出:
Hierarchy verification complete — [N] Accounts, parent chains valid, 0 orphans
- 写入操作返回
-
返回结构摘要(完成报告)
- 此报告描述实际创建/变更的内容(使用过去时),而非计划。以成功标题开头 — 例如,更新运行使用
# Institutional Hierarchy Expanded Successfully,新建设置使用# Institutional Hierarchy Created Successfully。如果提供了输出位置,必须实际调用文件写入工具,将报告写入该位置并命名为report.md— 不要只在聊天中打印报告内容并声称已保存;描述了但未写入的文件并不存在。否则直接显示报告。 - 显示层级可视化(使用第 3 步中的嵌套项目符号格式,参见
examples/hierarchy_visualization.md) - 显示各级别的总数:System(1)、第 1 级名称(N)、第 2 级名称(N)等。
- 对于更新模式,分类列出变更内容:已创建、已重命名、已移动、未变更以及任何未触及的额外项。
- 输出 System(根)Account Id,以便后续更新运行引用。
- 提供抽查选项:“是否要我显示特定节点的完整路径,或验证某个 account?”
- 如果用户要求抽查,则 GET 指定的 Account,然后沿
ParentId链逐级 GET 每个祖先,直至 System 根节点,并用/拼接它们的 Name,以显示物化路径(实时推导 — 无存储的路径字段)
- 此报告描述实际创建/变更的内容(使用过去时),而非计划。以成功标题开头 — 例如,更新运行使用
规则 / 约束
| 约束 | 原因 |
|---|---|
| 更新模式只变更差异部分 — 复用现有 Account,绝不重新创建 | 重新创建会产生重复项和孤立的 Business Profile;对账才是正确的维护方式 |
| 绝不自动删除 — 报告多余项,仅在用户针对每个节点明确确认后才删除 | 删除 Account 会级联删除其 Business Profile 及子项;此操作具有破坏性且不可逆 |
| System Account 没有 ParentId | 顶层 Account 无法引用父级 |
| 子项的 ParentId 必须指向其直接父级 Account | 保持树结构完整性 — 子项应关联直接父级,而非祖先 |
| 按深度优先顺序处理 CREATE;创建完成后再应用 MOVE/RENAME | 若父级尚不存在,ParentId 引用会失败 |
| 拒绝将节点移动到其自身后代之下的 MOVE 操作 | 循环会破坏树结构;Salesforce 也会抛出 CIRCULAR_DEPENDENCY |
| BusinessProfile 必须通过 AccountId 关联且仅关联一个 Account(1:1) | Education Cloud 的要求;绝不为现有 Account 创建第二个 Profile |
| 同一兄弟组中的所有 Account 名称必须唯一 | 差异匹配以父级内的名称为键;重复名称会导致对账结果不明确 |
在运行时通过 Account describe 解析 Account RecordType,绝不硬编码 — 从 recordTypeInfos 获取 recordTypeId;POST 使用 RecordTypeId(而非嵌套的 RecordType/DeveloperName) | 硬编码的 Id/DeveloperName 会与其他组织的信息静默不匹配;describe 是 RecordType 元数据的权威来源 |
| 遇到 API 速率限制时重试创建 Business Profile | 批量创建经常会触及速率限制;重试通常可以成功 |
| 实时推导物化路径(沿 ParentId 链向上遍历至根节点),而不是读取存储字段 | Account 上没有路径列;请求路径时,通过连接祖先 Names 并以 / 分隔来计算 |
| 支持任意数量的层级(2 层及以上) | 不要硬编码层级数量 — 解析源中出现的任意结构 |
headless-360 是所有 Account/BusinessProfile 读写操作的默认传输方式;仅在其未配置时,才回退到其他可用的 MCP 或经过身份验证的 sf CLI,并说明当前使用的传输方式 | 在可用时,确保组织身份验证使用会话绑定的 OAuth JWT;静默回退会让人无法得知实际执行变更所用的凭据/传输方式 |
| 请求的 URL 被阻止时,绝不静默替换为其他数据源 | 客户必须知道层级实际基于什么内容构建 — 请对方提供 PDF/CSV 或粘贴内容作为替代 |
BusinessProfile 上的 InstitutionType 是受管控的受限选项列表 — 对于不属于其分类体系的机构,应标记出来,不要猜测选项值 | 猜测选项值(或强行选择最接近的值)会歪曲机构的真实类别 |
注意事项
已知故障模式及其解决方案(名称变更/删除歧义、重复更新运行、分页、速率限制、解析歧义、缺少 Education Cloud 配置等),请参阅 references/gotchas.md。
输出要求
交付内容(新建配置):
- Account 记录:1 个 System + N 个 Campuses + N 个 Colleges + N 个 Departments(全部使用组织中解析出的 Account RecordType)
- BusinessProfile 记录:每个 Account 对应 1 个,通过
AccountId字段关联 - 层级可视化:以嵌套项目符号格式展示完整结构
- 验证摘要:确认所有父子关系均有效(物化路径按需从 ParentId 链推导,不持久化)
- System(根)Account Id:打印该 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 边缘情况:重复的同级名称、缩写、无父级的引用 |