mcpField
F
field-service-data-capture-reference-configure

field-service-data-capture-reference-configure

github.com/forcedotcom開発1.1k73 回インストール1 日前に更新
リポジトリ

field-service-data-capture-reference-configure について

Field Service のモバイル・オフラインフォーム向けに、Salesforce Data Capture Flow の作成とデプロイを支援するスキルです。コンポーネントのメタデータ、Repeater の利用法、データ操作の制約、デプロイ時の問題を扱います。

主な機能

  1. 01DataCaptureFlow メタデータ構造のガイド
  2. 02モバイル入力・選択コンポーネントのリファレンス
  3. 03Repeater の事前入力・反復・表示パターン
  4. 04レコード作成・更新・削除の制約
  5. 05デプロイとフォーム表示問題の調査

活用シーン

  1. 01Field Service のモバイルオフラインフォーム作成
  2. 02Repeater の項目を子レコードとして保存
  3. 03既存レコードのコレクションから行を事前入力
  4. 04Flow デプロイやモバイルフォーム表示の問題を調査

インストール

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

$npx skills add https://github.com/forcedotcom/sf-skills --skill field-service-data-capture-reference-configure

インストール後、Claude Code で/field-service-data-capture-reference-configureを入力して読み込まれたか確認します。

同梱ファイル

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

examples/
Data_Capture_All_Components.flow-meta.xml
DataCapture_Showcase.flow-meta.xml
Repeater_with_prepopulation.flow-meta.xml

詳細

クエリ用 Fs データキャプチャリファレンス

このスキルを使用するタイミング

Salesforce Data Capture Flow(processType DataCaptureFlow)を作成、編集、デプロイする場合に使用します。Field Service モバイル/オフラインフォーム向けです。runtime_service_fieldservice:dc* コンポーネントを使用する flow-meta.xml の作成、Repeater ループ(.AllItems)、主従関係の子レコードの永続化、見た目の調整(グラデーションバナー、進行状況バー、コールアウト)、FLS/権限セットを含むサポートオブジェクト、DataCaptureFlow のデプロイエラーのデバッグ、またはデプロイ済みフォームが FSL Mobile Forms タブに表示されない理由のトラブルシューティング(DDC/WorkPlan OWD と AssignedResource の共有が前提条件)に使用します。

ワークフロー

Salesforce Data Capture Flow スキル

processType: DataCaptureFlow を使用して Salesforce フロー(Field Service モバイル/オフラインフォーム)を作成、編集、デプロイします。


必須メタデータ(すべてのフロー)

<processType>DataCaptureFlow</processType>
<areMetricsLoggedToDataCloud>false</areMetricsLoggedToDataCloud>
<environments>Offline</environments>

省略可能な IsLlmTargetable カスタムプロパティを含める場合は、ブール値ではなく JSON 文字列にする必要があります。

<customProperties>
    <name>IsLlmTargetable</name>
    <value><stringValue>{&quot;value&quot;:&quot;false&quot;}</stringValue></value>
</customProperties>

<booleanValue>false</booleanValue> の形式ではデプロイできますが、有効化がブロックされ、次のエラーが発生します。The value of the IsLlmTargetable custom property's value field must be a string in JSON format。プロパティ自体を省略しても問題ありません。


XML 構造のルール

Salesforce の Flow スキーマではグループ化が必須です。同じ種類のすべての要素は、連続したひとつのブロック内に配置する必要があります。これに違反すると、Element X is duplicated at this location というエラーでデプロイが失敗します。

グループの順序は問いませんが、各グループ内の要素は隣接している必要があります。

  • すべての <choices> をまとめる
  • すべての <dynamicChoiceSets> をまとめる
  • すべての <screens> をまとめる
  • すべての <decisions> をまとめる
  • すべての <recordLookups> をまとめる
  • すべての <recordCreates> をまとめる
  • すべての <recordUpdates> をまとめる
  • すべての <loops> をまとめる
  • すべての <assignments> をまとめる
  • すべての <variables> をまとめる

実行順序は XML の順序ではなく、コネクタの参照によって決まります。


コンポーネントリファレンス

すべての拡張機能のプレフィックス:runtime_service_fieldservice:

コンポーネント拡張機能fieldType
短いテキストdcTextInputComponentInstance
長いテキストdcLongTextComponentInstance
メールdcEmailComponentInstance
電話dcPhoneComponentInstance
名前dcNameComponentInstance
数値dcNumericComponentInstance
カウンターdcCounterComponentInstance
日付dcDateComponentInstance
日付と時刻dcDateTimeComponentInstance
チェックボックスdcCheckboxComponentInstance
切り替えdcToggleComponentInstance
住所/GPSdcAddressComponentInstance
ルックアップdcLookupComponentInstance
静的画像dcFileViewComponentInstance
画像のアップロード(モバイル)dcUpImageComponentInstance
ファイルのアップロード(モバイル)dcUpFileComponentInstance
署名(モバイル)dcSignatureComponentInstance
単一選択リストdcPicklistComponentChoice
複数選択リストdcPicklistComponentMultiChoice
ラジオボタンdcRbGroupComponentChoice
チェックボックスグループdcCbGroupComponentMultiChoice
マトリックスdcMatrixComponentMultiChoice
表示テキスト(なし)DisplayText
セクション(なし)RegionContainer + Region
Repeater(なし)Repeater

