PeopleSoft Moodle Interface

I ran across this article recently, and it reminded me that I wanted to mention a project I just completed not too long ago.  I was asked to write an interface from PeopleSoft to Moodle.

At a high level, the interface was pretty simple.  Moodle was configured to allow logon security from LDAP.  Then, we we setup a view that told Moodle what courses to create based on enrollment data in PeopleSoft.  We created a screen to enable and disable a group of courses such as online courses based on term.  Then, we created another screen for an instructor to enable individual courses based on the instructor’s preference.

I heard some talk about implementing this interface at other schools, and I was curious how much interest was out there for this kind of thing.  If you are interested or have some thoughts, please leave me a comment.  Let me know if you are interested in some consulting on this, and I can put you in touch with our sales rep.

New Tables

I found some additional PeopleTools system tables that I am adding to my reference.

The PSPNLCNTRLDATA table stores additional settings for each field on the page.  For example, it holds the new fields PTGRDLAYOUT and GRIDROWS in PeopleTools 8.50 relating to scrollable grids.

The PSPNLFIELDEXT table also stores additional settings for the fields on the page.

The PSPTPNLRTEDITOR is a new table to PeopleTools 8.50 that stores settings related to the new rich-text editor on long character fields.

In the process of researching, I found a huge PeopleTools Tables Reference.

Here is another related tid-bit.  Here is how to decipher the bits in the UseEdit flag (for Oracle):

SELECT FIELDNAME, USEEDIT ,
BITAND(USEEDIT,1) BIT1,
BITAND(USEEDIT,2) BIT2,
BITAND(USEEDIT,4) BIT4,
BITAND(USEEDIT,8) BIT8,
BITAND(USEEDIT,16) BIT16,
BITAND(USEEDIT,32) BIT32,
BITAND(USEEDIT,64) BIT64,
BITAND(USEEDIT,128) BIT128,
BITAND(USEEDIT,256) BIT256,
BITAND(USEEDIT,512) BIT512,
BITAND(USEEDIT,1024) BIT1024,
BITAND(USEEDIT,2048) BIT2048,
BITAND(USEEDIT,4096) BIT4096,
BITAND(USEEDIT,8192) BIT8192,
BITAND(USEEDIT,16384) BIT16384,
BITAND(USEEDIT,32768) BIT32768,
BITAND(USEEDIT,65536) BIT65536,
BITAND(USEEDIT,131072) BIT131072,
BITAND(USEEDIT,262144) BIT262144,
BITAND(USEEDIT,524288) BIT524288,
BITAND(USEEDIT,1048576) BIT1048576,
BITAND(USEEDIT,2097152) BIT2097152,
BITAND(USEEDIT,4194304) BIT4194304,
BITAND(USEEDIT,8388608) BIT8388608,
BITAND(USEEDIT,16777216) BIT16777216,
BITAND(USEEDIT,33554432) BIT33554432,
BITAND(USEEDIT,67108864) BIT67108864,
BITAND(USEEDIT,134217728) BIT134217728,
BITAND(USEEDIT,268435456) BIT268435456
FROM PSRECFIELDALL
WHERE RECNAME = 'MIS_TEST_LONG'
AND FIELDNAME IN ('EMPLID', 'ACTION_TEXT');

For a reference on the UseEdit field, check out this link. I found that the second to last one is the new “Allow Search Events for Prompt Dialogs” option.  To find records that have this option selected, you can use this query:

SELECT * FROM PSRECFIELDALL 
WHERE BITAND(USEEDIT,134217728) <> 0;

Arrays Question

This post is to address a question posed in one of the comments on another post.  The answer is a little too in-depth for a comment reply.  Also, I had been wanting to blog more about arrays anyway.

Here is the question:

Hi i have seen your comment on Arrays.
i need your guidence on creating array and using it in Peoplecode App package.
I have some logic written in SQR. Same thing i want create in App Package which can be used.
Let me brief you my requirement.
i have several parameters to be stored in an array which i will get from different validations and SQL tables for employees.which i will store it in a array. After finishing validations for all the employees i have pass those employee id and details some other system so i want to replicate in App package using Array can you guide me how i can design it in App package.

I also decided to use my step-by-step that I just completed.  So, this answer will build on that post.

Listening to the requirements, I don’t think that we need to extend the array object like the post that this comment was on.  At most, I think we might want to create an employee object that will store all of the fields (or parameters as the requirements call them) needed.

So, I am creating a new Application Package called BLG_BLOGGING.  Then, I am inserting a new Application Class called “EmployeeObject”:

Then, I created three properties in that class to hold three parameters relating to an employee.  I did not specify the “get” or “set” keywords so I don’t have to create getter and setter methods.  This is the easiest way to add properties to a class because you don’t have to write any code for the properties.  Here is the code:

