やってみよう！プロセスビルダーからSalesforceフローへの移行

初めまして。
大阪の小さな企業でSalesforce管理者をしております、kobayashi(@kob_sf)と申します。

普段はQiitaを読んで勉強させていただいている側ですが、Salesforce Advent Calendarにずっと参加してみたかったので書きたかった話題があったこのタイミングで執筆させていただきました。

2021年10月ごろにワークフローとプロセスビルダーの廃止を聞いたことが本記事を書こうと思ったきっかけとなりましたが、Salesforce入門当時からお世話になっていた機能だっただけにかなり衝撃を受けました。
circlace様の記事によると直ちに廃止されるわけではありませんが、今からでもフローに慣れて徐々に移行していくことが重要だと考えます。
>要約すると、現時点での目標スケジュールは以下の通りです。
・ワークフロールールからフローへの移行をサポートする初期の移行ツールを Spring'22年にリリースする予定です。
・プロセスビルダーへの移行をサポートする追加ツールは、Summer’22を予定しています（初期の移行ツールからのフィードバックに依存します）。
・移行が成功し、コミュニティからの意見が得られれば、新しいプロセスやワークフローを作成する機能の停止を Winter’23に開始する予定です。

https://sf.forum.circlace.com/articles/665570554270453760

私自身もプロセスビルダーからフローへ移行するタイミングがなかなかキツかったことを覚えています。当時はUIも今ほど優しくなく、怪しい日本語訳が満載だったのでアングラな雰囲気しかありませんでした。

その頃と比較するとUIはもちろん、Trailheadもヘルプも充実しましたしTrailblazerの方々の文献も多数あります。

コロナ禍でリアルイベントとしてのセミナーが無くなり、以前のように聞きやすい雰囲気というのはなかなか難しいですが、企業で兼業アドミンをされている同じ境遇の方々の一助となれば幸いです。

#本記事の対象
本記事においては以下の方々を対象としており、内容としても概念や知識を埋め込むというよりは見て真似れば誰でも出来るを目指しております。

* ユーザー企業でアドミンをしておりプロセスビルダーを触っている人
* フローの概要は知っているがまだ使ったことがない人
* フローの細かな知識ではなくとりあえず移行を試したい人

#本記事のゴール
実際にプロセスビルダーを取り上げ、要素1つ1つをフローに置き換える方法をお伝えしていきます。
記事のためのプロセスであるため、若干無理のある設計となっている点はご容赦ください。

#プロセスビルダー
本記事においては商談のフェーズを更新したときに実行される以下のプロセスビルダーをフローへ置き換えていきます。
![ppb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/fa1a915b-5ff3-e09e-5513-865fe339bdc6.png)

* 対象オブジェクト：商談（Opportunity）
* トリガ：作成または更新したとき
* 実行タイミング：レコードが変更されたとき

##分岐と処理
このプロセスビルダーには分岐が全部で4つ設定されており、すべてレコードに指定の変更が行われた場合にのみアクションを実行するものとします。

1. フェーズ02に変更されたとき
2. フェーズ03に変更されたとき
3. フェーズ04に変更され、特定の項目に値が入力されているとき
4. 商談が受注になったとき

上記のような商談の作成または更新をトリガとして条件に一致する場合に処理を実行するプロセスを今回はSalesforceフローに置き換えてみましょう。

#フローへの置き換え
![flow-easy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/f94deb63-0074-c18f-9538-22484e7650ac.png)
プロセスビルダーからフローへの移行ですが、呼称は違えど機能はそれぞれ次のとおり対応した機能があります。
中には機能の名前が同一のものもあるので複雑なことをしなければ混乱はないかもしれません。

| No | プロセスビルダー | Salesforceフロー |
|:--|:--|:--|
| ① | 条件分岐 |  決定 |
|  ② | レコードを更新 | レコードを更新  |
|  ③ |  レコードを作成 |  レコードを作成 |
|  ④ |  承認プロセス |  アクション |
|  ⑤ |  Chatter投稿 |  アクション |

慣れるまでは戸惑いますが、慣れるとフローの魅力に惹きつけられるはずです！早速フローを作っていきましょう！

「商談フェーズをトリガとするフロー」を作っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/e4754190-9601-3ffc-0820-4ca9a11fae92.png)

* 設定からフローへ移動して「新規フロー」を選択
* 新規フローの画面で「レコードトリガフロー」を選択

レイアウトの形式は「自由形式」と「自動レイアウト（ベータ）」がありますが、今回は昔ながらの自由形式で進めていきます。