注:<fieldType>Range</fieldType> は DataCaptureFlow で有効なスライダーの fieldType ではありません(Builder UI のリストに「Range/Slider」と表示されていても同様です)。このプロセスタイプでは、純粋なメタデータでスライダーを利用できません。dcNumeric または dcCounter を使用してください。forceContent:repeater(Lightning 汎用)と <fieldType>Repeater</fieldType>(FSL オフライン)は別物です。概念は共通していますが、XML は異なります。

ラベルの設定
fieldType方法
ComponentInstance<inputParameters><name>label</name><value><stringValue>…</stringValue></value></inputParameters>
ComponentChoice / ComponentMultiChoice<fieldText>Label</fieldText>
DisplayText<fieldText>HTML</fieldText>

すべての ComponentInstance 拡張(dcAddress や dcToggle を含む)は label inputParameter を受け付けます — DisplayText でラップする必要はありません。

必須フラグ

すべての入力フィールドには、フィールドレベルで <isRequired>true/false</isRequired> が必要です。この単一のフラグはすべての dc* コンポーネントに対して十分です — 追加の required / isRequired inputParameter は不要です。

dcLookup はさらに isRequired inputParameter(boolean)も受け付けますが、適用を制御するのはフィールドレベルの <isRequired> です。

dcCheckbox と dcToggle は <isRequired>true</isRequired> を構文的には受け付けますが、実行時には適用しません。

すべての入力フィールドには以下も必要です
<inputsOnNextNavToAssocScrn>UseStoredValues</inputsOnNextNavToAssocScrn>
<storeOutputAutomatically>true</storeOutputAutomatically>
<styleProperties>
    <verticalAlignment><stringValue>top</stringValue></verticalAlignment>
    <width><stringValue>12</stringValue></width>
</styleProperties>

例外: <fieldType>Repeater</fieldType> は storeOutputAutomatically を明示的に拒否します("the storeOutputAutomatically field isn't supported")。Repeater の出力は常に .AllItems として利用可能です — オプトインは不要です。


画面のルール

すべての画面には、以下の 3 つすべてが必要です。そうでなければ Next/Finish ボタンがレンダリングされません:

  • <allowFinish>true</allowFinish>(最終画面でなくても)
  • <showFooter>true</showFooter>
  • <nextOrFinishButtonLabel>Next</nextOrFinishButtonLabel>

さらに:

  • <start> の後の最初の要素は常に <screens> 要素でなければなりません
  • すべての <screens> 要素は XML 内でまとめてグループ化する必要があります

Repeater — 行の反復と子レコードの作成

Repeater の出力コレクションは .AllItems として公開されます。API v66 で動作を確認済みです。


<fields>
    <name>MyRepeater</name>
    <fieldType>Repeater</fieldType>
    
    <fields>
        <name>Row_PartName</name>
        <extensionName>runtime_service_fieldservice:dcTextInput</extensionName>
        <fieldType>ComponentInstance</fieldType>
        <storeOutputAutomatically>true</storeOutputAutomatically>
        
    </fields>
    <fields>
        <name>Row_PartQty</name>
        <extensionName>runtime_service_fieldservice:dcCounter</extensionName>
        <fieldType>ComponentInstance</fieldType>
        <storeOutputAutomatically>true</storeOutputAutomatically>
        
    </fields>
    <isRequired>false</isRequired>
</fields>


<loops>
    <name>Loop_Parts</name>
    <collectionReference>MyRepeater.AllItems</collectionReference>   
    <iterationOrder>Asc</iterationOrder>
    <nextValueConnector>
        <targetReference>Create_Part</targetReference>
    </nextValueConnector>
</loops>
<recordCreates>
    <name>Create_Part</name>
    <object>CustomFormPart__c</object>
    <connector>
        <targetReference>Loop_Parts</targetReference>   
    </connector>
    <inputAssignments>
        <field>PartName__c</field>
        <value>
            <elementReference>Loop_Parts.Row_PartName.value</elementReference>
            
        </value>
    </inputAssignments>
    <inputAssignments>
        <field>Quantity__c</field>
        <value>
            <elementReference>Loop_Parts.Row_PartQty.value</elementReference>
        </value>
    </inputAssignments>
    <storeOutputAutomatically>true</storeOutputAutomatically>
</recordCreates>

やってはいけないこと:

  • <collectionReference>MyRepeater</collectionReference> → Element "MyRepeater" doesn't exist
  • <collectionReference>MyRepeater.items</collectionReference> → 汎用サーバーエラー
  • <collectionReference>MyRepeater.data</collectionReference> → 汎用サーバーエラー
  • ループ本体の内部では、MyRepeater.Row_PartName.value は動作しません — Repeater の名前ではなく、ループの名前を使用する必要があります。

行をまたぐ検証はコンパイルされません。 r_GR4.AllItems[$Items].field.value や r_GR4.AllItems[$Items - 1].field.value のような数式参照は Syntax error で失敗します。行ごとの検証は、ネストされたフィールド自身の validationRule 内で通常の fieldName.value を使って動作します。行をまたぐルールには、画面後の loops + decisions を使用してください。

その他の Repeater アクセサーは現在解決されません。 動作するのは .AllItems のみです。AddedItems、PrepopulatedItems、RemovedItems はすべて doesn't exist でデプロイに失敗します。

