Wednesday, November 13, 2013

PeopleSoft: Default log-in page in local language, and localized numeric system


We've a client in Germany. So, when the users  there click on the hyperlink to open the PeopleSoft application the default log-in language for the application is German.

But one fine day, after upgrading the Internet Explorer, all the users were seeing the default log-in language as English; Although the language for the browser was German.
On the top of it, the system was not taking the comma as decimal separator but a dot.
That is when user was entering the amount 52,23 in the numeric field and tab out, it was being formatted to 5223.00 !

But after giving it a closer look, found that default language selected in the browser setting was 

Whereas it should be 
 
Because as per the PeopleBooks: 
  • Web browsers enable users to specify a list of preferred languages for web content. PeopleTools uses the first language listed in the browser's preferred language list to determine the default language of the PeopleSoft signon page. If the user’s preferred language is not available, the default sign-in screen is displayed in U.S. English (en-US).
  • For PeopleTools to display the sign-in page in the user’s preferred language as determined from browser settings, the language codes used by the browser are mapped to PeopleSoft three-letter language codes. The PeopleSoft system reads the PSLANGUAGES table to perform this mapping. 


 

PeopleCode to generate sequence number


Sometimes it's required to automatically increment the value of a sequence field when user adds a row and decrement it when a user deletes a row, through PeopleCode.

The following code is one of the solutions to this problem. It ensures that the sequence number always increments by one, and adjusts the sequence numbers accordingly if a user deletes a row, even if the row deleted is out of order.

The code goes in two events of the record field.

/*--- RowInsert ---*/
Local Rowset &Rowset;
&Rowset = GetRowset();

NS_TEST.SEQ_NUM = &Rowset.ActiveRowCount;
&Rowset.Sort(NS_TEST.SEQ_NUM, "A");


/*-- RowDelete --*/
Local Rowset &Rowset;
Local Row &Row;

&Rowset = GetRowset();
For &i = 1 To &Rowset.ActiveRowCount;
   &Row = &Rowset(&i);
   If &Row.NS_TEST.SEQ_NUM.Value > NS_TEST.SEQ_NUM.Value Then
      &Row.NS_TEST.SEQ_NUM.Value = &Row.NS_TEST.SEQ_NUM.Value - 1;
   End-If;
  
End-For;
&Rowset.Sort(NS_TEST.SEQ_NUM, "A");

Tuesday, November 12, 2013

PeopleSoft: Why SQL & Call Section are mutually exclusive Actions in AppEngine

        

Both SQL and 'Call Section' are mutually exclusive Actions. This is basically to avoid Lock. 

Say for example:
We execute some DML transaction on Table T1 in SQL action (This is the first Action in a Step of Application Engine Section).
If we are trying to do some DML transaction again on Table T1 using Call Section action, this will create a Lock on table T1.


Main Program
SQL - Update T1, set salary = salary * 2.
Call Section - Calc


       Section Calc
       SQL Update T1, set salary = salary *3
       end-section
       (default commit)


Main Program
end-section
(default commit)

 
Since PS is creating a separate Database Session for these Actions, it is difficult to maintain COMMIT / ROLLBACK transaction controls.

PeopleSoft: Reboot only the Pub/Sub services on the application server

  
  1. Open up psadmin.
  2. Navigate to your domain.
  3. Choose option 5 to bring up the <tmadmin> command line.
  4. Type     shutdown - g PUBSUB (this should bring down the services).
  5. Type     boot -g PUBSUB  (which should bring them back up).

Monday, November 11, 2013

PeopleSoft: PL/SQL to fetch the details of the objects included in an AppDesigner project


