“紙の稟議”感覚でOK！別オブジェクトによるシンプルなSalesforce承認管理

## はじめに  
Salesforce標準の承認機能は「商談の値引きが20%以上になると自動申請→レコードロック」といった便利な自動化を提供します。しかし、導入初期の日本企業では運用ルールが固まらず、設定のハードルも高いため、思いどおりに動かせないケースが少なくありません。  
そこで本記事では、まず“申請と承認の記録”だけをシンプルに残し、運用が定まってから自動化を段階的に追加した際の事例を紹介します。

## 承認機能の問題と解決の方向性
Salesforceには上長により承認状況を記録できる機能があります。
例えば商談の値引きを20%以上で設定すると、自動的に承認申請が飛び、承認待ちの間には編集が出来ないようにロックする等の自動化ができます。

便利ではありますが、Salesforceの導入段階では鬼門だと思っております。
導入初期は運用ルールが流動的なのに、標準承認機能は“固定化”を前提に設計されているため、柔軟に試せません。
例えば「申請先をピックリストで指定→条件分岐の組み合わせ」でルート設定しますが、慣れない担当者には“分岐の組み合わせ”の理解に時間がかかります。

そこで私が今回提案するのは「美しい制御の前にとりあえず申請と承認状況の記録だけは安全に残し、その運用が回ってからレコードロック等の自動化をしませんか？」というものです。
やっていることは紙で稟議申請をしていたときと同様に、
稟議申請書とそれに関わる資料がまとまっているようにします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017914/71158aea-c093-40e4-a418-0cc6d1ae310b.png)

## 機能概要

本構築では「申請する対象のオブジェクトの子レコードとして汎用申請オブジェクトを用いて記録を残す」アプローチを取っております。

```mermaid
 erDiagram
      "申請する対象" ||--|{ "汎用申請" : has
```
このように「申請する対象 ← 汎用申請レコード」という親子構造で“まずは申請と記録だけ”を安全に試せる設計です。運用ルールや承認ルートが固まった後にレコードロックや自動通知をフェーズ２として追加することを目指してもらうものです。

また、申請承認ルートもすでにシステム化されていない場合は以下のような状況も多いでしょう。
* 決まっているようで決まっていない
* 例外が多発
このため、よくある申請承認ルートの例をいくつか用意して試せるようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017914/666c5e53-8d96-4b82-8e5e-1788e417ecfc.png)

* 手動で1名を選択する(申請者→最終承認者)
* 私のマネージャー(申請者→最終承認者)
* 手動で1名を選択する(申請者→承認者→最終承認者)
* 私のマネージャー(申請者→承認者→最終承認者)
* 独自設定(申請者→承認者→最終承認者)

これ以上複雑な場合はフローを開発するなど独自の手段を取る必要があります。
まずは標準のプロセスで可能なのかを試していただけるようにしています。

## 設定手順

### オブジェクトの作成

汎用申請オブジェクトを作成します。
尚、オブジェクトと項目の作成をショートカットしたい方の為にパッケージを用意しました。※承認プロセスはパッケージに入れられないため、ご自身で作成ください。
https://login.salesforce.com/packaging/installPackage.apexp?p0=04tWU0000008Bj3


| 項目の表示ラベル       | 項目名                           | データ型                          | 制御項目 | インデックス付 |
| :--------------------- | :------------------------------- | :------------------------------- | :------: | :------------: |
| 作成者                 | CreatedById                      | 参照関係(ユーザー)               |          |                |
| 商品                   | Product__c                       | 参照関係(商品)                   |    ✓     |                |
| 商談                   | Opportunity__c                   | 参照関係(商談)                   |    ✓     |                |
| 所有者                 | OwnerId                          | 参照関係(ユーザー, グループ)     |    ✓     |                |
| 承認済印               | ApprovedImage__c                 | 数式(テキスト)                   |          |                |
| 承認者                 | Approver__c                      | 参照関係(ユーザー)               |    ✓     |                |
| 承認者の選択方法       | ApproverSelectionMethod__c       | 選択リスト                       |          |                |
| 最終承認済             | IsFinalApproved__c               | チェックボックス                 |          |                |
| 最終承認者             | FinalApprover__c                 | 参照関係(ユーザー)               |    ✓     |                |
| 最終更新者             | LastModifiedById                 | 参照関係(ユーザー)               |          |                |
| 汎用申請名             | Name                             | 自動採番                         |    ✓     |                |
| 説明                   | Decription__c                    | ロングテキストエリア(32768)      |          |                |

### 承認プロセスの作成

承認プロセスを作成します。
承認者の選択方法別に作ります。
サンプル用に4種類作っていますが、実際は必要なところだけご用意ください。

#### 1. 汎用申請: 手動選択承認（申請者→最終承認者）