既存のコレクションからリピーターに値を事前入力する

既存の SObject コレクションをリピーターにバインドすると、ソースレコードごとに値が事前入力された行が 1 つずつ表示されます。その後、ユーザーは送信前に行を編集、追加、削除できます。

パターン:recordLookups(ソースコレクションを取得し、getFirstRecordOnly=false、storeOutputAutomatically=true)→ collection inputParameter を介してバインドした Repeater のある画面 → ネストされたフィールドでは、SourceCollection[$EachItem].FieldApiName を value のデフォルト値として使用します。

<recordLookups>
    <name>Get_Source</name>
    <object>ServiceResource</object>
    <getFirstRecordOnly>false</getFirstRecordOnly>
    <storeOutputAutomatically>true</storeOutputAutomatically>
    <connector><targetReference>Screen_Repeater</targetReference></connector>
    
</recordLookups>


<fields>
    <name>accountRepeater</name>
    <fieldType>Repeater</fieldType>
    <inputParameters>
        <name>collection</name>                                
        <value><elementReference>Get_Source</elementReference></value>
    </inputParameters>
    <fields>
        <name>account_info</name>
        <fieldType>DisplayText</fieldType>
        <fieldText>&lt;p&gt;Id: {!Get_Source[$EachItem].Id}&lt;/p&gt;</fieldText>
        
    </fields>
    <fields>
        <name>name</name>
        <extensionName>runtime_service_fieldservice:dcTextInput</extensionName>
        <fieldType>ComponentInstance</fieldType>
        <inputParameters>
            <name>label</name>
            <value><stringValue>Name</stringValue></value>
        </inputParameters>
        <inputParameters>
            <name>value</name>
            <value><elementReference>Get_Source[$EachItem].Name</elementReference></value>
            
        </inputParameters>
        <isRequired>true</isRequired>
        <storeOutputAutomatically>true</storeOutputAutomatically>
        <inputsOnNextNavToAssocScrn>UseStoredValues</inputsOnNextNavToAssocScrn>
        <styleProperties>…</styleProperties>
    </fields>
    <isRequired>false</isRequired>
    <styleProperties>…</styleProperties>
</fields>

要点:

  • バインド用の inputParameter の名前は collection です。value や source ではありません。
  • リピーター内では、SourceCollectionName[$EachItem].FieldApiName を使ってソース行を参照します。リピーターの名前ではなく、レコードルックアップの名前を使用してください。DisplayText.fieldText({!Get_Source[$EachItem].Id} として)と、コンポーネントの value のデフォルト値(<elementReference>Get_Source[$EachItem].Name</elementReference> として)の両方で機能します。
  • $EachItem は、リピーターのレンダリング時に Salesforce が挿入する行ごとのイテレーターです。リピーター内にネストされたフィールド内でのみ解決されます。
  • 後続のループでは、通常どおり Repeater_Name.AllItems を反復処理します。事前入力によって変わるのは入力であり、出力アクセサーではありません。
  • 事前入力された行は、送信後に通常の .AllItems エントリとして表示されます。PrepopulatedItems と AddedItems のような分割はありません(これらのアクセサーを使うとデプロイに失敗します)。
リピーターのエントリをユーザーに表示する(リピーター後のループ画面)

ユーザーが入力した内容(レビュー、確認、行ごとの詳細など)を表示するには、リピーター画面の後に、本体を表示画面に接続したループを配置します。表示画面からはループに戻るよう接続します。ループの終了コネクターは次のステップに進みます。

<loops>
    <name>Loop_Through_Repeater</name>
    <collectionReference>accountRepeater.AllItems</collectionReference>
    <iterationOrder>Asc</iterationOrder>
    <nextValueConnector>
        <targetReference>Repeater_Output_Screen</targetReference>   
    </nextValueConnector>
    
</loops>

<screens>
    <name>Repeater_Output_Screen</name>
    <connector><targetReference>Loop_Through_Repeater</targetReference></connector>   
    <fields>
        <name>display_info</name>
        <fieldType>DisplayText</fieldType>
        <fieldText>&lt;p&gt;Source Id: {!Loop_Through_Repeater.UniqueField__Id}&lt;/p&gt;
&lt;p&gt;Name: {!Loop_Through_Repeater.name.value}&lt;/p&gt;
&lt;p&gt;Type: {!Loop_Through_Repeater.description.value}&lt;/p&gt;</fieldText>
        <styleProperties>…</styleProperties>
    </fields>
    <allowFinish>true</allowFinish>
    <showFooter>true</showFooter>
    <nextOrFinishButtonLabel>Next</nextOrFinishButtonLabel>
</screens>

ループ本体内のアクセサールール:

  • ユーザーが入力した値 — {!LoopName.nestedFieldName.value}(他の場合と同じ .value/.selectedChoiceValues/.isActive などのアクセサーです)。
  • 事前入力された行のソースレコード Id — {!LoopName.UniqueField__Id}。これはリピーターが各反復で公開する合成フィールドです。バインドされた collection に由来する行にのみ値が入り(ユーザーが追加した新しい行は空欄になります)。
  • ループ本体内では、リピーターの名前ではなくループの名前を使用してください。前述の標準的な .AllItems + Create パターンと同じルールです。

