generating-custom-field について
Salesforceのカスタム項目メタデータを生成・検証し、Metadata APIのデプロイエラーを防ぐためのルールを示すスキルです。一般的な項目型に加え、主従関係と集計項目の制約を重点的に扱います。
主な機能
- 01項目メタデータの生成と検証
- 02一般的な項目型のルール
- 03主従関係の制約
- 04集計項目の要件
- 05数式項目の検証
- 06ルックアップフィルターの制約
活用シーン
- 01Salesforceカスタム項目の作成
- 02Lookupまたは主従関係の設定
- 03数式項目や集計項目の生成
- 04デプロイ前の項目メタデータ確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill generating-custom-fieldインストール後、Claude Code で/generating-custom-fieldを入力して読み込まれたか確認します。
詳細
このスキルを使用する場面
次の作業が必要な場合に、このスキルを使用します。
- 任意のオブジェクトにカスタム項目を作成する
- 任意の項目タイプの項目メタデータを生成する
- リレーション項目(Lookup または Master-Detail)を設定する
- 数式項目または積み上げ集計項目を作成する
- カスタム項目に関するデプロイエラーをトラブルシューティングする
Salesforce カスタム項目ジェネレーターおよびバリデーター
概要
デプロイエラーを防ぐための必須制約に従って、Salesforce のカスタム項目メタデータを生成および検証します。このスキルでは、失敗率が最も高い項目タイプである積み上げ集計と主従関係に特に重点を置いています。
仕様
1. 目的
このドキュメントでは、CustomField メタデータ XML を生成するための必須制約を定義します。メタデータ API のデプロイエラーを防ぐため、エージェントは XML を出力する前にこれらの制約を確認する必要があります。
重要な重点領域:
- 積み上げ集計項目の形式エラー
- 主従関係項目の属性制限
- 参照検索条件の制限
2. すべての項目に必須の属性
生成するすべての項目には、次のタグを含める必要があります。
| 属性 | 要件 | 備考 |
|---|---|---|
<fullName> | 必須 | <label>から生成します。各単語の先頭を大文字にし、スペースを_に置き換え、末尾に__cを付けます。先頭は英字にする必要があります。例:ラベルがTotal Contract Valueの場合、Total_Contract_Value__c |
<label> | 必須 | UI 上の名前(タイトルケース) |
<description> | 必須 | この項目が必要な業務上の「理由」を記述します |
<inlineHelpText> | 必須 | エンドユーザーが実行できる具体的なガイダンスを記述します。ラベルに加えて有益な情報を提供する必要があります(例:「金額」だけでなく「税を含む金額を USD で入力してください」) |
外部 ID の設定
トリガー: ユーザーが「integration」、「importing data」、「external system ID」、または「unique key from [System Name]」に言及した場合は、<externalId>true</externalId>を設定します。
適用可能なタイプ: Text、Number、Email
3. 技術的な相互関係:精度、スケール、長さ
デプロイを確実に成功させるには、次の数学的制約に従ってください。
精度とスケールのルール
precisionは合計桁数、scaleは小数部の桁数です- ルール:
precision ≤ 18かつscale ≤ precision - 計算: 小数点の左側の桁数 =
precision - scale
「固定 255」のルール
標準の TextArea タイプでは、UI で設定できない場合でも、メタデータ API で<length>255</length>が必須です。
表示行数
UI の高さを制御するため、Long/Rich テキストおよび複数選択リストには必須です。
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 | valueSetとvalueSetDefinitionおよびrestricted |
| テキスト | 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、2 番目は1です - 関係名: 複数形のパスカルケース文字列である必要があります(例:
Travel_Bookings) - 中間オブジェクト: 標準的な多対多の関係には、2 つの主従項目を使用します(積み上げ集計が可能になります)
- 上限: オブジェクトあたり主従関係は最大 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>を設定します
❌ 誤り — type として 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() ラッパーを削除してください。 |
CASE() | 最後のパラメータは常にデフォルト値です。パラメータの総数は偶数でなければなりません (値と結果のペア + デフォルト)。 |
VALUE() | テキスト項目でのみ使用しなければなりません。数値がパラメータとして渡されている場合は、VALUE() ラッパーを削除してください。 |
DAY() | 日付項目でのみ使用しなければなりません。DateTime 項目が使用されている場合は、まず日付に変換してください (例: DAY(DATEVALUE(DateTimeField__c)))。 |
MONTH() | 日付項目でのみ使用しなければなりません。DateTime 項目が使用されている場合は、まず日付に変換してください (例: MONTH(DATEVALUE(DateTimeField__c)))。 |
DATEVALUE() | DateTime 項目でのみ使用しなければなりません。日付項目が使用されている場合は、DATEVALUE() ラッパーを削除してください。 |
ISPICKVAL() | 選択リスト項目の等価性をチェックする際に使用しなければなりません。選択リスト項目で == を絶対に使用しないでください。 |
ISCHANGED() | 項目の値が変更されたかどうかをチェックするには ISCHANGED() を使用します。PRIORVALUE() と手動で比較しないでください。 |
8. よくあるデプロイエラー
| エラーメッセージ | 原因 | 対処方法 |
|---|---|---|
ConversionError: Invalid XML tags or unable to find matching parent xml file for CustomField | ルートの <CustomField> 要素より前に XML コメントが配置されています | .field-meta.xml ファイル内で <CustomField> より前にある XML コメント(``)を削除します |
Field [FieldName] does not exist. Check spelling. | 参照先のフィールドが存在しないか、まだデプロイされていません | 参照先のフィールドが存在し、このフィールドより先にデプロイされていることを確認します |
DUPLICATE_DEVELOPER_NAME | フィールドの fullName がすでにオブジェクトに存在します | ビジネス上の用途に沿った一意の名前を使用します |
MAX_RELATIONSHIPS_EXCEEDED | オブジェクト上に Master-Detail フィールドが 2 個を超えているか、Lookup フィールドが 15 個を超えています | 3 個目以降の Master-Detail には Lookup を使用し、Lookup の数を確認します |
| 予約語エラー | Order__c、Group__c などを使用しています | Status_Order__c などに名前を変更します |
9. 検証チェックリスト
CustomField XML を生成する前に、次の項目を確認します。
共通の確認事項
-
<fullName>が有効な形式で、末尾が__cになっていますか? -
<description>と<inlineHelpText>の両方に、意味のある内容が設定されていますか? -
<label>がタイトルケースになっていますか? - ルートの
<CustomField>要素より前に XML コメント(``)はありませんか?(ルート要素より前のコメントは SDR のパーサーでエラーになります)
Master-Detail フィールドの確認事項 ⭐ 重要
-
<required>属性がありませんか?(Master-Detail は常に必須です) -
<deleteConstraint>属性がありませんか?(Master-Detail は常に連鎖削除されます) -
<lookupFilter>ブロックがありませんか?(Lookup フィールドでのみ使用します) -
<relationshipOrder>が0または1に設定されていますか? - 親オブジェクトの
<sharingModel>がControlledByParentに設定されていますか?
Lookup フィールドの確認事項
-
<deleteConstraint>がSetNull、Restrict、またはCascadeに設定されていますか? -
<relationshipName>が複数形のパスカルケースになっていますか?
ロールアップ集計フィールドの確認事項 ⭐ 重要
-
<precision>属性がありませんか? -
<scale>属性がありませんか? -
<summaryForeignKey>がChildObject__c.MasterDetailField__cの形式になっていますか? - SUM/MIN/MAX の場合、
<summarizedField>がChildObject__c.FieldName__cの形式になっていますか? - COUNT の場合、
<summarizedField>がありませんか? - 子オブジェクトに、この親オブジェクトへの Master-Detail フィールドがありますか?
数式フィールドの確認事項
-
<type>が戻り値の型に設定されていますか(「Formula」ではありません)? -
<formula>の内容が<![CDATA[ ... ]]>で囲まれていますか? -
<returnType>属性がありませんか?(Metadata API には存在しません) - 数値の戻り値には
<formulaTreatBlanksAs>がBlankAsZeroに、テキスト/日付の戻り値にはBlankAsBlankに設定されていますか? - 参照されるすべてのフィールドが存在し、このフィールドより先にデプロイされますか?
数値フィールドの確認事項
-
scale ≤ precisionになっていますか? -
precision ≤ 18になっていますか?
テキストエリアの確認事項
- TextArea の場合、
<length>255</length>が明示的に含まれていますか? - LongTextArea/Html の場合、
<visibleLines>が設定されていますか?
リレーションシップ上限の確認事項
- オブジェクト上の Master-Detail リレーションシップは 2 個以下ですか?
- オブジェクト上の Lookup リレーションシップは 15 個以下ですか?
命名の確認事項
- API 名に予約語(
Order、Group、Selectなど)が含まれていませんか? - API 名はこのオブジェクト上で一意ですか?