Apexで承認申請・承認・却下を実行する(サンプルコードつき)

承認プロセスのオブジェクトを理解して、Apexで扱ってみましょう!

はじめに

この記事をご覧のみなさま、承認プロセスはお好きでしょうか?
私は好きです。好きになってしまいました。
さて、今回は承認プロセスのオブジェクトのご紹介と、Apexで承認の申請・承認・却下を実行する方法のご紹介です。
標準の承認プロセス機能だけでは実現できない場面に遭遇したらぜひご覧ください。

承認プロセスで登場するオブジェクト

承認プロセスのオブジェクトを理解しておきましょう。
基本的には以下のオブジェクトを抑えておけばOKです!
・ProcessDefinition:承認プロセスの定義
・ProcessNode:承認ステップの定義
・ProcessInstance:申請した承認プロセス
・ProcessInstanceStep:完了したステップのアクション
・ProcessInstanceWorkItem:承認待ちとなっているステップ
・ProcessInstanceNode:承認ステップの承認状況

・ProcessInstanceHistory:承認プロセスに関連付けられたすべてのステップと未承認の申請を表示
簡単に言ってしまえば『Instance』とつくオブジェクトは今動いている(動いた)情報でそれ以外は定義情報だと思ってよいかと思います!
詳細は参考記事・サイトを見ていただければわかりやすいです。
ワークフロー、承認に関するオブジェクト - Salesforce Developers
標準オブジェクト - Salesforce Developers

オブジェクトの取得(SOQL)

それではそれぞれのレコードを取得してみましょう。
今回は承認ステップが2段階の承認プロセスを使用します。
申請をして、一次承認が通った状態で取得していきます。

ProcessDefinition

SELECT Id, Name, DeveloperName, Type, Description, TableEnumOrId, LockType, State 
FROM ProcessDefinition 
WHERE Type = 'Approval'
ProcessDefinition

ProcessNode

SELECT Id, Name, DeveloperName, ProcessDefinitionId, Description 
FROM ProcessNode 
WHERE ProcessDefinitionId = '{ProcessDefinitionのId}'
ProcessNode

ProcessInstance

SELECT Id,ProcessDefinitionId,TargetObjectId,CompletedDate,LastActorId,ElapsedTimeInDays,ElapsedTimeInHours,ElapsedTimeInMinutes 
FROM ProcessInstance 
WHERE TargetObjectId = '{関連先レコードのId(今回はケースのレコードID)}'
ProcessInstance

ProcessInstance

ProcessInstanceStep

SELECT Id,ProcessInstanceId,StepStatus,OriginalActorId,ActorId,Comments,StepNodeId,ElapsedTimeInDays,ElapsedTimeInHours,ElapsedTimeInMinutes 
FROM ProcessInstanceStep
ProcessInstanceStep

ProcessInstanceStep

ProcessInstanceWorkItem

SELECT Id,ProcessInstanceId,OriginalActorId,ActorId,ElapsedTimeInDays, ElapsedTimeInHours, ElapsedTimeInMinutes
FROM ProcessInstanceWorkItem
WHERE ProcessInstanceId = '{ProcessInstanceのId}'
ProcessInstanceWorkItem

ProcessInstanceNode

SELECT Id, ProcessInstanceId, ProcessNodeId, NodeStatus, LastActorId, ElapsedTimeInDays, ElapsedTimeInHours, ElapsedTimeInMinutes 
FROM ProcessInstanceNode 
WHERE ProcessInstanceId = '{ProcessInstanceのId}'
ProcessInstanceNode

ProcessInstanceHistory

こちらは取得できません。実行してみると画像のエラーになります。
ProcessInstanceHistoryのオブジェクトリファレンス

レコードを取得してみて

ここでそれぞれのオブジェクトのレコード数を比較してみましょう。
ProcessDefinitionは承認プロセスの定義情報なので1レコード
ProcessNodeは承認プロセスに紐づくステップの定義情報なので2レコード
ProcessInstanceは実行されている承認プロセスなので1レコード
ProcessInstanceStepは申請ステップ、一次承認ステップで2レコード
ProcessInstanceWorkItemは二次承認待ちステップで1レコード
ProcessInstanceNodeは承認された一次承認、承認待ちの二次承認で2レコード