この .AllItems をループして表示するパターンは、Create/Update パターンと組み合わせられます。レビュー画面の表示に 1 つのループを使い、CUD に後続のループ(または順序上問題がなければ同じループ)を使います。CUD のルールを忘れないでください。連続する CUD ノードの間には、何も(画面、取得、判定など)置けません。そのため、レビュー用ループは CUD チェーンの開始前に完全に完了する必要があります。


CUD のルール(プラットフォーム上の厳格な制約)

  • Decision で開始する CUD チェーンを選択できます(たとえば、保存モードを判定する Decision の Create 分岐と Update 分岐)。ただし、CUD チェーンの開始後、連続する CUD ノードの間に Decision を配置することはできません。配置すると、Append multiple Create, Update, or Delete operations only at the end of the flow, in any order というエラーでデプロイに失敗します。
    • 回避策:「入力がある場合のみ作成する」には、常に作成する(空の行を許容する)か、CUD チェーンの開始前に条件ロジックを移動してください。
  • すべての CUD はフローの末尾に配置します。 いずれかの CUD の後に Get Records や画面を配置してはいけません。CUD を含むサブフローも配置できません。
  • ループ内の CUD 後の Assignment は v260 で不具合がありました。 v262/API 66 で修正されています。現在は安全に使用できます。

Counter パラメーター

<inputParameters><name>min</name><value><numberValue>1.0</numberValue></value></inputParameters>
<inputParameters><name>max</name><value><numberValue>10.0</numberValue></value></inputParameters>
<inputParameters><name>step</name><value><numberValue>1.0</numberValue></value></inputParameters>
<inputParameters><name>minCustomErrorMessage</name><value><stringValue>…</stringValue></value></inputParameters>
<inputParameters><name>maxCustomErrorMessage</name><value><stringValue>…</stringValue></value></inputParameters>

Date パラメーター

<inputParameters><name>minDate</name><value><elementReference>$Flow.CurrentDate</elementReference></value></inputParameters>
<inputParameters><name>maxDate</name><value><dateValue>2027-12-31</dateValue></value></inputParameters>

Picklist のコンパクトモード

すべてのラベルが 8 文字以下で、かつ選択肢が 5 個以下の場合に限り、isCompact=true を使用してください。

Lookup パラメーター

<inputParameters><name>objectApiName</name><value><stringValue>Asset</stringValue></value></inputParameters>
<inputParameters><name>searchedFields</name><value><stringValue>Name, SerialNumber</stringValue></value></inputParameters>
<inputParameters><name>isMultiSelection</name><value><booleanValue>true</booleanValue></value></inputParameters>
<inputParameters><name>recordIdCollection</name><value><elementReference>v_Ids</elementReference></value></inputParameters>
recordIdCollection — 検索対象の絞り込み
  • ビルダーのラベル: Record IDs Collection。XML 属性: recordIdCollection(単数形の recordId に Collection を付加)。recordIds を指定すると、デプロイ時に We can't find this input attribute: "recordIds" というエラーが発生します。
  • これは絞り込みフィルターであり、デフォルトの事前選択ではありません。 指定した Id の String コレクション内だけを検索するように絞り込みます。
  • isMultiSelection=true の場合にのみ有効です。 単一選択モードでは無視され、ユーザーにはフィルターされていないオブジェクト全体が表示されます。
  • 標準的なパターン:recordLookups(絞り込んだサブセット)→ loops + assignments(Id の String コレクションを構築)→ dcLookup recordIdCollection=v_Ids を指定した画面。この方法は Briefcase で事前に読み込まれたデータに対してオフラインで動作し、約 60,000 件のレコードを 1 秒未満で処理できます。
  • 複数選択モードでの出力は {!Lookup.recordIds}(String コレクション)です。以前 {!Lookup.recordId}(単数形)を使用していた表示ルールや DML では、コレクションを反復処理するか、最初の要素を取得する必要があります。
dcLookup の表示ラベル

dcLookup には表示フィールドの入力パラメーターがありません(displayField/primaryField はありません)。検索結果と選択済みチップに表示されるラベルは、オブジェクトの Primary Compact Layout によって決まります。そのレイアウトの先頭フィールドが使用されます。変更するには、Setup → Object Manager → Object → Compact Layouts の順に開き、順序を変更して Primary として割り当てます(組織全体に適用される変更です)。searchedFields は検索対象を制御するものであり、表示内容は制御しません。

フロー内で代替する場合は、dcLookup を、<displayField>/<valueField> を指定した dynamicChoiceSets を使用する dcPicklist に置き換えます。

GPS 付き住所

<inputParameters><name>useCoordinates</name><value><booleanValue>true</booleanValue></value></inputParameters>

マトリックス

<inputParameters><name>questions</name><value><stringValue>["Q1","Q2","Q3"]</stringValue></value></inputParameters>

JSON 文字列内の & は &amp; としてエスケープしてください。

2 列セクション

<fields>
    <name>MySection</name>
    <fieldText>Section Header</fieldText>
    <fieldType>RegionContainer</fieldType>
    <fields>
        <name>MySection_Col1</name>
        <fieldType>Region</fieldType>
        <fields></fields>
        <inputParameters><name>width</name><value><stringValue>6</stringValue></value></inputParameters>
        <isRequired>false</isRequired>
    </fields>
    <fields>
        <name>MySection_Col2</name>
        <fieldType>Region</fieldType>
        <fields></fields>
        <inputParameters><name>width</name><value><stringValue>6</stringValue></value></inputParameters>
        <isRequired>false</isRequired>
    </fields>
    <isRequired>false</isRequired>
    <regionContainerType>SectionWithHeader</regionContainerType>
    …styleProperties…
