关于 generating-custom-field
用于生成和校验 Salesforce 自定义字段元数据的技能,提供避免 Metadata API 部署错误的规则,涵盖常见及计算字段,并重点处理主从关系和汇总字段约束。
主要功能
- 01字段元数据生成与校验
- 02常见字段类型规则
- 03主从关系约束
- 04汇总字段要求
- 05公式字段校验
- 06查找过滤器限制
适用场景
- 01创建 Salesforce 自定义字段
- 02设置 Lookup 或主从关系
- 03生成公式或汇总字段
- 04部署前检查字段元数据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill generating-custom-field安装后在 Claude Code 中输入/generating-custom-field确认已加载。
详细介绍
何时使用此技能
在需要以下操作时使用此技能:
- 在任意对象上创建自定义字段
- 为任意字段类型生成字段元数据
- 设置关系字段(查找关系或主从关系)
- 创建公式字段或汇总汇总字段
- 排查与自定义字段相关的部署错误
Salesforce 自定义字段生成器和验证器
概述
生成并验证 Salesforce 自定义字段元数据,并应用强制约束以防止部署错误。此技能特别关注失败率最高的字段类型:汇总汇总和主从关系。
规范
1. 目的
本文档定义了生成 CustomField 元数据 XML 时必须遵守的约束。Agent 必须在输出 XML 之前验证这些约束,以防止 Metadata API 部署错误。
重点关注领域:
- 汇总汇总字段格式错误
- 主从字段属性限制
- 查找过滤器限制
2. 通用必需属性
每个生成的字段都必须包含以下标签:
| 属性 | 要求 | 说明 |
|---|---|---|
<fullName> | 必需 | 根据 <label> 推导:每个单词首字母大写,将空格替换为 _,并追加 __c。必须以字母开头。例如,标签 Total Contract Value → Total_Contract_Value__c |
<label> | 必需 | UI 名称(标题式大小写) |
<description> | 必需 | 说明字段背后的业务“原因” |
<inlineHelpText> | 必需 | 为最终用户提供可操作的指导。内容必须比标签更有价值(例如,使用“输入含税的 USD 金额”,而不只是“金额”) |
外部 ID 配置
触发条件: 如果用户提到“集成”“导入数据”“外部系统 ID”或“来自 [System Name] 的唯一键”,则设置 <externalId>true</externalId>。
适用类型: Text、Number、Email
3. 技术交互:精度、小数位数和长度
为确保部署成功,请遵守以下数学约束:
精度与小数位数规则
precision是总位数;scale是小数位数- 规则:
precision ≤ 18且scale ≤ precision - 计算: 小数点左侧的位数 =
precision - scale
“固定 255”规则
对于标准 TextArea 类型,Metadata API 要求 <length>255</length>,即使此值无法在 UI 中配置。
可见行数
长文本/富文本和多选列表框必需设置此项,以控制 UI 高度。
4. 字段数据类型
4.1 简单属性类型
| 类型 | <type> 值 | 必需属性 |
|---|---|---|
| 自动编号 | AutoNumber | displayFormat(必须包含 {0})、startingNumber |
| 复选框 | Checkbox | 默认将 defaultValue 设为 false |
| 日期 | Date | 无需精度/长度 |
| 日期/时间 | DateTime | 无需精度/长度 |
| 电子邮件 | Email | 内置格式验证 |
| 查找关系 | Lookup | referenceTo、relationshipName、deleteConstraint |
| 主从关系 | MasterDetail | referenceTo、relationshipName、relationshipOrder |
| 数字 | Number | precision、scale |
| 货币 | Currency | 默认精度:18,小数位数:2 |
| 百分比 | Percent | 默认精度:5,小数位数:2 |
| 电话 | Phone | 统一电话号码格式 |
| 选项列表 | Picklist | 包含 valueSetDefinition 和 restricted 的 valueSet |
| 文本 | Text | length(最大 255) |
| 文本区域 | TextArea | <length>255</length> |
| 长文本 | LongTextArea | length、visibleLines(默认 3) |
| 富文本 | Html | length、visibleLines(默认 25) |
| 时间 | Time | 仅存储时间(不含日期) |
| URL | Url | 验证协议和格式 |
4.2 计算类型与多值类型
| 类型 | <type> 值 | 必需属性 |
|---|---|---|
| 公式 | 结果类型(例如,Number) | formula、formulaTreatBlanksAs |
| 汇总汇总 | Summary | 完整要求请参见第 6 节 |
| 多选列表 | MultiselectPicklist | valueSet、visibleLines(默认值为 4) |
4.3 专用类型
| 类型 | <type> 值 | 必需属性 |
|---|---|---|
| 地理位置 | Location | scale、displayLocationInDecimal |
选项列表的 restricted 规则
<valueSet> 中的 <restricted> 布尔值用于控制是否仅允许管理员定义的值。
- 如果用户未指定 → 默认设置为
<restricted>true</restricted>(受限,可避免选项列表值集过大导致的性能问题) - 如果用户明确表示选项列表应允许自定义/新值,或提到“不受限”或“开放” → 设置为
<restricted>false</restricted> - 受限选项列表最多可包含 1,000 个值(启用 + 未启用)
<valueSet>
<restricted>true</restricted>
<valueSetDefinition>
<sorted>false</sorted>
<value>
<fullName>Option_A</fullName>
<default>false</default>
<label>Option A</label>
</value>
</valueSetDefinition>
</valueSet>
5. 主从关系规则 ⭐ 至关重要
主从字段有严格的属性限制,与查找字段不同。违反这些规则会导致部署失败。
主从字段中禁止使用的属性
绝不可在主从字段中包含以下属性:
| 禁止的属性 | 原因 | 结果 |
|---|---|---|
<required> | 主从关系按设计始终为必需 | 部署错误 |
<deleteConstraint> | 主从关系始终级联删除 | 部署错误 |
<lookupFilter> | 仅支持用于查找字段 | 部署错误 |
主从关系与查找关系对比
| 属性 | 主从关系 | 查找关系 |
|---|---|---|
<required> | ❌ 禁止 | ✅ 可选 |
<deleteConstraint> | ❌ 禁止(始终为 CASCADE) | ✅ 必需(SetNull、Restrict、Cascade) |
<lookupFilter> | ❌ 禁止 | ✅ 可选 |
<relationshipOrder> | ✅ 必需(0 或 1) | ❌ 不适用 |
<reparentableMasterDetail> | ✅ 可选 | ❌ 不适用 |
<writeRequiresMasterRead> | ✅ 可选 | ❌ 不适用 |
❌ 错误示例 — 主从字段包含禁止的属性:
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Account__c</fullName>
<label>Account</label>
<type>MasterDetail</type>
<referenceTo>Account</referenceTo>
<relationshipName>Contacts</relationshipName>
<relationshipOrder>0</relationshipOrder>
<required>true</required>
<deleteConstraint>Cascade</deleteConstraint>
<lookupFilter>
<active>true</active>
<filterItems>
<field>Account.Type</field>
<operation>equals</operation>
<value>Customer</value>
</filterItems>
</lookupFilter>
</CustomField>
错误:
Master-Detail Relationship Fields Cannot be Optional or RequiredCan not specify 'deleteConstraint' for a CustomField of type MasterDetailLookup filters are only supported on Lookup Relationship Fields
✅ 正确示例 — 主从字段:
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Account__c</fullName>
<label>Account</label>
<description>Links this record to its parent Account</description>
<type>MasterDetail</type>
<referenceTo>Account</referenceTo>
<relationshipLabel>Child Records</relationshipLabel>
<relationshipName>ChildRecords</relationshipName>
<relationshipOrder>0</relationshipOrder>
<reparentableMasterDetail>false</reparentableMasterDetail>
<writeRequiresMasterRead>false</writeRequiresMasterRead>
</CustomField>
✅ 正确示例 — 查找字段(含可选属性):
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Related_Account__c</fullName>
<label>Related Account</label>
<description>Optional link to a related Account</description>
<type>Lookup</type>
<referenceTo>Account</referenceTo>
<relationshipLabel>Related Records</relationshipLabel>
<relationshipName>RelatedRecords</relationshipName>
<required>false</required>
<deleteConstraint>SetNull</deleteConstraint>
<lookupFilter>
<active>true</active>
<filterItems>
<field>Account.Type</field>
<operation>equals</operation>
<value>Customer</value>
</filterItems>
<isOptional>false</isOptional>
</lookupFilter>
</CustomField>
主从关系的其他规则
- 关系顺序: 对象中的第一个主从关系 =
0,第二个 =1 - 关系名称: 必须是复数形式的 PascalCase 字符串(例如,
Travel_Bookings) - 联结对象: 标准多对多关系使用两个主从字段(可启用汇总)
- 限制: 每个对象最多可有 2 个主从关系。更多关系请使用查找关系。
6. 汇总字段规则 ⭐ 至关重要
汇总字段的部署失败率最高。请严格遵循以下规则。
汇总字段的必需元素
| 元素 | 要求 | 格式 |
|---|---|---|
<type> | 必需 | 始终为 Summary |
<summaryOperation> | 必需 | count、sum、min 或 max |
<summaryForeignKey> | 必需 | ChildObject__c.MasterDetailField__c |
<summarizedField> | 有条件必需 | sum、min、max 时必需;count 时不需要 |
汇总字段中禁止使用的元素
绝不可在汇总字段中包含以下属性:
| 禁止的属性 | 原因 |
|---|---|
<precision> | 汇总字段继承被汇总字段的精度 |
<scale> | 汇总字段继承被汇总字段的小数位数 |
<required> | 不适用于汇总字段 |
<length> | 不适用于汇总字段 |
summaryForeignKey 和 summarizedField 的格式规则
重要: summaryForeignKey 和 summarizedField 都必须使用完全限定格式:
ChildObjectAPIName__c.FieldAPIName__c
判断逻辑:
summaryForeignKey=ChildObject__c.MasterDetailFieldOnChild__csummarizedField=ChildObject__c.FieldToSummarize__c
❌ 错误 — 汇总汇总字段的常见错误:
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Total_Amount__c</fullName>
<label>Total Amount</label>
<type>Summary</type>
<precision>18</precision>
<scale>2</scale>
<summaryOperation>sum</summaryOperation>
<summaryForeignKey>Order__c</summaryForeignKey>
<summarizedField>Amount__c</summarizedField>
</CustomField>
错误:
Can not specify 'precision' for a CustomField of type SummaryMust specify the name in the CustomObject.CustomField format (e.g. Account.MyNewCustomField)
✅ 正确 — 汇总汇总字段(SUM 操作):
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Total_Amount__c</fullName>
<label>Total Amount</label>
<description>Sum of all line item amounts</description>
<inlineHelpText>Automatically calculated from child line items</inlineHelpText>
<type>Summary</type>
<summaryOperation>sum</summaryOperation>
<summarizedField>Order_Line_Item__c.Amount__c</summarizedField>
<summaryForeignKey>Order_Line_Item__c.Order__c</summaryForeignKey>
</CustomField>
✅ 正确 — 汇总汇总字段(COUNT 操作):
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Line_Item_Count__c</fullName>
<label>Line Item Count</label>
<description>Count of related line items</description>
<inlineHelpText>Automatically calculated from child records</inlineHelpText>
<type>Summary</type>
<summaryOperation>count</summaryOperation>
<summaryForeignKey>Order_Line_Item__c.Order__c</summaryForeignKey>
</CustomField>
✅ 正确 — 汇总汇总字段(MIN 操作):
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Earliest_Due_Date__c</fullName>
<label>Earliest Due Date</label>
<description>Earliest due date among all line items</description>
<inlineHelpText>Shows the soonest deadline</inlineHelpText>
<type>Summary</type>
<summaryOperation>min</summaryOperation>
<summarizedField>Order_Line_Item__c.Due_Date__c</summarizedField>
<summaryForeignKey>Order_Line_Item__c.Order__c</summaryForeignKey>
</CustomField>
✅ 正确 — 汇总汇总字段(MAX 操作):
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Highest_Price__c</fullName>
<label>Highest Price</label>
<description>Maximum unit price among all line items</description>
<inlineHelpText>Shows the most expensive item</inlineHelpText>
<type>Summary</type>
<summaryOperation>max</summaryOperation>
<summarizedField>Order_Line_Item__c.Unit_Price__c</summarizedField>
<summaryForeignKey>Order_Line_Item__c.Order__c</summaryForeignKey>
</CustomField>
汇总汇总字段速查
| 操作 | 是否需要 summarizedField? | 用途 |
|---|---|---|
count | 否 | 统计子记录数量 |
sum | 是 | 累加数值 |
min | 是 | 查找最小值 |
max | 是 | 查找最大值 |
汇总汇总字段的前提条件
- 汇总汇总字段只能在主从关系中的父对象上创建
- 子对象必须具有指向此父对象的主从字段
- 汇总字段必须存在于子对象上
7. 公式字段规则
公式结果类型
公式本身不是一种类型。<formula> 标签会添加到 <type> 设置为结果数据类型的字段中:
Checkbox、Currency、Date、DateTime、Number、Percent、Text
公式 XML 生成规则
<formula>标签中的内容必须使用<![CDATA[ ... ]]>部分包裹。这样可以防止 XML 解析器将公式运算符(如&、<、>)解释为 XML 标记。- 如果公式文本本身包含字面序列
]]>,请拆分 CDATA 块进行转义,例如:<![CDATA[Text_Field__c & "]]]]><![CDATA[>"]]> - 绝不能使用名为
returnType的属性或标签。它在 Metadata API 中不存在。<type>标签用于定义公式结果的返回数据类型。
formulaTreatBlanksAs 规则
判断逻辑:
- 如果公式结果类型为
Number、Currency或Percent→ 设置<formulaTreatBlanksAs>BlankAsZero</formulaTreatBlanksAs> - 如果公式结果类型为
Text、Date或DateTime→ 设置<formulaTreatBlanksAs>BlankAsBlank</formulaTreatBlanksAs>
❌ 错误 — 将 Formula 用作类型:
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Calculated_Value__c</fullName>
<type>Formula</type>
<returnType>Number</returnType>
<formula>Field1__c + Field2__c</formula>
</CustomField>
✅ 正确 — 公式字段:
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Calculated_Value__c</fullName>
<label>Calculated Value</label>
<description>Sum of Field1 and Field2</description>
<type>Number</type>
<precision>18</precision>
<scale>2</scale>
<formula><![CDATA[Field1__c + Field2__c]]></formula>
<formulaTreatBlanksAs>BlankAsZero</formulaTreatBlanksAs>
</CustomField>
公式字段依赖项
引用其他字段的公式字段,如果所引用的字段不存在或尚未部署,部署就会失败。请确保在部署公式字段之前,已部署所有被引用的字段。
特定函数指南
| 函数 | 规则 |
|---|---|
TEXT() | 绝不能用于 Text 字段。如果字段本身已是 Text 类型,请移除 TEXT() 包装。 |
CASE() | 最后一个参数始终为默认值。参数总数必须为偶数(值-结果对 + 默认值)。 |
VALUE() | 只能用于 Text 字段。如果传入的参数是 Number,请移除 VALUE() 包装。 |
DAY() | 只能用于 Date 字段。如果使用 DateTime 字段,请先将其转换为 Date(例如,DAY(DATEVALUE(DateTimeField__c)))。 |
MONTH() | 只能用于 Date 字段。如果使用 DateTime 字段,请先将其转换为 Date(例如,MONTH(DATEVALUE(DateTimeField__c)))。 |
DATEVALUE() | 只能用于 DateTime 字段。如果使用 Date 字段,请移除 DATEVALUE() 包装。 |
ISPICKVAL() | 检查 Picklist 字段是否相等时必须使用此函数。绝不能对 Picklist 字段使用 ==。 |
ISCHANGED() | 使用 ISCHANGED() 检查字段值是否已更改。不要手动使用 PRIORVALUE() 进行比较。 |
8. 常见部署错误
| 错误消息 | 原因 | 修复方法 |
|---|---|---|
ConversionError: Invalid XML tags or unable to find matching parent xml file for CustomField | XML 注释放在根 <CustomField> 元素之前 | 移除 .field-meta.xml 文件中位于 <CustomField> 之前的 XML 注释(``) |
Field [FieldName] does not exist. Check spelling. | 引用的字段不存在或尚未部署 | 确认引用的字段存在,并且在此字段之前已部署 |
DUPLICATE_DEVELOPER_NAME | 对象上已存在该字段的 fullName | 使用唯一且符合业务需求的名称 |
MAX_RELATIONSHIPS_EXCEEDED | 对象上的主从关系字段超过 2 个,或查找关系字段超过 15 个 | 第 3 个及之后的主从关系改用查找关系;检查查找关系字段数量 |
| 保留关键字错误 | 使用了 Order__c、Group__c 等名称 | 重命名为 Status_Order__c 等 |
9. 验证清单
生成 CustomField XML 之前,请确认:
通用检查
-
<fullName>是否采用有效格式并以__c结尾? -
<description>和<inlineHelpText>是否都已填写且内容有意义? -
<label>是否采用标题大小写? - 根
<CustomField>元素之前是否没有 XML 注释(``)?(根元素之前的注释会导致 SDR 解析器出错)
主从关系字段检查 ⭐ 关键
- 是否未设置
<required>属性?(主从关系字段始终必填) - 是否未设置
<deleteConstraint>属性?(主从关系始终级联删除) - 是否未设置
<lookupFilter>块?(仅用于查找关系字段) -
<relationshipOrder>是否设为0或1? - 父对象的
<sharingModel>是否设为ControlledByParent?
查找关系字段检查
-
<deleteConstraint>是否设为SetNull、Restrict或Cascade? -
<relationshipName>是否采用复数 PascalCase?
汇总汇总字段检查 ⭐ 关键
- 是否未设置
<precision>属性? - 是否未设置
<scale>属性? -
<summaryForeignKey>是否采用ChildObject__c.MasterDetailField__c格式? - 对于 SUM/MIN/MAX:
<summarizedField>是否采用ChildObject__c.FieldName__c格式? - 对于 COUNT:是否未设置
<summarizedField>? - 子对象是否具有指向此父对象的主从关系字段?
公式字段检查
-
<type>是否设为结果类型(而非“Formula”)? -
<formula>内容是否用<![CDATA[ ... ]]>包裹? - 是否未设置
<returnType>属性?(Metadata API 中不存在该属性) - 对于数值结果,
<formulaTreatBlanksAs>是否设为BlankAsZero;对于文本或日期结果,是否设为BlankAsBlank? - 所有引用的字段是否都存在,并且在此字段之前已部署?
数值字段检查
-
scale ≤ precision是否成立? -
precision ≤ 18是否成立?
文本区域检查
- 对于 TextArea:是否明确包含
<length>255</length>? - 对于 LongTextArea/Html:是否设置了
<visibleLines>?
关系数量限制检查
- 对象上的主从关系是否不超过 2 个?
- 对象上的查找关系是否不超过 15 个?
命名检查
- API 名称是否未使用保留字(
Order、Group、Select等)? - API 名称在此对象上是否唯一?