Monday 5 October 2015

PeopleSoft Approval Framework-Line Level Approval

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 :
  1.  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.
  2.   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.




 In the above screenshot, the value is entered as “L” which stands for Laptop. So, the Userlist mapped to this value can approve only Laptop transactions. Similarly, for Desktop and Printer, criteria is added and values are given as “D” and “P” respectively.

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
        Email: felice.jennifer@kovaion.com

Tuesday 12 May 2015

Peoplesoft - Drill Down PS Query

1. Introduction

How often  users run queries and write  down values returned to navigate to the appropriate page and view the underlying details of those vouchers, journals, vendors, etc?Wouldn't it be nice if  just on a click of  a hyperlink embedded within the query results ,have a page pop up in a separate browser window instead. As a solution to this,Drill down PS query can be used .

Drill down PS Query is a type of expression which returns the respective URL for the column along with the PS Query Search Results.By clicking the URL or Mapped Fields users are redirected to the respective peoplesoft page.

2. Business Benefits

Eliminates the need of noting down the value and navigating to the component manually to enter the data and open up the page for editing, resulting in a time saver

3. Types of  Drill down PS Query

  • Query URL 
  • Component URL
  • External URL     
  • Attachment URL 
  • Free Form URL

           4. Development of a  Drill Down PS Query

        A Drill Down PS Query can be developed in few simple steps:
       Step1Once the query is created, Click Expression -> Add Expression Button.


         Step2: Select the expression type as Drilling URL.


       Step3: Once Drilling URL is selected as the Expression type, types will be      highlighted.Choose anyone URL type based on the requirement.



         Step4: After all the fields were entered, click the search keys button to populate all the search keys which is in record.



       Step5: After search keys are populated, provide the respective key value. The Selection flag for the particular field name should be selected to fill their key value.These values will be used to By-pass the search key values while the component is redirected.
       


      Step6: Click the Map column button to populate all the fields from the query record.
      Select the field that needs to be mapped. While the query is executed, on clicking a mapped field the component will be redirected in a separate tab .


       
     Step7 (optional):“Use as field” hyperlink will be used to make the drilling URL expression as a new field .

<     


      Step8: Click the mapped fields or drilling URL hyperlink to redirecting the respective component in a new tab in our browser. 

<



    Author,
   Chandru Asokan
   Kovaion-Peoplesoft Consulting Practice
   Email:chandru.asokan@kovaion.com