</fields>

表示ルール

<visibilityRule>
    <conditionLogic>and</conditionLogic>
    <conditions>
        <leftValueReference>componentName.value</leftValueReference>
        <operator>GreaterThan</operator>
        <rightValue><numberValue>0.0</numberValue></rightValue>
    </conditions>
</visibilityRule>

プロパティアクセサー:.value(dcCheckbox を含む入力コンポーネント)、.selectedChoiceValues(選択肢コンポーネント)、.isActive(トグル)、.firstName/.lastName(Name コンポーネント)、.recordId/.recordIds(Lookup の単一選択/複数選択)。

同じアクセサーは、recordCreates/recordUpdates の inputAssignments 内でも使用します。例:<elementReference>new_Reading.value</elementReference>。

条件付きで非表示になる必須項目 — isRequired ではなく validationRule を使用
IF(TriggerField.selectedChoiceValues = "Yes",
   AND(NOT(ISBLANK(value)), value >= 0, value <= 100000),
   TRUE)
標準的な Decision の IsNull パターン

IsNull の右辺には null リテラルではなく、booleanValue を指定します。

<conditions>
    <leftValueReference>v_ParentId</leftValueReference>
    <operator>IsNull</operator>
    <rightValue>
        <booleanValue>false</booleanValue>   
    </rightValue>
</conditions>

計算のタイミング(重要)

計算値は、入力を収集する画面には表示できません。計算はユーザーが「次へ」をタップした後にのみ実行されます。パターン:

Screen N (collect inputs) → recordLookups / assignments / decisions → Screen N+1 (display results)

画面 N のコネクターは、画面 N+1 ではなく計算要素を指す必要があります。すべての Decision 分岐は、最終的に画面 N+1 に合流する必要があります。


DisplayText の数式の制限(モバイルランタイム)

DataCaptureFlow の DisplayText は、標準フローと比べて数式のサポートが 大幅に制限されています。複雑な数式は正常にデプロイされ、ビルダーのプレビューにも表示されますが、実行時に Error while resolving default value reference というエラーが発生します。

実行時に失敗するもの:

  • IF(Toggle.isActive, "YES", "NO") — コンポーネントのプロパティに対する IF/CASE はすべて失敗します
  • TEXT(CASE(...))、ADDMONTHS(...)、ネストされた日付計算
  • 1 つの fieldText 内で複数のコンポーネント参照と数式を組み合わせること

動作するもの:

  • 単純な単一変数:{!var_RiskScore}
  • 単純なコンポーネント参照:{!MyPicklist.selectedChoiceValues}、{!MyNumeric.value}
  • グローバル変数:{!$Flow.CurrentDate}、{!$User.FirstName}

パターン:<assignments> 要素で事前に計算し、変数に格納してから、その変数を DisplayText で参照します。

入力 value のデフォルト値としてのグローバル変数
デフォルトのバインド変数動作するか
dcTextInput$User.Username✅
dcTextInput$User.Name❌ 型の不一致エラー
dcDateTime$Flow.InterviewStartTime✅
dcDate$Flow.CurrentDate✅

選択肢セットの記録(dynamicChoiceSets)— モバイルのオフライン環境での注意点

dynamicChoiceSets 内の <outputAssignments> は問題なくデプロイできますが、モバイルのオフライン DataCaptureFlow では、実行時に対象の変数へ確実に値が設定されるわけではありません。後続の画面が空白で表示されます。

正しいパターン:選択肢セットは最小限(displayField、valueField、filters、object、dataType)に保ちます。選択画面の後に、Id = {!picklistName.selectedChoiceValues} で絞り込んだ recordLookups を経由し、ルックアップの outputAssignments を使って追加の項目を変数に格納します。ルックアップが選択画面と表示画面の間に配置されるため、計算タイミングのルールにも自然に沿います。

<recordLookups>
    <name>gr_SelectedChild</name>
    <filters>
        <field>Id</field>
        <operator>EqualTo</operator>
        <value><elementReference>pl_Child.selectedChoiceValues</elementReference></value>
    </filters>
    <getFirstRecordOnly>true</getFirstRecordOnly>
    <object>Child__c</object>
    <outputAssignments>
        <assignToReference>v_SelectedValue</assignToReference>
        <field>Reading_Value__c</field>
    </outputAssignments>
</recordLookups>

見た目を整えるパターン(モバイル実行環境での表示を確認済み)

Lightning Design System のカラー:#2E844A(緑)、#0176D3(青)、#FE9339(オレンジ)、#C9C7C5(ニュートラル)。

ヒーローバナー
<div style="background: linear-gradient(135deg, #2E844A 0%, #0176D3 100%); color: white; padding: 20px; border-radius: 10px; text-align: center;">
  <p style="margin: 0; font-size: 22px;"><strong>🔧 Site Visit Report</strong></p>
  <p style="margin: 4px 0 0 0; font-size: 13px;">Subtitle</p>
