【Apex】リードの取引開始アクション

本記事は、Salesforceのリードの取引開始を行うフローから利用可能なアクションの作成方法をまとめます。

## リードの取引開始の方法
リードの取引開始を実行するには、基本的には下記のいずれかの方法を使用する必要があります。

- リードの取引開始の標準アクションを使用
- Apexの`Database.convertLead`メソッドを使用

上記により、フローでリードの取引開始を行う場合はApexアクションを準備する必要があります。
リードの取引開始をApexで実装する場合、`Database.convertLead`メソッドに対して取引開始時の各種情報を設定した[Database.LeadConvert](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_dml_convertLead.htm)オブジェクトを渡す必要がありますが、このオブジェクトをフローで取り扱うことができないことから、本記事では設定する各種情報をアクションの引数として定義する方針を採ります。

:::note info
フローのみで __「リードの取引開始のような機能」__ を構築することは可能ですが、Salesforceの標準機能の様々な恩恵を享受するには上記のいずれかの方法を使用する必要があります。
これは、リードの取引開始に関連する下記の各標準項目が上記の機能でのみ設定可能であることに起因します。

|            項目名            |       API参照名        | 内容                                 |
| :--------------------------: | :--------------------: | :----------------------------------- |
|          取引開始日          |     ConvertedDate      | 取引開始の処理をした日付             |
|         取引開始済み         |      IsConverted       | 取引開始済みのリードを判別するフラグ |
|    取引開始済みの取引先ID    |   ConvertedAccountId   | 取引開始による変換先の取引先ID       |
| 取引開始済みの取引先責任者ID |   ConvertedContactId   | 取引開始による変換先の取引先責任者ID |
|     取引開始済みの商談ID     | ConvertedOpportunityId | 取引開始による変換先の商談ID         |

:::

## Apexによるリードの取引開始のアクションの作成
フローから利用可能なアクションは下記のように作成することができます。
```apex:LeadConvertAction.cls
public without sharing class LeadConvertAction {
    public class Request {
        @InvocableVariable(label='Lead ID' required=true)
        public String leadId;
        @InvocableVariable(label='Converted Status' required=true)
        public String status;
        @InvocableVariable(label='Account ID' required=false)
        public String accountId;
        @InvocableVariable(label='Contact ID' required=false)
        public String contactId;
        @InvocableVariable(label='Person Account ID' required=false)
        public String personId;
        @InvocableVariable(label='Opportunity ID' required=false)
        public String opportunityId;
        @InvocableVariable(label='Owner ID' required=false)
        public String ownerId;
        @InvocableVariable(label='Do Not Create Opportunity' required=false)
        public Boolean createOpportunity;
        @InvocableVariable(label='Opportunity Name' required=false)
        public String opportunityName;
        @InvocableVariable(label='Overwrite Lead Source' required=false)
        public Boolean overwriteLeadSource;
        @InvocableVariable(label='Send Notification Email' required=false)
        public Boolean sendEmail;
    }
    public class Result {
        @InvocableVariable(label='Success')
        public Boolean isSuccess;
        @InvocableVariable(label='Error Messages')
        public List<String> errorMessages;
    }
    @InvocableMethod(label='Lead Convert' description='Lead Convert' category='Apex')
    public static List<Result> convertLeads( List<Request> requests ){
        List<Database.LeadConvert> leadConverts = new List<Database.LeadConvert>();
        for( Request requestObj : requests ){
            leadConverts.add( createLeadConvert( requestObj ) );
        }
        List<Database.LeadConvertResult> leadConvertResults = Database.convertLead( leadConverts , false );
        List<Result> results = new List<Result>();
        for( Database.LeadConvertResult leadConvertResultObj : leadConvertResults ){
            results.add( createResult( leadConvertResultObj ) );
        }
        return results;
    }
    private static Database.LeadConvert createLeadConvert( Request requestObj ){
        Database.LeadConvert leadConvertObj = new Database.LeadConvert();
        leadConvertObj.setLeadId( requestObj.leadId );
        leadConvertObj.setConvertedStatus( requestObj.status );
        if( requestObj.accountId           != null ){ leadConvertObj.setAccountId( requestObj.accountId );                      }
        if( requestObj.contactId           != null ){ leadConvertObj.setContactId( requestObj.contactId );                      }
        if( requestObj.personId            != null ){ leadConvertObj.setRelatedPersonAccountId( requestObj.personId );          }
        if( requestObj.opportunityId       != null ){ leadConvertObj.setOpportunityId( requestObj.opportunityId );              }
        if( requestObj.ownerId             != null ){ leadConvertObj.setOwnerId( requestObj.ownerId );                          }
        if( requestObj.createOpportunity   != null ){ leadConvertObj.setDoNotCreateOpportunity( requestObj.createOpportunity ); }
        if( requestObj.opportunityName     != null ){ leadConvertObj.setOpportunityName( requestObj.opportunityName );          }
        if( requestObj.overwriteLeadSource != null ){ leadConvertObj.setOverwriteLeadSource( requestObj.overwriteLeadSource );  }
        if( requestObj.sendEmail           != null ){ leadConvertObj.setSendNotificationEmail( requestObj.sendEmail );          }
        return leadConvertObj;
    }
    private static Result createResult( Database.LeadConvertResult leadConvertResultObj ){
        Result resultObj = new Result();
        resultObj.isSuccess = leadConvertResultObj.isSuccess();
        resultObj.errorMessages = new List<String>();
        for( Database.Error error : leadConvertResultObj.getErrors() ){
            resultObj.errorMessages.add( error.getMessage() );
        }
        return resultObj;
    }
}
```