| 項目                                   | 値                                                                                      |
| :------------------------------------- | :-------------------------------------------------------------------------------------- |
| プロセス名                             | 汎用申請: 手動選択承認（申請者→最終承認者）                                              |
| API 名称 (一意の名前)                  | Manual_Select_ApplicantToFinal                                                          |
| 有効                                   | ✓                                                                                       |
| 説明                                   | 割り当て先として使用するユーザー項目                                                    |
| 開始条件                               | 汎用申請: 承認者の選択方法 が「手動で1名を選択する（申請者→最終承認者）」と一致        |
| 編集権限                               | システム管理者のみ                                                                       |
| 申請者                                 | 汎用申請: 所有者                                                                         |
| 申請者に承認申請の取り消しを許可       | ✓                                                                                       |

##### 申請時のアクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集できないようにロックする |

#### 承認ステップ

| 順番 | 名前             | 説明 | 条件       | 割り当て先     | 却下時の処理 |
| :--- | :--------------- | :--- | :--------- | :------------- | :----------- |
| 1    | 最終承認者承認   |      | 手動で選択 | （手動で選択） | 最終却下     |

#### 最終承認時のアクション

| アクション             | 種別         | 説明                              |
| :---------------------- | :----------- | :-------------------------------- |
| レコードのロック        | レコードのロック | レコードを編集できないようにロックする |
| UpdateIsFinalApproval   | 項目自動更新 | UpdateIsFinalApproval              |

#### 2. 汎用申請: マネージャー承認（申請者→最終承認者）

| 項目                                   | 値                                                                                                        |
| :------------------------------------- | :---------------------------------------------------------------------------------------------------------- |
| プロセス名                             | 汎用申請: マネージャー承認（申請者→最終承認者）                                                            |
| API 名称 (一意の名前)                  | Manager_Approval_ApplicantToFinal                                                                          |
| 有効                                   | ✓                                                                                                         |
| 説明                                   | 割り当て先として使用するユーザー項目（レコード申請者のマネージャー）                                      |
| 開始条件                               | 汎用申請: 承認者の選択方法 が「私のマネージャー(申請者→最終承認者)」と一致                                |
| 編集権限                               | システム管理者のみ                                                                                         |
| 申請者                                 | 汎用申請: 所有者                                                                                           |
| 申請者に承認申請の取り消しを許可       |                                                                                                           |


##### 申請時のアクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集できないようにロックする |

#### 承認ステップ

| 順番 | 名前             | 説明 | 条件 | 割り当て先   | 却下時の処理 |
| :--- | :--------------- | :--- | :--- | :------------ | :----------- |
| 1    | マネージャー承認 |      |      | マネージャー | 最終却下     |

#### 最終承認時のアクション

| アクション             | 種別         | 説明                                       |
| :---------------------- | :----------- | :----------------------------------------- |
| レコードのロック        | レコードのロック | レコードを編集できないようにロックする      |
| UpdateIsFinalApproval   | 項目自動更新 | UpdateIsFinalApproval                       |

#### 最終却下時のアクション

| アクション       | 種別             | 説明                                 |
| :--------------- | :--------------- | :----------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

#### 取消アクション

| アクション       | 種別             | 説明                                 |
| :--------------- | :--------------- | :----------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

#### 汎用申請: 手動選択承認（申請者→承認者→最終承認者）

| 項目                                   | 値                                                                                                            |
| :------------------------------------- | :-------------------------------------------------------------------------------------------------------------- |
| プロセス名                             | 汎用申請: 手動選択承認（申請者→承認者→最終承認者）                                                              |
| API 名称 (一意の名前)                  | Manual_Select_ApplicantToApprToFinal                                                                          |
| 有効                                   | ✓                                                                                                             |
| 説明                                   | 割り当て先として使用するユーザー項目                                                                            |
| 開始条件                               | 汎用申請: 承認者の選択方法 が「手動で1名を選択する(申請者→承認者→最終承認者)」と一致                            |
| 編集権限                               | システム管理者のみ                                                                                             |
| 申請者                                 | 汎用申請: 所有者                                                                                               |
| 申請者に承認申請の取り消しを許可       |                                                                                                               |

##### 申請時のアクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集できないようにロックする |

#### 承認ステップ

| 順番 | 名前             | 説明 | 条件 | 割り当て先     | 却下時の処理 |
| :--- | :--------------- | :--- | :--- | :------------- | :----------- |
| 1    | 承認者承認       |      |      | 手動で選択     | 最終却下     |
| 2    | 最終承認者承認   |      |      | 手動で選択     | 最終却下     |

##### 最終承認時のアクション

| アクション             | 種別         | 説明                                       |
| :---------------------- | :----------- | :----------------------------------------- |
| レコードのロック        | レコードのロック | レコードを編集できないようにロックする      |
| UpdateIsFinalApproval   | 項目自動更新 | UpdateIsFinalApproval                       |