</div>
プログレスバー(画面ごと)
<p><b>Step X of N – 📍 Section Title</b></p>
<div style="width: 100%; height: 8px; background-color: #C9C7C5; border-radius: 4px; margin: 5px 0;">
  <div style="width: PERCENT%; height: 100%; background: linear-gradient(90deg, #2E844A 0%, #0176D3 100%); border-radius: 4px;"></div>
</div>

カウンターとタイトルの区切りには、ハイフンではなくエンダッシュ –(U+2013)を必ず使用してください。

コールアウトボックス

<div style="background-color: #EAF5FE; border-left: 4px solid #0176D3; padding: 10px 14px; border-radius: 4px;">
  <p style="margin: 0; color: #014486; font-size: 13px;"><b>ℹ️ Info:</b> …</p>
</div>

<div style="background-color: #FFF4E6; border-left: 4px solid #FE9339; padding: 10px 14px; border-radius: 4px;">
  <p style="margin: 0; color: #704D00; font-size: 13px;"><b>⚠️ Heads up:</b> …</p>
</div>

<div style="background-color: #E8F5E9; border-left: 4px solid #2E844A; padding: 10px 14px; border-radius: 4px;">
  <p style="margin: 0; color: #1B5E20; font-size: 13px;"><b>✅ Ready:</b> …</p>
</div>
レビューカード(前の画面の差し込み項目を使用)
<div style="border: 1px solid #DDDBDA; border-radius: 8px; padding: 14px 16px; background-color: #FAFAF9;">
  <p style="margin: 0 0 8px 0; color: #0176D3; font-size: 14px;"><b>📍 Section</b></p>
  <p style="margin: 2px 0;"><b>Name:</b> {!Input_SiteName.value}</p>
  <p style="margin: 2px 0;"><b>Contact:</b> {!Input_Contact.firstName} {!Input_Contact.lastName}</p>
  <p style="margin: 2px 0;"><b>Priority:</b> {!Input_Priority.selectedChoiceValues}</p>
  <p style="margin: 2px 0;"><b>After-hours:</b> {!Input_Toggle.isActive}</p>
</div>

<fieldText> 内の HTML はすべて XML エスケープする必要があります:& → &amp;、" → &quot;、< → &lt;、> → &gt;。


フローと一緒に関連オブジェクトをデプロイする

カスタムオブジェクトと項目をデプロイしても、システム管理者プロファイルに FLS/CRUD が自動的に付与されることはありません。管理者として実行されるフローでも、新しい項目を読み書きできません。PermissionSet を用意して割り当ててください:


<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>My Object Access</label>
    <license>Salesforce</license>
    <hasActivationRequired>false</hasActivationRequired>
    <objectPermissions>
        <allowCreate>true</allowCreate><allowDelete>true</allowDelete>
        <allowEdit>true</allowEdit><allowRead>true</allowRead>
        <modifyAllRecords>true</modifyAllRecords><viewAllRecords>true</viewAllRecords>
        <object>MyObject__c</object>
    </objectPermissions>
    <fieldPermissions><field>MyObject__c.MyField__c</field><editable>true</editable><readable>true</readable></fieldPermissions>
    <tabSettings><tab>MyObject__c</tab><visibility>Visible</visibility></tabSettings>
</PermissionSet>

デプロイ後に割り当てます:sf org assign permset --name MyObject_Access --target-org <alias>

CustomObject に関する注意点
  • 主従関係の子オブジェクトには <sharingModel>ControlledByParent</sharingModel> が必要です。設定しないと Must specify a sharing model value が発生します。
  • Sfdx の取得では、標準ではないアクション(Automation、Details)の actionOverrides が含まれることがあります。再デプロイ前に削除してください。削除しないと X is not a standard action and cannot be overridden が発生します。
  • 255 文字を超えるテキスト項目には <type>LongTextArea</type> が必要です。Text の最大長は 255 です。
  • required=true の項目を参照する PermissionSet は問題なくデプロイできますが、FLS を別ファイルで設定すると You cannot deploy to a required field が発生します。項目を required=false にするか、必須設定をフロー側で処理してください。
カスタムタブ

ユーザーが App Launcher からレコードを一覧表示できるようにします:


<CustomTab xmlns="http://soap.sforce.com/2006/04/metadata">
    <customObject>true</customObject>
    <motif>Custom53: Form</motif>
</CustomTab>

次に、上記のように <tabSettings> を permset に追加します。


モバイルの前提条件 — FSL Mobile で Forms タブを表示するために必要

問題なくデプロイされ、デスクトップで表示されるフローでも、組織が割り当て済みの技術者と DDC および WorkPlan レコードを共有するように設定されていないと、FSL Mobile では "No forms available. Try Again" と表示され、何も通知されないまま失敗します。2026-05-28 に確認済み:完全に検証済みのフォーム(Sewerage Further Work Request)は、以下の 4 つの修正をすべて適用するまで、割り当てられた技術者の iOS Field Service に表示されませんでした。同じ問題により、SDO に標準搭載されていた Job Safety Assessment フォームも表示されませんでした。

通知されない理由:FSL Mobile は UI API エンドポイント /services/data/v67.0/ui-api/related-list-records/{woId}/DynamicDataCaptures を使用し、共有ルールを適用します。システム管理者としての SOQL クエリは共有を回避するため、デスクトップでの検証では問題が表面化しません。このエンドポイントは技術者に INSUFFICIENT_ACCESS を返しますが、iOS アプリはエラーを捕捉し、「Try Again」ボタンのある空の状態を表示します。