##商談フェーズをトリガとするフロー
![フロー全体図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/1db1d167-91ca-cf2c-aa11-ebb8d6fcebc0.png)
完成品はこちらになります。
フローの各要素の配置に厳密なルールはないので個々人のルールに合わせて配置してください。処理の流れを見るものなので上から降りていくイメージで作っていくとわかりやすいです。

順番は前後しますが、解説の関係上さきにいくつかの変数、数式を定義しておきます。
ツールボックス > マネージャ > 新規リソースを選択してください。

Chatter投稿で使用する本文を定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/8c8dce3b-8219-f5fc-5c47-444631af47c5.png)

```
リソース種別：テキストテンプレート
API参照名：txt_chatterPost
本文：
　☆.｡.:*･ﾟ☆.｡.:*･ﾟ☆ Congratulations ☆ﾟ･*:.｡.☆ﾟ･*:.｡.☆
　受注しました！！！！！
　商談名：{!$Record.Name}
　取引先名：{!$Record.Account.Name}
　商談金額：{!$Record.Amount}円
　詳細URL：https://********.lightning.force.com/lightning/r/Opportunity/{!$Record.Id}/view
※URLの****部分はご自身の組織によって変えてください
```

次はアラーム日付/時間で利用する日付時間型の数式です。
やや複雑な数式となっていますが、内容は単純で3日後の現在の時刻を返す数式を定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/5b75a5dd-0514-a3ed-84a6-bddc1b689d59.png)

```
リソース種別：数式
データ型：日付/時間
API参照名：calc_Aft3DateTime
数式：DATETIMEVALUE( TEXT(DATEVALUE( {!$Flow.CurrentDateTime} ) + 3) & " " & SUBSTITUTE( TEXT( {!$Flow.CurrentDateTime} ), LEFT( TEXT( {!$Flow.CurrentDateTime} ), 11), "" ) )
```

ToDoの期日などに使用する翌日の日付を返す数式を定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/e5e707d6-eb1f-6f13-fd0d-5ca63033afaa.png)

```
リソース種別：数式
データ型：日付
API参照名：calc_returnActivityDateAft1Day
数式：{!$Flow.CurrentDate} + 1
```

本日の3日後をクロージングの期日として返す数式を定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/18b125de-2f6e-9966-955c-743da3d64c59.png)

```
リソース種別：数式
データ型：日付/時間
API参照名：calc_returnClosingActivityDate
数式：{!$Flow.CurrentDate} + 3
```

変数・数式の定義はここまでです！
ここからは上図に沿って①〜⑥までの構築手順を解説していきます。

######①.開始条件の設定
![flow-detail1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/c37feecd-f2a4-5597-003f-83908eb04f5a.png)
フローの開始条件を指定します。
フェーズが変更されるたびに実行しても動作しますが、パフォーマンス面を考慮して処理が発生する場合にのみフローをトリガするよう以下の通り設定します。

```
オブジェクト：商談
トリガ：レコードが更新された
エントリ条件：カスタムロジックに一致 < (1 AND 6) OR (2 AND 6) OR (3 AND 4 AND 6) OR (5 AND 6) >
  1.StageNameが 次の文字列と一致 02.会話の有無
  2.StageNameが 次の文字列と一致 03.関係性構築
  3.StageNameが 次の文字列と一致 04.ヒアリング
  4.競合企業が null　False
  5.IsWonが 次の文字列と一致 True
  6.StageNameが 変更済み True
更新されたレコードでフローを実行するタイミング：レコードを更新し、条件の要件に一致するたび
フローを最適化：アクションと関連レコード
```

######②.商談の変更内容による分岐
![flow-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/5a10ef89-f816-2396-9040-2d03dae818f8.png)
ツールボックス内のロジックから「決定」をドラッグアンドドロップします。
意思決定要素を以下のように設定していきます。
![flow-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/3cf415a6-610b-c2d4-c25a-7230424b5b8b.png)

```
表示ラベル：商談の変更内容による分岐
API参照名：decide_OpportunityChange
結果の順序：
  1.フェーズが02になった
  2.フェーズが03になった
  3.フェーズが04、かつ競合企業が存在
  4.商談が成立した
```

1.フェーズが02になった
表示ラベル：フェーズが02になった
API参照名：isChangeStageName02
実行条件：すべての条件に一致（AND）
実行タイミング：フローの実行をトリガしたレコードが条件の要件を満たすように更新された場合のみ

| リソース | 演算子 | 値 |
|:--|:--|:--|
| {!$Record.StageName} | 次の文字列と一致する | 02.会話の有無 |

