Thursday, November 21, 2013

Purchase Requisition Approvals in Peoplesoft

I have been getting asked to show how we have designed our Approval process for Requisitions in PeopleSoft Finance.  First of all, I did not design this process.  I was just asked to come in and make it work. 

How we associate the signing authority to the user.  Oddly enough this is done in HR, we have a bolt on page within the JOB_DATA Component where we store Corporate Functions, HR is responsible for maintaining this data, so it makes sense within our organization.

This is our Corporate Functions Grid:

The Level 3-Up to $100,000 dollars is the Signing Authority for this User.  The initial work the consulting company did, failed to get this information into FIN, when we pressed them about it.  The told us that we needed to update in both FIN and HR.  So I used Integration Broker to send this information to FIN.

In Order to maintain the Approval Chain, we populate the PSOPERDEFN's ROLEUSER_SUPR in HR and use Integration Broker to send this to FIN.  We have a process that runs every fifteen minutes looking for changes and it maintains our PeopleSoft User Profiles and updates our Identity Management System, Novel Access Manager.

The on the FIN side, the consulting company built a configuration page to track the signing authority levels:


 They used this information from HR Corporate functions, the User Profile roleuser supervisor to populate a table called ZZ_WF_AUTHORITY.






The View within my Dynamic User List joins the signing Authority Configuration and the table above.:


SELECT A.OPRID
 , A.EMPLID
 , A.DESCR
 , A.EMAILID
 , A.ZZ_SIGN_AUTHORITY
 , A.SUPERVISOR_ID
 , B.MERCHANDISE_AMT
  FROM PS_ZZ_WF_AUTHORITY A
  , PS_ZZ_SIGN_AUTH B
 WHERE A.ZZ_SIGN_AUTHORITY = B.ZZ_SIGN_AUTHORITY



Thursday, November 14, 2013

Mobile Approvals Using Integration Broker and DataPower ESB Part II

Part two of my blog entry on using integration broker(tools 8.51) covers the request handler and the HTML objects used to generate the pages.  If you have not read the first entry I am attempting to build a simple mobile approval application that uses Integration Broker to parse a form submit and then return either a worklist page, transaction page or confirmation page.  Within each of these pages there are hidden inputs that get populated by the handler to control what HTML page the handler will generate.  The hidden inputs are the PSTOKEN, User Action (Approve or Deny), AWE Process ID and all the keys needed to identify the transaction the user is trying to approve.  These are stored in the HTML.ZZ_MYAPPROVAL_WRAPPER:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="application/x-www-form-urlencoded;charset=UTF-8"/>
</head>
<script>
function submitAction(form,  processid, bgn_dt, emplid, empl_rcd, end_dt, pin_take_num, transactionid, transactionnbr, eoawdefn_id, punch_type, zz_job_opening_id, userValue)
{
//alert('starting process');
// set form values


form.processid_e.value = processid;
form.bgn_dt_e.value = bgn_dt;
form.emplid_e.value = emplid;
form.empl_rcd_e.value = empl_rcd;
form.end_dt_e.value = end_dt;
form.pin_take_num_e.value = pin_take_num;
form.transactionid_e.value = transactionid;
form.transaction_nbr_e.value = transactionnbr;
form.eoawdefn_id_e.value = eoawdefn_id;
form.punch_type_e.value = punch_type;
form.zz_job_opening_id_e.value = zz_job_opening_id;
form.useraction_e.value = userValue;
// form.Submit.disabled=true;
form.submit();
}

</script>

<style>  add some css</style>

<body>

<form   action="%BIND(:1)" id="approval" name="approval" method="Post" >
<input type="hidden" name="pstoken_e" value="%BIND(:2)">

<input type="hidden" name="processid_e" value=" ">
<input type="hidden" name="bgn_dt_e" value=" ">
<input type="hidden" name="emplid_e" value=" ">
<input type="hidden" name="empl_rcd_e" value=" ">
<input type="hidden" name="end_dt_e" value=" ">
<input type="hidden" name="pin_take_num_e" value=" ">
<input type="hidden" name="transactionid_e" value=" ">
<input type="hidden" name="transaction_nbr_e" value=" ">
<input type="hidden" name="eoawdefn_id_e" value=" ">
<input type="hidden" name="punch_type_e" value=" ">
<input type="hidden" name="zz_job_opening_id_e" value=" ">
<input type="hidden" name="useraction_e" value="">