class EmployeeObject
   property string EmployeeID;
   property string FirstName;
   property string LastName;
end-class;

Then, in the Application Engine program, you have to import your new class.  This statement does nothing more than tell the program you are going to use this class later on.

import BLG_BLOGGING:EmployeeObject;

Here are the different variables that we will need.

Local File &log;
Local BLG_BLOGGING:EmployeeObject &emp;
Local array of BLG_BLOGGING:EmployeeObject &ary;
Local number &x;

This code creates an empty array.  We need to pass it a copy of the employee object just so it knows what data type will be stored in the array.  It will not actually store anything in the array at this point.

&emp = create BLG_BLOGGING:EmployeeObject();
&ary = CreateArrayRept(&emp, 0);

Here is where we load the first employee into the array.  We set all of the properties, and then, we use the push() method to insert it into the array.

&emp.EmployeeID = "001";
&emp.FirstName = "Bob";
&emp.LastName = "Tomato";
&ary.Push(&emp);
&log.WriteLine("Added Bob Tomato -- length = " | &ary.Len);

Then, we repeat that with another employee.

&emp = create BLG_BLOGGING:EmployeeObject();
&emp.EmployeeID = "002";
&emp.FirstName = "Larry";
&emp.LastName = "Cucumber";
&ary.Push(&emp);
&log.WriteLine("Added Larry Cucumber -- length = " | &ary.Len);

Finally, we add a third employee just to give us some data.

&emp = create BLG_BLOGGING:EmployeeObject();
&emp.EmployeeID = "003";
&emp.FirstName = "Lunt";
&emp.LastName = "Squash";
&ary.Push(&emp);
&log.WriteLine("Added Lunt Squash -- length = " | &ary.Len);

Then, we need to loop through the array to show what it contains.  The Get() method accesses one of the elements in the array.  It does not remove the element from the array.

&log.WriteLine("");
&log.WriteLine("Employees: ");
For &x = 1 To &ary.Len
     &emp = &ary.Get(&x);
     &log.WriteLine("  " | &emp.EmployeeID | ") " | &emp.LastName | ", " | &emp.FirstName);
End-For;

Final Solution

Here is the Application Package, Employee Object:

class EmployeeObject
   property string EmployeeID;
   property string FirstName;
   property string LastName;
end-class;

Here is the App Engine Program:

import BLG_BLOGGING:EmployeeObject;

Local File &log;
Local BLG_BLOGGING:EmployeeObject &emp;
Local array of BLG_BLOGGING:EmployeeObject &ary;
Local number &x;

&log = GetFile("c:\temp\log.txt", "W", "A", %FilePath_Absolute);

&emp = create BLG_BLOGGING:EmployeeObject();
&ary = CreateArrayRept(&emp, 0);

&emp.EmployeeID = "001";
&emp.FirstName = "Bob";
&emp.LastName = "Tomato";
&ary.Push(&emp);
&log.WriteLine("Added Bob Tomato -- length = " | &ary.Len);

&emp = create BLG_BLOGGING:EmployeeObject();
&emp.EmployeeID = "002";
&emp.FirstName = "Larry";
&emp.LastName = "Cucumber";
&ary.Push(&emp);
&log.WriteLine("Added Larry Cucumber -- length = " | &ary.Len);

&emp = create BLG_BLOGGING:EmployeeObject();
&emp.EmployeeID = "003";
&emp.FirstName = "Lunt";
&emp.LastName = "Squash";
&ary.Push(&emp);
&log.WriteLine("Added Lunt Squash -- length = " | &ary.Len);

&log.WriteLine("");
&log.WriteLine("Employees: ");
For &x = 1 To &ary.Len
     &emp = &ary.Get(&x);
     &log.WriteLine("  " | &emp.EmployeeID | ") " | &emp.LastName | ", " | &emp.FirstName);
End-For;

&log.Close();

Here is the final output:

Added Bob Tomato -- length = 1
Added Larry Cucumber -- length = 2
Added Lunt Squash -- length = 3

Employees:
  001) Tomato, Bob
  002) Cucumber, Larry
  003) Squash, Lunt

Step-by-Step: App Engine for Testing PeopleCode

This is a how-to post that I intend to refer back to from time to time.  The goal is to create a simple Application Engine program into which we can drop some PeopleCode and see how it works.  Assuming we don’t need any of the online pieces, this is much easier than going through all of the steps to create a page and register it so we can see it online.

Step 1: Create a new Application Engine Program

In Application Designer, click Ctrl + N or use the File > New menu option.  This will open the “New” dialog, and you can choose Application Engine program from the list.

You new program should look like this:

Step 2: Disable Restart

This step is very important.  If you don’t disable the restart and your program crashes, you will have to go through a few extra steps before you can rerun it.

First, click on the properties button while your program is in focus (you can also use the File > Definition Properties menu):