2.フェーズが03になった
表示ラベル：フェーズが03になった
API参照名：isChangeStageName03
実行条件：すべての条件に一致（AND）
実行タイミング：フローの実行をトリガしたレコードが条件の要件を満たすように更新された場合のみ

| リソース | 演算子 | 値 |
|:--|:--|:--|
| {!$Record.StageName} | 次の文字列と一致する | 03.関係性構築 |

3.フェーズが04、かつ競合企業が存在
表示ラベル：フェーズが04、かつ競合企業が存在
API参照名：isChangeStageName04
実行条件：すべての条件に一致（AND）
実行タイミング：フローの実行をトリガしたレコードが条件の要件を満たすように更新された場合のみ

| リソース | 演算子 | 値 |
|:--|:--|:--|
| {!$Record.StageName} | 次の文字列と一致する | 04.ヒアリング |
| {!$Record.competitor__c} | null | False |

4.商談が成立した
表示ラベル：フェーズが04、かつ競合企業が存在
API参照名：isChangeWon
実行条件：すべての条件に一致（AND）
実行タイミング：フローの実行をトリガしたレコードが条件の要件を満たすように更新された場合のみ

| リソース | 演算子 | 値 |
|:--|:--|:--|
| {!$Record.IsWon} | 次の文字列と一致 | True |

これでプロセスビルダーと同じ条件分岐まで作成できました。
ここからは各分岐の先の処理部分を作成していきます。

######③.フェーズ02への変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/31c4e4a7-8338-4d16-f2d2-edfba315f87b.png)

```
アクション：レコードの更新
レコードの更新条件：レコードを更新する条件がない
項目：最終フェーズ
種別：項目の参照
値：[Opportunity].StageName
```
本フェーズに変更されたとき無条件で実行され、商談の「最終フェーズ」というテキスト項目に現在のフェーズを代入します。
プロセスビルダーのこの部分を以下のフローに置き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/495d9324-adc4-7f8c-1cc3-c1d21dd378c6.png)

```
要素：レコードを作成
表示ラベル：現在のフェーズを記録
API参照名：update_lastStageName
更新するレコードの検索と値の設定方法：フローをトリガした 商談 レコードを使用
検索条件：なし（常にレコードを更新）
商談の項目値
・lastStageName__c　← {!$Record.StageName}
``` 
######④.フェーズ03への変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/76050fb6-1215-e6ab-9dfe-31c59142d697.png)

```
アクション：レコードの作成
オブジェクト：ToDo
項目値：
・期日のみ　← 数式：TODAY()+3
・アラーム設定　← Boolean：True
・割り当て先ID　← 項目の参照：[Opportunity].OwnerId
・優先度　← 選択リスト：High
・アラーム日付/時間　← 数式：DATETIMEVALUE( TEXT(DATEVALUE( NOW() ) + 3) & " " & SUBSTITUTE( TEXT( NOW() ), LEFT( TEXT( NOW() ), 11), "" ) )
・状況　← 選択リスト：Not Started
・件名　← 文字列：クロージング
・関連先ID　← 項目の参照：[Opportunity].Id
```
フローでは次のように置き換えられます。
あまりプロセスビルダーと違いがないため、そこまで難しくないと感じてもらえるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/f00255e1-2789-b5f4-58a2-b381e4cdf469.png)

```
要素：レコードを作成
表示ラベル：クロージングToDo作成
API参照名：create_Todo
作成するレコード数：1
レコード項目の設定方法：個別のリソースおよびリテラル値を使用
オブジェクト：ToDo
ToDoの項目値
・ActivityDate　← {!calc_returnClosingActivityDate}
・IsReminderSet　← {!$GlobalConstant.True}
・OwnerId　← {!$Record.OwnerId}
・Priority　← High
・ReminderDateTime　← {!calc_Aft3DateTime}
・Subject　← クロージング
```
######⑤.フェーズ04への変更、かつ特定の項目に値が入っている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/fc30529c-b21d-541c-308a-0a045df12ce3.png)

```
アクション：承認申請
承認プロセス：特定の承認プロセス
申請者：現在のユーザ
登録コメント：競合企業が存在するため値引きしてもよろしいでしょうか？
```
承認プロセスとToDoの作成を置き換えます。
フローでは承認プロセスを「アクション」という要素から呼び出します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/993a8656-e578-c824-fe60-4912be0e1853.png)
アクションをキャンバスにドロップすると検索ウィンドウが表示されるので、承認と入力して承認申請を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/1fbef95e-149e-a8a6-d047-2f8e7dd57c00.png)