##### 最終却下時のアクション

| アクション       | 種別             | 説明                                 |
| :--------------- | :--------------- | :----------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

##### 取消アクション

| アクション       | 種別             | 説明                                 |
| :--------------- | :--------------- | :----------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

#### 汎用申請: マネージャー承認（申請者→承認者→最終承認者）

| 項目                                 | 値                                                                                                      |
| :----------------------------------- | :------------------------------------------------------------------------------------------------------ |
| プロセス名                           | 汎用申請: マネージャー承認（申請者→承認者→最終承認者）                                                  |
| API 名称 (一意の名前)                | Manager_Approval_ApplicantToApprToFinal                                                                |
| 有効                                 | ✓                                                                                                       |
| 説明                                 | 割り当て先として使用するユーザー項目                                                                    |
| 開始条件                             | 汎用申請: 承認者の選択方法 が「私のマネージャー(申請者→承認者→最終承認者)」と一致                      |
| 編集権限                             | システム管理者のみ                                                                                     |
| 申請者                               | 汎用申請: 所有者                                                                                         |
| 申請者に承認申請の取り消しを許可     |                                                                                                         |

##### 申請時のアクション

| アクション       | 種別             | 説明                                 |
| :--------------- | :--------------- | :----------------------------------- |
| レコードのロック | レコードのロック | レコードを編集できないようにロックする |

##### 承認ステップ

| 順番 | 名前             | 説明 | 条件 | 割り当て先   | 却下時の処理 |
| :--- | :--------------- | :--- | :--- | :------------- | :----------- |
| 1    | マネージャー承認 |      |      | マネージャー | 最終却下     |
| 2    | 2ndMgr承認       |      |      | マネージャー | 最終却下     |

##### 最終承認時のアクション

| アクション           | 種別         | 説明                                     |
| :-------------------- | :----------- | :--------------------------------------- |
| レコードのロック      | レコードのロック | レコードを編集できないようにロックする    |
| UpdateIsFinalApproval | 項目自動更新 | UpdateIsFinalApproval                     |

##### 最終却下時のアクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

##### 取消アクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

#### 汎用申請: 独自設定承認（申請者→承認者→最終承認者）

| 項目                             | 値                                                                                              |
| :------------------------------- | :------------------------------------------------------------------------------------------------ |
| プロセス名                       | 汎用申請: 独自設定承認（申請者→承認者→最終承認者）                                               |
| API 名称 (一意の名前)            | CustomApproval_ApplToApprToFinal                                                                 |
| 有効                             | ✓                                                                                               |
| 説明                             | 割り当て先として使用するユーザー項目                                                             |
| 開始条件                         | 汎用申請: 承認者の選択方法 が「独自設定(申請者→承認者→最終承認者)」と一致                       |
| 編集権限                         | システム管理者のみ                                                                              |
| 申請者                           | 汎用申請: 所有者                                                                                |
| 申請者に承認申請の取り消しを許可 |                                                                                                |

##### 申請時のアクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集できないようにロックする |

##### 承認ステップ

| 順番 | 名前             | 説明 | 条件 | 割り当て先               | 却下時の処理 |
| :--- | :--------------- | :--- | :--- | :------------------------- | :----------- |
| 1    | 第1承認者承認    |      |      | 関連ユーザー: 承認者      | 最終却下     |
| 2    | 最終承認者承認  |      |      | 関連ユーザー: 最終承認者  | 最終却下     |

##### 最終承認時のアクション

| アクション           | 種別         | 説明                                       |
| :-------------------- | :----------- | :----------------------------------------- |
| レコードのロック      | レコードのロック | レコードを編集できないようにロックする      |
| UpdateIsFinalApproval | 項目自動更新 | UpdateIsFinalApproval                       |

##### 最終却下時のアクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

##### 取消アクション

| アクション       | 種別             | 説明                               |
| :--------------- | :--------------- | :--------------------------------- |
| レコードのロック | レコードのロック | レコードを編集するためにロック解除する |

### Lightning Pageの工夫
承認後にもボタンが出てしまうと混乱しますので、最終承認済であれば承認申請ボタンが出ないようにするとわかりやすいかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017914/ad6ea780-f1a1-48bb-9b2a-0ac2a039cda7.png)

### おまけ　画像で承認状況を見せる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017914/f085a80a-8318-41a9-80af-4931bbb8a316.png)
最終承認済になると、印鑑画像が出るようにしました。何故だかこういうのが喜ばれます…
静的リソースに画像をアップロードし、以下の数式を作ります。
```
IF( IsFinalApproved__c ,
    IMAGE("/resource/FinalApproval","最終承認済スタンプ",120,120),
    "未承認"
  )
```