Run Control in App Engine


The Default State Record must be built as an SQL Table. This is not documented (I think).

You can then use the Run Control by binding as in the following example. If it is a Derived Work table, not an SQL Table, the %Bind value will be Null.
    

Style Sheet Gotchas

So, you've created your own style sheet class to change the border colour of a Frame or Group Box to red. But, when you view the page rather than a red border you get no border. What is going wrong?
If you look at the HTML source you'll see your frame, which is actually a HTML Table, written there with your new class. Something like:

[table class="REDBORDER" style="border:none"]

Why is it hiding your borders?
Look above and you'll see another table:

[table class="REDBORDERWBO"...

What is this?

On the page definition in Application Designer you can turn a Frame's border on/off. It is in the properties for each Frame object. PeopleSoft adds another Table around your Frame's Table that is used to handle the on/off (hidden) state of the border. If the Frame border is on you'll see the wrapper table with class xxxWBO (with border) and if off you'll see the wraper table with class xxxNBO (no border).
Your custom class definition, in this example, also needs the classes REDBORDERWBO and REDBORDERNBO to handle the on/off state of the Frame border. Same goes for Group Boxes.

Who is SamDestroy?

To get around the SamDestroy error when comparing projects from file go to Config Manager, Remote Call/AE Tab, and check the Shared Flags "Disable DB Stats" checkbox and you should be fine.

This seems to only be an issue for DB2.

James Court Medina Apartments, Canberra

As an I.T. contractor I am required to work in different cities, sometimes 3 different contracts/year and 3 different cities.

I am writing a short review of James Court Medina apartments in Canberra to partially vent my frustration, and I know Google will probably pick up this post : )

I did some thinking last night, all the places I had ever lived in, including my first slum/sharehouse as a teenager. James Court Medina is actually the worst apartment I have ever lived in, ever. Including addresses in Russia. DO NOT LIVE HERE. At least my slums had one or two appealing factors, like the beach being across the road or price. They all had a working shower.

1. Location. You will not sleep. Take a look at the location on a map. That is the intersection of two major roads. The car noise is actually fine, it is the trucks that will rob you of any sleep. They compression brake in to those traffic lights all morning, starting at about 4am. BRRRRRRR-rrrrrr-RRRRRR-SQUEEEEEEEEK. You will jump awake the first few times. It's best to go to bed around 8pm in anticipation of being woken very early.

2. Heating. I arrived here in Spring and even then the heater in the living room, a split system from the late 80's, was insufficient to heat the room. I spent weeks watching television in thermals and a beanie. I'd hate to see what it's like in winter. You could turn the fridge off I'm sure.

3. Condition. Nothing has been updated since it was built in the late 80's early 90's. I opened my windows one afternoon and now two weeks later they are still stuck open. I'm still waiting for them to be fixed. This is just lovely at night when a 6 degree wind blows through, My lounge room is now like a fridge. Also, as I mentioned, NO maintenance has been done since the aprtments were built. I had to decalcify the shower heads myself.

4. Price. Seriously WTF? Look elsewhere. I know for a fact that for an extra $50/week you can have lake views and a marble kitchen. The only reason I moved in here was because I was extremely unlucky with my timing, and there was nothing else available. I regret my decision.

To Summarise: LOOK ELSEWHERE. DO NOT LIVE AT James Court Medina, Canberra.

P.S. The fire alarm went off yesterday afternoon. I could hear it from the lounge room but I could not hear it from the bedroom, even though I knew it was ringing. Dodgy.

Inserting Random Test Data

INSERT INTO PS_SOME_TEST_TBL
SELECT EMPLID, 'Test ID' 
FROM
    (SELECT EMPLID FROM PS_JOB
    ORDER BY DBMS_RANDOM.VALUE)
WHERE ROWNUM < 101;

Component Arrays - Caching

One Application Engine performance tip I found was to place the results of commonly used queries into Component level arrays that could be searched through on the Application Server instead of making a call to the database. Some code was triggered that many times the DB calls numberd in millions and all the round-trips were expensive.