%bind(:3)

</form> 

</body>
</html>

This wrapper is used every time the service generates HTML.  And the Bind(:3) is replaced by either the worklist, transaction or confirmation pages. 

The final HTML object is the HTML.ZZ_MYAPPROVAL_XML, that wraps the HTML.ZZ_MYAPPROVALS_WRAPPER and transaction data into a CDATA of an XML document so Integration broker can respond with an XML.  The XSLT to remove this XML wrapper can be found on the part I of this blog.

<?xml version="1.0"?>
<data psnonxml="Yes"><![CDATA[
%BIND(:1)
]]></data>

And finally the entire Handler:

import PS_PT:Integration:IRequestHandler;
import EOAW_CORE:ApprovalManager;
import ZZ_UTILITIES:getUserName;

class RequestHandler implements PS_PT:Integration:IRequestHandler
   method RequestHandler();
   method OnRequest(&_MSG As Message) Returns Message;
   method BuildWorkList() Returns string;
  
   property Rowset rs_TL_APP_RPTD_XRF;
   property Rowset rs_GP_ABSSS_V_XREF_RS;
   property Rowset rs_ZZ_REQ_AWE_XREF;
   property ZZ_UTILITIES:getUserName Util;
   property number TimeSheet_Count;
   property number Absence_Count;
   property number JobReqs_Count;
   property string postURL;
end-class;

/* constructor */
method RequestHandler
   %This.postURL = GetURL(URL.ZZ_MYAPPROVALS);
end-method;

