PeopleSoft has moved from the traditional workflow to the Approval
Workflow Engine. Approval Workflow Engine (AWE) also known as Approval Framework is
the framework providing capabilities to create, run and manage the approval
processes within PeopleSoft. When the user submits a transaction, the
application hands the transaction over to Approval Workflow Engine, which will
determine the appropriate approval process definition and then launch the
required routing based on the steps configured.
There are two types of approval process :
- Header Level - Header level approval is the commonly used approval process in AWE where only the top level header record is used and transaction lines are grouped together and processed as one unit.
- Line Level – In line level approval, action can be taken on different line items without waiting for the approval of other line items. In this case, the application can act on the individual lines as they get approved. Each item can be routed to different approvers. For example, if a purchase order contains multiple line items, each line item is treated as a different transaction. So, if you order laptops,printers and desktops, you might obtain approval for laptops only, and not for printers and desktops. The denial of printers and desktops will not have any impact for the approval process of laptops. If treated as a header approval, the entire PO would have been denied. This is the advantage of line level processing.
Business benefits of Line Level Approval:
- In line level approval, multiple approvers can be included for individual steps
- Each item can be routed to different approvers, based on certain criteria.
- Denial /Approval of one line item does not affect the other.
There are many websites for detailed study on Header level approval.
Here, let us have a glance on Line Level Approval with an example.
Line level approval:
Most of the
steps in line level are same as Header level approval. Let us see a sample
workflow process using line level approval.
Sample Test Case:
An employee
tries to submit different items (Laptop, Desktop and Printer) based on the
asset id. Each item is routed to different approvers and the approver can
approve only the specific items routed to him/her.
A component has to be created for the employee
to submit the asset items and for the managers to approve/deny them. Let’s see
the process step by step.
Development Steps:
Step 1: Create a top-level header record
ASSET_ID as key-field. Also, create a line record with ASSET_ID and
KOV_ITEM_NAME as keys. For header level approval, only the header record is
enough.
KOV_TEST_HEADER:
KOV_TEST_LINE-
Step 2: Create a cross reference record
with the key-fields used in header and line record as non-keys here to link the
workflow process to PIA. Include the EOAW_XREF_SBR
delivered sub-record in this record for getting the thread values.
Step 3: Design a standard page with the
header record at level 0 and line record at level 1 as shown below. Include the
delivered sub-page EOAW_MON_SBP to
this page for displaying the Approval
status monitor.
Step 4: Create a new component with the
header record as search record. Place the page in this component and register
the component to a menu.
Step 5: Give the appropriate permission
lists and security access to the component.
Step 6: Coming to the PIA configuration,
navigate to Set Up HRMS -> Common Definitions -> Approvals ->
Transaction Registry. Add a new Process ID and specify the cross reference,
header and line level record names as shown below. Create a new application
package and a class and include it here. The coding for app package is
mentioned later.
Step 7:
Create three generic templates for submission, approval and denial by
navigating to Set Up HRMS -> Common Definitions -> Approvals -> Generic
Templates. The emails triggered to the requester and approver will be in the
format of this template created. Create a SQL to fetch the bind values
mentioned in the template. Like the approval template shown below, similarly
create a template for submission and denial mails. This step is needed only if
business requires notifications to be sent, else creation of generic templates
is optional.
Step 8: Navigate to Set Up HRMS ->
Common Definitions -> Approvals -> Transaction Configuration. Here, add
the following four events:
a)
On Process Launch (Header
level)
b)
On Final Approval (Line Level)
c)
On Final Denial (Line Level)
d)
Route For Approval (Line Level)
If generic templates had been created earlier step , then mention
those names here to each event respectively, but this is not mandatory. For header level approval, all the events
specified, including “On Final Approval” and “On Final Denial” must be given as
Header level only.
Step 9: Navigate to Set Up HRMS ->
Common Definitions -> Approvals -> Approval Process Setup. Add a new
Definition ID for the process id created.
a)
The checkbox “Take Action on
Line Completion” gets automatically checked for line level approval.
b)
Approver Userlist can be
created by mapping it to a specified role or Application Package, SQL or Query.
The approvalof submitted transactions are based on certain criteria.
c) Stage is a collection of paths and can
be at header level or line level. As level here, specify line level is being
used here , create 3 paths.
d)
A path is a collection of steps and since we have 3 items here.Once a
transaction is being submitted,it will route to three different approvers as
shown above.
Printer – Department Head
Laptop - Manager
Desktop – Admin
e)
Click on the Definition
Criteria and Alert Criteria links and give it as always true. In all the three
path level criteria, mention the criteria as “User Entered” and enter the
record field value which must be considered for approving.
Step 10: In the backend, the coding in
work record buttons FieldChange and the Component PostBuild are same as the
Header level coding. There are few changes in SavePostChange coding for passing
the line record which is highlighted below. The coding in Application Package
includes two more events “OnLineApprove” and “OnLineDeny” other than the events
used in Header level approval.
Component
SavePostChange:
/***
* AWE SavePostChange Code
* This Save Post Change Code Will Handled
When Submit, Approve & Deny Action Performed
**/
/** Import Approval
Framework Base Classes */
import
EOAW_CORE:LaunchManager;
import
EOAW_CORE:ApprovalManager;
/** Declare functions*/
Declare Function
createStatusMonitor PeopleCode EOAW_MON_WRK.EOAW_FC_HANDLER FieldFormula;
Component EOAW_CORE:LaunchManager
&c_aweLaunchManager;
Component
EOAW_CORE:ApprovalManager &c_aweApprovalManager;
Component string
&sbmt_action;
Component string
&c_AWEProcessDefnID;
Component Record
&headerRec; /** We have set it Component Level, So Get Acess to Others Component
**/
Component Rowset
&line_rws;
Local Record &line;
Local number &i;
&line_rws = GetLevel0()(1).GetRowset(Scroll.KOV_TEST_LINE);
Local boolean
&IsActionTaken = True;
Local string
&sActionMsgString = "";
Evaluate &sbmt_action
When "S"
/* Call DoSubmit, passing in current
header info. ;*/
/** It is always safe to call this method
(as long as the header record being passed in is valid!), */
&c_aweLaunchManager.DoSubmit();
If (&c_aweLaunchManager.hasAppInst)
Then
/** Initialize Approval Manager if
transaction was submitted */
&c_aweApprovalManager = create
EOAW_CORE:ApprovalManager(&c_aweLaunchManager.txn.awprcs_id,
&headerRec, %OperatorId);
End-If;
Break;
When "A"
/* Call DoApprove, passing in current header
info. */
For &i = 1 To
&line_rws.ActiveRowCount
&line =
&line_rws(&i).GetRecord(Record.KOV_TEST_LINE);
&c_aweApprovalManager.DoApprove(&headerRec);
&c_aweApprovalManager.DoApprove(&line);
End-For;
Break;
When "D"
/* Call DoDeny, passing in current header
info. */
For &i = 1 To
&line_rws.ActiveRowCount
&line =
&line_rws(&i).GetRecord(Record.KOV_TEST_LINE);
&c_aweApprovalManager.DoDeny(&headerRec);
&c_aweApprovalManager.DoDeny(&line);
End-For;
Break;
When-Other
&sActionMsgString = "Error -
Invalid Action.";
&IsActionTaken = False;
End-Evaluate;
/** Show Transaction Status
Monitor & Save & Submit Button **/
If
&c_aweApprovalManager.hasAppInst Then
REM &IsActionTaken =
&c_aweApprovalManager.hasPending;
createStatusMonitor(&c_aweApprovalManager.the_inst, "D",
Null, False);
KOV_TEST_WRK.EOAW_SUBMIT.Visible = False;
KOV_TEST_WRK.EOAW_APPROVE.Visible = False;
KOV_TEST_WRK.EOAW_DENY.Visible = False;
End-If;
/* Reset &Action to
Null */
&sbmt_action = "
";
Application package:
/***
* Approval Event Handler Class
* This Handle All the AWE Events
*Event values include:
*/
import
EOAW_CORE:ApprovalEventHandler;
import
EOAW_CORE:ENGINE:AppInst;
import
EOAW_CORE:ENGINE:UserStepInst;
import
EOAW_CORE:ENGINE:StepInst;
import
EOAW_CORE:ENGINE:Thread;
import EOAW_CORE:*;
class ApprEventHandler
extends EOAW_CORE:ApprovalEventHandler
method ApprEventHandler();
method OnProcessLaunch(&appinst As
EOAW_CORE:ENGINE:AppInst);
method OnLineDeny(&userstep As
EOAW_CORE:ENGINE:UserStepInst);
method OnLineApprove(&appinst As
EOAW_CORE:ENGINE:AppInst, &thread As EOAW_CORE:ENGINE:Thread);
private
instance Record &HeaderRecord; /**
Declare Record Instance **/
end-class;
/** Constructor */
method ApprEventHandler
%Super = create
EOAW_CORE:ApprovalEventHandler();
&HeaderRecord =
CreateRecord(Record.KOV_TEST_HEADER); /** Set the Header Record **/
end-method;
method OnProcessLaunch
/+ &appinst as
EOAW_CORE:ENGINE:AppInst +/
/+ Extends/implements
EOAW_CORE:ApprovalEventHandler.OnProcessLaunch +/; /** Set Approval Prcoess
**/
Local string &item, &asset;
Local Rowset &line_rws;
Local Record &line;
Local number &i;
/** Update the Workflow Status **/
&line_rws =
GetLevel0()(1).GetRowset(Scroll.KOV_TEST_LINE);
For &i = 1 To
&line_rws.ActiveRowCount
&line =
&line_rws(&i).GetRecord(Record.KOV_TEST_LINE);
&asset =
&line.GetField(Field.ASSET_ID).Value;
&item =
&line.GetField(Field.KOV_ITEM_NAME).Value;
End-For;
Local Record &recHdrRecord =
CreateRecord(Record.KOV_TEST_LINE);
&recHdrRecord.GetField(Field.ASSET_ID).Value = &asset;
&recHdrRecord.GetField(Field.KOV_ITEM_NAME).Value = &item;
If &recHdrRecord.SelectByKey() = True
Then
For &i = 1 To
&line_rws.ActiveRowCount
&line =
&line_rws(&i).GetRecord(Record.KOV_TEST_LINE);
&line.GetField(Field.WF_STATUS).Value = "S"; /** Set
InApproval Process **/
&line.Update();
End-For;
GetLevel0().Refresh();
End-If;
end-method;
method OnLineApprove
/+ &appinst as
EOAW_CORE:ENGINE:AppInst, +/
/+ &thread as EOAW_CORE:ENGINE:Thread
+/
/+ Extends/implements
EOAW_CORE:ApprovalEventHandler.OnLineApprove +/
Local string &as, &kov;
Local Record &poRecord;
Local EOAW_CORE:ApprovalManager
&appMgr;
Local number &lineNbr;
/*---Line Approval---*/
&poRecord =
CreateRecord(Record.KOV_TEST_LINE);
&thread.SetAppKeys(&poRecord);
&as = &poRecord.ASSET_ID.Value;
&kov =
&poRecord.KOV_ITEM_NAME.Value;
SQLExec("UPDATE PS_KOV_TEST_LINE SET
WF_STATUS = :1 WHERE ASSET_ID = :2 AND KOV_ITEM_NAME = :3",
"A", &as, &kov);
GetLevel0().Refresh();
end-method;
method OnLineDeny
/+ &userstep as EOAW_CORE:ENGINE:UserStepInst
+/
/+ Extends/implements
EOAW_CORE:ApprovalEventHandler.OnLineDeny +/
Local string &as, &kov;
Local Record &poRecord;
Local EOAW_CORE:ApprovalManager
&appMgr;
Local number &lineNbr;
/*---Line Approval---*/
&poRecord =
CreateRecord(Record.KOV_TEST_LINE);
&userstep.step.path.thread.SetAppKeys(&poRecord);
&as = &poRecord.ASSET_ID.Value;
&kov =
&poRecord.KOV_ITEM_NAME.Value;
SQLExec("UPDATE PS_KOV_TEST_LINE SET
WF_STATUS = :1 WHERE ASSET_ID = :2 AND KOV_ITEM_NAME = :3",
"D", &as, &kov);
GetLevel0().Refresh();
end-method;
|
Step 11: The coding and configuration is
complete.
Now this can be tested by log in to PIA with the requestor’s id and add a new transaction.Below screenshot
shows a submitted transaction for Laptop and Printer and it has
been routed to two different approvers,showing the line level approval.
Step 12: To approve this transaction,
login with one of these approvers‘ id. For example, login with the Department
Head’s ID and approve/deny the transaction. Since the Department Head is mapped
to the asset Printer, once Approve button is clicked, the Printer line alone
gets approved as shown below.
Best Practices
- In line level approval, the line level record must be passed in all events except OnProcessLaunch which is done at header level only.
- The header record is usually given as the search record in the component.
- A line record cannot be used alone in transaction registry and can be used only along with a header record. The cross reference record in this case must have the line record key values.
- An approval process once created and if some transactions have occurred, cannot be modified.The same Process ID has to be cloned with a different effective date in order to modify it. The older ones have to be made INACTIVE.
Author:
Felice Jennifer
Kovaion-Peoplesoft Consulting Practice
Felice Jennifer
Kovaion-Peoplesoft Consulting Practice
Email: felice.jennifer@kovaion.com