1. DynamicDataCapture と WorkPlan の OWD は「公開/参照・更新可」にする必要があります

両方のオブジェクトで、プラットフォームの既定の OWD は 非公開 です。オブジェクトのメタデータで上書きします:


<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <sharingModel>ReadWrite</sharingModel>
    <externalSharingModel>ReadWrite</externalSharingModel>
</CustomObject>

<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <sharingModel>ReadWrite</sharingModel>
    <externalSharingModel>ReadWrite</externalSharingModel>
</CustomObject>

WorkStep は ControlledByParent を介して継承するため、個別に変更する必要はありません。

2. FieldServiceSettings で、SA と親 WO を割り当て済みリソースと共有する必要があります

多くの SDO 組織では、これらは false に設定されています。これらを有効にしないと、AssignedResource は SA のリソース一覧に表示されていても、WO への共有アクセスを得られません。


<FieldServiceSettings xmlns="http://soap.sforce.com/2006/04/metadata">
    <doesShareSaWithAr>true</doesShareSaWithAr>
    <doesShareSaParentWoWithAr>true</doesShareSaParentWoWithAr>
</FieldServiceSettings>
3. 設定変更後、既存の AssignedResources を再保存する

設定変更が適用されるのは、新しい AssignedResource 行のみです。共有の再計算を実行するには、既存の行を更新して変更を反映させる必要があります。

sf apex run --target-org <alias> <<'APEX'
List<AssignedResource> ars = [
    SELECT Id FROM AssignedResource
    WHERE ServiceResource.RelatedRecord.Username = :techUsername
];
update ars;
APEX
4. 担当者はサインアウトしてから、再度サインインする必要があります
原因ではないもの(これらに時間を費やさないでください)
  • レイアウトの関連リスト名 — <relatedList>DynamicDataCapture</relatedList>(単数形)が正しい XML 形式です。UI API では別途、複数形の DynamicDataCaptures が使われます。両者を揃えようとしないでください。
  • PausedFlowInterviewId の項目レベルセキュリティ — デフォルトですべてのプロファイルに付与されています。
  • DynamicDataCapture のオブジェクト権限 — デフォルトで Standard User および SDO-Service プロファイルに付与されています。
  • 権限セットの構成 — SDO_SFS_All_Permissions(または同等の FSL 権限セット)で十分です。Forms タブに追加の権限セットは必要ありません。
  • 詳細設定での API バージョンの上書き — 本番用 iOS では v67.0 がハードコードされています。動的に検出されるのは DEBUG ビルドのみです。
  • Briefcase/オフライン用データの事前読み込み — デバイスがインターネットに接続されている場合は関係ありません。Forms タブは事前読み込みキャッシュからではなく、ライブでデータを取得します。

禁止パターン — デプロイエラーと修正方法

誤り正しい設定デプロイエラー(正確なメッセージ)
dcRadioButtonsdcRbGroupextension not found
dcSectionRegionContainerextension not found
minimumDate / maximumDateminDate / maxDateinput attribute not found
Lookup の multiSelectionisMultiSelectioninput attribute not found
Lookup の disabled / readOnlyisDisabled / isReadonly(o は小文字)input attribute not found
flow の <apiVersion> タグ完全に省略You can't specify the field API Version
Repeater 自体の extensionNameネストされたフィールドにのみ指定extensionName isn't supported
InputField の fieldTypeComponentInstance + extensionNameフィールドタイプが拒否される
ComponentInstance の <fieldText>label inputParameter を使用A required input parameter is missing: 'label'
dc* の placeholder inputParameterサポート対象外 — ラベルテキストに含めるWe can't find this input attribute: "placeholder"
dcNumeric の min / maxdcCounter でのみ有効We can't find this input attribute: "min"
<fieldType>Range</fieldType>(スライダー)DataCaptureFlow では無効'Range' is not a valid value for the enum 'FlowScreenFieldType'
Repeater の storeOutputAutomatically省略(コレクションは常に .AllItems)the storeOutputAutomatically field isn't supported
ループ内の collectionReference=Repeater_NameRepeater_Name.AllItemsElement "X" doesn't exist. Specify an existing collection element
ループ本体の Repeater_Name.field.valueLoop_Name.field.value(Repeater ではなくループの名前)無効な参照
行をまたぐ検証:AllItems[$Items - 1]画面後のループ + 判定を使用数式の Syntax error
CUD ノード間の判定分岐を使わず、CUD を順番に実行Append multiple Create, Update, or Delete operations only at the end of the flow
CUD の後の Get RecordsGet を CUD の前に移動フロー構造が拒否される
Step X of Y - Topic(ハイフン)Step X of Y – Topic(en ダッシュ U+2013)バリデーターが進行状況インジケーターを 0 件としてカウントする
<start> → recordLookups / 判定<start> → <screens>(最初に導入画面を配置)モバイルオフラインでレンダリングされない
<actionCalls>削除し、通知には DisplayText を使用アクション要素は許可されない
helpText inputParameterラベルテキストに含めるinput attribute not found
<booleanValue> としての IsLlmTargetable(任意プロパティですが、指定する場合)<stringValue>{&quot;value&quot;:&quot;false&quot;}</stringValue> またはプロパティを完全に省略有効化エラー:The value of the IsLlmTargetable custom property's value field must be a string in JSON format
Lookup の recordIds inputParameterrecordIdCollection(Id は単数形、Collection を付加)We can't find this input attribute: "recordIds"
単一選択の Lookup での recordIdCollectionisMultiSelection=true を設定(それ以外の場合、スコープ指定は無視される)エラーなし — 実行時にフィルターが適用されない
dynamicChoiceSets 内の <outputAssignments>選択後の recordLookups で outputAssignments を使用デプロイエラーなし — 後続の画面で変数が空のままになる
DisplayText 内の IF / CASE / 日付計算Assignment で事前計算し、単純な変数を参照実行時の Error while resolving default value reference
dcTextInput のデフォルト value としての $User.Name$User.Usernamefield integrity exception… type for input parameter "Value" doesn't match
画面に nextOrFinishButtonLabel がない<nextOrFinishButtonLabel>Next</nextOrFinishButtonLabel> を追加Next/Finish ボタンが表示されない
DataCaptureFlow から AutoLaunched サブフローを呼び出すロジックをインライン化するか、別の DataCaptureFlow のみを呼び出すThis flow can't reference [FlowName] because the referenced flow type is Autolaunched Flow
visibilityRule の背後にあるフィールドでの isRequired=trueisRequired=false に設定し、validationRule で IF(trigger, rule, TRUE) を使用非表示のフィールドが原因で、ユーザーが先に進めなくなる