この情報を使えば、承認ステップの残りステップ数もカウントできそうです。
ProcessNode2レコードあります。
ProcessInstanceStepは完了したステップのアクションなので、2レコードありますが、申請ステップは引いて1レコード。
そのため、以下の計算式になりますね。
ProcessNodeのレコード数 - (ProcessInstanceStepのレコード数 - 申請ステップの1レコード) = 残りのステップ数

Apexで実行

ここからは、承認プロセスをApexで動かしていきましょう。
基本的に使用するのはシステム名前空間のApproval クラスと承認名前空間の各クラスです。
今回はメインとなるアクションの申請、承認、却下をしていきます。
Approvalクラスのリファレンス
承認名前空間のリファレンス

申請

まずは、先ほど作成した二次承認の承認プロセスをApexで申請します。
今回使う承認ステップは『申請者が承認者を手動で選択する。』設定にしているので、割り当て先も指定します。
Approval.ProcessSubmitRequest psr = new Approval.ProcessSubmitRequest();

//承認プロセスを指定
psr.setProcessDefinitionNameOrId('ApprovalProcess_2Step');//承認プロセスの一意の名前かIdを指定

//申請するレコードを指定
psr.setObjectId('500J2000009PZpqIAG');//申請するレコードのIdを指定(今回はケースのレコードId)

//申請者Idを指定
psr.setSubmitterId('0055h000002dAzh');//申請を実行するユーザーのIdを指定

//次の承認者の設定
psr.setNextApproverIds(new Id[]{'0055h000008iyX7'});//次の承認者のユーザーIdを含むリストを指定※キューのグループIDを指定でも可

//実行&結果取得
Approval.ProcessResult result = Approval.process(psr);
System.debug(result);
申請Apexサンプルコード

ちゃんと申請ができていることが確認できました!
実行結果も載せておきますね。
isSuccessやgetErrorsを使えばエラー処理も作れますし、getInstanceStatusの値によっては、最終承認かの判断もつきそうです!
Approval.ProcessResult[getActorIds=(0055h000008iyX7AAI);getEntityId=500J2000009PZpqIAG;getErrors=null;getInstanceId=04gJ200000403qBIAQ;getInstanceStatus=Pending;getNewWorkitemIds=(04iJ20000040mSRIAY);isSuccess=true;]
実行結果

承認・却下

次に先ほどの承認申請を承認・却下していきましょう。
※承認する際に、承認先が自動割り当てや、その承認ステップが最終承認の場合は、次の承認者の指定は不要なのでお気をつけください。
Approval.ProcessWorkitemRequest pwr = new Approval.ProcessWorkitemRequest();

//承認するProcessWorkitemレコードを指定
pwr.setWorkitemId('04iJ20000040mSRIAY');//ProcessWorkitemのレコードIdを指定

//次の承認者の設定
pwr.setNextApproverIds(new Id[]{'0055h000008iyXC'});

//アクションの設定(Approve:承認、 Reject:却下、 Removed:削除(システム管理者のみ))
pwr.setAction('Approve');

//コメントの設定
pwr.setComments('承認します。');

//実行&結果取得
Approval.ProcessResult result = Approval.process(pwr);
System.debug(result);
承認Apexサンプルコード

ちゃんと承認ができていることが確認できましたね!
却下はアクションの指定を変えてあげれば簡単にできます。
Approval.ProcessWorkitemRequest pwr = new Approval.ProcessWorkitemRequest();

//却下するProcessWorkitemレコードを指定
pwr.setWorkitemId('04iJ20000040mUwIAI');

//アクションの設定(Approve:承認、 Reject:却下、 Removed:削除(システム管理者のみ))
pwr.setAction('Reject');

//コメントの設定
pwr.setComments('却下します。');

//実行&結果取得
Approval.ProcessResult result = Approval.process(pwr);
System.debug(result);
却下Apexサンプルコード

さいごに

今回は承認プロセスのオブジェクトのご紹介と、Apexで申請から承認まで行う方法をご紹介しました。
承認プロセスのオブジェクト構成を理解すれば、Apexで扱うのも難しくはないと思います!
サンプルコードも載せていますので、実際にご自身で実行して理解を深めていただけると幸いです。
また、今回ご紹介したApexのメソッドはほんの一部に過ぎないので、リファレンスを確認して気になるメソッドがあれば、ぜひ試してみてください!

参考記事・サイト