2024年2月16日金曜日

オラクルの公式ブログMulti Level Expense Approval using APEX Workflowのワークフローを理解する

Oracle CorporationでAPEXワークフローを開発しているAnanya Chatterjeeさんが、オラクルの公式ブログに以下の記事を寄稿しています。

Multi Level Expense Approval using APEX Workflow

Ananya ChatterjeeさんはOracle APEXの承認タスクの開発も行なっています。APEXワークフローがリリースされる前のAPEXで、承認タスクによる多段階承認の実装を紹介する記事も書かれています。

Implementing Multi-Approvals in Oracle APEX 22.1
https://blogs.oracle.com/apex/post/implementing-multi-approvals-in-oracle-apex-221

承認タスクを使った多段階認証の実装については、本ブログでも以下の記事で紹介しています。

APEX 22.1の承認コンポーネント(4) - 多段階承認の実装

Oracle APEX 23.2からAPEXワークフローが提供されたため、承認タスクによる多段階承認の記事に以下のコメントが追記されました。
Note: With the availability of Workflow feature in APEX 23.2 release, it is now possible to visualize and design multi-level approvals in a more declarative manner, which you can read about in another blog. This blog is still relevant if you are looking to use using Approval Components, standalone, without Workflow and is also relevant for pre 23.2 versions of APEX.

APEX 23.2以降あれば、多段階承認はAPEXワークフローで実装することを推奨していると言えます。

以下より、ブログ記事「Multi Level Expense Approval using APEX Workflow」で作成しているワークフローで、多段階承認をどう実装しているのか説明しようと思います。ワークフローを組み込んだアプリケーションは、元記事の手順にそって作業を行うことで作成できます。英語ですが、手順が具体的でコードおよびスクリーンショットも揃っていることから、作業はそれほど難しくありません。

本記事では、ワークフローを以下のように若干簡素にしています。電子メールの送信アクティビティを削除し、ワークフロー終了に接続しています。


以下より、多段階承認のワークフローを確認していきます。

最初に経費精算の承認ワークフローを開始します。

ユーザーSTEVEでサインインし、経費申請を行います。以下の画面で重要なパラメータはExpense Amount、つまり費用です。


費用はページ・アイテムP4_EXPENSE_AMOUNTに入力されます。


ボタンSUBMITを押すと、経費精算のワークフロー(定義はExpense Reimbursement Workflow)が開始します。


ワークフロー・パラメータAmountにページ・アイテムP4_EXPENSE_AMOUNTの値を割り当てています。ワークフロー・パラメータはワークフローの開始時に値が設定され、開始後は値を変更することはできません。経費精算の承認処理を行なっている間に、申請した費用が変更されたら困ります。経費申請の申請者や費用といった、ワークフローの処理中に変更できない値をワークフロー・パラメータとして設定します。


ワークフローExpense Reimbursement Workflowを確認します。

ワークフロー・パラメータとしてAmountが設定されています。このパラメータにページ・アイテムP4_EXPENSE_AMOUNTの値が設定されます。ワークフローの中でこのパラメータは静的IDAMOUNTより参照します。

Oracle APEXでは、ページ・アイテムアプリケーション・アイテムの値をバインド変数置換文字列として参照できますが、その際はページ・アイテムやアプリケーション・アイテムの名前を指定します。ワークフローのワークフロー・パラメータおよびワークフロー・バージョン変数は名前の代わりに静的IDを指定して参照します。


ワークフローが開始すると、最初にアクティビティCompute Max Levelが実行されます。このアクティビティでは以下のPL/SQLコードが実行されます。
declare
    level_no number;
begin
    if :AMOUNT < 500 then
        level_no := -1;
    elsif :AMOUNT < 1000 then
        level_no := 1;
    elsif :AMOUNT < 5000 then
        level_no := 2;
    else
        level_no := 3;
    end if;
    :MAX_LEVEL := level_no;
end;
申請した費用が500より少なければMAX_LEVEL-11000より少なければ 15000より少なければ 2、それ以上は 3 を設定しています。

表APPROVAL_LEVELSに、以下のシード・データが挿入されています。
insert into APPROVAL_LEVELS values (10, 'JANE', 'jane@expenseteam.com', 1);
insert into APPROVAL_LEVELS values (20, 'MATT', 'martin@expenseteam.com', 1);
insert into APPROVAL_LEVELS values (30, 'BO', 'bo@expenseteam.com', 2);
insert into APPROVAL_LEVELS values (40, 'CLARA', 'clara@expenseteam.com', 2);
insert into APPROVAL_LEVELS values (50, 'SUSIE', 'susie@expenseteam.com', 3);
このワークフローでは、費用が500より少なければ自動承認、1000より少なければ承認レベル(表APPROVAL_LEVELSの列LEVEL_CODEの値)が1であるJANEかMATTが承認が必要、1000以上5000未満ではさらに承認レベルが2であるBOかCLARAの承認が必要、それ以上はさらに承認レベルが3であるSUSIEの承認が必要、という承認フローを実装しています。


