You are on page 1of 127

Oracle Approvals Management Developers Guide

RELEASE 11i10/AME.A December 2004

Oracle Approvals Management Developers Guide 1

Oracle Approvals Management Release R11i

Copyright © 2001, 2002, 2003, 2004 Oracle Corporation. All rights reserved.
Contributors: Todd Morley, Nilakshi Soni, Bill Kerr The Programs (which include both the software and documentation) contain proprietary information of Oracle Corporation; they are provided under a license agreement containing restrictions on use and disclosure and are also protected by copyright, patent and other intellectual property law. Reverse engineering, disassembly or decompilation of the Programs, except to the extent required to obtain interoperability with other independently created software or as specified by law, is prohibited. Program Documentation is licensed for use solely to support the deployment of the Programs and not for any other purpose. The information contained in this document is subject to change without notice. If you find any problems in the documentation, please report them to us in writing. Oracle Corporation does not warrant that this document is error free. Except as may be expressly permitted in your license agreement for these Programs, no part of these Programs may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose, without the express written permission of Oracle Corporation. If the Programs are delivered to the US Government or anyone licensing or using the Programs on behalf of the US Government, the following notice is applicable: RESTRICTED RIGHTS NOTICE Programs delivered subject to the DOD FAR Supplement are ”commercial computer software” and use, duplication and disclosure of the Programs, including documentation, shall be subject to the licensing restrictions set forth in the applicable Oracle license agreement. Otherwise, Programs delivered subject to the Federal Acquisition Regulations are ”restricted computer software” and use, duplication, and disclosure of the Programs shall be subject to the restrictions in FAR 52.227-19, Commercial Computer Software - Restricted Rights (June, 1987). Oracle Corporation, 500 Oracle Parkway, Redwood City, CA 94065. The Programs are not intended for use in any nuclear, aviation, mass transit, medical, or other inherently dangerous applications. It shall be licensee’s responsibility to take all appropriate fail-safe, back up, redundancy and other measures to ensure the safe use of such applications if the Programs are used for such purposes, and Oracle disclaims liability for any damages caused by such use of the Programs. The Programs may provide links to Web sites and access to content, products, and services from third parties. Oracle is not responsible for the availability of, or any content provided on, third-party Web sites. You bear all risks associated with the use of such content. If you choose to purchase any products or services from a third party, the relationship is directly between you and the third party. Oracle is not responsible for: (a) the quality of third-party products or services; or (b) fulfilling any of the terms of the agreement with the third party, including delivery of products or services and warranty obligation related to purchased products or services. Oracle is not responsible for any loss or damage of any sort that you may incur from dealing with any third party. Oracle is a registered trademark and ConText, Enabling the Information Age, Oracle7, Oracle8, Oracle8i, Oracle Access, Oracle Application Object Library, Oracle HRMS, Oracle Discoverer, Oracle Web Customers, Oracle Web Employees, Oracle Workflow, Oracle Work in

Oracle Approvals Management Developers Guide 2

Progress, PL/SQL, Pro*C, SmartClient, SQL*, SQL*Forms, SQL*Loader, SQL*Menu, SQL*Net, SQL*Plus, and SQL*Reports are trademarks or registered trademarks of Oracle Corporation. Other names may be trademarks of their respective owners.

Oracle Approvals Management Developers Guide 3

Table of Contents
1 Integrating AME into an Application .................................................................7 Overview ...................................................................................................................8 Audience ................................................................................................................8 Steps Required to Integrate AME into an Application ..........................................8 AME Security ........................................................................................................9 Deciding how Many Transaction Types to Create ................................................9 Creating a Transaction Type..................................................................................9 2 Building an Action Type ....................................................................................11 Overview .................................................................................................................12 Important – Changes from 11i9 version of AME ................................................12 Deciding Whether to Create an Action Type.......................................................12 Creating an Action Type......................................................................................13 Coding an Action-Type Handler..........................................................................14 Registering an Action Type .................................................................................25 Major changes in the Engine/ Handler Interface since R11i9 .............................26 3 Defining an Approver Type ...............................................................................29 Overview .................................................................................................................30 Approver Types in AME .....................................................................................30 Registering an Approver Type.............................................................................30 4 Defining an Item Class ......................................................................................37 Overview .................................................................................................................38 When to Define an Item Class .............................................................................38 How to Define an Item Class ...............................................................................38 5 Integrating AME with Workflow.......................................................................39 Overview .................................................................................................................40 Notifications.........................................................................................................40 The Basic Algorithm............................................................................................40 Modifications to the Basic Algorithm..................................................................41 Frequently Asked Questions ................................................................................43 Sample Workflow ................................................................................................44 Appendix A API Functional Specifications ..........................................................53 Overview .................................................................................................................54 Calling AME API Routines .................................................................................54 ame_api2 ..............................................................................................................55 What New APIs Map to the 11.5.9 APIs? ...........................................................83 Appendix B ame_util Package ...............................................................................85 Overview .................................................................................................................86 Data Types ...........................................................................................................86 Appendix C The Action-Type-Handler Programming Interface........................107 Overview ...............................................................................................................108 The ame_engine.engStApprovers Data Structure..............................................108

Oracle Approvals Management Developers Guide 5

Engine Functions ...............................................................................................108 Engine Procedures .............................................................................................115 Appendix D Sample AME Objects .......................................................................122 Overview ...............................................................................................................123 Transaction Type ...............................................................................................123

Oracle Approvals Management Developers Guide 6

1 Integrating AME into an Application

Integrating AME into an Application 7

Overview
AME is a powerful application. It provides a great deal of flexibility for creating the approvals processes an organization needs, usually without writing any custom code. AME is highly extensible. If an organization has special requirements that AME’s seeded functionality does not provide, one can often write AME extensions that meet the organization’s requirements.

Audience
This guide has two principle audiences: 1. 2. Customer requiring additional Action Types to those supplied by Oracle Corporation Development team wishing to integrate AME into their own application module

For the second audience it is normally expected that such a development team would be part of the Oracle E-Business Suite development. However, it is possible that a customer may wish to provide approval management capabilities to their own custom applications. It is for this reason that this guide is supplied to customers. For any Action Types that are not seeded or any Oracle Application module that is not integrated with AME, please submit a request to your support representative with a business case for this addition. Your principle reference to AME is the Implementation Guide rather than this Development Guide.

Steps Required to Integrate AME into an Application
1. Understand AME’s features and functionality. Study the AME Implementation Guide carefully to understand the system’s various intricacies. Identify and document the types of approval processes that the application’s customers typically require. Determine how to configure AME to satisfy each of the requirements in step two. Document any requirements in step two that AME’s seeded functionality does not satisfy. Determine how to extend AME to satisfy the requirements in step four. Define one or more transaction types for the application. Build and test any AME extensions required by step five.

2. 3. 4. 5. 6. 7.

Integrating AME into an Application 8

8.

Integrate the application’s workflow with AME’s runtime APIs.

Note: The remainder of this guide assumes that you have studied the implementation guide.

AME Security
A developer must have the AME Developer or AME Application Administrator ICX responsibility to use AME’s user interface to integrate an application with AME. (The developer responsibility has all of the administrator responsibility’s privileges, and some that the administrator responsibility lacks. See “Security” in Chapter 1 of the implementation guide for details.) Except where this guide indicates otherwise, it assumes that you will use the administrator responsibility.

Deciding how Many Transaction Types to Create
An originating application always has at least one transaction type (by definition). One of the main design decisions involved in integrating AME into an originating application is deciding how many transaction types to create for the application. Multiple transaction types may be necessary whenever customers might have good business reasons to vary any of the following, depending on the nature of a transaction generated by the originating application: • • • • an attribute usage approval-process parallelization ordering numbers and modes that are transaction-type specific an item class usage a configuration variable’s value(s)

Creating a Transaction Type
To create a transaction type, follow these steps: 1. 2. 3. 4. 5. Select the admin tab. Select ‘application administration’ and then the ‘Continue’ button on the ‘Choose an Activity Type’ form. Select ‘Maintain transaction types’ and then the ‘Continue’ button on the ‘Choose an Activity’ form. Select the ‘Add a Transaction Type’ button at the bottom of the ‘All Transaction Types’ form. Select the originating application that will own the transaction type, and then the ‘Continue’ button, on the ‘Choose an Application’ form.

Integrating AME into an Application 9

On the ‘Enter Transaction-Type Details’ form, a. Enter the transaction type’s description. (This should be a short, user-friendly description.)

b. Enter the transaction type’s ID. (This should be an acronym, typically related to the originating application’s Workflow item type.) c. Select the transaction type’s sublist mode.

d. Select the ‘Continue’ button. 6. Use the ‘Mandatory-Attribute Queries’ form to enter a usage for each mandatory attribute. For each usage you enter in a ‘Usage’ textarea, use the following ‘Static Usage’ select list to indicate whether the usage is static. Select the ‘Continue’ button at the bottom of the form to create the transaction type.

The transaction type will be created with a default item-class usage for the header item class. See Chapter 4 of this guide to learn how to add other itemclass usages to the transaction type. See Chapter 3 of the implementation guide to learn how to edit your transaction type’s attribute usages. See Chapter 11 of the implementation guide to learn how to edit your transaction type’s configuration variables.

Integrating AME into an Application 10

2 Building an Action Type

Building an ActionType 11

Overview
Note: Chapter 5 of the Oracle Approvals Management Implementation Guide explains actions and action types. Please study that chapter carefully before reading this one. There are six categories of action type: • • • • • • chain of authority list–modification substitution pre-approval post-approval production

An action type in any of the first five categories is implemented as a PL/SQL package called an action-type handler. (The AME engine processes production actions without using a handler package, so you cannot create a production action type.)

Important – Changes from 11i9 version of AME
The engine/handler interface has changed in AME 11.5.10 / AME.A. As such the old custom handlers created and used in AME 11.5.9 will have to be modified before it can be called in AME 11.5.10. Please review the section at the end of this chapter on changes to the handler interface.

Deciding Whether to Create an Action Type
The programming interface between the AME engine and action-type handlers has changed several times, and is likely to continue evolving. In contrast, AME’s attribute and approval-group architecture is more stable. These facts make custom action types more difficult to maintain than other approaches to expressing an organization’s business rules in AME. Even when you understand the action-type-handler programming interface, coding an action-type handler that is both correct and efficient can be a challenge. For these reasons, we encourage you to create a custom action type only when you have no alternative. To determine whether you need to create a custom action type, follow these

Building an ActionType 12

steps: 1. Review the seeded action types’ descriptions in Chapter 5 of the implementation guide. Make sure you can’t express the approvals logic you require with one or more existing action types. If you need to use a hierarchy of approvers not supported by a seeded action type, and the hierarchy does not exist outside AME, consider using nested approval groups to create the approver hierarchy you need in AME, and then using the approval-group chain-of-authority action type to generate chains of authority from the nested approval groups. If you need to use an approver hierarchy that resides outside of AME (say in the schema of an originating application), consider using dynamic approval groups to access the hierarchy, and the approval-group chainof-authority action type to generate chains of authority from the dynamic approval groups. If the approvers you want to use reside in a hierarchy supported by an AME action type, but their signing limits reside elsewhere, consider defining an attribute whose dynamic usage indicates the number or levels of approvers required, and referencing that attribute in your rules’ conditions. The rules’ actions would then be of an action type using the supported approver hierarchy. For example, the custom attribute might be TRANSACTION_SUPERVISORY_LEVELS. Its usage could fetch a function that ascended the hierarchy until it found an approver with sufficient signing authority, and then it could return the number of approvers it ascended. The rules would then have the form, If TRANSACTION_SUPERVISORY_LEVELS = 4 then require approvals up to the first four supervisors. 5. If the above approaches don’t meet your needs, contact AME development and request that we consider building the action type.

2.

3.

4.

If none of the above approaches meets your needs, you may elect to build a custom action type. NOTE: AME development and Oracle Support offer best effort support for custom action types.

Creating an Action Type
Creating an action type takes five steps: 1. Identify the approver types that the action type is based on. (See Chapter 3 of this guide for details about approver types.) Code the action type’s handler, and give the APPS account execute privileges on it. Register the action type in AME using the actions tab in the AME UI.

2.

3.

Building an ActionType 13

4.

Create actions for the new action type. (See Chapter 5 of the implementation guide for details.) Test the action type. (See Chapter 10 of the implementation guide for details.)

5.

The remainder of this chapter explains how to do steps 2 and 3.

Coding an Action-Type Handler
Defining Action Parameters
Most action types have several actions, and each action has a set of (zero, one, or two) parameters defined for it. How the action type’s handler interprets an action’s parameters varies with the action type. The parameters of an authority action type’s actions typically represent requirements for certain levels of authority, and the handler typically generates a chain of authority satisfying the most stringent of such requirement. The parameters of approver–group action types’ actions typically identify approval groups. The parameters of list–editing actions represent specific types of alterations to an approver list, for example changes that reflect non–uniformities in an organization’s signing–authority rules. Before you code your handler, you should define the syntax and semantics rules for the parameters of your action type’s actions. The rules should make it easy for your handler efficiently to sort, aggregate, and interpret the parameters of several actions.

Coding an Efficient Handler
AME may call your action-type handler very frequently. Recall that listmodification and substitution rules apply to an entire transaction’s approver list. As a result, AME’s engine invokes the handlers of the action types used by these rules once per transaction. In contrast, The other rules types (ignoring the production rule type) can apply to each item in a transaction’s lists of subordinate items. AME’s engine may invoke the handlers of the action types used by these rules once per item. So if, for example, a transaction has 50 line items, AME’s engine may invoke an authority action type’s handler 50 times for the transaction. If the originating application generates 1,000 transactions of the same type per day, AME’s engine might invoke the handler 50,000 times per day. So if the number of transactions and items that use your action type may be substantial, it is critical that you make your handler efficient. Efficient PL/SQL architecture is far beyond the scope of this chapter. We recommend you do at least three things to make your handler efficient: 1. Minimize the number of database queries your handler executes per transaction using language features such as bulk fetches. Tune your handler’s database queries.

2.

Building an ActionType 14

3.

Compare your handler’s asymptotic (long run) performance to that of one of the seeded handlers.

In our experience, a test set of a few thousand transactions suffices to measure asymptotic performance. Code a PL/SQL test procedure that follows these steps: 1. Bulk fetch a set of several thousand test-transaction IDs into a local PL/SQL table. Loop through the test-transaction IDs, calling ame_api2.getAllApprovers7 once for each ID, using dbms_utility.get_time to measure the execution time to the nearest hundredth of a second. Calculate and output the mean execution time per transaction ID.

2.

3.

Set up your rules to use a seeded action type (and not use the action type you’re testing), and run the test procedure. Then, change the rules using the seeded action type to use your action type instead, and re-run the test procedure. The results should be comparable.

Programming Interface
Appendix C of this guide documents AME’s action-type-handler programming interface. Please review it carefully after reading this chapter.

Package Specification Package Name
An action-type handler’s package name should be of the form ame_actionType_handler where actionType suggests the name of the action type. For example, if your handler ascended an approver custom hierarchy called the “functional” hierarchy, the handler package could be named ‘ame_functional_handler’.

Entry-Point Procedure
Each handler must have a public entry-point procedure named ‘handler’. The procedure should take no arguments. (The AME engine calls the handler procedure to invoke the handler.) The handler procedure should be the only public feature of your handler package. Thus your entire package specification might be: create or replace package ame_functional_handler as procedure handler;

Building an ActionType 15

end ame_function_handler;

Package Body
An action-type handler alters a transaction’s approver list in response to a combination of required-attribute values and actionparameter values. It should use AME-engine routines to fetch these values as necessary (see Appendix C for details). AME’s fundamental architectural principle is to encode in approval rules, attribute usages, and configuration-variable values all decisions about the general structure of a transaction’s approval process. While writing an AME action–type handler, it is possible to violate this principle by hard-coding business rules into the handler. Doing so hides business logic from the end users whose responsibility it is to define it, so please avoid the practice.

Handler-Procedure Architecture
There are three different kinds of action-type handler architectures: 1. Authority handlers generate chains of authority for action types used by list-creation and exception rules. Approval-group handlers add approval groups to an approver list for action types used by pre- or post-approval rules. List-editing handlers modify the approver list when a target approver is in it, for action types used by list-modification or substitution rules.

2.

3.

The following subsections describe the architecture appropriate for each type of handler.

Authority-Handler Architecture
An authority handler translates required-attribute and actionparameter values into one or more chains of authority, either for a given subordinate item, or for the header item. For each approver that the handler adds to the item’s approver list, the handler must populate all but one of the fields in the approver’s ame_util.approverRecord2. (AME’s engine calculates the value of the record’s approver_order_number field.) The handler procedure should implement the following pseudocode to generate the chains of authority: 1. Call ame_engine.getHandlerRules2 to fetch the applicable rules’ IDs and action parameters, and the approver categories that the rule usages assign them. Call one of the engine’s attribute-value-fetching routines to fetch any required attributes.

2.

Building an ActionType 16

3.

Analyze the action parameters to determine how many chains of authority the rules require, and when to end each chain. For each required chain, loop. a. Fetch the chain’s first approver. Check for a non-default first approver identified by a required attribute (in analogy with the JOB_LEVEL_NON_DEFAULT_STARTING_POINT_PER SON_ID attribute for the seeded absolute-job-level action type). Also check for an inserted first approver (by calling ame_engine.getHandlerCOAFirstApprover). If the required attribute has a non-null value, it should override the default value. An inserted starting point should override all others.

4.

b. Make the first approver the current approver. c. Populate the approver’s ame_util.approverRecord2 and add it to the engine’s approver list using ame_engine.addApprover().

d. Check whether the current approver has final authority. e. Try to fetch the chain-of-authority insertion following the current approver (by calling ame_engine.getHandlerCOAInsertion). If an insertion exists, make them the current approver and go to step 4c

f.

g. If final authority was found at step 4d, iterate at step 4. h. Fetch the next approver in the chain of authority. i. j. Notes: 1. At step 3, you may eliminate duplicate action parameters, but if you do, you should keep track of the IDs of all rules requiring a given parameter, for use in populating each approver’s source field. When a handler populates an approver’s ame_util.approverRecord2 fields at steps 4.a, 4.c, 4.e, and 4.h, it should follow the instructions in this table: Value Make the next approver the current approver. Go to step 4d.

2.

Field

Building an ActionType 17

Field name, orig_system, orig_system_id