#### 基本的な仕様
リードの取引開始のアクションを呼び出す際に指定する値は下記のように対応します。

|        変数         | 必須 | 指定する内容                                                                                                                                                                                                        |
| :-----------------: | :--: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|       leadId        | 必須 | 取引開始するリードのIDを指定する。                                                                                                                                                                                  |
|       status        | 必須 | 取引開始後のリードの状況を指定する。                                                                                                                                                                                |
|      accountId      |  ー  | 取引開始で既存の取引先にマージする場合に既存の取引先のIDを指定する。指定しない場合は取引先が新規作成される。                                                                                                        |
|      contactId      |  ー  | 取引開始で既存の取引先責任者にマージする場合に既存の取引先責任者のIDを指定する。指定した取引先責任者に紐づく取引先は`accountId`で指定する取引先と一意する必要がある。指定しない場合は取引先責任者が新規作成される。 |
|      personId       |  ー  | 取引開始で既存の個人取引先にマージする場合に既存の個人取引先のIDを指定する。指定しない場合はリードの会社名項目の入力がないときに限り個人取引先が新規作成される。                                                    |
|    opportunityId    |  ー  | 取引開始で既存の商談にマージする場合に既存の商談のIDを指定する。指定しない場合は`createOpportunity`がTRUEでない場合に限り商談が新規作成される。                                                                     |
|       ownerId       |  ー  | 新規作成されるレコードの所有者のIDを指定する。指定しない場合はリードの所有者が新規作成されたレコードの所有者となる。                                                                                                |
|  createOpportunity  |  ー  | 商談を新規作成するか否かを指定する。TRUEの場合は商談を新規作成しない。                                                                                                                                              |
|   opportunityName   |  ー  | 商談を新規作成する場合に商談名を指定する。                                                                                                                                                                          |
| overwriteLeadSource |  ー  | 変換先の取引先責任者のリードソース項目を上書きするか否かを指定する。TRUEの場合は`contactId`で指定された取引先責任者のリードソース項目をリードのリードソース項目で上書きする。                                       |
|      sendEmail      |  ー  | 新しい所有者に通知メールを送信するか否かを指定する。TRUEの場合は`ownerId`で指定された所有者へ通知メールを送信する。                                                                                                 |