MAX_LEVELワークフロー・バージョン変数として作成されています。


続く切替えApproval Needed?では、ワークフロー・バージョン変数MAX_LEVEL-1であれば自動承認としてワークフローを終了させ、それ以外(1か2か3)であれば、ヒューマン・タスクを生成するアクティビティCreate Approved Requestへ進みます。


アクティビティCreate Approval Requestでは、承認タスクReimbursement Requestを作成します。承認タスクの結果はワークフロー・バージョン変数TASK_OUTCOMEに設定され、後続の切替えApproved?により参照されます。承認タスクの結果はAPPROVEDまたはREJECTEDです。


承認タスクReimbursement RequestのパラメータにLevel Noがあります。Level Noには、ワークフロー・バージョン変数CURRENT_LEVELが割り当てられています。


ワークフロー・バージョン変数CURRENT_LEVELには、タイプ静的値静的値として1が設定されています。ワークフロー・バージョン変数はアクティビティによって変更できるため、この値は初期値またはデフォルト値になります。


承認タスクReimbursement Requestのタスク定義では、潜在的所有者SQL問合せが設定されています。
select mgr_name from approval_levels where level_code = :LEVEL_NO
パラメータLEVEL_NOにはアクティビティCreate Approval Requestが呼び出された時点でのワークフロー・バージョン変数CURRENT_LEVELの値が割り当てられて、承認タスクが作成されます。つまりCreate Approval Requestの初回呼び出し時はCURRENT_LEVELは初期値のなので、LEVEL_NOになります。

結果として費用が500以上の経費申請(自動承認の対象にならない経費申請)は、最初に承認レベルが1のJANEかMATTのどちらかの承認を必要とします。


JANEかMATTが承認タスクを承認すると、切替えApproved?を経由して切替えAll Approvals Completed?へ進みます。

反対に承認タスクを却下すると、切替えRejected At First Level?に進みます。


切替えAll Approvals Completed?では、ワークフロー・バージョン変数CURRENT_LEVELと比較する切替えタイプが設定されています。タイプCheck Workflow Variableでは、実際の条件は切替えから伸びている接続に設定されます。


切替えAll Approvals Completed?とアクティビティIncrement Levelの接続No条件として&MAX_LEVEL.より小さいが設定されています。申請した費用が4000のときはMAX_LEVELが2なのでCURRENT_LEVELより小さいため、こちらの接続が選択されます。

それ以外、つまりMAX_LEVELCURRENT_LEVELが同じ値であれば、経費申請が承認されてワークフローは終了します。


アクティビティIncrement Levelでは以下のPL/SQLコードが実行されます。ワークフロー・バージョン変数CURRENT_LEVELに1が加算されます。
begin
:CURRENT_LEVEL := :CURRENT_LEVEL+1;
end;
その後、アクティビティCreate Approval Requestが呼び出されます。アクティビティCreate Approval Requestにて作成される承認タスクの潜在的所有者はパラメータLEVEL_NO、つまりワークフロー・バージョン変数CURRENT_LEVELで決まります。CURRENT_LEVEL2の場合、承認レベルがのBOかCLARAの承認が必要になります。


JANEかMATTが承認タスクを却下した場合は、切替えRejected at First Level?に進みます。この切替えは条件として、CURRENT_LEVEL1であれば経費申請を却下してワークフローを終了します。

JANEかMATTが経費申請を承認し、次の承認レベルのBOからCLARAにより経費申請が却下されるとCURRENT_LEVELは2になるため、アクティビティReset Levelに進みます。


アクティビティReset Levelでは以下のPL/SQLコードを実行し、CURRENT_LEVELに戻しています。
begin
:CURRENT_LEVEL := 1;
end;
つまり経費申請の承認は、承認レベルが1のJANEとMATTの承認から取り直しになります。


以上が、ブログ記事Multi Level Expense Approval using APEX Workflowで実装しているワークフローの説明になります。

今回の説明に使用したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/expense-reimbursement.zip

ワークスペースへのユーザー作成を避けるため、以下のPL/SQLファンクションによるカスタム認証をカレント・スキームにしています。
function demo_authentication (
    p_username in varchar2,
    p_password in varchar2 )
    return boolean
is
begin
    if upper(p_username) in (
        'STEVE','JANE','BO','SUSIE','CLARA'
    ) then
        return true;
    end if;
    return false;
end;

Oracle APEXのアプリケーション作成の参考になれば幸いです。