Apex

承認プロセスをApexから申請・承認・照会する実装

承認プロセスを作成し、Approval.ProcessSubmitRequestで申請、Approval.ProcessWorkitemRequestで承認する流れをVisualforceの例とともに説明します。

2023.02.14

シナリオ

カスタムオブジェクトに承認プロセスを設定します。レコードの申請と承認は、標準のボタンだけでなくApexからも操作できます。ここでは、承認待ちの一覧を出して選んだものだけ承認する画面を、Apexと承認プロセスの標準APIで作ります。

「承認プロセス」(Approval Process)は、廃止されたプロセスビルダーとは別の機能です。名前が似ていますが、混同しないでください。承認プロセスは現在も標準の機能として提供されています。

カスタムオブジェクトを準備する

承認対象になるカスタムオブジェクトを作成します。

  1. オブジェクトを新規作成する

    オブジェクトマネージャから新規作成します。表示ラベルを「承認テスト対象」、API参照名を ApprovalTestObject__c とします。

  2. レコード名を自動採番にする

    レコード名の項目を、テキストから自動採番へ変更します。表示形式は TAPO-{0000}、開始番号は1にします。

  3. タブを作成する

    作成したオブジェクトのタブを作成し、詳細を入力します。

  4. プロファイルとアプリケーションに追加する

    タブを表示するプロファイルを選び、使用するカスタムアプリケーションへ追加して保存します。

承認プロセスを作成する

  1. 承認プロセスの対象オブジェクトを選ぶ

    設定の「承認プロセス」から、作成したカスタムオブジェクトを選び、「承認プロセスの新規作成」から「標準ウィザードを使用」を選びます。

  2. 承認プロセスの管理対象オブジェクトを選ぶドロップダウン。作成したオブジェクトが選択されている
    承認プロセスを作る前に、管理対象のオブジェクトをここで切り替えます。選び忘れが多い箇所です。
    承認プロセスの新規作成メニューが開き、標準ウィザードを使用が選べる状態
    「承認プロセスの新規作成」を押すと出るメニューです。ここで標準ウィザードを選びます。
  3. 名前と入力条件を設定する

    プロセス名と一意の名前を入力します。承認の対象にするレコードの条件(入力条件)を設定します。

  4. 承認プロセスウィザードのステップ1。プロセス名と一意の名前の入力欄
    ステップ1です。プロセス名と一意の名前を入力します。一意の名前は後から変えにくい項目です。
    ウィザードのステップ2。入力条件の項目・演算子・値を指定する画面
    ステップ2です。どのレコードを承認の対象にするかを、この条件で決めます。
  5. 承認者項目とメールテンプレートを設定する

    承認者が編集できる項目と、通知に使うメールテンプレートを選びます。

  6. ウィザードのステップ3。承認者項目の選択と編集権限のプロパティを設定する画面
    ステップ3です。承認中にレコードを編集できるのが誰かを、下の選択肢で決めます。
    ウィザードのステップ4。承認割り当てメールテンプレートの入力欄
    ステップ4です。承認者への通知に使うメールテンプレートを指定します。
    メールテンプレートの検索画面。標準の通知テンプレートが一覧で並んでいる
    テンプレートは検索画面から選びます。左上のフォルダの切り替えを見落とさないでください。
  7. 承認ページと申請者を設定する

    承認ページレイアウトに表示する項目を選び、申請できるユーザーを指定して保存します。

  8. ウィザードのステップ5。承認ページに表示する項目を左右の箱で選ぶ画面
    ステップ5です。承認者が見る画面に出したい項目を、選択済みの側へ移します。
    ウィザードのステップ6。申請を許可するユーザーを指定する画面
    ステップ6です。申請できる人として所有者を、許可される申請者の側に入れます。
  9. 承認ステップを作成する

    「承認ステップを今すぐ作成します」を選び、ステップの条件と割り当て先(承認者)を設定します。

  10. 承認プロセス作成後の確認画面。承認ステップを今すぐ作成するかを選ぶ
    「はい、承認ステップを今すぐ作成します」を選んで、そのままステップ作成へ進みます。
    新規承認ステップのステップ1。名前と一意の名前、順番の入力欄
    承認ステップの名前と順番を決めます。順番は1から始まり、上から順に評価されます。
    新規承認ステップのステップ2。ステップ条件を指定する画面
    このステップに入るレコードの条件です。既定ではすべてのレコードが入ります。
    新規承認ステップのステップ3。承認者の割り当て方法を選ぶ画面
    割り当て先の決め方です。ここでは自動的に承認者に割り当てるを選んでいます。
    ユーザー検索の別ウィンドウ。最近参照したユーザーの一覧が表示されている
    承認者はユーザー検索の別ウィンドウから選びます。組織名と利用者名は伏せています。
    承認者の欄にユーザーが入った状態のステップ3。複数承認者の扱いも選べる
    承認者が入った状態です。複数指定したときに全員の承認が要るかもここで決めます。
    承認ステップ作成後の確認画面。ワークフローアクションを設定するかを選ぶ
    ここでは「いいえ、後で設定します」を選び、承認プロセスの詳細画面へ戻ります。
  11. 有効化する

    承認プロセスの詳細画面から「有効化」します。

