自動化プロセスの実行順序

<!-- TODO -->
<!-- ★1 つのトランザクション内で、フロートリガは、すべてのワークフロー項目 (ワークフロー項目更新の結果として実行される Apex トリガや標準の入力規則を含む) が更新された後に実行されます。フロートリガの実行後、エスカレーションルールが実行されます。 -->
<!-- ★承認プロセスによる編集ロックはどのタイミングで判定されるのか？Approval.unlock() -->
<!-- ★親レコード削除による参照項目の更新はトリガーをキックするか？ -->

# insert、update時にサーバーで処理される順番
<img width="935" alt="自動化プロセスの実行順序_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/5dda31b7-cdc0-cafe-d672-bdce5ec36dc5.png">


★は同一オブジェクトに対して再度Apexトリガが実行される可能性のあるもの。

1. データベースから元のレコードをロードするか、レコードを初期化する。
1. 新しい項目値をロードし、古い値を上書きする。項目の必須・型・長さの検証。
1. <font color="Blue">高速項目更新のレコードトリガーフローの実行。</font>
1. <font color="Red">Beforeトリガの実行。</font>
1. システム入力規則・カスタム入力規則の検証。
1. 重複ルールの実行。
1. レコードのデータベースへの保存(コミットはされない)。[^list-2]
1. <font color="Red">Afterトリガの実行。</font>★
1. 割り当てルールの実行。
1. 自動レスポンスルールの実行。
1. ワークフロールールの実行。項目自動更新があるのみ、次の項目が実行される。★
    - 再びレコードを更新する。
    - システム検証を再度実行する（カスタム入力規則、フロー、重複ルール、プロセス、エスカレーションルールは再実行されない）。
    - 1度のみBefore UpdateトリガとAfter Updateトリガの実行