Value The handler fetches these values at steps 4.a, 4.e, and 4.h. The handler may start by fetching an approver’s wf_roles.name value, and then use ame_approver_type_pkg. getOrigSystemIdAndDisplayName to fetch the other fields’ values. Or, the handler may start by fetching the approver’s orig_system_id value (such as a per_all_people_f.person_id value), and then use ame_approver_type_pkg. getWfRolesNameAndDisplayName to fetch the other values. The handler calculates this value from data returned by ame_engine.getHandlerRules2 in step 1, depending on which rules require the approver. The value is ame_util.approvalApproverCategory if any of the rule usages requiring the approver is this value; otherwise the value is ame_util.fyiApproverCategory. For rule-generated approvers, the handler should set this value to ame_util.oamGenerated. For inserted approvers, the handler should set this value to ame_util.apiAuthorityInsertion. The handler should always set this value to ame_util.authorityApprover. The handler should call ame_engine.getHandlerApprovalStatus once per approver to fetch this value. The handler should call ame_engine.getHandlerActionTypeId once per handler cycle to fetch this value. The handler should calculate this value by setting it to once for the first chain it generates, and incrementing the value once for each iteration of the loop at step 4. The handler should call ame_engine.getHandlerOccurrence once per approver to fetch this value.

approver_category

api_insertion

authority

approval_status

action_type_id

group_or_chain_id

occurrence

Building an ActionType 18

Field source

Value For rule-generated approvers, the source value should be a list of the IDs of the rules requiring the approver, separated by ame_util.fieldDelimiter. In this case, you should use ame_util.appendRuleIdToSource to build a valid source value. For inserted approvers, the ame_engine. getHandlerCOAFirstApprover or ame_engine.getHandlerCOAInsertion procedure outputs the correct source value for each inserted approver. The handler should call ame_engine.getHandlerItemClassName once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerItemId once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerItemClassOrderNumber once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerItemOrderNumber once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerSublistOrderNum once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerActionTypeOrderNum once per handler cycle to fetch this value. The handler should call ame_engine. getActionTypeChainOrderMode once per handler cycle to fetch the chain-ordering mode of its action type. If the mode is ame_util.serialChainsMode, the group_or_chain_order_number should have the same value as the group_or_chain_id. If the mode is ame_util. parallelChainsMode, the group_or_chain_order_number should always be one.

item_class

item_id

item_class_order_number

item_order_number

sub_list_order_number

action_type_order_numb er

group_or_chain_order_n umber

Building an ActionType 19

Field member_order_number

Value The handler should call ame_engine.getActionTypeVotingRegime once per handler cycle to fetch the voting regime of its action type. If the regime is ame_util.consensusVoting or ame_util.firstApproverVoting, the member_order_number should always be one. If the regime is ame_util.serializedVoting, the member_order_number should be one for the first approver in each chain, and should increment at step 4.3. The handler should leave this field null (AME’s engine populates this field.)

approver_order_number

You can help make your handler code efficient by re-using a local ame_util.approverRecord2 variable for the current approver, and calling the functions that return a constant value for the handler’s cycle just once each at the start of the handler cycle, to populate the constant fields of the current-approver record. 3. If the handler only needs to generate one chain of authority, eliminate the loop at step 4, and simply do invidual steps contained 4 once.

Approver-Group-Handler Architecture
An approval-group handler translates required-attribute and actionparameter values into one or more pre-approval or post-approval approval groups, either for a given subordinate item, or for the header item. For each approver that the handler adds to the item’s approval list, the handler must populate all but one of the fields in the approver’s ame_util.approverRecord2. (AME’s engine calculates the value of the record’s approver_order_number field.) The handler procedure should implement the following pseudocode to generate the approval groups: 1. Call ame_engine.getHandlerRules to fetch the applicable rules’ IDs and action parameters (which are the IDs of the approval groupsthat the rules require), and the approver categories that the rule usages assign them. Call one of the engine’s attribute-value-fetching routines to fetch the values of any required attributes. Remove any duplicate approver-group IDs from the list of action parameters. Fetch the required groups’ order numbers and ordering modes by calling ame_engine.getApprovalGroupConfigs. (Note that this procedure sorts

2.

3.

4.

Building an ActionType 20

the group IDs in place by group order number first, then by group ID.) 5. For each required approval group, loop. a. Fetch the group’s membership by calling ame_engine.getRuntimeGroupMembers.

b. For each approver returned by getRuntimeGroupMembers, loop • Set the values of the fields of the approver’s ame_util.approverRecord2. • Call ame_engine.addApprover. Notes: 1. At step 3, you may eliminate duplicate action parameters, but if you do, you should preserve in your rule-ID list the IDs of all the applicable rules, for use in populating each approver’s source field. When a handler populates an approver’s ame_util.approverRecord2 fields at step 5b, it should follow the instructions in this table: Value The ame_engine.getRuntimeGroupMembers procedure returns all of these values. The handler calculates this value from data returned by ame_engine.getHandlerRules2 in step a, depending on which rules require the approver. The value is ame_util.approvalApproverCategory if any of the rule usages requiring the approver is this value; otherwise the value is ame_util.fyiApproverCategory. The handler should always set this value to ame_util.oamGenerated. The handler should set this value to ame_util.preApprover or ame_util.postApprover. The handler should call ame_engine.getHandlerApprovalStatus once per approver to fetch this value.

2.

Field name, orig_system, orig_system_id approver_category

api_insertion

authority

approval_status

Building an ActionType 21

Field action_type_id

Value The handler should call ame_engine.getHandlerActionTypeId once per handler cycle to fetch this value. The parameters returned by ame_engine.getHandlerRules at step 1 are approver-group IDs. The loop at step 5 iterates through the group IDs (typically after any duplicates have been removed). The handler should call ame_engine.getHandlerOccurrence once per approver to fetch this value. The source value should be a list of the IDs of the rules requiring the approver, separated by ame_util.fieldDelimiter. You should use ame_util.appendRuleIdToSource to build a valid source value. The handler should call ame_engine.getHandlerItemClassName once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerItemId once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerItemClassOrderNumber once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerItemOrderNumber once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerSublistOrderNum once per handler cycle to fetch this value. The handler should call ame_engine.getHandlerActionTypeOrderNum once per handler cycle to fetch this value.

group_or_chain_id

occurrence

source

item_class

item_id

item_class_order_number

item_order_number

sub_list_order_number

action_type_order_numb er

Building an ActionType 22

Field group_or_chain_order_n umber

Value The call to ame_engine.getApprovalGroupConfigs at step 4 fetches each group’s order number. The call to ame_engine.getApprovalGroupConfigs at step 4 fetches each group’s voting regime. If the regime is ame_util.consensusVoting or ame_util.firstApproverVoting, the member_order_number should always be one. If the regime is ame_util.serializedVoting, the member_order_number should be the index of the approver in the approverNamesOut output argument of ame_engine.getRuntimeGroupMembers. If the regime is ame_util.orderNumberVoting, the member_order_number should be the member order number in the approverOrderNumbersOut argument of ame_engine.getRuntimeGroupMembers. The handler should leave this field null (AME’s engine populates this field.)

member_order_number

approver_order_number

You can help make your handler code efficient by re-using a local ame_util.approverRecord2 variable for the current approver, and calling the functions that return a constant value for the handler’s cycle just once each at the start of the handler cycle, to populate the constant fields of the current-approver record.

List-Editing-Handler Architecture
AME seeds three list-editing handlers, one each to reduce an approver’s authority, extend it, and substitute one approver for another. The first two of these operations are for list-modification rules, the third is for substitution rules. The architectural feature these handlers share is, they all modify the approver list only when a target approver appears in an appropriate context in the list. Here is the basic algorithm: 1. Call ame_engine.getHandlerRules3 to fetch the list of applicable rules. Optionally sort the values returned by ame_engine.getHandlerRules3 to eliminate duplicates and leave the values in an order that is meaningful to your handler.

2.

Building an ActionType 23

3.

For each (remaining) row in the output variables of ame_engine.getHandlerRules3, loop. a. Call ame_engine.getHandlerLMApprovers to fetch the approvers that match the current list-modification condition.

b. For each row in the output variables of ame_engine.getHandlerLMApprovers, loop. c. Perform some operation on the approver list targeting the approver identified by the current approver.

Notes: 1. 2. Call ame_engine.substituteApprover to effect substitututions. Call ame_engine.truncateChain to truncate a chain of authority after a target approver. If your handler extends a chain of authority, it should populate the new approvers’ ame_util.approverRecord2 fields according to note 2 under “Authority-Handler Architecture” above. Substituted approvers should have the same ame_util.approverRecord2 field values as the approvers they replace. The ame_engine.substituteApprover sets all of the fields values; your handler code should not change any of them. A list-modification handler that removes approvers from the approver list should not change the ame_util.approverRecord2 fields of any remaining approvers.

3.

4.

5.

PL/SQL Exceptions
Every routine in your handler should include an exception block. The exception block should at least have a when-others exception handler. The last two statements in each exception handler for an unhandled exception should always be a call to ame_util.runtimeException, followed by a raise statement or raise_application_error call. In the latter case it is idiomatic in AME coding to have the enclosing routine declare the local variables errorCode integer; errorMessage ame_util.longestStringType and then begin your exception handler by setting these variables’ values. Then the last two statements in the exception handler can reference these variables, rather than their values. The following example illustrates both kinds of exception handlers: exception when jobLevelException then errorCode := -20001; errorMessage :=

Building an ActionType 24

