承認プロセスをApexから申請・承認・照会する実装
承認プロセスを作成し、Approval.ProcessSubmitRequestで申請、Approval.ProcessWorkitemRequestで承認する流れをVisualforceの例とともに説明します。
シナリオ
カスタムオブジェクトに承認プロセスを設定します。レコードの申請と承認は、標準のボタンだけでなくApexからも操作できます。ここでは、承認待ちの一覧を出して選んだものだけ承認する画面を、Apexと承認プロセスの標準APIで作ります。
カスタムオブジェクトを準備する
承認対象になるカスタムオブジェクトを作成します。
オブジェクトを新規作成する
オブジェクトマネージャから新規作成します。表示ラベルを「承認テスト対象」、API参照名を
ApprovalTestObject__cとします。レコード名を自動採番にする
レコード名の項目を、テキストから自動採番へ変更します。表示形式は
TAPO-{0000}、開始番号は1にします。タブを作成する
作成したオブジェクトのタブを作成し、詳細を入力します。
プロファイルとアプリケーションに追加する
タブを表示するプロファイルを選び、使用するカスタムアプリケーションへ追加して保存します。
承認プロセスを作成する
承認プロセスの対象オブジェクトを選ぶ
設定の「承認プロセス」から、作成したカスタムオブジェクトを選び、「承認プロセスの新規作成」から「標準ウィザードを使用」を選びます。
名前と入力条件を設定する
プロセス名と一意の名前を入力します。承認の対象にするレコードの条件(入力条件)を設定します。
承認者項目とメールテンプレートを設定する
承認者が編集できる項目と、通知に使うメールテンプレートを選びます。
承認ページと申請者を設定する
承認ページレイアウトに表示する項目を選び、申請できるユーザーを指定して保存します。
承認ステップを作成する
「承認ステップを今すぐ作成します」を選び、ステップの条件と割り当て先(承認者)を設定します。
有効化する
承認プロセスの詳細画面から「有効化」します。
⚠️ 有効化するまで、このプロセスは申請に使えません。入力条件・承認者項目・承認ステップの3つが噛み合っていないと、意図しないレコードが承認待ちになったり、誰にも割り当たらなかったりします。
Apexで申請する ProcessSubmitRequest
承認プロセスへの申請は、標準ページの「承認申請」ボタンでもできますが、レコード作成と同じトランザクションでまとめて申請したい場合などはApexから行います。
Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest(); req.setObjectId(recordId); req.setComments('Apexから申請しました。'); req.setSubmitterId(UserInfo.getUserId()); Approval.ProcessResult result = Approval.process(req); System.debug(LoggingLevel.INFO, 'Submitted: ' + result.isSuccess());
レコードIdを指定して承認プロセスへ申請します。コメントは省略可能です。
setObjectId に渡したレコードに一致する承認プロセスが1つに決まらない場合は、setProcessDefinitionNameOrId で対象のプロセスを明示します。対象オブジェクトに有効な承認プロセスが無い場合や、入力条件に一致しない場合は失敗します。
Apexで承認待ちを照会する ProcessInstance
承認待ちの一覧は ProcessInstance と、その子である ProcessInstanceWorkitem を組み合わせて取得します。StepsAndWorkitems は、ステップの履歴と現在の承認待ちをまとめて返す関係名です。
List<ProcessInstance> instances = [
SELECT Id, TargetObjectId, TargetObject.Name,
ProcessDefinition.Name, Status,
(SELECT Id, ActorId, Actor.Name, StepStatus, CreatedDate
FROM StepsAndWorkitems
WHERE StepStatus = 'Pending' AND ActorId = :UserInfo.getUserId()
ORDER BY CreatedDate ASC)
FROM ProcessInstance
ORDER BY TargetObjectId ASC, CreatedDate ASC
];自分が承認者になっている、承認待ちのレコードだけを取得します。
⚠️ ActorId と OriginalActorId は意味が違います。ActorId は現時点でその作業項目を持っているユーザーです。承認が別のユーザーへ再割り当てされると変わります。OriginalActorId は最初に割り当てられたユーザーのままです。「いま自分が承認すべきもの」を出すなら ActorId で絞り込みます。
Apexで承認・却下する ProcessWorkitemRequest
一覧から選んだ作業項目を承認・却下します。setWorkitemId に渡すのは、ProcessInstanceWorkitem のIdです。
public static void processApprovals(List<Id> workitemIds, String action) { List<Approval.ProcessWorkitemRequest> requests = new List<Approval.ProcessWorkitemRequest>(); for (Id workitemId : workitemIds) { Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest(); req.setWorkitemId(workitemId); req.setAction(action); requests.add(req); } List<Approval.ProcessResult> results = Approval.process(requests); for (Approval.ProcessResult result : results) { System.debug(LoggingLevel.INFO, 'Success: ' + result.isSuccess()); } }
action には Approve か Reject を渡します。
Visualforceで一覧画面を作る
承認待ちの照会と、選んだ項目の承認をまとめた画面です。コントローラは前節までのSOQLとApexをそのまま使います。
ApprovalWorklistController.cls
public with sharing class ApprovalWorklistController { public List<WorkitemRow> rows { get; set; } public ApprovalWorklistController() { rows = new List<WorkitemRow>(); load(); } private void load() { rows.clear(); List<ProcessInstance> instances = [ SELECT Id, TargetObjectId, TargetObject.Name, ProcessDefinition.Name, (SELECT Id, StepStatus, Actor.Name FROM StepsAndWorkitems WHERE StepStatus = 'Pending' AND ActorId = :UserInfo.getUserId() ORDER BY CreatedDate ASC) FROM ProcessInstance ORDER BY TargetObjectId ASC ]; for (ProcessInstance pi : instances) { for (ProcessInstanceHistory item : pi.StepsAndWorkitems) { rows.add(new WorkitemRow(pi, item)); } } } public PageReference approveSelected() { List<Id> ids = new List<Id>(); for (WorkitemRow row : rows) { if (row.selected) { ids.add(row.workitemId); } } if (!ids.isEmpty()) { List<Approval.ProcessWorkitemRequest> requests = new List<Approval.ProcessWorkitemRequest>(); for (Id workitemId : ids) { Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest(); req.setWorkitemId(workitemId); req.setAction('Approve'); requests.add(req); } Approval.process(requests); } load(); return null; } public class WorkitemRow { public Boolean selected { get; set; } public Id workitemId { get; set; } public String processName { get; set; } public String targetName { get; set; } public Id targetId { get; set; } public WorkitemRow(ProcessInstance pi, ProcessInstanceHistory item) { this.selected = false; this.workitemId = item.Id; this.processName = pi.ProcessDefinition.Name; this.targetName = pi.TargetObject.Name; this.targetId = pi.TargetObjectId; } } }
承認待ちを取得し、選択されたものだけ承認処理へ渡します。
ApprovalWorklistPage.page
<apex:page controller="ApprovalWorklistController" title="Approval Worklist" sidebar="false"> <apex:form> <apex:pageBlock title="承認待ち一覧"> <apex:pageBlockButtons> <apex:commandButton value="選択した項目を承認" action="{!approveSelected}" reRender="worklist"/> </apex:pageBlockButtons> <apex:pageBlockTable value="{!rows}" var="row" id="worklist"> <apex:column headerValue="選択"> <apex:inputCheckbox value="{!row.selected}"/> </apex:column> <apex:column headerValue="承認プロセス" value="{!row.processName}"/> <apex:column headerValue="対象レコード"> <apex:outputLink value="/{!row.targetId}">{!row.targetName}</apex:outputLink> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>
一覧をpageBlockTableで表示し、チェックした行だけ承認するボタンを置きます。
動作確認
レコードを作成して申請する
承認対象のレコードを作成し、標準の「承認申請」ボタンを押します。承認プロセスの入力条件に一致していれば、承認待ちの状態になります。
作成したVisualforceページとApexクラスへのアクセス権を承認者へ付与する
プロファイルまたは権限セットで、ページとクラスへのアクセスを許可します。
承認者としてログインし直す
承認者の権限を持つユーザーで、作成したVisualforceページを開きます。
一覧から選んで承認する
対象の行を選択し、「選択した項目を承認」を押します。
結果を確認する
対象レコードの承認ステータスが「承認済み」になっていることを確認します。
ここで間違えやすい
| 間違い | 何が起きるか |
|---|---|
ProcessWorkitemRequest を、承認プロセスに未提出のレコードに使う | 対応する作業項目が無いため処理できません。先に ProcessSubmitRequest で申請します |
ActorId の代わりに OriginalActorId で絞り込む | 他のユーザーへ再割り当て済みの項目まで「自分の承認待ち」に混ざります |
| 承認プロセスをプロセスビルダーと同じものだと思い込む | 別の機能です。承認プロセスは廃止されていません |
| 承認プロセスを有効化せずに申請を試す | 申請できません。詳細画面で「有効化」してから使います |
確認した環境
- 2026年9月 / Salesforce Summer '26(API バージョン 67.0)時点の公式ドキュメントで確認しています
ApprovalTestObject__cなどのAPI参照名はご自身の組織のものに置き換えてください
まとめ
- 承認プロセスはプロセスビルダーとは別の機能で、いまも標準機能として提供されています
- 申請は
Approval.ProcessSubmitRequest、承認・却下はApproval.ProcessWorkitemRequestを使います。どちらもApproval.process()に渡します - 承認待ちの照会は
ProcessInstanceのStepsAndWorkitemsサブクエリで取得します - 「いま自分が承認すべきもの」を絞り込むなら
ActorIdを使います。OriginalActorIdは最初の割り当て先のままです
参考:当時の画面
記事を最初に書いた当時の画面です。いまの手順と違うところは、各画像の説明に書いています。
Salesforceの導入・運用についてご相談ください
導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。