1. エスカレーションルールの実行。
1. プロセス、プロセスによって開始されたフロー、ワークフロールールによって開始されたフローの実行（順不同）★
1. <font color="Blue">アクションと関連レコードのレコードトリガフローの実行。</font>
1. エンタイトルメントルールの実行。
1. 主オブジェクトの更新(積み上げ集計項目、クロスオブジェクトの項目自動更新)
1. 主オブジェクトが更新された場合、主オブジェクトの種オブジェクトの更新(積み上げ集計項目、クロスオブジェクトの項目自動更新)
1. 条件に基づく共有ルールの実行。
1. <font color="Red">DML操作のコミット。</font>
1. コミット後のロジックの実行（順不同）。
    - メール送信
    - キューに追加された非同期Apexジョブ(queueable、future）
    - アウトバウンドメッセージ
    - <font color="Blue">レコードトリガフローの非同期パス</font>

再帰保存中、Salesforce は手順 9 (割り当てルール) から 17 (祖父母レコードの積み上げ集計項目) をスキップします。

<!-- 未反映の公式ドキュメントの記述


## その他の考慮事項

* 組織で取引先責任者-to-複数取引先を使用している場合、非公開の取引先責任者を挿入すると必ず AccountContactRelation が作成され、取引先責任者がデータベースに保存された (ステップ 6) 直後にその入力規則、データベースの挿入、トリガが実行されます。取引先責任者の主取引先を変更した場合は、AccountContactRelation が作成または編集されることがあり、取引先責任者がデータベースに保存された (ステップ 6) 直後に AccountContactRelation の入力規則、データベースの変更、トリガが実行されます。
* before トリガを使用して商談レコードの [フェーズ] および [売上予測分類] を設定する場合、次のように動作します。
    * [フェーズ] および [売上予測分類] を設定すると、商談レコードにはこれらの正確な値が含まれます。
    * [フェーズ] を設定して [売上予測分類] を設定しない場合、商談レコードの [売上予測分類] はデフォルトで [フェーズ] トリガに関連付けられた値に設定されます。
    * [フェーズ] を API コールで指定した値またはユーザインターフェースから受信した値にリセットすると、[売上予測分類] 値も API コールまたはユーザインターフェースによって入力されます。[売上予測分類] に値を指定せず、入力された [フェーズ] がトリガ [フェーズ] とは異なる場合、[売上予測分類] はデフォルトで [フェーズ] に関連付けられた値に設定されます。トリガ [フェーズ] と入力された [フェーズ] が同じ場合、[売上予測分類] はデフォルト値に設定されません。
* 商品に関連する商談をコピーする場合、次のイベントが順に発生します。
    * 親商談が上記のイベントのリストに従って保存されます。
    * 商談商品が上記のイベントのリストに従って保存されます。
メモ
商談商品でエラーが発生した場合は、商談に戻ってエラーを修正してからコピーを行う必要があります。

商談商品に固有のカスタム項目が含まれている場合は、それらをすべて null に設定してから商談をコピーする必要があります。
-->

# 留意事項
## トランザクション
* 一連の処理の流れは1トランザクションとしてみなされます。そのため<strong>ガバナ制限</strong>に注意する必要があります(CPU使用時間など)。
* 静的変数はトランザクションの範囲内で維持されます。そのため、同一トランザクションで複数回トリガが実行されるようなときに、静的変数を使用することで初回のみ処理を行うというようなことができます。(Apexでは、静的変数はトランザクションをまたいで使用することができず、トランザクション終了後に破棄されます)。
    * たとえば、「従オブジェクトを保存→従オブジェクトのApexトリガ(1)→主オブジェクトの積み上げ集計項目が更新→主オブジェクトのApexトリガ(2)」の処理が行われたとき、(1)の静的変数は(2)でも維持されます。

> 静的変数は、Apex トランザクションの範囲内でのみ静的です。サーバ全体または組織全体で静的なわけではありません。静的変数の値は、1 回のトランザクションのコンテキスト内で保持され、トランザクションの境界を超えたときにリセットされます。たとえば、Apex DML 要求によってトリガが何回も起動される場合、これらのトリガ呼び出しを通して静的変数は保持されます。(Apex 開発者ガイド)

## 数式項目
* 数式項目は任意の方法で項目にアクセスするたびにその結果を計算しリアルタイムに表示します。
    * ワークフロールールがその条件や式に数式項目を使用している場合、ワークフロールールの条件がチェックされたときに、その数式項目は計算されます。
    * トリガのTrigger.oldはデータベースから元のレコードが読み込まれたとき、Trigger.newは要求から新しいレコード項目の値が読み込まれ、古い値を上書きされた時に計算されます。

## 保存前更新を実行するフロー
<!-- * 保存前更新を実行するフローを使用する際は、フロービルダーで「レコードトリガフロー」を選択し、開始の設定のフローを実行で「レコードが保存される前」を選択します。 -->
* 保存前更新を実行するフローが複数存在する場合、実行順序は制御できません。
* レコード所有者のみの変更では、レコードトリガフローは起動されません。

## トリガ
* 同一オブジェクトに複数のトリガがある場合、実行順序は制御できません。
* 複数のトリガがあっても、triggerファイル単位で「Beforeトリガ処理→Afterトリガ処理」が行われるわけでなく、上記手順5.ですべてのBeforeトリガが実施され、上記手順9.ですべてのAfterトリガが実施されます。
* 項目自動更新やプロセスビルダーの項目更新、Afterトリガでのアップデートなどを行うと、再度トリガが実行されます。
    * 同一トランザクションで、初回の実行時のみに処理を行いたい場合は、静的変数を利用します。
    * BeforeInsert・AfterInsertのあとに再度トリガが実行された場合はBeforeUpdate・AfterUpdateが実施されます。
    * 2回目以降のトリガ実行であっても、Trigger.oldはトランザクションの直前の値が使用されます(注:Insertトリガのあとに実施されるUpdateトリガでもTrigger.old、Trigger.oldMapにオブジェクトは格納されています)。
* BeforeトリガはDBに保存される前なので、BeforeInsert時は、作成日・作成者・最終更新日・最終更新者・自動採番項目・IDがnullとなります。BeforeUpdate時は、Trigger.newでも最終更新日・最終更新者の値が古いままとなります(ただし項目自動更新などで再度トリガが実施される場合のTrigger.newは最新の値)。
* Beforeトリガ・Afterトリガともに親の積上げ集計項目の計算より先に実行されます。なので、トリガの中で親の積上げ集計項目を参照するときは古い値になります。
* カスケード削除などではトリガは実行されない（[トリガを呼び出さない操作 | Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.244.0.apexcode.meta/apexcode/apex_triggers_ignoring_operations.htm)）。

## 入力規則
* Insert時は、自動採番項目・ID項目・作成者・最終更新者はnull扱いとなります。
* Insert時は、作成日・最終更新日を使用した式は無視されます。[^validationlule-1]
    * なので、特定の日付以降に作成されたレコードのみ入力規則を実施したい場合は`&& (DATEVALUE(CreatedDate) >= DATE(2020,05,06) || ISNEW())`のように`ISNEW()`を併用する必要があります。
* カスタム入力規則は、入力値ではなくbeforeトリガ後の値で評価されます。
* 入力規則は親の積上げ集計項目の計算より先に実行されます。なので、入力規則のなかで親の積上げ集計項目を参照するのは避けるべきです。主オブジェクトの入力規則で積上げ集計項目を使用するとつねに更新後の値で判定されます(従オブジェクトの更新で主オブジェクトの積上げ集計項目が更新されると主オブジェクトの入力規則が判定されます)。

## 積み上げ集計項目
* 親レコードに対する編集アクセス権限がない場合でも、親レコードが更新されます。
* 主オブジェクトの積み上げ集計項目が変更されるような従オブジェクトの更新は、主オブジェクトに対して上述の全処理フローが実施されます。

## ワークフロー項目自動更新
* 同一オブジェクトに複数のワークフロー項目自動更新がある場合、実行順序は制御できません。
* ワークフロー項目自動更新でレコードが更新された場合、下記が実行されます(<font color="Red">カスタム入力規則、フロー、重複ルール、ワークフロー、プロセスビルダーおよびエスカレーションルールは<strong>再実行されません</strong></font>)。
    * 標準の入力規則
    * BeforeUpdate トリガ
    * AfterUpdate トリガ
* 時間依存のアクションに基づくワークフロー項目更新は、いかなるルールもトリガしません。
* 「項目変更後にワークフロールールを再評価する」にチェックをすると、更新が起きたレコードに対し、すべてのワークフロールールが検証され、条件を満たしているワークフローが実施されます。
* 変更前と変更後の値が一致しているときは項目自動更新が実施されないため、Apexトリガを再実行しません。
* 項目レベルセキュリティの影響を受けません。

### クロスオブジェクトの項目自動更新
* 親レコードに対する編集アクセス権限がない場合でも、親レコードが更新されます。
* 主オブジェクトの積み上げ集計項目が変更されるような従オブジェクトの更新は、主オブジェクトに対して上述の全処理フローが実施されます。

## プロセスビルダー
* 同一オブジェクトに複数のプロセスビルダーがある場合、実行順序は制御できません。
* 処理中に呼ばれたプロセスビルダーでレコードの更新が行われると、<font color="Red">再度Apexトリガ、カスタム入力規則、重複ルール、エスカレーションルールが実行されます</font>。
* 「この条件を評価した後の操作を指定」で「次の条件を評価」を選び、次のアクションで再度レコードを更新すると再度Apexトリガが実行されます。
* アクション「レコードの更新」は、項目レベルセキュリティの影響を受けません。

## その他
<!-- TODO
### 複数行レイアウトについて
-->

### リードの取引開始について
* リード設定 [取引開始済みのリードに入力規則が必須] を有効化しない限り、リードの取引開始時に上述の処理フローは実施されません。

### 承認プロセスについて
* 承認プロセスではクロスオブジェクトの項目自動更新を含めることはできません。
* 「項目変更後にワークフロールールを再評価する」の項目自動更新によって、ワークフロールールの判定が行われたとき、クロスオブジェクトの項目自動更新は実施されません。
* 承認プロセスによる項目自動更新ではカスタム入力規則は実施されません([idea](https://trailblazer.salesforce.com/ideaview?id=087300000007lcTAAQ))。

## 参考
* 全般
    * [トリガと実行順序 | Apex 開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm)
    * [Salesforce-Order-Of-Execution-Diagram.png (3401×2297)](https://architect.salesforce.com/1/asset/immutable/s/e6cf2ac/assets/images/Salesforce-Order-Of-Execution-Diagram.png)
    * [Order of Execution (Rules, Triggers etc.) in Salesforce & Debug Log](https://www.asagarwal.com/order-of-execution-rules-triggers-etc-in-salesforce-debug-log/)
* トランザクション
    * [Apex のトランザクション | Apex 開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_transaction.htm)
    * [Apex ガバナ制限 | Salesforce Developer の制限および割り当てクイックリファレンス
](https://developer.salesforce.com/docs/atlas.ja-jp.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm)
    * [静的メソッドとインスタンスメソッド、変数、初期化コード | Apex 開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_static.htm)
* 数式項目
    * [オートメーションルール、および、Apex トリガはどのような順番で処理されますか？ | 公式ナレッジ](https://help.salesforce.com/articleView?id=000327325&language=ja&type=1&mode=1)
* 保存前更新を実行するフロー
    * [保存前更新を実行するフローのレコードトリガ | Salesforceヘルプ](https://help.salesforce.com/articleView?id=flow_concepts_trigger_record.htm&type=5)
    * [フロー内の保存前更新を使用した新規レコードと変更されたレコードの 10 倍速い更新 | Salesforce Spring '20 リリースノート](https://releasenotes.docs.salesforce.com/ja-jp/spring20/release-notes/rn_forcecom_flow_fbuilder_before_save_updates.htm)
* トリガ
    * [静的メソッドとインスタンスメソッド、変数、初期化コード | Apex 開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_static.htm)
    * [ワークフローとトリガを同時に使用する際トリガを２回起動しない方法はありますか | 公式ナレッジ](https://help.salesforce.com/articleView?id=000325747&language=ja&type=1&mode=1)
* 入力規則
    * [過去レコードの編集時に発生する 入力規則エラーを回避したい | AGORA](https://www.pasonatquila.com/blog/agora/bu3042_salesforce_validation_rules.html)
* 積上げ集計項目
    * [積み上げ集計項目 | Salesforceヘルプ](https://help.salesforce.com/articleView?id=fields_about_roll_up_summary_fields.htm&type=5) 
* ワークフロールール
    * [ワークフロールールを再評価する項目自動更新 | Salesforceヘルプ](https://help.salesforce.com/articleView?id=workflow_field_updates_reevalute_wf.htm&type=5)
    * [クロスオブジェクトの項目更新 | Salesforceヘルプ](https://help.salesforce.com/articleView?id=workflow_cross_object_field_updates.htm&type=5)
* プロセスビルダー
    * [プロセスでレコードの変更が評価されるタイミング | Salesforceヘルプ](https://help.salesforce.com/articleView?id=process_considerations_works.htm&type=5)

<!-- 脚注 -->
[^list-2]: この段階で「作成日・作成者・最終更新日・最終更新者・ID・自動採番項目」が設定されます。
[^validationlule-1]: 「OR(CreatedDate <> null, CreatedDate = null)」でもエラーになりませんでした。