承認プロセスの詳細画面。開始条件、申請時のアクション、承認ステップの一覧が並ぶ
詳細画面です。右上の有効化ボタンと、承認ステップの割り当て先を確認してください。
有効化の確認ダイアログ。有効化後は承認ステップを追加・削除できない旨の警告
有効化すると承認ステップを足したり消したりできなくなります。組織名は伏せています。

⚠️ 有効化するまで、このプロセスは申請に使えません。入力条件・承認者項目・承認ステップの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で表示し、チェックした行だけ承認するボタンを置きます。

動作確認

  1. レコードを作成して申請する

    承認対象のレコードを作成し、標準の「承認申請」ボタンを押します。承認プロセスの入力条件に一致していれば、承認待ちの状態になります。

  2. 作成したVisualforceページとApexクラスへのアクセス権を承認者へ付与する

    プロファイルまたは権限セットで、ページとクラスへのアクセスを許可します。

  3. 承認者としてログインし直す

    承認者の権限を持つユーザーで、作成したVisualforceページを開きます。

  4. 一覧から選んで承認する

    対象の行を選択し、「選択した項目を承認」を押します。

  5. 結果を確認する

    対象レコードの承認ステータスが「承認済み」になっていることを確認します。

ここで間違えやすい

間違い何が起きるか
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 は最初の割り当て先のままです

参考:当時の画面

記事を最初に書いた当時の画面です。いまの手順と違うところは、各画像の説明に書いています。

カスタムオブジェクトの定義の詳細画面。表示ラベルとAPI参照名が並んでいる
作成し終えた直後のオブジェクト定義です。表示ラベルとAPI参照名が対になっているかを見てください。
レコード名の項目編集画面。データ型を自動採番、表示形式をTAPO-0000に設定している
データ型を自動採番へ変えたところです。表示形式と開始番号の欄を確認してください。
新規カスタムタブのステップ1。対象オブジェクトとタブスタイルを選ぶ画面
タブ作成の最初の画面です。どのオブジェクトのタブかと、タブスタイルを選びます。
新規カスタムタブのステップ2。タブを表示するプロファイルを選ぶ画面
どのプロファイルにタブを見せるかを決める画面です。既定で表示かどうかもここで選びます。
新規カスタムタブのステップ3。タブを含めるカスタムアプリケーションの一覧
タブを追加するアプリケーションにチェックが付いているかを確認してから保存します。
作成したレコードの詳細画面。承認履歴に表示するレコードがない状態
申請する前の状態です。承認履歴がまだ空であることを確認してから申請します。
承認申請の確認ダイアログ。申請後は編集や取り消しができなくなる旨の警告
承認申請ボタンを押したときの確認です。設定によっては後から取り消せません。
承認申請後のレコード画面。承認履歴に未承認の行が追加されている
申請した直後です。承認履歴に未承認の行が増えていれば申請できています。
Visualforceページのプロファイルアクセスを有効化する画面
ページを使うプロファイルを、有効にされたプロファイルの側へ移します。
Apexクラスのプロファイルアクセスを有効化する画面
クラス側も同じように許可します。ページだけを許可しても画面は動きません。
承認待ち一覧のVisualforceページ。1件が未選択の状態で表示されている
承認者でページを開いた直後です。承認待ちが1件だけ出ています。
承認待ち一覧でチェックボックスを選択した状態の画面
承認する行にチェックを入れてから、上のボタンを押します。
承認後のレコード画面。承認履歴の状況が承認済みに変わっている
承認履歴の状況が承認済みに変わっていれば成功です。利用者名は伏せています。

Salesforceの導入・運用についてご相談ください

導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。