Select projectname, DECODE(OBJECTTYPE,
'0','Record',
'1','Index',
'2','Field',
'3','Field Formats',
'4','Translate',
'5','Page',
'6','Menus',
'7','Component',
'8','RecordPC',
'9','Menu People Code',
'10','Query',
'11','Tree Structures',
'12','Trees',
'13','Access Groups',
'14','Colors',
'15','Styles',
'16','Business Process Map',
'17','Business Process',
'18','Activities',
'19','Role',
'20','Process Definition',
'21', 'Server Definition',
'22' , 'Process Type Definition',
'23','Job Defination',
'24','Recurrence Definition',
'25','Message Catalog',
'26','Dimensions',
'27','Cube Definitions',
'28','Cube Instance Definitions',
'29','Business Interlinks',
'30','SQL',
'31','File Layout',
'32','Component Interface',
'33','AE Program',
'34','AE Sections',
'35','Message Nodes',
'36','Message Channel',
'37','Message',
'38','Approval Rule Set',
'39','Message Peoplecode',
'40','Subscription PeopleCode',
'41','Channel PeopleCode',
'42','Comp Interface People Code',
'43', 'AE Peoplecode',
'44','Page PC',
'45','Page Field PeopleCode',
'46','Component Peoplecode',
'47','Component Record PeopleCode',
'48','Component Record PC',
'49','Image',
'50','Style Sheets',
'51','HTML',
'52','File Reference',
'53','Permission List',
'54','Portal Registry Definition',
'55','Portal Registry',
'56','URL',
'57','Application Packages',
'58','Application Package PC',
'59','Portal Registry User homepage',
'60','Problem type definition',
'61','Archieve templates',
'62','XSLT','63','Portal Registry User Favorite',
'64','MobilePages',
'65','Relationships',
'66','Component Interface Property PeopleCode',
'67','Optimization Models',
'68','File Reference',
'69','File Reference Type Codes',
'70','Archive Object Definition',
'71','Archive Template',
'72','Diagnostic Plug-In',
'73','Analytic Models',
'79','Services',
'80','Service Operations',
'81','Service Operation Handlers',
'82','Service Operation Versions',
'83','Service Operation Routings',
'84','IB Queues',
'85','XMLP Template Definition',
'86','XMLP Report Definition',
'87','XMLP File Definition',
'88','XMLP Data Source Definition',objecttype) OBJECT
, OBJECTVALUE1||'-->'||OBJECTVALUE2||'-->'||OBJECTVALUE3||'-->'||OBJECTVALUE4 KEY
, DECODE(SOURCESTATUS,'0','Unknown','1','Absent','2','Changed','3','Unchanged','4','*Changed','6','Same', SOURCESTATUS) SOURCE
, DECODE(TARGETSTATUS,'0','Unknown','1','Absent','2','Changed','3','Unchanged', '4','*Changed','6','Same',targetstatus) TARGET
, DECODE(UPGRADEACTION,'0','Copy','1','1','2','None','3','CopyProp',UPGRADEACTION) ACTION
, DECODE(TAKEACTION,'0','No','1','Yes', takeaction)UPGRADE
, DECODE(COPYDONE,'0','No','1','Yes', COPYDONE) COPY
From psprojectitem
Where projectname like 'PROJECT_NAME%';
 

PeopleSoft: SQL to know the Users, who can access the Page




SELECT DISTINCT B.MENUNAME, B.BARNAME, B.BARITEMNAME, D.PNLNAME, C.PAGEACCESSDESCR, B.DISPLAYONLY, F.ROLEUSER
FROM PSROLECLASS A, PSAUTHITEM B, PSPGEACCESSDESC C, PSPNLGROUP D, PSMENUITEM E, PSROLEUSER F
WHERE  B.MENUNAME  =  E.MENUNAME
     AND B.BARNAME =  E.BARNAME
     AND B.BARITEMNAME =  E.ITEMNAME
     AND D.PNLGRPNAME = E.PNLGRPNAME
     AND A.CLASSID =  B.CLASSID
     AND B.MENUNAME NOT IN ('APPLICATION_DESIGNER','OBJECT_SECURITY','QUERY','PERFMONPPMI','IMPORT_MANAGER','CLIENTPROCESS','DATA_MOVER')
     AND B.MENUNAME NOT LIKE 'WEBLIB%'
     AND B.AUTHORIZEDACTIONS = C.AUTHORIZEDACTIONS
     AND A.ROLENAME = F.ROLENAME
     AND D.PNLNAME = 'PAGE_NAME'
  ORDER BY 2

PeopleSoft: Get the names of Properties in a CI


