Pages

Thursday, July 3, 2008

Classic PC: Installing Zool (Gremlin) Into DOS Box

This is a fairly quick and easy guide for running classic PC games, games intended to be run under DOS, under later versions of windows.

As an example I'll be taking the game "Zool" (from Gremlin Interactive, released in 1996) and using the original PC CD-ROM and a piece of software called DOSBox get this game running under Windows XP Home.

DOSBox is an Software Emulator that allows you to play old games on a modern system (such as Windows XP or even Windows Vista) or even play them on an alternate system such as under Ubuntu (or any other flavour of Linux).

The steps to follow are;

1. Download & Install DOSBox
Visit http://www.dosbox.com/download.php?main=1 and download the Windows installer (the top link under "DOSBox"). The download link on this page takes you to a different website (SourceForge.Net) which hosts the pre-built installation files.

The size is approximately 1.2MB (should take about 10 seconds, maybe a minute if you're on dial up).

Install the software by double-clicking the DOSBox0.72-win32-installer.exe file (the "0.72" part of the filename will change depending on whatever the current version is).

2. Configure DOXBox
Find the DOSBox-X.XX group;

Figure 1: DOSBOX-0.72 Program Icons

Start the DOSBox application by clicking on it. Two new windows will appear, one called "DOSBox Status Window" and the other beginning "DOSBox 0.72".

Using Windows Explorer (or My Computer) go to your C:\ or D:\ drives and create a directory called "DOSGAMES". On my system I'm going to create and use a directory called "C:\DOSGAMES".

Next create a file in the new directory called TEST.TXT.

Now in the window titled "DOSBox 0.72" type the following lines;

MOUNT C C:\DOSGAMES
C:

DIR


In your window you should now have something looking like this;

Figure 2: Configuring DOSBox

You can see in the Figure above that TEST.TXT file you created earlier. Now you can delete that file.

Next you need to mount your CD ROM drive (so you can install the game). You need to find the letter associated with your CD ROM, on my system this is "F". After you've got the letter you need to enter the following lines (also in the window titled "DOSBox 0.72");

MOUNT D F:\ -t cdrom
D:

DIR


You should now see a listing for the CD in the DOSBox window.

Clearly you're not going to want to do this every single time you want to play a game so under the DOSBox program group is an icon called "DOSBox.conf", run this and a file will open in Notepad. Scroll down to the bottom and add the two mount lines in the section titled "[autoexec]" (as shown below):

[autoexec]
# Lines in this section will be run at startup.

mount c c:\dosgames

mount D F:\ -t cdrom


Close down DOSBox (click on the "X" at the top right of the window) and re-start it. You should see that the two MOUNT commands are automatically executed when you start the application.

3. Installing Zool
Switch to your CD ROM drive (in DOSBox) by typing;

D: DIR

There INSTALL.EXE file will install the application so type;

INSTALL.EXE
1 (for English)
1 (install the game)
C (the drive to install to)
Y (yes, you did mean C)
Y (yes, "C:\ZOOL" is the directory you want it to use)
(ANY KEY) (it's a classic game, let's re-live that classic joke too ... ;-)
ESC (exit)

Now the game is installed.

4. Running Zool!
Let's be honest, this is the important bit. Type the following;

C:
CD C:\ZOOL
GO

Now you should see something like;

Figure 3: Zool!

Hope this has been useful for you, any questions leave a comment and I'll help where I can.

Wednesday, May 14, 2008

Oracle EBS: Automating Changes of Username

As as typically the case within any organisation that has been around for a while the rules behind generating a user name will change. In our case the change was from initials (ARP01 - Andy Pellew) to a sort of initial/surname combination (APE06 - yes, one day I'll get together with apes 1-5 and we'll take over the world).

Oracle will allow you to update a single users user name as everything is stored against the USER_ID (from the FND_USER table under APPLSYS) in the database.

The package below (XXXX_APPUSERMANAGER) allows you to specify an old user name and a new user name and does the switch for you (after validating that it should let you). The source code for the package is below;

create or replace package XXXX_APPUSERMANAGER is

  procedure RenameUsers(p_ReturnMessage OUT VARCHAR2,
                        p_ReturnCode    OUT NUMBER,
                        p_OldUserName   IN VARCHAR2 default '',
                        p_NewUserName   IN VARCHAR2 default '');

end XXXX_APPUSERMANAGER;

And here is the required code for the package body;

create or replace package body XXXX_APPUSERMANAGER is

  c_NOTFOUND constant number := -998;
  c_BLANK    constant number := -999;

  /* ********** ********** ********** ********** ********** --
  -- PRIVATE Routines (available only to this package)      --
  -- ********** ********** ********** ********** ********** */
  function private_GetUser(p_Username in varchar2) return number as
    cursor c_GetUser is
      select u.user_id
        from applsys.fnd_user u
       where upper(u.user_name) = upper(p_UserName);
    v_UserId applsys.fnd_user.user_id%type;
  begin
    open c_GetUser;
    fetch c_GetUser
      into v_UserId;
    close c_GetUser;
 
    if v_UserId is null then
      if length(p_UserName) = 0 then
        v_UserId := c_BLANK;
      else
        v_UserId := c_NOTFOUND;
      end if;
    end if;
    return v_UserId;
  end private_GetUser;

  function private_emailSubjectTag return varchar2 as
    v_Database v$database.name%TYPE;
  begin
    select distinct name into v_Database from v$database;
    return '[User Admin - ' || nvl(v_Database, 'Null') || ']';
  end private_emailSubjectTag;

  function private_passwordGenerator return varchar2 as
    -- This is not massively secure, but it's secure enough (providing you don't have external users!)
    c_ALPHA constant varchar2(255) := '1DFC84XSW3ERTGBZA52KI9JM6LOPYH70N';
    v_Position number := mod(to_number(to_char(sysdate, 'SSSSS')),
                             length(c_ALPHA));
    v_Length   number := mod(to_number(to_char(sysdate, 'SSSSS')), 4) + 6;
  begin
    return substr(c_ALPHA || c_ALPHA, v_Position, v_Length);
  end;

  /* ********** ********** ********** ********** ********** --
  -- PUBLIC Routines (available globally)                   --
  -- ********** ********** ********** ********** ********** */
  procedure RenameUsers(p_ReturnMessage OUT VARCHAR2,
                        p_ReturnCode    OUT NUMBER,
                        p_OldUserName   IN VARCHAR2 default '',
                        p_NewUserName   IN VARCHAR2 default '') as
    pragma autonomous_transaction;
 
    v_OldUserId    number;
    v_NewUserId    number;
    v_RowCount     number;
    v_Password     varchar2(255);
    v_EmailAddress applsys.fnd_user.email_address%TYPE;
    v_URL          varchar2(255) := 'http://%HOST%:8000/OA_HTML/AppsLocalLogin.jsp?cancelUrl=/OA_HTML/AppsLocalLogin.jsp&langCode=US&username=' ||
                                    upper(p_NewUserName);
    v_Host         v$instance.HOST_NAME%TYPE;
 
    procedure LogMessage(p_Text in varchar2) as
    begin
      apps.fnd_file.put_line(apps.fnd_file.log, p_Text);
    end;
  begin
    LogMessage('START');
    v_OldUserId := private_GetUser(p_OldUserName);
    v_NewUserId := private_GetUser(p_NewUserName);
    LogMessage('Renaming ' || p_OldUserName || '(' || to_char(v_OldUserId) ||
               ') to ' || p_NewUserName || '(' || to_char(v_NewUserId) || ')');
 
    -- If the user details are blank raise an error
    if (v_OldUserId = c_BLANK) or (Length(trim(p_NewUserName)) = 0) then
      raise_application_error(-20005,
                              'ERROR: You cannot rename from/to a blank username!');
    end if;
 
    -- If the old user is not found then raise an error
    if v_OldUserId = c_NOTFOUND then
      raise_application_error(-20005,
                              'ERROR: The user "' || p_OldUsername ||
                              '" does not exist');
    end if;
 
    -- If the old user is not found then raise an error
    if upper(p_OldUserName) = upper(p_NewUserName) then
      raise_application_error(-20005,
                              'ERROR: Old and new usernames are the same!');
    end if;
 
    -- Get the email address, if there is no email address raise an error
    select email_address
      into v_EmailAddress
      from applsys.fnd_user u
     where u.user_id = v_OldUserId;
    if v_EmailAddress is null then
      raise_application_error(-20005,
                              'ERROR: Unable to update user "' ||
                              upper(p_OldUserName) ||
                              '" because they do not have a valid email address');
    end if;
 
    -- If the old user *is* found then raise an error
    if v_NewUserId <> c_NOTFOUND then
      raise_application_error(-20005,
                              'ERROR: The user "' || p_NewUserName ||
                              '" already exists');
    end if;
 
    -- Perform the rename
    LogMessage('Updating user record (ID=' || to_char(v_OldUserId) || ')');
    update applsys.fnd_user u
       set u.user_name = upper(p_NewUserName)
     where u.user_id = v_OldUserId;
    v_RowCount := SQL%ROWCOUNT;
    -- If anything other than a single record has been updated raise an error
    if v_RowCount <> 1 then
      raise_application_error(-20005,
                              'ERROR: Updating the user record has failed (' ||
                              to_char(v_RowCount) || ')');
    end if;
 
    -- Reset the users password. This is necessary because the encryption on the account includes
    -- the Username in the key (so when we change the username we make it impossible for the user
    -- to login - hence the resetting of the users password to a known value).
    LogMessage('Initialising Oracle Application Suite (required for Password Change)');
    execute immediate 'alter session set NLS_LANGUAGE = AMERICAN'; -- oddly we need these lines
    execute immediate 'alter session set NLS_TERRITORY = AMERICA';
    apps.fnd_global.apps_initialize(0, 20420, 1); -- switch to SYSADMIN under apps.
    v_Password := private_passwordGenerator; -- this is a pretty poor generator, but is almost certainly secure enough for us.
 
    -- Get the hostname (necessary to customise the URLs).
    select lower(host_name) into v_Host from v$instance where rownum = 1;
 
    LogMessage('Changing the users password');
    fnd_user_pkg.UpdateUser(x_user_name                  => upper(p_NewUserName),
                            x_owner                      => 'SEED',
                            x_unencrypted_password       => v_Password,
                            x_password_lifespan_days     => '',
                            x_password_lifespan_accesses => '',
                            x_password_accesses_left     => '');
    -- Notify the user their account name and password have changed
    XXXX_emailmanager.addEmail(p_From    => v_EmailAddress,
                               p_To      => v_EmailAddress,
                               p_Subject => private_emailSubjectTag ||
                                            ' User/Password Change Notification',
                               p_Body    => '

Your username (which was "' ||
                                            upper(p_OldUserName) ||
                                            '") has been changed to "' ||
                                            upper(p_NewUserName) ||
                                            '
". Your password has also been reset to "' ||
                                            v_Password ||
                                            '" (without the quotes).

Please click the Oracle link below to logon and change your password:
' ||
                                            Replace(v_URL, '%HOST%', v_Host) ||
                                            '

If you have any problems accessing the system please contact the IT Helpdesk.
');
    XXXX_emailmanager.processMails;
    commit;
    p_ReturnMessage := 'OK';
    p_ReturnCode    := 0;
    LogMessage('END');
  exception
    when others then
      begin
        p_ReturnMessage := '(' || TO_CHAR(SQLCODE) || ') ' || SQLERRM;
        p_ReturnCode    := 1;
        logMessage('999 ERROR: (' || TO_CHAR(SQLCODE) || '): ' || SQLERRM);
        XXXX_emailmanager.addEmail(p_From    => 'errors@company.com',
                                   p_To      => 'errors@company.com',
                                   p_Subject => private_emailSubjectTag ||
                                                ' Error',
                                   p_Body    => '999 ERROR: (' ||
                                                TO_CHAR(SQLCODE) || '): ' ||
                                                SQLERRM ||
                                                '
Please raise this issue with the helpdesk.');
        XXXX_emailmanager.processMails;
        rollback;
      end;
  end RenameUsers;

end XXXX_APPUSERMANAGER;


Now the bad news; this won't work (yes, I know that's a bit of a biggie). For copyright reasons several routines are missing from the package, the routine that sends the notification email to the user letting them know that their user name and password have been changed. In the packages these routines are referred to as:
XXXX_emailmanager.addEmail, and
XXXX_emailmanager.processMails

The former allows you to add an e-mail to a queue, the latter processes all emails in the queue (rather than waiting for an automated process to pick the new email up).

These are custom packages that sit on top of two packages from oracle; BASE64ENCODER and EMAILER. Unfortunately the links I have for these packages are no longer working but as this is pretty standard functionality that most people would want to do it shouldn't be too hard to find a replacement (or the packages themselves - try google).

One day it's my goal to write an installation script to get everything installed nicely, but that goal is not going to be met today (and as I'm updating this post 3 years later and I still haven't done it it's looking like "never" is the window of time this work will be dropping into!).

Wednesday, April 16, 2008

Oracle EBS: Tidying Up Partially Paid Expenses (in Internet Expenses)

As I may have mentioned previously I'm nearing the end of an implementation of Oracle Internet Expenses for a medium-sized pharmaceutical company in the UK. One of the issues that came up is the interesting way expenses are handled in the current (pre-OIE) Accounts Payable world.

At the moment, once a month, the company receives a statement from Barclaycard which lists the total amount outstanding on each of the company credit cards for all staff in Head Office and across the UK in the Sales Force. Because the credit cards are "company pay" and the payment itself is handled outside of AP (i.e. Barclaycard isn't setup as a vendor/supplier in Oracle) one of the AP staff sits down and enters each card total as a "prepayment" in AP against that individuals supplier record. This takes a couple of days.

The individual then accounts for their expenses in the usual way (it's an Excel spreadsheet in case you're wondering), returns all the details to Finance and then the AP staff enter the expenses on the system in the usual way. Because the prepayments have been entered the employee will only actually be paid for any expenses they incurred that haven't been paid for on their company Barclaycard.

There are plenty of loop holes (not to mention lots of reports checking to make sure that loop-holes we know about aren't being abused) and the entire process is very time consuming.

The reason I mention the way the system is being used is that it causes a problem with Internet Expenses (although it's pretty unique ... who else does it this way?). The problem is that in AP the expense is recorded as being "partially paid". This means that when the user logs into Internet Expenses the expense will still appear in their "active" list at the top (and they have no way of clearing it).

After working with Oracle they suggested a fairly simple piece of SQL that would be "fix" the open expenses;

update ap_invoices_all i
set payment_status_flag = 'Y'
where i.payment_status_flag <> 'Y'
   and i.source = 'XpenseXpress'
   and i.invoice_type_lookup_code = 'EXPENSE REPORT'
   and payment_status_flag = 'P';


This marks the expense as "paid" from the AP side. It's almost certainly best to make sure that you have a list of the affected invoices before you make any changes (just in case);

select i.invoice_id, i.invoice_num
from ap_invoices_all i
where i.payment_status_flag <> 'Y'
and i.source = 'XpenseXpress'
and i.invoice_type_lookup_code = 'EXPENSE REPORT'
and payment_status_flag = 'P';

It's a very specific circumstance, maybe it will be useful to others!

Friday, April 11, 2008

Oracle EBS: Comparing Profile Options In Two Systems (i.e. Test vs Live)

Probably one of the most useful code snippets. By creating a database link between test and live systems you can directly compare the contents of tables and see which items have changed. This script specifically details the profile options that have changed as well as any new profile options that have appeared.

I find this especially useful for writing documentation, or just for capturing changes.

NOTE: For the purposes of this script the link between live and test is called APPSRO, the live system is called APPLIVE (and runs on ENTERPRISE) and the test system is called APPDEV(and runs on DEFIANT).

declare
  -- These constants have the server names and SIDs, they're necessary so that "normal" changes during the
  -- cloning process aren't reported as profile option changes.
  c_TEST_SERVERNAME constant varchar2(255) := 'APPDEV';
  c_TEST_SERVER     constant varchar2(255) := 'DEFIANT';
  c_LIVE_SERVERNAME constant varchar2(255) := 'APPLIVE';
  c_LIVE_SERVER     constant varchar2(255) := 'ENTERPRISE';

  -- This will produce a MASSIVE report if set to YES
  v_ShowUnchanged varchar2(3) := 'NO';

  cursor c_AllProfileOptions is
    select fpo.profile_option_id, fpo.profile_option_name
      from applsys.fnd_profile_options fpo;

  cursor c_TestOptions(p_OptionId in number) is
    select Application_Id, Profile_Option_Id, Level_Id, Level_Value, Profile_Option_Value
      from applsys.fnd_profile_option_values fpov
     where fpov.profile_option_id = p_OptionId
       and fpov.level_id in (10001, 10002, 10003); -- site/app/resp level

  cursor c_LiveOption(p_Application in number, p_ProfileOption in number, p_Level in number, p_LevelValue in number) is
    select profile_option_value
      from applsys.fnd_profile_option_values@APPSRO fpov
     where fpov.application_id = p_Application
       and fpov.profile_option_id = p_ProfileOption
       and fpov.level_id = p_Level
       and fpov.level_value = p_LevelValue;

  cursor c_NewOptions is
    select fpov1.Profile_Option_Id,
           fpov1.Level_Id,
           fpov1.Profile_Option_Value,
           fpov1.Application_Id,
           fpo.profile_option_name
      from applsys.fnd_profile_option_values fpov1,
           applsys.fnd_profile_options       fpo
     where fpov1.level_id in (10001, 10002, 10003)
       and fpov1.profile_option_id = fpo.profile_option_id
       and not exists
     (select 'x'
              from applsys.fnd_profile_option_values@APPSRO fpov2
             where fpov2.application_id = fpov1.application_id
               and fpov2.profile_option_id = fpov1.profile_option_id
               and fpov2.level_id = fpov1.level_id
               and fpov2.level_value = fpov1.level_value);

  function isDifferent(p_Text1 in varchar2, p_Text2 in varchar2) return boolean is
    v_Text1 varchar2(1024);
    v_Text2 varchar2(1024);
  begin
    v_Text1 := upper(nvl(p_Text1, ''));
    v_Text2 := upper(nvl(p_Text2, ''));
    if instr(v_Text1, c_TEST_SERVERNAME) > 0 then
      v_Text1 := replace(v_Text1, c_TEST_SERVERNAME, c_LIVE_SERVERNAME);
    end if;
    if instr(v_Text2, c_TEST_SERVERNAME) > 0 then
      v_Text2 := replace(v_Text2, c_TEST_SERVERNAME, c_LIVE_SERVERNAME);
    end if;
  
    if instr(v_Text1, c_TEST_SERVER) > 0 then
      v_Text1 := replace(v_Text1, c_TEST_SERVER, c_LIVE_SERVER);
    end if;
    if instr(v_Text2, c_TEST_SERVER) > 0 then
      v_Text2 := replace(v_Text2, c_TEST_SERVER, c_LIVE_SERVER);
    end if;
  
    return not(v_Text1 = v_Text2);
  end isDifferent;
begin
  rollback; -- because of the DB link you can get transaction problems if you run the process twice
  for v_Option in c_AllProfileOptions loop
    for v_Test in c_TestOptions(v_Option.Profile_Option_Id) loop
      for v_LiveValue in c_LiveOption(v_Test.Application_Id,
                                      v_Test.Profile_Option_Id,
                                      v_Test.Level_Id,
                                      v_Test.Level_Value) loop
        if isDifferent(v_LiveValue.profile_option_value,
                   v_Test.Profile_Option_Value) then
          dbms_output.put_line('CHANGED TESTVALUE ' ||
                               v_Test.Application_Id || ',' ||
                               v_Test.Profile_Option_Id || ',' ||
                               v_Test.Level_Id || ' (' ||
                               v_Option.Profile_Option_Name || ')=' ||
                               v_Test.Profile_Option_Value);
          dbms_output.put_line('CHANGED LIVEVALUE ' ||
                               v_Test.Application_Id || ',' ||
                               v_Test.Profile_Option_Id || ',' ||
                               v_Test.Level_Id || ' (' ||
                               v_Option.Profile_Option_Name || ')=' ||
                               v_LiveValue.profile_option_value);
        else
          if v_ShowUnchanged = 'YES' then
            dbms_output.put_line('NO CHANGE ' || v_Test.Application_Id || ',' ||
                                 v_Test.Profile_Option_Id || ',' ||
                                 v_Test.Level_Id || ' (' ||
                                 v_Option.Profile_Option_Name || ')=' ||
                                 v_Test.Profile_Option_Value);
          end if;
        end if;
      end loop;
    end loop;
  end loop;

  for v_NewOption in c_NewOptions loop
    dbms_output.put_line('NEW OPTION ' || v_NewOption.Application_Id || ',' ||
                         v_NewOption.Profile_Option_Id || ',' ||
                         v_NewOption.Level_Id || ' (' ||
                         v_NewOption.Profile_Option_Name || ')=' ||
                         v_NewOption.Profile_Option_Value);
  end loop;
  rollback;
end;

Friday, February 8, 2008

Oracle EBS: Hiding Import Spreadsheet/Export Spreadsheet in Oracle Internet Expenses

So your company wants to implement a web-only version of Oracle Internet Expenses (i.e. no off-line completing expenses in Excel). The problem is that whenever a user logs into OIE they are presented with three buttons; Create Expense Report, Import Spreadsheet, and Export Spreadsheet (see below)

Figure 1: Expense Report Buttons (default view)

You'll notice that there are a lot of "personalize" links in Figure 1. In order to turn on personalisation you need to following the instructions in my "Changing Justification to Description" blog to update the system profile setting (click here).

In order to start the Personalization process click "Personalize Page" (top right):

Figure 2: Personalize Page

This screen shows you all the options you have when personalizing the screen. There are a lot of them. In order to find the one of we want to alter press Ctrl-F (Internet Explorer/ Firefox "Find") and enter "Import" as shown below:

Figure 3: Internet Explorer Find Dialog

After you click "Next" it will jump to the bottom of the screen and display:

Figure 4: Button Settings

As you can probably just make out from the screen shot (isn't the resizing in Blogger terrible?!) there are options for two buttons; "Button: Import Spreadsheet", and "Button: Export Spreadsheet". Click on the little pencil (edit) in the first line:

Figure 5: Available Personalization Options

Whilst this screen looks complicated it really isn't. What you basically have is options down the left side and across the top you have permission levels. You can change the settings just for you, for all users of your company, for all users of the site, for all users of the system, etc. Wherever you see "Inherit" the option is "use the default".

The bit we need to change is "Rendered". At the moment this is set to "true", we need to change this to "false". However, when you make the change a "warning" will appear that is usefully titled "Error" (just to really worry you):

Figure 6: Error when Changing Rendered Property (really a warning)

What this telling you is that if there are any children for the object you are making invisible they will be made invisible to. For buttons there aren't any children so this error is really just to put the wind up you and doesn't really have any effect.

Now you've made the change for this button, make the change for the other button and then go back to the Expenses page and as if by magic both buttons will be gone.

Thursday, January 24, 2008

Oracle EBS: Changing "Justification" to "Description" in Internet Expenses

Now this is a pretty obscure one, I'd be amazed if there were too many people out there who had this problem!

Basically the issue is that I work for a company that rather than having the traditional pyramid structure of management with the people at the top never talking to anyone we have a much flatter structure and if you are brand new in through the door and fancy talking to the MD about something ... then that's fine (even encouraged).

In light of this different culture people who tested our i-Expenses system commented that the word "Justification" wasn't really in keeping with the companies culture. We also didn't require a "justification" to make an expense claim, but a Description would sure help us authorise it. It's a fairly simple change so why not?!

First of all you need to login and select the "System Administrator" responsibility, then go into "Profiles > System" and query for "Personalize Self-Service Defn%". By default this is set to "No", you need to set it to "Yes" (and remember to switch it off after you're done!):

Figure 1: Setting System Profile Options

Next you need to log out and choose the "Internet Expenses" responsibility and then go into the website. You'll notice that there is a "Personalize" link at the the top right of the page and various other links through the website. You can use these to change the way the page displays. You can also use these to make the site completely unusable - so be careful!

The "Description" we are trying to change is on the "Receipt-based Expenses" page. So you need to create a new expense claim and click through to that page (we won't be submitting, so it doesn't matter what you enter). Your screen will look something like this:

Figure 2: Cash and Other Expenses Page

A new link has appeared above the table beginning "Personalize" ... Clicking this link gets you to the field you need to edit quicker, but clicking any link and drilling down will work just as well (well, I'm assuming here ...!).

Now you will need to move down the list of options until you find "Message Text Input: Justification", then click the pencil (edit) to the right:

Figure 3: Editing "Justification"

Clicking on the pencil will display the following screen:

Figure 4: Changing Text

I have highlighted the entry boxes to change "Justification" for your entire organisation. If you just want to change it for your site (or even just for you) then use the boxes immediately to their left.

Clicking on the circular arrow next to the entry boxes restores them to "Inherit" which in effect deletes your change.

NOTE: When you look for these items again (say you wanted to change back to "Justification") then in Figure 3 where it shows "Justification" it would now show "Description".

Friday, January 4, 2008

Oracle EBS: Editing the FA Account Generator Process (Oracle Financials)

1. Editing Workflows using Oracle Workflow BuilderInstall "Oracle Workflow Builder" from the Oracle.com website. The version you will need depends on the version of Oracle Applications you are currently using. If you are unsure which version to use you can always raise a Service Request (SR) via Metalink and ask Oracle.

To open the workflow select “File > Open” from the menu:

Figure 1: Oracle Workflow Builder, Open Dialog

User and password are for the Oracle APPS account.

If you want a version of the Workflow other than the current version you can enter a date in the “Effective” entry box and it will give you the version of the workflow that was in effect on that date. Unless you’re doing a rollback to a previous version you can leave this blank.

Clicking “OK” will connect to the database and then display the “Show Item Types” dialog:

Figure 2: Oracle Workflow Builder, Show Item Types

The Workflow to edit is called “FA Account Generator”, in order to edit it you need to highlight it in the right-hand list (Hidden) and move it into the left-hand list (Visible) – as shown in Figure 2. Once you’ve selected it click “OK”.

NOW THIS IS IMPORTANT: If you work on a workflow while connected to the database any change you make is immediately committed to the server. As soon as you have opened a Workflow for editing you should save the Workflow locally and work on the local copy rather than working against a database (you can then open the local file and save it back to the database when you’re done).

The Workflow builder uses an MDI interface, a window will open titled “Navigator”:

Figure 3: Oracle Workflow Builder, Navigator

All the items shown in the figure above (beginning "Generate ...") are the workflows provided by Oracle. You should never edit these, if you do there is a risk (well, a practical certainty) of them being overwritten during an upgrade. If you need to make changes to a standard item (i.e. the process “Generate Book Level Account” in Figure 3) then you must create a copy of that item by right-clicking it, selecting “Copy” and then “Paste”. When prompted to enter the details prefix the name with a short-code, for example your company name or initials (there are length limitations, if you go over the length just remove characters from the end until it fits).

Fixing problems with the “Generate Accounts” process requires that you open (double-click) the “XXXX Generate Book Level Account” process (where XXXX is your chosen prefix). The original version (i.e. the “Generate Book Level Account” process) is below:

Figure 4: Generate Book Level Account Process

As you can see the "out of the box" process is fairly straight forward. The most common changes are usually to create "custom" branches coming off the "Get Book Account Name" process (where it shows "" above the arrow). Looking at the company I currently work for our customised process is:

Figure 5: Customised Generate Book Level Account Process

This shows separate flows for Proceeds of Sale (Loss/ Gain/ Clearing), Cost of Removal (Loss/ Gain/ Clearing) and Net Book Value Retired (Gain/ Loss). If you check the first “Assign to Value …” in each of the three flows you’ll see that these route to hard-coded constants:

Figure 6: Process Flow Hard-Coded Values (009) .

If a new branch needs to be created then you will need to copy most of the values from an existing branch (unfortunately there is no “copy/paste” for processes so you need to create new processes by dragging and dropping from the navigator and then set their properties).

2. Configuring Apps to use the New Workflow
After the work flows have been altered and you have uploaded them into Apps you need to configure Oracle E-Business Suite to stop using the Default workflow and switch to the customised version.

To do this you need to connect to Apps and switch to the “Fixed Assets Manager” responsibility. Expand the Financials > Flexfields > Key option in the tree view and select “Accounts” (see below):

Figure 7: Showing the Account Generation Options

Once you have selected this you are presented with an empty grid:

Figure 8: Account Generator Processes

Click on the “Find” button on the toolbar and search for “General Ledger%” and click “Find”. Select the entry with the correct structure (usually the company name)

Click “OK”.

The main Account Generator Process window will now populate with a list of Item Types and Processes. Scroll down and highlight the “FA Account Generator” Item Type:

Figure 9: Selecting the FA Account Generator

Click on the “…” (in the Process Name field) and you are presented with a list of processes from your workflow. Select the correct process (most likely “XXXX Generate Default Account”) and then click the save button on the toolbar.