method OnRequest
   /+ &_MSG as Message +/
   /+ Returns Message +/
   /+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
   /* Variable Declaration */
   Local Message &msgData, &msgReply;
   Local Record &recReply, &headerRec;
   Local JavaObject &urldecoder;
   Local XmlDoc &ResponseXML, &XML_MESSAGE;
   Local array of string &formArray, &valArray;
   Local number &X, &c;
   Local Rowset &rs_TL_APP_RPT_LINE;
   Local boolean &lineApproval;
   Local string &Worklist_html, &Worklist_html2, &Worklist_html3;
   Local string &CreateRecName, &RecName, &FormPost, &userId, &userPswd, &pstoken, &processId, &userAction, &bgn_dt, &emplid, &empl_rcd, &end_dt, &pin_take_num, &transaction_id, &transaction_nbr, &eoawdefn_id, &punch_type, &zz_job_opening_id, &reason;
   Local EOAW_CORE:ApprovalManager &apprManager;
  
   %This.Util = create ZZ_UTILITIES:getUserName();
   REM &msgReply = CreateMessage(Operation.ZZ_TEST_SERVICE, %IntBroker_Response);
   &msgReply = CreateMessage(Operation.ZZ_MYAPPROVALS, %IntBroker_Response);
   &lineApproval = False;
   &XML_MESSAGE = &_MSG.GetXmlDoc();
  
   &urldecoder = CreateJavaObject("java.net.URLDecoder");
   &FormPost = &urldecoder.decode(&XML_MESSAGE.DocumentElement.GetCDataValue(), "UTF-8");
   &formArray = Split(&FormPost, "&");
   For &X = 1 To &formArray.Len
      &valArray = Split(&formArray [&X], "_e=");
      If &valArray.Len > 1 Then
         Evaluate &valArray [1]
         When = "username"
            &userId = &valArray [2];
            Break;
         When = "password"
            &userPswd = &valArray [2];
            Break;
         When = "pstoken"
            &pstoken = &valArray [2];
            Break;
         When = "processid"
            &processId = &valArray [2];
            Break;
         When = "useraction"
            &userAction = &valArray [2];
            Break;
         When = "bgn_dt"
            &bgn_dt = &valArray [2];
            Break;
         When = "emplid"
            &emplid = &valArray [2];
            Break;
         When = "empl_rcd"
            &empl_rcd = &valArray [2];
            Break;
         When = "end_dt"
            &end_dt = &valArray [2];
            Break;
         When = "pin_take_num"
            &pin_take_num = &valArray [2];
            Break;
         When = "transactionid"
            &transaction_id = &valArray [2];
            Break;
         When = "transaction_nbr"
            &transaction_nbr = &valArray [2];
            Break;
         When = "eoawdefn_id"
            &eoawdefn_id = &valArray [2];
            Break;
         When = "punch_type"
            &punch_type = &valArray [2];
            Break;
         When = "zz_job_opening_id"
            &zz_job_opening_id = &valArray [2];
            Break;
         When-Other
            Break;
         End-Evaluate;
      End-If;
   End-For;
  
  
   If Not SwitchUser(&userId, &userPswd, &pstoken, "") Then
      /* switch failed, do error processing */
      &ResponseXML = CreateXmlDoc(GetHTMLText(HTML.ZZ_MYAPPROVAL_TIMESHEET));
   Else
      REM  switch user success;
      If %PasswordExpired Then
         /* application specific processing for expired passwords */
         &ResponseXML = CreateXmlDoc(GetHTMLText(HTML.ZZ_MYAPPROVAL_TIMESHEET));
      Else
         /*Switch user Succeded, now do processing*/
         If None(&processId) Then
            rem build worklist;
           
            %This.rs_TL_APP_RPTD_XRF = CreateRowset(Record.TL_APP_RPTD_XRF);
            %This.TimeSheet_Count = %This.rs_TL_APP_RPTD_XRF.Fill("Where FILL.Recname = 'TL_APP_HDR' And FILL.Eoawthread_Status = 'S' AND FILL.EOAWPARENT_THREAD IN (Select L.Eoawparent_Thread From Ps_Hcm_Appr_Stat_V X,Ps_Tl_App_Rptd_Xrf L Where X.Eoawthread_Id = L.Eoawthread_Id  AND X.EOAWPRCS_ID = L.EOAWPRCS_ID AND X.oprid = :1 AND X.EOAWSTEP_STATUS = 'P'  AND X.EOAWPRCS_ID = 'TLReportedTime')", %OperatorId);
            %This.rs_GP_ABSSS_V_XREF_RS = CreateRowset(Record.GP_ABSSS_V_XREF);
            %This.Absence_Count = %This.rs_GP_ABSSS_V_XREF_RS.Fill("WHERE FILL.EOAWTHREAD_ID IN (select EOAWTHREAD_ID from ps_hcm_appr_stat_v X where X.oprid  = :1 And X.EoawSTEP_Status = 'P' AND X.EOAWPRCS_ID = 'Absence_Mgmt_ByPosnSupervisor')", %OperatorId);
            %This.rs_ZZ_REQ_AWE_XREF = CreateRowset(Record.ZZ_REQ_AWE_XREF);
            %This.JobReqs_Count = %This.rs_ZZ_REQ_AWE_XREF.Fill("WHERE FILL.EOAWTHREAD_ID IN (select EOAWTHREAD_ID from ps_hcm_appr_stat_v X where X.oprid  = :1 And X.EoawSTEP_Status = 'P' AND X.EOAWPRCS_ID = 'ZZ_BR_APPROVE_REQ')", %OperatorId);
            &Worklist_html = %This.BuildWorkList();
            &ResponseXML = CreateXmlDoc(GetHTMLText(HTML.ZZ_MYAPPROVAL_XML, GetHTMLText(HTML.ZZ_MYAPPROVAL_WRAPPER, %This.postURL, GenToken(), GetHTMLText(HTML.ZZ_MYAPPROVAL_WL, &Worklist_html))));
           
         Else
            rem we have a process id do we have an action to approve or deny?;
            If Substring(&userAction, 1, 1) = "A" Or
                  Substring(&userAction, 1, 1) = "D" Then
               rem we have an action and a processid we have an approval;
               SQLExec("SELECT RECNAME FROM PS_EOAW_TXN_LVL WHERE EOAWPRCS_ID = :1 and EOAWLEVEL = 0", &processId, &RecName);
               &CreateRecName = "Record." | &RecName;
               &headerRec = CreateRecord(@&CreateRecName);
               Evaluate &RecName
               When = "TL_APP_HDR"
                  &headerRec.EMPLID.Value = &emplid;
                  &headerRec.EMPL_RCD.Value = &empl_rcd;
                  &headerRec.EOAWDEFN_ID.Value = &eoawdefn_id;
                  &headerRec.PUNCH_TYPE.Value = &punch_type;
                  &headerRec.TRANSACTIONID.Value = &transaction_id;
                  &lineApproval = True;
                  Break;
               When = "GP_ABS_SS_DAT"
                  &headerRec.EMPLID.Value = &emplid;
                  &headerRec.EMPL_RCD.Value = &empl_rcd;
                  &headerRec.BGN_DT.Value = &bgn_dt;
                  &headerRec.END_DT.Value = &end_dt;
                  &headerRec.PIN_TAKE_NUM.Value = &pin_take_num;
                  &headerRec.TRANSACTION_NBR.Value = &transaction_nbr;
                  Break;
               When = "ZZ_REQUISITIONS"
                  &headerRec.ZZ_JOB_OPENING_ID.Value = &zz_job_opening_id;
                  Break;
               When-Other;
                  Break;
               End-Evaluate;
               &headerRec.SelectByKey();
               &apprManager = create EOAW_CORE:ApprovalManager(&processId, &headerRec, %OperatorId);
               If (&apprManager.hasAppInst) Then
                  Evaluate Substring(&userAction, 1, 1)
                  When = "A"
                     If &lineApproval Then
                        &rs_TL_APP_RPT_LINE = CreateRowset(Record.TL_APP_RPT_LINE);
                        &rs_TL_APP_RPT_LINE.Fill("Where fill.TRANSACTIONID = :1 AND FILL.EMPLID = :2 AND FILL.EMPL_RCD = :3 AND FILL.EOAWDEFN_ID = :4 AND FILL.PUNCH_TYPE = :5", &headerRec.TRANSACTIONID.Value, &headerRec.EMPLID.Value, &headerRec.EMPL_RCD.Value, &headerRec.EOAWDEFN_ID.Value, &headerRec.PUNCH_TYPE.Value);
                        &apprManager.DoApproveRowSet(&rs_TL_APP_RPT_LINE);
                     Else
                        &apprManager.DoApprove(&headerRec);
                     End-If;
                     Break;
                  When = "D"
                     &apprManager.DoDeny(&headerRec);
                     Break;
                  End-Evaluate;
               Else
                  REM NOTHING TO APPROVE;
                 
                 
               End-If;
               &ResponseXML = CreateXmlDoc(GetHTMLText(HTML.ZZ_MYAPPROVAL_XML, GetHTMLText(HTML.ZZ_MYAPPROVAL_WRAPPER, %This.postURL, GenToken(), GetHTMLText(HTML.ZZ_MYAPPROVAL_CONFIRM, "", "", "", "", "", "", "", "", "", "", ""))));
              
            Else
               rem build transaction html;
               Evaluate &processId
               When = "Absence_Mgmt_ByPosnSupervisor"
                  Local Record &gp_pin = CreateRecord(Record.GP_PIN);
                  &gp_pin.PIN_NUM.Value = &pin_take_num;
                  &gp_pin.SelectByKey();
                  Local Record &GP_ABS_EVENT = CreateRecord(Record.GP_ABS_EVENT);
                  &GP_ABS_EVENT.EMPLID.Value = &emplid;
                  &GP_ABS_EVENT.EMPL_RCD.Value = &empl_rcd;
                  &GP_ABS_EVENT.BGN_DT.Value = &bgn_dt;
                  &GP_ABS_EVENT.PIN_TAKE_NUM.Value = &pin_take_num;
                  &GP_ABS_EVENT.END_DT.Value = &end_dt;
                  &GP_ABS_EVENT.SelectByKey();
                  If All(&GP_ABS_EVENT.ABSENCE_REASON.Value) Then
                     Local Record &GP_ABS_TAKE = CreateRecord(Record.GP_ABS_TAKE);
                     &GP_ABS_TAKE.PIN_NUM.Value = &pin_take_num;
                     &GP_ABS_TAKE.SelectByKeyEffDt(%Date);
                     Local Record &GP_ABS_REASON = CreateRecord(Record.GP_ABS_REASON);
                     &GP_ABS_REASON.USED_BY.Value = "C";
                     &GP_ABS_REASON.COUNTRY.Value = "USA";
                     &GP_ABS_REASON.ABS_TYPE_OPTN.Value = &GP_ABS_TAKE.ABS_TYPE_OPTN.Value;
                     &GP_ABS_REASON.ABSENCE_REASON.Value = &GP_ABS_EVENT.ABSENCE_REASON.Value;
                     &GP_ABS_REASON.SelectByKeyEffDt(%Date);
                     &reason = &GP_ABS_REASON.DESCR.Value
                  Else
                     &reason = "None";
                  End-If;
                 
                  &ResponseXML = CreateXmlDoc(GetHTMLText(HTML.ZZ_MYAPPROVAL_XML, GetHTMLText(HTML.ZZ_MYAPPROVAL_WRAPPER, %This.postURL, GenToken(), GetHTMLText(HTML.ZZ_MYAPPROVAL_ABS, &processId, &bgn_dt, &emplid, &empl_rcd, &end_dt, &pin_take_num, &transaction_id, &transaction_nbr, &eoawdefn_id, &punch_type, &zz_job_opening_id, &bgn_dt, &end_dt, &gp_pin.DESCR.Value, &reason, &GP_ABS_EVENT.DURATION_ABS.Value, "8", &Util.getUserNamebyEmplid(&emplid)))));
                  Break;
               When = "TLReportedTime"
                  rem build the time and labor html;
                  Break;
               When = "ZZ_BR_APPROVE_REQ"

                  rem build the absence request;
                  Local Record &Job_Opening = CreateRecord(Record.ZZ_REQUISITIONS);
                  &Job_Opening.ZZ_JOB_OPENING_ID.Value = &zz_job_opening_id;
                  &Job_Opening.SelectByKey();
                  Local Record &DEPT_TBL = CreateRecord(Record.DEPT_TBL);
                  &DEPT_TBL.SETID.Value = "SHARE";
                  &DEPT_TBL.DEPTID.Value = &Job_Opening.DEPTID.Value;
                  &DEPT_TBL.SelectByKeyEffDt(%Date);
                  Local Record &COMPANY_TBL = CreateRecord(Record.COMPANY_TBL);
                  &COMPANY_TBL.COMPANY.Value = &DEPT_TBL.COMPANY.Value;
                  &COMPANY_TBL.SelectByKeyEffDt(%Date);
                  Local Record &ZZ_FLATTREE_ORG = CreateRecord(Record.ZZ_FLATTREE_ORG);
                  SQLExec("select * from %TABLE(:1) WHERE DEPTID = :2", &ZZ_FLATTREE_ORG, &Job_Opening.DEPTID.Value, &ZZ_FLATTREE_ORG);
                  Local Record &JOBCODE_TBL = CreateRecord(Record.JOBCODE_TBL);
                  &JOBCODE_TBL.SETID.Value = "SHARE";
                  &JOBCODE_TBL.JOBCODE.Value = &Job_Opening.JOBCODE.Value;
                  &JOBCODE_TBL.SelectByKeyEffDt(%Date);
                  Local Record &LOCATION_TBL = CreateRecord(Record.LOCATION_TBL);
                  &LOCATION_TBL.SETID.Value = "SHARE";
                  &LOCATION_TBL.LOCATION.Value = &Job_Opening.LOCATION.Value;
                  &LOCATION_TBL.SelectByKeyEffDt(%Date);
                  &ResponseXML = CreateXmlDoc(GetHTMLText(HTML.ZZ_MYAPPROVAL_XML, GetHTMLText(HTML.ZZ_MYAPPROVAL_WRAPPER, %This.postURL, GenToken(), GetHTMLText(HTML.ZZ_MYAPPROVAL_REQ, &processId, &bgn_dt, &emplid, &empl_rcd, &end_dt, &pin_take_num, &transaction_id, &transaction_nbr, &eoawdefn_id, &punch_type, &zz_job_opening_id, &Job_Opening.ZZ_JOB_OPENING_ID.Value, &Job_Opening.ZZ_STATUS.LongTranslateValue, &Job_Opening.POSN_DESCR.Value, &Job_Opening.DESCR.Value, &Job_Opening.POSITION_NBR.Value, &DEPT_TBL.COMPANY.Value, &COMPANY_TBL.DESCR.Value, &ZZ_FLATTREE_ORG.ZZ_DIVISION.Value, &ZZ_FLATTREE_ORG.ZZ_DIVISION_DESCR.Value, &Job_Opening.REPORTS_TO.Value, "LOOKUP MANAGER", &Job_Opening.MANAGER_ID.Value, "LOOK UP MANAGER", &Job_Opening.JOBCODE.Value, &JOBCODE_TBL.DESCR.Value, &Job_Opening.DEPTID.Value, &DEPT_TBL.DESCR.Value, &Job_Opening.LOCATION.Value, &LOCATION_TBL.DESCR.Value, &Job_Opening.ZZ_WORK_SCHED_TEXT.Value, &Job_Opening.ZZ_FULL_PART_TIME.LongTranslateValue, &Job_Opening.SHIFT.LongTranslateValue, &Job_Opening.ZZ_JOB_OPN_REASON.LongTranslateValue))));
                  Break;
               End-Evaluate;
             
            End-If;
         End-If;
      End-If;
   End-If;
  
  
  
  
   &msgReply.SetXmlDoc(&ResponseXML);
  
  
   Return &msgReply;
  