The following piece of code would fetch the name of the Properties, of a Component Interface,  upto level 2.

   &MYSESSION = %Session;
   &CI = &MYSESSION.GetCompIntfc(CompIntfc.NS_CI);


   &PROPINFO_0 = &CI.PropertyInfoCollection;
       /*Level0 Properties*/   For &I = 1 To &PROPINFO_0.Count;
      &PROPITEM_0 = &PROPINFO_0.Item(&I);
      Warning (&PROPITEM_0.Name);


      If (&PROPITEM_0.IsCollection) Then
         &PROPINFO_1 = &PROPITEM_0.PropertyInfoCollection;


         /*Level1 Properties*/
         For &J = 1 To &PROPINFO_1.Count;
            &PROPITEM_1 = &PROPINFO_1.Item(&J);
            &S1 = &PROPITEM_0.Name | "." | &PROPITEM_1.Name;
            Warning (&S1);


            If (&PROPITEM_1.IsCollection) Then
               &PROPINFO_2 = &PROPITEM_1.PropertyInfoCollection;


           /*Level2 Properties*/               For &K = 1 To &PROPINFO_2.Count;
                  &PROPITEM_2 = &PROPINFO_2.Item(&K);
                  &S1 = &PROPITEM_0.Name | "." | &PROPITEM_1.Name | "." | &PROPITEM_2.Name;
                  Warning (&S1);


               End-For;
            End-If

         End-For;
      End-If;
   End-For;

Thursday, November 7, 2013

PeopleSoft: Using multi-dimensional array


This post is to explain the usage of multi-dimensional array in PeopleSoft.
To explain it, I’m taking an example to display the field label text for all the dropdown fields on a page.

Create a SQL object NS_DROPDOWN_FLD_LBL , with the following SQL statement:
Select FieldType, FieldName, LblText
From PSPNLFIELD
Where PNLNAME=:1 And RECNAME =:2 And LABEL_ID<>' '


Now write this PeopleCode at appropriate place:

Local number &n_FldType, &n_element;
Local string  &s_FieldName, &s_FldLabel, &b_state;

/*Declare & initiate array*/
Local array of array of string &a_FieldList;


/*Array with 3 elements*/
&a_FieldList = CreateArrayRept(CreateArrayRept(" ", 0), 3);


/*Fetch fields for record JOB on JOB_DATA1 page*/
&sql = GetSQL(SQL.NS_DROPDOWN_FLD_LBL, “JOB_DATA1”, “JOB” ); 
&a_FieldList.Len = 0;
&n_element=1;

   While &sql.Fetch(&n_FldType, &s_FieldName, &s_FldLabel)
     
      If &n_FldType = 5 Then
         &b_state = "Y";
      Else
         &b_state = "N";
      End-If;
     
      &a_FieldList.Push(&s_FieldName);
      &a_FieldList [&n_element, 2] = &b_state;
      &a_FieldList [&n_element, 3] = &s_FldLabel;
      &n_element = &n_element + 1;
   End-While;
  
   /* Getting values out of the array */
   /* This would display messagebox for all the fields which are dropdown. */
   For &i = 1 To &a_FieldList.Len
      If &a_FieldList [&i][2] = "Y" Then
         MessageBox(0, "", 0, 0, " FieldName:- " | String(&a_FieldList [&i][1]) | " FieldLabel:- " | String(&a_FieldList [&i][3]));
      End-If;
   End-For;



PeopleSoft: Creating XML Publisher report with PS Query



STEP I: - Create a PS Query, to fetch the required data. E.g, I created a PS Query with the name NS_HRS_OFFER_DS

STEP II: - Create the Data Source for the XML Publisher, by following the below listed steps.

1.      Navigate to Main Menu > Reporting Tools > XML Publisher > Data Source




Select ‘Add a New Value’, and in ‘Data Source ID‘enter the name of the PS Query created in STEP I.
Then click ADD button.


Click the ‘Generate‘ hyperlink to create the XML file, for the Data Source.
This would generate the sample data file, similarly generate schema file for the data source.




Below is the sample data file generated by the above step.


Below is the schema data file generated by the above step.



STEP III: - Create a RTF template, using MSWord.
Load the sample XML Data

Select the XML file generated in STEP II.


To insert the field values in template, do the following steps.


Insert the desired fields at appropriate place, in the template.

Below is the template, after all the required fields are inserted into the template.


There are number of things that you can do with the XML publisher, for example if you want to create a table for the compensation, you can do it by following steps.



