Workflow and Account Generator in Oracle Projects: An Oracle White Paper July 2001
Workflow and Account Generator in Oracle Projects: An Oracle White Paper July 2001
Workflow and Account Generator in Oracle Projects: An Oracle White Paper July 2001
Definitions
Data Store – The file or database that holds the workflow process information.
Item Type – A collection of processes and components that represents what we
generally think of as a ‘workflow’ (e.g., “Project Supplier Invoice Account
Generation” or “PA Project Workflow”).
Attributes – Variables or parameters that are available to the “Item Type” and
store related information. Generally, most of the attributes for an “Item Type”
are initialized when the workflow is kicked off.
Processes – The actual workflow definitions. They define what should happen
at each stage. These are represented graphically in the workflow builder with
nodes, decision points, subprocesses etc.
Notifications – Used within processes at decision points or to inform someone of
an action that has occurred within the workflow. These can be purely
informative, or may require a response from the user.
Functions – Activities within a workflow process that call a stored PL/SQL
procedure. For example in the PO Account Generator item type, there is a
function “PO-Project Related?”. Depending on the result of this function the
workflow process branches in two distinct directions.
Messages – The messages that are sent during notification activities.
Message attributes – Attributes which are referenced in your message. Send
attributes are existing attributes that you can reference in your message (e.g.
project number). Respond source attributes prompt the receiver of the
1
notification for a response. A special respond attribute called RESULT can be
used to determine how the workflow process will branch after a notification
activity.
Lookup Types – Lists of valid results. These can be referenced by notifications,
functions, messages or processes to define the valid outcomes.
Activities – The nodes of your workflow process. They can be notifications,
functions, or subprocesses.
Transitions – The arrows that lead from one process activity to the next. A
transition can be associated with a particular result value. When an activity
returns a result, the process will follow the transition associated with that result.
Version considerations **
regsvr32 d:\orant_wf25\wf\wfproc20.ocx
regsvr32 d:\orant_wf25\wf\wfnvg20.ocx
2
These files are located in %ORACLE_HOME%\wf20 for version 2.0 and in
%ORACLE_HOME%\wf for version 2.5. Before registering the files make
sure you are located in the bin directory for the appropriate oracle home.
Protection Level
If “Lock at this Access Level” is not checked, then this value is 1000, otherwise
it is some value between 0 and 1000. You may only modify an object if your
access level is lower than this value
So assuming that customization and access level protections are both enabled,
you can only modify an object if your access level is between the customization
and protection access levels for that objects.
3
The item type parameter is only used for the DOWNLOAD mode.
Example:
WFLOAD apps/apps 0 Y UPGRADE \
$PA_TOP/admin/import/PAPROWF.wft
This process (Workflow Definitions Loader) can also be run from within the
application in the System Administrator responsibility.
The modes used are as follows:
UPLOAD
Upload the definition from the file using the access level specified by the
environment variable WF_ACCESS_LEVEL. This allows the user to control
what access the file is loaded with and what customization level will be
preserved. This variable could be set in the applications environment file.
UPGRADE
Upload the definition from the file using the access level defined as the ‘Seed
Data’ access level. This should preserve all customizations created at above this
level.
FORCE
Upload the definition exactly as it is from the file overwriting any existing
definition including any customizations. This is useful for restoring the
definition of an item type that may have been corrupted to its original value.
DOWNLOAD
Used for extracting the stored definition of an item type from the database.
4
Project Workflow PAPROWF PA Project Workflow
5
$ grep 'BEGIN ITEM_TYPE <ITEMTYPENAME>' *.wft
For example:
$ grep ‘BEGIN ITEM_TYPE PATCARD’ *.wft
These files (when available) can be loaded into workflow builder and saved to
the database or vice versa. They can also be loaded into the database using the
WFLOAD utility as described above.
Monitoring Workflows
There are several methods of monitoring the progress of a particular workflow
instance. Each involves knowing the item type (eg, PAWPROF, or “PA Project
Workflow) and the “item key” for the particular workflow process you wish to
monitor. The item key is an identifier that names a particular run or instance of
an item type. Whenever a workflow process is initiated, that individual run is
assigned an item key to identify it.
The item types are listed above. The item key can be found in the Workflow ®
Status form in Projects (Release 11.0) (Querying by item type and dates) or,
more generally, via SQL*Plus from the table: WF_ITEMS. A sample script for
getting the key is below:
Select item_key, begin_date, end_date
From wf_items
Where item_type = ‘PAPROWF’
And begin_date between ‘&low_start’ and ‘&high_start’;
If this does not definitively identify your item you can query on the various items
in the Workflow status form to give you more information about the activities
associated with them. For project and budget workflows you can also use the
table ‘PA_WF_PROCESSES’ to get your key. This table stores the project_id
or budget_version_id (depending on the workflow type) in the column
entity_key1 and the item_key in the column item_key.
The item_key for the timecard approval workflow (PATCARD) is the same as
the timecard number.
6
Viewing the Workflow Diagram from Within Projects
From within Projects you can monitor the progress of a project or budget
workflow from within the relevant forms (Projects or Budgets) via the Special
® Monitor Project|Budget Workflows menu item (in 11.0). In 11.5 the menu
path is Tools ® Monitor Project|Budget Workflows. Unfortunately this only
allows you to view the progress, and does not allow you to administer the
workflow. Below is a little trick to get to the administration URL if you do not
have access via a Web Applications responsibility.
How to Get Administration URL for a Workflow:
**************************************************
set serveroutput on
declare
url_l varchar2(1000);
l_agent VARCHAR2(2000) := NULL;
begin
l_agent := WF_CORE.TRANSLATE('WF_WEB_AGENT');
url_l := wf_monitor.getEnvelopeUrl
(x_agent => l_agent
, x_item_type => upper('&item_type')
, x_item_key => '&item_key'
, x_admin_mode => 'YES'
);
dbms_output.put_line (url_l);
end;
/
**************************************************
Plug the resulting URL into your browser and it will bring up the same
workflow diagram you were able to view from within the application, but with
administration privileges:
7
The diagram will show you where the process is, its status, the values of
attributes, etc.
The green line indicates the progress of the workflow process. So for instance,
the above process is currently in the approval process stage. Double clicking on
this icon would bring up a new diagram showing the “Approval Process”. The
“Definition”, “Usage”, “Status”, “Notification”, and “Item” tabs provide
detailed information about the node of the process that is currently highlighted.
At the bottom of the screen you have several buttons that allow you to
administer the process. When the diagram is viewed without administrator
privilege, these buttons and the “Item” tab are not present.
Abort Process
The “Abort Process” button will result in the termination of the process and the
cancellation of any outstanding notifications.
Suspend/Resume Process
The “Suspend Process” button will suspend execution of the process so that no
new transitions occur. Outstanding notifications can be completed, but the
process will not advance. When a process is suspended, the “Resume Process”
button will be enabled. This button will allow the process to continue on to its
next transition as normal.
8
Reassign
The “Reassign” button will be enabled when a current activity with a performer
is highlighted. The “performer” is the person who will perform the activity,
which in most cases means that he is the receiver of a notification.
Expedite
The “Expedite” button allows you to bypass the normal functioning of the
process. When a workflow process is stuck waiting for a response to a
notification, the expedite button allows you to advance to the next transition. If
the current activity should return a value (eg, “Approved” or “Rejected”) then
the expedite button will allow you to select the appropriate return value. It will
give you the opportunity to “Retry” the current activity, if you think that you
have fixed the problem that caused it to become stuck, or if you choose you can
select the appropriate return value and “Skip” the activity. This will cause the
workflow to continue on to the next transition without performing the current
activity.
Attributes
The “Attributes” button will display a listing of all the attributes associated with
the workflow process and their current values.
In Release 11.5, you can also access the Workflow monitor from the “Workflow
Administrator” responsibility. This will take you to the same screen as you
access via the “Workflow” responsibility in Self-Service applications described
below. The Workflow responsibility is available in 11.0 and 11.5.
From with in the Self Service applications, if you have been assigned the
“Workflow” responsibility, you will have access the “View Progress” screen
shown below:
9
Once you have entered your criteria and pressed “Find” you will be taken to a
list of workflow processes. Selecting one of these processes will take you to the
same screens pictured above.
What processes you are able to see depends on whether you have the
administration privilege or not. If you do, you will be able to query all existing
item types and view all processes. If you do not, you will be able only to view
those processes where you are the process owner.
Technically, you are the process owner if WF_ITEMS.OWNER_ROLE is equal
to your username. In some cases, the owner role may not be populated at all,
and as a result you will not be able to see your own process.
Administrator Privilege
Viewing the workflow process with administration privilege is very useful for
If you are trying to fix a workflow process
cases where a bad workflow is stuck at some point and cannot be moved
that is “stuck”, you will need to access it in
the workflow monitor with administration forward because, for example, someone never received a notification.
privileges. Otherwise the workflow
What determines how one gets administrator privilege is a particular value in the
monitor is view only.
table WF_RESOURCES. In this table there is one record with:
TYPE=WFTKN and NAME=WF_ADMIN_ROLE
The value of the TEXT column for this record determines what role(s) will be
able to access the workflow monitor in administrator mode. If the value of
TEXT is ‘*’, then all roles and all users will access the monitor with
administrator privilege; otherwise, a user will only be able to access the
administrator mode if he has been assigned the ROLE specified by TEXT.
That is, if there is a record in the view WF_USER_ROLES indicating the user’s
user name, and the administrator role. The value of this role can be anything: a
user name, a responsibility, or some other string. The WF_USER_ROLES view
will contain automatically one record where the role assigned is just your user
name, and one record for each of the applications responsibilities you have been
assigned. For these responsibility roles, the role_name format is
“FND_RESP<APPID>:<RESPID>” where <APPID> represents the application
id of the responsibility and <RESPID> represents the responsibility id.
You can also assign roles to users manually by creating records in the table
WF_LOCAL_USER_ROLES.
So, for example, if I wanted only the user ALUMPE to have administrator
privilege, I would set the WF_ADMIN_ROLE to be ‘ALUMPE’:
update wf_resources
set text = ‘ALUMPE’
where type = ‘WFTKN’
and name = ‘WF_ADMIN_ROLE’;
10
If I wanted only users with “Projects, Vision Services (USA)” responsibility to
have administrator privilege, I would set this value to: ‘FND_RESP275:50604’
where 275 is the application id for Oracle Projects, and 50604 is the
responsibility_id for “Projects, Vision Services (USA)”.
These, and other administrative scripts, are listed and described in the Workflow
Users Guide. They can be found in $FND_TOP/sql.
wfstatus.sql
Given the item type and item key, this script prints an end user report of the
status of the workflow. It shows information about the item type and process,
the activities, error activities, and the values of the process attributes. The script
output looks like the following:
8 rows selected.
**** Errored Activities
11
FORWARD_FROM_NAME
LINE_TABLE plsql:PA_SELF_SERVICE_WF_PKG.G
enerateTimecardLines/PATCARD:1
1352
wfstat.sql
Given the same parameters, this script prints a “developer level” status report.
The information included is basically the same as that produced by wfstatus.sql,
but in some cases underlying system names are used rather than “User” names
when displaying the information.
12
ACCOUNT GENERATOR
An Account Generator workflow is a specific type of workflow used within the
applications to dynamically generate an account combination for the accounting
flexfield. It uses the workflow technology to replace the “Flexbuilder” feature
used in Release 10.7 and prior.
Assigning Processes
There is a pre-defined item type for each of the account generator workflows
within the applications. Generally there is a seeded process that will be called
when the account generator is invoked, although in some cases this seeded
process contains no default logic and must be customized (e.g., the Project
Supplier Invoice Account Generator). Customers can always modify the pre-
defined processes or create new account generator workflow processes within
these pre-defined item types to implement their own account generating logic.
The actual process that will be called when the account generator is invoked is
defined in the form:
Setup®Flexfields®Key®Accounts
In this form, the flexfield application is “Oracle General Ledger” and the
flexfield is the “Accounting Flexfield”. The structure you select is the
Accounting Flexfield structure being used by the set of books whose account
generator processes you are assigning. In the bottom zone of the form, there is a
list of applicable item types followed by the process being used to generate the
13
corresponding account. For each item type, you can select any ‘Runnable’
process defined within the item type. A ‘Runnable’ process is one which has the
‘Runnable’ attribute enabled in workflow builder.
If you were to create a custom process for one of your account generators, you
would have to come to this form and assign it to the corresponding item type in
order for it to take effect.
In some cases your item type (e.g. Supplier Invoice Account Generation) may
not appear in the form. Often this is because the process that has been assigned
to the item type no longer has the 'Runnable' attribute enabled. You can update
this attribute for the process in Workflow Builder and re-save to the database.
Once the process has been flagged runnable, the record for this item type will
again show up in the form.
14
· PAAPWEBX -- Project Expense Report Account Generator
· POWFPOAG -- PO Account Generator
· POWFRQAG -- PO Requisition Account Generator
Note that each of these processes is invoked from within an application other
than Oracle Projects. The first two are called from Oracle Payables when
creating project related supplier invoices and expense reports, and the second
two are called from Oracle Purchasing when entering projects related
requisitions and purchase orders. For transactions created within Oracle
Projects, account codes are generated using your autoaccounting setup rather
than Account Generator processes.
Project Supplier Invoice by default: There is no default setup. Unless you have
upgraded from Release 10.7 and are using your converted flexbuilder rules (see
below) this account generator process MUST be customized. The default
process “Generate default account” contains nothing more than a dummy
procedure (PA_ACC_GEN_WF_PKG.AP_INV_ACC_UNDEFINED_RULES)
which generates the following message and aborts:
The default workflow for the Oracle Payables account function Project Supplier Invoice
Charge Account has not been customised. Please replace the dummy function in the
default process for account generation by your own account generation method.
PO Project-Related?
The default PO and Requisition Account Generator processes contain a
procedure to determine if the PO or requisition is project-related or not. This
procedure (PO_WF_PO_CHARGE_ACC.IS_PO_PROJECT_RELATED) as
defined is a dummy procedure that always returns false. In order to generate
15
specific accounts for project-related purchase orders and requisitions, this
process must be modified, or the activity replaced with another that accurately
determines whether the object is projects-related.
A common technique to accomplish this is to replace the function activity with a
“Compare Number” function (available in the list of standard functions). This
function allows you to compare the value of the “Test value” (which you set to
be the item attribute “Project id”) and the “Reference value” (which you set to
be the constant 0). The results of this function are “Greater Than”, “Less Than”,
“Equal” or “Null”. It will return null if the test value is null. Therefore
branching off of this comparison you will have two transitions. One linked to
the “Null” return value which leads to the non project-related process, and one
which is the <Default> encompassing all the other return values which leads to
the project-related process. In this way, if the project_id is not null, it will
branch to the project related process.
16
· Segment – The value that corresponds the the Segment Identifier. For
example, if you chose “Name” for segment identifier, here you would
supply an actual segment name. If you had selected “Qualifier” you would
supply the flexfield qualifier that would identify the segment (eg,
“Company”, “Cost Center”, or “Account”).
· Value – Either a constant value that will be assigned to the segment or the
name of an item attribute whose value will be assigned to the segment.
· Replace existing value – Takes a value of “True” or “False” and indicates
what to do if the segment already has a value assigned. True will result in
the existing value being over-written. False results in retaining the existing
assignment.
17
Also, as for the “Copy Value from Code Combination” function you have an
alternative version “Get Value from Other Structure Code Combination”. In this
case too you can access values from another chart of accounts by specifying a
value for the structure id.
Given that Oracle Projects uses autoaccounting to generate most of the account
combinations used by the application, there is often a good deal of effort that
goes into establishing and maintaining lookup sets and their values. In many
cases it would be useful to be able to take advantage of this effort when creating
your account generator processes as well.
To this end, the Projects development team has provided a seeded function
“Segment Lookup Set Value”. It’s attributes are:
· Lookup Set Name – Name of the lookup set you wish to use
· Intermediate Value – The reference value that will be used to locate the
lookup set value. This can be a constant value, or some item attribute whose
value will be used.
The resulting lookup set is then assigned to the item attribute “Lookup Set
Value”. You can subsequently assign this to a flexfield segment using the
“Assign Value to Segment” function referencing this item attribute (“Lookup Set
Value”) as your value.
You can create your own PL/SQL procedures that can be executed by a function
activity in your workflow process. These PL/SQL procedures must have a
standard format. The parameters of the procedure need to be the same as in the
following declaration:
18
activityid in number,
funcmode in varchar2,
resultout out varchar2 ) is
Workflow will pass the appropriate values for all of the “IN” parameters.
Somewhere in your procedure you will assign the value of the “OUT” parameter
“resultout”. The “itemtype” parameter will hold the internal name of the
workflow, (e.g., PAAPINVW). The “activityid” will hold the value of the
identifier for the function activity that has called the procedure. For a function
activity, “funcmode” will be either “RUN” or “CANCEL”. You can use the
value of “funcmode” to invoke separate logic in the case of a normal call and in
the case the activity is being cancelled.
If your function activity has a result type, then the “resultout” parameter will
normally be assigned a value of the form: “COMPLETE:<RESULT CODE>”
where <RESULT CODE> is one of the valid internal values for the result type.
For example, if the activity’s result type is “Flexfield Result” the valid values for
this lookup are “Success” and “Failure”. The corresponding internal values are
“SUCCESS” and “FAILURE”. So in this case you would normally assign one
of the following to the “resultout” parameter:
COMPLETE:SUCCESS
COMPLETE:FAILURE
Your function activity can then branch based on the outcome returned.
Within your PL/SQL procedure you can retrieve and assign the values of your
workflow’s item attributes using the workflow engine API’s. The Oracle
Workflow Guide has a complete listing of these API’s but some of the more
useful ones are described below
GetItemAttribute
There are actually several different API’s that fall under this heading, but all
perform the same function: they allow you to access the value of the item
attributes associated with your workflow process. The particular API you would
use depends on the data type of the attribute whose value you are accessing:
· GetItemAttrText
· GetItemAttrNumber
· GetItemAttrDate
Each of these functions takes the same three parameters and returns the value of
the attribute:
1) The item type
2) The item key
19
3) The attribute name.
Using these API’s you can access the values associated with the workflow
process which will allow you to implement the logic of your PL/SQL procedure.
For example, if your account code will depend on the expenditure type of the
invoice distribution in question, you can get the value of the
EXPENDITURE_TYPE attribute and use this in your PL/SQL procedure.
SetItemAttribute
Similar to the “GetItemAttribute” functions, there are also different versions of
this API which correspond to the different possible data types of the attribute
whose value you wish to set:
· SetItemAttrText
· SetItemAttrNumber
· SetItemAttrDate
A Sample Procedure
One simple strategy to implement your Account generator almost completely
within PL/SQL would be the following, which we will illustrate with an example
below:
1) Create an item attribute of type number to store a code combination id
2) Write your process to extract the code combination of the account
combination you wish to use in PL/SQL
3) In your PL/SQL process, assign this value to your attribute
4) Use the standard flexfield function “Copy Values from Code
Combination” to assign values to all the account segments using your item
attribute for the “Code Combination ID” activity attribute.
The commented example below illustrates most of the concepts you would need
to carry out steps 1-3 above:
CREATE OR REPLACE PROCEDURE AGL_WF_FCN (
itemtype in varchar2,
itemkey in varchar2,
actid in number,
funcmode in varchar2,
result out varchar2) IS
-- Above: create the procedure with the 5 required parameters
20
l_expenditure_type varchar2(60);
l_my_ccid number;
BEGIN
-- Assuming our CCID will depend on the expenditure type, get the
-- value of this attribute for use in our procedure:
-- Get the code combination id of the account I want. This would normally be
-- where you would incorporate all of the logic required to build your
-- account. In this simple example, use account '5050' for all but 'Furniture'
-- expenditure types.
select code_combination_id
into l_my_ccid
from gl_code_combinations
where segment1 = '01'
and segment2 = '420'
and segment3 = decode(l_expenditure_type, 'Furniture','7334','5050')
and segment4 = '000';
fnd_message.set_name('PA', 'AGL_SINGLE_TOKEN_MESSAGE');
21
fnd_message.set_token('MSG_TOKEN', 'MY ERROR: '||sqlerrm);
wf_engine.SetItemAttrText
( itemtype=> itemtype,
itemkey => itemkey,
aname => 'ERROR_MESSAGE',
avalue => fnd_message.get_encoded);
result:='COMPLETE:FAILURE';
end;
/
In Account Generator, frequently you will want to abort the procedure should
The custom error messages you wish to
some procedure produce an error. In these cases often it would be useful to
display when aborting an account
generator process must be in an “encoded” display a custom error message when calling the 'Abort Generating Code
error message format. Combination' function to give the user some indication of what error actually
occurred. The example above contains an illustration of how we can do this in
the exception handler, which we will now explain in detail.
The “Abort Generating Code Combination” function includes an attribute “Error
Message”. However, it is not sufficient to simply assign this attribute a constant
text string with your error message. It also will not work to assign this attribute
the name of a registered applications error message. The value assigned to this
attribute must be a registered applications error message, but it must be in
“encoded” format (See the Oracle Applications Flexfields Guide for more
details on this encoded format).
The actual encoded format that is expected is as follows:
MSGAPP||fnd_global.local_chr(12)||MSGNAME||
fnd_global.local_chr(12)||MSGDATA
Where:
MSGAPP = The message application
MSGNAME = The message name
MSGDATA = Token assignments
The first thing to note here is that, given the use of the special character
fnd_global.local_chr(12), it would not be possible to assign this directly as a
constant value in the "Abort Generating Account Combination" node.
Therefore, we must assign an item attribute to this “Error Message” function
attribute and set the value of the item attribute in PL/SQL prior to branching to
the Abort node.
The first step is to assign the item attribute “Error Message” to the function
attribute of the same name in the "Abort Generating Code Combination" node:
· Right click on the Abort node and bring up Properties
· Click on node attributes
22
· Set the value of the Error Message attribute to the Item Attribute: "Error
Message"
You then need to set the value of the item attribute 'ERROR_MESSAGE' in the
PL/SQL code of the node which will branch to the "Abort" function. As
mentioned above, the value we assign to this attribute must be in the 'encoded'
error message format.
To accomplish this we can use the following procedures from the seeded
FND_MESSAGE package:
SET_NAME
This process indicates what message is to be called. The syntax is:
FND_MESSAGE.SET_NAME('<msg application short name>',
'<registered apps msg name>');
SET_TOKEN
If the message includes any tokens you can set their value using this procedure.
The syntax is:
FND_MESSAGE.SET_TOKEN('<TOKEN>', '<TOKEN VALUE>');
One way to accomplish dynamic custom error messages is to register one custom
error message whose text consists only of one token. Whenever this error
message is called, the token is then assigned the text of the error message to be
displayed
For example if the error message you have registered consists only of the token
"&ERRMSG" then to set your token to the error message you want to display
you might call:
FND_MESSAGE.SET_TOKEN('ERRMSG','This is my custom error text');
GET_ENCODED
This function will retrieve the encoded message format for the current message
and token settings. It will return the message in the format required for the
ERROR_MESSAGE attribute. The syntax is:
FND_MESSAGE.GET_ENCODED
23
wf_engine.SetItemAttrText
( itemtype=> itemtype,
itemkey => itemkey,
aname => 'ERROR_MESSAGE',
avalue => fnd_message.get_encoded);
Once this has been set, your code can return the value that will branch it to the
Abort node and your custom message will be displayed.
Common Mistakes
There are certain mistakes that occur frequently when customizing account
generator processes. Some of the most common are listed below.
When using several of the standard flexfield functions, there are two node
attributes that you must assign: Segment Identifier, and Segment. Segment
identifier will be either “Name” or “Qualifier”. You could use qualifier, for
example, to identify the cost center segment, or any other of the qualified
accounting flexfield segments, but generally is it simpler and more direct to use
the segment Name.
A common mistake, however, is to select ‘Name’ and then not enter the segment
name correctly. In some cases users will enter the segment prompt or
description rather than the name, and in others there will be differences of case,
punctuation or spelling. The value that is entered for “Segment” must
correspond exactly to the “Name” of the segment as defined in the Setup ®
Flexfield ® Key ® Segments form for the corresponding segment.
Most commonly this occurs with the standard function “Validate Code
Combination.” The name would indicate that if validation should fail we should
abort the account generator. As a result many people will hang an additional
“Abort Generating Code Combination” node off of this activity assuming that if
it fails, it will branch to this Abort node.
If you examine the properties of this function, however, you will see that its
result type is “None”. Which means there are no alternative results which it can
use to branch when it is finished validating. By adding the transition to an
“Abort” node you are simply confusing the workflow process by setting two
transitions out of the single node, with no result values to distinguish them.
As a result your account generator process will always abort.
24
Top Process Must have Start and End Nodes and be Runnable
25
Workflow and Account Generator in Oracle Projects
July 2001
Author: Andrew Lumpe
Copyright © Oracle Corporation 1995
All Rights Reserved Printed in the U.S.A.
Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065
U.S.A.
Worldwide Inquiries:
415.506.7000
Fax 415.506.7200
26