end-method;

method BuildWorkList
   /+ Returns String +/
   Local string &html;
   Local string &empl_name;
   Local Record &Requistion;
   Local number &z;
  
   Local string &dur;
   &Requistion = CreateRecord(Record.ZZ_REQUISITIONS);
  
  
   If %This.TimeSheet_Count + %This.Absence_Count + %This.JobReqs_Count = 0 Then
      &html = "<tr><td>No Pending Transactions</td></tr>"
   Else
      For &z = 1 To %This.TimeSheet_Count
         &empl_name = %This.Util.getUserNamebyEmplid(%This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).EMPLID.Value);
         SQLExec("select Min(dur) from ps_tl_app_rptd_xrf where eoawparent_thread = :1", %This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).EOAWTHREAD_ID.Value, &dur);
         &html = &html | "<tr><td>Timesheet</td>" | "<td>" | &empl_name | " Period starting " | &dur | "</td><td>" | GetHTMLText(HTML.ZZ_MYAPPROVAL_WL_SUBMIT, %This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).EOAWPRCS_ID.Value, "", %This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).EMPLID.Value, %This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).EMPL_RCD.Value, "", "", %This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).TRANSACTIONID.Value, "", %This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).EOAWDEFN_ID.Value, %This.rs_TL_APP_RPTD_XRF.GetRow(&z).GetRecord(1).PUNCH_TYPE.Value, "", "TimeSheet") | "</td></tr>";
      End-For;
      For &z = 1 To %This.Absence_Count
         &empl_name = %This.Util.getUserNamebyEmplid(%This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).EMPLID.Value);
         &html = &html | "<tr><td>Absence Request</td>" | "<td>" | &empl_name | " from " | %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).BGN_DT.Value | " Through " | %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).BGN_DT.Value | "</td><td>" | GetHTMLText(HTML.ZZ_MYAPPROVAL_WL_SUBMIT, %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).EOAWPRCS_ID.Value, %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).BGN_DT.Value, %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).EMPLID.Value, %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).EMPL_RCD.Value, %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).END_DT.Value, %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).PIN_TAKE_NUM.Value, "", %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).TRANSACTION_NBR.Value, %This.rs_GP_ABSSS_V_XREF_RS.GetRow(&z).GetRecord(1).EOAWDEFN_ID.Value, "", "", "Absence Request") | "</td></tr>";
      End-For;
      For &z = 1 To %This.JobReqs_Count
         &Requistion.ZZ_JOB_OPENING_ID.Value = %This.rs_ZZ_REQ_AWE_XREF.GetRow(&z).GetRecord(1).ZZ_JOB_OPENING_ID.Value;
         &Requistion.SelectByKey();
        
         &html = &html | "<tr><td>Job Opening</td>" | "<td>" | %This.rs_ZZ_REQ_AWE_XREF.GetRow(&z).GetRecord(1).ZZ_JOB_OPENING_ID.Value | "-" | &Requistion.DESCR.Value | "</td><td>" | GetHTMLText(HTML.ZZ_MYAPPROVAL_WL_SUBMIT, %This.rs_ZZ_REQ_AWE_XREF.GetRow(&z).GetRecord(1).EOAWPRCS_ID.Value, "", "", "", "", "", "", "", %This.rs_ZZ_REQ_AWE_XREF.GetRow(&z).GetRecord(1).EOAWDEFN_ID.Value, "", %This.rs_ZZ_REQ_AWE_XREF.GetRow(&z).GetRecord(1).ZZ_JOB_OPENING_ID.Value, "Job Opening") | "</td></tr>";
      End-For;
   End-If;
  
  
  
   Return &html