Drag the node to ‘template‘ area, like I did for the ‘Row‘ node in this example.
And remove all the fields from the node which are not required in the template.
After setting the properties for the table & fields, select OK to insert the table into the template.




So below is the template, which we get after going through above steps.


STEP IV: - Create the Report Definition in PIA.





Select the ‘Report Category ID‘, to give the access of the report.
The Report Category is defined at {Main Menu -> Reporting Tools -> XML Publisher  -> Setup  -> Report Category }


Upload the template for the report.


After the template is uploaded, then mark the status ‘Active’.


Also mark the status of the report to ‘Active’, and save it.


STEP V: - Run the report.

Enter the report name, and template ID to be used for the report.
Then click ‘Update Parameters’ to give the values to the bind variables of the PS Query.


Click ‘OK‘ button.


Click ‘Run‘ button.

After the process PSXPQRYRPT is run to success, then view the generated report in ‘Report Manager’ component.



Below is the generated report.



PeopleSoft: Sending email Code

Creating a Text Email

The following code example creates and sends a very simple email, then tests the results.
import PT_MCF_MAIL:*;

/*-- Create an outbound email object --*/  
Local PT_MCF_MAIL:MCFOutboundEmail &eMail =
create PT_MCF_MAIL:MCFOutboundEmail();  

/*-- Initialize the usual fields of an email --*/  
&eMail.From = &FromAddress;
&eMail.Recipients = &ToList;
&eMail.Subject = &Subject;
&eMail.Text = &MailBody;
  
/*-- The send method uses the default SMTP parameters as set in the app server configuration file.
This send method makes a connection to the SMTP server, sends the mail and then disconnects.
The result are returned as a number corresponding to the possible values.
The list of ValidSent, InvalidSent and Invalid addresses are returned in the email object itself
----*/
  
Local integer &resp = &eMail.Send();
Local boolean &done;
  
Evaluate &resp
   When %ObEmail_Delivered
      /* every thing ok */
      &done = True;
      Break;
     
   When %ObEmail_NotDelivered
/*-- Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses */
      &done = False;
      Break;
     
   When %ObEmail_PartiallyDelivered
/* Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses; */
      &done = True;
      Break;
     
   When %ObEmail_FailedBeforeSending
/* Get the Message Set Number, message number;
Or just get the formatted messages from &email.ErrorDescription,
&email.ErrorDetails;*/
     
      &done = False;
      Break;
   End-Evaluate;

 

 

Creating Email and Overriding SMTP Settings

The following code example creates a text email and overrides the SMTP settings as found in the application server configuration file.
import PT_MCF_MAIL:*;

/*-- Create an email object by setting individual parameters ---*/

Local PT_MCF_MAIL:MCFOutboundEmail &eMail =
create PT_MCF_MAIL:MCFOutboundEmail();

&eMail.Recipients = &ToList; /* comma separated list of email addresses */
&eMail.CC = &CCList; /* comma separated list of email addresses */
&eMail.BCC = &BCCList; /* comma separated list of email addresses */
&eMail.From = &FromAddress; /* from email address */
&eMail.ReplyTo = &ReplyToAddress; /* in case the reply is to be sent to a
 different email address */
&eMail.Sender = &SenderAddress; /* If different from the "from" address */  
&eMail.Subject = &Subject; /* email subject line */
&eMail.Text = &MailBody; /* email body text */
  
  
/*-- Override the default SMTP parameters specified in app server configuration file ----*/
  
&eMail.SMTPServer = "psp-smtpg-01";
&eMail.SMTPPort = 10266; /*-- Usually this is 25 by default */
  
Local integer &resp = &eMail.Send();
 
/* Now check the &resp for the result */

Local boolean &done;
  
Evaluate &resp
   When %ObEmail_Delivered
      /* every thing ok */
      &done = True;
      Break;
     
   When %ObEmail_NotDelivered
/*-- Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses */
      &done = False;
      Break;
     
   When %ObEmail_PartiallyDelivered
/* Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses; */
      &done = True;
      Break;
     
   When %ObEmail_FailedBeforeSending
/* Get the Message Set Number, message number;
Or just get the formatted messages from &email.ErrorDescription,
&email.ErrorDetails;*/
     
      &done = False;
      Break;
   End-Evaluate;

