フローの基本 | 複数のレコードを挿入/作成するためのフローの一括化


+ [フローを使った一括更新](https://qiita.com/Keiji_otsubo/items/413456cdcbbb6821a7a1)

[Flow Basics | Bulkify Flows to Insert/Create Multiple Records](https://www.accidentalcodersf.com/2020/07/flow-bulkify-flows-to-insert-multiple-records-salesforce.html)

この投稿では、Salesforce でフローを使用してレコードを一括挿入する方法を紹介します。ループ内で 1 つずつ作成するのではなく、オブジェクトの複数のレコードを一度に作成するためにフローを一括処理します。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/bda2a580-4245-d539-1491-d87de62c9d07.png)

# フローに複数のレコードを挿入する方法 (一度に)

フローには、 任意のオブジェクトの新しいレコードを作成/挿入するために使用できる レコード作成要素があります。単一のレコードを作成するのは簡単で、ベスト プラクティスに関して心配することはあまりありません。 

注意が必要なのは、特定のオブジェクトに対して複数のレコードを一度に作成/挿入することです。少なくとも、これを初めて試したときは、少しトリッキーでした。最初に考えた方法は 2 つあります。 1. フローで Create Record Element を複数回使用する。ループ内またはそれ以外のいずれか。2. 単一の Create Record 要素を使用して、作成するすべての新しいレコードを渡し、一度に作成します。明らかに、2 番目の方法が正しい方法です。

注 :この記事では、Salesforce フローで複数のレコードを作成する際のフローの一括処理について説明しています。フローで一括更新する方法またはフローでレコードを一括更新する方法を確認したい場合は、この記事をチェックアウトして理解を深めてください: [フロー でのレコードの一括更新](https://www.accidentalcodersf.com/2020/12/flow-bulkification-mass-update-records.html)

# フロー ループ内で Create Records 要素を使用しないでください。一度もない！

先に進む前に、この点を常に覚えておいてください。複数のレコードを作成/挿入する簡単な方法は、ループ内でレコードの作成要素を使用することです。しかし、それをしないでください。

ループ内で Create Record Element を使用しないでください。Salesforce ガバナーの制限はあまり好きではありません。大量のレコードを処理している場合、制限に達する可能性が高くなります。 この種の設計はスケーラブルではなく、処理するレコードが増えると失敗し、同じトランザクション内で他の自動化 (トリガー、フローなど) が実行/起動される場合に失敗します。 

# フローのループ内で Create Records 要素を使用しないようにする方法 

ループ内で Create Record Element を使用しないようにする最善の方法は、実際に Record タイプの New Collection Variable を作成して、作成するすべての新しいレコードを保持/保存し、最後にこの Record Collection Variable に対して単一の Create Records Element を使用することです。

# これは、フローのバルク化またはバルク化 フローと呼ばれます。

注:特定のユース ケースを紹介するために、この記事ではフロー開発に関連するベスト プラクティスのいくつかを見落としている可能性があります。実際のシナリオやプロジェクトでは、必ずこれらに従ってください。

サンプルシナリオ・ユースケース取引先実績ページの画面フローが必要 です。このフローは、アカウントのすべての取引先責任者に対して新しいケースを作成するために使用されます。 アカウントのすべての取引先責任者に対して、新しいケースを作成する必要があります。すべてのケースを一度に作成する必要があります。すべてのケース (取引先責任者ごとに 1 つ) は、同じアカウント ID を持つ必要があります。つまり、同じアカウントに関連付ける必要があります。ケースの件名は取引先責任者名と等しく、ケースのタイプは内部である必要があります。

注: これは、このバルク化プロセスの背後にある全体的なロジックを説明するための非常に基本的なシナリオです。実際の要件やユースケースに応じて、同じロジックと設計を他のシナリオに適用できます。サンプルデータ (私の最新のお気に入りの Netflix シリーズ「ダーク」にインスパイアされたもの)アカウント名: ダーク取引先責任者 : Ulrich、 Martha、Jonas、Magnus、Claudia

画面フローの [完了] ボタンをクリックすると、システムは取引先責任者ごとに 1 つずつ、合計 5 つのケースを作成する必要があります。これらのすべてのケースは親アカウント (アカウント: ダーク) に関連付ける必要があり、その件名はそれぞれの取引先責任者の名前と同じであり、発信元は内部と同じである必要があります。全体のフローの構成

:::note info
取引先に５つの取引先責任者があって、その取引先の詳細画面にボタンがあるということかな？
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1362d910-833f-72c6-4a71-5e296dcc9b11.png)


解決策と説明当フローは基本的な画面フローです。取引先レコード ページに配置されるため、取引先 ID だけでなく、取引先レコードをフロー (Summer'20 機能) に直接渡すことができます。注: このフローの画面要素には実際の目的はありません。アカウントページにフローを表示し、ユーザーがフローを起動するためのボタンを提供するためにのみ使用されます。 したがって、最初のステップは、オブジェクト (アカウント) 型の入力レコード変数を作成して、アカウント レコードをページからフローに渡すことです。この変数にAccountRecordという名前を付けました

このフローを保存して有効化し、取引先の Lightning レコード ページに配置すると、この変数名が表示され、ページからデータを渡すオプションが表示されます。 次に、Account に基づいて、フローのGet Elementを使用して、その Account に関連するすべての取引先責任者を取得します。この例では、ダミー データに従ってこれらの 5 つのレコードを取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/aac987fd-066d-77b2-829b-6f659a89d22e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b71ffd6a-6f0b-9c17-e3a7-a5ec790b50d3.png)

-------------------------------------------------- --
ヒント: Get Record 要素の後に必ず Decision 要素を追加して、レコードが返されたかどうかを確認します。Get Records でレコードが見つかった場合にのみ、フローをさらに実行する必要があります。
-------------------------------------------------- --
次に、これらの取引先責任者を 1 つずつループして、それぞれのケースを作成する必要があります。ここがトリッキーな部分です。取引先責任者を 1 つずつループする場合、ループ内で Create Record 要素を使用しないようにするにはどうすればよいでしょうか。 それを達成するために必要な2つのステップがあります。取引先責任者をループする前に、以下に示すように、さらに 2 つの変数が必要です。

挿入するすべての新しいケース レコードを保持/保存する空のコレクション変数を作成する 最初のステップは 、タイプ Record (Object type Case) の新しい変数を作成することです。 複数の値 (コレクション)を持つことができるようにします 。この変数は、最後に作成/挿入する必要がある新しいレコード (ケース) の最終的なリスト/コレクションになります。名前は「CasesToCreate」です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9153283a-68ec-605c-2e1b-617bad9aabfd.png)