This should bring up the Properties dialog.  Then, go to the Advanced tab.  Check the “Disable Restart” option.

Step 3: Add an Action

First, click on the “Step 1” step to select it.  I usually click anywhere in the gray, and this should turn it black.

Next, click on the Add Action button, or you can use the Insert > Action menu.

Finally, change the type from SQL to PeopleCode.

Step 4: Save the program

At this point, you need to save before you can add PeopleCode.  You can use Ctrl + S, click on the Save icon on the toolbar, or you can use the File > Save menu.

Step 5: Enter the PeopleCode

First, open the PeopleCode program by double clicking anywhere on the gray of the PeopleCode action.  Or, you can right click on it and choose the “View PeopleCode” option.

Next, you will probably want to open a file to show output from your PeopleCode testing.  You can use this PeopleCode:

Local File &log;
&log = GetFile("c:\temp\log.txt", "W", "A", %Filepath_Absolute);

Then, you can print to that file with the writeline() method.  For now, we will just print Hello, World.

&log.WriteLine("Hello, World!");

Finally, you will probably want to close your file:

&log.Close();

Here is what it all looks like:

Make sure to save once you make these changes.

Step 6: Run the Program

Again, after you have saved, go back to the main program window where you can see the Main section, Step 1, and your new PeopleCode action.  Then, click the run icon.

In the dialog, Check the Output log to file and uncheck Run Minimized.  The output log to file allows you to see what happened.  Otherwise, the window will close before you see what happened.  The run minimized isn’t a big deal, but if the program doesn’t run minimized you see it pop up and go away better.  When the program goes away, you know it is done running.

Finally, when it is done, check the output.  If you used the paths that I did your output should be in the c:\temp directory.  You should have two files.  The first, is the main output from the program.  Check this to make sure the program ran to success:

The second is the log that your PeopleCode created.  For now, it should just say, “Hello, World”.

Good Looking Messages

I have often wanted to display an informational message at the top of the page.  Rather than just slap a Long Edit Box at the top of the screen, I decided to look for a nice looking way to do it.  One of the great things about PeopleSoft, it always has an example somewhere in the huge product for what you are trying to do.

Here are some of the messages that I found:

Information Message:

Example Page: SSS_STDNTCTR_SR_SP

Here are the different pieces:

  • Stylesheet of the page: SSS_STYLESHEET
  • Group Box:
    • Label Stylesheet: PAGROUPBOXLABELINVISIBLE
    • Body Stylesheet: SSSMSGINFOFRAME
  • Static Image:
    • Image: PS_CS_MESSAGE_INFO_ICN
    • Size: 23×23
  • Static Text:
    • Style: SSSMSGINFOTEXT

Alert Message:

Example Page: SSF_SS_ERRORMSG

Here are the different pieces:

  • Page Stylesheet: SSS_STYLESHEET
  • Group Box
    • Label Stylesheet: PAGROUPBOXLABELINVISIBLE
    • Body Stylesheet: SSSMSGALERTFRAME
  • Push Button (for the image, you could use a static icon instead)
    • Image: PS_CS_MESSAGE_ALERT_ICN
    • Size: Large Icon
  • Long Edit Box (works the same as the static textbox, but lets you change it from code)
    • Stylesheet: SSSMSGALERTTEXT
    • No Label

Great Link: Combined Sections Video

Today, I was doing some research on how Combined Sections work.  I found this video from the University of Southern Mississippi:

PeopleSoft Class Schedule Entry: Combined Section

Watching the video helped me figure out what I needed to do.  The version was a little old, but I found the same page at Curriculum Management > Combined Sections > Identify Combined Sections (in version 9.0).

It looks like there are a lot more videos here that might prove helpful in the future, so I am bookmarking this page!

University of Southern Mississippi: PeopleSoft Class Schedule Entry

UPK Publish Preview Problem

I have been learning the Oracle UPK product recently, and I was having trouble with the publish preview.  I was getting this error message: “preview requires intranet settings to be enabled. These settings are located on the security tab in the Internet Settings of Internet Explorer.”.

I found a post that gave some options for fixing this.  Unfortunately, I did not see the “Automatically detect intranet network” option that they were talking about.  I was running Internet Explorer 7, and I think my problem was that my OS was Windows Server 2003.  I think the Enhanced Internet Explorer Security was enabled, but I looked to try to see if I could uninstall it.  I also tried changing my default browser to Firefox, but it still opens IE to launch the preview.

The solution that ended up working was simply upgrading to Internet Explorer 8.  I am curious if anyone else has had the same problem and how they fixed it.

News: SAP Making Tracks

I ran across these two articles today:

If SAP does buy Sybase that will put them in line with Oracle as far as owning both the database platform and the Application part.  I don’t know that much about SAP, but I was thinking they used Java in their framework.  I am curious about their feeling on Oracle owning Java.