ame_util.getMessage( applicationShortNameIn => 'PER', messageNameIn => AME_400448_AJHA_JOB_NOT_ASSD'); ame_util.runtimeException( packageNameIn => 'ame_absolute_job_level_handler', routineNameIn => 'getJobLevelAndSupervisor', exceptionNumberIn => errorCode, exceptionStringIn => errorMessage); raise_application_error(errorCode, errorMessage); when others then ame_util.runtimeException( packageNameIn => 'ame_absolute_job_level_handler', routineNameIn => 'getJobLevelAndSupervisor', exceptionNumberIn => sqlcode, exceptionStringIn => sqlerrm); raise;

Registering an Action Type
Once your handler is ready, you need to register it with AME using the actions tab. Note that this tab requires administrative or developer privileges. To create an action type, follow these steps: 1. 2. 3. Select the actions tab. Select the ‘Add Action Type’ button at the bottom of the list of actions. Select the appropriate rule type from the ‘Create an Action Type-Step 1’ form, and then select the ‘Create Action Type’ button. Enter and select the properties of the action type, and the current transaction type’s configuration for it, on the ‘Create an Action Type-Step 2’ form. If you select ‘yes’ on the ‘Dynamic Action Description’ radio button, you must enter a dynamic action-description query in the ‘Action-Description Query’ field below. Such queries can reference the bind variables :parameterOne and (for list-editing action types) :parameterTwo, which AME binds to an action’s parameter values. For example, select :parameterOne||' / '||:parameterTwo from dual might be a dynamic action description for a list-modification action type. (Note the absence of a semi-colon at the end of the query. Do not include a semi-colon.) When you have entered and selected your action type’s properties and configuration values for the current action type, select the ‘Create Action Type’ button. At this point the wizard creates the action type and takes you to the

4.

Building an ActionType 25

‘Create an Action’ form. You can use this form to create the first action for your action type. When you submit the form, the wizard takes you to the new action type’s editing form, where you can add more actions or change some of the action type’s properties and configuration values. See Chapter 5 of the implementation guide for additional information about an action type’s properties and configuration values.

Major changes in the Engine/ Handler Interface since R11i9
As discussed at the start of this chapter there has been some major changes to the way custom action type handlers are required to be coded. The conversion steps to move handlers developed on R11i9 and earlier and preceeding the patchset AME.A, that was released in early Dec 2005.

Step 1.

AME 11.5.9
The handler has 3 public routines which are called by the engine. They are: getFirstApprover(), getNextApprover() and hasFinalAuthourity() The handler returns at most one approver back to the engine. No special routines needed to define the handler context. The relevant information is passed in as arguments. The engine makes multiple calls to a handler in order to get all the approvers. The approver recovered is of type ame_util.approverRecord The approver list being maintained by the engine is stored in public tables which can be directly accessed by the handler.

AME 11.5.10 / AME.A
The handler has only one public routine which is called by the engine. It is: handler() The handler does not have any arguments being passed IN or OUT. Special callable engine routines are available to set handler context.

2. 3. 4. 5. 6.

7. 8. 9.

The engine calls the handler once. All approvers are processed by this one call. The approver record is of type ame_util.approverRecord2 The approver list being maintained by the engine is private and cannot be directly accessed by the handler. Special callable engine routines are defined to do this. The approver record is passed between No serialization of the approver record is necessary. the handler and the engine after serialization. The logic to identify the starting point The logic to identify the starting point approver is embedded partly in the approver is part of the handler code engine and partly in the handler. only. The logic to take into account COA The logic to take into account COA
Building an ActionType 26

10. 11.

insertions resides in the engine. The logic to identify surrogate approvers resides in the handler. The handler transaction state needs to be maintained in temporary tables/ global engine variables. The rules which require the approver to be part of the approver list are not accurately identified. All applicable rules are included in the source column of the approver record. The List Modification actions which truncates the approver list actually delete the approvers from the approver list.

12.

13.

insertions resides in the handler. The logic to identify surrogate approvers resides in the approver type object layer. Temporary tables/ global engine variables are not needed to maintain transaction state. This can be done by using private handler package variables. The rules which require the approver to be part of the approver list are accurately identified. Only rules which require the approver to be included in the approver list are mentioned in the source column of the approver record. The List Modification actions which truncates the approver list will either set the approvers approver_category to ame_util.fyiApproverCategory, if possible or will set the approvers approval_status to ame_util.suppressedStatus.

Environment to Migrate Custom Handler
The new custom handler code can be written and tested on an AME 11.5.10 instance only. Hence it is recommended

• • • • •

Upgrade a test instance to 11.5.10. Migrate/code the new custom handler on this test instance System test the new custom handler on this test instance Upgrade production instance to 11.5.10. Implement new custom handler on the production instance

Building an ActionType 27

3 Defining an Approver Type

Defining an Approver Type 29

Overview
An approver type is any Workflow Directory Services originating system that defines entities that can receive Workflow notifications requesting approval. For example, the HRMS application exports employees from its per_all_people_f table to the PER Directory Services originating system so an HR employee can be an approver in AME.

Approver Types in AME
For AME to use an approver type, it must be be registered with AME (not merely Workflow Directory Services). Currently there is no user interface to register an approver type. Rather, one must execute a set of SQL statements that insert rows into the ame_approver_types and ame_approver_type_usages tables, and you must customize several runtime routines in AME code. (AME enhancement request 32767685 requests eliminating the need to customize AME code when adding an approver type.) If you need to use an approver type that AME does not yet seed, we strongly encourage you to request that AME development release a patch supporting the approver type, rather than registering it yourself. Note: Unless AME development provides support for an approver type in this fashion, you will have to modify an AME PL/SQL package each time you patch AME. Oracle Support and AME development do not support custom approver types other than through best effort.

Registering an Approver Type
Registering an approver type takes four steps: 1. 2. 3. 4. Code a PL/SQL procedure that AME users can invoke to query for approvers of the new type. Insert a row into ame_approver_types for the approver type. Identify the action types that can use the new approver type. For each such action type, insert a row into ame_approver_type_usages. Update certain routines in ame_approver_type_pkg that AME uses at runtime.

The rest of this chapter explains how to perform each of these steps.

Coding an Approver-Query Procedure
AME’s user interface includes an approver-query wizard. AME uses the wizard in various contexts where an end user must identify an approver, for example while populating an approval group or creating a list-modification condition. Each approver type registered with AME must provide an

Defining an Approver Type 30

approver-query procedure that the approver-query wizard can invoke. The wizard can prompt end users to provide up to five query criteria (first name, last name, etc.), which the wizard passes to the query procedure.

Procedure Signature Procedure Name
The name of your approver-query procedure should have the following form: [approverType]ApproverQuery where approverType suggests the approver type. For example, ‘PER’ is the originating system for HR employees, so that the approver type’s approver-query procedure is ame_approver_type_pkg.perApproverQuery.

Argument List
Your approver-query procedure’s signature should be: procedure approverTypeApproverQuery( criterion1In in varchar2 default null, criterion2In in varchar2 default null, criterion3In in varchar2 default null, criterion4In in varchar2 default null, criterion5In in varchar2 default null, excludeListCountIn in integer, approverNamesOut out nocopy varchar2, approverDescriptionsOut out nocopy varchar2); At run time, the first five arguments contain the query criteria that the end user entered or selected on the approver-query form of the approver-query wizard. The integer excludeListCountIn sets appropriately the the number of rows that the procedure may output, to account for a set of excluded approvers known to the approver-query wizard at run time. The two output arguments identify approvers that match the query criteria.

Functionality
When you register your approver type with AME, you provide a set of query criteria that the approver-query wizard should present when an end user queries for approvers of your approver type. The end user may leave any or all of these blank, so that your procedure may receive null values in any combination of its criterion[n]In arguments. The simplest way to accommodate such null query criteria is to have your cursor define a cursor that encapsulates your approver query. The cursor’s argument list should match exactly the input argument list of the query procedure. The cursor’s where clause should accommodate null query criteria like this: where (criterion1In is null or

Defining an Approver Type 31

some_column like ‘%’ || criterion1In || ‘%’) and (criterion2In is null or some_column like ‘%’ || criterion2In || ‘%’) and . . . Your procedure should limit the number of rows it returns by including the following line in its main cursor’s where clause: rownum < 52 + rowsToExcludeIn The approver-query wizard checks your procedure’s output values for a set of approvers to exclude. This set has rowsToExcludeIn members. So worst case, the set of approvers that the approver-query wizard presents to the end user, after filtering out the approvers to exclude, should have 50 approvers in it. The value 52 lets the cursor return one row too many. Your code should check for this condition and raise an exception, as follows (assuming the procedure fetches the cursor into a local approverNames variable): if(approverNames.count - rowsToExcludeIn > 50) then raise ame_util.tooManyApproversException; approverNamesOut := null; approverDescriptionsOut := null; return; end if; If the cursor does not select too many rows, your procedure should check that it returns at least one: if(approverNames.count = 0) then raise ame_util.zeroApproversException; approverNamesOut := null; approverDescriptionsOut := null; return; end if; If the cursor selects an apprpriate number of rows, your procedure should serialize the lists of approver names and descriptions selected by the query, and return the serialized lists in the procedure’s output arguments, like this: ame_util.serializeApprovers( approverNamesIn => approverNames, approverDescriptionsIn => approverDescriptions, maxOutputLengthIn => ame_util.longestStringTypeLength, approverNamesOut => approverNamesOut, approverDescriptionsOut => approverDescriptionsOut);

Inserting a Row into ame_approver_types
Use the following insert statement to register the new approver type with AME: insert into ame_approver_types( approver_type_id, orig_system, query_variable_1_label, query_variable_2_label,

Defining an Approver Type 32

query_variable_3_label, query_variable_4_label, query_variable_5_label, variable_1_lov_query, variable_2_lov_query, variable_3_lov_query, variable_4_lov_query, variable_5_lov_query, query_procedure, created_by, creation_date, last_updated_by, last_update_date, last_update_login, start_date, end_date) values( approverTypeId, origSystem, queryVariable1Label, queryVariable2Label, queryVariable3Label, queryVariable4Label, queryVariable5Label, variable1LovQuery, variable2LovQuery, variable3LovQuery, variable4LovQuery, variable5LovQuery, queryProcedure, createdBy, creationDate, lastUpdatedBy, lastUpdateDate, lastUpdateLogin, startDate, endDate); Below are descriptions of the values you must supply in the above insert statement.

approverTypeId
To determine the appropriate approverTypeId value, execute the following query: select 1 + max(approver_type_id) from ame_approver_types;

origSystem
The origSystem value should be the wf_roles.orig_system value that approvers of the new approver type have. You can view all of the available orig_system values by executing the following query: select distinct orig_system from wf_directory_partitions;

Defining an Approver Type 33

queryVariable[n]Label
If you want the approver-query wizard to present k query criteria for your approver type, you must supply user-friendly labels for these criteria in the first k queryVariable[n]Label columns, and null in the remaining 5 – k queryVariable[n]Label columns. Each label may be up to 50 bytes long.

variable[n]LovQuery
If you want the ith query criterion to be a select list, variable[i]LovQuery should be an SQL query that returns the values you want to appear in the select list. The query may be up to 4000 bytes long, and should not include a terminating semi-colon. If variable[I]LovQuery is null, the ith query criterion will be a textentry input.

queryProcedure
This value should be the name of your query procedure. If the procedure resides in a package, prepend the package name and a period to the procedure’s name.

createdBy
This value should be the fnd_user.user_id value of the user that inserts the row.

creationDate
Use sysdate for this value.

lastUpdatedBy
This value should be the same as the createdBy value.

lastUpdateDate
Use sysdate for this value.

lastUpdateLogin
This value should be the same as the createdBy value.

startDate
Use sysdate for this value.

endDate
The endDate value should be null.

Defining an Approver Type 34

Identifying the Action Types that can use the new Approver Type
Once you have inserted a row into ame_approver_types for your approver type, you must tell AME which custom action types may use the approver type. Do not include seeded action types in your list. For each action type in your list, follow these steps: 1. 2. 3. 4. Select the action tab. Select the action type on the list of action types. Select the ‘Add Approver Types’ button at the bottom of the ‘Edit Action Type’ form. Select the new approver type from the ‘Approver Type’ select list, and then select the ‘Add’ button.

Updating ame_approver_type_pkg Runtime Routines
There are three runtime ame_approver_type_pkg routines that you must modify to accommodate your new approver type. Be very careful not to alter the existing code, and remember that you will have to repeat your additions each time you install an AME patch. AME’s engine calls these procedures, so your code should be as efficient as possible.

isASubordinate
The function ame_approver_type_pkg.isASubordinate returns true if the approver possibleSubordApproverIn is a subordinate of the approver approverIn (presumably within a common approver hierarchy), and false otherwise. The function returns false by default. If your approver type does not represent an organizational hierarchy, you do not need to modify the procedure (because in this case no subordination relations exist among your approver type’s approvers). Otherwise, you must modify the procedure so that if the two input approvers belong to your approver type, the procedure checks whether the one is a subordinate of the other.

getSuperior
The procedure ame_approver_type_pkg.getSuperior returns in superiorOut the superior of the input approver approverIn, raising the procedure’s noSurrogateException exception if no superior exists. The procedure raises the exception by default, so if your approver type does not represent an organizational hierarchy, you do not need to modify the procedure (because in this case no subordination relations exist among your approver type’s approvers). Otherwise, you must modify the procedure so that when the input approver belongs to your approver type, the procedure returns the input approver’s superior.

getSurrogate
The ame_approver_type_pkg.getSurrogate procedure outputs the surrogate approver that AME should substitute for the unresponsive approver identified by the procedure’s input arguments, raising the local exception

Defining an Approver Type 35

noSurrogateException if no surrogate exists. The procedure raises the exception by default, so if your approver type does not admit surrogateapprover functionality, you do not need to modify the procedure. Otherwise, you must modify the procedure so that when the input approver belongs to your approver type, the procedure returns the input approver’s surrogate.

Defining an Approver Type 36

4 Defining an Item Class

Defining an Item Class 37

Overview
This chapter explains when and how to define an item class. You must have the AME Developer responsibility to define an item class. See Chapter 8 of the Oracle Approvals Management Implementation Guide for more information about item classes.

When to Define an Item Class
AME currently seeds item classes for a transaction’s header, line items, cost centers, and project codes. Your originating application may recognize other entities having a many-to-one relation to a transaction. For example, your application may divide a transaction’s cost among several entities of the same kind. If you want to enable any of your transaction types to define attributes for these entities, or to generate one approver list per entity, you should define an AME item class for the entity.

How to Define an Item Class
To define an item class, follow these steps: 1. 2. 3. 4. 5. 6. 7. Select the admin tab. Select ‘transaction-type administration’, and then the ‘Continue’ button. Select ‘Maintain item classes’, and then the ‘Continue’ button. Select the ‘Add Item Class’ button. Select the ‘Create New Item Class’ button on the ‘Add an Item Class— Step 1’ form. Enter the item class’ name on the ‘Add an Item Class—Step 2’ form. Enter the properties of the current transaction type’s usage of the new item class on the ‘Add an Item Class—Step 3’ form, and then select the ‘Continue’ button to create the item class.

The item class will now appear on the list of item classes you reached at step 3 above.

Defining an Item Class 38

5 Integrating AME with Workflow

Integrating AME with Workflow 39

Overview
AME’s basic design imperative is to locate all approvals–related logic in a single module, rather than having each application provide its own approvals logic. This chapter explains how you can integrate AME into your application’s Workflow processes.

Notifications
Information to Include in Notifications
AME’s APIs provide a variety of information you can include in the notifications you send the approvers in a transaction’s approver list: • • • • • whether the notification should be informational or should request the approver’s approval which subordinate items require the approver’s attention which approval rules required that the approver receive the notification which productions appy to the approver which productions apply to the transaction.

(See Appendix A for details.) Your application should interpret the productions before presenting them to an end user in a notification.

Encoding Responses to Notifications Requesting Approval
Appendix B’s description of the approval_status field of the ame_util.approverRecord2 data type lists and describes the ame_util constants your code may use to represent an approver’s response to a notification requesting approval. If you try to pass any other approval_status value to AME’s APIs, AME will raise an exception.

The Basic Algorithm
Here is the basic algorithm that an application should implement in its Workflow processes, to let AME manage the approval processes of a transaction type that the application owns. 1. Call one of the ame_api2.getNextApprovers[n] procedures to get the wf_role.name values of any approvers that currently require notification, and to determine whether the transaction’s approval process is complete. If ame_api2.getNextApprovers[n] outputs the value
Integrating AME with Workflow 40

2.

ame_util.booleanTrue in approvalProcessCompleteYNOut, stop (the transaction is approved). 3. Notify any approvers output by ame_api2.getNextApprovers[n] at step two above, and wait for a response from each approver who must approve. When an approver who must approve responds, communicate the response to AME by calling ame_api2.updateApprovalStatus or ame_api2.updateApprovalStatus2, and go to step one above.

4.

Telling AME that an Approver has been Notified
Usually you should pass ame_util.booleanTrue in flagApproversAsNotifiedIn. Otherwise you must update each notified approver’s status to ame_util.notifiedStatus upon notifying the approver at step three.

Exception Handling
AME complies with the Workflow exception-handling model by raising all runtime exceptions to the originating application’s Workflow processes, without issuing a rollback. To clear an exception from a transaction’s approval-process state in AME, you need to pass the status ame_util.clearExceptionsStatus at step four in the basic algorithm. Note that this only clears the transaction’s exception status within AME. It does not affect the transaction’s status in its Workflow process.

Modifications to the Basic Algorithm
There are several ways to enhance the basic algorithm. This section describes some of them. To learn about other ways to enhance the basic algorithm, review the API specifications in Appendix A.

Handling Rejections
The basic algorithm does not terminate if one of the approvers rejects the transaction. In the event of a rejection, you may wish to stop at step four to make sure the algorithm terminates.

Inserting Approvers into the Default Approver List
In the basic algorithm, your application does not determine the membership of a transaction’s approver list. It leaves all such decisions to AME. If your application needs to let an end user insert approvers into the approver list that AME generates for a given transaction, modify the basic algorithm as follows: 1. 2. Call ame_api2.getAllApprovers[n] to get a transaction’s default approver list. Display the approver list to the end user. Include suppressed and

Integrating AME with Workflow 41

repeated approvers, but flag them as such (perhaps by greying out their names). 3. 4. 5. 6. 7. 8. 9. Prompt the user to choose a location (index) in the approver list at which to perform the insertion, or to stop. If the user chooses to stop, stop. Call ame_api3.getAvailableInsertions for that location. Display the resulting list of available insertions. Prompt the user to choose one of the available insertions. Prompt the user to query for an approver to insert. Call ame_api2.validateApprover to validate the approver chosen at step seven above.

10. If the approver is invalid, go to step 8 above. 11. If the insertion type is ame_util.firstAuthority, call ame_api2.setFirstAuthorityApprover to perform the insertion. Otherwise, call ame_api3.insertApprover to perform the insertion.

Suppressing Approvers in the Default Approver List
If your application needs to let an end user suppress approvers in the approver list that AME generates for a given transaction, modify the basic algorithm as follows: 1. 2. Call ame_api2.getAllApprovers[n] to get a transaction’s default approver list. Display the approver list to the end user. (You don’t need to include suppressed or repeated approvers, but you should track internally the indexes of the approvers you display.) Prompt the user to choose an approver to suppress, or to stop. If the user chooses to stop, stop. Call ame_api3.suppressApprover to suppress the approver. Go to step one.

3. 4. 5. 6.

Accounting for Unresponsive Approvers
You may wish to account for notification timeouts in your application’s Workflow process. To do so, modify step three of the basic algorithm by timing each notification. Modify step four to catch timeouts as well as responses, and to pass ame_util.noResponseStatus to ame_api2.updateApprovalStatus or ame_api2.updateApprovalStatus2 in the event of an unresponsive approver.

Integrating AME with Workflow 42

Forcing an Approver who has Already Approved an Item to Approve it Again
If you want to force a single approver to re-approve an item they have already approved, update the approver’s status to null.

Frequently Asked Questions
What does final (signing) authority mean in AME?
The basic algorithm only uses Workflow to send and receive notifications. It does not use Workflow to determine which approver has final or signing authority (in any sense). AME determines final authority internally. Your application’s Workflow process knows that a transaction has been approved when AME so indicates (at step two of the basic algorithm). AME can generate an approver list for each item in a transaction. Each approver list can have several chains of authority. Each chain of authority has at least one approver with final (signing) authority (arriving at such an approver is how AME decides to end the chain). So in general, no single approver has final authority for the overall approver list. Furthermore, AME’s parallel-approvals functionality makes it possible for an approver having signing authority to be notified along with previous approvers in the chain of authority. So the temporal order of notifications does not generally reveal which approver is a final approver.

Why call AME each time an approver responds to a notification requesting approval?
Calling ame_api2.getNextApprovers[n] each time an approver responds to a notification requesting is natural in several ways. 1. It accounts for the possibility that a transaction’s approver list will change during the transaction’s approval process. Several phenomena can cause the approver list to change: • • • • • • • An attribute value can change. A currency conversion rate can change. An organizational hierarchy can change. An approval group can change. The rules that apply to a transaction can change. The relevant transaction type’s configuration-variable values can change. The relevant transaction type’s mandatory-attribute values can change.

Integrating AME with Workflow 43

2.

An approver may be unresponsive long enough for your application to tell AME that the approver was unresponsive, in which case AME will add the approver’s surrogate to the approver list. An approver may reject some but not all items, and AME may stop those items’ approval processes while continuing the approval processes of remaining items. It checks for more approvers to notify at the exact moment when their existence becomes likely. It is efficient with respect to performance overhead in the sense that the least upper bound on the number of different approver_order_number values is the number of approvers, and in the typical scenario (where each approver approves), the number of approver responses is the same as the number of approvers.

3.

4. 5.

Does AME do transaction management?
AME does not perform any commits or rollbacks while responding to an API call originating within a workflow. (Where necessary, AME determines whether it has been called from within a workflow by checking the value of the useWorkflow configuration variable.) If the calling application does not use Workflow, the only transaction management that AME performs at runtime is to commit inserts into its exception log within autonomous transactions. Thus, if an application integrates AME without using Workflow, it must commit or rollback AME’s work within the code that calls AME’s APIs.

Sample Workflow
This section explains how to implement the basic algorithm in Workflow.

Overview
To implement the basic algorithm in Workflow, you need to do three things: 1. 2. Create a Workflow item type to manage your transaction type’s approval processes. Create the following things within your item type: • • • Create an item attribute of type text (say ‘Approver’) to contain notification performer data. Create an item attribute of type text (say ‘Master Item Key’) to contain the master process’ item-key value. Create a lookup type (say ‘Approval Status’), and add to it the approval_status values that your item type will use. (See ‘Encoding Responses to Notifications

Integrating AME with Workflow 44

Requesting Approval’ above.) • Create a message of type response (say ‘Response Message’) by attaching the result to its result tab, with the display name ‘Result’, the description ‘Response Result’, and the lookup type ‘Approval Status’.

3. 4.

Create two processes, one each for master and detail. (See below for details.) Create a PL/SQL package whose procedures call AME’s API routines on behalf of your Workflow.

Workflow Processes
The master process essentially does the following: 1. 2. 3. 4. Fetch the next approvers to notify (if any) using ame_api2.getNextApprovers4. For each approver fetched, spawn a child process. Wait for a response from at least one child process to continue. When a child process receives a response, process the response and go to step one above.

The child process essentially does the following: 1. 2. 3. Send a notification to the approver. If the notification requests a response, wait for a response from the approver. When the response arrives, so indicate to the master process.

The Master Process
The master process has four nodes. Here are descriptions of each node:

Start Node
The first node is a standard function activity that simply marks the start of the process. Function WF_STANDARD.NOOP

Result Type none Required yes none

Prerequisite Activities

Integrating AME with Workflow 45

Item Attributes Set by Function none Item Attributes Retrieved by Function none

Is-Approval-Complete Node
The second node fetches the next set of approvers (if any) by calling your PL/SQL package’s wrapper procedure for ame_api2.getNextApprovers4. The node also checks whether the transaction’s approval process is complete. If the process is incomplete, the node creates and starts a child process for each approver requiring notification. Function <package_name>.<procedure_name>

Result Type yes/no (determines whether the transaction is completed or not) Required yes

Prerequisite Activities none (initially none, subsequently waits for the response from the notified approver at the third node) Item Attributes Set by Function none Item Attributes Retrieved by Function none

The following pseudocode describes this node’s logic: 1. 2. 3. Call your ame_api2.getNextApprovers4 wrapper procedure to get the next set of approvers to notify (if any). If approvalProcessCompleteYN = ame_util.booleanTrue, end the process. Loop through the approvers returned at step one. Follow these steps for each approver: • A - Create a child processes by calling wf_engine.createProcess( itemType => <itemType>, itemKey => <childItemKey>, process => <childProcessName>); • B - Set the item Approver attribute to the approver’s wf_roles.name value by calling wf_engine.SetItemAttrText( itemType => <itemType>,

Integrating AME with Workflow 46

itemKey => <childItemKey>, aName => ‘Approver’, aValue => <approver’s wf_roles.name>); C - Set the item Master Item Key attribute to the master item’s item key by calling wf_engine.SetItemAttrText( itemType => <itemType>, itemKey => <childItemKey>, aName => ‘Master Item Key’, aValue => <itemKey>); D - Start the child processes by calling wf_engine.StartProcess( <itemType>, <childItemKey>); Each child process’ item key must be unique.

Wait-for-Approver-Response Node
The third node is a customized standard function activity that waits for a response from the child processes. Function Result Type Required yes third node of child process (Get WF_STANDARD.BLOCK none

Prerequisite Activities Approver Response)

Item Attributes Set by Function none Item Attributes Retrieved by Function none

End Node
This is a standard function activity that marks the end of the process. Function Result Type Required yes
Integrating AME with Workflow 47

WF_STANDARD.BLOCK none

Prerequisite Activities

node two, if result type = Y

Item Attributes Set by Function none Item Attributes Retrieved by Function none

The Child Process Start Node
The start node is a standard function activity that marks the start of the process. Function Result Type Required yes none WF_STANDARD.NOOP none

Prerequisite Activities

Item Attributes Set by Function none Item Attributes Retrieved by Function none

Send-Notification Node
The send-notification node is a standard notification activity that notifies the approver. Function Message Result Type Required yes none none response message Approval Status

Prerequisite Activities

Item Attributes Set by Function Set the performer attribute to the approver’s wf_roles.name value. Item Attributes Retrieved by Function none

Get-Approver-Response Node
This activity node should call a procedure in your PL/SQL package that gets the approver’s response, passes it to AME, and then completes the master process’ waiting activity (its Wait for Approver Response node). Function Result Type <package_name>.<procedure_name> none

Integrating AME with Workflow 48

Required

yes none

Prerequisite Activities

Item Attributes Set by Function none Item Attributes Retrieved by Function none

The following pseudocode describes this node’s logic: 1. Get approver attribute’s value by calling wf_engine.GetItemAttrText( itemType => <itemType>, itemKey => <childItemKey>, aName => ‘Approver’); 2. 3. Get the approver’s response notification response for the above approver Update the approver’s status calling ame_api2.updateApprovalStatus or ame_api2.updateApprovalStatus2. 4. Communicate the response to the master process’ waiting node by setting masterItemKey := wf_engine.GetItemAttrText( itemType => <itemType>, itemKey => <childItemKey>, aName => 'Master Item Key'); and then calling wf_engine.CompleteActivity( itemType => <itemType>, itemKey => <masterItemKey>, activity => <Wait for Approver Response>, result => null);

End Node
This is a standard function activity that marks the end of the process.

Integrating AME with Workflow 49

Function Result Type Required

WF_STANDARD.BLOCK none yes none

Prerequisite Activities

Item Attributes Set by Function none Item Attributes Retrieved by Function none

Integrating AME with Workflow 50

Integrating AME with Workflow 51

Appendix A API Functional Specifications

Appendix A API Functional Specifications 53

Overview
AME provides three runtime API packages. The ame_api2 package contains routines that a typical workflow uses to process a typical approval process, while ame_api3 contains ancillary routines. The ame_api package is available for backwards compatibility only. If you are integrating AME into your product for the first time, use ame_api2 and ame_api3 only. This chapter explains how to call AME API routines.

Calling AME API Routines
Arguments
Many of AME’s API routines share certain arguments. Here are brief descriptions of each. applicationIdIn is the fnd_application.application_id value of the originating application calling the AME API routine. transactionTypeIn is a string up to 50 bytes long. It distinguishes one transaction type from another, within a given originating application. It can be null, but you must always pass its value explicitly. transactionIdIn is a string up to 50 bytes long. It identifies a transaction within a transaction type. Its value must not contain white-space characters, and must not be the character representation of a negative integer. approverIn is an ame_util.approverRecord2 (or an ame_util.approverRecord in ame_api) that represents an approver. For ame_api2 and ame_api3, the above four arguments always appear at the top of a procedure’s input in the above order, when they appear at all.

Passing Arguments by Name
Always pass arguments by name to AME’s APIs. This lets AME development add default-null arguments to an API routine without breaking pre-existing code that references the routine.

Approver Comparisons
When AME must determine whether two ame_util.approverRecord2 records represent the same occurrence of an approver in a given transaction’s approver list, it compares the following fields: • item_class

Appendix A API Functional Specifications 54

• • • • •

item_id name action_type_id group_or_chain_id occurrence.

The two records represent the same occurrence of the approver if and only if all of these fields have the same values.

ame_api2
validateApprover Syntax
function validateApprover( approverIn in ame_util.approverRecord2) return boolean;

Description
The validateApprover function returns true if the approver represented by approverIn has a current wf_roles entry, otherwise returns false. Use this API to check whether an ame_util.approverRecord2 that your application generates is valid, especially before passing an ame_util.approverRecord2 to an AME API routine. (AME always validates approvers before returning them via its APIs, so your code need not do so)

clearAllApprovals Syntax
procedure clearAllApprovals( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2);

Description
The clearAllApprovals procedure clears a transaction’s approvalprocess state. Restores the default approver list (removing approver insertions, suppressions, forwardings, etc.). Use this API to restart a transaction’s approval process from scratch, undoing any operations that have already modified the approval process.

Appendix A API Functional Specifications 55

getAdminApprover Syntax
procedure getAdminApprover( applicationIdIn in number default null, transactionTypeIn in varchar2, adminApproverOut out nocopy ame_util.approverRecord2);

Description
The getAdminApprover procedure outputs in adminApproverOut an ame_util.approverRecord2 representing the input transaction type’s administrative approver. An originating application may wish to notify this approver when AME raises an exception.

getAllApprovers1 Syntax
procedure getAllApprovers1( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList);

Description
The getAllApprovers1 procedure Outputs in approversOut a transaction’s current approver list, including both rule– generated and inserted approvers. The approvers’ indexes in approversOut are consecutive ascending integers starting at one. The order induced by the indexes is consistent with the ordering inducd by the approvers’ approver_order_number values (which AME’s parallel-approval-process functionality generates). The approvers’ approval_status values reflect the approvers’ latest responses to requests for approvals, assuming the originating application has communicated such responses to AME via ame_api2.updateApprovalStatus or ame_api2.updateApprovalStatus2. If approvalProcessCompleteYNOut is ame_util.booleanTrue, the transaction’s approval process is complete; otherwise it is incomplete. If an approver’s item_id value is null, several items require the approver. If such an approver is at index i in approversOut, and itemIndexesOut(j) = i, then itemIdsOut(j) is the ID of an item requiring the approver, itemClassesOut(i) is the item’s item class, and itemSourcesOut(j) is the source field indicating which rules required the approver for the same item.

Appendix A API Functional Specifications 56

(There will be at least two such entries in itemIndexesOut, itemIdsOut, itemClassesOut, and itemSourcesOut, for an approver in approversOut required by multiple items.) Use this API to fetch and display the entire approver list, either for information or to prompt for approver insertions or suppresions. Do not use getAllApprovers1 by calling it, storing its output approver list, and then iterating through that list in your application. Doing so would risk inaccuracies in the approver list introduced by changes in transaction values, organizational structures, approval rules, etc.

GetAllApprovers2 Syntax
procedure getAllApprovers2( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList, productionIndexesOut out nocopy ame_util.idList, variableNamesOut out nocopy ame_util.stringList, variableValuesOut out nocopy ame_util.stringList);

Description
The getAllApprovers2 procedure has the same functionality as getAllApprovers1, but it also returns per-approver productions stored in variableNamesOut and variableValuesOut. Several productions can be assigned a single approver, so productionIndexesOut contains for each production the index of the approver in approversOut to which the production is assigned. That is, if productionIndexesOut(i) = j, then the production in variableNamesOut(i) and variableValuesOut(i) is assigned to approversOut(j). Use getAllApprovers2 as you would getAllApprovers1, when you need to display perapprover productions with the approvers. See also ame_api2.getAllApprovers1.

getAllApprovers3 Syntax
procedure getAllApprovers3( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList,

Appendix A API Functional Specifications 57

itemSourcesOut out nocopy ame_util.longStringList, productionIndexesOut out nocopy ame_util.idList, variableNamesOut out nocopy ame_util.stringList, variableValuesOut out nocopy ame_util.stringList, transVariableNamesOut out nocopy ame_util.stringList, transVariableValuesOut out nocopy ame_util.stringList);

Description
The getAllApprovers3 procedure has the same functionality as getAllApprovers2, but it also returns per-transaction productions. Use getAllApprovers3 as you would getAllApprovers2, when you need to display per-transaction productions as well as the approver list. See also ame_api2.getAllApprovers1 and ame_api2.getAllApprovers2.

getAllApprovers4 Syntax
procedure getAllApprovers4( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopyame_util.longStringList, ruleIndexesOut out nocopy ame_util.idList, sourceTypesOut out nocopy ame_util.stringList, ruleIdsOut out nocopy ame_util.idList);

Description
The getAllApprovers4 procedure has the same functionality as getAllApprovers1, but it also classifies the approvers in approversOut according to the reasons for their occurrence in the approver list. When one or more rules require an approver, ruleIdsOut identifies the rules. More particularly: every approver in approversOut has at least one row in ruleIndexesOut, sourceTypesOut and ruleIdsOut. If ruleIndexesOut(i) = j, then the values in sourceTypesOut(i) and ruleIdsOut(i) pertain to the approver in approversOut(j). Every approver in approversOut has only one source value, no matter how many rules required the approver. That is, if ruleIndexesOut(i1) = j and ruleIndexesOut(i2) = j for i1 ¹ i2, sourceTypesOut(i1) = sourceTypesOut(i2). Some source values indicate that an approver is not required by any rules, but is present for other reasons. In such cases, if the approver is at index i, then if sourceTypesOut(j) = i, then ruleIdsOut(j) = null. Use getAllApprovers4 when you need to display the approver list, along with the rules requiring each approver. See also ame_api2.getAllApprovers1. Note that getAllApprovers4

Appendix A API Functional Specifications 58

requires significantly more performance overhead than some of its sibling getAllApprovers[n] procedures.

getAllApprovers5 Syntax
procedure getAllApprovers5( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList, ruleIndexesOut out nocopy ame_util.idList, sourceTypesOut out nocopy ame_util.stringList, ruleDescriptionsOut out nocopy ame_util.stringList);

Description
The getAllApprovers5 procedure has the same functionality as getAllApprovers4, but it returns rule descriptions rather than rule IDs. See also ame_api2.getAllApprovers4.

getAllApprovers6 Syntax
procedure getAllApprovers6( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList, ruleIndexesOut out nocopy ame_util.idList, sourceTypesOut out nocopy ame_util.stringList, ruleIdsOut out nocopy ame_util.idList, ruleDescriptionsOut out nocopy ame_util.stringList);

Description
The getAllApprovers6 procedure has the same functionality as getAllApprovers4, but it returns both rule IDs and rule descriptions. See also ame_api2.getAllApprovers4.

Appendix A API Functional Specifications 59

getAllApprovers7 Syntax
procedure getAllApprovers7( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2);

Description
The getAllApprovers7 procedure has the same functionality as getAllApprovers1, but omitting the per-item outputs. This is the lowest-overhead getAllApprovers[n] procedure. See also ame_api2.getAllApprovers1.

getAllItemApprovers Syntax
procedure getAllItemApprovers1( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, itemClassIdIn in number, itemIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut outnocopy ame_util.approversTable2);

Description
The getAllItemApprovers1 procedure has the same functionality as getAllApprovers1, but for the single item with ID itemIdIn of the item class with the ID itemClassIdIn. See also ame_api2.getAllApprovers1.

getAllItemApprovers2 Syntax
procedure getAllItemApprovers2( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, itemClassNameIn in varchar2, itemIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2);

Description
The getAllItemApprovers2 procedure has the same functionality as getAllItemApprovers1, but it identifies the input item class by name in itemClassNameIn. See also ame_api2.getAllApprovers1

Appendix A API Functional Specifications 60

and ame_api2.getAllItemApprovers1.

getAndRecordAllApprovers Syntax
procedure getAndRecordAllApprovers( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList);

Description
The getAndRecordAllApprovers procedure has the same functionality as getAllApprovers1, but it also updates the state of the transaction’s approval process in AME (in particular accounting for any approver insertions or suppressions made via the API since the last AME engine cycle). You can call this API to make sure AME has accounted for an approver insertion or suppression before calling ame_api3.getOldApprovers. Otherwise, calling getAndRecordAllApprovers is generally not necessary. See also ame_api2.getAllApprovers1.

getItemStatus1 Syntax
procedure getItemStatus1( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, itemClassIdIn in integer, itemIdIn in varchar2, approvalProcessCompleteYNOut out varchar2);

Description
The getItemStatus1 procedure outputs the status of the approval process of the item identified by itemIdIn of the item class identified by itemClassIdIn for the input transaction. If approvalProcessCompleteYNOut is ame_util.booleanTrue, the item has been approved; otherwise the item’s approval process is incomplete.

getItemStatus2 Syntax
procedure getItemStatus2( applicationIdIn in number, transactionTypeIn in varchar2,

Appendix A API Functional Specifications 61

transactionIdIn in varchar2, itemClassNameIn in varchar2, itemIdIn in varchar2, approvalProcessCompleteYNOut out varchar2);

Description
The getItemStatus2 procedure outputs the status of the approval process of the item identified by itemIdIn for the item class identified by its name in itemClassNameIn. See also ame_api2.getItemStatus1.

getItemStatuses Syntax
procedure getItemStatuses( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, itemClassNamesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, approvalProcessesCompleteYNOut out nocopy ame_util.charList);

Description
The getItemStatuses procedure outputs the statuses of the approval processes of the input transaction’s items. If approvalProcessesCompleteYNOut(i) is ame_util.booleanTrue, the item with ID itemIdsOut(i) of the item class itemClassNamesOut(i) has been approved; otherwise the item’s approval process is incomplete.

getNextApprovers1 Syntax
procedure getNextApprovers1( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, flagApproversAsNotifiedIn in varchar2 default ame_util.booleanTrue, approvalProcessCompleteYNOut out varchar2, nextApproversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList)

Description
The getNextApprovers1 procedure outputs in nextApproversOut the approvers requiring notification for the current stage of the input transaction’s approval process. Once

Appendix A API Functional Specifications 62

an originating application updates an approver’s status to ame_util.notifiedStatus, getNextApprovers1 excludes the approver from nextApproversOut. An originating application can update an approver’s status to ame_util.notifiedStatus by passing ame_util.booleanTrue as flagApproversAsNotifiedIn to a call to getNextApprovers1 that includes the approver in nextApproversOut. Or the originating application can pass ame_util.booleanFalse in flagApproversAsNotifiedIn, and instead call updateApprovalStatus or updateApprovalStatus2 to update the approver’s status independently of a call to getNextApprovers. When getNextApprovers1 outputs ame_util.booleanTrue in approvalProcessCompleteYNOut, the input transaction’s approval process is complete. Until then, the approval process is incomplete, even if nextApproversOut.count is zero. (See getAllApprovers1 above for an explanation of itemIndexesOut, itemClassesOut, itemIdsOut, and itemSourcesOut.) Use getNextApprovers1 to iterate through a transaction’s approval process one stage at a time. See also ame_api2.getAllApprovers1.

getNextApprovers2 Syntax
procedure getNextApprovers2( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, flagApproversAsNotifiedIn in varchar2 default ame_util.booleanTrue, approvalProcessCompleteYNOut out varchar2, nextApproversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList, productionIndexesOut out nocopy ame_util.idList, variableNamesOut out nocopy ame_util.stringList, variableValuesOut out nocopy ame_util.stringList);

Description
The getNextApprovers2 procedure has the same functionality as as getNextApprovers1, but it also returns per-approver productions. Use getNextApprovers2 to iterate through a transaction’s approval process one stage at a time when your application enables per-approver productions, for example to track per-approver eSignature requirements. See also ame_api2.getAllApprovers2 and ame_api2.getNextApprovers1.

getNextApprovers3 Syntax
procedure getNextApprovers3(

Appendix A API Functional Specifications 63

applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, flagApproversAsNotifiedIn in varchar2 default ame_util.booleanTrue, approvalProcessCompleteYNOut out varchar2, nextApproversOut out nocopy ame_util.approversTable2, itemIndexesOut out nocopy ame_util.idList, itemClassesOut out nocopy ame_util.stringList, itemIdsOut out nocopy ame_util.stringList, itemSourcesOut out nocopy ame_util.longStringList, productionIndexesOut out nocopy ame_util.idList, variableNamesOut out nocopy ame_util.stringList, variableValuesOut out nocopy ame_util.stringList, transVariableNamesOut out nocopy ame_util.stringList, transVariableValuesOut out nocopy ame_util.stringList);

Description
The getNextApprovers3 procedure has the same functionality as getNextApprovers2, but it also returns per-transaction productions. Use getNextApprovers3 when your application enables per-approver and per-transaction productions, for example to track eSignature requirements per approver and transaction. See also ame_api2.getAllApprovers3 and ame_api2.getNextApprovers2.

getNextApprovers4 Syntax
procedure getNextApprovers4( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, flagApproversAsNotifiedIn in varchar2 default ame_util.booleanTrue, approvalProcessCompleteYNOut out varchar2, nextApproversOut out nocopy ame_util.approversTable2);

Description
The getNextApprovers4 procedure has the same functionality as getNextApprovers1, but it omits per-item outputs. This is the lowest-overhead getNextApprovers[n] procedure. See also ame_api2.getAllApprovers7 and ame_api2.getNextApprovers1.

getPendingApprovers Syntax
procedure getPendingApprovers( applicationIdIn in number,

Appendix A API Functional Specifications 64

transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalProcessCompleteYNOut out varchar2, approversOut out nocopy ame_util.approversTable2);

Description
The getPendingApprovers procedure outputs in approversOut the approvers with approver_category ame_util.approvalApproverCategory and approval_status ame_util.notifiedStatus. These are the approvers who must approve before the input transaction’s approval process will continue to the next stage. If approvalProcessCompleteYNOut is ame_util.booleanTrue, the transaction’s approval process is complete. If approvalProcessCompleteYNOut is ame_util.booleanFalse and approversOut.count is zero, the application should call one of the getNextApprovers[n] procedures, and notify the approvers returned by that procedure.

getTransactionProductions Syntax
procedure getTransactionProductions( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, variableNamesOut out nocopy ame_util.stringList, variableValuesOut out nocopy ame_util.stringList);

Description
The getTransactionProductions procedure outputs all pertransaction productions for the input transaction. Use this API when your application uses AME as a general-purpose production-rule engine. See also ame_api2.getAllApprovers3.

initializeApprovalProcess Syntax
procedure initializeApprovalProcess( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, recordApproverListIn in boolean default false);

Description
The initializeApprovalProcess procedure causes AME’s engine to prepare a transaction’s approval process, if it has not already done so. In particular, the engine sets the approval process’ start date to sysdate. This API does not clear the state of the approval process; use clearAllApprovals for that. When recordApproverListIn is true, this API has the same effect as

Appendix A API Functional Specifications 65

getAndRecordAllApprovers. Calling initializeApprovalProcess guarantees that subsequent calls to getAllApprovers1 will be read only.

setFirstAuthorityApprover Syntax
procedure setFirstAuthorityApprover( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approverRecord2, clearChainStatusYNIn in varchar2);

Description
The setFirstAuthorityApprover procedure sets the approver represented by approverIn as the first chain-of-authority approver in the chain of authority identified by the action_type_id and group_or_chain_id fields of approverIn. This procedure succeeds only if the approval_status field of approverIn is null, and all the approvers in the target chain of authority also have null approval statuses. If clearChainStatusYNIn is ame_util.booleanTrue, AME clears the target chain of authority’s approval status before making approverIn the chain’s new first approver. Use this API to force AME to generate a chain of authority that satisfies a given set of rules, but that starts from an unusual first approver.

updateApprovalStatus Syntax
procedure updateApprovalStatus( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approverRecord2, forwardeeIn in ame_util.approverRecord2 default ame_util.emptyApproverRecord2, updateItemIn in boolean default false);

Description
The updateApprovalStatus procedure updates the approval status of the approver identified by approverIn to approverIn.approval_status. If the approval-status value indicates that the approver forwarded (with or without approving), forwardeeIn identifies the forwardee. If the approval_status value is ame_util.clearExceptionsStatus, the procedure clears the transaction’s exception log in AME without changing any approver’s status, regardless of the approver identified by approverIn. When a chain-of-authority approver forwards, the forwardee is also a chain–of–authority approver. Otherwise, the forwardee has the api_insertion value

Appendix A API Functional Specifications 66

ame_util.apiInsertion, and the same authority value as the forwarder. Use this API to update the state of a transaction’s approval process when an approver responds to a notification requesting approval.

updateApprovalStatus2 Syntax
procedure updateApprovalStatus2( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalStatusIn in varchar2, approverNameIn in varchar2, itemClassIn in varchar2 default null, itemIdIn in varchar2 default null, actionTypeIdIn in number default null, groupOrChainIdIn in number default null, occurrenceIn in number default null, forwardeeIn in ame_util.approverRecord2 default ame_util.emptyApproverRecord2);

Description
The updateApprovalStatus2 procedure has the same functionality as updateApprovalStatus, but it lets you identify the target approver by their wf_roles.name value, and as many other approver-distinguishing ame_util.approverRecord2 fields as you care to specify. When you leave one or more of the fields null, AME matches updates the status of the first occurrence of the approver having an approval status that does not indicate approval or forwarding. See also ame_api2.updateApprovalStatus.

updateApprovalStatuses Syntax
procedure updateApprovalStatuses( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approverRecord2, approvalStatusesIn in ame_util.stringList default ame_util.emptyStringList, itemClassesIn in ame_util.stringList default ame_util.emptyStringList, itemIdsIn in ame_util.stringList default ame_util.emptyStringList, forwardeesIn in ame_util.approversTable2 default ame_util.emptyApproversTable2);

Description
The updateApprovalStatuses procedure is currently a stub, and has no present functionality. Do not use it.

Appendix A API Functional Specifications 67

updateApprovalStatuses2 Syntax
procedure updateApprovalStatuses2( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approvalStatusIn in varchar2, approvalStatusIn in varchar2, approverNameIn in varchar2, itemClassIn in varchar2 default null, itemIdIn in varchar2 default null, actionTypeIdIn in number default null, groupOrChainIdIn in number default null, occurrenceIn in number default null, approvalStatusesIn in ame_util.stringList default ame_util.emptyStringList, itemClassesIn in ame_util.stringList default ame_util.emptyStringList, itemIdsIn in ame_util.stringList default ame_util.emptyStringList, forwardeesIn in ame_util.approversTable2 default ame_util.emptyApproversTable2);

Description
The updateApprovalStatuses2 procedure is currently a stub, and has no present functionality. Do not use it.

ame_api3 getRuleDescription Syntax
function getRuleDescription( ruleIdIn in varchar2) return varchar2;

Description
The getRuleDescription function returns the description of the rule with ID ruleIdIn. Rule descriptions are at most 100 bytes long.

clearSuppression Syntax
procedure clearSuppression( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approverRecord2);

Appendix A API Functional Specifications 68

Description
The clearSuppression procedure clears an approver suppression previously submitted by a call to suppressApprover or suppressApprovers, as long as approverIn is an AME generated approver. Use this API to reactivate an AME-generated approver who has been suppressed from the input transaction’s approver list. See also ame_api3.suppressApprover and ame_api3.suppressApprovers.

clearSuppressions Syntax
procedure clearSuppressions( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2);

Description
The clearSuppressions procedure has the effect of clearSuppression for all suppressed AME-generated approvers. See also ame_api3.suppressApprover, ame_api3.suppressApprovers, and ame_api3.clearSuppression.

clearInsertion Syntax
procedure clearInsertion( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approverRecord2);

Description
The clearInsertion procedure removes the input approver from the input transaction’s approver list. Use this API to remove an inserted approver from a transaction’s approver list.

clearInsertions Syntax
procedure clearInsertions( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2);

Description
The clearInsertions procedure has the effect of clearInsertion for all inserted approvers in the input transaction’s approver list. Use this API to remove all previously inserted approvers from a

Appendix A API Functional Specifications 69

transaction’s approver list. See also ame_api3.clearInsertion.

getAllApprovalGroups Syntax
procedure getAllApprovalGroups( groupIdsOut out nocopy ame_util.idList, groupNamesOut out nocopy ame_util.stringList);

Description
The getAllApprovalGroups procedure outputs all current AME approval groupsin ascending order of their names.

getApplicableRules1 Syntax
procedure getApplicableRules1( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, ruleIdsOut out nocopy ame_util.idList);

Description
The getApplicableRules1 procedure outputs in ruleIdsOut the IDs of the rules that apply to the input transaction. Use this API when you only need the rule IDs. See also ame_api3.getApplicableRules2 and getApplicableRules3.

getApplicableRules2 Syntax
procedure getApplicableRules2( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, ruleDescriptionsOut out nocopy ame_util.stringList);

Description
The getApplicableRules2 procedure outputs in ruleDescriptionsOut the descriptions of the rules that apply to the input transaction. Use this API when you only need the rule descriptions. See also ame_api3.getApplicableRules1 and ame_api3.getApplicableRules3.

Appendix A API Functional Specifications 70

getApplicableRules3 Syntax
procedure getApplicableRules3( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, ruleIdsOut out nocopy ame_util.idList, ruleDescriptionsOut out nocopy ame_util.stringList);

Description
The getApplicableRules3 procedure outputs in ruleIdsOut and ruleDescriptionsOut the IDs and descriptions of the rules that apply to the input transaction. This procedure is useful to construct a displayable list of descriptiosn of applicable rules, where each rule description hyperlinks to a more detailed description of the rule (generated by one of the ame_api3.getRuleDetails[n] procedures). See also ame_api3.getApplicableRules1, ame_api3.getApplicableRules1, and the three ame_api3.getRuleDetails[n] procedures.

getApprovalGroupId Syntax
procedure getApprovalGroupId( groupNameIn ame_util.stringType, groupIdOut out nocopy number);

Description
The getApprovalGroupId procedure outputs in groupIdOut the ID of the approval group with the name groupNameIn.

getAttributeValue Syntax
procedure getAttributeValue( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, attributeNameIn in varchar2, itemIdIn in varchar2, attributeValue1Out out varchar2, attributeValue2Out out varchar2, attributeValue3Out out varchar2);

Appendix A API Functional Specifications 71

Description
The getAttributeValue procedure outputs in attributeValue1Out, attributeValue2Out, and attributeValue3Out the values of the attribute with the name attributeNameIn for the item with ID itemIdIn, for the input transaction. An attribute is always associated with an item classes, and attribute names are unique across item classes; so it is not necessary to input the item class. If the attribute pertains to the header item class, itemIdIn should have the same value as transactionIdIn. For all attribute types other than currency attributes, attributeValue1Out contains the attribute’s value, and attributeValue2Out and attributeValue3Out are null. For currency attributes, attributeValue1Out is the amount, attributeValue2Out is the General Ledger currency code, and attributeValue3Out is the General Ledger conversion type.

getConditionDetails Syntax
procedure getConditionDetails( conditionIdIn in number, attributeNameOut out nocopy varchar2, attributeTypeOut out nocopy varchar2, attributeh4 DescriptionOut out nocopy varchar2, lowerLimitOut out nocopy varchar2, upperLimitOut out nocopy varchar2, includeLowerLimitOut out nocopy varchar2, includeUpperLimitOut out nocopy varchar2, currencyCodeOut out nocopy varchar2, allowedValuesOut out nocopy ame_util.longestStringList);

Description
The getConditionsDetails procedure outputs various descriptive details about the condition with ID conditionIdIn.

getGroupMembers1 Syntax
procedure getGroupMembers1( applicationIdIn in number default null, transactionTypeIn in varchar2 default null, transactionIdIn in varchar2 default null, groupIdIn in number, memberDisplayNamesOut out nocopy ame_util.longStringList);

Description
The getGroupMembers procedure outputs the display names of the members of the AME approval group with ID groupIdIn. If applicationIdIn, transactionIdIn, and transactionTypeIn default null, the ID must be for a static approval group. If the group is

Appendix A API Functional Specifications 72

dynamic, these three inputs must identify the transaction for which AME should calculate the group’s membership.

getGroupMembers2 Syntax
procedure getGroupMembers2( applicationIdIn in number default null, transactionTypeIn in varchar2 default null, transactionIdIn in varchar2 default null, groupIdIn in number, memberNamesOut out nocopy ame_util.longStringList, memberDisplayNamesOut out nocopy ame_util.longStringList);

Description
The getGroupMembers2 procedure has the same functionality as getGroupMembers, but it also outputs the group members’ wf_roles.name values. See also ame_api3.getGroupMembers1.

getGroupMembers3 Syntax
procedure getGroupMembers3( applicationIdIn in number default null, transactionTypeIn in varchar2 default null, transactionIdIn in varchar2 default null, groupIdIn in number, memberNamesOut out nocopy ame_util.longStringList, memberOrderNumbersOut out nocopy ame_util.idList, memberDisplayNamesOut out nocopy ame_util.longStringList);

Description
The getGroupMembers3 procedure has the same functionality as getGroupMembers2, but it also outputs the members’ order numbers. See also ame_api3.getGroupMembers2.

getGroupMembers4 Syntax
procedure getGroupMembers4( applicationIdIn in number default null, transactionTypeIn in varchar2 default null, transactionIdIn in varchar2 default null, groupIdIn in number, memberNamesOut out nocopy ame_util.longStringList, memberOrderNumbersOut out nocopy ame_util.idList, memberDisplayNamesOut out nocopy ame_util.longStringList, memberOrigSystemIdsOut out nocopy ame_util.idList, memberOrigSystemsOut out nocopy ame_util.stringList);

Appendix A API Functional Specifications 73

Description
The getGroupMembers4 procedure has the same functionality as getGroupMembers3, but it also outputs the members’ wf_roles.orig_system and wf_roles.orig_system_id values. See also ame_api3.getGroupMembers3.

getItemClasses Syntax
procedure getItemClasses( applicationIdIn in number default null, transactionTypeIn in varchar2 default null, transactionIdIn in varchar2 default null, itemClassIdsOut out nocopy ame_util.idList, itemClassNamesOut out nocopy ame_util.stringList);

Description
The getItemClasses procedure outputs the IDs and names of the item classes used by the input transaction.

getItemClassId Syntax
procedure getItemClassId( itemClassNameIn in varchar2, itemClassIdOut out number);

Description
The getItemClassId procedure outputs in itemClassIdOut the item-class ID of the item class with the name itemClassNameIn.

getItemClassName Syntax
procedure getItemClassName( itemClassIdIn in number, itemClassNameOut out varchar2);

Description
The getItemClassName procedure outputs in itemClassNameOut the name of the item class with the ID itemClassIdIn.

getOldApprovers Syntax
procedure getOldApprovers( applicationIdIn in number,

Appendix A API Functional Specifications 74

transactionTypeIn in varchar2, transactionIdIn in varchar2, oldApproversOut out nocopy ame_util.approversTable2);

Description
The getOldApprovers procedure outputs in oldApproversOut the approver list that AME calculated most recently for the input transaction. This approver list may not be the transaction’s current list. That is, simultaneous calls to getAllApprovers1 and getOldApprovers could return different approver lists (and the list returned by getOldApprovers would then be outdated). This API is a deprecated routine available only for the sake of backwards compatibility.

getRuleDetails1 Syntax
procedure getRuleDetails1( ruleIdIn in number, ruleTypeOut out nocopy varchar2, ruleDescriptionOut out nocopy varchar2, conditionIdsOut out nocopy ame_util.idList, actionTypeNamesOut out nocopy ame_util.stringList, actionTypeDescriptionsOut out nocopy ame_util.stringList, actionDescriptionsOut out nocopy ame_util.stringList);

Description
The getRuleDetails1 procedure outputs various descriptive details about the rule with ID ruleIdIn. Use getRuleDetails1 in connection with one of the getApplicableRules procedures. See also the getApplicableRules[n] procedures.

getRuleDetails2 Syntax
procedure getRuleDetails2( ruleIdIn in number, ruleTypeOut out nocopy varchar2, ruleDescriptionOut out nocopy varchar2, conditionDescriptionsOut out nocopy ame_util.longestStringList, actionTypeNamesOut out nocopy ame_util.stringList, actionTypeDescriptionsOut out nocopy ame_util.stringList, actionDescriptionsOut out nocopy ame_util.stringList);

Description
The getRuleDetails2 procedure has the same functionality as

Appendix A API Functional Specifications 75

getRuleDetails1, but it outputs condition descriptions rather than condition IDs. See also ame_api3.getRuleDetails1.

getRuleDetails3 Syntax
procedure getRuleDetails3( ruleIdIn in number, ruleTypeOut out nocopy varchar2, ruleDescriptionOut out nocopy varchar2, conditionIdsOut out nocopy ame_util.idList, conditionDescriptionsOut out nocopy ame_util.longestStringList, conditionHasLOVsOut out nocopy ame_util.charList, actionTypeNamesOut out nocopy ame_util.stringList, actionTypeDescriptionsOut out nocopy ame_util.stringList, actionDescriptionsOut out nocopy ame_util.stringList);

Description
The getRuleDetails3 procedure has the same functionality as getRuleDetails1, but it outputs condition ID and descriptions, and indicates whether each condition has a list of allowed values. See also ame_api3.getRuleDetails2.

insertApprover Syntax
procedure insertApprover( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approverRecord2, positionIn in number, insertionIn in ame_util.insertionRecord2);

Description
The insertApprover procedure inserts approverIn into the input transaction’s approver list at the approver-list index positionIn using the insertion parameter and order relation in insertionIn. See also ame_api3.getAvailableInsertions.

parseApproverSource Syntax
procedure parseApproverSource( approverSourceIn in varchar2, sourceTypeOut out varchar2, ruleIdsOut out nocopy ame_util.idList);

Appendix A API Functional Specifications 76

Description
The parseApproverSource procedure parses the ame_util.approverRecord2 source field in approverSourceIn into a source designator in sourceTypeOut and a possibly empty ruleID list in ruleIdsOut. When the list is non-empty, it contains the IDs of the rules requiring the approver having the input source value. Use this API to determine (and optionally display) the reason an approver occurs in a transaction’s approver list.

suppressApprover Syntax
procedure suppressApprover( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approverRecord2);

Description
The suppressApprover procedure suppresses approverIn from the input transaction’s approver list. The approver must match an approver in the transaction’s approver list according to the comparison rules explained earlier in this appendix. If approverIn matches a rule-generated approver from the transaction’s approver list and the mandatory boolean attribute ALLOW_DELETING_RULE_GENERATED_APPROVERS has the value ’true’, the target approver’s status is set to ame_util.suppressedStatus. If approverIn matches an inserted approver, the approver is deleted (undoing the insertion entirely).

suppressApprovers Syntax
procedure suppressApprovers( applicationIdIn in number, transactionTypeIn in varchar2, transactionIdIn in varchar2, approverIn in ame_util.approversTable2);

Description
The suppressApprovers procedure has the same effect as suppressApprover, but for each approver in approversIn. See also ame_api3.suppressApprover.

Appendix A API Functional Specifications 77

ame_api validateApprover Syntax
function validateApprover( approverIn in ame_util.approverRecord) return boolean;

Description
The validateApprover function returns true if the approver is valid, otherwise false. AME’s APIs always return valid approvers, so you don’t need to validate approvers returned by AME. You should call validateApprover to validate an approver you plan to insert into a transaction’s approver list. See also ame_api2.validateApprover.

clearAllApprovals Syntax
procedure clearAllApprovals( applicationIdIn in integer, transactionIdIn in varchar2, transactionTypeIn in varchar2 default null);

Description
The clearAllApprovals procedure has the same functionality as ame_api2.clearAllApprovers. See also ame_api2.clearAllApprovers.

deleteApprover Syntax
procedure deleteApprover( applicationIdIn in integer, transactionIdIn in varchar2, approverIn in ame_util.approverRecord, transactionTypeIn in varchar2 default null);

Description
The deleteApprover procedure suppresses the approver represented by approverIn in the input transaction’s approver list. See also ame_api3.suppressApprover.

deleteApprovers Syntax
procedure deleteApprovers( applicationIdIn in integer,

Appendix A API Functional Specifications 78

transactionIdIn in varchar2, approversIn in ame_util.approversTable, transactionTypeIn in varchar2 default null);

Description
The deleteApprovers procedure suppresses the approvers represented by approversIn in the input transaction’s approver list. See also ame_api3.suppressApprovers.

getAdminApprover Syntax
procedure getAdminApprover( applicationIdIn in integer default null, transactionTypeIn in varchar2 default null, adminApproverOut out ame_util.approverRecord);

Description
The getAdminApprover procedure outputs an ame_util.approverRecord identifying the administrative administrator for the input transaction type. See also ame_api3.getAdminApprover.

getAllApprovers Syntax
procedure getAllApprovers( applicationIdIn in integer, transactionIdIn in varchar2, transactionTypeIn in varchar2 default null, approversOut out ame_util.approversTable);

Description
The getAllApprovers procedure outputs the input transaction’s current approver list, including rule–generated, inserted, suppressed, and repeated approvers. The rows in approversOut are indexed by consecutive ascending integers starting at one. The approval_status values in approversOut reflect each approver’s most recent response to any request for approval they have received, assuming the originating application has passed such responses to AME via updateApprovalStatus or updateApprovalStatus2. In AME 11.5.9, the AME engine excluded from the approver list any approvers deleted by calls to ame_api.deleteApprover(s), or suppressed to account for the value of the repeatedApprovers configuration variable. In AME 11.5.10, this behavior has changed. The approver list in approversOut now includes deleted and repeated approvers, but assigns them one of the approval_status values ame_util.suppressedStatus and ame_util.repeatedStatus. Your code should treat these statuses as logically equivalent to ame_util.approvedStatus. The ame_api.getNextApprover will

Appendix A API Functional Specifications 79

skip approvers with either status when it iterates through the approver list to find the first approver that has not yet approved. See also the ame_api2.getAllApprovers[n] procedures.

getAvailableInsertions Syntax
procedure getAvailableInsertions( applicationIdIn in integer, transactionIdIn in varchar2, positionIn in integer, transactionTypeIn in varchar2 default null, availableInsertionsOut out nocopy ame_util.insertionsTable);

Description
The getAvailableInsertions procedure outputs a list of ame_util.insertionRecord records representing the approver insertions possible at the index positionIn in the transaction’s current approver list. See also ame_api3.getAvailableInsertions.

getAvailableOrders Syntax
procedure getAvailableOrders( applicationIdIn in integer, transactionIdIn in varchar2, positionIn in integer, transactionTypeIn in varchar2 default null, availableOrdersOut out ame_util.ordersTable);

Description
The getAvailableOrders procedure outputs a list of ame_util.orderType records. Each orderType record indicates a possible order type for an approver insertion at the index positionIn in the transaction’s current approver list. This procedure is deprecated. Use getAvailableInsertions instead. See also ame_api3.getAvailableInsertions.

getNextApprover Syntax
procedure getNextApprover( applicationIdIn in integer, transactionIdIn in varchar2, transactionTypeIn in varchar2 default null, nextApproverOut out ame_util.approverRecord);

Description
The getNextApprover procedure outputs the next approver that
Appendix A API Functional Specifications 80

should approve the input transaction. Unlike the ame_api2.getNextApprovers[n] procedures, ame_api.getNextApprover outputs the same approver each time the procedure is called for a given transaction, until the approver approves the input transaction.

getGroupMembers Syntax
procedure getGroupMembers( applicationIdIn in integer, transactionTypeIn in varchar2, transactionIdIn in varchar2, groupIdIn in number, memberOrderNumbersOut out nocopy ame_util.idList, memberPersonIdsOut out nocopy ame_util.idList, memberUserIdsOut out nocopy ame_util.idList);

Description
The getGroupMembers procedure outputs the members of the approval group with ID groupIdIn. See also ame_api3.getGroupMembers.

getOldApprovers Syntax
procedure getOldApprovers( applicationIdIn in integer, transactionIdIn in varchar2, transactionTypeIn in varchar2 default null, oldApproversOut out ame_util.approversTable);

Description
The getOldApprovers procedure outputs the approver list that AME calculated the last time it generated the input transaction’s approver list. See also ame_api3.getOldApprovers.

insertApprover Syntax
procedure insertApprover( applicationIdIn in integer, transactionIdIn in varchar2, approverIn in ame_util.approverRecord, positionIn in integer, orderIn in ame_util.orderRecord, transactionTypeIn in varchar2 default null);

Description
The insertApprover procedure inserts approverIn into the input transaction’s approver list at the index positionIn using the

Appendix A API Functional Specifications 81

insertion parameter and order relation in insertionIn. See also ame_api3.insertApprover.

setFirstAuthorityApprover Syntax
procedure setFirstAuthorityApprover( applicationIdIn in Integer, transactionIdIn in varchar2 approverIn in ame_util.approverRecord, transactionTypeIn in varchar2 default null);

Description
The setFirstAuthorityApprover procedure sets the first approver for each chain of authority in the input transaction’s approver list. Thus if the approver list includes several chains of authority, they will all start with approverIn. See also ame_api2.setFirstAuthorityApprover.

updateApprovalStatus Syntax
procedure updateApprovalStatus( applicationIdIn in integer, transactionIdIn in varchar2, approverIn in ame_util.approverRecord, transactionTypeIn in varchar2 default null, forwardeeIn in ame_util.approverRecord default ame_util.emptyApproverRecord);

Description
The updateApprovalStatus procedure updates the status of the approver approverIn in the input transaction’s approver list. A given person ID or user ID can appear several times in a transaction’s approver list, so AME uses all of the approvercomparison fields that occur in ame_util.approverRecord to match approverIn to an ame_util.approverRecord in the input transaction’s approver list. See also ame_api2.updateApprovalStatus and ame_api.updateApprovalStatus2.

updateApprovalStatus2 Syntax
procedure updateApprovalStatus2( applicationIdIn in integer, transactionIdIn in varchar2, approvalStatusIn in varchar2, approverPersonIdIn in integer default null, approverUserIdIn in integer default null, transactionTypeIn in varchar2 default null, forwardeeIn in ame_util.approverRecord default

Appendix A API Functional Specifications 82

ame_util.emptyApproverRecord);

Description
The updateApprovalStatus2 procedure has the same functionality as updateApprovalStatus, except that it updates the first ame_util.approverRecord in the input transaction’s approver list that matches whichever of approverPersonIdIn and approverUserIdIn is non-null, if the record’s status is not already an approving or forwarding response. See also ame_api2.updateApprovalStatus2 and ame_api.updateApprovalStatus.

What New APIs Map to the 11.5.9 APIs?
Most of the ame_api routines are essentially wrappers for ame_api2 or ame_api3 routines, with modifications to preserve pre-existing ame_api functionality. The following table tells you which ame_api routine serves as a wrapper for a given ame_api2 or ame_api3 routine. ame_api Routine Equivalent ame_api2 or ame_api3 Routine ame_api3.getRuleDescription ame_api2.validateApprover ame_api2.clearAllApprovals ame_api3.clearSuppression ame_api3.clearSuppressions ame_api3.clearInsertion ame_api3.clearInsertions ame_api3.suppressApprover ame_api3.suppressApprovers ame_api2.getAdminApprover ame_api2.getAllApprovers7 ame_api2.getAndRecordAllApprovers

getRuleDescription validateApprover clearAllApprovals clearDeletion clearDeletions clearInsertion clearInsertions deleteApprover deleteApprovers getAdminApprover getAllApprovers getAndRecordAllApprovers

Appendix A API Functional Specifications 83

ame_api Routine

Equivalent ame_api2 or ame_api3 Routine ame_api3.getApplicableRules1 ame_api3.getApplicableRules2 ame_api3.getApplicableRules3 ame_api2.getAllApprovers4 ame_api2.getAllApprovers5 ame_api2.getAllApprovers6 ame_api3.getAvailableInsertions Not available anymore ame_api3.getConditionDetails ame_api3.getGroupMembers4 ame_api2.getNextApprovers4 ame_api3.getOldApprovers ame_api3.getRuleDetails1 ame_api3.getRuleDetails2 ame_api3.getRuleDetails3 ame_api2.initializeApprovalProcess ame_api3.insertApprover ame_api2.setFirstAuthorityApprover ame_api2.updateApprovalStatus ame_api2.updateApprovalStatus2

getApplicableRules1 getApplicableRules2 getApplicableRules3 getApproversAndRules1 getApproversAndRules2 getApproversAndRules3 getAvailableInsertions getAvailableOrders getConditionDetails getGroupMembers getNextApprover getOldApprovers getRuleDetails1 getRuleDetails2 getRuleDetails3 initializeApprovalProcess insertApprover setFirstAuthorityApprover updateApprovalStatus updateApprovalStatus2

Appendix A API Functional Specifications 84

Appendix B ame_util Package

Appendix B ame_util Package 85

Overview
Many of the constants, data types, and routines in ame_util can be useful to originating applications. In fact, it’s important that you use appropriate ame_util features in your code, so that changes to AME functionality do not break your code. This appendix documents the ame_util features that your code should incorporate where appropriate.

Data Types
All of the AME data types your code requires are declared in ame_util’s package specification (in the package-header file ameoutil.pkh). This section describes the data types you may find useful.

approverRecord2
The ame_api2 and ame_api3 packages use the approverRecord2 record to represent an approver. This type has the declaration type approverRecord2 is record( name varchar2(320), orig_system varchar2(30), orig_system_id number, display_name varchar2(360), approver_category varchar2(1), api_insertion varchar2(1), authority varchar2(1), approval_status varchar2(50), action_type_id integer, group_or_chain_id integer, occurrence integer, source varchar2(500), item_class ame_item_classes.name%type, item_id ame_temp_old_approver_lists.item_id%type, item_class_order_number integer,

Appendix B ame_util Package 86

item_order_number integer, sub_list_order_number integer, action_type_order_number integer, group_or_chain_order_number integer, member_order_number integer, approver_order_number integer); Here are explanations of the allowed values and semantics of the record’s fields.

name
This is the approver’s wf_roles.name value, which essentially identifies the approver uniquely in wf_roles.

orig_system
This is the approver's wf_roles.orig_system value, which represents the system in which the approver originates. For example, the orig_system ‘PER’ is for approvers originating in the HRMS per_all_approvers_f table (that is, HR employees).

orig_system_id
This is the approver's wf_roles.orig_system_id value. The combination of the approver's orig_system and orig_system_id values also essentially identifies the approver uniquely in wf_roles.

display_name
This is the approver's wf_roles.display_name value.

approver_category
This field may contain either of two constants. • ame_util.approvalApproverCategory indicates that this occurrence of the approver must approve one or more items of the transaction in whose approver list the record occurs. ame_util.fyiApproverCategory indicates that this occurrence of the approver should just receive an informational notification describing the transaction in whose approver list the record occurs, and does not need to approve any of the transaction’s items.

Appendix B ame_util Package 87

api_insertion
This field may contain any of three constants: • ame_util.apiAuthorityInsertion indicates that the approver was inserted into a chain of authority as a chain-of-authority approver, so that the chain should continue with the superior of the inserted approver. The inserted approver must be from an originating system consistent with the action type that generated the chain of authority. This situation often arises when one chain-of-authority approver forwards a request for approval to the inserted approver. ame_util.apiInsertion indicates that the approver was inserted into a transaction’s approver list as an ad hoc approver—that is, an approver who is not part of a chain of authority (even if the approver occurs between two chain-ofauthority approvers who belong to the same approver list). ame_util.oamGenerated indicates that the rules applying to the transaction in whose approver list the approver occurs, required the approver’s presence in the transaction’s approver list. In this case the approver’s source field contains a value that includes the requiring rules’ IDs. (See ame_api3.parseApproverSource in Appendix A.)

authority
This field may contain any of three constants: • • • ame_util.preApprover identifies a pre–approver. ame_util.authorityApprover identifies an authority approver. ame_util.postApprover identifies a post–approver.

approval_status
This field may contain any of twelve constants. Some of these represent possible approver responses to notifications requesting approval, and so are allowed values in the approval-status input arguments of the ame_api2.updateApprovalStatus and ame_api2.updateApprovalStatus2 procedures. Others must be generated by AME. The items within the relevant transaction to which the approver’s approval_status value applies are identified by certain output arguments of the ame_api[n].getAllApprovers[n] and getNextApprovers[n] procedures. • ame_util.approvedStatus means the approver approved one or more of the relevant transaction’s items, without forwarding the notification requesting approval. You can pass this status to ame_api2.updateApprovalStatus and ame_api2.updateApprovalStatus2.

Appendix B ame_util Package 88

ame_util.approveAndForwardStatus means the approver approved one or more of the relevant transaction’s items, and also forwarded the notification requesting approval. You can pass this status to ame_api2.updateApprovalStatus and ame_api2.updateApprovalStatus2. ame_util.beatByFirstResponderStatus means the approver either has not responded, or responded after the first responder in the approval group or chain of authority containing the approver. (In the latter case, AME logs the approver's response and otherwise ignores it.) AME generates this status when the first-responderwins voting regime is in force for the group or chain containing the approver. You cannot pass this status to ame_api2.updateApprovalStatus or ame_api2.updateApprovalStatus2. ame_util.clearExceptionsStatus should be passed to ame_api[n].updateApprovalStatus or ame_api[n].updateApprovalStatus2 to clear a transaction’s exception log when the transaction’s workflow is restarted. This is necessary when the approver's status is ame_util.exceptionStatus. ame_util.exceptionStatus is sometimes returned by the API routines when AME raises an unhandled exception in the process of calculating a transaction’s approver list. (You cannot pass this status to ame_api2.updateApprovalStatus or ame_api2.updateApprovalStatus2.) In this case, the originating application may wish to stop the transaction’s workflow. ame_util.forwardStatus means the approver forwarded the notification requesting approval, without approving the items identified in the notification. You can pass this status to ame_api2.updateApprovalStatus and ame_api2.updateApprovalStatus2. ame_util.noResponseStatus means the originating application sent the approver a notification requesting approval, but the approver did not respond to the notification in a timely fashion. (The originating application decides what "timely" means.) You can pass this status to ame_api2.updateApprovalStatus and ame_api2.updateApprovalStatus2. AME responds to it by inserting the approver’s surrogate into the approver list, immediately after the approver. ame_util.notifiedStatus means the originating application has told AME that it has sent the approver a notification, and—if the notification requested approval—the approver has not yet responded to it. ame_util.nullStatus (or better yet, a null approval_status
Appendix B ame_util Package 89

value) means the approver has not yet been notified, or that their previous approval_status value was cleared. • ame_util.rejectStatus means the approver rejected one or more of the items in the approver list of the relevant transaction. You can pass this status to ame_api2.updateApprovalStatus and ame_api2.updateApprovalStatus2. ame_util.repeatedStatus means this occurrence of the approver has been aggregated with one or more other occurrences of the same approver, in the relevant transaction's approver list. (See the documentation of the repeatedApprovers configuration variable in Chapter 11 of the Oracle Approvals Management Implementation Guide for details.) The ame_api2.getNextApprovers[n] routines treat this status as equivalent to ame_util.approvedStatus, and so never output approvers with this status. ame_util.suppressedStatus means this occurrence of the approver has been suppressed, typically by a call to one of the ame_api3.suppressApprover(s) routines. The ame_api2.getNextApprovers[n] routines treat this status as equivalent to ame_util.approvedStatus, and so never output approvers with this status.

action_type_id
For AME-generated approvers, this field contains the ID that AME assigns to the action type that generated the approver. For example, if a rule using the absolute-job-level action type requires an approver, and that action type has the action-type ID 456, the approver's action_type_id value would be 456. For inserted chain-of-authority approvers, this field contains the same value that AME assigns to the AME-generated approvers in the same chain. For inserted ad-hoc approvers, this field contains the constant ame_util.nullInsertionActionTypeId.

group_or_chain_id
This field's semantics depend on whether the approver belongs to an approval group or a chain of authority. In the former case, the field contains the ID that AME assigns to the approval group. In the latter case, the action type generating the chain of authority assigns its chains ascending positive integer group_or_chain_id values, starting at one. For example, the dualchains-of-authority approval type generates two chains of authority. Approvers in the first chain have a group_or_chain_id value of one, and approvers in the second chain have a group_or_chain_id value of two. For inserted chain-of-authority approvers, this field contains the same value that AME assigns to rule-generated approvers in the same chain. For ad hoc inserted approvers, this field contains the constant ame_util.nullInsertionGroupOrChainId.

Appendix B ame_util Package 90

occurrence
The occurrence field indicates how many times the approver's wf_roles.name value has occurred in the approver's approval group or chain of authority, including the approver proper. For example, if an approver occurs twice in a given chain of authority, the first occurrence has the occurrence value one, and the second the value two.

source
This field's semantics may vary over time. You should never parse or interpret this field yourself. Instead, use ame_api3.parseApproverSource to do so. AME development will not support any code you write to parse the source field.

item_class
This field contains the name of the item class of the item ID identified by the approver's item_id field.

item_id
When an approver must approve or be notified about a single item, this field contains the ID of the item. When the approver must approver or be notified about several items, this field is null, and the list of items appears in certain API routines’ output arguments instead. See the ame_api2.getNextApprovers1 documentation in Appendix A for details.

item_class_order_number
AME uses this field internally to calculate the approver's approver_order_number value.

item_order_number
AME uses this field internally to calculate the approver's approver_order_number value.

sub_list_order_number
AME uses this field internally to calculate the approver's approver_order_number value.

action_type_order_number
AME uses this field internally to calculate the approver's approver_order_number value.

group_or_chain_order_number
AME uses this field internally to calculate the approver's
Appendix B ame_util Package 91

approver_order_number value.

member_order_number
AME uses this field internally to calculate the approver's approver_order_number value.

approver_order_number
AME uses the six other order-number fields to calculate the approver_order_number value by treating them as a six-tuple and sorting them in lexicographic order. AME uses the approver_order_number to determine which approvers to return in successive calls to the ame_api2.getNextApprovers[n] routines. See Chapter 11 of the implementation guide for details.

approversTable2
AME’s API represents approver lists as arguments of type approversTable2, which is a PL/SQL table of approverRecord2 records. Objects of this type should always be indexed by consecutive ascending integers starting at one.

insertionRecord2
The ame_api3.getAvailableInsertions procedure uses the insertionRecord2 record to represent a possible approver insertion. This type has the declaration, type insertionRecord2 is record( item_class ame_item_classes.name%type, item_id ame_temp_old_approver_lists.item_id%type, action_type_id integer, group_or_chain_id integer, order_type varchar2(50), parameter ame_temp_insertions.parameter%type, api_insertion varchar2(1), authority varchar2(1), description varchar2(200));

Fields that also Occur in approverRecord2
The item_class, item_id, action_type_id, group_or_chain_id, api_insertion, and authority fields have the same semantics here as they do for the approverRecord2 type. Here are explanations

Appendix B ame_util Package 92

of the other fields.

The order_type, parameter, and description Fields
The order_type field indicates the order relation that AME uses to determine the insertion’s index in an approver list. AME recalculates the location each time it generates the approver list. Here are brief explanations of each possible value for the order_type field, with accompanying syntax and semantics rules for the parameter and description fields. Absolute Order The value ame_util.absoluteOrder means the insertionRecord’s parameter field should be interpreted as an absolute order number. In this case the parameter should be the string representation of a positive integer between one and one more than the number of approvers already in the approver list. The description should have the syntax ame_util.absoluteOrderDescription || n || '. ' where n is the index at which the insertion should take place. For example, if the insertee should always be third in the transaction's approver list, the parameter should be ’3’. After an Approver The value ame_util.afterApprover means the insertee should immediately follow the approver that the insertion parameter identifies. In this case the parameter should have the syntax approver.name || ame_util.fieldDelimiter || approver.item_class || ame_util.fieldDelimiter || approver.item_id || ame_util.fieldDelimiter || approver.action_type_id || ame_util.fieldDelimiter || approver.group_or_chain_id || ame_util.fieldDelimiter || approver.occurrence and the description should have the form ame_util.afterApproverDescription || approver.display_name Before an Approver The value ame_util.beforeApprover means the insertee should immediately precede the approver that the insertion parameter identifies. In this case the parameter should have the syntax approver.name || ame_util.fieldDelimiter || approver.item_class || ame_util.fieldDelimiter ||

Appendix B ame_util Package 93

approver.item_id || ame_util.fieldDelimiter || approver.action_type_id || ame_util.fieldDelimiter || approver.group_or_chain_id || ame_util.fieldDelimiter || approver.occurrence and the description should have the form ame_util.afterApproverDescription || approver.display_name First Authority The value ame_util.firstAuthority means the insertee should be the first chain–of–authority approver in the chain of authority identified by the parameter. In this case the parameter should have the syntax ame_util.firstAuthorityParameter || ame_util.fieldDelimiter || approver.item_class || ame_util.fieldDelimiter || approver.item_id || ame_util.fieldDelimiter || approver.action_type_id || ame_util.fieldDelimiter || approver.group_or_chain_id and the description should have the form ame_util.firstAuthorityDescription First Post-Approver The value ame_util.firstPostApprover means the insertee should be the first post–approver in the approver list for the item identified by the parameter. In this case the parameter should have the syntax ame_util.firstPostParameter || ame_util.fieldDelimiter || approver.item_class || ame_util.fieldDelimiter || approver.item_id and the description should have the form ame_util.firstPostApproverDescription First Pre-Approver The value ame_util.firstPreApprover means the insertee should be the first pre–approver in the approver list for the item identified by the parameter. In this case the parameter should have the syntax ame_util.firstPreParameter || ame_util.fieldDelimiter || approver.item_class || ame_util.fieldDelimiter || approver.item_id and the description should have the form ame_util.firstPreApproverDescription

Appendix B ame_util Package 94

Last Post-Approver The value ame_util.lastPostApprover means the insertee should be the last post–approver in the approver list for the item identified by the parameter. In this case the parameter should have the syntax ame_util.lastPostParameter || ame_util.fieldDelimiter || approver.item_class || ame_util.fieldDelimiter || approver.item_id and the description should the form ame_util.lastPostApproverDescription Last Pre-Approver The value ame_util.lastPreApprover means the insertee should be the last pre–approver in the approver list for the item identified by the parameter. In this case the parameter should have the syntax ame_util.lastPreParameter || ame_util.fieldDelimiter || approver.item_class || ame_util.fieldDelimiter || approver.item_id and the description should have the form ame_util.lastPreApproverDescription

insertionsTable2
The insertionsTable2 type is a PL/SQL table of ame_util.insertionRecord2 records. The getAvailableInsertions procedure uses an argument of this type to represent the set of possible approver insertions at a given index in an approver list. Objects of this type should always be indexed by consecutive ascending integers starting at one.

approverRecord
In AME versions prior to 11.5.10 the approverRecord type represented an approver in an approver list. This data type is available for backward compatibility. It has the declaration type approverRecord is record( user_id fnd_user.user_id%type, person_id per_all_people_f.person_id%type, first_name per_all_people_f.first_name%type, last_name per_all_people_f.last_name%type, api_insertion varchar2(1),

Appendix B ame_util Package 95

authority varchar2(1), approval_status varchar2(50), approval_type_id integer, group_or_chain_id integer, occurrence integer, source varchar2(500)); Below are explanations of the allowed values and semantics for each field that does not occur in the ame_util.approverRecord2 type. (The rules for the other fields are the same here as there.)

user_id
The user_id field is null if and only if the person_id field is not null. If the user_id field is not null, it must contain a valid fnd_user.user_id value.

person_id
The person_id field is null if and only if the user_id field is not null. If the person_id field is not null, it must contain a valid per_all_people_f.person_id value.

first_name
If the person_id field is null, the first_name field contains the approver's fnd_user.user_name value. Otherwise the first_name field contains the approver's per_all_people_f.first_name value.

last_name
If the person_id field is null, the last_name field is also null. Otherwise the last_name field contains the approver's per_all_people_f.last_name value.

approval_type_id
The approval_type_id field has the same semantics as the action_type_id field in an approverRecord2. See “approverRecord2” above.

approversTable
This data type is a PL/SQL table of approverRecord records. The ame_api package represents approver lists as approversTable objects. Objects of this type should always be indexed by consecutive ascending integers starting at one. (This type is available for backward compatibility.)

Appendix B ame_util Package 96

insertionRecord
In AME versions prior to 11.5.10 the ame_util.insertionRecord record represented a possible approver insertion. This type is available for backward compatibility. It has the declaration, type insertionRecord is record( order_type varchar2(50), parameter ame_temp_insertions.parameter%type, api_insertion varchar2(1), authority varchar2(1), description ame_temp_insertions.description%type); The api_insertion and authority fields have the same interpretation here as for the approverRecord type. See the description above of the insertionOrder2 type for explanations of the available order types. Below are explanations of the syntax and semantics rules for each order type’s parameter and description values.

Absolute Order
The absolute-order order relation has the same order_type, parameter, and description values here as for the insertionRecord2 type.

After an Approver
The after-approver order type requires parameters with the syntax {person_id,user_id}:n The string preceding the colon indicates the semantics of n, where n is the person or user ID of the approver that the insertee should follow. For example, ’person_id:123’ indicates that the insertee should follow the approver with the person ID 123. The description should have the form ame_util.afterApproverDescription || first_name || ‘ ‘ || last_name where first_name and last_name are the values that you would assign to the first_name and last_name fields of an approverRecord representing the inserted approver.

Before an Approver
The before-approver order type requires parameters of the same form as those for the after-approver order type. The description

Appendix B ame_util Package 97

should have the form ame_util.beforeApproverDescription || first_name || ‘ ‘ || last_name where first_name and last_name are the values that you would assign to the first_name and last_name fields of an approverRecord representing the inserted approver. See “After an Approver” above.

First Authority
The first-authority order type does not use the parameter field. The description should be ame_util.firstAuthorityDescription

First Post-Approver
The first post-approver order relation does not use the parameter field. The description should be ame_util.firstPostApproverDescription

First Pre-Approver
The first pre-approver order relation does not use the parameter field. The description should be ame_util.firstPreApproverDescription

Last Post-Approver
The last post-approver order relation does not use the parameter field. The description should be ame_util.lastPostApproverDescription

Last Pre-Approver
The last pre-approver order relation does not use the parameter field. The description should be ame_util.lastPreApproverDescription

insertionTable
The insertionsTable type is a PL/SQL table of insertionRecord records. The ame_api.getAvailableInsertions procedure uses an argument of this type to represent the set of possible approver insertions at a given index in an approver list. Objects of this type should always be indexed by consecutive ascending integers starting at one. (This type is available for backward compatibility.)
Appendix B ame_util Package 98

Constants
The following table lists and describes frequently used ame_util constants, sorted first by purpose and then by alphabetical order.

Purpose approval status

Name approveAndForwardStatus

Description The approver approved and forwarded. The approver approved without forwarding. The approver’s approval group or chain of authority had the firstresponder-wins voting regime, and the approver was not the first responder. When passed to ame_api[n].updateApprovalStatus[ n], tells AME to clear an exception raised by the transaction’s approval process. The transaction’s approval process raised an exception. The approver forwarded. The approver did not respond in the time allowed by the originating application. The approver has been notified, and—if the approver must approve—has not yet responded. The approver has not yet been notified. The approver rejected. AME aggregated the approver with another occurrence of the same approver in the transaction's approver list.

approvedStatus

beatByFirstResponderStatus

clearExceptionsStatus

exceptionStatus

forwardStatus noResponseStatus

notifiedStatus

nullStatus

rejectStatus repeatedStatus

Appendix B ame_util Package 99

Purpose

Name suppressedStatus

Description The originating application suppressed the approver from the transaction’s approver list. The approver’s response is required. The approver’s response is not required. The approver is an inserted chainof-authority approver. The approver is an ad hoc approver. The approver is generated by approval rules. ALLOW_REQUESTOR_APPROVA L. ALLOW_EMPTY_APPROVAL_GR OUPS EFFECTIVE_RULE_DATE FIRST_STARTING_POINT_PERSO N_ID JOB_LEVEL_NON_DEFAULT_STA RTING_POINT_PERSON_ID INCLUDE_ALL_JOB_LEVEL_APP ROVERS LINE_ITEM_STARTING_POINT_P ERSON_ID NON_DEFAULT_STARTING_POI NT_POSITION_ID NON_DEFAULT_POSITION_STR UCTURE_ID

approver category

approvalApproverCategory

fyiApproverCategory

API insertion

apiAuthorityInsertion

apiInsertion

oamGenerated

attribute names

allowAutoApprovalAttribute

allowEmptyGroupAttribute

effectiveRuleDateAttribute firstStartingPointAttribute

jobLevelStartingPointAttribute

includeAllApproversAttribute

lineItemStartingPointAttribute

nonDefStartingPointPosAttr

nonDefPosStructureAttr

Appendix B ame_util Package 100

Purpose

Name secondStartingPointAttribute

Description SECOND_STARTING_POINT_PER SON_ID SIMPLE_POS_NON_DEFAULT_ST ARTING_POINT_PERSON_ID SUPERVISORY_NON_DEFAULT_ STARTING_POINT_PERSON_ID TOP_POSITION_ID TOP_SUPERVISOR_PERSON_ID TRANSACTION_DATE TRANSACTION_REQUESTOR_PE RSON_ID TRANSACTION_REQUESTOR_US ER_ID TRANSACTION_ORG_ID TRANSACTION_GROUP_ID TRANSACTION_REQUESTOR_PO SITION_ID TRANSACTION_SET_OF_BOOKS_ ID The approver is a member of a chain of authority. The approver is a member of a postapproval approval group. The approver is a member of a preapproval approval group. The approver should be inserted at the approver-list index identified by the insertion parameter.

simplePosStartPointAttribute

supStartingPointAttribute

topPositionIdAttribute topSupPersonIdAttribute transactionDateAttribute transactionRequestorAttribute

transactionReqUserAttribute

transactionOrgAttribute transactionGroupAttribute transactionReqPositionAttr

transactionSetOfBooksAttribute

authority

authorityApprover

postApprover

preApprover

insertion order

absoluteOrder

Appendix B ame_util Package 101

Purpose

Name afterApprover

Description The approver should be inserted right after the approver specified by the insertion parameter. The approver should be inserted right before the approver specified by the insertion parameter. The approver should be the first approver in the target chain of authority. The approver should be the first pre-approver for the item_class and item_id specified by insertion parameter. The approver should be the first post-approver for the item_class and item_id specified by insertion parameter. The approver should be the last pre-approver for the item_class and item_id specified by insertion parameter. The approver should be the last post-approver for the item_class and item_id specified by insertion parameter. the cost-center item class the header item class the line-item item class the FND_RESP originating system

beforeApprover

firstAuthority

firstPreApprover

firstPostApprover

lastPreApprover

lastPostApprover

item-class names

costCenterItemClassName headerItemClassName lineItemItemClassName

originating system names

fndRespOrigSystem

fndUserOrigSystem perOrigSystem

the FND_USR originating system the PER originating system

Appendix B ame_util Package 102

Purpose

Name posOrigSystem

Description the POS originating system the false value for boolean attributes the true value for boolean attributes a varchar2(1) pseudo-boolean constant for false a varchar2(1) pseudo-boolean constant for true the false value for boolean configuration variables the true value for boolean configuration variables Only the rejected item’s approval process stops.

pseudo-boolean constants

booleanAttributeFalse

booleanAttributeTrue booleanFalse

booleanTrue

no

yes

REJECTION_RES PONSE possible values

continueAllOtherItems

continueOtherSubItems

The header and rejected subordinate items’ approval processes stop. Other items’ approval processes continue. All items’ approval processes stop.

StopAllItems

Routines
Here are some frequently used ame_util routines.

getAdminName Syntax
function getAdminName( applicationIdIn in integer default null) return varchar2;

Description
This function returns the default value of the the adminApprover

Appendix B ame_util Package 103

configuration variable. You should only call this function in action-type handlers.

fieldDelimiter Syntax
function fieldDelimiter return varchar2;

Description
This function returns the field delimiter used by AME. You should only call this function in action-type handlers.

recordDelimiter Syntax
function recordDelimiter return varchar2;

Description
This function returns the record delimiter used by AME. You should only call this function in action-type handlers.

appendRuleIdToSource Syntax
procedure appendRuleIdToSource( ruleIdIn in integer, sourceInOut in out nocopy varchar2);

Description
This procedure appends the input rule ID to the input source value, and outputs the source value in place. Use this function in an action-type handler to build an approverRecord2’s source value.

copyApproverRecord2 Syntax
procedure copyApproverRecord2( approverRecord2In in approverRecord2, approverRecord2Out out nocopy approverRecord2);

Description
This procedure copies the input approverRecord2 to the output approverRecord2.

Appendix B ame_util Package 104

copyApproversTable2 Syntax
procedure copyApproversTable2( approversTable2In in approversTable2, approversTable2Out out nocopy approversTable2);

Description
This procedure copies the input approversTable2 to the output approversTable2.

runtimeException Syntax
procedure runtimeException( packageNameIn in varchar2, routineNameIn in varchar2, exceptionNumberIn in integer, exceptionStringIn in varchar2);

Description
All code that extends AME functionality should call runtimeException. This routine logs runtime exceptions in the AME exception log, and in the Workflow exception stack as appropriate.

Appendix B ame_util Package 105

Appendix C The Action-TypeHandler Programming Interface

Appendix C The Action-Type-Handler Programming Interface 107

Overview
The ame_util and ame_engine PL/SQL packages define a programming interface for action-type handlers. The ame_util package defines a set of datatypes and utility routines. The ame_engine package provides a collection of routines that it uses to exchange data with action-type handlers. See Appendix B of this guide for details about ame_util. This appendix documents the relevant ame_engine routines.

The ame_engine.engStApprovers Data Structure
The engine stores and manipulates a transaction’s approver list in a private data structure, ame_engine.engStApprovers, which is of type ame_util.approversTable2. This section refers to the data structure for convenience only. You should not modify the engine to access this data structure directly. (For one thing, the engine’s internal implementation may change, breaking your code’s references to ame_engine.engStApprovers.)

Engine Functions
getActionTypeChainOrderMode Syntax
function getActionTypeChainOrderMode( actionTypeIdIn in integer) return varchar2;

Description
Returns the chain-ordering mode of the action type with ID actionTypeIdIn. The possible values are ame_util.parallelChainsMode and ame_util.serialChainsMode. An authority handler typically uses this function to calculate the group_or_chain_order_number values of the approvers it generates.

getActionTypeVotingRegime Syntax
function getActionTypeVotingRegime( actionTypeIdIn in integer) return varchar2;

Description
Returns the voting regime of the action type with ID actionTypeIdIn. The possible values are

Appendix C The Action-Type-Handler Programming Interface 108

ame_util.consensusVoting, ame_util.firstApproverVoting, and ame_util.serializedVoting. An authority handler typically uses this function to calculate the member_order_number values of the approvers it generates.

getAttributeName Syntax
function getAttributeName( attributeIdIn in integer) return varchar2;

Description
Returns the name of the attribute with the ID attributeIdIn.

getAttributeIdByName Syntax
function getAttributeIdByName( attributeNameIn in varchar2) return integer;

Description
Returns the ID of the attribute with the name attributeNameIn.

getEffectiveRuleDate Syntax
function getEffectiveRuleDate return date;

Description
Returns the value of the RULE_EFFECTIVE_DATE attribute for the transaction that the engine is currently processing.

getHandlerActionTypeId Syntax
function getHandlerActionTypeId return integer;

Description
Only an action-type handler may call this function. It returns the ID of the action type that uses the handler. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s action_type_id field.

Appendix C The Action-Type-Handler Programming Interface 109

getHandlerActionTypeOrderNum Syntax
function getHandlerActionTypeOrderNum return integer;

Description
Only an action-type handler may call this function. It returns the order number of the action type that uses the handler. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s action_type_order_number field.

getHandlerApprovalStatus Syntax
function getHandlerApprovalStatus( approverIn in ame_util.approverRecord2) return varchar2;

Description
Only an action-type handler may call this function. It returns the current approval status of the approver identified by approverIn. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s approval_status field.

getHandlerAuthority Syntax
function getHandlerAuthority return varchar2;

Description
Only an action-type handler may call this function. It returns the ame_util sub-list (authority) constant of the approvers that the handler generates. A handler should only call this function if it always generates approvers in a fixed sub-list. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s authority field.

getHandlerItemClassId Syntax
function getHandlerItemClassId return integer;

Description
Only an action-type handler may call this function. It returns the

Appendix C The Action-Type-Handler Programming Interface 110

ID of the item class of the item whose approver list the engine is currently constructing. (This is not necessarily the ID of the item class of the item that satisfies the rule that uses the handler’s action type. These items, and their item classes, differ for header-level rules with conditions on subordinate-item-class attributes, when per-item evaluation is enabled.) A handler might call this function when preparing to populate an am_util.approverRecord2 record’s item_class field (using ame_engine.getItemClassName) or item_class_order_number field (using ame_engine.getItemClassOrderNumber). It is usually more efficient simply to call ame_engine.getHandlerItemClassName or ame_engine.getHandlerItemClassOrderNumber directly.

getHandlerItemClassName Syntax
function getHandlerItemClassName return varchar2;

Description
Only an action-type handler may call this function. It returns the name of the item class of the item whose approver list the engine is currently constructing. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s item_class field. See also getHandlerItemClassId above.

getHandlerItemClassOrderNumber Syntax
function getHandlerItemClassOrderNumber return integer;

Description
Only an action-type handler may call this function. It returns the order number of the item class of the item whose approver list the engine is currently constructing. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s item_class_order_number field. See also getHandlerItemClassId above.

getHandlerItemId Syntax
function getHandlerItemId return integer;

Description
Only an action-type handler may call this function. It returns the ID of the item whose approver list the engine is currently
Appendix C The Action-Type-Handler Programming Interface 111

constructing. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s item_id field. See also getHandlerItemClassId above.

getHandlerItemOrderNumber Syntax
function getHandlerItemOrderNumber return integer;

Description
Only an action-type handler may call this function. It returns the order number of the item whose approver list the engine is currently constructing. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s item_order_number field. See also getHandlerItemClassId above.

getHandlerOccurrence Syntax
function getHandlerOccurrence( nameIn in varchar2, itemClassIn in varchar2 default null, itemIdIn in varchar2 default null, actionTypeIdIn in integer default null, groupOrChainIdIn in integer default null) return integer;

Description
Only an action-type handler may call this function. It returns the occurrence value of the approver identified by the input arguments (which should have the values of the corresponding fields in the approver’s ame_util.approverRecord2 record). If any of the default-null input arguments is null, the function returns the occurrence value appropriate for adding the approver to the end of the approver list in ame_engine.engStApprovers. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s occurrence field.

getHandlerSublistOrderNum Syntax
function getHandlerSublistOrderNum return integer;

Description
Only an action-type handler may call this function. It returns the order number of the sub-list that the engine is currently

Appendix C The Action-Type-Handler Programming Interface 112

populating. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s sub_list_order_number field.

getHeaderAttValue1 Syntax
function getHeaderAttValue1( attributeIdIn in integer) return varchar2;

Description
This function returns the value of the header-level attribute with the ID attributeIdIn, for the transaction that the engine is currently processing. The function only works for attributes that are not of the currency attribute type. For header-level currency attributes, use one of the getHeaderAttValues[n] procedures (see below). A handler could call this function to fetch the value of one of its required attributes, but it would have to fetch the attribute’s ID (using ame_engine.getAttributeIdByName) first. Typically a handler would take the direct route by calling ame_engine.getHeaderAttValue2 (see below) instead. Note that any attribute referenced by your handler must be listed among the corresponding action type’s required attributes. (See “Creating an Action Type” below for details.)

getHeaderAttValue2 Syntax
function getHeaderAttValue2( attributeNameIn in varchar2) return varchar2

Description
This function returns the value of the header-level attribute with the name attributeNameIn, for the transaction that the engine is currently processing. The function only works for attributes that are not of the currency attribute type. For header-level currency attributes, use one of the getHeaderAttValues[n] procedures (see below). Typically a handler calls this function to fetch the value of one of its required attributes. Note that any attribute referenced by your handler must be listed among the corresponding action type’s required attributes. (See “Creating an Action Type” below for details.)

getItemClassId Syntax
function getItemClassId( itemClassNameIn in varchar2) return integer;

Appendix C The Action-Type-Handler Programming Interface 113

Description
This function returns the ID of the item class with the name itemClassNameIn.

getItemClassName Syntax
function getItemClassName( itemClassIdIn in integer) return varchar2;

Description
This function returns the name of the item class with ID itemClassIdIn.

getItemClassOrderNumber Syntax
function getItemClassOrderNumber( itemClassIdIn in integer) return integer;

Description
This function returns the order number of the item class with ID itemClassIdIn, for the transaction type of the transaction that the engine is currently processing. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s item_class_order_number field.

getItemOrderNumber Syntax
function getItemOrderNumber( itemClassNameIn in varchar2, itemIdIn in varchar2) return integer;

Description
This function returns the order number for the item with the ID itemIdIn in the item class with the name itemClassNameIn. Typically a handler calls this function to populate populate an ame_util.approverRecord2 record’s item_order_number field.

getRuntimeGroupCount Syntax
function getRuntimeGroupCount( groupIdIn in integer)

Appendix C The Action-Type-Handler Programming Interface 114

return integer;

Description
This function returns the number of static members of the approval group with ID groupIdIn.

getSublistOrderNum Syntax
function getSublistOrderNum( itemClassNameIn in varchar2, authorityIn in varchar2) return integer;

Description
This function returns the sub-list order number for the sub-list identified by the ame_util sub-list (authority) constant authorityIn, for the item class with the name itemClassNameIn. Typically a handler calls this function to populate an ame_util.approverRecord2 record’s sub_list_order_number field.

Engine Procedures
addApprover Syntax
procedure addApprover( approverIn in ame_util.approverRecord2);

Description
This procedure appends the record approverIn to the end of the approver list in ame_engine.engStApprovers. Typically a handler calls this procedure to add an approver to the end of the approver list.

getApprovalGroupConfigs Syntax
procedure getApprovalGroupConfigs( groupIdsInOut in out nocopy ame_util.idList, orderNumbersOut out nocopy ame_util.idList, votingRegimesOut out nocopy ame_util.charList);

Description
This procedure sorts the approver-group IDs groupIdsInOut in place by group order number first and then by group ID. It then returns the groups’ order numbers and voting regimes in a

Appendix C The Action-Type-Handler Programming Interface 115

consistent order. Typically an approver-group handler uses this procedure to populate the group_or_chain_order_number and member_order_number fields of the ame_util.approverRecord2 records representing the approvers in the input approval groups. (For details about approver-group voting regimes, see Appendix C of the implementation guide.)

getHandlerCOAFirstApprover Syntax
procedure getHandlerCOAFirstApprover( itemClassIn in varchar2, itemIdIn in varchar2, actionTypeIdIn in integer, groupOrChainIdIn in integer, nameOut out nocopy varchar2, origSystemOut out nocopy varchar2, origSystemIdOut out nocopy integer, displayNameOut out nocopy varchar2, sourceOut out nocopy varchar2);

Description
Only an action-type handler may call this procedure. If the originating application has inserted a starting point (first approver) for the chain of authority that the engine is currently constructing, this procedure returns the inserted approver in nameOut, origSystemOut, origSystemIdOut, and displayNameOut; and it returns the appropriate source-field value for the returned approver’s ame_util.approverRecord2 record. If no starting point has been inserted, the output arguments’ values are null.

getHandlerCOAInsertion Syntax
procedure getHandlerCOAInsertion( nameIn in varchar2, itemClassIn in varchar2, itemIdIn in varchar2, actionTypeIdIn in integer, groupOrChainIdIn in integer, occurrenceIn in integer, approvalStatusIn in varchar2, nameOut out nocopy varchar2, origSystemOut out nocopy varchar2, origSystemIdOut out nocopy integer, displayNameOut out nocopy varchar2, sourceOut out nocopy varchar2);

Description
Only an action-type handler may call this procedure. If the originating application has inserted a chain-of-authority approver into the chain of authority immediately after the input

Appendix C The Action-Type-Handler Programming Interface 116

approver (identified by all of the input arguments), this procedure returns the inserted approver in nameOut, origSystemOut, origSystemIdOut, and displayNameOut; and it returns the appropriate source-field value for the returned approver’s ame_util.approverRecord2 record. If no such insertion has occurred, the output arguments’ values are null.

getHandlerRules Syntax
procedure getHandlerRules( ruleIdsOut out nocopy ame_util.idList, approverCategoriesOut out nocopy ame_util.charList, parametersOut out nocopy ame_util.stringList, parameterTwosOut out nocopy ame_util.stringList);

Description
Only an action-type handler may call this procedure. It returns in ruleIdsOut the IDs of the rules that apply to the transaction the engine is currently processing, which use the action type. For each rule ID, the procedure also returns in approverCategoriesOut the approver category of the transaction type’s rule usage for the rule, and the action parameters of the rule’s action in parametersOut and parameterTwosOut. (If an applicable rule has several actions of the same action type, they appear in separate rows in the output arguments.) Typically a handler uses getHandlerRules for several purposes. First, it uses the action parameters to compute the set of approvers the rules require. Second, it uses the rule usages’ approver categories to determine each required approver’s approver category (that is, the approver_category field of the approver’s ame_util.approverRecord2). Third, it uses the rule IDs to populate the source field of each approver’s ame_util.approverRecord2. Use getHandlerRules2 if the actions processed by the handler only have one parameter each.

getHandlerRules2 Syntax
procedure getHandlerRules2( ruleIdsOut out nocopy ame_util.idList, approverCategoriesOut out nocopy ame_util.charList, parametersOut out nocopy ame_util.stringList);

Description
The handlers of action types whose actions only have one parameter should use getHandlerRules2 instead of

Appendix C The Action-Type-Handler Programming Interface 117

getHandlerRules (which a handler expecting two parameters per action should use). Otherwise, this procedure functions just like getHandlerRules. See “getHandlerRules” above for details.

getHandlerRules3 Syntax
procedure getHandlerRules3( ruleIdsOut out nocopy ame_util.idList, parametersOut out nocopy ame_util.stringList, listModParameterOnesOut out nocopy ame_util.stringList, listModParameterTwosOut out nocopy ame_util.longStringList);

Description
Only a handler for an action type used by list-modification rules may call this procedure. It functions in much the same way as getHandlerRules1, but for list-modification action types. Each row in the two listModParameter[n]Out arguments represents a list-modification condition. Each row in listModParameterOnesOut contains one of the constants ame_util.anyApprover and ame_util.finalApprover. Each row in listModParameterTwosOut contains the wf_roles.name of a target approver. the See “getHandlerRules1” above for further details.

getHandlerLMApprovers Syntax
procedure getHandlerLMApprovers( listModParameterOneIn in varchar2, listModParameterTwoIn in varchar2, includeFyiApproversIn in boolean, includeApprovalGroupsIn in boolean, returnForwardeesIn in boolean, approverIndexesOut out nocopy ame_util.idList, lastForwardeeIndexesOut out nocopy ame_util.idList);

Description
Only a list-modification action-type handler may call this procedure. It returns the indexes of the approvers in ame_engine.engStApprovers that satisfy the following requirements: 1. 2. The approver has the wf_roles.name value listModParameterTwoIn. The approver is in a position consistent with listModParameterOneIn (which can be ame_util.anyApprover or ame_util.finalApprover).

Appendix C The Action-Type-Handler Programming Interface 118

3.

If includeFyiApproversIn is false, the approver’s approver category is ame_util.approvalApproverCategory. If includeApprovalGroupsIn is false, the approver is in a chain of authority.

4.

The procedure returns matching approver occurrences’ indexes (in ame_engine.engStApprovers) in approverIndexesOut. If returnForwardeesIn is true, lastForwardeeIndexesOut(i) contains the index of the approver at the end of a succession of forwardings, starting with a forwarding from the approver at the index approverIndexesOut(i). (If there are no forwardings, the two values are the same.) Use getHandlerLMApprovers in conjunction with getHandlerRules3 (see “getHandlerRules3” above).

getHeaderAttValues1 Syntax
procedure getHeaderAttValues1( attributeIdIn in integer, attributeValue1Out out nocopy varchar2, attributeValue2Out out nocopy varchar2, attributeValue3Out out nocopy varchar2);

Description
This procedure returns the values of the header-level attribute with the ID attributeIdIn. The procedure returns null in attributeValue2Out and attributeValue3Out unless attributeIdIn identifies a currency attribute. Typically a handler uses this procedure to fetch a currency attribute’s values. However, the handler would typically first have to fetch the attribute’s ID, starting with its name, using ame_engine.getAttributeIdByName. The direct route is typically to use getHeaderAttValues2 (see “getHeaderAttValues2” below).

getHeaderAttValues2 Syntax
procedure getHeaderAttValues2( attributeNameIn in varchar2, attributeValue1Out out nocopy varchar2, attributeValue2Out out nocopy varchar2, attributeValue3Out out nocopy varchar2);

Description
This procedure returns the values of the header-level attribute with the name attributeNameIn. The procedure returns null in attributeValue2Out and attributeValue3Out unless attributeNameIn identifies a currency attribute. Typically a

Appendix C The Action-Type-Handler Programming Interface 119

handler uses this procedure to fetch a currency attribute’s values.

getRuntimeGroupMembers Syntax
procedure getRuntimeGroupMembers( groupIdIn in integer, approverNamesOut out nocopy ame_util.longStringList, approverOrderNumbersOut out nocopy ame_util.idList, approverDisplayNamesOut out nocopy ame_util.longStringList, origSystemIdsOut out nocopy ame_util.idList, origSystemsOut out nocopy ame_util.stringList);

Description
This procedure returns the members of the approval group with ID groupIdIn. The members’ order numbers within the group (corresponding to the member_order_number field of an ame_util.approverRecord2) are in approverOrderNumbersOut. Typically a pre-approval, post-approval, or approver-group chain-of-authority action type uses this procedure to fetch an approval group’s membership, so the handler can add the group to the approver list.

insertApprover Syntax
procedure insertApprover( indexIn in integer, approverIn in ame_util.approverRecord2, adjustMemberOrderNumbersIn in boolean default false);

Description
This procedure inserts the approver represented by approverIn at index indexIn of the current approver list (in ame_engine.engStApprovers). indexIn must be between one and one more than the number of approvers already in the list (inclusive). If adjustMemberOrderNumbersIn is true, insertApprover performs the insertion and then adjusts the member_order_number values of the approvers at and above indexIn, in the same group or chain as approverIn.

insertApprovers Syntax
procedure insertApprovers( firstIndexIn in integer, approversIn in ame_util.approversTable2);

Appendix C The Action-Type-Handler Programming Interface 120

Description
This procedure inserts the list of approvers in approversIn into consecutive positions in the current approver list, starting at the index firstIndexIn, which must be between one and one more than the number of approvers already in the list. Unlike insertApprover, insertApprovers does not adjust the member order numbers of any approvers following the inserted approvers. For this reason you should only use insertApprovers in cases where you’re confident no such adjustment could be appropriate.

substituteApprover Syntax
procedure substituteApprover( approverIndexIn in integer, nameIn in varchar2, actionTypeIdIn in varchar2, ruleIdIn in integer);

Description
This procedure replaces the wf_roles.name of the approver in ame_engine.engStApprovers at index approverIndexIn with the nameIn. It also appends ruleIdIn to the rule-ID list in the target approver’s source field.

truncateChain Syntax
procedure truncateChain( approverIndexIn in integer, ruleIdIn in integer);

Description
Only a list-modification action type’s handler may call this procedure. The procedure truncates the chain of authority containing the approver at index approverIndexIn of ame_engine.engStApprovers, so that this approver becomes the final approver in the chain. If the allowFyiNotifications configuration variable is set to yes, the approvers that would otherwise be truncated remain in the approver list, but their approver category becomes ame_util.fyiApproverCategory. The procedure also appends ruleIdIn to the truncated approvers’ source value.

Appendix C The Action-Type-Handler Programming Interface 121

Appendix D Sample AME Objects

Index 122

Overview
This chapter illustrates how to create a variety of AME objects that a development team would typically create, in the process of seeding a transaction type: • • • • • a transaction type proper mandatory-attribute usages an item-class usage a header-level attribute and a usage for it a line-item-level attribute and a usage for it.

The chapter includes sample code for each object, where appropriate. It generally assumes that it describes the activities of the development team for a fictitious Oracle Applications product Some Application.

Transaction Type
Before actually creating a transaction type, the team reviews and documents the following decisions: 1. 2. 3. 4. How many transaction types to create What usages to give the mandatory attributes What item-class usages to create How to configure the item-class usages.

The following subsections describe these decisions.

Number of Transaction Types
Suppose an originating application wants to integrate AME. The application has historically included its own approvals functionality. The approvals functionality applies the same approvals logic to all transactions generated by the application. The logic interprets its decision variables the same way for all transactions. In the development team’s experience, their customers generally implement a modest number of rules in the old approvals functionality. For all these reasons the development team concludes that it only needs to seed one transaction type.

Mandatory-Attribute Usages
Next, the development team reviews the mandatory attributes to

Index 123

decide what values or usages to seed for each. Their guiding principle is to preserve or improve upon their old approvals logic in their AME seed data. Here are their decisions: • The old approvals logic never allowed an end user to suppress approvers required by the application’s approvals logic, so the development team gives ALLOW_DELETING_RULE_GENERATED_APPROVERS a static false usage. Likewise, the old approvals logic never allowed an end user to approve the transactions they submit, so the development team gives ALLOW_REQUESTOR_APPROVAL a static false usage. In the old logic, all transactions having a total value over a user-configuration threshold must have someone’s approval. The application owns a PL/SQL package named some_app_package that contains a public function getApprovalThreshold; this function returns the threshold. Therefore the development team gives AT_LEAST_ONE_RULE_MUST_APPLY the dynamic usage

select decode(sign(sum(line_item_amount) – some_app_package.getApprovalThreshold), 1, ‘true’, ‘false’) from some_app_line_items where transaction_id = :transactionId; Note that this usage assumes that the line-item amounts are in the same currency as the threshold. • The old logic always evaluates its rules as of sysdate; so the development team gives EFFECTIVE_RULE_DATE a static null usage. The old logic does not have a rule-priority construct, so the team gives EVALUATE_PRIORITIES_PER_ITEM a static false usage. The old logic is able to request approval per line item, and it stops a transaction’s approval process when any line item is rejected. So the team gives REJECTION_RESPONSE a static usage having the value ame_util.stopAllItems.The old logic never does per-line-item rule evaluation, so the team gives USE_RESTRICTIVE_ITEM_EVALUATION a static false usage. The team will integrate AME API calls into its application’s Workflow process, so it gives USE_WORKFLOW a static true usage.

Index 124

The team uses its transactions’ Workflow item keys as transaction IDs, so it gives WORKFLOW_ITEM_KEY the dynamic usage

select :transactionId from dual

The team will give its master Workflow approvals process the item type the named ‘OSA’, so it gives WORKFLOW_ITEM_TYPE the static usage ‘OSA’.

Configuration-Variable Values
The development team chooses its seeded configuration-variable values according to the same principle by which it chose its mandatory-attribute usages: preserving or improving upon their application’s pre-AME functionality. Here are their decisions: • Each customer organization will have its own administrative approver, so the team does not seed a value for adminApprover. The team plans to seed a new approver type based on the (imaginary) ‘ORG’ originating system in Workflow Directory Services. So the team seeds the value ‘yes’ for allowAllApproverTypes. The old functionality uses line items, so the team seeds the value ‘true’ for allowAllItemClassRules. The team plans to enable FYI notifications in their approvals Workflow process, so the team sets allowFyiNotifications to ‘yes’. The old functionality limits currency conversions to a twomonth period, so the team sets currencyConversionWindow to 60 (days). The team decides not to seed values for forwardingBehaviors, assuming that their customers will generally already have created appropriate default values for this variable. The team will not use AME’s production functionality, so it sets productionFunctionality to ‘no’. The old approvals functionality clears and restarts a transaction’s approval process if it does not finish within two weeks, so the team sets purgeFrequency to 14 (days). The old functionality does not suppress repeated approvers, so the team sets repeatedApprovers to ‘each occurrence’.

• •

• •

Index 125

The old functionality does not have a rule-priority construct, so the team disables rule priorities for all rule types in rulePriorityModes.

Item-Class Usage
Next the team prepares to create an item-class usage for the lineitem item class.

Item-Class Order Number
The old approvals functionality created an approver list for each line item. It ordered all approvers serially, with line items’ approver lists following the header’s approver list. Consequently the team assigns the line-item item class the itemclass order number two.

Parallelization Mode
Per the above, the team assigns the line-item item class the serial parallelization mode.

Sublist Mode
Per the above, the team assigns the line-item item class the serial sublist mode.

Line-Item-ID Query
The application’s line items apear in the table some_app_line_items; their IDs are in the line_item_id column of that table. That table joins the application’s some_app_headers table via the transaction_id column. So the item-class usage must have the line-item-ID query select to_char(line_item_id) from some_app_line_items where transaction_id = :transactionId order by line_item_id asc; Note that the order-by clause orders the item IDs in ascending numerical order, rather than in ascending character-set order. Character-set ordering would force the transaction type’s lineitem-level attributes’ usages to order by to_char(line_item_id), which would be inefficient and easy to forget.

Action Parameters, 14 Action Type, 12 action_type_id, 90 AME Security, 8, 9 appendRuleIdToSource, 104

approval_status, 88 chain of authority, 12, 14, 17, 20, 24, 43, 66, 82, 88, 89, 90, 91, 94, 99, 101, 102, 116, 119, 121 clearAllApprovals, 55, 78
Index 126

clearInsertion, 69 clearInsertions, 69 clearSuppression, 68 Configuration-Variable Values, 125 Creating a Transaction Type, 9 Define an Item Class, 38 deleteApprover, 78 deleteApprovers, 78 Exception Handling, 41 fieldDelimiter, 104 final (signing) authority, 43 getActionTypeChainOrderMode, 108 getActionTypeVotingRegime, 108 getAdminApprover, 56 getAdminName, 103 getAllApprovalGroups, 70 getAllApprovers, 57, 79 getAllApprovers1, 56 getAllApprovers3, 57 getAllApprovers4, 58 getAllApprovers5, 59 getAllApprovers6, 59 getAllApprovers7, 60 getAllItemApprovers, 60 getAllItemApprovers2, 60 getAndRecordAllApprovers, 61 getApplicableRules1, 70 getApplicableRules2, 70 getApplicableRules3, 71 getApprovalGroupId, 71 getAttributeValue, 71 getAvailableInsertions, 80 getAvailableOrders, 80 getConditionDetails, 72 getGroupMembers1, 72 getGroupMembers2, 73 getGroupMembers3, 73 getGroupMembers4, 73 getItemClasses, 74 getItemClassId, 74

getItemClassName, 74 getItemStatus1, 61 getItemStatus2, 61 getItemStatuses, 62 getNextApprover, 80 getNextApprovers1, 62 getNextApprovers2, 63 getNextApprovers3, 63 getNextApprovers4, 64 getOldApprovers, 74, 81 getPendingApprovers, 64 getRuleDescription, 68 getRuleDetails1, 75 getRuleDetails2, 75 getRuleDetails3, 76 getTransactionProductions, 65 group_or_chain_id, 90 initializeApprovalProcess, 65 insertApprover, 76, 81 List-Editing-Handler, 23 list–modification, 12 parseApproverSource, 76 PL/SQL Exceptions, 24 post-approval, 12, 16, 20, 101, 120 pre-approval, 12, 20, 101, 120 production, 12, 14, 57, 65, 125 recordDelimiter, 104 setFirstAuthorityApprover, 66, 82 suppressApprover, 77 suppressApprovers, 77 Suppressing Approvers, 42 the Default Approver List, 41 Unresponsive Approvers, 42 updateApprovalStatus, 66, 82 updateApprovalStatus2, 67, 82 updateApprovalStatuses, 67 updateApprovalStatuses2, 68 validateApprover, 55, 78 Workflow Directory Services, 30

Index 127