より適切に表現するために、このコレクション変数をTray of Casesと呼びましょう  。この変数を作成すると、Tray(Collection) は空で、レコードがありません。注意:このケース コレクション変数 (トレイ) は、ケース オブジェクトのレコードのみを保存/持つことができます。このトレイは、他のタイプの変数/レコードまたはプロパティを保持/保存することはできません。この問題を解決するには、以下の次の手順を参照してください。重要:空白/ダミー ケースを作成するには、タイプ レコード (オブジェクト: ケース) の変数を作成します。


最後のステップで、空のコレクション ケース変数 (ケース トレイ) を作成しました。ここで、この空のトレイ (ケース コレクション変数) に新規/ダミー ケースをループ内の取引先責任者ごとに 1 つずつ入力する必要があります。これにより、トレイ全体またはコレクション変数を使用して一度にケースを挿入できるようになります。 再度注意してください: ケース コレクション変数 (ケース トレイ) は、ケース オブジェクトのレコードのみを保存/持つことができます。このトレイは、他のタイプの変数/レコードまたはプロパティを保持/保存することはできません。そこで 、タイプ Record (Object type Case) の変数をもう 1 つ作成します。これは 1 つの 変数のみです (複数の値には対応していません)。 





このケース変数は、ループの反復ごとにダミーのケース レコードとして機能し、ループの反復ごとにそのプロパティ/フィールド値 (サブジェクト、オリジン、アカウント) を変更し、 トレイ (コレクション変数)に追加します。変数名は「Case Individual Record」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8b6ab682-d615-617a-a25c-f44952a4a235.png)


ループ要素:  Get 要素から取引先責任者をループするだけです。ループ変数は、Summer'20 以降に自動的に作成されるため、作成する必要はありません。ループ内には、2 つの代入要素があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/bda2a580-4245-d539-1491-d87de62c9d07.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9f675096-d6fe-8a06-ef83-da9e19624b32.png)


最初の割り当て要素は、サブジェクト、オリジン、およびアカウント ID のフィールド値を、作成したダミーのケース単一変数 ( {!CaseIndividualRecord ) に割り当てます。取引先責任者をループしているため、取引先責任者の名前はループ変数から取得されます。Origin は Internal として設定され、Account ID は、タイプ Record の Input 変数と、最初のステップで作成した object Account から入手できます。このアカウント値は、アカウント ページからフローに渡されます。2 番目の割り当ては、このダミー ケース (前の手順でフィールド値が割り当てられたもの) をケース コレクション変数( {! CasesToCreate} ) に追加することです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d8aca5e9-b503-d4b3-7870-bda912441103.png)


または、ここで言及したケース トレイ。 これは、実際にどのように機能するかを大まかに (文字通り) 図解したものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/dd6ff765-a1e3-d8c8-b0e6-736c798823f2.png)

ここで注意すべきこと (私の悪い手書きと描画は別として) は、ダミー ケース変数のフィールド値が反復ごとに変更され、そのダミー ケースが反復ごとにケース コレクション (トレイ) 変数に追加されることです。

ループの終了後、上の図に示すように、取引先責任者ごとに 1 つのダミー ケースをケース トレイに追加します。

最後に、Create Record Elementを使用して、コレクション変数 ( {!CasesToCreate} ) にケース レコードを一度に挿入します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0763a2d6-1b97-31c6-76a2-d69e99641991.png)



# もし同じ処理をApexで書いたら

こんな感じで簡単だけど。フローで処理して何が楽しいのかさっぱり理解できない。素直にApexを覚えた方が絶対に早い。

```
List<Contact> conList =[SELECT Id,FrisName,AccountId FROM Contact WHERE AccountId =: AccountRecord.Id]; // 1
List<Case> CasesToCreate = new List<Case>();
for ( Contct con : ContctList){ //2
   Case c = new Case();
   c.subject = con.FirstName; //3
   c.type = 'Internal'; //3
   c.AccountId = con.AccountId; //3
   CasesToCreate,add(c); //4
}

if (CasesToCreate.size()> 0) insert CasesToCreate; //5
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/adffd212-88d9-ed8f-08b8-b3ee2eb37ba2.png)

フローも一括更新の時にはList変数を使えばいいのは分かったけど、そもそもApex トリガーのように入力をList変数にはどうやったらやれるのか？　

またMap変数を使って値を一発で取得できるのか？