end-method;

The Handler uses either the PSTOKEN or the USERID/PASSWORD to authenticate the request. Then it evaluates if there is a PROCESS_ID, if there is a process id and a user Action then it attempts to Approve or Deny the transaction and then present the confirmation page.  If there is a Process ID and no Action, then it creates the Transaction page for the user to Approve or Deny.  If there is no Process Id, then the Handler returns the Worklist page of pending transactions.  In my example I have only accounted for Three HCM transactions.  One being a custom bolt-on that we built to approve Job Requisitions and two delivered, Time and Labor and Absence Requests.


Saturday, November 2, 2013

AutoSave ePerformance Part II

In September I posted a link to some auto Save JavaScript for ePerformance.  This worked, but it prevented the page from timing out and it would also save while I would be typing on the document and then all of a sudden I would be at the top of the document.  This was quite annoying.  At the same time I was working on warning the user about leaving the page via the back button, I had asked Jim Marion a couple questions and he recommended I monkey patch the timeout function to auto save the document. So below is my JavaScript that monkey patches the displayTimeoutMsg function and warns the user if they navigate away from the page with the back button.


<input type="hidden" name="AUTOSAVE" value=""/>
<script type="text/javascript">

threadLock = false;

function user_function()
{
//alert('starting process');

var changes = checkFormChanged(document.%formname);
if (changes && !threadLock)
{
threadLock = true;
if ("%page" == "EP_APPR_MAIN1" || "%page" == "EP_APPR_BASE1")
{
//submitAction_%Formname(document.%Formname,"EP_BTN_LINK_WRK_EP_STORE_PB");
hAction_%Formname(document.%Formname,'EP_BTN_LINK_WRK_EP_STORE_PB', 0, 0, 'Save', false, true);
}
}
}

</script>
<script type="text/javascript" language="javascript">
(function() {
  var originalendModalCntrl = ptCommonObj.endModalCntrl;
  ptCommonObj.endModalCntrl = function() {
    window.onbeforeunload = function(){};
    return new originalendModalCntrl();
  }
})();

window.onbeforeunload = function(e) {
           var changes = checkFormChanged(document.%formname);
if (changes && !threadLock)
{
threadLock = true;
if ("%page" == "EP_APPR_MAIN1" || "%page" == "EP_APPR_BASE1")
{
            return "You have unsaved changes, please save them."
        };
}
}
</script>

<script type="text/javascript">
function adaptLinks() {
    var links = document.getElementsByTagName('a');
    for (i = 0; i != links.length; i++) {
        links[i].onclick = (function () {
            var origOnClick = links[i].onclick;
            return function (e) {
                 window.onbeforeunload = function(){};
                if (origOnClick != null && !origOnClick()) {
                    return false;
                }               
            }
        })();
    }
}
(function() {
  var originaldisplayTimeoutMsg = displayTimeoutMsg;
  displayTimeoutMsg = function() {
    window.onbeforeunload = function(){};
   
    user_function();

    return new  originaldisplayTimeoutMsg();
  }
})();

adaptLinks();
</script>