Creating a Multipart Email with Text and HTML Parts

The following code example creates an email with both HTML and text sections.
The email client on the target host must be able to detect the HTML and text parts in the email and display the part that the client is configured to display.

import PT_MCF_MAIL:*;
 
Local PT_MCF_MAIL:MCFOutboundEmail &email = 
create PT_MCF_MAIL:MCFOutboundEmail();
Local string &TestName = "Text and its alternate html body";
   
&email.From = &FromAddress;
&email.Recipients = &ToList;
&email.Subject = &Subject;
   
Local PT_MCF_MAIL:MCFBodyPart &text = create PT_MCF_MAIL:MCFBodyPart();
&text.Text = "Hi There";
   
Local PT_MCF_MAIL:MCFBodyPart &html = create PT_MCF_MAIL:MCFBodyPart();
&html.Text = 
"<html><BODY><H1>EMail test with HTML content</H1><b>Hi There</b>" | 
"<A href='http://www.peoplesoft.com'>Check this out!</A>" |
"<P></BODY></html>";
&html.ContentType = "text/html";
   
Local PT_MCF_MAIL:MCFMultipart &mp = create PT_MCF_MAIL:MCFMultipart();
&mp.SubType = "alternative; differences=Content-type";
   
&mp.AddBodyPart(&text);
&mp.AddBodyPart(&html);
   
&email.MultiPart = &mp;
   
Local integer &res = &email.Send();
 
Local boolean &done;
   
Evaluate &resp
   When %ObEmail_Delivered
      /* every thing ok */
      &done = True;
      Break;
      
   When %ObEmail_NotDelivered
/*-- Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses */
      &done = False;
      Break;
      
   When %ObEmail_PartiallyDelivered
/* Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses; */
      &done = True;
      Break;
      
   When %ObEmail_FailedBeforeSending
/* Get the Message Set Number, message number;
Or just get the formatted messages from &email.ErrorDescription,
&email.ErrorDetails;*/
      
      &done = False;
      Break;
   End-Evaluate;


Sending PDF as attachment in EMail


import PT_MCF_MAIL:*;
import PT_MCF_MAIL:MCFOutboundEmail;
import PT_MCF_MAIL:MCFEmail;

Local PT_MCF_MAIL:MCFOutboundEmail &email = create PT_MCF_MAIL:MCFOutboundEmail();
Local PT_MCF_MAIL:MCFBodyPart &text = create PT_MCF_MAIL:MCFBodyPart();

&email.Recipients = "HCMGENUser5@ap6023fems.us.oracle.com";
&email.From = "SMTPUser@oracle.com";
&email.BCC = "";
&email.Subject = "MCF Outbound Email of PDF test";
&email.ReplyTo = "";
&text.Text = "Email Body - This is a Test of the MCF Outbound Email, attaching pdf file";
/*** Add Attachment - Start ***/

Local PT_MCF_MAIL:MCFMultipart &mp = create PT_MCF_MAIL:MCFMultipart();
Local PT_MCF_MAIL:MCFBodyPart &attach = create PT_MCF_MAIL:MCFBodyPart();
&attach.SetAttachmentContent("/home/psadm2/ps/pt/8.50/appserv/prcs/PRCSDOM/MCF-Email-Pcode.pdf", %FilePath_Absolute, "Test.pdf", "Test.pdf", "", "");

&attach.Disposition = "attachment";
&mp.AddBodyPart(&text);
&mp.AddBodyPart(&attach);
&email.MultiPart = &mp;
/*** Add Attachment - End ***/

/*** Send the Email ***/
&res = &email.Send();

/*** Check the Email made the trip ***/
Local boolean &done;

Evaluate &res
When %ObEmail_Delivered
/* every thing ok */
&done = True;
Exit 0;

When %ObEmail_NotDelivered
/*-- Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses */
&done = False;
Exit 1;

When %ObEmail_PartiallyDelivered
/* Check &email.InvalidAddresses, &email.ValidSentAddresses
and &email.ValidUnsentAddresses; */
&done = True;
Exit 1;


When %ObEmail_FailedBeforeSending
/* Get the Message Set Number, message number;
Or just get the formatted messages from &email.ErrorDescription,
&email.ErrorDetails;*/

&done = False;
Exit 1;
End-Evaluate;