デプロイ

# Single file
sf project deploy start -d force-app/main/default/flows/MyFlow.flow-meta.xml \
  --target-org <alias> --wait 60 --json

# Multi-dir (use repeated -d, NOT comma-separated)
sf project deploy start \
  -d force-app/main/default/objects \
  -d force-app/main/default/permissionsets \
  -d force-app/main/default/tabs \
  --target-org <alias> --wait 60 --json

エラーを抽出:

... --json 2>&1 | python3 -c "
import sys, json
d = json.load(sys.stdin)
r = d.get('result', {})
print('Status:', r.get('status'))
for f in r.get('details', {}).get('componentFailures', []):
    print('ERROR:', f.get('fullName'), '-', f.get('problem'))
"

参考例

このスキルの examples/ に同梱されています。

  • Data_Capture_All_Components.flow-meta.xml — デプロイ可能な XML で、すべてのコンポーネントを記載
  • DataCapture_Showcase.flow-meta.xml — エンドツーエンドのフロー全体:複数画面のフォーム、編集を続けられる recordLookup、Repeater → Loop → .AllItems 経由の子レコード、Decision によって動作する Create-or-Update CUD チェーン、視覚的な仕上げ(バナー、進捗表示、コールアウト、レビューカード)。XML 形式の標準となる「正解」です。スキルのルールとこのファイルの内容が食い違う場合は、このファイルを優先してください。
  • Repeater_with_prepopulation.flow-meta.xml — 事前入力された Repeater の標準パターン:recordLookups(ServiceResource)→ collection inputParameter でバインドされた Repeater。ネストされたフィールドの value のデフォルト値には SourceCollection[$EachItem].FieldApiName を使用 → .AllItems を対象とした Repeater 後の Loop で、{!LoopName.nestedField.value} と {!LoopName.UniqueField__Id} を読み取る表示画面にデータを渡します。検証済みの例です。事前入力および Repeater 後の表示 XML の信頼できる正解として扱ってください。
  • DataCapture_Repeater_with_data_showcase.flow(コミットされていない組織内のファイル)— .AllItems のループに関する標準的な検証例です。動作しない、行をまたいだ検証式の構文も記載しています。

───── 実行時のコンテキスト(Headless 360/エージェント型): このスキルが Headless 360/エージェント型のコンテキストで実行される場合は、可能であれば CLI ツール(sf project deploy、sfdx、シェルコマンド)よりもプラットフォームのディスパッチツール(ホスト型 Headless 360 MCP の dispatch、ローカル開発用 MCP の dispatch)を優先してください。利用可能な操作は以下の steps: に記載されており、実稼働組織でそれぞれ検証済みです。正規のパスを指定してディスパッチツールを呼び出してください。該当する機能に API パスがない場合に限り、CLI を代替として使用できます。

重要な制約

運用ルール:

  • 必須の入力変数:
<variables><name>recordId</name><dataType>String</dataType><isInput>true</isInput><isOutput>false</isOutput><isCollection>false</isCollection></variables>
<variables><name>parentRecordId</name><dataType>String</dataType><isInput>true</isInput><isOutput>false</isOutput><isCollection>false</isCollection></variables>
<variables><name>parentObjectType</name><dataType>String</dataType><isInput>true</isInput><isOutput>false</isOutput><isCollection>false</isCollection></variables>
  • フィールドが visibilityRule の対象になっている場合、そのフィールドを isRequired=true にしないでください。フィールドが非表示でも必須チェックが実行されるため、ユーザーが先に進めなくなります。代わりにフィールドを isRequired=false に設定し、ルールを次のように記述します。
  • FSL Mobile はログイン時に共有スナップショットをキャッシュします。プルして更新しても新しい共有設定は反映されず、新しい認証トークンが必要です。ユーザーには FSL Mobile アプリから完全にサインアウトしてから、再度サインインするよう案内してください。その後、Forms タブの取得が成功し、DDC レコードが表示されます。

コメント