The following creates component arrays that store the results for a common query, in this case PIN_NUM and PIN_NM from the GP_PIN table.

/* Create a set of global look-up arrays. 
   This will remove the need to call the db many, many times. 

  See CC_FUNCLIB_UOA.LOOKUP.FieldFormula for how to call/use. */

Component array of string &arrPinNumIndex;
Component array of number &arrPinNumVal;

Component array of number &arrPinNmIndex;
Component array of string &arrPinNmVal;

Local SQL &sql;
Local string &pinNm;
Local integer &pinNum, &i;

/* PIN_NUM Lookup: */
&arrPinNumIndex = CreateArrayRept("", 0);
&arrPinNumVal = CreateArrayRept(0, 0);

&sql = CreateSQL("SELECT PIN_NM, PIN_NUM FROM %Table(GP_PIN) ORDER BY 1");
&i = 1;
While &sql.Fetch(&pinNm, &pinNum)
   &arrPinNumIndex [&i] = &pinNm;
   &arrPinNumVal [&i] = &pinNum;
   &i = &i + 1;
End-While;


/* PIN_NM Lookup: */
&arrPinNmIndex = CreateArrayRept(0, 0);
&arrPinNmVal = CreateArrayRept("", 0);

&sql = CreateSQL("SELECT PIN_NUM, PIN_NM FROM %Table(GP_PIN) ORDER BY 1");
&i = 1;
While &sql.Fetch(&pinNum, &pinNm)
   &arrPinNmIndex [&i] = &pinNum;
   &arrPinNmVal [&i] = &pinNm;
   &i = &i + 1;
End-While;

There is a Function that can be called to interrogate the arrays for the value you are searching for:

<* Search the global array that stores cached lookup values from database.
   This removes (a lot of) roundtrips between app server and db server. 

   Example of use:

     /* previously populated arrays - index and value. */
     Component array of string &arrPinNumIndex;
     Component array of number &arrPinNumVal;

     Declare Function GetCached PeopleCode CC_FUNCLIB_UOA.LOOKUP FieldFormula;
     &x = GetCached("ZACC ALA", &arrPinNumIndex, &arrPinNumVal);

   i.e. Pass it a pin name and two, synchronised arrays.
   The first array contains the index, the second contains values that are returned.
   Obviously only works on "2 dimensional arrays"

*>



Function BinarySearch(&arr, &srchVal, &low As integer, &high As integer) Returns integer
   
   If (&high < &low) Then
      Return - 1; /* not found */
   End-If;
   
   &mid = &low + ((&high - &low) / 2);
   If &arr [&mid] > &srchVal Then
      Return BinarySearch(&arr, &srchVal, &low, &mid - 1);
   Else
      If &arr [&mid] < &srchVal Then
         Return BinarySearch(&arr, &srchVal, &mid + 1, &high);
      Else
         Return &mid; /* found */
      End-If;
   End-If;
   
End-Function;

Function GetCached(&srch, &arrIndex, &arrVal) Returns any
   
   &i = BinarySearch(&arrIndex, &srch, 1, &arrIndex.len);
   If &i = - 1 Then
      Return 0; /* not found */
   Else
      Return &arrVal [&i];
   End-If;
   
End-Function;



To use them try the following code:

/* Lookup array arrays: */
Component array of string &arrPinNumIndex;
Component array of number &arrPinNumVal;

&x = GetCached("BASE PAY", &arrPinNumIndex, &arrPinNumVal);

Commitments / Encumbrances

After building this twice now, both while specs were being written (sigh) I suggest the following approach.

Multiple App Engines.

Main: Contains main outer loop(s)
Grouping Code: Contains calls to Element AEs
Element: Contains Section for each Element calculation.
Functions: Sections for populating component arrays and the like
Population: AE that deals only with splitting, account code mapping and population of temp tables.

... something lik ethat. Would make things more legible, pluggable.

The need for an environment that has accurate pay run data to compare against cannot be stressed enough, preferably dev. The lag between code changes and migrations and runs in downstream envs that have comparable data can be days, very slow and confusing.