```
要素：承認申請アクション
表示ラベル：値引き申請
API参照名：action_DiscountApprovalProcess
カスタムオブジェクトID：{!$Record.Id}
承認プロセス名または ID：値引きの承認プロセス
申請者ID：{!$User.Id}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/c186f814-e03f-3077-e86a-507755f00446.png)
続いてToDoの作成も設定していきます。

```
要素：レコードの作成
表示ラベル：承認リマインドToDoの作成
API参照名：create_todoApprovalProcessReminder
作成するレコード数：1
レコード項目の設定方法：個別のリソースおよびリテラル値を使用
オブジェクト：ToDo
項目値：
・ActivityDate ← calc_returnActivityDateAft1Day
・OwnerId ← {!$Record.Owner.ManagerId}
・Priority ← High
・Status ← Not Started
・Subject ← 値引き承認申請の判断
・WhatId ← {!$Record.Id}
```
フェーズ04へ変更され、競合企業（テキスト型）に値が入力されている場合に自動的に承認プロセスが申請される設定です。
また、承認者に対してToDoを自動作成して承認申請が放置されないようにしています。

######⑥.商談が受注に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/c8d58955-6ebb-9c3c-3404-6b12f0d109d4.png)
受注時にChatterへの受注報告と受注後の処理ToDo作成を設定しており、トリガした商談の情報を取得してChatterグループへ投稿しています。

```
アクション：Chatterに投稿
投稿先：Chatterグループ
グループ：受注報告
メッセージ：
　☆.｡.:*･ﾟ☆.｡.:*･ﾟ☆ Congratulations ☆ﾟ･*:.｡.☆ﾟ･*:.｡.☆
　受注しました！！！！！
　商談名：{![Opportunity].Name}
　取引先名：{![Opportunity].Account.Name}
　商談金額：{![Opportunity].Amount}円
　詳細URL：https://**********.lightning.force.com/lightning/r/Opportunity/{![Opportunity].Id}/view
```

要素からアクションを選択してキャンバスにドロップし、検索ウィンドウに「Chatter」を入力したらChatterに投稿というアクションを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/1c898afe-9693-2cd8-106d-1f7ffff3ff05.png)

```
表示ラベル：Chatterに受注を報告
API参照名：action_PostToChatter
メッセージ：{!txt_chatterPost}
対象名またはID：{!$Record.Id}
```
続いてリマインド用のToDoを作成する設定をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348223/a91040dd-7e56-ff2b-3302-7d09b4c84675.png)

```
要素：レコードの作成
表示ラベル：受注処理ToDoの作成
API参照名：create_todoOrder
作成するレコード数：1
レコード項目の設定方法：個別のリソースおよびリテラル値を使用
オブジェクト：ToDo
項目値：
・ActivityDate ← calc_Aft3DateTime
・OwnerId ← {!$Record.OwnerId}
・Priority ← High
・Status ← Not Started
・Subject ← 受注処理
・WhatId ← {!$Record.Id}
```

ここまで設定すればあとは各要素をドラッグ&ドロップでつないで完成です！
デバッグテストをしたうえで有効化してください。

あとはプロセスビルダーを無効化すればフローが今までと同じ機能を実現してくれます！

#終わりに
最後までお読みいただきありがとうございました。
私自身の話となりますが、現在の企業に入るまではフロントエンド側にいたためシステムの知識など一切触れることなく生きてきました。

そんな私が今の会社で突然salesforce管理者になり、今日まで何とか運用を続けて来られたのは周囲のコミュニティの方々、気軽に多様な相談に乗ってくださる諸先輩方、そして何より当時ベンダーとして弊社に関わってくださっていた"株式会社ウフルの山田さん"のサポートに他なりません。心から御礼申し上げます。

色々な場面で口を揃えて言われていることですが、Salesforceは互いによくし合おうというコミュニティの意識が素晴らしいと感じます。プロセスビルダーを愛しすぎていた私をフロー沼に叩き落としていただいたのもコミュニティがきっかけでした。
ごめんねプロセスビルダー、もうフロー無しじゃいられないんです・・

冗談はさておき、もしSalesforceの導入や運用を決める立場にある偉い方が読まれていたら、コストカットのためだけにベンダーさんを切らないでください。瞬間的なコストは浮くかもしれませんが価格と価値は必ずしも一致しません。
将来的に自社内だけでの運用を考えているのであれば自社のアドミンを育ててくれるようなベンダーさんを見極めて投資することもご検討ください！

最後に記事内でミスや問題点があればTwitter等でもご指摘いただけますと幸いです。