DBA Data[Home] [Help]

PACKAGE BODY: APPS.AME_ENGINE

Source


1 PACKAGE BODY AME_ENGINE as
2 /* $Header: ameeengi.pkb 120.60.12020000.3 2013/02/14 10:49:49 nivsubra ship $ */
3   /*************************************************************************************
4   package variables
5   All engine package variables' names begin with the prefix 'eng'.  All engine package
6   variables are private.
7   *************************************************************************************/
8   /* transaction identifiers */
9   engAmeApplicationId integer;
10   engFndApplicationId integer;
11   engTransactionId ame_temp_old_approver_lists.transaction_id%type;
12   engTransactionTypeId ame_calling_apps.transaction_type_id%type;
13   /* engTransactionIsLocked is for the transaction-locking utilities used by the APIs. */
14   engTransactionIsLocked boolean := false;
15   /*
16     engIsLocalTransaction indicates whether the current engine cycle originates in an API
17     call or a test-tab routine.  If the test tab is testing a real transaction ID, it should
18     set engIsTestTransaction to false (via a call to updateTransactionState), and it should
19     set engIsLocalTransaction to true.  The API should set both engIsTestTransaction and
20     engIsLocalTransaction to false.  The ame_util.runtimeException checks engIsLocalTransaction
21     to determine whether to log an exception to the Workflow context stack.
22   */
23   engIsLocalTransaction boolean := true;
24   /*
25     engIsTestTransaction indicates whether the current transaction is a test transaction.
26     If so, the engine fetches the transaction's attribute values from ame_test_trans_att_values.
27     engIsTestTransaction is initialized to true so ame_util.runtimeException will see
28     a value of true in the absence of a call to updateTransactionState, before the
29     call to ame_util.runtimeException.  That is, unless a call to updateTransactionState
30     sets this variable's value, we assume the transaction is a test transaction, to
31     avoid writing spurious exceptions to the Workflow context stack.
32    */
33   engIsTestTransaction boolean := true;
34   /*
35     updateTransactionState sets the following variables.  They indicate which parts of its
36     cycle the engine should or should not execute.
37   */
38   engPrepareItemData boolean;
39   engPrepareRuleDescs boolean;
40   engPrepareApproverTree boolean;
41   engItemDataPrepared boolean;
42   engPrepareRuleIds boolean;
43   engProcessPriorities boolean;
44   engProcessProductionActions boolean;
45   engProcessProductionRules boolean;
46   engUpdateCurrentApproverList boolean;
47   engUpdateOldApproverList boolean;
48   /* configuration-variable caches */
49   engConfigVarNames ame_util.longStringList; /* kept compact */
50   engConfigVarValues ame_util.longStringList; /* kept compact */
51   /*
52     Generally, all runtime queries should use engEffectiveRuleDate in their date logic, to make sure
53     they all rely on the same snapshot of AME data.  (Failure to do this can lead to inconsistent data
54     in different parts of the engine cycle, which could make the engine crash.)
55   */
56   engEffectiveRuleDate date;
57   engEvalPrioritiesPerItem boolean;
58   engForwardingBehaviors ame_util.stringList; /* kept compact */
59   /*
60     engPriorityModes and engPriorityThresholds are indexed by rule-type constant, so their
61     indexes run from zero to seven.
62   */
63   engPriorityModes ame_util.stringList;
64   engPriorityThresholds ame_util.idList;
65   /*
66     Approval-group members are cached (once fetched as required) in the engGroup variables.  These
67     lists are compact.  All of a group's members are in a consecutive order consistent with the
68     group members' order numbers (whether static or dynamic in the group definition).
69   */
70   engGroupMemberGroupIds ame_util.idList;
71   engGroupMemberNames ame_util.longStringList;
72   engGroupMemberOrderNumbers ame_util.idList;
73   engGroupMemberDisplayNames ame_util.longStringList;
74   engGroupMemberOrigSystems ame_util.stringList;
75   engGroupMemberOrigSystemIds ame_util.idList;
76   -- Array to keep track if approval group needs to be rerun for each item class, item ID
77   engGroupUseItemBind ame_util.charList;
78   /* approver lists */
79   engDeletedApproverList ame_util.approversTable2; /* kept compact */
80   engInsertedApproverList ame_util.approversTable2; /* kept compact */
81   engOldApproverList ame_util.approversTable2; /* kept compact, read only */
82   /* lists related to approver insertion and deletion */
83   engInsertionOrderTypeList ame_util.stringList; /* corresponds in order to engInsertedApproverList */
84   engInsertionParameterList ame_util.longestStringList; /* corresponds in order to engInsertedApproverList */
85   engInsertionIsSpecialForwardee ame_util.charList; /* ame_util.booleanTrue if insertee is a special forwardee */
86   engInsApproverIndex ame_util.idList; /*maintain the approver index for the insertion*/
87   /* action-type configuration data, all sparse, indexed by action-type ID */
88   engActionTypeChainOrderModes ame_util.charList;
89   engActionTypeOrderNumbers ame_util.idList;
90   engActionTypeVotingRegimes ame_util.charList;
91   engActionTypeNames ame_util.stringList;
92   engActionTypeUsages ame_util.idList;
93   engActionTypePackageNames ame_util.stringList;
94   /*
95     list-modification condition caches, all sparse, indexed by the ID of the rule using the LM condition,
96     not by the condition ID (It's more efficient to index by rule ID.)
97   */
98   engLMParameterOnes ame_util.stringList;
99   engLMParameterTwos ame_util.longStringList;
100   /*
101     The item-class usages are stored in engItemClassIds, engItemClassNames, engItemClassOrderNumbers,
102     engItemClassParModes, and engItemClassSublistModes.  All of these are compact, and ordered by
103     item_class_order_number order.  If engItemClassIds(i) is a given item class' item-class ID, then
104     engItemClassIndexes(engItemClassIds(i)) = i.  So the index of the row in the item-class-usage
105     data structures for an item class with the item-class ID item_class_id is
106     engItemClassIndexes(item_class_id).  engItemClassItemIdIndexes(i) is the index of the first item
107     ID in itemIds of the item class with ID engItemClassIds(i).
108   */
109   engItemClassIds ame_util.idList;
110   engItemClassIndexes ame_util.idList;
111   engItemClassItemIdIndexes ame_util.idList;
112   engItemClassNames ame_util.stringList;
113   engItemClassOrderNumbers ame_util.idList;
114   engItemClassParModes ame_util.charList;
115   engItemClassSublistModes ame_util.charList;
116   /*
117     engItemCounts(i) is the number of items of the item class with item-class ID
118     engItemClassIds(i).  engItemIds contains the item-ID lists returned by all
119     of the item classes' item-ID queries, in item_class_order_number order.
120   */
121   engItemCounts ame_util.idList; /* compact */
122   engItemIds ame_util.stringList; /* compact */
123   /* attributes */
124   engAttributeIsStatics ame_util.charList; /* indexed by attribute id */
125   engAttributeItemClassIds ame_util.idList; /* indexed by attribute id */
126   engAttributeNames ame_util.stringList; /* indexed by attribute id */
127   engAttributeTypes ame_util.stringList; /* indexed by attribute id */
128   /* New arrays to store the query details and whether they need to be evaluated
129      for each itemClass and itemID */
130   engAttributeQueries ame_util.longestStringList;
131   engAttributeVariant ame_util.stringList;
132   /*
133     The attribute values are kept compact.  The values of the attribute with ID i
134     are stored starting at the index engAttributeValueIndexes(i), in the order
135     that their item IDs occur in engItemIds.
136   */
137   engAttributeValueIndexes ame_util.idList; /* indexed by attribute id */
138   engAttributeValues1 ame_util.attributeValueList; /* compact */
139   engAttributeValues2 ame_util.attributeValueList; /* compact */
140   engAttributeValues3 ame_util.attributeValueList; /* compact */
141   /*
142     engHeaderConditionValues caches the truth values of conditions on
143     attributes in the header item class.  It is indexed by condition ID.
144   */
145   engHeaderConditionValues ame_util.charList;
146   /*
147     The engACUsage variables store active condition usages and related data.
148     engACUsageRulePriorities, engACUsageRuleTypes, and engACUsageRuleApprCategories
149     are indexed by rule ID; the other variables are indexed consecutively, and are
150     ordered first by item-class ID (with null item-class IDs last), then by rule ID.
151     The first order-by is so the engine can efficiently access the related engAC and
152     engACU data structures by item-class ID.  (List-modification rules have null
153     item-class IDs, so they'll get processed last.)  The second order-by is so the
154     engine can efficiently do weak per-item evaluation for rules in the header item
155     class, when that is required.  engACUsageFirstIndexes(item_class_id) is the index
156     of the first row in the engACUsage variables for the item class with ID
157     item_class_id.  That is, engACUsageFirstIndexes is indexed by item-class
158     ID.  An item class may have no active condition usages.  In this case,
159     engACUsageFirstIndexes.exists(item_class_id) returns false.
160     engACUsageItemClassCounts(item_class_id) is the number of rows in the
161     engACUsage variables for the item class with ID item_class_id, starting at
162     the index engACUsageFirstIndexes(item_class_id).
163   */
164   engACUsageConditionIds ame_util.idList;
165   engACUsageFirstIndexes ame_util.idList;
166   engACUsageItemClassCounts ame_util.idList;
167   engACUsageRuleIds ame_util.idList;
168   engACUsageRulePriorities ame_util.idList; /* indexed by rule ID */
169   engACUsageRuleTypes ame_util.idList; /* indexed by rule ID */
170   engACUsageRuleApprCategories ame_util.charList; /* indexed by rule ID */
171   /*
172     The engAC variables store properties of conditions in the active condition usages.
173     They are indexed by condition ID.
174   */
175   engACAttributeIds ame_util.idList;
176   engACConditionTypes ame_util.stringList;
177   engACIncludeLowerLimits ame_util.charList;
178   engACIncludeUpperLimits ame_util.charList;
179   engACParameterOnes ame_util.stringList;
180   engACParameterThrees ame_util.stringList;
181   engACParameterTwos ame_util.longStringList;
182   /*
183     engACStringValues stores string values for active conditions on string attributes.
184     It is ordered by condition ID.  engACStringValueFirstIndexes(condition_id) is the
185     index of the first row in engACStringValues for the condition with ID condition_id.
186     That is, engACStringValueFirstIndexes is indexed by condition ID.
187     engACStringValueCounts(condition_id) is the number of rows in
188     engACStringValues for the condition with ID condition_id, starting at
189     the index engACStringValueFirstIndexes(condition_id).
190   */
191   engACStringValueCounts ame_util.idList;
192   engACStringValueFirstIndexes ame_util.idList;
193   engACStringValues ame_util.attributeValueList;
194   /*
195     >> engApp indexing
196     The variables
197       engAppHandlerFirstIndex
198       engAppHandlerLastIndex
199     are single-valued.  The variables
200       engAppLMSubItemClassIds
201       engAppLMSubItemIds
202     are indexed by rule ID.  All other engApp variables are stored in a common, dense
203     order, with each row representing the application of a single rule to a single
204     item.  (Thus the same rule ID can appear several times in engAppRuleIds, as long
205     as when i <> j, if engAppRuleIds(i) = engAppRuleIds(j) then engAppAppItemIds(i)
206     <> engAppItemIds(j) and of course engAppRuleItemClassIds(i) does not identify the
207     header item class.)  The rules determining the ordering of the dense engApp
208     variables change somewhat at different engine-processing stages; see below.
209     >> engApp semantics
210     Most of the engApp variables store the list of applicable rules.  The following
211     variables store actual rule and rule-usage properties:
212       engAppActionTypeIds
213       engAppApproverCategories
214       engAppPriorities
215       engAppRuleIds
216       engAppRuleItemClassIds
217       engAppRuleTypes.
218     The variables
219       engAppParameters
220       engAppParameterTwos
221     store the parameters of the rules' actions.  The variables
222       engAppItemClassIds
223       engAppItemIds
224     store the item-class IDs and item IDs of the item that satisfies a rule.  The
225     variable
226       engAppAppItemIds
227     contains the IDs of the items to which the rules apply (and these items always
228     belong to the item classes identified by engAppRuleItemClassIds).  Usually the item
229     that satisfies a rule is the same as the item to which the rule applies.  That is,
230     usually
231       engAppRuleItemClassIds(i) = engAppItemClassIds(i)
232       engAppAppItemIds(i) = engAppItemIds(i).
233     However, if per-item evaluation is enabled, these equalities fail for a rule
234     that contains a subordinate-item-class level condition.  In this case,
235     engAppRuleItemClassIds(i) identifies the header item class, and
236     engAppAppItemIds(i) is the transaction ID; but engAppItemClassIds(i) and
237     engAppItemIds(i) identify a subordinate item-class item satisfying the
238     subordinate-item-class level conditions.  Note that the engine treats list-
239     modification and substitution rules as applying to all item classes and items, so
240       engAppItemClassIds
241       engAppItemIds
242     are null for rules of these types.  These rules' satisfying item classes and items
243     are stored instead in
244       engAppLMSubItemClassIds
245       engAppLMSubItemIds.
246     Finally, the variables
247       engAppHandlerFirstIndex
248       engAppHandlerLastIndex
249     mark the first and last rows in the other engApp variables that the procedure
250     processActionType is currently processing.  They have no meaning outside this context.
251     >> engApp processing
252     The procedure evaluateRules populates
253       engAppRuleIds
254       engAppRuleTypes
255       engAppRuleItemClassIds
256       engAppPriorities
257       engAppApproverCategories
258       engAppItemClassIds
259       engAppItemIds
260       engAppAppItemIds
261     leaving them compact and sorted lexicographically by these values:
262       the item-class order numbers of the engAppRuleItemClassIds values
263       the engAppRuleItemClassIds values themselves
264       the engAppItemClassIds values
265       the engAppRuleTypes values.
266     The processRelativePriorities procedure (called by evaluateRules)
267       1.  deletes a row in the compact engApp lists if the rule represented by the row
268           is of insufficient relative priority.
269       2.  re-compacts the same lists (preserving the above lexicographic ordering).
270     At this point, a rule with several actions still appears just once in the engApp
271     lists.  The procedure fetchApplicableActions
272       1.  populates engAppActionTypeIds, engAppParameters, and engAppParameterTwos.
273       2.  splits out the actions in a rule so that the rule has one row in the engApp
274           lists for each of the rule's actions.
275       3.  converts each combination rule's rule type to the rule type that corresponds
276           with the rule's action type.
277       4.  re-sorts the lists lexicographically by these values:
278             rule's item-class order number
279             rule's item-class ID
280             item ID of the item to which the rule applies
281             rule type
282             action-type order number
283             action-type ID.
284     fetchApplicableActions deletes engAppPriorities because priorities have already been
285     processed; so engAppPriorities should not be referenced after fetchApplicableActions
286     is called.  Next, processExceptions
287       1.  deletes from the engApp variables any list-creation (authority) rules
288           suppressed by the exception rules.
289       2.  re-compacts the lists (preserving the above lexicographic ordering).
290       3.  converts the exception rules to list-creation rules.
291     processExceptions occurs in the engine algorithm after applicable actions have been
292     fetched, so that the actions of any list-creation rules suppressed by exception
293     rules will have been fetched unnecessarily.  The assumption here is that exception
294     rules are deprecated, so if performance becomes an issue, exception rules should be
295     converted to list-creation rules with appropriate priorities.
296   */
297   engAppActionTypeIds ame_util.idList;
298   engAppAppItemIds ame_util.stringList;
299   engAppApproverCategories ame_util.charList;
300   engAppHandlerFirstIndex integer;
301   engAppHandlerLastIndex integer;
302   engAppItemClassIds ame_util.idList;
303   engAppItemIds ame_util.stringList;
304   engAppLMSubItemClassIds ame_util.idList;
305   engAppLMSubItemIds ame_util.stringList;
306   engAppParameters ame_util.stringList;
307   engAppParameterTwos ame_util.stringList;
308   engAppPriorities ame_util.idList;
309   engAppRuleIds ame_util.idList;
310   engRuleAppliedYN ame_util.charList;
311   engAppRuleItemClassIds ame_util.idList;
312   engAppRuleTypes ame_util.idList;
313   /*
314     The engAppPerAppProd variables contain per-approver productions sorted by rule ID.
315     fetchApplicableActions populates these variables.  Then populateEngStVariables transfers
316     the values into engStProductionIndexes, engStVariableNames, and engStVariableValues,
317     after the approver list has been built.  Finally processRepeatedApprovers modifies the
318     values as it suppresses repeated approvers.  All of the per-approver productions generated
319     by a rule appear in consecutive order in the engAppPerAppProd variables.
320     engAppPerAppProdFirstIndexes(i) is the index of the first row in the other
321     engAppPerAppProd variables that contains a production generated by the rule with ID i.
322   */
323   engAppPerAppProdFirstIndexes ame_util.idList;
324   engAppPerAppProdRuleIds ame_util.idList;
325   engAppPerAppProdVariableNames ame_util.stringList;
326   engAppPerAppProdVariableValues ame_util.stringList;
327   /* engRepeatSubstitutions is a new private engine flag indicating whether the substitution handler
328      needs to be called a second time after adhoc insertions and surrogate processing */
329   engRepeatSubstitutions    boolean;
330   /* engAppSub variables store relevant data needed to call the substitution handler a second time. */
331   engAppSubHandlerFirstIndex integer;
332   engAppSubHandlerLastIndex integer;
333   /*
334     The engSt variables contain approval-process state data for AME API code to output.
335     Here are descriptions of each engSt variable.
336     - engStApprovalProcessCompleteYN is a pseudoboolean indicating whether the entire
337       transaction's approval process is complete.
338     - engStApprovers is the current approver list.  It is compact.
339     - engStItemIds, engStItemClasses, engStItemIndexes, and engStItemSources relate approvers in
340       engStApprovers to the items requiring them.  If the item_id and item_class fields of an
341       approverRecord2 in engStApprovers are null, several items require the approver.  (The
342       converse is not true.  The item_id and item_class fields of an approver with the status
343       ame_util.repeatedStatus are not nulled, even though the approver occurs several times.
344       Only the first occurrence of an approver within the applicable repeated-approvers grouping
345       will have null item_id and item_class values, when several items require the approver.)
346       If such an approver is at index i in engStApprovers, and engStItemIndexes(j) = i, then
347       engStItemIds(j) is the ID of an item requiring the approver, engStItemClasses(j) is the
348       corresponding item class, and engStItemSources(j) is the source field indicating which
349       rules require the approver for that item.  (There will be at least two such "rows" in
350       these lists, for an approver in engStApprovers required by multiple items.)
351     - engStProductionIndexes, engStVariableNames, and engStVariableValues store per-approver
352       productions.  A variable-name/value pair is stored at the same index in
353       engStVariableNames and engStVariableValues.  Several productions can be assigned to a
354       single approver, so engStProductionIndexes contains for each production the index of the
355       approverRecord2 in engStApprovers to which the production is assigned.  That is, if
356       engStProductionIndexes(i) = j, then the production in engStVariableNames(i) and
357       engStVariableValues(i) is assigned to engStApprovers(j).
358     - engStTransVariableNames and engStTransVariableValues store per-transaction productions
359       in compact lists.
360     - engStRuleIds, engStRuleDescriptions, engStRuleIndexes, and engStSourceTypes classify
361       approvers in engStApprovers according to their sources (the reasons for their occurrence
362       in the approver list).  When an approver is required by one or more rules, the rules are
363       identified in engStRuleIds.  More particularly:  every approverRecord2 in engStApprovers
364       has at least one row in engStRuleIndexes, engStSourceTypes and engStRuleIds.  If
365       engStRuleIndexes(i) = j, then the values in engStSourceTypes(i) and engStRuleIds(i)
366       pertain to the approver in engStApprovers(j).  Every approver in engStApprovers has only
367       one source value, no matter how many rules required the approver.  That is, if
368       engStRuleIndexes(i1) = j and engStRuleIndexes(i2) = j for i1 <> i2, then
369       engStSourceTypes(i1) = engStSourceTypes(i2).  Some source values indicate that an
370       approver is not required by any rules, but is present for other reasons.  In such cases,
371       if the approver is at index i and engStSourceTypes(j) = i, then engStRuleIds(j) is null.
372     - engStItemAppProcesscompleteYN is compact.  It stores the approval-process status per item.
373       It is ordered so that the approval-process status of engItemIds(i) is
374       engStItemAppProcessCompleteYN(i).
375   */
376   engStApprovalProcessCompleteYN ame_util.charType;
377   engStApprovers ame_util.approversTable2;
378   /* This global variable stores the approver tree */
379   engStApproversTree ame_util.approversTreeTable;
380   engStItemClasses ame_util.stringList;
381   engStItemIds ame_util.stringList;
382   engStItemIndexes ame_util.idList;
383   engStItemSources ame_util.longStringList;
384   engStProductionIndexes ame_util.idList;
385   /* Following two global variables to store repeated indexes */
386   engStRepeatedIndexes    ame_util.idList;
387   engStRepeatedAppIndexes ame_util.idList;
388   engStRuleDescriptions ame_util.stringList;
389   engStRuleIds ame_util.idList;
390   engStRuleIndexes ame_util.idList;
391   engStSourceTypes ame_util.stringList;
392   /* Following two global variables store the list of suspended items */
393   engStSuspendedItems ame_util.stringList;
394   engStSuspendedItemClasses ame_util.stringList;
395   engStVariableNames ame_util.stringList;
396   engStVariableValues ame_util.stringList;
397   engStProductionsTable ame_util2.productionsTable;
398   engStItemAppProcessCompleteYN ame_util.charList;
399   engStInsertionIndexes ame_util.idList;
400   engInsertionOrderList ame_util.idList;
401     /*eng deviation list*/
402   engDeviationResultList ame_approver_deviation_pkg.deviationReasonList;
403   engInsertionReasonList ame_util.stringList;
404   engInsertionDateList ame_util.dateList;
405   engSuppressionDateList ame_util.dateList;
406   engSupperssionReasonList ame_util.stringList;
407   engTempReason varchar2(50);
408   engTempDate   date;
409   engRepSubFlag ame_util.charType;
410   engSATOFlag ame_util.charType;
411   /*************************************************************************************
412   forward declarations of private functions
413   *************************************************************************************/
414   /******************************** boolean functions *********************************/
415   /*
416     conditionIsSatisfied assumes that itemIndexIn indexes an item ID in engItemIds, and
417     that this item is of the same item class as that of the attribute used by the
418     condition with ID conditionIdIn.
419   */
420   function conditionIsSatisfied(conditionIdIn in integer,
421                                 itemClassIdIn in integer,
422                                 itemIndexIn in integer) return boolean;
423   /********************************* fetch functions **********************************/
424   function fetchAmeApplicationId(fndApplicationIdIn in integer,
425                                  transactionTypeIdIn in varchar2 default null) return integer;
426   /********************************** get functions ***********************************/
427   function getItemIndex(itemClassIdIn in integer,
428                         itemIdIn in varchar2) return integer;
429   function getItemOffset(itemClassIdIn in integer,
430                          itemIdIn in varchar2) return integer;
431   /********************************** sort functions **********************************/
432   /* compareApplicableRules is a subroutine of the sortApplicableRules procedure. */
433   function compareApplicableRules(index1In in integer,
434                                   index2In in integer,
435                                   compareActionTypesIn in boolean) return boolean;
436   function getTestVariantAttValue(attributeIdIn in integer,
437                                  itemClassIdIn  in integer,
438                                  itemIdIn       in varchar2) return number;
439   function isVariant(attributeIdIn in integer) return boolean;
440   /*************************************************************************************
441   forward declarations of private procedures
442   *************************************************************************************/
443   procedure addApproverToTree
444     (approverRecordIn   in            ame_util.approverRecord2
445     ,approverIndexIn    in            integer
446     ,approverLocationIn in            boolean default ame_util.lastAmongEquals);
447   procedure calculateApproverOrderNumbers;
448   procedure compactEngAppLists(compactPrioritiesIn in boolean,
449                                compactActionTypeIdsIn in boolean,
450                                compactParametersIn in boolean);
451   procedure doPerItemRuleEvaluation(itemClassIdIn in integer,
452                                     itemIndexIn in varchar2);
453   procedure doStrictHeaderRuleEvaluation(itemClassIndexIn in integer,
454                                          itemClassIdIn in integer);
455   procedure doWeakHeaderRuleEvaluation(itemClassIndexIn in integer,
456                                        itemClassIdIn in integer);
457   procedure evaluateRules;
458   procedure fetchActiveConditionUsages;
459   procedure fetchApplicableActions;
460   procedure fetchAttributeValues(fetchInactivesIn in boolean);
461   procedure fetchConfigVars;
462   procedure fetchDeletedApprovers;
463   procedure fetchFndApplicationId(applicationIdIn in integer,
464                                   fndApplicationIdOut out nocopy integer,
465                                   transactionTypeIdOut out nocopy varchar2);
466   procedure fetchInsertedApprovers;
467   procedure fetchItemClassData;
468   procedure fetchOldApprovers;
469   procedure fetchRuntimeGroup(groupIdIn in integer);
470   procedure finalizeTree(parentIndexIn          in integer default 1
471                         ,maximumOrderOut       out nocopy integer
472                         ,approvalStatusOut     out nocopy integer
473                         ,rejectedItemsExistOut out nocopy boolean);
474   procedure getLMCondition(ruleIdIn in integer,
475                            parameterOneOut out nocopy varchar2,
476                            parameterTwoOut out nocopy varchar2);
477   procedure insertIntoTransApprovalHistory
478               (transactionIdIn  ame_trans_approval_history.transaction_id%type
479               ,applicationIdIn  ame_trans_approval_history.application_id%type
480               ,orderNumberIn    ame_trans_approval_history.order_number%type
481               ,nameIn           ame_trans_approval_history.name%type
482               ,appCategoryIn    ame_trans_approval_history.approver_category%type
483               ,itemClassIn      ame_trans_approval_history.item_class%type
484               ,itemIdIn         ame_trans_approval_history.item_id%type
485               ,actionTypeIdIn   ame_trans_approval_history.action_type_id%type
486               ,authorityIn      ame_trans_approval_history.authority%type
487               ,statusIn         ame_trans_approval_history.status%type
488               ,grpOrChainIdIn   ame_trans_approval_history.group_or_chain_id%type
489               ,occurrenceIn     ame_trans_approval_history.occurrence%type
490               ,apiInsertionIn   ame_trans_approval_history.api_insertion%type
491               ,memberOrderNumberIn ame_trans_approval_history.member_order_number%type
492               ,notificationIdIn ame_trans_approval_history.notification_id%type
493               ,userCommentsIn   ame_trans_approval_history.user_comments%type
494               ,dateClearedIn    ame_trans_approval_history.date_cleared%type
495               ,historyTypeIn    varchar2);
496   procedure parseForwardingBehaviors(forwardingBehaviorsIn in varchar2);
497   procedure parsePriorityModes(priorityModesIn in varchar2);
498   procedure populateEngStVariables;
499   procedure prepareItemData(approverIndexesIn  in ame_util.idList default ame_util.emptyIdList
500                            ,itemIndexesOut     out nocopy ame_util.idList
501                            ,itemItemClassesOut out nocopy ame_util.stringList
502                            ,itemIdsOut         out nocopy ame_util.stringList
503                            ,itemSourcesOut     out nocopy ame_util.longStringList);
504   procedure preparePerApproverProductions
505            (approverIndexesIn    in ame_util.idList default ame_util.emptyIdList
506            ,itemIndexesIn        in ame_util.idList default ame_util.emptyIdList
507            ,itemSourcesIn        in ame_util.longStringList default ame_util.emptyLongStringList
508            ,prodIndexesOut      out nocopy ame_util.idList
509            ,productionNamesOut  out nocopy ame_util.stringList
510            ,productionValuesOut out nocopy ame_util.stringList);
511   procedure prepareRuleData;
512   procedure processActionType;
513   procedure processAdHocInsertions;
514   procedure processSuppressions;
515   procedure processRelativePriorities;
516   procedure processRepeatedApprovers;
517   procedure processRules(processOnlyProductionsIn in boolean default false);
518   procedure processUnresponsiveApprovers;
519   procedure populateInsertionIndexes(indexIn in integer
520                                     ,insertionOrderIn in integer);
521   procedure repeatSubstitutions;
522   procedure setContext(isTestTransactionIn in boolean,
523                        isLocalTransactionIn in boolean,
524                        fetchConfigVarsIn in boolean,
525                        fetchOldApproversIn in boolean,
526                        fetchInsertionsIn in boolean,
527                        fetchDeletionsIn in boolean,
528                        fetchAttributeValuesIn in boolean,
529                        fetchInactiveAttValuesIn in boolean,
530                        processProductionActionsIn in boolean,
531                        processProductionRulesIn in boolean,
532                        updateCurrentApproverListIn in boolean,
533                        updateOldApproverListIn in boolean,
534                        processPrioritiesIn in boolean,
535                        prepareItemDataIn in boolean,
536                        prepareRuleIdsIn in boolean,
537                        prepareRuleDescsIn in boolean,
538                        prepareApproverTreeIn in boolean default false,
539                        transactionIdIn in varchar2,
540                        ameApplicationIdIn in integer default null,
541                        fndApplicationIdIn in integer default null,
542                        transactionTypeIdIn in varchar2 default null);
543   procedure setInsertedApprovalStatus(currentApproverIndexIn in integer
544                                       ,approvalStatusIn in varchar2);
545 
546   procedure sortApplicableRules(sortByActionTypeIn in boolean);
547   procedure updateOldApproverList;
548   /*************************************************************************************
549   functions
550   *************************************************************************************/
551   /******************************** boolean functions *********************************/
552   function approversMatch(approverRecord1In in ame_util.approverRecord2,
553                           approverRecord2In in ame_util.approverRecord2) return boolean as
554     begin
555       /* The following if statement's conditions are in decreasing order of specificity for efficiency. */
556       if(approverRecord1In.name = approverRecord2In.name and
557          approverRecord1In.occurrence = approverRecord2In.occurrence and
558          approverRecord1In.group_or_chain_id = approverRecord2In.group_or_chain_id and
559          approverRecord1In.action_type_id = approverRecord2In.action_type_id and
560          approverRecord1In.item_id = approverRecord2In.item_id and
561          approverRecord1In.item_class = approverRecord2In.item_class) then
562         return(true);
563       end if;
564       return(false);
565       exception
566         when others then
567           ame_util.runtimeException(packageNameIn => 'ame_engine',
568                                     routineNameIn => 'approversMatch',
569                                     exceptionNumberIn => sqlcode,
570                                     exceptionStringIn => sqlerrm);
571           raise;
572           return(false);
573     end approversMatch;
574   function checkAttributeVariant(attributeIdIn in integer) return varchar2 as
575     begin
576       if (engAttributeNames(attributeIdIn)  = ame_util.jobLevelStartingPointAttribute or
577           engAttributeNames(attributeIdIn)  = ame_util.nonDefStartingPointPosAttr or
578           engAttributeNames(attributeIdIn)  = ame_util.nonDefPosStructureAttr or
579           engAttributeNames(attributeIdIn)  = ame_util.supStartingPointAttribute or
580           engAttributeNames(attributeIdIn)  = ame_util.firstStartingPointAttribute or
581           engAttributeNames(attributeIdIn)  = ame_util.secondStartingPointAttribute ) then
582         return(ame_util.booleanTrue);
583       else
584         return(ame_util.booleanFalse);
585       end if;
586     end;
587   function getVariantAttributeValue(attributeIdIn in integer,
588                                     itemClassIn in varchar2,
589                                     itemIdIn in varchar2) return number as
590     dynamicCursor integer;
591     dynamicQuery ame_util.longestStringType;
592     rowsFound integer;
593     tempAttributeValues1 dbms_sql.varchar2_table;
594     begin
595       if engIsTestTransaction then
596         if checkAttributeVariant(attributeIdIn) = ame_util.booleanTrue then
597           return (getTestVariantAttValue(attributeIdIn => attributeIdIn
598                                         ,itemClassIdIn => getItemClassId(itemClassNameIn => itemClassIn)
599                                         ,itemIdIn      => itemIdIn));
600         else
601           return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
602         end if;
603       end if;
604       /* fetch the value for real transactions using the dynamic query */
605       if(engAttributeVariant.exists(attributeIdIn))then
606         dynamicQuery := ame_util.removeReturns(stringIn => engAttributeQueries(attributeIdIn),
607                                                replaceWithSpaces => true);
608         dynamicCursor := dbms_sql.open_cursor;
609         dbms_sql.parse(dynamicCursor,
610                        dynamicQuery,
611                        dbms_sql.native);
612         if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
613           dbms_sql.bind_variable(dynamicCursor,
614                                  ame_util.transactionIdPlaceholder,
615                                  engTransactionId,
616                                  50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
617         end if;
618         if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
619           dbms_sql.bind_variable(dynamicCursor,
620                                  ame_util2.itemClassPlaceHolder,
621                                  itemClassIn,
622                                  50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
623         end if;
624         if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
625           dbms_sql.bind_variable(dynamicCursor,
626                                  ame_util2.itemIdPlaceHolder,
627                                  itemIdIn,
628                                  50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
629         end if;
630         dbms_sql.define_array(dynamicCursor,
631                               1,
632                               tempAttributeValues1,
633                               ame_util.attributeValueTypeLength,
634                               1);
635         rowsFound := dbms_sql.execute(dynamicCursor);
636         loop
637           rowsFound := dbms_sql.fetch_rows(dynamicCursor);
638           dbms_sql.column_value(dynamicCursor,
639                                 1,
640                                 tempAttributeValues1);
641           exit when rowsFound < 2;
642         end loop;
643         dbms_sql.close_cursor(dynamicCursor);
644         return(tempAttributeValues1(1));
645       else
646       /* this is not a variant attribute value would have fetched already in
647          fetchAttributeValues return the same */
648         return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
649       end if;
650       exception
651         when others then
652           ame_util.runtimeException(packageNameIn => 'ame_engine',
653                                     routineNameIn => 'getVariantAttributeValue',
654                                     exceptionNumberIn => sqlcode,
655                                     exceptionStringIn => sqlerrm);
656           raise;
657           return null;
658     end getVariantAttributeValue;
659 /*  function getVariantAttributeValue2(attributeIdIn in integer,
660                                      itemClassIn in varchar2,
661                                      itemIdIn in varchar2) return number as
662     begin
663       return(getVariantAttributeValue(attributeIdIn => attributeIdIn,
664                                       itemClassIn => itemClassIn,
665                                       itemIdIn => itemIdIn));
666       exception
667         when others then
668           ame_util.runtimeException(packageNameIn => 'ame_engine',
669                                     routineNameIn => 'getVariantAttributeValue2',
670                                     exceptionNumberIn => sqlcode,
671                                     exceptionStringIn => sqlerrm);
672           raise;
673           return null;
674     end getVariantAttributeValue2;*/
675   function conditionIsSatisfied(conditionIdIn in integer,
676                                 itemClassIdIn in integer,
677                                 itemIndexIn in integer) return boolean as
678     attributeId integer;
679     attributeNumberValue number;
680     attributeType ame_attributes.attribute_type%type;
681     attributeTypeException exception;
682     attributeValue1 ame_util.attributeValueType;
683     attributeValue2 ame_util.attributeValueType;
684     attributeValue3 ame_util.attributeValueType;
685     attributeValueDate date;
686     errorCode integer;
687     errorMessage ame_util.longestStringType;
688     headerLevelCondition boolean;
689     includeLowerLimit ame_conditions.include_lower_limit%type;
690     includeUpperLimit ame_conditions.include_upper_limit%type;
691     parameterOne ame_conditions.parameter_one%type;
692     parameterOneDate date;
693     parameterOneNumber number;
694     parameterThree ame_conditions.parameter_three%type;
695     parameterTwo ame_conditions.parameter_two%type;
696     parameterTwoDate date;
697     parameterTwoNumber number;
698     begin
699       /* Check whether the condition is on a header-level attribute. */
700       if(engItemClassNames(engItemClassIndexes(engAttributeItemClassIds(engACAttributeIds(conditionIdIn)))) =
701            ame_util.headerItemClassName) then
702         headerLevelCondition := true;
703       else
704         headerLevelCondition := false;
705       end if;
706       attributeId := engACAttributeIds(conditionIdIn);
707       /* Check for a cached value, for conditions on header-level attributes. */
708       if (headerLevelCondition and
709            not engIsTestTransaction and
710            not engAttributeVariant.exists(attributeId) and
711            engHeaderConditionValues.exists(conditionIdIn)) then
712         /* The value is cached. */
713         if(engHeaderConditionValues(conditionIdIn) = ame_util.booleanTrue) then
714           return(true);
715         end if;
716         return(false);
717       end if;
718       /* The value must be calculated. */
719       attributeType := engAttributeTypes(attributeId);
720       if(attributeType <> ame_util.stringAttributeType) then
721         includeLowerLimit := engACIncludeLowerLimits(conditionIdIn);
722         includeUpperLimit := engACIncludeUpperLimits(conditionIdIn);
723         parameterOne := engACParameterOnes(conditionIdIn);
724         parameterTwo := engACParameterTwos(conditionIdIn);
725         parameterThree := engACParameterThrees(conditionIdIn);
726       end if;
727       if(headerLevelCondition) then
728         if isVariant(attributeId) then
729           attributeValue1 :=  getVariantAttributeValue
730                                  (attributeIdIn => attributeId,
731                                   itemClassIn   => getItemClassName(itemClassIdIn => itemClassIdIn),
732                                   itemIdIn      => engItemIds(itemIndexIn));
733         else
734           getHeaderAttValues1(attributeIdIn => attributeId,
735                               attributeValue1Out => attributeValue1,
736                               attributeValue2Out => attributeValue2,
737                               attributeValue3Out => attributeValue3);
738         end if;
739       else
740         getItemAttValues3(attributeIdIn => attributeId,
741                           itemIndexIn => itemIndexIn,
742                           attributeValue1Out => attributeValue1,
743                           attributeValue2Out => attributeValue2,
744                           attributeValue3Out => attributeValue3);
745       end if;
746       /* numbers and currencies */
747       if(attributeType = ame_util.numberAttributeType or
748          attributeType = ame_util.currencyAttributeType) then
749         /* First handle the case of a null value. */
750         if(attributeValue1 is null) then
751           if(parameterOne is null and
752              parameterTwo is null) then
753             if(headerLevelCondition) then
754               engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
755             end if;
756             return(true);
757           else
758             if(headerLevelCondition) then
759               engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
760             end if;
761             return(false);
762           end if;
763         end if;
764         /* Now handle the other cases. */
765         if(attributeType = ame_util.currencyAttributeType and
766         /* Issue 6 of the Bug list bug (4094080) */
767         /* modified form parameterThree <> attributeValue3 to */
768         /* parameterThree <> attributeValue2 */
769            parameterThree <> attributeValue2) then
770           attributeNumberValue :=
771             ame_util.convertCurrency(fromCurrencyCodeIn => attributeValue2,
772                                      toCurrencyCodeIn => parameterThree,
773                                      conversionTypeIn => attributeValue3,
774                                      amountIn => fnd_number.canonical_to_number(canonical => attributeValue1),
775                                      dateIn => engEffectiveRuleDate,
776                                      applicationIdIn => engAmeApplicationId);
777         else
778           attributeNumberValue := fnd_number.canonical_to_number(canonical => attributeValue1);
779         end if;
780         parameterOneNumber := fnd_number.canonical_to_number(canonical => parameterOne);
781         parameterTwoNumber := fnd_number.canonical_to_number(canonical => parameterTwo);
782         if(includeLowerLimit = ame_util.booleanTrue and
783            attributeNumberValue = parameterOneNumber) then
784           if(headerLevelCondition) then
785             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
786           end if;
787           return(true);
788         end if;
789         if(includeUpperLimit = ame_util.booleanTrue and
790            attributeNumberValue = parameterTwoNumber) then
791           if(headerLevelCondition) then
792             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
793           end if;
794           return(true);
795         end if;
796         if((parameterOneNumber is null and attributeNumberValue < parameterTwoNumber) or
797            (parameterOneNumber < attributeNumberValue and parameterTwoNumber is null) or
798            (parameterOneNumber < attributeNumberValue and attributeNumberValue < parameterTwoNumber)) then
799           if(headerLevelCondition) then
800             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
801           end if;
802           return(true);
803         end if;
804       /* dates */
805       elsif(attributeType = ame_util.dateAttributeType) then
806         attributeValueDate := ame_util.versionStringToDate(stringDateIn => attributeValue1);
807         parameterOneDate := ame_util.versionStringToDate(stringDateIn => parameterOne);
808         parameterTwoDate := ame_util.versionStringToDate(stringDateIn => parameterTwo);
809         /* First handle the case of a null value. */
810         if(attributeValue1 is null) then
811           if(parameterOne is null and
812              parameterTwo is null) then
813             if(headerLevelCondition) then
814               engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
815             end if;
816             return(true);
817           else
818             if(headerLevelCondition) then
819               engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
820             end if;
821             return(false);
822           end if;
823         end if;
824         /* Now handle the other cases. */
825         if(includeLowerLimit = ame_util.booleanTrue and
826            attributeValueDate = parameterOneDate) then
827           if(headerLevelCondition) then
828             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
829           end if;
830           return(true);
831         end if;
832         if(includeUpperLimit = ame_util.booleanTrue and
833            attributeValueDate = parameterTwoDate) then
834           if(headerLevelCondition) then
835             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
836           end if;
837           return(true);
838         end if;
839         if((parameterOneDate is null and attributeValueDate < parameterTwoDate) or
840            (parameterOneDate < attributeValueDate and parameterTwoDate is null) or
841            (parameterOneDate < attributeValueDate and attributeValueDate < parameterTwoDate)) then
842           if(headerLevelCondition) then
843             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
844           end if;
845           return(true);
846         end if;
847       /* booleans */
848       elsif(attributeType = ame_util.booleanAttributeType) then
849         if((attributeValue1 is null and
850             parameterOne is null) or
851            attributeValue1 = parameterOne) then
852           if(headerLevelCondition) then
853             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
854           end if;
855           return(true); /* If both pseudo-booleans are null, the condition applies. */
856         end if;
857         return(false);
858       /* strings */
859       elsif(attributeType = ame_util.stringAttributeType) then
860         /* Note that if the attribute value and a string value are both null, the condition applies. */
861         for stringValueIndex in
862           engACStringValueFirstIndexes(conditionIdIn) ..
863           (engACStringValueFirstIndexes(conditionIdIn) + engACStringValueCounts(conditionIdIn) - 1) loop
864           if((attributeValue1 is null and engACStringValues(stringValueIndex) is null) or
865              attributeValue1 = engACStringValues(stringValueIndex)) then
866             if(headerLevelCondition) then
867               engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
868             end if;
869             return(true);
870           end if;
871         end loop;
872       else
873         raise attributeTypeException;
874       end if;
875       /* The condition is not satisfied. */
876       if(headerLevelCondition) then
877         engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
878       end if;
879       return(false);
880       exception
881         when attributeTypeException then
882           errorCode := -20001;
883           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
884                                               messageNameIn => 'AME_400113_ENG_ATTR_UNREG_TYPE');
885           ame_util.runtimeException(packageNameIn => 'ame_engine',
886                                     routineNameIn => 'conditionIsSatisfied',
887                                     exceptionNumberIn => errorCode,
888                                     exceptionStringIn => errorMessage);
889           raise_application_error(errorCode,
890                                   errorMessage);
891           return(null);
892         when others then
893           ame_util.runtimeException(packageNameIn => 'ame_engine',
894                                     routineNameIn => 'conditionIsSatisfied',
895                                     exceptionNumberIn => sqlcode,
896                                     exceptionStringIn => sqlerrm);
897           raise;
898           return(null);
899     end conditionIsSatisfied;
900   function evalPrioritiesPerItem return boolean as
901     begin
902       return(engEvalPrioritiesPerItem);
903       exception
904         when others then
905           ame_util.runtimeException(packageNameIn => 'ame_engine',
906                                     routineNameIn => 'evalPrioritiesPerItem',
907                                     exceptionNumberIn => sqlcode,
908                                     exceptionStringIn => sqlerrm);
909           raise;
910           return(null);
911     end evalPrioritiesPerItem;
912   function insertionExists(orderTypeIn in varchar2,
913                            parameterIn in varchar2) return boolean as
914     begin
915       for i in 1 .. engInsertionOrderTypeList.count loop
916         if(engInsertionOrderTypeList(i) = orderTypeIn and
917            engInsertionParameterList(i) = parameterIn) then
918           return(true);
919         end if;
920       end loop;
921       return(false);
922       exception
923         when others then
924           ame_util.runtimeException(packageNameIn => 'ame_engine',
925                                     routineNameIn => 'insertionExists',
926                                     exceptionNumberIn => sqlcode,
927                                     exceptionStringIn => sqlerrm);
928           raise;
929           return(null);
930     end insertionExists;
931   function isLocalTransaction return boolean as
932     begin
933       return(engIsLocalTransaction);
934       exception
935         when others then
936           ame_util.runtimeException(packageNameIn => 'ame_engine',
937                                     routineNameIn => 'isLocalTransaction',
938                                     exceptionNumberIn => sqlcode,
939                                     exceptionStringIn => sqlerrm);
940           raise;
941           return(null);
942     end isLocalTransaction;
943   function isStaticAttUsage(attributeIdIn in integer) return boolean as
944     begin
945       if(engAttributeIsStatics(attributeIdIn) = ame_util.booleanTrue) then
946         return(true);
947       end if;
948       return(false);
949       exception
950         when others then
951           ame_util.runtimeException(packageNameIn => 'ame_engine',
952                                     routineNameIn => 'isStaticAttUsage',
953                                     exceptionNumberIn => sqlcode,
954                                     exceptionStringIn => sqlerrm);
955           raise;
956           return(false);
957     end isStaticAttUsage;
958   function isTestTransaction return boolean as
959     begin
960       return(engIsTestTransaction);
961       exception
962         when others then
963           ame_util.runtimeException(packageNameIn => 'ame_engine',
964                                     routineNameIn => 'isTestTransaction',
965                                     exceptionNumberIn => sqlcode,
966                                     exceptionStringIn => sqlerrm);
967           raise;
968           return(null);
969     end isTestTransaction;
970   function isVariant(attributeIdIn in integer) return boolean as
971   begin
972     if checkAttributeVariant(attributeIdIn) = ame_util.booleanTrue then
973       if engIsTestTransaction then
974         return true;
975       elsif engAttributeVariant.exists(attributeIdIn) then
976         return true;
977       end if;
978     end if;
979     return false;
980     exception
981       when others then
982         ame_util.runtimeException(packageNameIn => 'ame_engine',
983                                   routineNameIn => 'isVariant',
984                                   exceptionNumberIn => sqlcode,
985                                   exceptionStringIn => sqlerrm);
986         raise;
987         return(null);
988   end isVariant;
989   function processPriorities return boolean as
990     begin
991       return(engProcessPriorities);
992       exception
993         when others then
994           ame_util.runtimeException(packageNameIn => 'ame_engine',
995                                     routineNameIn => 'processPriorities',
996                                     exceptionNumberIn => sqlcode,
997                                     exceptionStringIn => sqlerrm);
998           raise;
999           return(null);
1000     end processPriorities;
1001   function processProductionActions return boolean as
1002     begin
1003       return(engProcessProductionActions);
1004       exception
1005         when others then
1006           ame_util.runtimeException(packageNameIn => 'ame_engine',
1007                                     routineNameIn => 'processProductionActions',
1008                                     exceptionNumberIn => sqlcode,
1009                                     exceptionStringIn => sqlerrm);
1010           raise;
1011           return(null);
1012     end processProductionActions;
1013   function processProductionRules return boolean as
1014     begin
1015       return(engProcessProductionRules);
1016       exception
1017         when others then
1018           ame_util.runtimeException(packageNameIn => 'ame_engine',
1019                                     routineNameIn => 'processProductionRules',
1020                                     exceptionNumberIn => sqlcode,
1021                                     exceptionStringIn => sqlerrm);
1022           raise;
1023           return(null);
1024     end processProductionRules;
1025   /********************************* fetch functions **********************************/
1026   function fetchAmeApplicationId(fndApplicationIdIn in integer,
1027                                  transactionTypeIdIn in varchar2 default null) return integer as
1028     ameApplicationId integer;
1029     begin
1030       select application_id
1031         into ameApplicationId
1032         from ame_calling_apps
1033         where
1034           fnd_application_id = fndApplicationIdIn and
1035           ((transactionTypeIdIn is null and transaction_type_id is null) or
1036            (transaction_type_id = transactionTypeIdIn)) and
1037           /* Don't use engEffectiveRuleDate here. */
1038           sysdate between
1039             start_date and
1040             nvl(end_date - ame_util.oneSecond, sysdate) and
1041           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
1042       return(ameApplicationId);
1043       exception
1044         when others then
1045           ame_util.runtimeException(packageNameIn => 'ame_engine',
1046                                     routineNameIn => 'fetchAmeApplicationId',
1047                                     exceptionNumberIn => sqlcode,
1048                                     exceptionStringIn => sqlerrm);
1049           raise;
1050           return(null);
1051     end fetchAmeApplicationId;
1052   /********************************** get functions ***********************************/
1053   function getActionTypeChainOrderMode(actionTypeIdIn in integer) return varchar2 as
1054     begin
1055       return(engActionTypeChainOrderModes(actionTypeIdIn));
1056       exception
1057         when others then
1058           ame_util.runtimeException(packageNameIn => 'ame_engine',
1059                                     routineNameIn => 'getActionTypeChainOrderMode',
1060                                     exceptionNumberIn => sqlcode,
1061                                     exceptionStringIn => sqlerrm);
1062           raise;
1063           return(null);
1064     end getActionTypeChainOrderMode;
1065   function getActionTypeId(actionTypeNameIn in varchar2) return integer as
1066     tempIndex integer;
1067     begin
1068       tempIndex := engActionTypeNames.first;
1069       while(tempIndex is not null) loop
1070         if(engActionTypeNames(tempIndex) = actionTypeNameIn) then
1071           return(tempIndex);
1072         end if;
1073         tempIndex := engActionTypeNames.next(tempIndex);
1074       end loop;
1075       return(null);
1076       exception
1077         when others then
1078           ame_util.runtimeException(packageNameIn => 'ame_engine',
1079                                     routineNameIn => 'getActionTypeId',
1080                                     exceptionNumberIn => sqlcode,
1081                                     exceptionStringIn => sqlerrm);
1082           raise;
1083           return(null);
1084     end getActionTypeId;
1085   function getActionTypeName(actionTypeIdIn in integer) return varchar2 as
1086     begin
1087       if(actionTypeIdIn = ame_util.nullInsertionActionTypeId or actionTypeIdIn = -2 ) then
1088         return(null);
1089       end if;
1090       return(engActionTypeNames(actionTypeIdIn));
1091       exception
1092         when others then
1093           ame_util.runtimeException(packageNameIn => 'ame_engine',
1094                                     routineNameIn => 'getActionTypeName',
1095                                     exceptionNumberIn => sqlcode,
1096                                     exceptionStringIn => sqlerrm);
1097           raise;
1098           return(null);
1099     end getActionTypeName;
1100   function getActionTypeOrderNumber(actionTypeIdIn in integer) return integer as
1101     begin
1102       return(engActionTypeOrderNumbers(actionTypeIdIn));
1103       exception
1104         when others then
1105           ame_util.runtimeException(packageNameIn => 'ame_engine',
1106                                     routineNameIn => 'getActionTypeOrderNumber',
1107                                     exceptionNumberIn => sqlcode,
1108                                     exceptionStringIn => sqlerrm);
1109           raise;
1110           return(null);
1111     end getActionTypeOrderNumber;
1112   function getActionTypePackageName(actionTypeIdIn in integer) return varchar2 as
1113     begin
1114       return(engActionTypePackageNames(actionTypeIdIn));
1115       exception
1116         when others then
1117           ame_util.runtimeException(packageNameIn => 'ame_engine',
1118                                     routineNameIn => 'getActionTypePackageName',
1119                                     exceptionNumberIn => sqlcode,
1120                                     exceptionStringIn => sqlerrm);
1121           raise;
1122           return(null);
1123     end getActionTypePackageName;
1124   function getActionTypeUsage(actionTypeIdIn in integer) return integer as
1125     begin /* getActionTypeUsage returns the rule type that uses the input action type. */
1126       return(engActionTypeUsages(actionTypeIdIn));
1127       exception
1128         when others then
1129           ame_util.runtimeException(packageNameIn => 'ame_engine',
1130                                     routineNameIn => 'getActionTypeUsage',
1131                                     exceptionNumberIn => sqlcode,
1132                                     exceptionStringIn => sqlerrm);
1133           raise;
1134           return(null);
1135     end getActionTypeUsage;
1136   function getActionTypeVotingRegime(actionTypeIdIn in integer) return varchar2 as
1137     begin
1138       if(actionTypeIdIn = ame_util.nullInsertionActionTypeId or actionTypeIdIn = -2 ) then
1139         return(null);
1140       end if;
1141       return(engActionTypeVotingRegimes(actionTypeIdIn));
1142       exception
1143         when others then
1144           ame_util.runtimeException(packageNameIn => 'ame_engine',
1145                                     routineNameIn => 'getActionTypeVotingRegime',
1146                                     exceptionNumberIn => sqlcode,
1147                                     exceptionStringIn => sqlerrm);
1148           raise;
1149           return(null);
1150     end getActionTypeVotingRegime;
1151   function getAmeApplicationId return integer as
1152     begin
1153       return(engAmeApplicationId);
1154       exception
1155         when others then
1156           ame_util.runtimeException(packageNameIn => 'ame_engine',
1157                                     routineNameIn => 'getAmeApplicationId',
1158                                     exceptionNumberIn => sqlcode,
1159                                     exceptionStringIn => sqlerrm);
1160           raise;
1161           return(null);
1162     end getAmeApplicationId;
1163   function getApprovalProcessCompleteYN return varchar2 as
1164     begin
1165       return(engStApprovalProcessCompleteYN);
1166       exception
1167         when others then
1168           ame_util.runtimeException(packageNameIn => 'ame_engine',
1169                                     routineNameIn => 'getApprovalProcessCompleteYN',
1170                                     exceptionNumberIn => sqlcode,
1171                                     exceptionStringIn => sqlerrm);
1172           raise;
1173           return(null);
1174     end getApprovalProcessCompleteYN;
1175   function getAttributeIdByName(attributeNameIn in varchar2) return integer as
1176     errorCode integer;
1177     errorMessage ame_util.longestStringType;
1178     notFoundException exception;
1179     tempIndex integer;
1180     begin
1181       tempIndex := engAttributeNames.first;
1182       loop
1183         if(tempIndex is null) then
1184           raise notFoundException;
1185         end if;
1186         if(engAttributeNames(tempIndex) = attributeNameIn) then
1187           return(tempIndex);
1188         end if;
1189         tempIndex := engAttributeNames.next(tempIndex);
1190       end loop;
1191       exception
1192         when notFoundException then
1193           errorCode := -20001;
1194           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1195                                               messageNameIn   => 'AME_400680_NO_ID_FOR_ATTR',
1196                                               tokenNameOneIn  => 'ATTRIBUTE_NAME',
1197                                               tokenValueOneIn => attributeNameIn);
1198           ame_util.runtimeException(packageNameIn => 'ame_engine',
1199                                     routineNameIn => 'getAttributeIdByName',
1200                                     exceptionNumberIn => errorCode,
1201                                     exceptionStringIn => errorMessage);
1202           raise_application_error(errorCode, errorMessage);
1203           return(null);
1204         when others then
1205           ame_util.runtimeException(packageNameIn => 'ame_engine',
1206                                     routineNameIn => 'getAttributeIdByName',
1207                                     exceptionNumberIn => sqlcode,
1208                                     exceptionStringIn => attributeNameIn || ':  ' || sqlerrm);
1209           raise;
1210           return(null);
1211     end getAttributeIdByName;
1212   function getAttributeName(attributeIdIn in integer) return varchar2 as
1213     begin
1214       return(engAttributeNames(attributeIdIn));
1215       exception
1216         when others then
1217           ame_util.runtimeException(packageNameIn => 'ame_engine',
1218                                     routineNameIn => 'getAttributeName',
1219                                     exceptionNumberIn => sqlcode,
1220                                     exceptionStringIn => sqlerrm);
1221           raise;
1222           return(null);
1223     end getAttributeName;
1224   function getAttributeType(attributeIdIn in integer) return varchar2 as
1225     begin
1226       return(engAttributeTypes(attributeIdIn));
1227       exception
1228         when others then
1229           ame_util.runtimeException(packageNameIn => 'ame_engine',
1230                                     routineNameIn => 'getAttributeType',
1231                                     exceptionNumberIn => sqlcode,
1232                                     exceptionStringIn => sqlerrm);
1233           raise;
1234           return(null);
1235     end getAttributeType;
1236   function getConfigVarValue(configVarNameIn in varchar2) return varchar2 as
1237     errorCode integer;
1238     errorMessage ame_util.longestStringType;
1239     noValueException exception;
1240     begin
1241       for i in 1 .. engConfigVarNames.count loop
1242         if(engConfigVarNames(i) = configVarNameIn) then
1243           return(engConfigVarValues(i));
1244         end if;
1245       end loop;
1246       raise noValueException;
1247       exception
1248         when noValueException then
1249           errorCode := -20001;
1250           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
1251                                               messageNameIn => 'AME_400114_ENG_INV_CON_VAR',
1252                                               tokenNameOneIn => 'CONFIG_VAR',
1253                                               tokenValueOneIn => configVarNameIn);
1254           ame_util.runtimeException(packageNameIn => 'ame_engine',
1255                                     routineNameIn => 'getConfigVarValue',
1256                                     exceptionNumberIn => errorCode,
1257                                     exceptionStringIn => errorMessage);
1258           raise_application_error(errorCode,
1259                                   errorMessage);
1260         when others then
1261           ame_util.runtimeException(packageNameIn => 'ame_engine',
1262                                     routineNameIn => 'getConfigVarValue',
1263                                     exceptionNumberIn => sqlcode,
1264                                     exceptionStringIn => sqlerrm);
1265           raise;
1266           return(null);
1267     end getConfigVarValue;
1268   function getEffectiveRuleDate return date as
1269     begin
1270       return(engEffectiveRuleDate);
1271       exception
1272         when others then
1273           ame_util.runtimeException(packageNameIn => 'ame_engine',
1274                                     routineNameIn => 'getEffectiveRuleDate',
1275                                     exceptionNumberIn => sqlcode,
1276                                     exceptionStringIn => sqlerrm);
1277           raise;
1278           return(null);
1279     end getEffectiveRuleDate;
1280   function getFndApplicationId return integer as
1281     begin
1282       return(engFndApplicationId);
1283       exception
1284         when others then
1285           ame_util.runtimeException(packageNameIn => 'ame_engine',
1286                                     routineNameIn => 'getFndApplicationId',
1287                                     exceptionNumberIn => sqlcode,
1288                                     exceptionStringIn => sqlerrm);
1289           raise;
1290           return(null);
1291     end getFndApplicationId;
1292   function getForwardingBehavior(forwarderTypeIn in varchar2,
1293                                  forwardeeTypeIn in varchar2,
1294                                  approvalStatusIn in varchar2) return varchar2 as
1295     errorCode integer;
1296     errorMessage ame_util.longestStringType;
1297     badArgsException exception;
1298     begin
1299       if(forwarderTypeIn = ame_util.chainOfAuthorityForwarder) then
1300         if(forwardeeTypeIn = ame_util.previousSameChainForwardee) then
1301           if(approvalStatusIn = ame_util.forwardStatus) then
1302             return(engForwardingBehaviors(1));
1303           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1304             return(engForwardingBehaviors(2));
1305           end if;
1306         elsif(forwardeeTypeIn = ame_util.subordSameHierarchyForwardee) then
1307           if(approvalStatusIn = ame_util.forwardStatus) then
1308             return(engForwardingBehaviors(3));
1309           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1310             return(engForwardingBehaviors(4));
1311           end if;
1312         elsif(forwardeeTypeIn = ame_util.alreadyInListForwardee) then
1313           if(approvalStatusIn = ame_util.forwardStatus) then
1314             return(engForwardingBehaviors(5));
1315           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1316             return(engForwardingBehaviors(6));
1317           end if;
1318         end if;
1319       elsif(forwarderTypeIn = ame_util.adHocForwarder) then
1320         if(forwardeeTypein = ame_util.alreadyInListForwardee) then
1321           if(approvalStatusIn = ame_util.forwardStatus) then
1322             return(engForwardingBehaviors(7));
1323           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1324             return(engForwardingBehaviors(8));
1325           end if;
1326         end if;
1327       end if;
1328       raise badArgsException;
1329       exception
1330         when badArgsException then
1331           errorCode := -20001;
1332           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1333                                               messageNameIn => 'AME_400115_ENG_INV_VAL_ARG');
1334           ame_util.runtimeException(packageNameIn => 'ame_engine',
1335                                     routineNameIn => 'getForwardingBehavior',
1336                                     exceptionNumberIn => errorCode,
1337                                     exceptionStringIn => errorMessage);
1338           raise_application_error(errorCode,
1339                                   errorMessage);
1340           return(null);
1341         when others then
1342           ame_util.runtimeException(packageNameIn => 'ame_engine',
1343                                     routineNameIn => 'getForwardingBehavior',
1344                                     exceptionNumberIn => sqlcode,
1345                                     exceptionStringIn => sqlerrm);
1346           raise;
1347           return(null);
1348     end getForwardingBehavior;
1349   function getHandlerActionTypeId return integer as
1350     begin
1351       return(engAppActionTypeIds(engAppHandlerFirstIndex));
1352       exception
1353         when others then
1354           ame_util.runtimeException(packageNameIn => 'ame_engine',
1355                                     routineNameIn => 'getHandlerActionTypeId',
1356                                     exceptionNumberIn => sqlcode,
1357                                     exceptionStringIn => sqlerrm);
1358           raise;
1359           return(null);
1360     end getHandlerActionTypeId;
1361   function getHandlerActionTypeOrderNum return integer as
1362     begin
1363       return(engActionTypeOrderNumbers(engAppActionTypeIds(engAppHandlerFirstIndex)));
1364       exception
1365         when others then
1366           ame_util.runtimeException(packageNameIn => 'ame_engine',
1367                                     routineNameIn => 'getHandlerActionTypeOrderNum',
1368                                     exceptionNumberIn => sqlcode,
1369                                     exceptionStringIn => sqlerrm);
1370           raise;
1371           return(null);
1372     end getHandlerActionTypeOrderNum;
1373   function getHandlerApprovalStatus(approverIn in ame_util.approverRecord2,
1374                                     votingRegimeIn in varchar2 default null,
1375                                     isInsertionapprover in boolean default false) return varchar2 as
1376     l_approvalStatus varchar2(50);
1377     l_action_type_id number;
1378     l_votingRegime  varchar2(100);
1379     l_action_type_name varchar2(100);
1380     begin
1381       for i in 1..engOldApproverList.count loop
1382         if(approversMatch(approverRecord1In => approverIn,
1383                           approverRecord2In => engOldApproverList(i))) then
1384           l_approvalStatus := engOldApproverList(i).approval_status;
1385         end if;
1386       end loop;
1387        if l_approvalStatus is null and (approverIn.action_type_id <> ame_util.nullInsertionActionTypeId and
1388                           approverIn.action_type_id is not null) and
1389                           not isInsertionapprover then
1390         l_action_type_id := approverIn.action_type_id;
1391         l_action_type_name := getActionTypeName(l_action_type_id);
1392         if l_action_type_name not in (ame_util.postApprovalTypeName,ame_util.preApprovalTypeName ) then
1393           l_votingRegime := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => approverIn.action_type_id);
1394         else
1395           l_votingRegime := votingRegimeIn;
1396         end if;
1397         if l_votingRegime = ame_util.firstApproverVoting then
1398           for i in 1..engOldApproverList.count loop
1399             if approverIn.name <> engOldApproverList(i).name and
1400                 approverIn.action_type_id = engOldApproverList(i).action_type_id and
1401                 approverIn.group_or_chain_id = engOldApproverList(i).group_or_chain_id and
1402                 approverIn.item_class = engOldApproverList(i).item_class and
1403                 approverIn.item_id = engOldApproverList(i).item_id and
1404                 engOldApproverList(i).api_insertion <> ame_util.apiInsertion and
1405                 engOldApproverList(i).approval_status in (ame_util.approvedStatus
1406                                                       ,ame_util.beatByFirstResponderStatus
1407                                                       ,ame_util.rejectStatus  ) then
1408                  return(ame_util.beatByFirstResponderStatus);
1409            end if;
1410           end loop;
1411         end if;
1412           return(l_approvalStatus);
1413       else
1414         return(l_approvalStatus);
1415       end if;
1416       return(null);
1417       exception
1418         when others then
1419           ame_util.runtimeException(packageNameIn => 'ame_engine',
1420                                     routineNameIn => 'getHandlerApprovalStatus',
1421                                     exceptionNumberIn => sqlcode,
1422                                     exceptionStringIn => sqlerrm);
1423           raise;
1424           return(null);
1425     end getHandlerApprovalStatus;
1426   function getHandlerAuthority return varchar2 as
1427     errorCode integer;
1428     errorMessage ame_util.longestStringType;
1429     badRuleTypeException exception;
1430     ruleType integer;
1431     begin
1432       ruleType := getHandlerRuleType;
1433       if(ruleType = ame_util.preListGroupRuleType) then
1434         return(ame_util.preApprover);
1435       elsif(ruleType = ame_util.postListGroupRuleType) then
1436         return(ame_util.postApprover);
1437       elsif(ruleType = ame_util.authorityRuleType) then
1438         return(ame_util.authorityApprover);
1439       else
1440         raise badRuleTypeException;
1441       end if;
1442       exception
1443         when badRuleTypeException then
1444           errorCode := -20001;
1445           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1446                                               messageNameIn => 'AME_400681_INV_HANDLER_RUL_TYP');
1447           ame_util.runtimeException(packageNameIn => 'ame_engine',
1448                                     routineNameIn => 'getHandlerAuthority',
1449                                     exceptionNumberIn => errorCode,
1450                                     exceptionStringIn => errorMessage);
1451           raise_application_error(errorCode,
1452                                   errorMessage);
1453           return(null);
1454         when others then
1455           ame_util.runtimeException(packageNameIn => 'ame_engine',
1456                                     routineNameIn => 'getHandlerAuthority',
1457                                     exceptionNumberIn => sqlcode,
1458                                     exceptionStringIn => sqlerrm);
1459           raise;
1460           return(null);
1461     end getHandlerAuthority;
1462   function getHandlerItemClassId return integer as
1463     begin
1464       return(engAppRuleItemClassIds(engAppHandlerFirstIndex));
1465       exception
1466         when others then
1467           ame_util.runtimeException(packageNameIn => 'ame_engine',
1468                                     routineNameIn => 'getHandlerItemClassId',
1469                                     exceptionNumberIn => sqlcode,
1470                                     exceptionStringIn => sqlerrm);
1471           raise;
1472           return(null);
1473     end getHandlerItemClassId;
1474   function getHandlerItemClassName return varchar2 as
1475     begin
1476       return(getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)));
1477       exception
1478         when others then
1479           ame_util.runtimeException(packageNameIn => 'ame_engine',
1480                                     routineNameIn => 'getHandlerItemClassName',
1481                                     exceptionNumberIn => sqlcode,
1482                                     exceptionStringIn => sqlerrm);
1483           raise;
1484           return(null);
1485     end getHandlerItemClassName;
1486   function getHandlerItemClassOrderNumber return integer as
1487     begin
1488       return(engItemClassOrderNumbers(engItemClassIndexes(engAppRuleItemClassIds(engAppHandlerFirstIndex))));
1489       exception
1490         when others then
1491           ame_util.runtimeException(packageNameIn => 'ame_engine',
1492                                     routineNameIn => 'getHandlerItemClassOrderNumber',
1493                                     exceptionNumberIn => sqlcode,
1494                                     exceptionStringIn => sqlerrm);
1495           raise;
1496           return(null);
1497     end getHandlerItemClassOrderNumber;
1498   function getHandlerItemId return varchar2 as
1499     begin
1500       return(engAppAppItemIds(engAppHandlerFirstIndex));
1501       exception
1502         when others then
1503           ame_util.runtimeException(packageNameIn => 'ame_engine',
1504                                     routineNameIn => 'getHandlerItemId',
1505                                     exceptionNumberIn => sqlcode,
1506                                     exceptionStringIn => sqlerrm);
1507           raise;
1508           return(null);
1509     end getHandlerItemId;
1510   function getHandlerItemOrderNumber return integer as
1511     begin
1512       if(getItemClassParMode(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)) =
1513          ame_util.parallelItems) then
1514         return(1);
1515       else /* The parallelization modes is ame_util.serialItems. */
1516         return(1 + getItemOffset(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex),
1517                                  itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex)));
1518       end if;
1519       exception
1520         when others then
1521           ame_util.runtimeException(packageNameIn => 'ame_engine',
1522                                     routineNameIn => 'getHandlerItemOrderNumber',
1523                                     exceptionNumberIn => sqlcode,
1524                                     exceptionStringIn => sqlerrm);
1525           raise;
1526           return(null);
1527     end getHandlerItemOrderNumber;
1528   function getHandlerOccurrence(nameIn in varchar2,
1529                                 itemClassIn in varchar2 default null,
1530                                 itemIdIn in varchar2 default null,
1531                                 actionTypeIdIn in integer default null,
1532                                 groupOrChainIdIn in integer default null) return integer as
1533     engStApproversCount integer;
1534     itemClass ame_temp_old_approver_lists.item_class%type;
1535     itemId ame_temp_old_approver_lists.item_id%type;
1536     actionTypeId integer;
1537     groupOrChainId integer;
1538     occurrence integer;
1539     begin
1540       engStApproversCount := engStApprovers.count;
1541       /* Handle the empty-list case first. */
1542         if(engStApproversCount = 0) then
1543           return(1);
1544         end if;
1545       /* Determine which chain of authority to match. */
1546       if(itemClassIn is null or
1547          itemIdIn is null or
1548          actionTypeIdIn is null or
1549          groupOrChainIdIn is null) then
1550         /*
1551           If we're not trying to match an inserted approver with nullInsertionActionTypeId and
1552           nullInsertionGroupOrChainId, and one of the input arguments is null, match the most
1553           recently added group or chain.
1554         */
1555         for i in reverse 1 .. engStApproversCount loop
1556           if(engStApprovers(i).action_type_id <> ame_util.nullInsertionActionTypeId and
1557              engStApprovers(i).group_or_chain_id <> ame_util.nullInsertionGroupOrChainId and
1558              engStApprovers(i).item_class is not null and
1559              engStApprovers(i).item_id is not null and
1560              engStApprovers(i).action_type_id is not null and
1561              engStApprovers(i).group_or_chain_id is not null) then
1562             itemClass := engStApprovers(i).item_class;
1563             itemId := engStApprovers(i).item_id;
1564             actionTypeId := engStApprovers(i).action_type_id;
1565             groupOrChainId := engStApprovers(i).group_or_chain_id;
1566             exit;
1567           end if;
1568         end loop;
1569       else
1570         itemClass := itemClassIn;
1571         itemId := itemIdIn;
1572         actionTypeId := actionTypeIdIn;
1573         groupOrChainId := groupOrChainIdIn;
1574       end if;
1575       if(itemClass is null) then
1576         /*
1577           One of the input arguments is null, and all approvers in the list have nullInsertionActionTypeId and
1578           nullInsertionGroupOrChainId.  So these are the only action-type ID and group-or-chain ID we can match.
1579           In this case, match the item class and item ID of the most recent insertion.
1580         */
1581         itemClass := engStApprovers(engStApproversCount).item_class;
1582         itemId := engStApprovers(engStApproversCount).item_id;
1583         actionTypeId := engStApprovers(engStApproversCount).action_type_id;
1584         groupOrChainId := engStApprovers(engStApproversCount).group_or_chain_id;
1585       end if;
1586       /* Now count matches within the target item class, item ID, action-type ID, and group-or-chain ID. */
1587       occurrence := 1;
1588       for i in 1 .. engStApproversCount loop
1589         /*
1590           The order of the comparisons in the if statement below is significant for efficiency.
1591           (Most of the time, the names won't match, and that ends the comparison for engStApprovers(i).)
1592           (We could stop the comparison upon leaving the target item's approver list, but this would
1593           generally take more work than it would save.)
1594         */
1595         if(engStApprovers(i).name = nameIn and
1596            engStApprovers(i).group_or_chain_id = groupOrChainId and
1597            engStApprovers(i).action_type_id = actionTypeId and
1598            engStApprovers(i).item_id = itemId and
1599            engStApprovers(i).item_class = itemClass) then
1600           occurrence := occurrence + 1;
1601         end if;
1602       end loop;
1603       return(occurrence);
1604       exception
1605         when others then
1606           ame_util.runtimeException(packageNameIn => 'ame_engine',
1607                                     routineNameIn => 'getHandlerOccurrence',
1608                                     exceptionNumberIn => sqlcode,
1609                                     exceptionStringIn => sqlerrm);
1610           raise;
1611           return(null);
1612     end getHandlerOccurrence;
1613   function getHandlerRuleType return integer as
1614     begin
1615       return(engAppRuleTypes(engAppHandlerFirstIndex));
1616       exception
1617         when others then
1618           ame_util.runtimeException(packageNameIn => 'ame_engine',
1619                                     routineNameIn => 'getHandlerRuleType',
1620                                     exceptionNumberIn => sqlcode,
1621                                     exceptionStringIn => sqlerrm);
1622           raise;
1623           return(null);
1624     end getHandlerRuleType;
1625   function getHandlerState(handlerNameIn in varchar2,
1626                            parameterIn in varchar2 default null) return varchar2 as
1627     handlerName ame_temp_handler_states.handler_name%type;
1628     tempState ame_temp_handler_states.state%type;
1629     begin
1630       handlerName := upper(handlerNameIn);
1631       select state
1632         into tempState
1633         from ame_temp_handler_states
1634         where
1635           handler_name = handlerName and
1636           ((application_id is null and engAmeApplicationId is null) or
1637            (application_id = engAmeApplicationId)) and
1638           ((parameter is null and parameterIn is null) or
1639            (parameter = parameterIn)) and
1640           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
1641       return(tempState);
1642       exception
1643         when no_data_found then
1644           return(null);
1645         when others then
1646           ame_util.runtimeException(packageNameIn => 'ame_engine',
1647                                     routineNameIn => 'getHandlerState',
1648                                     exceptionNumberIn => sqlcode,
1649                                     exceptionStringIn => sqlerrm);
1650           raise;
1651           return(null);
1652     end getHandlerState;
1653   function getHandlerSublistOrderNum return integer as
1654     handlerAuthority ame_util.charType;
1655     itemClassSublistMode ame_util.charType;
1656     begin
1657       handlerAuthority := getHandlerAuthority;
1658       itemClassSublistMode := getItemClassSublistMode(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex));
1659       if(itemClassSublistMode = ame_util.serialSublists) then
1660         if(handlerAuthority = ame_util.preApprover) then
1661           return(1);
1662         elsif(handlerAuthority = ame_util.authorityApprover) then
1663           return(2);
1664         else
1665           return(3);
1666         end if;
1667       elsif(itemClassSublistMode = ame_util.parallelSublists) then
1668         return(1);
1669       elsif(itemClassSublistMode = ame_util.preFirst) then
1670         if(handlerAuthority = ame_util.preApprover) then
1671           return(1);
1672         else
1673           return(2);
1674         end if;
1675       else
1676         if(handlerAuthority = ame_util.postApprover) then
1677           return(2);
1678         else
1679           return(1);
1680         end if;
1681       end if;
1682       exception
1683         when others then
1684           ame_util.runtimeException(packageNameIn => 'ame_engine',
1685                                     routineNameIn => 'getHandlerSublistOrderNum',
1686                                     exceptionNumberIn => sqlcode,
1687                                     exceptionStringIn => sqlerrm);
1688           raise;
1689           return(null);
1690     end getHandlerSublistOrderNum;
1691   function getHeaderAttValue1(attributeIdIn in integer) return varchar2 as
1692     begin
1693       return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
1694       exception
1695         when others then
1696           ame_util.runtimeException(packageNameIn => 'ame_engine',
1697                                     routineNameIn => 'getHeaderAttValue1',
1698                                     exceptionNumberIn => sqlcode,
1699                                     exceptionStringIn => sqlerrm);
1700           raise;
1701           return(null);
1702     end getHeaderAttValue1;
1703   function getTestVariantAttValue(attributeIdIn in integer,
1704                                  itemClassIdIn  in integer,
1705                                  itemIdIn       in varchar2) return number as
1706     tempValue ame_util.attributeValueType;
1707     begin
1708       select attribute_value_1 into tempValue from ame_test_trans_att_values
1709         where application_id = engAmeApplicationId
1710           and transaction_id = engTransactionId
1711           and attribute_id = attributeIdIn
1712           and item_class_id = itemClassIdIn
1713           and item_id    = itemIdIn;
1714       return tempValue;
1715       exception
1716         when no_data_found then
1717           begin
1718             select attribute_value_1
1719               into tempValue
1720               from ame_test_trans_att_values
1721              where application_id = engAmeApplicationId
1722                and transaction_id = engTransactionId
1723                and attribute_id = attributeIdIn
1724                and item_class_id = getItemClassId(ame_util.headerItemClassName)
1725                and item_id    = engTransactionId;
1726             return tempValue;
1727           exception
1728             when others then
1729               ame_util.runtimeException(packageNameIn => 'ame_engine',
1730                                         routineNameIn => 'getTestVariantAttValue',
1731                                         exceptionNumberIn => sqlcode,
1732                                         exceptionStringIn => sqlerrm);
1733               raise;
1734               return(null);
1735           end;
1736         when others then
1737           ame_util.runtimeException(packageNameIn => 'ame_engine',
1738                                     routineNameIn => 'getTestVariantAttValue',
1739                                     exceptionNumberIn => sqlcode,
1740                                     exceptionStringIn => sqlerrm);
1741           raise;
1742           return(null);
1743     end getTestVariantAttValue;
1744   function getHeaderAttValue2(attributeNameIn in varchar2) return varchar2 as
1745     attributeId integer;
1746     begin
1747       if engIsTestTransaction then
1748         attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
1749         if checkAttributeVariant(attributeId) = ame_util.booleanTrue then
1750            return getTestVariantAttValue(attributeIdIn => attributeId
1751                                        ,itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)
1752                                        ,itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex));
1753         else
1754           return(engAttributeValues1(engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn))));
1755         end if;
1756       else
1757         if(engAttributeVariant.exists(getAttributeIdByName(attributeNameIn => attributeNameIn))) then
1758           return(getVariantAttributeValue(attributeIdIn => getAttributeIdByName(attributeNameIn => attributeNameIn),
1759                                           itemClassIn => getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
1760                                           itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex)));
1761         else
1762           return(engAttributeValues1(engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn))));
1763         end if;
1764       end if;
1765       exception
1766         when others then
1767           ame_util.runtimeException(packageNameIn => 'ame_engine',
1768                                     routineNameIn => 'getHeaderAttValue2',
1769                                     exceptionNumberIn => sqlcode,
1770                                     exceptionStringIn => sqlerrm);
1771           raise;
1772           return(null);
1773     end getHeaderAttValue2;
1774   function getItemAttValue1(attributeIdIn in integer,
1775                             itemIdIn in varchar2) return varchar2 as
1776     begin
1777       return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn) +
1778                                  getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeIdIn),
1779                                                itemIdIn => itemIdIn)));
1780       exception
1781         when others then
1782           ame_util.runtimeException(packageNameIn => 'ame_engine',
1783                                     routineNameIn => 'getItemAttValue1',
1784                                     exceptionNumberIn => sqlcode,
1785                                     exceptionStringIn => sqlerrm);
1786           raise;
1787           return(null);
1788     end getItemAttValue1;
1789   function getItemAttValue2(attributeNameIn in varchar2,
1790                             itemIdIn in varchar2) return varchar2 as
1791     attributeId integer;
1792     begin
1793       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
1794       return(engAttributeValues1(engAttributeValueIndexes(attributeId) +
1795                                   getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeId),
1796                                                 itemIdIn => itemIdIn)));
1797       exception
1798         when others then
1799           ame_util.runtimeException(packageNameIn => 'ame_engine',
1800                                     routineNameIn => 'getItemAttValue2',
1801                                     exceptionNumberIn => sqlcode,
1802                                     exceptionStringIn => sqlerrm);
1803           raise;
1804           return(null);
1805     end getItemAttValue2;
1806   function getItemClassId(itemClassNameIn in varchar2) return integer as
1807     begin
1808       for itemClassIndex in 1 .. engItemClassNames.count loop
1809         if(engItemClassNames(itemClassIndex) = itemClassNameIn) then
1810           return(engItemClassIds(itemClassIndex));
1811         end if;
1812       end loop;
1813       return(null);
1814       exception
1815         when others then
1816           ame_util.runtimeException(packageNameIn => 'ame_engine',
1817                                     routineNameIn => 'getItemClassId',
1818                                     exceptionNumberIn => sqlcode,
1819                                     exceptionStringIn => sqlerrm);
1820           raise;
1821           return(null);
1822     end getItemClassId;
1823   function getItemClassName(itemClassIdIn in integer) return varchar2 as
1824     begin
1825       return(engItemClassNames(engItemClassIndexes(itemClassIdIn)));
1826       exception
1827         when others then
1828           ame_util.runtimeException(packageNameIn => 'ame_engine',
1829                                     routineNameIn => 'getItemClassName',
1830                                     exceptionNumberIn => sqlcode,
1831                                     exceptionStringIn => sqlerrm);
1832           raise;
1833           return(null);
1834     end getItemClassName;
1835   function getItemClassOrderNumber(itemClassIdIn in integer) return integer as
1836     begin
1837       return(engItemClassOrderNumbers(engItemClassIndexes(itemClassIdIn)));
1838       exception
1839         when others then
1840           ame_util.runtimeException(packageNameIn => 'ame_engine',
1841                                     routineNameIn => 'getItemClassOrderNumber',
1842                                     exceptionNumberIn => sqlcode,
1843                                     exceptionStringIn => sqlerrm);
1844           raise;
1845           return(null);
1846     end getItemClassOrderNumber;
1847   function getItemClassParMode(itemClassIdIn in integer) return varchar2 as
1848     begin
1849       return(engItemClassParModes(engItemClassIndexes(itemClassIdIn)));
1850       exception
1851         when others then
1852           ame_util.runtimeException(packageNameIn => 'ame_engine',
1853                                     routineNameIn => 'getItemClassParMode',
1854                                     exceptionNumberIn => sqlcode,
1855                                     exceptionStringIn => sqlerrm);
1856           raise;
1857           return(null);
1858     end getItemClassParMode;
1859   function getItemClassSublistMode(itemClassIdIn in integer) return varchar2 as
1860     begin
1861       return(engItemClassSublistModes(engItemClassIndexes(itemClassIdIn)));
1862       exception
1863         when others then
1864           ame_util.runtimeException(packageNameIn => 'ame_engine',
1865                                     routineNameIn => 'getItemClassSublistMode',
1866                                     exceptionNumberIn => sqlcode,
1867                                     exceptionStringIn => sqlerrm);
1868           raise;
1869           return(null);
1870     end getItemClassSublistMode;
1871   function getItemIndex(itemClassIdIn in integer,
1872                         itemIdIn in varchar2) return integer as
1873     errorCode integer;
1874     errorMessage ame_util.longestStringType;
1875     firstItemIndex integer;
1876     itemClassIndex integer;
1877     noIndexException exception;
1878     begin
1879       itemClassIndex := engItemClassIndexes(itemClassIdIn);
1880       firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
1881       for i in firstItemIndex .. (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
1882         if(engItemIds(i) = itemIdIn) then
1883           return(i);
1884         end if;
1885       end loop;
1886       raise noIndexException;
1887       exception
1888         when noIndexException then
1889           errorCode := -20001;
1890           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1891                                               messageNameIn => 'AME_400682_ENG_INV_ITEM_OFFSET');
1892           ame_util.runtimeException(packageNameIn => 'ame_engine',
1893                                     routineNameIn => 'getItemIndex',
1894                                     exceptionNumberIn => errorCode,
1895                                     exceptionStringIn => errorMessage);
1896           raise_application_error(errorCode,
1897                                   errorMessage);
1898           return(null);
1899         when others then
1900           ame_util.runtimeException(packageNameIn => 'ame_engine',
1901                                     routineNameIn => 'getItemIndex',
1902                                     exceptionNumberIn => sqlcode,
1903                                     exceptionStringIn => sqlerrm);
1904           raise;
1905           return(null);
1906     end getItemIndex;
1907   function getItemOffset(itemClassIdIn in integer,
1908                          itemIdIn in varchar2) return integer as
1909     errorCode integer;
1910     errorMessage ame_util.longestStringType;
1911     firstItemIndex integer;
1912     itemClassIndex integer;
1913     noOffsetException exception;
1914     begin
1915       itemClassIndex := engItemClassIndexes(itemClassIdIn);
1916       firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
1917       for i in firstItemIndex .. (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
1918         if(engItemIds(i) = itemIdIn) then
1919           return(i - firstItemIndex);
1920         end if;
1921       end loop;
1922       raise noOffsetException;
1923       exception
1924         when noOffsetException then
1925           errorCode := -20001;
1926           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1927                                               messageNameIn => 'AME_400682_ENG_INV_ITEM_OFFSET');
1928           ame_util.runtimeException(packageNameIn => 'ame_engine',
1929                                     routineNameIn => 'getItemOffset',
1930                                     exceptionNumberIn => errorCode,
1931                                     exceptionStringIn => errorMessage);
1932           raise_application_error(errorCode,
1933                                   errorMessage);
1934           return(null);
1935         when others then
1936           ame_util.runtimeException(packageNameIn => 'ame_engine',
1937                                     routineNameIn => 'getItemOffset',
1938                                     exceptionNumberIn => sqlcode,
1939                                     exceptionStringIn => sqlerrm);
1940           raise;
1941           return(null);
1942     end getItemOffset;
1943   function getItemOrderNumber(itemClassNameIn in varchar2,
1944                               itemIdIn in varchar2) return integer as
1945     itemClassId integer;
1946     begin
1947       itemClassId := getItemClassId(itemClassNameIn => itemClassNameIn);
1948       if(getItemClassParMode(itemClassIdIn => itemClassId) = ame_util.parallelItems) then
1949         return(1);
1950       else /* The parallelization modes is ame_util.serialItems. */
1951         return(1 + getItemOffset(itemClassIdIn => itemClassId,
1952                                  itemIdIn => itemIdIn));
1953       end if;
1954       exception
1955         when others then
1956           ame_util.runtimeException(packageNameIn => 'ame_engine',
1957                                     routineNameIn => 'getItemOrderNumber',
1958                                     exceptionNumberIn => sqlcode,
1959                                     exceptionStringIn => sqlerrm);
1960           raise;
1961           return(null);
1962     end getItemOrderNumber;
1963   function getNextInsertionOrder return integer as
1964     maxInsertionOrderNumber number;
1965     begin
1966       select max(insertion_order)
1967         into maxInsertionOrderNumber
1968         from ame_temp_insertions
1969        where transaction_id = engTransactionId
1970          and application_id = engAmeApplicationId;
1971       if maxinsertionOrderNumber is null
1972       then
1973         return 1;
1974       else
1975         return (maxInsertionOrderNumber + 1);
1976       end if;
1977       exception
1978         when others then
1979           ame_util.runtimeException(packageNameIn => 'ame_engine',
1980                                     routineNameIn => 'getNextInsertionOrder',
1981                                     exceptionNumberIn => sqlcode,
1982                                     exceptionStringIn => sqlerrm);
1983           raise;
1984           return(null);
1985     end getNextInsertionOrder;
1986   function getNullActionTypeOrderNumber return integer as
1987     maxOrderNumber integer := 0;
1988     tempIndex integer;
1989     begin
1990       tempIndex := engActionTypeOrderNumbers.first;
1991       while(tempIndex is not null) loop
1992         if(maxOrderNumber is null or
1993            engActionTypeOrderNumbers(tempIndex) < maxOrderNumber) then
1994           maxOrderNumber := engActionTypeOrderNumbers(tempIndex);
1995         end if;
1996         tempIndex := engActionTypeOrderNumbers.next(tempIndex);
1997       end loop;
1998       return(maxOrderNumber + 1);
1999       exception
2000         when others then
2001           ame_util.runtimeException(packageNameIn => 'ame_engine',
2002                                     routineNameIn => 'getNullActionTypeOrderNumber',
2003                                     exceptionNumberIn => sqlcode,
2004                                     exceptionStringIn => sqlerrm);
2005           raise;
2006           return(null);
2007     end getNullActionTypeOrderNumber;
2008   function getRuntimeGroupCount(groupIdIn in integer) return integer as
2009     tempIndex integer;
2010     begin
2011       tempIndex := 0; /* pre-increment */
2012       -- Check if group is defined or has to be re run for every item class/item ID
2013       if(not engGroupUseItemBind.exists(groupIdIn)) then
2014         fetchRuntimeGroup(groupIdIn => groupIdIn);
2015       elsif (engGroupUseItemBind(groupIdIn) = ame_util.booleanTrue) then
2016         fetchRuntimeGroup(groupIdIn => groupIdIn);
2017       end if;
2018       /* Group membership must exist in  engGroupMemberGroupIds now. */
2019       for i in 1 .. engGroupMemberGroupIds.count loop
2020         if(engGroupMemberGroupIds(i) = groupIdIn) then
2021           tempIndex := tempIndex + 1;
2022         elsif(tempIndex > 0) then
2023           /* The group was found and has been passed. */
2024           return(tempIndex);
2025         end if;
2026       end loop;
2027       exception
2028         when others then
2029           ame_util.runtimeException(packageNameIn => 'ame_engine',
2030                                     routineNameIn => 'getRuntimeGroupCount',
2031                                     exceptionNumberIn => sqlcode,
2032                                     exceptionStringIn => sqlerrm);
2033           raise;
2034           return(null);
2035     end getRuntimeGroupCount;
2036   function getSublistOrderNum(itemClassNameIn in varchar2,
2037                               authorityIn in varchar2) return integer as
2038     itemClassSublistMode ame_util.charType;
2039     begin
2040       itemClassSublistMode :=
2041         getItemClassSublistMode(itemClassIdIn => getItemClassId(itemClassNameIn => itemClassNameIn));
2042       if(itemClassSublistMode = ame_util.serialSublists) then
2043         if(authorityIn = ame_util.preApprover) then
2044           return(1);
2045         elsif(authorityIn = ame_util.authorityApprover) then
2046           return(2);
2047         else
2048           return(3);
2049         end if;
2050       elsif(itemClassSublistMode = ame_util.parallelSublists) then
2051         return(1);
2052       elsif(itemClassSublistMode = ame_util.preFirst) then
2053         if(authorityIn = ame_util.preApprover) then
2054           return(1);
2055         else
2056           return(2);
2057         end if;
2058       else
2059         if(authorityIn = ame_util.postApprover) then
2060           return(2);
2061         else
2062           return(1);
2063         end if;
2064       end if;
2065       exception
2066         when others then
2067           ame_util.runtimeException(packageNameIn => 'ame_engine',
2068                                     routineNameIn => 'getSublistOrderNum',
2069                                     exceptionNumberIn => sqlcode,
2070                                     exceptionStringIn => sqlerrm);
2071           raise;
2072           return(null);
2073     end getSublistOrderNum;
2074   function getTransactionId return varchar2 as
2075     begin
2076       return(engTransactionID);
2077       exception
2078         when others then
2079           ame_util.runtimeException(packageNameIn => 'ame_engine',
2080                                     routineNameIn => 'getTransactionId',
2081                                     exceptionNumberIn => sqlcode,
2082                                     exceptionStringIn => sqlerrm);
2083           raise;
2084           return(null);
2085     end getTransactionId;
2086   function getTransactionTypeId return varchar2 as
2087     begin
2088       return(engTransactionTypeID);
2089       exception
2090         when others then
2091           ame_util.runtimeException(packageNameIn => 'ame_engine',
2092                                     routineNameIn => 'getTransactionTypeId',
2093                                     exceptionNumberIn => sqlcode,
2094                                     exceptionStringIn => sqlerrm);
2095           raise;
2096           return(null);
2097     end getTransactionTypeId;
2098   /********************************** sort functions **********************************/
2099   function compareApplicableRules(index1In in integer,
2100                                   index2In in integer,
2101                                   compareActionTypesIn in boolean) return boolean as
2102     /* Returns true if the applicable rule at the first index weakly precedes the second. */
2103     actionTypeId1 integer;
2104     actionTypeId2 integer;
2105     itemClassId1 integer;
2106     itemClassId2 integer;
2107     begin
2108       itemClassId1 := engAppRuleItemClassIds(index1In);
2109       itemClassId2 := engAppRuleItemClassIds(index2In);
2110       /* Account for the possibility that one or both rules may have null item-class IDs. */
2111       if(itemClassId1 is null) then
2112         if(itemClassId2 is not null) then
2113           return(false);
2114         end if;
2115       else /* itemClassId1 is not null. */
2116         if(itemClassId2 is null) then
2117           return(true);
2118         else /* Both item-class IDs are non-null. */
2119           /* item-class order number */
2120           if(engItemClassOrderNumbers(engItemClassIndexes(itemClassId1)) >
2121              engItemClassOrderNumbers(engItemClassIndexes(itemClassId2))) then
2122             return(false);
2123           end if;
2124           if(engItemClassOrderNumbers(engItemClassIndexes(itemClassId1)) <
2125              engItemClassOrderNumbers(engItemClassIndexes(itemClassId2))) then
2126             return(true);
2127           end if;
2128           /* item-class ID */
2129           if(itemClassId1 > itemClassId2) then
2130             return(false);
2131           end if;
2132           if(itemClassId1 < itemClassId2) then
2133             return(true);
2134           end if;
2135         end if;
2136       end if;
2137       /* item ID */
2138       if(engAppAppItemIds(index1In) > engAppAppItemIds(index2In)) then
2139         return(false);
2140       end if;
2141       if(engAppAppItemIds(index1In) < engAppAppItemIds(index2In)) then
2142         return(true);
2143       end if;
2144       /* rule type */
2145       if(engAppRuleTypes(index1In) > engAppRuleTypes(index2In)) then
2146         return(false);
2147       end if;
2148       /*
2149         The second rule-type comparison is only necessary if compareActionTypesIn is true;
2150         otherwise, we return true regardless of the outcome of the second rule-type comparison.
2151         So include it within the if(compareActionTypesIn) below.
2152       /* optional action-type comparisons */
2153       if(compareActionTypesIn) then
2154         if(engAppRuleTypes(index1In) < engAppRuleTypes(index2In)) then
2155           return(true);
2156         end if;
2157         /* Do the action-type comparisons. */
2158         actionTypeId1 := engAppActionTypeIds(index1In);
2159         actionTypeId2 := engAppActionTypeIds(index2In);
2160         /* action-type order numbers */
2161         if(engActionTypeOrderNumbers(actionTypeId1) >
2162            engActionTypeOrderNumbers(actionTypeId2)) then
2163           return(false);
2164         end if;
2165         if(engActionTypeOrderNumbers(actionTypeId1) <
2166            engActionTypeOrderNumbers(actionTypeId2)) then
2167           return(true);
2168         end if;
2169         /* action-type ID */
2170         if(actionTypeId1 > actionTypeId2) then
2171           return(false);
2172         end if;
2173         /*
2174           The second comparison on action-type ID is unnecessary, because whether it succeeds
2175           or fails, we return true.
2176         */
2177       end if;
2178       return(true);
2179         exception
2180           when others then
2181             ame_util.runtimeException(packageNameIn => 'ame_engine',
2182                                       routineNameIn => 'compareApplicableRules',
2183                                       exceptionNumberIn => sqlcode,
2184                                       exceptionStringIn => sqlerrm);
2185             raise;
2186             return(false);
2187     end compareApplicableRules;
2188   /*************************************************************************************
2189   procedures
2190   *************************************************************************************/
2191   procedure addApprover(approverIn in ame_util.approverRecord2) as
2192     errorCode integer;
2193     errorMessage ame_util.longestStringType;
2194     listTooLongException exception;
2195     nullFieldException exception;
2196     begin
2197       if(engStApprovers.count > 2500) then
2198         raise listTooLongException;
2199       end if;
2200       checkApprover(approverIn => approverIn);
2201       if(approverIn.name is null or
2202          approverIn.orig_system is null or
2203          approverIn.orig_system_id is null or
2204          approverIn.display_name is null or
2205          approverIn.approver_category is null or
2206          approverIn.api_insertion is null or
2207          approverIn.authority is null or
2208          approverIn.action_type_id is null or
2209          approverIn.group_or_chain_id is null or
2210          approverIn.occurrence is null or
2211          approverIn.source is null or
2212          approverIn.item_class is null or
2213          approverIn.item_id is null or
2214          approverIn.item_class_order_number is null or
2215          approverIn.item_order_number is null or
2216          approverIn.sub_list_order_number is null or
2217          approverIn.action_type_order_number is null or
2218          approverIn.group_or_chain_order_number is null or
2219          approverIn.member_order_number is null) then
2220         raise nullFieldException;
2221       end if;
2222       ame_util.copyApproverRecord2(approverRecord2In => approverIn,
2223                                    approverRecord2Out => engStApprovers(engStApprovers.count + 1));
2224       /* Add the approver to the tree whenever he is added to the approver list */
2225       /* Approvers location in list is engStApprovers.count                     */
2226       /* Add the approver as the last approver among the approvers with same    */
2227       /* order number                                                           */
2228       if engPrepareApproverTree then
2229         addApproverToTree
2230             (approverRecordIn    => engStApprovers(engStApprovers.count)
2231             ,approverIndexIn     => engStApprovers.count
2232             ,approverLocationIn  => ame_util.lastAmongEquals);
2233       end if;
2234       exception
2235         when listTooLongException then
2236           errorCode := -20001;
2237           errorMessage :=
2238           ame_util.getMessage(applicationShortNameIn => 'PER',
2239                               messageNameIn => 'AME_400118_ENG_LOOP_CHA_AUTH');
2240           ame_util.runtimeException(packageNameIn => 'ame_engine',
2241                                     routineNameIn => 'addApprover',
2242                                     exceptionNumberIn => errorCode,
2243                                     exceptionStringIn => errorMessage);
2244           raise_application_error(errorCode,
2245                                   errorMessage);
2246         when nullFieldException then
2247           errorCode := -20001;
2248           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
2249                                               messageNameIn => 'AME_400683_APPR_REC_INV');
2250           ame_util.runtimeException(packageNameIn => 'ame_engine',
2251                                     routineNameIn => 'addApprover',
2252                                     exceptionNumberIn => errorCode,
2253                                     exceptionStringIn => errorMessage);
2254           raise_application_error(errorCode,
2255                                   errorMessage);
2256         when others then
2257           ame_util.runtimeException(packageNameIn => 'ame_engine',
2258                                     routineNameIn => 'addApprover',
2259                                     exceptionNumberIn => sqlcode,
2260                                     exceptionStringIn => sqlerrm);
2261           raise;
2262     end addApprover;
2263   procedure addApproversTodevList(approverRecordIndexIn in integer) is
2264    tempCount integer;
2265   begin
2266     if engTempReason is not null or engTempDate is not null then
2267       engDeviationResultList(approverRecordIndexIn).reason := engTempReason;
2268       engDeviationResultList(approverRecordIndexIn).effectiveDate := engTempDate;
2269     end if;
2270     engTempReason := null;
2271     engTempDate := null;
2272   exception
2273     when others then
2274       ame_util.runtimeException(packageNameIn => 'ame_engine',
2275                                 routineNameIn => 'addApproversTodevList',
2276                                 exceptionNumberIn => sqlcode,
2277                                 exceptionStringIn => sqlerrm);
2278   end addApproversTodevList;
2279   /* This procedure is used to add an approver to the approver tree */
2280   procedure addApproverToTree
2281     (approverRecordIn   in            ame_util.approverRecord2
2282     ,approverIndexIn    in            integer
2283     ,approverLocationIn in            boolean default ame_util.lastAmongEquals) is
2284     orderNumbers                 ame_util.idList;
2285     treeLevelIds                 ame_util.stringList;
2286     approverIndexs               ame_util.idList;
2287     previousTreeNodeIndex        integer;
2288     currentTreeNodeIndex         integer;
2289     newTreeNodeIndex             integer;
2290     newTreeNode                  ame_util.approverTreeRecord;
2291     currentSiblingTreeNodeIndex  integer;
2292     lowerOrderLastSiblingIndex   integer;
2293     higherOrderFirstSiblingIndex integer;
2294     sameOrderFirstSiblingIndex   integer;
2295     sameOrderLastSiblingIndex    integer;
2296     currentTreeNodeFound         boolean;
2297   begin
2298     /* Initialise the tree with the transaction level node if the tree */
2299     /* is not yet built.The tree level node will have min_order of 1   */
2300     /* which is the minimum allowed approver order number              */
2301     if engStApproversTree.count = 0 then
2302       newTreeNode.parent_index := ame_util.noParentIndex;
2303       newTreeNode.child_index := ame_util.noChildIndex;
2304       newTreeNode.sibling_index := ame_util.noSiblingIndex;
2305       newTreeNode.approver_index := ame_util.noApproverIndex;
2306       newTreeNode.tree_level_id := -1;
2307       newTreeNode.order_number := -1;
2308       newTreeNode.min_order := ame_util.minimumApproverOrderNumber;
2309       newTreeNode.is_suspended := ame_util.booleanFalse;
2310 --      newTreeNode.repeated_index := -1;
2311       newTreeNode.tree_level := 0;
2312       engStApproversTree(1)  := newTreeNode;
2313     end if;
2314     /* For each tree level assign the node order number, unique tree level */
2315     /* ids and the approver indices                                        */
2316     orderNumbers(1) := approverRecordIn.item_class_order_number;
2317     orderNumbers(2) := approverRecordIn.item_order_number;
2318     orderNumbers(3) := approverRecordIn.sub_list_order_number;
2319     orderNumbers(4) := approverRecordIn.action_type_order_number;
2320     orderNumbers(5) := approverRecordIn.group_or_chain_order_number;
2321     orderNumbers(6) := approverRecordIn.member_order_number;
2322     treeLevelIds(1) := approverRecordIn.item_class;
2323     treeLevelIds(2) := approverRecordIn.item_id;
2324     treeLevelIds(3) := approverRecordIn.authority;
2325     treeLevelIds(4) := to_char(approverRecordIn.action_type_id);
2326     treeLevelIds(5) := to_char(approverRecordIn.group_or_chain_id);
2327     treeLevelIds(6) := approverRecordIn.name;
2328     approverIndexs(1) := ame_util.noApproverIndex;
2329     approverIndexs(2) := ame_util.noApproverIndex;
2330     approverIndexs(3) := ame_util.noApproverIndex;
2331     approverIndexs(4) := ame_util.noApproverIndex;
2332     approverIndexs(5) := ame_util.noApproverIndex;
2333     approverIndexs(6) := approverIndexIn;
2334     /* Starting with the transaction node traverse the tree through the    */
2335     /* item class,item,sublist,action type,group or chain and finally      */
2336     /* insert the approver into the tree.In the way if any of other nodes  */
2337     /* are missing create them.                                            */
2338     previousTreeNodeIndex := 1;
2339     for i in 1 .. 6 loop
2340       if engStApproversTree(previousTreeNodeIndex).child_index
2341                                                    = ame_util.noChildIndex then
2342         newTreeNode.parent_index := previousTreeNodeIndex;
2343         newTreeNode.sibling_index := ame_util.noSiblingIndex;
2344         newTreeNode.child_index := ame_util.noChildIndex;
2345         newTreeNode.approver_index := approverIndexs(i);
2346         newTreeNode.tree_level_id := treeLevelIds(i);
2347         newTreeNode.order_number := orderNumbers(i);
2348         newTreeNode.is_suspended := ame_util.booleanFalse;
2349         newTreeNode.tree_level := i;
2350         newTreeNodeIndex := engStApproversTree.last + 1;
2351         engStApproversTree(newTreeNodeIndex) := newTreeNode;
2352         engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2353         currentTreeNodeIndex := newTreeNodeIndex;
2354       else
2355         currentSiblingTreeNodeIndex :=
2356                              engStApproversTree(previousTreeNodeIndex).child_index;
2357         lowerOrderLastSiblingIndex := -1;
2358         higherOrderFirstSiblingIndex := -1;
2359         sameOrderFirstSiblingIndex := -1;
2360         sameOrderLastSiblingIndex := -1;
2361         currentTreeNodeFound := false;
2362         loop
2363           if engStApproversTree(currentSiblingTreeNodeIndex).order_number
2364                                                               < orderNumbers(i) then
2365             lowerOrderLastSiblingIndex := currentSiblingTreeNodeIndex;
2366           elsif engStApproversTree(currentSiblingTreeNodeIndex).order_number
2367                                                               = orderNumbers(i) then
2368             if engStApproversTree(currentSiblingTreeNodeIndex).tree_level_id
2369                                                               = treeLevelIds(i)
2370                and (i <> 6) then --added for bug 4232137
2371               currentTreeNodeIndex := currentSiblingTreeNodeIndex;
2372               currentTreeNodeFound := true;
2373               exit;
2374             end if;
2375             if sameOrderFirstSiblingIndex = -1 then
2376               sameOrderFirstSiblingIndex := currentSiblingTreeNodeIndex;
2377             end if;
2378             sameOrderLastSiblingIndex := currentSiblingTreeNodeIndex;
2379           elsif engStApproversTree(currentSiblingTreeNodeIndex).order_number
2380                                                               > orderNumbers(i) then
2381             if higherOrderFirstSiblingIndex = -1 then
2382               higherOrderFirstSiblingIndex := currentSiblingTreeNodeIndex;
2383             end if;
2384           end if;
2385           currentSiblingTreeNodeIndex
2386                    := engStApproversTree(currentSiblingTreeNodeIndex).sibling_index;
2387           exit when currentSiblingTreeNodeIndex = ame_util.noSiblingIndex;
2388         end loop;
2389         if not currentTreeNodeFound then
2390           if approverLocationIn then
2391             /* approverLocationIn is ame_util.firstAmongEquals */
2392             newTreeNode.parent_index := previousTreeNodeIndex;
2393             if sameOrderFirstSiblingIndex = -1 then
2394               newTreeNode.sibling_index := higherOrderFirstSiblingIndex;
2395             else
2396               newTreeNode.sibling_index := sameOrderFirstSiblingIndex;
2397             end if;
2398             newTreeNode.child_index := ame_util.noChildIndex;
2399             newTreeNode.approver_index := approverIndexs(i);
2400             newTreeNode.tree_level_id := treeLevelIds(i);
2401             newTreeNode.order_number := orderNumbers(i);
2402             newTreeNode.is_suspended := ame_util.booleanFalse;
2403             newTreeNode.tree_level := i;
2404             newTreeNodeIndex := engStApproversTree.last + 1;
2405             engStApproversTree(newTreeNodeIndex) := newTreeNode;
2406             if lowerOrderLastSiblingIndex = -1 then
2407               engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2408             else
2409               engStApproversTree(lowerOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2410             end if;
2411             currentTreeNodeIndex := newTreeNodeIndex;
2412           else
2413             /* approverLocationIn is ame_util.lastAmongEquals */
2414             newTreeNode.parent_index := previousTreeNodeIndex;
2415             newTreeNode.sibling_index := higherOrderFirstSiblingIndex;
2416             newTreeNode.child_index := ame_util.noChildIndex;
2417             newTreeNode.approver_index := approverIndexs(i);
2418             newTreeNode.tree_level_id := treeLevelIds(i);
2419             newTreeNode.order_number := orderNumbers(i);
2420             newTreeNode.is_suspended := ame_util.booleanFalse;
2421             newTreeNode.tree_level := i;
2422             newTreeNodeIndex := engStApproversTree.last + 1;
2423             engStApproversTree(newTreeNodeIndex) := newTreeNode;
2424             if sameOrderLastSiblingIndex = -1 and lowerOrderLastSiblingIndex = -1 then
2425               engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2426             elsif sameOrderLastSiblingIndex = -1 then
2427               engStApproversTree(lowerOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2428             else
2429               engStApproversTree(sameOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2430             end if;
2431             currentTreeNodeIndex := newTreeNodeIndex;
2432           end if;
2433         end if;
2434       end if;
2435       previousTreeNodeIndex := currentTreeNodeIndex;
2436     end loop;
2437     addApproversTodevList(approverRecordIndexIn => approverIndexIn);
2438   exception
2439     when others then
2440       ame_util.runtimeException(packageNameIn => 'ame_engine',
2441                                 routineNameIn => 'addApproverToTree',
2442                                 exceptionNumberIn => sqlcode,
2443                                 exceptionStringIn => sqlerrm);
2444       raise;
2445   end addApproverToTree;
2446   procedure calculateApproverOrderNumbers as
2447     maximumApproverOrderNumber integer;
2448     transactionApprovalStatus integer;
2449     transactionhasSuspendedItems boolean;
2450     stoppingRule ame_util.stringType;
2451     headerItemRejected boolean;
2452     loopIndex integer;
2453     begin
2454       /* The call to finalizeTree does the following            */
2455       /* 1.Calculate the approver order number                  */
2456       /* 2.Populates the list of rejected items and itemclasses */
2457       /* 3.Returns whether the transaction has rejected Items   */
2458       /* 4.Returns the maximum order number of approvers        */
2459       /* 5.Returns the approval status of the transaction       */
2460       finalizeTree
2461         (parentIndexIn         => 1
2462         ,maximumOrderOut       => maximumApproverOrderNumber
2463         ,approvalStatusOut     => transactionApprovalStatus
2464         ,rejectedItemsExistOut => transactionhasSuspendedItems);
2465       engStApproversTree(1).status := transactionApprovalStatus;
2466       engStApproversTree(1).max_order := maximumApproverOrderNumber;
2467       stoppingRule := ame_engine.getHeaderAttValue2
2468                                  (attributeNameIn => ame_util.rejectionResponseAttribute);
2469       if transactionhasSuspendedItems then
2470         /* Check if any of the suspended item is a header item */
2471         /* If a header item is suspended then it is as good as */
2472         /* the entire transaction being suspended              */
2473         headerItemRejected := false;
2474         for i in 1 .. engStSuspendedItemClasses.count loop
2475           if engStSuspendedItemClasses(i) = ame_util.headerItemClassName then
2476             headerItemRejected := true;
2477             exit;
2478           end if;
2479         end loop;
2480         if stoppingRule = ame_util.stopAllItems or headerItemRejected then
2481           /* Suspend the transaction node */
2482           engStApproversTree(1).is_suspended := ame_util.booleanTrue;
2483         elsif stoppingRule = ame_util.continueAllOtherItems then
2484           /* Suspend all items in the suspended items list */
2485           for i in 1 .. engStSuspendedItems.count loop
2486             /* Approvers Tree can be sparse */
2487             loopIndex := engStApproversTree.first;
2488             loop
2489               if(engStApproversTree(loopIndex).tree_level = 2 and
2490                  engStApproversTree(loopIndex).tree_level_id = engStSuspendedItems(i) and
2491                  engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2492                                                          = engStSuspendedItemClasses(i)) then
2493                 engStApproversTree(loopIndex).is_suspended := ame_util.booleanTrue;
2494                 exit;
2495               end if;
2496               exit when loopIndex = engStApproversTree.last;
2497               loopIndex := engStApproversTree.next(loopIndex);
2498             end loop;
2499           end loop;
2500         elsif stoppingRule = ame_util.continueOtherSubItems then
2501           /* Suspend all items in the suspended items list and header item */
2502           for i in 1 .. engStSuspendedItems.count loop
2503             /* Approvers Tree can be sparse */
2504             loopIndex := engStApproversTree.first;
2505             loop
2506               if(engStApproversTree(loopIndex).tree_level = 2 and
2507                  ((engStApproversTree(loopIndex).tree_level_id = engStSuspendedItems(i) and
2508                   engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2509                                                         = engStSuspendedItemClasses(i))
2510                                                         or
2511                   (engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2512                                                         = ame_util.headerItemClassName))) then
2513                 engStApproversTree(loopIndex).is_suspended := ame_util.booleanTrue;
2514               end if;
2515               exit when loopIndex = engStApproversTree.last;
2516               loopIndex := engStApproversTree.next(loopIndex);
2517             end loop;
2518           end loop;
2519         end if;
2520       end if;
2521       exception
2522         when others then
2523           ame_util.runtimeException(packageNameIn => 'ame_engine',
2524                                     routineNameIn => 'calculateApproverOrderNumbers',
2525                                     exceptionNumberIn => sqlcode,
2526                                     exceptionStringIn => sqlerrm);
2527           raise;
2528     end calculateApproverOrderNumbers;
2529   --+
2530   --+ check Approver
2531   --+
2532   procedure checkApprover(approverIn in ame_util.approverRecord2) is
2533     errorCode integer;
2534     errorMessage ame_util.longestStringType;
2535     tempApproverTypeCount integer;
2536     tempApproverType ame_approver_types.orig_system%type;
2537     invalidApproverException1 exception;
2538     invalidApproverException2 exception;
2539     begin
2540       tempApproverType := approverIn.orig_system;
2541       if tempApproverType like 'FND_RESP%' or tempApproverType = 'AME_INS_ORIG_SYSTEM' then
2542         return;
2543       end if;
2544       if getConfigVarValue(ame_util.allowAllApproverTypesConfigVar) = ame_util.yes then
2545         select count(*)
2546           into tempApproverTypeCount
2547           from ame_approver_types
2548          where orig_system = approverIn.orig_system
2549            and sysdate between start_date and end_date;
2550         if tempApproverTypeCount = 0 then
2551           raise invalidApproverException1;
2552         end if;
2553       else
2554         if(tempApproverType in (ame_util.perOrigSystem
2555                                ,ame_util.fndUserOrigSystem )) then
2556           null;
2557         else
2558           raise invalidApproverException2;
2559         end if;
2560       end if;
2561     exception
2562       when invalidApproverException1 then
2563         errorCode := -20001;
2564         errorMessage := 'The Approver '
2565                         ||approverIn.display_name
2566                         ||' belongs to approver type '
2567                         ||approverIn.orig_system
2568                         ||' which is not registered in AME.';
2569         ame_util.runtimeException(packageNameIn => 'ame_engine',
2570                                   routineNameIn => 'checkApprover',
2571                                   exceptionNumberIn => errorCode,
2572                                   exceptionStringIn => errorMessage);
2573         raise_application_error(errorCode,
2574                                   errorMessage);
2575       when invalidApproverException2 then
2576         errorCode := -20001;
2577         errorMessage := 'The Approver '
2578                         ||approverIn.display_name
2579                         ||' belongs to approver type '
2580                         ||approverIn.orig_system
2581                         ||'. And the allowAllApproverTypes configuration variable set to No.';
2582         ame_util.runtimeException(packageNameIn => 'ame_engine',
2583                                   routineNameIn => 'checkApprover',
2584                                   exceptionNumberIn => errorCode,
2585                                   exceptionStringIn => errorMessage);
2586         raise_application_error(errorCode,
2587                                   errorMessage);
2588     end checkApprover;
2589   --+
2590   procedure clearHandlerState(handlerNameIn in varchar2,
2591                               parameterIn in varchar2 default null) as
2592     handlerName ame_temp_handler_states.handler_name%type;
2593     begin
2594       handlerName := upper(handlerNameIn);
2595       delete
2596         from ame_temp_handler_states
2597         where
2598           handler_name = handlerName and
2599           application_id = engAmeApplicationId and
2600           ((parameter is null and parameterIn is null) or
2601            (parameter = parameterIn));
2602       exception
2603         when others then
2604           ame_util.runtimeException(packageNameIn => 'ame_engine',
2605                                     routineNameIn => 'clearHandlerState',
2606                                     exceptionNumberIn => sqlcode,
2607                                     exceptionStringIn => sqlerrm);
2608           raise;
2609     end clearHandlerState;
2610   procedure compactEngAppLists(compactPrioritiesIn in boolean,
2611                                compactActionTypeIdsIn in boolean,
2612                                compactParametersIn in boolean) as
2613     tempCount integer;
2614     tempFirstIndex integer;
2615     tempLastIndex integer;
2616     begin
2617       tempCount := engAppRuleIds.count;
2618       if(tempCount = 0) then
2619         return;
2620       end if;
2621       tempFirstIndex := engAppRuleIds.first;
2622       for i in 1 .. tempCount loop
2623         if(i <> tempFirstIndex) then /* (Don't copy a row onto itself.) */
2624           engAppItemClassIds(i) := engAppItemClassIds(tempFirstIndex);
2625           engAppItemIds(i) := engAppItemIds(tempFirstIndex);
2626           engAppApproverCategories(i) := engAppApproverCategories(tempFirstIndex);
2627           engAppRuleIds(i) := engAppRuleIds(tempFirstIndex);
2628           engRuleAppliedYN(i) := engRuleAppliedYN(tempFirstIndex);
2629           engAppRuleTypes(i) := engAppRuleTypes(tempFirstIndex);
2630           engAppRuleItemClassIds(i) := engAppRuleItemClassIds(tempFirstIndex);
2631           engAppAppItemIds(i) := engAppAppItemIds(tempFirstIndex);
2632           if(compactPrioritiesIn) then
2633             engAppPriorities(i) := engAppPriorities(tempFirstIndex);
2634           end if;
2635           if(compactActionTypeIdsIn) then
2636             engAppActionTypeIds(i) := engAppActionTypeIds(tempFirstIndex);
2637           end if;
2638           if(compactParametersIn) then
2639             engAppParameters(i) := engAppParameters(tempFirstIndex);
2640             engAppParameterTwos(i) := engAppParameterTwos(tempFirstIndex);
2641           end if;
2642         end if;
2643         tempFirstIndex := engAppRuleIds.next(tempFirstIndex);
2644       end loop;
2645       /*
2646         engAppRuleIds.next will set tempFirstIndex null just before the for loop
2647         exits, so we have to set it anew here.
2648       */
2649       tempFirstIndex := tempCount + 1;
2650       tempLastIndex := engAppRuleIds.last;
2651       engAppItemClassIds.delete(tempFirstIndex, tempLastIndex);
2652       engAppItemIds.delete(tempFirstIndex, tempLastIndex);
2653       engAppApproverCategories.delete(tempFirstIndex, tempLastIndex);
2654       engAppRuleIds.delete(tempFirstIndex, tempLastIndex);
2655       engRuleAppliedYN.delete(tempFirstIndex, tempLastIndex);
2656       engAppRuleTypes.delete(tempFirstIndex, tempLastIndex);
2657       engAppRuleItemClassIds.delete(tempFirstIndex, tempLastIndex);
2658       engAppAppItemIds.delete(tempFirstIndex, tempLastIndex);
2659       if(compactPrioritiesIn) then
2660         engAppPriorities.delete(tempFirstIndex, tempLastIndex);
2661       end if;
2662       if(compactActionTypeIdsIn) then
2663         engAppActionTypeIds.delete(tempFirstIndex, tempLastIndex);
2664       end if;
2665       if(compactParametersIn) then
2666         engAppParameters.delete(tempFirstIndex, tempLastIndex);
2667         engAppParameterTwos.delete(tempFirstIndex, tempLastIndex);
2668       end if;
2669       exception
2670         when others then
2671           ame_util.runtimeException(packageNameIn => 'ame_engine',
2672                                     routineNameIn => 'compactEngAppLists',
2673                                     exceptionNumberIn => sqlcode,
2674                                     exceptionStringIn => sqlerrm);
2675           raise;
2676     end compactEngAppLists;
2677   procedure doPerItemRuleEvaluation(itemClassIdIn in integer,
2678                                     itemIndexIn in varchar2) as
2679     currentACUsageConditionIds ame_util.idList;
2680     currentACUsageRuleIds ame_util.idList;
2681     currentConditionRuleCounts ame_util.idList;
2682     tempConditionId integer;
2683     tempConditionId2 integer;
2684     tempHighestRuleCount integer;
2685     tempIndex integer;
2686     tempIndex2 integer;
2687     tempIndex3 integer;
2688     tempPendingRuleIds ame_util.idList;
2689     tempRuleApplies boolean;
2690     tempRuleId integer;
2691     begin
2692       /* Handle the null case (no active conditions) first. */
2693       if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
2694         return;
2695       end if;
2696       /*
2697         Initialize the current condition usages.  Note that while the currentACUsage local
2698         variables start out as compact lists, the algorithm that iterates through them
2699         deletes them in an unpredictable order, and does not re-compact the lists; so the
2700         algorithm must treat these lists as sparse.
2701       */
2702       tempIndex := 0; /* pre-increment */
2703       if(engACUsageFirstIndexes.exists(itemClassIdIn)) then
2704         for ACUIndex in
2705           engACUsageFirstIndexes(itemClassIdIn) ..
2706           (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
2707           tempIndex := tempIndex + 1;
2708           currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
2709           currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
2710         end loop;
2711       else
2712         return;
2713       end if;
2714       /*
2715         Initialize the rule counts.  currentConditionRuleCounts is indexed by condition ID for
2716         efficiency (the alternative requires a lot more looping).
2717       */
2718       tempHighestRuleCount := 0;
2719       tempIndex := currentACUsageConditionIds.first;
2720       while(tempIndex is not null) loop
2721         tempConditionId := currentACUsageConditionIds(tempIndex);
2722         if(currentConditionRuleCounts.exists(tempConditionId)) then
2723           currentConditionRuleCounts(tempConditionId) := currentConditionRuleCounts(tempConditionId) + 1;
2724         else
2725           currentConditionRuleCounts(tempConditionId) := 1;
2726         end if;
2727         tempIndex := currentACUsageConditionIds.next(tempIndex);
2728       end loop;
2729       /* Loop through the condition usages. */
2730       while(currentACUsageConditionIds.count > 0) loop
2731         /* Set tempHighestRuleCount. */
2732         tempHighestRuleCount := 0;
2733         tempIndex := currentConditionRuleCounts.first;
2734         while(tempIndex is not null) loop
2735           if(tempHighestRuleCount < currentConditionRuleCounts(tempIndex)) then
2736             tempHighestRuleCount := currentConditionRuleCounts(tempIndex);
2737             tempConditionId := tempIndex;
2738           end if;
2739           tempIndex := currentConditionRuleCounts.next(tempIndex);
2740         end loop;
2741         /* Clear the pending-rule list. */
2742         tempPendingRuleIds.delete;
2743         /*
2744           Choose the first condition with a maximal rule count.  Recall that
2745           currentConditionRuleCounts is indexed by condition ID.
2746         */
2747     /* Following while loop commented asper Issue 14 Please refer the        */
2748     /* comments in doWeakHeaderEvaluation                                    */
2749     /*  tempConditionId := currentConditionRuleCounts.first;
2750         while(tempConditionId is not null) loop
2751           if(currentConditionRuleCounts(tempConditionId) = tempHighestRuleCount) then
2752             exit;
2753           end if;
2754           tempConditionId := currentConditionRuleCounts.next(tempConditionId);
2755         end loop;  */
2756         /* From now on, tempConditionId is the ID of the chosen condition with maximal rule count. */
2757         /* Delete this condition from currentConditionRuleCounts. */
2758         currentConditionRuleCounts.delete(tempConditionId);
2759         /*
2760           Evaluate the chosen condition.  Note that whether or not the condition is satisfied, the
2761           code first loops through the currentAC variables, locating each currentAC instance matching
2762           the chosen condition.  The code avoids compressing the two cases' loops into a single loop
2763           to avoid repeatedly branching on a boolean variable inside the loops, for efficiency.
2764         */
2765         if(conditionIsSatisfied(conditionIdIn => tempConditionId,
2766                                 itemClassIdIn => itemClassIdIn,
2767                                 itemIndexIn => itemIndexIn)) then
2768           /*
2769             Remove all usages of this condition from the current condition-usage list, adding their
2770             rules to the pending-rule list.  tempIndex indexes the next currentAC variables.
2771             tempIndex2 indexes the current currentAC variables, which may be deleted.  tempIndex3
2772             indexes tempPendingRuleIds.
2773           */
2774           tempIndex := currentACUsageConditionIds.first;
2775           tempIndex3 := 0; /* pre-increment */
2776           while(tempIndex is not null) loop
2777             tempIndex2 := tempIndex;
2778             tempIndex := currentACUsageConditionIds.next(tempIndex);
2779             if(currentACUsageConditionIds(tempIndex2) = tempConditionId) then
2780               tempIndex3 := tempIndex3 + 1;
2781               tempPendingRuleIds(tempIndex3) := currentACUsageRuleIds(tempIndex2);
2782               currentACUsageConditionIds.delete(tempIndex2);
2783               currentACUsageRuleIds.delete(tempIndex2);
2784             end if;
2785           end loop;
2786           /* If a pending rule has no other usages, add it to the applicable-rules list. */
2787           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
2788             tempRuleApplies := true;
2789             tempIndex := currentACUsageConditionIds.first;
2790             while(tempIndex is not null) loop
2791               if(currentACUsageRuleIds(tempIndex) = tempPendingRuleIds(pendingRuleIndex)) then
2792                 tempRuleApplies := false;
2793                 exit;
2794               end if;
2795               tempIndex := currentACUsageConditionIds.next(tempIndex);
2796             end loop;
2797             if(tempRuleApplies) then
2798               tempIndex2 := engAppRuleIds.count + 1;
2799               tempRuleId := tempPendingRuleIds(pendingRuleIndex);
2800               engAppRuleIds(tempIndex2) := tempRuleId;
2801               engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId);
2802               engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
2803               engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId);
2804               engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId);
2805               engAppItemClassIds(tempIndex2) := itemClassIdIn;
2806               engAppItemIds(tempIndex2) := engItemIds(itemIndexIn);
2807               /*
2808                 doPerItemRuleEvaluation only evaluates subordinate-item-class rules, so here
2809                   engAppRuleItemClassIds(i) = engAppItemClassIds(i) and
2810                   engAppAppItemIds(i) = engAppItemIds(i)
2811                 always.
2812               */
2813               engAppRuleItemClassIds(tempIndex2) := itemClassIdIn;
2814               engAppAppItemIds(tempIndex2) := engItemIds(itemIndexIn);
2815             end if;
2816           end loop;
2817         else /* The condition is not satisfied. */
2818           /* Find all rules using the chosen condition. */
2819           tempIndex := currentACUsageConditionIds.first;
2820           tempIndex2 := 0; /* tempIndex2 indexes tempPendingRuleIds; pre-increment it. */
2821           while(tempIndex is not null) loop
2822             if(currentACUsageConditionIds(tempIndex) = tempConditionId) then
2823               tempIndex2 := tempIndex2 + 1;
2824               tempPendingRuleIds(tempIndex2) := currentACUsageRuleIds(tempIndex);
2825             end if;
2826             tempIndex := currentACUsageConditionIds.next(tempIndex);
2827           end loop;
2828           /*
2829             Remove all usages for rules using the chosen condition.  If the usage is for
2830             a condition other than the chosen condition, decrement that condition's
2831             rule count.  Here tempIndex indexes the next currentAC variable; tempIndex2
2832             indexes the current currentAC variable, which may be deleted; and tempIndex3
2833             indexes the engApp variables.
2834           */
2835           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
2836             tempIndex := currentACUsageConditionIds.first;
2837             while(tempIndex is not null) loop
2838               tempIndex2 := tempIndex;
2839               tempIndex := currentACUsageConditionIds.next(tempIndex);
2840               if(currentACUsageRuleIds(tempIndex2) = tempPendingRuleIds(pendingRuleIndex)) then
2841                 tempConditionId2 := currentACUsageConditionIds(tempIndex2);
2842                 if(tempConditionId2 <> tempConditionId) then
2843                   currentConditionRuleCounts(tempConditionId2) := currentConditionRuleCounts(tempConditionId2) - 1;
2844                 end if;
2845                 currentACUsageConditionIds.delete(tempIndex2);
2846                 currentACUsageRuleIds.delete(tempIndex2);
2847               end if;
2848             end loop;
2849           end loop;
2850         end if;
2851       end loop;
2852       exception
2853         when others then
2854           ame_util.runtimeException(packageNameIn => 'ame_engine',
2855                                     routineNameIn => 'doPerItemRuleEvaluation',
2856                                     exceptionNumberIn => sqlcode,
2857                                     exceptionStringIn => sqlerrm);
2858           raise;
2859     end doPerItemRuleEvaluation;
2860   procedure doStrictHeaderRuleEvaluation(itemClassIndexIn in integer,
2861                                          itemClassIdIn in integer) as
2862     currentACUsageConditionIds ame_util.idList;
2863     currentACUsageRuleIds ame_util.idList;
2864     headerItemIndex integer;
2865     tempFirstRuleIndex integer;
2866     tempLastRuleIndex integer;
2867     tempIndex integer;
2868     tempIndex2 integer;
2869     tempItemClassId integer;
2870     tempItemClassIndex integer;
2871     tempItemId ame_util.stringType;
2872     tempLowerLimit integer;
2873     tempRuleApplies boolean;
2874     tempRuleId integer;
2875     tempRuleId2 integer;
2876     tempUpperLimit integer;
2877     begin
2878       /* Handle the null case (no active conditions) first. */
2879       if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
2880         return;
2881       end if;
2882       /*
2883         A header-level rule can have conditions on attributes of at most one subordinate
2884         item class.  The active condition usages are sorted first by item class, then
2885         by rule ID; so within this procedure, the header item class' active condition
2886         usages are sorted by rule ID.  This procedure therefore loops through the rules
2887         in the active condition usages one rule at a time.  For each rule, if any of the
2888         conditions is defined on an attribute of a subordinate item class, the procedure
2889         loops through the items of that class, looking for an item that satisfies all of
2890         the rule's subordinate-item-level conditions.
2891       */
2892       /* Initialize the current condition usages. */
2893       tempIndex := 0; /* pre-increment */
2894       for ACUIndex in
2895         engACUsageFirstIndexes(itemClassIdIn) ..
2896         (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
2897         tempIndex := tempIndex + 1;
2898         currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
2899         currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
2900       end loop;
2901       if(currentACUsageRuleIds.count = 0) then
2902         /* There are no condition usages to process, so just return. */
2903         return;
2904       end if;
2905       headerItemIndex := engItemClassItemIdIndexes(itemClassIndexIn);
2906       tempFirstRuleIndex := 1;
2907       /* The following value of tempIndex is used throughout the remainder of the code; don't change it. */
2908       tempIndex := currentACUsageRuleIds.count;
2909       while(tempFirstRuleIndex is not null) loop
2910         tempRuleId := currentACUsageRuleIds(tempFirstRuleIndex);
2911         /* Find the last current condition usage with the rule ID tempRuleId. */
2912         tempLastRuleIndex := tempFirstRuleIndex;
2913         while(tempLastRuleIndex < tempIndex and
2914               currentACUsageRuleIds(tempLastRuleIndex + 1) = tempRuleId) loop
2915           tempLastRuleIndex := tempLastRuleIndex + 1;
2916         end loop;
2917         /*
2918           Determine whether the current rule references any conditions on attributes belonging
2919           to a subordinate item class.  If so, all such conditions are on the same item class,
2920           and tempItemClassId is its index.  Otherwise, tempItemClassId identifies the header
2921           item class, and tempItemId identifies the header item.
2922         */
2923         tempItemClassId := itemClassIdIn;
2924         tempItemId := engTransactionId;
2925         for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2926           tempItemClassId := engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex)));
2927           if(tempItemClassId <> itemClassIdIn) then
2928             exit;
2929           end if;
2930         end loop;
2931         tempRuleApplies := true;
2932         /* First loop through the header-level conditions. */
2933         for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2934           if(engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex))) = itemClassIdIn and
2935              not conditionIsSatisfied(conditionIdIn => currentACUsageConditionIds(ruleIndex),
2936                                       itemClassIdIn => itemClassIdIn,
2937                                       itemIndexIn   => headerItemIndex)) then
2938             tempRuleApplies := false;
2939             exit;
2940           end if;
2941         end loop;
2942         /*
2943           If the rule still applies and at least one condition is defined on a subordinate-item-level
2944           attribute, loop through the subordinate items, looking for an item that satisfies all of the
2945           rule's subordinate-item-level conditions.
2946         */
2947         if(tempRuleApplies and
2948            tempItemClassId <> itemClassIdIn) then
2949           tempItemClassIndex := engItemClassIndexes(tempItemClassId);
2950           tempLowerLimit := engItemClassItemIdIndexes(tempItemClassIndex);
2951           tempRuleApplies := false;
2952           /*
2953             If tempLowerLimit is null, no items exist in this item class, so the rule's conditions
2954             on attributes defined on the item class cannot be satisfied.  In this case, tempRuleApplies
2955             stays false.
2956           */
2957           if(tempLowerLimit is not null) then
2958             tempUpperLimit := (engItemClassItemIdIndexes(tempItemClassIndex) + engItemCounts(tempItemClassIndex) - 1);
2959             for itemIndex in tempLowerLimit .. tempUpperLimit loop
2960               for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2961                 if(engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex))) =
2962                      tempItemClassId) then
2963                   if(conditionIsSatisfied(conditionIdIn => currentACUsageConditionIds(ruleIndex),
2964                                           itemClassIdIn => tempItemClassId,
2965                                           itemIndexIn => itemIndex)) then
2966                     /* The rule is only satisfied if all the conditions have succeeded. */
2967                     if(ruleIndex = tempLastRuleIndex) then
2968                       tempRuleApplies := true;
2969                       tempItemId := engItemIds(itemIndex);
2970                       exit;
2971                     end if;
2972                   else
2973                     /*
2974                       The condition is not satisfied, so the current item does not satisfy the rule.
2975                       Leave tempRuleApplies false and exit the inner loop.
2976                     */
2977                     exit;
2978                   end if;
2979                 end if;
2980               end loop;
2981               if(tempRuleApplies) then
2982                 exit;
2983               end if;
2984             end loop;
2985           end if;
2986         end if;
2987         /* If the rule applies, write it to the applicable-rule package variables. */
2988         if(tempRuleApplies) then
2989           tempIndex2 := engAppRuleIds.count + 1;
2990           tempRuleId2 := currentACUsageRuleIds(tempFirstRuleIndex);
2991           engAppRuleIds(tempIndex2) := tempRuleId2;
2992           engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId2);
2993           engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
2994           engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId2);
2995           engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId2);
2996           /* These two variables indicate which item satisfied the rule. */
2997           engAppItemClassIds(tempIndex2) := tempItemClassId;
2998           engAppItemIds(tempIndex2) := tempItemId;
2999           /* These two variables indicate which item the rule applies to, i.e. the header item. */
3000           engAppRuleItemClassIds(tempIndex2) := itemClassIdIn;
3001           engAppAppItemIds(tempIndex2) := engTransactionId;
3002         end if;
3003         /* Iterate or exit the main loop. */
3004         if(tempLastRuleIndex < tempIndex) then
3005           tempFirstRuleIndex := tempLastRuleIndex + 1;
3006         else
3007           exit;
3008         end if;
3009       end loop;
3010       exception
3011         when others then
3012           ame_util.runtimeException(packageNameIn => 'ame_engine',
3013                                     routineNameIn => 'doStrictHeaderRuleEvaluation',
3014                                     exceptionNumberIn => sqlcode,
3015                                     exceptionStringIn => sqlerrm);
3016           raise;
3017     end doStrictHeaderRuleEvaluation;
3018   procedure doWeakHeaderRuleEvaluation(itemClassIndexIn in integer,
3019                                        itemClassIdIn in integer) as
3020     currentACUsageConditionIds ame_util.idList;
3021     currentACUsageRuleIds ame_util.idList;
3022     currentConditionRuleCounts ame_util.idList;
3023     tempAttributeItemClassIndex integer;
3024     tempConditionId integer;
3025     tempConditionId2 integer;
3026     tempConditionIsSatisfied boolean;
3027     tempHighestRuleCount integer;
3028     tempIndex integer;
3029     tempIndex2 integer;
3030     tempIndex3 integer;
3031     tempLowerLimit integer;
3032     tempPendingRuleIds ame_util.idList;
3033     tempRuleApplies boolean;
3034     tempRuleId integer;
3035     tempUpperLimit integer;
3036     begin
3037       /* Handle the null case (no active conditions) first. */
3038       if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
3039         return;
3040       end if;
3041       /*
3042         Initialize the current condition usages.  Note that while the currentACUsage local
3043         variables start out as compact lists, the algorithm that iterates through them
3044         deletes them in an unpredictable order, and does not re-compact the lists; so the
3045         algorithm must treat these lists as sparse.
3046       */
3047       tempIndex := 0; /* pre-increment */
3048       for ACUIndex in
3049         engACUsageFirstIndexes(itemClassIdIn) ..
3050         (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
3051         tempIndex := tempIndex + 1;
3052         currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
3053         currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
3054       end loop;
3055       /*
3056         Initialize the rule counts.  currentConditionRuleCounts is indexed by condition ID for
3057         efficiency (the alternative requires a lot more looping).
3058       */
3059       tempIndex := currentACUsageConditionIds.first;
3060       while(tempIndex is not null) loop
3061         tempConditionId := currentACUsageConditionIds(tempIndex);
3062         if(currentConditionRuleCounts.exists(tempConditionId)) then
3063           currentConditionRuleCounts(tempConditionId) := currentConditionRuleCounts(tempConditionId) + 1;
3064         else
3065           currentConditionRuleCounts(tempConditionId) := 1;
3066         end if;
3067         tempIndex := currentACUsageConditionIds.next(tempIndex);
3068       end loop;
3069       /* Loop through the condition usages. */
3070       while(currentACUsageConditionIds.count > 0) loop
3071         /* Set tempHighestRuleCount. */
3072         tempHighestRuleCount := 0;
3073         tempIndex := currentConditionRuleCounts.first;
3074         while(tempIndex is not null) loop
3075           if(tempHighestRuleCount < currentConditionRuleCounts(tempIndex)) then
3076             tempHighestRuleCount := currentConditionRuleCounts(tempIndex);
3077     /* Following line has been added to avoid the another while loop to      */
3078     /* find the condition with highest rule count. Issue 14 of the bug list  */
3079     /* No bug logged for this                                                */
3080     /* currentConditionRuleCounts is pl/sql list which is sparse and indexes */
3081     /* are nothig but condition_ids.Hence there is no need to find the       */
3082     /* condition_id which has highestRuleCount in another loop.after this    */
3083     /* while loop the tempConditionId is the condition with highestRuleCount.*/
3084             tempConditionId := tempIndex;
3085           end if;
3086           tempIndex := currentConditionRuleCounts.next(tempIndex);
3087         end loop;
3088         /* Clear the pending-rule list. */
3089         tempPendingRuleIds.delete;
3090         /*
3091           Choose the first condition with a maximal rule count.  Recall that currentConditionRuleCounts
3092           is indexed by condition ID.
3093         */
3094     /* Removing this while loop as we already know the condition with        */
3095     /* highest rule count                                                    */
3096     /*  tempConditionId := currentConditionRuleCounts.first;
3097         while(tempConditionId is not null) loop
3098           if(currentConditionRuleCounts(tempConditionId) = tempHighestRuleCount) then
3099             exit;
3100           end if;
3101           tempConditionId := currentConditionRuleCounts.next(tempConditionId);
3102         end loop;*/
3103         /* From now on, tempConditionId is the ID of the chosen condition with maximal rule count. */
3104         /* Delete this condition from currentConditionRuleCounts. */
3105         currentConditionRuleCounts.delete(tempConditionId);
3106         /*
3107           Test the condition for each item in the item class of the attribute on which the condition
3108           is defined, until an item satisfies the condition or no items are left.
3109         */
3110         tempAttributeItemClassIndex :=
3111           engItemClassIndexes(engAttributeItemClassIds(engACAttributeIds(tempConditionId)));
3112         tempConditionIsSatisfied := false;
3113         tempLowerLimit := engItemClassItemIdIndexes(tempAttributeItemClassIndex);
3114         if(tempLowerLimit is not null) then
3115           tempUpperLimit :=
3116             (engItemClassItemIdIndexes(tempAttributeItemClassIndex) + engItemCounts(tempAttributeItemClassIndex) - 1);
3117           for itemIndex in tempLowerLimit .. tempUpperLimit loop
3118             if(conditionIsSatisfied(conditionIdIn => tempConditionId,
3119                                     itemClassIdIn => engAttributeItemClassIds(engACAttributeIds(tempConditionId)),
3120                                     itemIndexIn   => itemIndex)) then
3121               tempConditionIsSatisfied := true;
3122               exit;
3123             end if;
3124           end loop;
3125         end if;
3126         /*
3127           If the condition is satisfied, eliminate its usages, and add any rules with no other
3128           usages to the applicable-rules list.  If the condition is not satisfied, just eliminate
3129           its usages, and any other usages for the rules in the condition's usages.
3130         */
3131         if(tempConditionIsSatisfied) then
3132           /*
3133             Remove all usages of this condition from the current condition-usage list, adding their
3134             rules to the pending-rule list.  tempIndex indexes the next currentAC variables.
3135             tempIndex2 indexes the current currentAC variables, which may be deleted.  tempIndex3
3136             indexes tempPendingRuleIds.
3137           */
3138           tempIndex := currentACUsageConditionIds.first;
3139           tempIndex3 := 0; /* pre-increment */
3140           while(tempIndex is not null) loop
3141             tempIndex2 := tempIndex;
3142             tempIndex := currentACUsageConditionIds.next(tempIndex);
3143             if(currentACUsageConditionIds(tempIndex2) = tempConditionId) then
3144               tempIndex3 := tempIndex3 + 1;
3145               tempPendingRuleIds(tempIndex3) := currentACUsageRuleIds(tempIndex2);
3146               currentACUsageConditionIds.delete(tempIndex2);
3147               currentACUsageRuleIds.delete(tempIndex2);
3148             end if;
3149           end loop;
3150           /* If a pending rule has no other usages, add it to the applicable-rules list. */
3151           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
3152             tempRuleApplies := true;
3153             tempIndex := currentACUsageConditionIds.first;
3154             while(tempIndex is not null) loop
3155               if(currentACUsageRuleIds(tempIndex) = tempPendingRuleIds(pendingRuleIndex)) then
3156                 tempRuleApplies := false;
3157                 exit;
3158               end if;
3159               tempIndex := currentACUsageConditionIds.next(tempIndex);
3160             end loop;
3161             if(tempRuleApplies) then
3162               tempIndex2 := engAppRuleIds.count + 1;
3163               tempRuleId := tempPendingRuleIds(pendingRuleIndex);
3164               engAppRuleIds(tempIndex2) := tempRuleId;
3165               engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId);
3166               engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
3167               engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId);
3168               engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId);
3169               engAppItemClassIds(tempIndex2) := itemClassIdIn;
3170               engAppItemIds(tempIndex2) := engTransactionId;
3171               /* In this case the satisfying item and item to which the rule applies always match. */
3172               engAppRuleItemClassIds(tempIndex2) := engAppItemClassIds(tempIndex2);
3173               engAppAppItemIds(tempIndex2) := engAppItemIds(tempIndex2);
3174             end if;
3175           end loop;
3176         else /* The condition is not satisfied. */
3177           /* Put all rules using the chosen condition in the pending-rule list. */
3178           tempIndex := currentACUsageConditionIds.first;
3179           tempIndex2 := 0; /* tempIndex2 indexes tempPendingRuleIds; pre-increment it. */
3180           while(tempIndex is not null) loop
3181             if(currentACUsageConditionIds(tempIndex) = tempConditionId) then
3182               tempIndex2 := tempIndex2 + 1;
3183               tempPendingRuleIds(tempIndex2) := currentACUsageRuleIds(tempIndex);
3184             end if;
3185             tempIndex := currentACUsageConditionIds.next(tempIndex);
3186           end loop;
3187           /*
3188             Remove all usages for rules using the chosen condition.  If the usage is for
3189             a condition other than the chosen condition, decrement that condition's
3190             rule count.  Here tempIndex indexes the next currentAC variable, and tempIndex2
3191             indexes the current currentAC variable (which may be deleted).
3192           */
3193           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
3194             tempIndex := currentACUsageConditionIds.first;
3195             while(tempIndex is not null) loop
3196               tempIndex2 := tempIndex;
3197               tempIndex := currentACUsageConditionIds.next(tempIndex);
3198               if(currentACUsageRuleIds(tempIndex2) = tempPendingRuleIds(pendingRuleIndex)) then
3199                 tempConditionId2 := currentACUsageConditionIds(tempIndex2);
3200                 if(tempConditionId2 <> tempConditionId) then
3201                   currentConditionRuleCounts(tempConditionId2) := currentConditionRuleCounts(tempConditionId2) - 1;
3202                 end if;
3203                 currentACUsageConditionIds.delete(tempIndex2);
3204                 currentACUsageRuleIds.delete(tempIndex2);
3205               end if;
3206             end loop;
3207           end loop;
3208         end if;
3209       end loop;
3210       exception
3211         when others then
3212           ame_util.runtimeException(packageNameIn => 'ame_engine',
3213                                     routineNameIn => 'doWeakHeaderRuleEvaluation',
3214                                     exceptionNumberIn => sqlcode,
3215                                     exceptionStringIn => sqlerrm);
3216           raise;
3217     end doWeakHeaderRuleEvaluation;
3218   procedure evaluateRules as
3219     /*
3220       conditionlessRuleCursor finds all rules having no ordinary or exception conditions
3221       that the current transaction type uses.
3222     */
3223     cursor conditionlessRuleCursor(processPrioritiesIn in varchar2,
3224                                    processProductionRulesIn in varchar2,
3225                                    combinationRulePriorityModeIn in varchar2,
3226                                    combinationRuleThresholdIn in integer,
3227                                    authorityRulePriorityModeIn in varchar2,
3228                                    authorityRuleThresholdIn in integer,
3229                                    exceptionRulePriorityModeIn in varchar2,
3230                                    exceptionRuleThresholdIn in integer,
3231                                    listModRulePriorityModeIn in varchar2,
3232                                    listModRuleThresholdIn in integer,
3233                                    substRulePriorityModeIn in varchar2,
3234                                    substRuleThresholdIn in integer,
3235                                    preRulePriorityModeIn in varchar2,
3236                                    preRuleThresholdIn in integer,
3237                                    postRulePriorityModeIn in varchar2,
3238                                    postRuleThresholdIn in integer,
3239                                    productionRulePriorityModeIn in varchar2,
3240                                    productionRuleThresholdIn in integer,
3241                                    headerItemClassIdIn in integer) is
3242       select
3243         ame_rules.rule_id rule_id,
3244         nvl(ame_rules.item_class_id,
3245             headerItemClassIdIn) item_class_id,
3246         ame_rules.rule_type rule_type,
3247         ame_rule_usages.priority priority,
3248         ame_rule_usages.approver_category approver_category
3249       from
3250         ame_rules,
3251         ame_rule_usages,
3252         ame_item_class_usages
3253       where
3254         ame_rules.rule_id = ame_rule_usages.rule_id and
3255         ame_rule_usages.item_id = engAmeApplicationId and
3256         nvl(ame_rules.item_class_id, headerItemClassIdIn) = ame_item_class_usages.item_class_id and
3257         ame_item_class_usages.application_id = engAmeApplicationId and
3258         (processPrioritiesIn = ame_util.booleanFalse or
3259          (ame_rules.rule_type = ame_util.combinationRuleType and
3260           (combinationRulePriorityModeIn <> ame_util.absoluteRulePriority or
3261            combinationRuleThresholdIn >= ame_rule_usages.priority)) or
3262          (ame_rules.rule_type = ame_util.authorityRuleType and
3263           (authorityRulePriorityModeIn <> ame_util.absoluteRulePriority or
3264            authorityRuleThresholdIn >= ame_rule_usages.priority)) or
3265          (ame_rules.rule_type = ame_util.exceptionRuleType and
3266           (exceptionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3267            exceptionRuleThresholdIn >= ame_rule_usages.priority)) or
3268          (ame_rules.rule_type = ame_util.listModRuleType and
3269           (listModRulePriorityModeIn <> ame_util.absoluteRulePriority or
3270            listModRuleThresholdIn >= ame_rule_usages.priority)) or
3271          (ame_rules.rule_type = ame_util.substitutionRuleType and
3272           (substRulePriorityModeIn <> ame_util.absoluteRulePriority or
3273            substRuleThresholdIn >= ame_rule_usages.priority)) or
3274          (ame_rules.rule_type = ame_util.preListGroupRuleType and
3275           (preRulePriorityModeIn <> ame_util.absoluteRulePriority or
3276            preRuleThresholdIn >= ame_rule_usages.priority)) or
3277          (ame_rules.rule_type = ame_util.postListGroupRuleType and
3278           (postRulePriorityModeIn <> ame_util.absoluteRulePriority or
3279            postRuleThresholdIn >= ame_rule_usages.priority)) or
3280          (ame_rules.rule_type = ame_util.productionRuleType and
3281           (productionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3282            productionRuleThresholdIn >= ame_rule_usages.priority))) and
3283         (processProductionRulesIn = ame_util.booleanTrue or
3284          ame_rules.rule_type <> ame_util.productionRuleType) and
3285         not exists (select *
3286                       from
3287                         ame_conditions,
3288                         ame_condition_usages
3289                       where
3290                         ame_conditions.condition_type <> ame_util.listModConditionType and
3291                         ame_conditions.condition_id = ame_condition_usages.condition_id and
3292                         ame_condition_usages.rule_id = ame_rules.rule_id and
3293                         engEffectiveRuleDate between
3294                           ame_conditions.start_date and
3295                           nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3296                         engEffectiveRuleDate between
3297                           ame_condition_usages.start_date and
3298                           nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3299                         /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
3300                         rownum < 2) and
3301         engEffectiveRuleDate between
3302           ame_rules.start_date and
3303           nvl(ame_rules.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3304         engEffectiveRuleDate between
3305           ame_rule_usages.start_date and
3306           nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3307         engEffectiveRuleDate between
3308           ame_item_class_usages.start_date and
3309           nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3310       order by
3311         ame_item_class_usages.item_class_order_number,
3312         item_class_id,
3313         ame_rules.rule_type,
3314         ame_rules.rule_id;
3315     conditionlessItemClassIds ame_util.idList;
3316     conditionlessRuleApprCats ame_util.charList;
3317     conditionlessRuleIds ame_util.idList;
3318     conditionlessRulePriorities ame_util.idList;
3319     conditionlessRuleTypes ame_util.stringList;
3320     errorCode integer;
3321     errorMessage ame_util.longestStringType;
3322     firstConditionlessRuleFound boolean;
3323     firstConditionlessRuleIndex integer;
3324     lastConditionlessRuleIndex integer;
3325     lowerBound integer;
3326     noRulesException exception;
3327     processPriorities ame_util.charType;
3328     processProductions ame_util.charType;
3329     tempIndex integer;
3330     tempItemClassId integer;
3331     upperBound integer;
3332     upperBound2 integer;
3333     begin
3334       /* Fetch all conditionless rules and store them in local variables. */
3335       if(engProcessPriorities) then
3336         processPriorities := ame_util.booleanTrue;
3337       else
3338         processPriorities := ame_util.booleanFalse;
3339       end if;
3340       if(engProcessProductionRules) then
3341         processProductions := ame_util.booleanTrue;
3342       else
3343         processProductions := ame_util.booleanFalse;
3344       end if;
3345       open conditionlessRuleCursor(processPrioritiesIn => processPriorities,
3346                                    processProductionRulesIn => processProductions,
3347                                    combinationRulePriorityModeIn => engPriorityModes(ame_util.combinationRuleType),
3348                                    combinationRuleThresholdIn => engPriorityThresholds(ame_util.combinationRuleType),
3349                                    authorityRulePriorityModeIn => engPriorityModes(ame_util.authorityRuleType),
3350                                    authorityRuleThresholdIn => engPriorityThresholds(ame_util.authorityRuleType),
3351                                    exceptionRulePriorityModeIn => engPriorityModes(ame_util.exceptionRuleType),
3352                                    exceptionRuleThresholdIn => engPriorityThresholds(ame_util.exceptionRuleType),
3353                                    listModRulePriorityModeIn => engPriorityModes(ame_util.listModRuleType),
3354                                    listModRuleThresholdIn => engPriorityThresholds(ame_util.listModRuleType),
3355                                    substRulePriorityModeIn => engPriorityModes(ame_util.substitutionRuleType),
3356                                    substRuleThresholdIn => engPriorityThresholds(ame_util.substitutionRuleType),
3357                                    preRulePriorityModeIn => engPriorityModes(ame_util.preListGroupRuleType),
3358                                    preRuleThresholdIn => engPriorityThresholds(ame_util.preListGroupRuleType),
3359                                    postRulePriorityModeIn => engPriorityModes(ame_util.postListGroupRuleType),
3360                                    postRuleThresholdIn => engPriorityThresholds(ame_util.postListGroupRuleType),
3361                                    productionRulePriorityModeIn => engPriorityModes(ame_util.productionRuleType),
3362                                    productionRuleThresholdIn => engPriorityThresholds(ame_util.productionRuleType),
3363                                    headerItemClassIdIn => getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
3364       fetch conditionlessRuleCursor bulk collect
3365         into
3366           conditionlessRuleIds,
3367           conditionlessItemClassIds,
3368           conditionlessRuleTypes,
3369           conditionlessRulePriorities,
3370           conditionlessRuleApprCats;
3371       close conditionlessRuleCursor;
3372       firstConditionlessRuleIndex := 0;
3373       lastConditionlessRuleIndex := 0;
3374       /*
3375         Loop through the item classes in engItemClassIds, evaluating the
3376         transaction type's rules for each item in each class.
3377       */
3378       for itemClassIndex in 1 .. engItemClassIds.count loop
3379         lowerBound := engItemClassItemIdIndexes(itemClassIndex);
3380         if(lowerBound is not null) then
3381           upperBound := engItemClassItemIdIndexes(itemClassIndex) + engItemCounts(itemClassIndex) - 1;
3382           tempItemClassId := engItemClassIds(itemClassIndex);
3383           /* Find this item class' conditionless rules. */
3384           firstConditionlessRuleFound := false;
3385           upperBound2 := conditionlessRuleIds.count;
3386           /* Following for loop modified for bug 4094058 Issue 19 */
3387           for i in firstConditionlessRuleIndex + 1 .. upperBound2 loop
3388             if(firstConditionlessRuleFound) then
3389               if(conditionlessItemClassIds(i) = tempItemClassId) then
3390                 lastConditionlessRuleIndex := i;
3391               end if;
3392             else
3393               if(conditionlessItemClassIds(i) = tempItemClassId) then
3394                 firstConditionlessRuleFound := true;
3395                 firstConditionlessRuleIndex := i;
3396                 lastConditionlessRuleIndex := i;
3397               end if;
3398             end if;
3399             if (i < upperBound2 and conditionlessItemClassIds(i+1) <> tempItemClassId) then
3400               exit;
3401             end if;
3402           end loop;
3403           /* Loop through the items in this item class. */
3404           for itemIndex in lowerBound .. upperBound loop
3405             /* Add any conditionless rules for the current item class to the current item's applicable-rule list. */
3406             if(firstConditionlessRuleFound) then
3407               tempIndex := engAppRuleIds.count; /* pre-increment */
3408               for conditionlessRuleIndex in firstConditionlessRuleIndex .. lastConditionlessRuleIndex loop
3409                 tempIndex := tempIndex + 1;
3410                 engAppRuleIds(tempIndex) := conditionlessRuleIds(conditionlessRuleIndex);
3411                 engAppPriorities(tempIndex) := conditionlessRulePriorities(conditionlessRuleIndex);
3412                 engAppApproverCategories(tempIndex) := conditionlessRuleApprCats(conditionlessRuleIndex);
3413                 engAppRuleTypes(tempIndex) := conditionlessRuleTypes(conditionlessRuleIndex);
3414                 engRuleAppliedYN(tempIndex) := ame_util.booleanTrue;
3415                 /* These are the item class and item to which the rule applies. */
3416                 engAppItemClassIds(tempIndex) := tempItemClassId;
3417                 engAppItemIds(tempIndex) := engItemIds(itemIndex);
3418                 /*
3419                   These are the item class and item that satisfy the rule.  By convention, for rules
3420                   having no ordinary conditions, these are the same as the item class and item to
3421                   which the rule applies.
3422                 */
3423                 engAppRuleItemClassIds(tempIndex) := tempItemClassId;
3424                 engAppAppItemIds(tempIndex) := engItemIds(itemIndex);
3425               end loop;
3426             end if;
3427             /* Evaluate the rules with conditions for this item. */
3428             if(engItemClassNames(itemClassIndex) = ame_util.headerItemClassName) then
3429               /*
3430                 The header item class always has exactly one item, so one of the procedures
3431                 in the following if/else will get called exactly once per engine cycle.
3432               */
3433               if(getHeaderAttValue2(attributeNameIn => ame_util.restrictiveItemEvalAttribute) =
3434                  ame_util.booleanAttributeTrue) then
3435                 doStrictHeaderRuleEvaluation(itemClassIndexIn => itemClassIndex,
3436                                              itemClassIdIn => tempItemClassId);
3437               else
3438                 doWeakHeaderRuleEvaluation(itemClassIndexIn => itemClassIndex,
3439                                            itemClassIdIn => tempItemClassId);
3440               end if;
3441             else
3442               /* Evaluate the rules in the active conditions for the current item only. */
3443               doPerItemRuleEvaluation(itemClassIdIn => tempItemClassId,
3444                                       itemIndexIn => itemIndex);
3445             end if;
3446           end loop;
3447         end if;
3448       end loop;
3449       /*
3450         So far, list-modification and substitution rules have been treated as if they belonged
3451         to the header item class.  Now set their item-class IDs and item IDs null and sort the
3452         applicable rules, so the list-modification and substitution rules get processed last.
3453       */
3454       for i in 1 .. engAppRuleIds.count loop
3455         if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3456           engRuleAppliedYN(i) := ame_util.booleanFalse;
3457           engAppLMSubItemClassIds(engAppRuleIds(i)) := engAppRuleItemClassIds(i);
3458           engAppLMSubItemIds(engAppRuleIds(i)) := engAppAppItemIds(i);
3459           engAppRuleItemClassIds(i) := null;
3460           engAppAppItemIds(i) := null;
3461         end if;
3462       end loop;
3463       sortApplicableRules(sortByActionTypeIn => false);
3464       /*
3465         Priority processing has so far occurred only for absolute priorities--for conditionless
3466         rules in the conditionlessRuleCursor in this procedure, for rule with conditions in the
3467         activeCondUsageCursor cursor of the procedure fetchActiveConditionUsages.  Now that the
3468         remaining applicable rules are sorted by rule type, we can process relative priorities.
3469       */
3470       if(engProcessPriorities) then
3471         processRelativePriorities;
3472       end if;
3473       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
3474         if engAppRuleIds.count = 0 then
3475           fnd_log.string
3476             (fnd_log.level_statement
3477             ,'ame_engine.evaluateRules'
3478             ,'*********** No Rules Applicable ************'
3479             );
3480         else
3481           for i in 1 .. engAppRuleIds.count loop
3482             fnd_log.string
3483               (fnd_log.level_statement
3484               ,'ame_engine.evaluateRules'
3485               ,'Applicable Rule ::: ' || engAppRuleIds(i)
3486               );
3487           end loop;
3488         end if;
3489       end if;
3490       /* Check for no rules, if AT_LEAST_ONE_RULE_MUST_APPLY is true. */
3491       if(getHeaderAttValue2(attributeNameIn => ame_util.atLeastOneRuleAttribute) = ame_util.booleanAttributeTrue and
3492          engAppRuleIds.count = 0) then
3493         raise noRulesException;
3494       end if;
3495       exception
3496         when noRulesException then
3497           errorCode := -20102;
3498           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
3499                                               messageNameIn => 'AME_400117_ENG_ONE_RULE_APPLY');
3500           ame_util.runtimeException(packageNameIn => 'ame_engine',
3501                                     routineNameIn => 'evaluateRules',
3502                                     exceptionNumberIn => errorCode,
3503                                     exceptionStringIn => errorMessage);
3504           raise_application_error(errorCode,
3505                                   errorMessage);
3506         when others then
3507           if(conditionlessRuleCursor%isopen) then
3508             close conditionlessRuleCursor;
3509           end if;
3510           ame_util.runtimeException(packageNameIn => 'ame_engine',
3511                                     routineNameIn => 'evaluateRules',
3512                                     exceptionNumberIn => sqlcode,
3513                                     exceptionStringIn => sqlerrm);
3514           raise;
3515     end evaluateRules;
3516   procedure fetchActiveConditionUsages as
3517     cursor activeCondStringValueCursor is
3518       select
3519         condition_id,
3520         string_value
3521       from ame_string_values
3522       where
3523         condition_id in
3524           (select ame_condition_usages.condition_id
3525             from
3526               ame_attributes,
3527               ame_conditions,
3528               ame_condition_usages,
3529               ame_rule_usages
3530             where
3531               ame_attributes.attribute_type = ame_util.stringAttributeType and
3532               ame_attributes.attribute_id = ame_conditions.attribute_id and
3533               ame_conditions.condition_id = ame_condition_usages.condition_id and
3534               ame_condition_usages.rule_id = ame_rule_usages.rule_id and
3535               ame_rule_usages.item_id = engAmeApplicationId and
3536               engEffectiveRuleDate between
3537                 ame_attributes.start_date and
3538                 nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3539               engEffectiveRuleDate between
3540                 ame_conditions.start_date and
3541                 nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3542               engEffectiveRuleDate between
3543                 ame_condition_usages.start_date and
3544                 nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3545               engEffectiveRuleDate between
3546                 ame_rule_usages.start_date and
3547                 nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)) and
3548         engEffectiveRuleDate between
3549           ame_string_values.start_date and
3550           nvl(ame_string_values.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3551       order by condition_id;
3552     cursor activeCondUsageCursor(processPrioritiesIn in varchar2,
3553                                  processProductionRulesIn in varchar2,
3554                                  combinationRulePriorityModeIn in varchar2,
3555                                  combinationRuleThresholdIn in integer,
3556                                  authorityRulePriorityModeIn in varchar2,
3557                                  authorityRuleThresholdIn in integer,
3558                                  exceptionRulePriorityModeIn in varchar2,
3559                                  exceptionRuleThresholdIn in integer,
3560                                  listModRulePriorityModeIn in varchar2,
3561                                  listModRuleThresholdIn in integer,
3562                                  substRulePriorityModeIn in varchar2,
3563                                  substRuleThresholdIn in integer,
3564                                  preRulePriorityModeIn in varchar2,
3565                                  preRuleThresholdIn in integer,
3566                                  postRulePriorityModeIn in varchar2,
3567                                  postRuleThresholdIn in integer,
3568                                  productionRulePriorityModeIn in varchar2,
3569                                  productionRuleThresholdIn in integer,
3570                                  headerItemClassIdIn in integer) is
3571       select
3572         ame_conditions.condition_id condition_id,
3573         ame_conditions.condition_type condition_type,
3574         ame_conditions.attribute_id attribute_id,
3575         ame_conditions.parameter_one parameter_one,
3576         ame_conditions.parameter_two parameter_two,
3577         ame_conditions.parameter_three parameter_three,
3578         ame_conditions.include_lower_limit,
3579         ame_conditions.include_upper_limit,
3580         ame_condition_usages.rule_id rule_id,
3581         ame_rules.rule_type rule_type,
3582         nvl(ame_rules.item_class_id,
3583             headerItemClassIdIn) rule_item_class,
3584         ame_rule_usages.priority priority,
3585         ame_rule_usages.approver_category
3586       from
3587         ame_attributes,
3588         ame_conditions,
3589         ame_condition_usages,
3590         ame_rules,
3591         ame_rule_usages
3592       where
3593         ame_attributes.attribute_id = ame_conditions.attribute_id and
3594         ame_conditions.condition_type <> ame_util.listModConditionType and
3595         ame_conditions.condition_id = ame_condition_usages.condition_id and
3596         ame_condition_usages.rule_id = ame_rules.rule_id and
3597         ame_rules.rule_id = ame_rule_usages.rule_id and
3598         ame_rule_usages.item_id = engAmeApplicationId and
3599         (processPrioritiesIn = ame_util.booleanFalse or
3600          (ame_rules.rule_type = ame_util.combinationRuleType and
3601           (combinationRulePriorityModeIn <> ame_util.absoluteRulePriority or
3602            combinationRuleThresholdIn >= ame_rule_usages.priority)) or
3603          (ame_rules.rule_type = ame_util.authorityRuleType and
3604           (authorityRulePriorityModeIn <> ame_util.absoluteRulePriority or
3605            authorityRuleThresholdIn >= ame_rule_usages.priority)) or
3606          (ame_rules.rule_type = ame_util.exceptionRuleType and
3607           (exceptionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3608            exceptionRuleThresholdIn >= ame_rule_usages.priority)) or
3609          (ame_rules.rule_type = ame_util.listModRuleType and
3610           (listModRulePriorityModeIn <> ame_util.absoluteRulePriority or
3611            listModRuleThresholdIn >= ame_rule_usages.priority)) or
3612          (ame_rules.rule_type = ame_util.substitutionRuleType and
3613           (substRulePriorityModeIn <> ame_util.absoluteRulePriority or
3614            substRuleThresholdIn >= ame_rule_usages.priority)) or
3615          (ame_rules.rule_type = ame_util.preListGroupRuleType and
3616           (preRulePriorityModeIn <> ame_util.absoluteRulePriority or
3617            preRuleThresholdIn >= ame_rule_usages.priority)) or
3618          (ame_rules.rule_type = ame_util.postListGroupRuleType and
3619           (postRulePriorityModeIn <> ame_util.absoluteRulePriority or
3620            postRuleThresholdIn >= ame_rule_usages.priority)) or
3621          (ame_rules.rule_type = ame_util.productionRuleType and
3622           (productionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3623            productionRuleThresholdIn >= ame_rule_usages.priority))) and
3624         (processProductionRulesIn = ame_util.booleanTrue or
3625          ame_rules.rule_type <> ame_util.productionRuleType) and
3626         engEffectiveRuleDate between
3627           ame_attributes.start_date and
3628           nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3629         engEffectiveRuleDate between
3630           ame_conditions.start_date and
3631           nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3632         engEffectiveRuleDate between
3633           ame_condition_usages.start_date and
3634           nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3635         engEffectiveRuleDate between
3636           ame_rules.start_date and
3637           nvl(ame_rules.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3638         engEffectiveRuleDate between
3639           ame_rule_usages.start_date and
3640           nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3641       order by
3642         rule_item_class,
3643         ame_rules.rule_type,
3644         ame_rules.rule_id,
3645         ame_attributes.item_class_id;
3646     /*
3647       The tempACU tables are buffers between the active-condition-usage fetch and
3648       the engAC variables.  The temp variables are indexed consecutively, while
3649       the engAC variables are indexed by condition ID or rule ID.
3650     */
3651     tempACUAttributeIds ame_util.idList;
3652     tempACUConditionTypes ame_util.stringList;
3653     tempACUIncludeLowerLimits ame_util.charList;
3654     tempACUIncludeUpperLimits ame_util.charList;
3655     tempACUItemClassIds ame_util.idList;
3656     tempACUParameterOnes ame_util.stringList;
3657     tempACUParameterThrees ame_util.stringList;
3658     tempACUParameterTwos ame_util.longStringList;
3659     tempACURuleApprCats ame_util.charList;
3660     tempACURulePriorities ame_util.idList;
3661     tempACURuleTypes ame_util.idList;
3662     /*
3663       tempACConditionIds is a buffer between the string-value fetch and the
3664       engACStringValue variables.
3665     */
3666     tempACConditionIds ame_util.idList;
3667     /* misc. local variables */
3668     processPriorities ame_util.charType;
3669     processProductions ame_util.charType;
3670     tempConditionID integer;
3671     tempCount integer;
3672     tempItemClassID integer;
3673     tempRuleId integer;
3674     begin
3675       /*
3676         Fetch all condition usages for conditions used by the rules that are used by
3677         the current transaction type.
3678       */
3679       if(engProcessPriorities) then
3680         processPriorities := ame_util.booleanTrue;
3681       else
3682         processPriorities := ame_util.booleanFalse;
3683       end if;
3684       if(engProcessProductionRules) then
3685         processProductions := ame_util.booleanTrue;
3686       else
3687         processProductions := ame_util.booleanFalse;
3688       end if;
3689       open activeCondUsageCursor(processPrioritiesIn => processPriorities,
3690                                  processProductionRulesIn => processProductions,
3691                                  combinationRulePriorityModeIn => engPriorityModes(ame_util.combinationRuleType),
3692                                  combinationRuleThresholdIn => engPriorityThresholds(ame_util.combinationRuleType),
3693                                  authorityRulePriorityModeIn => engPriorityModes(ame_util.authorityRuleType),
3694                                  authorityRuleThresholdIn => engPriorityThresholds(ame_util.authorityRuleType),
3695                                  exceptionRulePriorityModeIn => engPriorityModes(ame_util.exceptionRuleType),
3696                                  exceptionRuleThresholdIn => engPriorityThresholds(ame_util.exceptionRuleType),
3697                                  listModRulePriorityModeIn => engPriorityModes(ame_util.listModRuleType),
3698                                  listModRuleThresholdIn => engPriorityThresholds(ame_util.listModRuleType),
3699                                  substRulePriorityModeIn => engPriorityModes(ame_util.substitutionRuleType),
3700                                  substRuleThresholdIn => engPriorityThresholds(ame_util.substitutionRuleType),
3701                                  preRulePriorityModeIn => engPriorityModes(ame_util.preListGroupRuleType),
3702                                  preRuleThresholdIn => engPriorityThresholds(ame_util.preListGroupRuleType),
3703                                  postRulePriorityModeIn => engPriorityModes(ame_util.postListGroupRuleType),
3704                                  postRuleThresholdIn => engPriorityThresholds(ame_util.postListGroupRuleType),
3705                                  productionRulePriorityModeIn => engPriorityModes(ame_util.productionRuleType),
3706                                  productionRuleThresholdIn => engPriorityThresholds(ame_util.productionRuleType),
3707                                  headerItemClassIdIn => getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
3708       fetch activeCondUsageCursor bulk collect
3709         into
3710           engACUsageConditionIds,
3711           tempACUConditionTypes,
3712           tempACUAttributeIds,
3713           tempACUParameterOnes,
3714           tempACUParameterTwos,
3715           tempACUParameterThrees,
3716           tempACUIncludeLowerLimits,
3717           tempACUIncludeUpperLimits,
3718           engACUsageRuleIds,
3719           tempACURuleTypes,
3720           tempACUItemClassIds,
3721           tempACURulePriorities,
3722           tempACURuleApprCats;
3723       close activeCondUsageCursor;
3724       /*
3725         Loop through the active condition usages, writing their conditions to the
3726         engAC variables each time a new condition is encountered.
3727       */
3728       tempCount := engACUsageConditionIds.count;
3729       for activeCUIndex in 1 .. tempCount loop
3730         tempItemClassID := tempACUItemClassIds(activeCUIndex);
3731         tempConditionID := engACUsageConditionIds(activeCUIndex);
3732         if(not engACAttributeIds.exists(tempConditionID)) then
3733           engACAttributeIds(tempConditionID) := tempACUAttributeIds(activeCUIndex);
3734           engACConditionTypes(tempConditionID) := tempACUConditionTypes(activeCUIndex);
3735           engACParameterOnes(tempConditionID) := tempACUParameterOnes(activeCUIndex);
3736           engACParameterTwos(tempConditionID) := tempACUParameterTwos(activeCUIndex);
3737           engACParameterThrees(tempConditionID) := tempACUParameterThrees(activeCUIndex);
3738           engACIncludeLowerLimits(tempConditionID) := tempACUIncludeLowerLimits(activeCUIndex);
3739           engACIncludeUpperLimits(tempConditionID) := tempACUIncludeUpperLimits(activeCUIndex);
3740         end if;
3741         /*
3742           If this iteration starts an item class, record this iteration's index
3743           in engACUsageFirstIndexes.
3744         */
3745         if(activeCUIndex = 1 or
3746            tempItemClassID <> tempACUItemClassIds(activeCUIndex - 1)) then
3747           engACUsageFirstIndexes(tempItemClassID) := activeCUIndex;
3748         end if;
3749         /*
3750           If this iteration is the last iteration for its item class,
3751           record the item class' active-condition-usage count.
3752         */
3753         if(activeCUIndex = tempCount or
3754            tempItemClassID <> tempACUItemClassIds(activeCUIndex + 1)) then
3755           engACUsageItemClassCounts(tempItemClassID) :=
3756             activeCUIndex - engACUsageFirstIndexes(tempItemClassID) + 1;
3757         end if;
3758         /*
3759           Write the rule priority and rule type into engACUsageRulePriorities indexed by rule ID.
3760           This lets the engine fetch the rule priorities and types efficiently, without carrying
3761           them through all of its algorithms.
3762         */
3763         tempRuleId := engACUsageRuleIds(activeCUIndex);
3764         engACUsageRulePriorities(tempRuleId) := tempACURulePriorities(activeCUIndex);
3765         engACUsageRuleTypes(tempRuleId) := tempACURuleTypes(activeCUIndex);
3766         engACUsageRuleApprCategories(tempRuleId) := tempACURuleApprCats(activeCUIndex);
3767       end loop;
3768       /* Second, fetch the string values for any active conditions on string attributes. */
3769       open activeCondStringValueCursor;
3770       fetch activeCondStringValueCursor bulk collect
3771         into
3772           tempACConditionIds,
3773           engACStringValues;
3774       close activeCondStringValueCursor;
3775       /* Loop through the string conditions, writing them out to the engACStringValue variables. */
3776       tempCount := tempACConditionIds.count;
3777       for stringValueIndex in 1 .. tempCount loop
3778         tempConditionID := tempACConditionIds(stringValueIndex);
3779         /*
3780           If this iteration starts a condition's string-value list, record this
3781           iteration's index in engACStringValueFirstIndexes.
3782         */
3783         if(stringValueIndex = 1 or
3784            tempConditionID <> tempACConditionIds(stringValueIndex - 1)) then
3785           engACStringValueFirstIndexes(tempConditionID) := stringValueIndex;
3786         end if;
3787         /*
3788           engACStringValueCounts(condition_id) is the number of rows in
3789           engACStringValues for the condition with ID condition_id, starting at
3790           the index engACStringValueFirstIndexes(condition_id).
3791         */
3792         if(stringValueIndex = tempCount or
3793            tempConditionID <> tempACConditionIds(stringValueIndex + 1)) then
3794           engACStringValueCounts(tempConditionID) :=
3795             stringValueIndex - engACStringValueFirstIndexes(tempConditionID) + 1;
3796         end if;
3797       end loop;
3798       exception
3799         when others then
3800           if(activeCondUsageCursor%isopen) then
3801             close activeCondUsageCursor;
3802           end if;
3803           if(activeCondStringValueCursor%isopen) then
3804             close activeCondStringValueCursor;
3805           end if;
3806           ame_util.runtimeException(packageNameIn => 'ame_engine',
3807                                     routineNameIn => 'fetchActiveConditionUsages',
3808                                     exceptionNumberIn => sqlcode,
3809                                     exceptionStringIn => sqlerrm);
3810           raise;
3811     end fetchActiveConditionUsages;
3812   procedure fetchApplicableActions as
3813     cursor applicableActionsCursor(ruleIdIn in integer) is
3814       select
3815         ame_actions.action_type_id,
3816         ame_actions.parameter,
3817         ame_actions.parameter_two
3818         from
3819           ame_actions,
3820           ame_action_usages
3821         where
3822           ame_actions.action_id = ame_action_usages.action_id and
3823           ame_action_usages.rule_id = ruleIdIn and
3824           engEffectiveRuleDate between
3825             ame_actions.start_date and
3826             nvl(ame_actions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3827           engEffectiveRuleDate between
3828             ame_action_usages.start_date and
3829             nvl(ame_action_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate);
3830     productionActionTypeId integer;
3831     tempActionTypeIds ame_util.idList;
3832     tempBoolean boolean;
3833     tempNewRuleIndex integer;
3834     tempRuleCount integer;
3835     tempRuleIndex integer;
3836     tempParameters ame_util.stringList;
3837     tempParameterTwos ame_util.stringList;
3838     tempPerAppProdIndex integer;
3839     begin
3840       /* Initialize per-approver-production variables. */
3841       productionActionTypeId := getActionTypeId(actionTypeNameIn => ame_util.productionActionTypeName);
3842       tempPerAppProdIndex := 0; /* pre-increment */
3843       /* Delete priorities, to make sure they don't get used from here on. */
3844       engAppPriorities.delete;
3845       /* Fetch each applicable rule's actions. */
3846       tempRuleCount := engAppRuleIds.count;
3847       tempNewRuleIndex := tempRuleCount; /* pre-increment tempNewRuleIndex */
3848       for i in 1 .. tempRuleCount loop
3849         tempActionTypeIds.delete;
3850         tempParameters.delete;
3851         tempParameterTwos.delete;
3852         open applicableActionsCursor(ruleIdIn => engAppRuleIds(i));
3853         fetch applicableActionsCursor bulk collect
3854           into
3855             tempActionTypeIds,
3856             tempParameters,
3857             tempParameterTwos;
3858         close applicableActionsCursor;
3859         /* Populate the engAppPerAppProd variables. */
3860         if(engAppRuleTypes(i) <> ame_util.productionRuleType) then
3861           tempBoolean := true; /* Here tempBoolean is true until a production action for this rule is found. */
3862           for j in 1 .. tempActionTypeIds.count loop
3863             if(engActionTypeUsages(tempActionTypeIds(j)) = ame_util.productionRuleType) then
3864               tempPerAppProdIndex := tempPerAppProdIndex + 1;
3865               if(tempBoolean) then
3866                 tempBoolean := false;
3867                 engAppPerAppProdFirstIndexes(engAppRuleIds(i)) := tempPerAppProdIndex;
3868               end if;
3869               engAppPerAppProdRuleIds(tempPerAppProdIndex) := engAppRuleIds(i);
3870               engAppPerAppProdVariableNames(tempPerAppProdIndex) := tempParameters(j);
3871               engAppPerAppProdVariableValues(tempPerAppProdIndex) := tempParameterTwos(j);
3872               tempActionTypeIds(j) := null;  /* This prevents further processing later. */
3873             end if;
3874           end loop;
3875         end if;
3876         /*
3877           If the rule is a production rule, put the first action in the same row as the rule.
3878           Otherwise, put the first non-production action in that row.  (There should always be
3879           at least one non-production action in a non-production rule, and at least one production
3880           action in a production rule.)  Put any remaining actions (non-production actions, unless
3881           the rule is a production rule) in new rows.
3882         */
3883         /* Here tempBoolean is true until the first useable production action is found. */
3884         tempBoolean := true;
3885         for j in 1 .. tempActionTypeIds.count loop
3886           /* Ignore actions with null action-type IDs; these were per-approver production actions. */
3887           if(tempActionTypeIds(j) is not null) then
3888             if(tempBoolean) then
3889               tempBoolean := false;
3890               tempRuleIndex := i;
3891             else
3892               tempNewRuleIndex := tempNewRuleIndex + 1;
3893               tempRuleIndex := tempNewRuleIndex;
3894             end if;
3895             engAppItemClassIds(tempRuleIndex) := engAppItemClassIds(i);
3896             engAppItemIds(tempRuleIndex) := engAppItemIds(i);
3897             engAppRuleIds(tempRuleIndex) := engAppRuleIds(i);
3898             engRuleAppliedYN(tempRuleIndex) := engRuleAppliedYN(i);
3899             engAppRuleTypes(tempRuleIndex) := engAppRuleTypes(i);
3900             engAppApproverCategories(tempRuleIndex) := engAppApproverCategories(i);
3901             engAppActionTypeIds(tempRuleIndex) := tempActionTypeIds(j);
3902             engAppParameters(tempRuleIndex) := tempParameters(j);
3903             engAppParameterTwos(tempRuleIndex) := tempParameterTwos(j);
3904             engAppRuleItemClassIds(tempRuleIndex) := engAppRuleItemClassIds(i);
3905             engAppAppItemIds(tempRuleIndex) := engAppAppItemIds(i);
3906           end if;
3907         end loop;
3908       end loop;
3909       /* Convert combination rules to other rule types. */
3910       for i in 1 .. engAppRuleTypes.count loop
3911         if(engAppRuleTypes(i) = ame_util.combinationRuleType) then
3912           engAppRuleTypes(i) := engActionTypeUsages(engAppActionTypeIds(i));
3913           /* The following if statement was added to resolve bug 3522880. */
3914           if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3915             engAppLMSubItemClassIds(engAppRuleIds(i)) := engAppRuleItemClassIds(i);
3916             engAppLMSubItemIds(engAppRuleIds(i)) := engAppAppItemIds(i);
3917             engAppRuleItemClassIds(i) := null;
3918             engAppAppItemIds(i) := null;
3919           end if;
3920         end if;
3921       end loop;
3922       /*
3923         Sort all of the engApp lists:  first by item-class order number, then by
3924         item-class ID, then by item ID, then by rule type, then by action-type order
3925         number, then by action-type ID.  See engApp declaration comment block for
3926         details.
3927       */
3928       sortApplicableRules(sortByActionTypeIn => true);
3929       /* Restore the item-class IDs and item IDs of list-modification and substitution rules. */
3930       for i in 1 .. engAppRuleIds.count loop
3931         /* The following if statement was changed to resolve bug 3522880. */
3932         -- if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3933         if(engAppRuleItemClassIds(i) is null) then
3934           engAppRuleItemClassIds(i) := engAppLMSubItemClassIds(engAppRuleIds(i));
3935           engAppAppItemIds(i) := engAppLMSubItemIds(engAppRuleIds(i));
3936           engRuleAppliedYN(i) := ame_util.booleanFalse;
3937         end if;
3938       end loop;
3939       engAppLMSubItemClassIds.delete;
3940       engAppLMSubItemIds.delete;
3941       exception
3942         when others then
3943           if(applicableActionsCursor%isopen) then
3944             close applicableActionsCursor;
3945           end if;
3946           ame_util.runtimeException(packageNameIn => 'ame_engine',
3947                                     routineNameIn => 'fetchApplicableActions',
3948                                     exceptionNumberIn => sqlcode,
3949                                     exceptionStringIn => sqlerrm);
3950           raise;
3951     end fetchApplicableActions;
3952   procedure fetchAttributeValues(fetchInactivesIn in boolean) as
3953     cursor attributeCursor(applicationIdIn in integer,
3954                            fetchInactivesIn in varchar2) is
3955       select
3956         ame_attributes.attribute_id attribute_id,
3957         ame_attributes.name attribute_name,
3958         ame_attributes.attribute_type attribute_type,
3959         ame_attributes.item_class_id item_class_id,
3960         ame_attribute_usages.query_string,
3961         ame_attribute_usages.is_static
3962         from
3963           ame_attributes,
3964           ame_attribute_usages,
3965           ame_item_class_usages
3966         where
3967           ame_attributes.name not in (ame_util.workflowItemKeyAttribute, ame_util.workflowItemTypeAttribute) and
3968           ame_attributes.attribute_id = ame_attribute_usages.attribute_id and
3969           ame_attribute_usages.application_id = applicationIdIn and
3970           ame_item_class_usages.application_id = applicationIdIn and
3971           ame_attributes.item_class_id = ame_item_class_usages.item_class_id and
3972           (fetchInactivesIn = ame_util.booleanTrue or
3973            ame_attribute_usages.use_count > 0 or
3974            ame_attributes.attribute_id in
3975             (select ame_attributes2.attribute_id
3976               from
3977                 ame_attributes ame_attributes2,
3978                 ame_mandatory_attributes
3979               where
3980                 ame_attributes2.attribute_id = ame_mandatory_attributes.attribute_id and
3981                 ame_mandatory_attributes.action_type_id = -1 and
3982                 engEffectiveRuleDate between
3983                   ame_attributes2.start_date and
3984                   nvl(ame_attributes2.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3985                 engEffectiveRuleDate between
3986                   ame_mandatory_attributes.start_date and
3987                   nvl(ame_mandatory_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate))) and
3988           engEffectiveRuleDate between
3989             ame_attributes.start_date and
3990             nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3991           engEffectiveRuleDate between
3992             ame_attribute_usages.start_date and
3993             nvl(ame_attribute_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3994           engEffectiveRuleDate between
3995             ame_item_class_usages.start_date and
3996             nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3997         /*
3998           The order-by conditions are all necessary.  The second is to break
3999           item_class_order_number ties in a determinate order.  The third is
4000           to display attribute names in alphabetical order on the test tab.
4001           Compare the itemClassUsageCursor cursor in the procedure updateTransactionState.
4002         */
4003         order by
4004           ame_item_class_usages.item_class_order_number,
4005           ame_item_class_usages.item_class_id,
4006           ame_attributes.name;
4007     cursor testTransCurrencyCursor(attributeIdIn in integer) is
4008       select
4009         attribute_value_1,
4010         attribute_value_2,
4011         attribute_value_3
4012       from ame_test_trans_att_values
4013       where
4014         application_id = engAmeApplicationId and
4015         transaction_id = engTransactionId and
4016         attribute_id = attributeIdIn
4017       order by item_id;
4018     cursor testTransNonCurrencyCursor(attributeIdIn in integer) is
4019       select attribute_value_1
4020       from ame_test_trans_att_values
4021       where
4022         application_id = engAmeApplicationId and
4023         transaction_id = engTransactionId and
4024         attribute_id = attributeIdIn
4025       order by item_id;
4026     cursor testTransVariantHeaderCursor(attributeIdIn in integer) is
4027       select attribute_value_1
4028       from ame_test_trans_att_values
4029       where
4030         application_id = engAmeApplicationId and
4031         transaction_id = engTransactionId and
4032         attribute_id = attributeIdIn and
4033         item_class_id = getItemClassId(ame_util.headerItemClassName) and
4034         item_id = engTransactionId;
4035     attributeCount integer;
4036     attributeIds ame_util.idList;
4037     attributeItemClassIds ame_util.idList;
4038     attributeNames ame_util.stringList;
4039     attributeTypes ame_util.stringList;
4040     dynamicCursor integer;
4041     dynamicQuery ame_util.longestStringType;
4042     errorCode integer;
4043     errorMessage ame_util.longestStringType;
4044     fetchInactives varchar2(1);
4045     isStatics ame_util.charList;
4046     queryStrings ame_util.longestStringList;
4047     rowCountException exception;
4048     rowsFound integer;
4049     tempAttributeId integer;
4050     tempAttributeName ame_attributes.name%type;
4051     tempAttributeType ame_attributes.attribute_type%type;
4052     tempAttributeValue1 ame_util.attributeValueType;
4053     tempAttributeValue2 ame_util.attributeValueType;
4054     tempAttributeValue3 ame_util.attributeValueType;
4055     tempAttributeValueIndex integer;
4056     tempAttributeValues1 dbms_sql.varchar2_table;
4057     tempAttributeValues2 dbms_sql.varchar2_table;
4058     tempAttributeValues3 dbms_sql.varchar2_table;
4059     tempItemClassIndex integer;
4060     begin
4061       /*
4062         fetchInactives is necessary because we can't use a PL/SQL boolean variable
4063         in a select statement.
4064       */
4065       if(fetchInactivesIn) then
4066         fetchInactives := ame_util.booleanTrue;
4067       else
4068         fetchInactives := ame_util.booleanFalse;
4069       end if;
4070       /* Bulk fetch attributeCursor into a PL/SQL table. */
4071       open attributeCursor(applicationIdIn => engAmeApplicationId,
4072                            fetchInactivesIn => fetchInactives);
4073       fetch attributeCursor bulk collect
4074         into
4075           attributeIds,
4076           attributeNames,
4077           attributeTypes,
4078           attributeItemClassIds,
4079           queryStrings,
4080           isStatics;
4081       close attributeCursor;
4082       /*
4083         Fetch each attribute's value.  The attributes are in order of their item classes'
4084         item_class_order_numbers, so we can simply load them into the attribute package
4085         variables in index order, noting in engAttributeValueIndexes where each attribute's
4086         values start.
4087       */
4088       attributeCount := attributeIds.count;
4089       /* tempAttributeValueIndex indexes into engAttributeValues1-3.  Pre-increment it. */
4090       tempAttributeValueIndex := 0;
4091       for i in 1 .. attributeCount loop
4092         tempItemClassIndex := engItemClassIndexes(attributeItemClassIds(i));
4093         tempAttributeId := attributeIds(i);
4094         tempAttributeType := attributeTypes(i);
4095         /* Set the attribute's package variables, even if the attribute's item class has no items. */
4096         engAttributeIsStatics(tempAttributeId) := isStatics(i);
4097         engAttributeNames(tempAttributeId) := attributeNames(i);
4098         engAttributeTypes(tempAttributeId) := attributeTypes(i);
4099         engAttributeItemClassIds(tempAttributeId) := attributeItemClassIds(i);
4100         /* Check if the attribute is a variant and set the engAttributeQueries and engAttributeVariant accordingly */
4101         dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4102                                                replaceWithSpaces => true);
4103         if(checkAttributeVariant(attributeIdIn => tempAttributeId) = ame_util.booleanTrue) then
4104           if ((isStatics(i) = ame_util.booleanFalse) and
4105              (instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0 or
4106               instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0)) then
4107             engAttributeVariant(tempAttributeId) := ame_util.booleanTrue;
4108             engAttributeQueries(tempAttributeId) := queryStrings(i);
4109           end if;
4110         end if;
4111         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4112           fnd_log.string
4113             (fnd_log.level_statement
4114             ,'ame_engine.fetchAttributeValues'
4115             ,'Attribute ::: ' || engAttributeNames(tempAttributeId) || '(' || tempAttributeId || ')'
4116             );
4117         end if;
4118         /*
4119           Set this attribute's values in engAttributeValues1-3, if the attribute's item class
4120           has any items.
4121         */
4122         if(engItemCounts(tempItemClassIndex) = 0) then
4123           engAttributeValueIndexes(attributeIds(i)) := null;
4124         else
4125           /* (tempAttributeValueIndex will be pre-incremented when it's actually used.) */
4126           engAttributeValueIndexes(attributeIds(i)) := tempAttributeValueIndex + 1;
4127           if(engIsTestTransaction) then
4128               tempAttributeValues1.delete;
4129               tempAttributeValues2.delete;
4130               tempAttributeValues3.delete;
4131               if(checkAttributeVariant(tempAttributeId) = ame_util.booleanTrue) then
4132                 open testTransVariantHeaderCursor(attributeIdIn => tempAttributeId);
4133                 fetch testTransVariantHeaderCursor bulk collect
4134                   into tempAttributeValues1;
4135                 close testTransVariantHeaderCursor;
4136               else
4137                 if(tempAttributeType = ame_util.currencyAttributeType) then
4138                   open testTransCurrencyCursor(attributeIdIn => tempAttributeId);
4139                   fetch testTransCurrencyCursor bulk collect
4140                     into
4141                       tempAttributeValues1,
4142                       tempAttributeValues2,
4143                       tempAttributeValues3;
4144                   close testTransCurrencyCursor;
4145                 else
4146                   open testTransNonCurrencyCursor(attributeIdIn => tempAttributeId);
4147                   fetch testTransNonCurrencyCursor bulk collect
4148                     into tempAttributeValues1;
4149                   close testTransNonCurrencyCursor;
4150                 end if;
4151               end if;
4152               for j in 1 .. tempAttributeValues1.count loop
4153                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4154                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4155                 if(tempAttributeType = ame_util.currencyAttributeType) then
4156                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4157                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4158                 else
4159                   engAttributeValues2(tempAttributeValueIndex) := null;
4160                   engAttributeValues3(tempAttributeValueIndex) := null;
4161                 end if;
4162                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4163                   fnd_log.string
4164                     (fnd_log.level_statement
4165                     ,'ame_engine.fetchAttributeValues'
4166                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4167                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4168                     );
4169                 end if;
4170               end loop;
4171               if tempAttributeValues1.count = 0 then
4172                 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4173                   tempAttributeValueIndex := tempAttributeValueIndex + 1;
4174                   engAttributeValues1(tempAttributeValueIndex) := null;
4175                   engAttributeValues2(tempAttributeValueIndex) := null;
4176                   engAttributeValues3(tempAttributeValueIndex) := null;
4177                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4178                     fnd_log.string
4179                       (fnd_log.level_statement
4180                       ,'ame_engine.fetchAttributeValues'
4181                       ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4182                        ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4183                       );
4184                   end if;
4185                 end loop;
4186               end if;
4187           else
4188             if(isStatics(i) = ame_util.booleanTrue) then
4189               /*
4190                 Write the static usage into the attribute-value package variables once for each item
4191                 of the attribute's item class.
4192               */
4193               if(attributeTypes(i) = ame_util.currencyAttributeType) then
4194                 ame_util.parseStaticCurAttValue(applicationIdIn => engAmeApplicationId,
4195                                                 attributeIdIn => tempAttributeId,
4196                                                 attributeValueIn => queryStrings(i),
4197                                                 localErrorIn => false,
4198                                                 amountOut => tempAttributeValue1,
4199                                                 currencyOut => tempAttributeValue2,
4200                                                 conversionTypeOut => tempAttributeValue3);
4201               else
4202                 tempAttributeValue1 := queryStrings(i);
4203                 tempAttributeValue2 := null;
4204                 tempAttributeValue3 := null;
4205               end if;
4206               for j in 1 .. engItemCounts(tempItemClassIndex) loop
4207                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4208                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValue1;
4209                 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValue2;
4210                 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValue3;
4211                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4212                   fnd_log.string
4213                     (fnd_log.level_statement
4214                     ,'ame_engine.fetchAttributeValues'
4215                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4216                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4217                     );
4218                 end if;
4219               end loop;
4220             else
4221               tempAttributeValues1.delete;
4222               tempAttributeValues2.delete;
4223               tempAttributeValues3.delete;
4224               /*
4225                 We need to do old-style dynamic PL/SQL here to make sure all occurrences of
4226                 ame_util.transactionIdPlaceholder in dynamicQuery get bound.
4227               */
4228               dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4229                                                      replaceWithSpaces => true);
4230               dynamicCursor := dbms_sql.open_cursor;
4231               dbms_sql.parse(dynamicCursor,
4232                              dynamicQuery,
4233                              dbms_sql.native);
4234               if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
4235                 dbms_sql.bind_variable(dynamicCursor,
4236                                        ame_util.transactionIdPlaceholder,
4237                                        engTransactionId,
4238                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4239               end if;
4240               if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
4241                 dbms_sql.bind_variable(dynamicCursor,
4242                                        ame_util2.itemClassPlaceHolder,
4243                                        ame_util.headerItemClassName,
4244                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4245               end if;
4246               if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
4247                 dbms_sql.bind_variable(dynamicCursor,
4248                                        ame_util2.itemIdPlaceHolder,
4249                                        engTransactionId,
4250                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4251               end if;
4252               dbms_sql.define_array(dynamicCursor,
4253                                     1,
4254                                     tempAttributeValues1,
4255                                     ame_util.attributeValueTypeLength,
4256                                     1);
4257               if(tempAttributeType = ame_util.currencyAttributeType) then
4258                 dbms_sql.define_array(dynamicCursor,
4259                                       2,
4260                                       tempAttributeValues2,
4261                                       ame_util.attributeValueTypeLength,
4262                                       1);
4263                 dbms_sql.define_array(dynamicCursor,
4264                                       3,
4265                                       tempAttributeValues3,
4266                                       ame_util.attributeValueTypeLength,
4267                                       1);
4268               end if;
4269               rowsFound := dbms_sql.execute(dynamicCursor);
4270               loop
4271                 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
4272                 dbms_sql.column_value(dynamicCursor,
4273                                       1,
4274                                       tempAttributeValues1);
4275                 if(tempAttributeType = ame_util.currencyAttributeType) then
4276                   dbms_sql.column_value(dynamicCursor,
4277                                         2,
4278                                         tempAttributeValues2);
4279                   dbms_sql.column_value(dynamicCursor,
4280                                         3,
4281                                         tempAttributeValues3);
4282                 end if;
4283                 exit when rowsFound < 100;
4284               end loop;
4285               dbms_sql.close_cursor(dynamicCursor);
4286               /* Make sure the attribute usage returned the right number of rows. */
4287               if(tempAttributeValues1.count <> engItemCounts(tempItemClassIndex)) then
4288                 raise rowCountException;
4289               end if;
4290               /* Transfer the attribute values into the appropriate package variables. */
4291               for j in 1 .. tempAttributeValues1.count loop
4292                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4293                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4294                 if(tempAttributeType = ame_util.currencyAttributeType) then
4295                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4296                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4297                 else
4298                   engAttributeValues2(tempAttributeValueIndex) := null;
4299                   engAttributeValues3(tempAttributeValueIndex) := null;
4300                 end if;
4301                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4302                   fnd_log.string
4303                     (fnd_log.level_statement
4304                     ,'ame_engine.fetchAttributeValues'
4305                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4306                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4307                     );
4308                 end if;
4309               end loop;
4310             end if;
4311           end if;
4312         end if;
4313       end loop;
4314       exception
4315         when rowCountException then
4316           if(attributeCursor%isopen) then
4317             close attributeCursor;
4318           end if;
4319           if(dbms_sql.is_open(dynamicCursor)) then
4320             dbms_sql.close_cursor(dynamicCursor);
4321           end if;
4322           if(testTransCurrencyCursor%isopen) then
4323             close testTransCurrencyCursor;
4324           end if;
4325           if(testTransNonCurrencyCursor%isopen) then
4326             close testTransNonCurrencyCursor;
4327           end if;
4328           tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4329           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4330            fnd_log.string
4331             (fnd_log.level_statement
4332             ,'ame_engine.fetchAttributeValues'
4333             ,'Attribute ::: ' || tempAttributeName || '(' || tempAttributeId || ')'||
4334             'attribute returned ::'||tempAttributeValues1.count||'rows but the number of items for the '||
4335             'itemclass ::'||engItemCounts(tempItemClassIndex)
4336             );
4337           end if;
4338           errorCode := -20108;
4339           errorMessage :=
4340             ame_util.getMessage(applicationShortNameIn =>'PER',
4341                                 messageNameIn   => 'AME_400684_ATR_INV_DYN_USG',
4342                                 tokenNameOneIn  => 'ATTRIBUTE_NAME',
4343                                 tokenValueOneIn => tempAttributeName);
4344           ame_util.runtimeException(packageNameIn => 'ame_engine',
4345                                     routineNameIn => 'fetchAttributeValues',
4346                                     exceptionNumberIn => errorCode,
4347                                     exceptionStringIn => errorMessage);
4348           raise_application_error(errorCode,
4349                                   errorMessage);
4350         when others then
4351           if(attributeCursor%isopen) then
4352             close attributeCursor;
4353           end if;
4354           if(dbms_sql.is_open(dynamicCursor)) then
4355             dbms_sql.close_cursor(dynamicCursor);
4356           end if;
4357           if(testTransCurrencyCursor%isopen) then
4358             close testTransCurrencyCursor;
4359           end if;
4360           if(testTransNonCurrencyCursor%isopen) then
4361             close testTransNonCurrencyCursor;
4362           end if;
4363           tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4364           errorMessage := sqlerrm;
4365           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4366            fnd_log.string
4367             (fnd_log.level_statement
4368             ,'ame_engine.fetchAttributeValues'
4369             ,'Attribute ::: ' || tempAttributeName || '(' || tempAttributeId || '),error:'||errorMessage
4370             );
4371            end if;
4372           ame_util.runtimeException(packageNameIn => 'ame_engine',
4373                                     routineNameIn => 'fetchAttributeValues',
4374                                     exceptionNumberIn => sqlcode,
4375                                     exceptionStringIn => errorMessage);
4376           raise;
4377     end fetchAttributeValues;
4378   procedure fetchOtherAttributeValues as
4379     cursor attributeCursor(applicationIdIn in integer) is
4380       select
4381         ame_attributes.attribute_id attribute_id,
4382         ame_attributes.name attribute_name,
4383         ame_attributes.attribute_type attribute_type,
4384         ame_attributes.item_class_id item_class_id,
4385         ame_attribute_usages.query_string,
4386         ame_attribute_usages.is_static
4387         from
4388           ame_attributes,
4389           ame_attribute_usages,
4390           ame_item_class_usages
4391         where
4392           ame_attributes.name not in (ame_util.workflowItemKeyAttribute, ame_util.workflowItemTypeAttribute) and
4393           ame_attributes.attribute_id = ame_attribute_usages.attribute_id and
4394           ame_attribute_usages.application_id = applicationIdIn and
4395           ame_item_class_usages.application_id = applicationIdIn and
4396           ame_attributes.item_class_id = ame_item_class_usages.item_class_id and
4397           (ame_attribute_usages.use_count = 0 and
4398            ame_attributes.attribute_id not in
4399             (select ame_attributes2.attribute_id
4400               from
4401                 ame_attributes ame_attributes2,
4402                 ame_mandatory_attributes
4403               where
4404                 ame_attributes2.attribute_id = ame_mandatory_attributes.attribute_id and
4405                 ame_mandatory_attributes.action_type_id = -1 and
4406                 sysdate between
4407                   ame_attributes2.start_date and
4408                   nvl(ame_attributes2.end_date - ame_util.oneSecond, sysdate) and
4409                 sysdate between
4410                   ame_mandatory_attributes.start_date and
4411                   nvl(ame_mandatory_attributes.end_date - ame_util.oneSecond, sysdate))) and
4412           sysdate between
4413             ame_attributes.start_date and
4414             nvl(ame_attributes.end_date - ame_util.oneSecond, sysdate) and
4415           sysdate between
4416             ame_attribute_usages.start_date and
4417             nvl(ame_attribute_usages.end_date - ame_util.oneSecond, sysdate) and
4418           sysdate between
4419             ame_item_class_usages.start_date and
4420             nvl(ame_item_class_usages.end_date - ame_util.oneSecond, sysdate) and
4421             -- Condition to check whether the attribute is used in the rule
4422             exists
4423             (
4424               select 1
4425                from ame_conditions,
4426                     ame_condition_usages,
4427                     ame_rules,
4428                     ame_rule_usages
4429               where ame_conditions.attribute_id = ame_attributes.attribute_id
4430                 and ame_conditions.condition_id = ame_condition_usages.condition_id
4431                 and ame_condition_usages.rule_id = ame_rules.rule_id
4432                 and ame_rules.rule_id = ame_rule_usages.rule_id
4433                 and ame_rule_usages.item_id = applicationIdIn
4434                 and ((engEffectiveRuleDate between ame_rules.start_date
4435                         and nvl(ame_rules.end_date - (1/86400), engEffectiveRuleDate)))
4436                 and ((engEffectiveRuleDate between ame_rule_usages.start_date
4437                         and nvl(ame_rule_usages.end_date - (1/86400), engEffectiveRuleDate)))
4438                 and engEffectiveRuleDate between ame_conditions.start_date
4439                       and nvl(ame_conditions.end_date - (1/86400), engEffectiveRuleDate)
4440                 and ((engEffectiveRuleDate between ame_condition_usages.start_date
4441                       and nvl(ame_condition_usages.end_date - (1/86400), engEffectiveRuleDate)))
4442               union
4443               select 1
4444                 from ame_mandatory_attributes,
4445                      ame_actions,
4446                      ame_action_usages,
4447                      ame_rules,
4448                      ame_rule_usages
4449                where ame_mandatory_attributes.attribute_id = ame_attributes.attribute_id
4450                  and ame_mandatory_attributes.action_type_id =
4451                         ame_actions.action_type_id
4452                  and ame_actions.action_id = ame_action_usages.action_id
4453                  and ame_action_usages.rule_id = ame_rules.rule_id
4454                  and ame_rules.rule_id = ame_rule_usages.rule_id
4455                  and ame_rule_usages.item_id = applicationIdIn
4456                  and ((engEffectiveRuleDate between ame_rules.start_date
4457                  and nvl(ame_rules.end_date - (1/86400), engEffectiveRuleDate)))
4458                  and ((engEffectiveRuleDate between ame_rule_usages.start_date
4459                  and nvl(ame_rule_usages.end_date - (1/86400), engEffectiveRuleDate)))
4460                  and engEffectiveRuleDate between ame_mandatory_attributes.start_date
4461                  and nvl(ame_mandatory_attributes.end_date - (1/86400), engEffectiveRuleDate)
4462                  and engEffectiveRuleDate between ame_actions.start_date
4463                  and nvl(ame_actions.end_date - (1/86400), engEffectiveRuleDate)
4464                  and ((engEffectiveRuleDate between ame_action_usages.start_date
4465                  and nvl(ame_action_usages.end_date - (1/86400), engEffectiveRuleDate)))
4466             )
4467         /*
4468           The order-by conditions are all necessary.  The second is to break
4469           item_class_order_number ties in a determinate order.  The third is
4470           to display attribute names in alphabetical order on the test tab.
4471           Compare the itemClassUsageCursor cursor in the procedure updateTransactionState.
4472         */
4473         order by
4474           ame_item_class_usages.item_class_order_number,
4475           ame_item_class_usages.item_class_id,
4476           ame_attributes.name;
4477     cursor testTransCurrencyCursor(attributeIdIn in integer) is
4478       select
4479         attribute_value_1,
4480         attribute_value_2,
4481         attribute_value_3
4482       from ame_test_trans_att_values
4483       where
4484         application_id = engAmeApplicationId and
4485         transaction_id = engTransactionId and
4486         attribute_id = attributeIdIn
4487       order by item_id;
4488     cursor testTransNonCurrencyCursor(attributeIdIn in integer) is
4489       select attribute_value_1
4490       from ame_test_trans_att_values
4491       where
4492         application_id = engAmeApplicationId and
4493         transaction_id = engTransactionId and
4494         attribute_id = attributeIdIn
4495       order by item_id;
4496     cursor testTransVariantHeaderCursor(attributeIdIn in integer) is
4497       select attribute_value_1
4498       from ame_test_trans_att_values
4499       where
4500         application_id = engAmeApplicationId and
4501         transaction_id = engTransactionId and
4502         attribute_id = attributeIdIn and
4503         item_class_id = getItemClassId(ame_util.headerItemClassName) and
4504         item_id = engTransactionId;
4505     attributeCount integer;
4506     attributeIds ame_util.idList;
4507     attributeItemClassIds ame_util.idList;
4508     attributeNames ame_util.stringList;
4509     attributeTypes ame_util.stringList;
4510     dynamicCursor integer;
4511     dynamicQuery ame_util.longestStringType;
4512     errorCode integer;
4513     errorMessage ame_util.longestStringType;
4514     fetchInactives varchar2(1);
4515     isStatics ame_util.charList;
4516     queryStrings ame_util.longestStringList;
4517     rowCountException exception;
4518     rowsFound integer;
4519     tempAttributeId integer;
4520     tempAttributeName ame_attributes.name%type;
4521     tempAttributeType ame_attributes.attribute_type%type;
4522     tempAttributeValue1 ame_util.attributeValueType;
4523     tempAttributeValue2 ame_util.attributeValueType;
4524     tempAttributeValue3 ame_util.attributeValueType;
4525     tempAttributeValueIndex integer;
4526     tempAttributeValues1 dbms_sql.varchar2_table;
4527     tempAttributeValues2 dbms_sql.varchar2_table;
4528     tempAttributeValues3 dbms_sql.varchar2_table;
4529     tempItemClassIndex integer;
4530     begin
4531       open attributeCursor(applicationIdIn => engAmeApplicationId);
4532 
4533       fetch attributeCursor bulk collect
4534         into
4535           attributeIds,
4536           attributeNames,
4537           attributeTypes,
4538           attributeItemClassIds,
4539           queryStrings,
4540           isStatics;
4541       close attributeCursor;
4542       /*
4543         Fetch each attribute's value.  The attributes are in order of their item classes'
4544         item_class_order_numbers, so we can simply load them into the attribute package
4545         variables in index order, noting in engAttributeValueIndexes where each attribute's
4546         values start.
4547       */
4548       attributeCount := attributeIds.count;
4549       /* tempAttributeValueIndex indexes into engAttributeValues1-3.  Pre-increment it. */
4550       tempAttributeValueIndex := engAttributeValues1.last;--getMaxValueIndex;
4551       for i in 1 .. attributeCount loop
4552         tempItemClassIndex := engItemClassIndexes(attributeItemClassIds(i));
4553         tempAttributeId := attributeIds(i);
4554         tempAttributeType := attributeTypes(i);
4555         /* Set the attribute's package variables, even if the attribute's item class has no items. */
4556         engAttributeIsStatics(tempAttributeId) := isStatics(i);
4557         engAttributeNames(tempAttributeId) := attributeNames(i);
4558         engAttributeTypes(tempAttributeId) := attributeTypes(i);
4559         engAttributeItemClassIds(tempAttributeId) := attributeItemClassIds(i);
4560         /* Check if the attribute is a variant and set the engAttributeQueries and engAttributeVariant accordingly */
4561         dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4562                                                replaceWithSpaces => true);
4563         if(checkAttributeVariant(attributeIdIn => tempAttributeId) = ame_util.booleanTrue) then
4564           if ((isStatics(i) = ame_util.booleanFalse) and
4565              (instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0 or
4566               instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0)) then
4567             engAttributeVariant(tempAttributeId) := ame_util.booleanTrue;
4568             engAttributeQueries(tempAttributeId) := queryStrings(i);
4569           end if;
4570         end if;
4571         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4572           fnd_log.string
4573             (fnd_log.level_statement
4574             ,'ame_engine.fetchOtherAttributeValues'
4575             ,'Attribute ::: ' || engAttributeNames(tempAttributeId) || '(' || tempAttributeId || ')'
4576             );
4577         end if;
4578         /*
4579           Set this attribute's values in engAttributeValues1-3, if the attribute's item class
4580           has any items.
4581         */
4582         if(engItemCounts(tempItemClassIndex) = 0) then
4583           engAttributeValueIndexes(attributeIds(i)) := null;
4584         else
4585           /* (tempAttributeValueIndex will be pre-incremented when it's actually used.) */
4586           engAttributeValueIndexes(attributeIds(i)) := tempAttributeValueIndex + 1;
4587           if(engIsTestTransaction) then
4588               tempAttributeValues1.delete;
4589               tempAttributeValues2.delete;
4590               tempAttributeValues3.delete;
4591               if(checkAttributeVariant(tempAttributeId) = ame_util.booleanTrue) then
4592                 open testTransVariantHeaderCursor(attributeIdIn => tempAttributeId);
4593                 fetch testTransVariantHeaderCursor bulk collect
4594                   into tempAttributeValues1;
4595                 close testTransVariantHeaderCursor;
4596               else
4597                 if(tempAttributeType = ame_util.currencyAttributeType) then
4598                   open testTransCurrencyCursor(attributeIdIn => tempAttributeId);
4599                   fetch testTransCurrencyCursor bulk collect
4600                     into
4601                       tempAttributeValues1,
4602                       tempAttributeValues2,
4603                       tempAttributeValues3;
4604                   close testTransCurrencyCursor;
4605                 else
4606                   open testTransNonCurrencyCursor(attributeIdIn => tempAttributeId);
4607                   fetch testTransNonCurrencyCursor bulk collect
4608                     into tempAttributeValues1;
4609                   close testTransNonCurrencyCursor;
4610                 end if;
4611               end if;
4612               for j in 1 .. tempAttributeValues1.count loop
4613                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4614                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4615                 if(tempAttributeType = ame_util.currencyAttributeType) then
4616                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4617                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4618                 else
4619                   engAttributeValues2(tempAttributeValueIndex) := null;
4620                   engAttributeValues3(tempAttributeValueIndex) := null;
4621                 end if;
4622                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4623                   fnd_log.string
4624                     (fnd_log.level_statement
4625                     ,'ame_engine.fetchOtherAttributeValues'
4626                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4627                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4628                     );
4629                 end if;
4630               end loop;
4631               if tempAttributeValues1.count = 0 then
4632                 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4633                   tempAttributeValueIndex := tempAttributeValueIndex + 1;
4634                   engAttributeValues1(tempAttributeValueIndex) := null;
4635                   engAttributeValues2(tempAttributeValueIndex) := null;
4636                   engAttributeValues3(tempAttributeValueIndex) := null;
4637                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4638                     fnd_log.string
4639                       (fnd_log.level_statement
4640                       ,'ame_engine.fetchOtherAttributeValues'
4641                       ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4642                        ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4643                       );
4644                   end if;
4645                 end loop;
4646               end if;
4647           else
4648             if(isStatics(i) = ame_util.booleanTrue) then
4649               /*
4650                 Write the static usage into the attribute-value package variables once for each item
4651                 of the attribute's item class.
4652               */
4653               if(attributeTypes(i) = ame_util.currencyAttributeType) then
4654                 ame_util.parseStaticCurAttValue(applicationIdIn => engAmeApplicationId,
4655                                                 attributeIdIn => tempAttributeId,
4656                                                 attributeValueIn => queryStrings(i),
4657                                                 localErrorIn => false,
4658                                                 amountOut => tempAttributeValue1,
4659                                                 currencyOut => tempAttributeValue2,
4660                                                 conversionTypeOut => tempAttributeValue3);
4661               else
4662                 tempAttributeValue1 := queryStrings(i);
4663                 tempAttributeValue2 := null;
4664                 tempAttributeValue3 := null;
4665               end if;
4666               for j in 1 .. engItemCounts(tempItemClassIndex) loop
4667                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4668                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValue1;
4669                 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValue2;
4670                 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValue3;
4671                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4672                   fnd_log.string
4673                     (fnd_log.level_statement
4674                     ,'ame_engine.fetchOtherAttributeValues'
4675                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4676                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4677                     );
4678                 end if;
4679               end loop;
4680             else
4681               tempAttributeValues1.delete;
4682               tempAttributeValues2.delete;
4683               tempAttributeValues3.delete;
4684               /*
4685                 We need to do old-style dynamic PL/SQL here to make sure all occurrences of
4686                 ame_util.transactionIdPlaceholder in dynamicQuery get bound.
4687               */
4688               dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4689                                                      replaceWithSpaces => true);
4690               dynamicCursor := dbms_sql.open_cursor;
4691               dbms_sql.parse(dynamicCursor,
4692                              dynamicQuery,
4693                              dbms_sql.native);
4694               if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
4695                 dbms_sql.bind_variable(dynamicCursor,
4696                                        ame_util.transactionIdPlaceholder,
4697                                        engTransactionId,
4698                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4699               end if;
4700               if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
4701                 dbms_sql.bind_variable(dynamicCursor,
4702                                        ame_util2.itemClassPlaceHolder,
4703                                        ame_util.headerItemClassName,
4704                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4705               end if;
4706               if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
4707                 dbms_sql.bind_variable(dynamicCursor,
4708                                        ame_util2.itemIdPlaceHolder,
4709                                        engTransactionId,
4710                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4711               end if;
4712               dbms_sql.define_array(dynamicCursor,
4713                                     1,
4714                                     tempAttributeValues1,
4715                                     ame_util.attributeValueTypeLength,
4716                                     1);
4717               if(tempAttributeType = ame_util.currencyAttributeType) then
4718                 dbms_sql.define_array(dynamicCursor,
4719                                       2,
4720                                       tempAttributeValues2,
4721                                       ame_util.attributeValueTypeLength,
4722                                       1);
4723                 dbms_sql.define_array(dynamicCursor,
4724                                       3,
4725                                       tempAttributeValues3,
4726                                       ame_util.attributeValueTypeLength,
4727                                       1);
4728               end if;
4729               rowsFound := dbms_sql.execute(dynamicCursor);
4730               loop
4731                 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
4732                 dbms_sql.column_value(dynamicCursor,
4733                                       1,
4734                                       tempAttributeValues1);
4735                 if(tempAttributeType = ame_util.currencyAttributeType) then
4736                   dbms_sql.column_value(dynamicCursor,
4737                                         2,
4738                                         tempAttributeValues2);
4739                   dbms_sql.column_value(dynamicCursor,
4740                                         3,
4741                                         tempAttributeValues3);
4742                 end if;
4743                 exit when rowsFound < 100;
4744               end loop;
4745               dbms_sql.close_cursor(dynamicCursor);
4746               /* Make sure the attribute usage returned the right number of rows. */
4747               if(tempAttributeValues1.count <> engItemCounts(tempItemClassIndex)) then
4748                 raise rowCountException;
4749               end if;
4750               /* Transfer the attribute values into the appropriate package variables. */
4751               for j in 1 .. tempAttributeValues1.count loop
4752                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4753                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4754                 if(tempAttributeType = ame_util.currencyAttributeType) then
4755                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4756                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4757                 else
4758                   engAttributeValues2(tempAttributeValueIndex) := null;
4759                   engAttributeValues3(tempAttributeValueIndex) := null;
4760                 end if;
4761                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4762                   fnd_log.string
4763                     (fnd_log.level_statement
4764                     ,'ame_engine.fetchOtherAttributeValues'
4765                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4766                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4767                     );
4768                 end if;
4769               end loop;
4770             end if;
4771           end if;
4772         end if;
4773       end loop;
4774       exception
4775         when rowCountException then
4776           if(attributeCursor%isopen) then
4777             close attributeCursor;
4778           end if;
4779           if(dbms_sql.is_open(dynamicCursor)) then
4780             dbms_sql.close_cursor(dynamicCursor);
4781           end if;
4782           if(testTransCurrencyCursor%isopen) then
4783             close testTransCurrencyCursor;
4784           end if;
4785           if(testTransNonCurrencyCursor%isopen) then
4786             close testTransNonCurrencyCursor;
4787           end if;
4788           tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4789           errorCode := -20108;
4790           errorMessage :=
4791             ame_util.getMessage(applicationShortNameIn =>'PER',
4792                                 messageNameIn   => 'AME_400684_ATR_INV_DYN_USG',
4793                                 tokenNameOneIn  => 'ATTRIBUTE_NAME',
4794                                 tokenValueOneIn => tempAttributeName);
4795           ame_util.runtimeException(packageNameIn => 'ame_engine',
4796                                     routineNameIn => 'fetchOtherAttributeValues',
4797                                     exceptionNumberIn => errorCode,
4798                                     exceptionStringIn => errorMessage);
4799           raise_application_error(errorCode,
4800                                   errorMessage);
4801         when others then
4802           if(attributeCursor%isopen) then
4803             close attributeCursor;
4804           end if;
4805           if(dbms_sql.is_open(dynamicCursor)) then
4806             dbms_sql.close_cursor(dynamicCursor);
4807           end if;
4808           if(testTransCurrencyCursor%isopen) then
4809             close testTransCurrencyCursor;
4810           end if;
4811           if(testTransNonCurrencyCursor%isopen) then
4812             close testTransNonCurrencyCursor;
4813           end if;
4814           ame_util.runtimeException(packageNameIn => 'ame_engine',
4815                                     routineNameIn => 'fetchOtherAttributeValues',
4816                                     exceptionNumberIn => sqlcode,
4817                                     exceptionStringIn => sqlerrm);
4818           raise;
4819     end fetchOtherAttributeValues;
4820   procedure fetchConfigVars as
4821     cursor actionTypeConfigCursor is
4822       select
4823         ame_action_type_config.action_type_id,
4824         ame_action_type_config.voting_regime,
4825         ame_action_type_config.order_number,
4826         ame_action_type_config.chain_ordering_mode,
4827         ame_action_types.name,
4828         ame_action_types.procedure_name,
4829         ame_action_type_usages.rule_type
4830         from
4831           ame_action_type_config,
4832           ame_action_types,
4833           ame_action_type_usages
4834         where
4835           ame_action_type_config.application_id = engAmeApplicationId and
4836           ame_action_types.action_type_id = ame_action_type_config.action_type_id and
4837           ame_action_type_usages.action_type_id = ame_action_types.action_type_id and
4838           /*
4839             Only action types for list-creation and exception rules have two action-type usages;
4840             all other action types have exactly one (current) action-type usage each.
4841           */
4842           ame_action_type_usages.rule_type <> ame_util.exceptionRuleType and
4843           engEffectiveRuleDate between
4844             ame_action_type_config.start_date and
4845             nvl(ame_action_type_config.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
4846           engEffectiveRuleDate between
4847             ame_action_types.start_date and
4848             nvl(ame_action_types.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
4849           engEffectiveRuleDate between
4850             ame_action_type_usages.start_date and
4851             nvl(ame_action_type_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
4852         order by ame_action_types.action_type_id;
4853     cursor configVarCursor is
4854       select
4855         decode(nvl(application_id,0),0,0,-1) application_id,
4856         /* modified from
4857            application_id to
4858            decode(nvl(application_id,0),0,0,-1) application_id
4859            for the bug 5614208 */
4860         variable_name,
4861         variable_value
4862         from ame_config_vars
4863         where
4864           (application_id = 0 or application_id is null or application_id = engAmeApplicationId) and
4865           /* Config vars can impact the approver list, so use engEffectiveRuleDate here. */
4866           engEffectiveRuleDate between
4867             start_date and
4868             nvl(end_date - ame_util.oneSecond, engEffectiveRuleDate)
4869         order by
4870           variable_name,
4871           application_id;
4872     appIds ame_util.idList;
4873     configVarIndex integer;
4874     variableNames ame_util.stringList;
4875     variableValues ame_util.longStringList;
4876     tempActionTypeId integer;
4877     tempActionTypeIds ame_util.idList;
4878     tempActionTypeNames ame_util.stringList;
4879     tempActionTypePackageNames ame_util.stringList;
4880     tempActionTypeUsages ame_util.idList;
4881     tempChainOrderingModes ame_util.charList;
4882     tempOrderNumbers ame_util.idList;
4883     tempVotingRegimes ame_util.charList;
4884     begin
4885       /* Fetch action-type configuration data. */
4886       open actionTypeConfigCursor;
4887       fetch actionTypeConfigCursor bulk collect
4888         into
4889           tempActionTypeIds,
4890           tempVotingRegimes,
4891           tempOrderNumbers,
4892           tempChainOrderingModes,
4893           tempActionTypeNames,
4894           tempActionTypePackageNames,
4895           tempActionTypeUsages;
4896       close actionTypeConfigCursor;
4897       for actionTypeIndex in 1 .. tempActionTypeIds.count loop
4898         tempActionTypeId := tempActionTypeIds(actionTypeIndex);
4899         engActionTypeChainOrderModes(tempActionTypeId) := tempChainOrderingModes(actionTypeIndex);
4900         engActionTypeOrderNumbers(tempActionTypeId) := tempOrderNumbers(actionTypeIndex);
4901         engActionTypeVotingRegimes(tempActionTypeId) := tempVotingRegimes(actionTypeIndex);
4902         engActionTypeNames(tempActionTypeId) := tempActionTypeNames(actionTypeIndex);
4903         engActionTypePackageNames(tempActionTypeId) := tempActionTypePackageNames(actionTypeIndex);
4904         engActionTypeUsages(tempActionTypeId) := tempActionTypeUsages(actionTypeIndex);
4905       end loop;
4906       /* Fetch configuration-variable values. */
4907       open configVarCursor;
4908       fetch configVarCursor bulk collect
4909         into
4910           appIds,
4911           variableNames,
4912           variableValues;
4913       close configVarCursor;
4914       /*
4915         This loop relies on the ordering of configVarCursor, which groups first by
4916         variable name, then by application ID.  Rows with null application ID follow
4917         rows with non-null application ID in this ordering, so if a transaction type
4918         has defined a value for a configuration variable, the loop will reach this
4919         value before reaching the default value.
4920       */
4921       /*
4922         Always write the first row to the package variables.  (This eliminates a
4923         comparison that would otherwise be necessary within the loop.)
4924       */
4925       engConfigVarNames(1) := variableNames(1);
4926       engConfigVarValues(1) := variableValues(1);
4927       configVarIndex := 1; /* pre-increment */
4928       for i in 2 .. variableValues.count loop
4929         if(variableNames(i) <> variableNames(i - 1)) then
4930           configVarIndex := configVarIndex + 1;
4931           engConfigVarNames(configVarIndex) := variableNames(i);
4932           engConfigVarValues(configVarIndex) := variableValues(i);
4933           if(engConfigVarNames(configVarIndex) = ame_util.forwardingConfigVar) then
4934             parseForwardingBehaviors(forwardingBehaviorsIn => engConfigVarValues(configVarIndex));
4935           elsif(engConfigVarNames(configVarIndex) = ame_util.rulePriorityModesConfigVar) then
4936             parsePriorityModes(priorityModesIn => engConfigVarValues(configVarIndex));
4937           end if;
4938         end if;
4939       end loop;
4940       exception
4941         when others then
4942           if(actionTypeConfigCursor%isopen) then
4943             close actionTypeConfigCursor;
4944           end if;
4945           if(configVarCursor%isopen) then
4946             close configVarCursor;
4947           end if;
4948           ame_util.runtimeException(packageNameIn => 'ame_engine',
4949                                     routineNameIn => 'fetchConfigVars',
4950                                     exceptionNumberIn => sqlcode,
4951                                     exceptionStringIn => sqlerrm);
4952           raise;
4953     end fetchConfigVars;
4954   procedure fetchDeletedApprovers as
4955     cursor deletedApproversCursor(applicationIdIn in integer,
4956                                   transactionIdIn in varchar2) is
4957       select
4958         name,
4959         item_class,
4960         item_id,
4961         approver_category,
4962         action_type_id,
4963         group_or_chain_id,
4964         occurrence,
4965         effective_date,
4966         reason
4967         from ame_temp_deletions
4968         where
4969           application_id = applicationIdIn and
4970           transaction_id = transactionIdIn;
4971     actionTypeIds ame_util.idList;
4972     approverCategories ame_util.charList;
4973     approverNames ame_util.longStringList;
4974     groupOrChainIds ame_util.idList;
4975     itemClasses ame_util.stringList;
4976     itemIds ame_util.stringList;
4977     occurrences ame_util.idList;
4978     upperLimit integer;
4979     tempSuppressionDateList ame_util.dateList;
4980     tempReasonList ame_util.stringList;
4981     begin
4982       open deletedApproversCursor(applicationIdIn => engAmeApplicationId,
4983                                    transactionIdIn => engTransactionId);
4984       fetch deletedApproversCursor bulk collect
4985         into
4986           approverNames,
4987           itemClasses,
4988           itemIds,
4989           approverCategories,
4990           actionTypeIds,
4991           groupOrChainIds,
4992           occurrences,
4993           engSuppressionDateList,
4994           engSupperssionReasonList;
4995       close deletedApproversCursor;
4996       upperLimit := actionTypeIds.count;
4997       for i in 1 .. upperLimit loop
4998         engDeletedApproverList(i).name := approverNames(i);
4999         engDeletedApproverList(i).item_class := itemClasses(i);
5000         engDeletedApproverList(i).item_id := itemIds(i);
5001         engDeletedApproverList(i).approver_category := approverCategories(i);
5002         engDeletedApproverList(i).action_type_id := actionTypeIds(i);
5003         engDeletedApproverList(i).group_or_chain_id := groupOrChainIds(i);
5004         engDeletedApproverList(i).occurrence := occurrences(i);
5005       end loop;
5006       exception
5007         when others then
5008           if(deletedApproversCursor%isopen) then
5009             close deletedApproversCursor;
5010           end if;
5011           ame_util.runtimeException(packageNameIn => 'ame_engine',
5012                                     routineNameIn => 'fetchDeletedApprovers',
5013                                     exceptionNumberIn => sqlcode,
5014                                     exceptionStringIn => sqlerrm);
5015           raise;
5016     end fetchDeletedApprovers;
5017   procedure fetchInsertedApprovers as
5018     cursor insertedApproversCursor(applicationIdIn in integer,
5019                                    transactionIdIn in varchar2) is
5020       select
5021         name,
5022         item_class,
5023         item_id,
5024         nvl(approver_category,ame_util.approvalApproverCategory) approver_category,
5025         api_insertion,
5026         authority,
5027         order_type,
5028         parameter,
5029         special_forwardee,
5030         insertion_order,
5031         effective_date,
5032         reason,
5033         approval_status
5034         from ame_temp_insertions
5035         where
5036           application_id = applicationIdIn and
5037           transaction_id = transactionIdIn
5038           order by insertion_order;
5039     approverApiInsertions ame_util.charList;
5040     approverAuthorities ame_util.charList;
5041     approverCategories ame_util.charList;
5042     approverItemClasses ame_util.stringList;
5043     approverItemIds ame_util.stringList;
5044     approverNames ame_util.longStringList;
5045     approvalStatuses ame_util.stringList;
5046     upperLimit integer;
5047     l_error_code number;
5048     errorCode integer;
5049     errorMessage ame_util.longestStringType;
5050     begin
5051       open insertedApproversCursor(applicationIdIn => engAmeApplicationId,
5052                                    transactionIdIn => engTransactionId);
5053       fetch insertedApproversCursor bulk collect
5054         into
5055           approverNames,
5056           approverItemClasses,
5057           approverItemIds,
5058           approverCategories,
5059           approverApiInsertions,
5060           approverAuthorities,
5061           engInsertionOrderTypeList,
5062           engInsertionParameterList,
5063           engInsertionIsSpecialForwardee,
5064           engInsertionOrderList,
5065           engInsertionDateList,
5066           engInsertionReasonList,
5067           approvalStatuses;
5068       close insertedApproversCursor;
5069       upperLimit := approverAuthorities.count;
5070       for i in 1 .. upperLimit loop
5071         engInsertedApproverList(i).name := approverNames(i);
5072         engInsertedApproverList(i).item_class := approverItemClasses(i);
5073         engInsertedApproverList(i).item_id := approverItemIds(i);
5074         engInsertedApproverList(i).approver_category := approverCategories(i);
5075         engInsertedApproverList(i).api_insertion := approverApiInsertions(i);
5076         engInsertedApproverList(i).authority := approverAuthorities(i);
5077         engInsertedApproverList(i).approval_status := approvalStatuses(i);
5078       end loop;
5079       exception
5080         when others then
5081           if(insertedApproversCursor%isopen) then
5082             close insertedApproversCursor;
5083           end if;
5084           ame_util.runtimeException(packageNameIn => 'ame_engine',
5085                                     routineNameIn => 'fetchInsertedApprovers',
5086                                     exceptionNumberIn => sqlcode,
5087                                     exceptionStringIn => sqlerrm);
5088           raise;
5089     end fetchInsertedApprovers;
5090   procedure fetchItemClassData as
5091     cursor itemClassUsageCursor(applicationIdIn in integer) is
5092       select
5093         ame_item_classes.item_class_id,
5094         ame_item_classes.name,
5095         ame_item_class_usages.item_id_query,
5096         ame_item_class_usages.item_class_order_number,
5097         ame_item_class_usages.item_class_par_mode,
5098         ame_item_class_usages.item_class_sublist_mode
5099         from
5100           ame_item_classes,
5101           ame_item_class_usages
5102         where
5103           ame_item_classes.item_class_id = ame_item_class_usages.item_class_id and
5104           ame_item_class_usages.application_id = applicationIdIn and
5105           engEffectiveRuleDate between
5106             ame_item_classes.start_date and
5107             nvl(ame_item_classes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
5108           engEffectiveRuleDate between
5109             ame_item_class_usages.start_date and
5110             nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
5111         /*
5112           The order-by conditions are both critical.  The second is to break
5113           item_class_order_number ties in a determinate order.  Compare the
5114           attributeCursor cursor in the procedure fetchAttributeValues.
5115         */
5116         order by
5117           ame_item_class_usages.item_class_order_number,
5118           ame_item_class_usages.item_class_id;
5119     cursor testTransItemIdCursor(itemClassIdIn in integer) is
5120       select distinct item_id
5121       from ame_test_trans_att_values
5122       where
5123         application_id = engAmeApplicationId and
5124         transaction_id = engTransactionId and
5125         item_class_id = itemClassIdIn
5126       order by item_id;
5127     dynamicCursor integer;
5128     itemIdQuery ame_util.longestStringType;
5129     itemIds dbms_sql.varchar2_table;
5130     lastEngItemIdIndex integer;
5131     rowsFound integer;
5132     tempIndex integer;
5133     tempItemIdQueries ame_util.longestStringList;
5134     begin
5135       /* Fetch the item-class usages. */
5136       open itemClassUsageCursor(applicationIdIn => engAmeApplicationId);
5137       fetch itemClassUsageCursor bulk collect
5138         into
5139           engItemClassIds,
5140           engItemClassNames,
5141           tempItemIdQueries,
5142           engItemClassOrderNumbers,
5143           engItemClassParModes,
5144           engItemClassSublistModes;
5145       close itemClassUsageCursor;
5146       /* Fetch the item IDs. */
5147       lastEngItemIdIndex := null;
5148       for i in 1 .. engItemClassIds.count loop
5149         engItemClassIndexes(engItemClassIds(i)) := i;
5150         itemIds.delete;
5151         /* Fetch the current item class' item IDs into itemIds. */
5152         if(engItemClassNames(i) = ame_util.headerItemClassName) then
5153           /*
5154             The header item class should always have just one item, with the ID
5155             engTransactionId.  Note that the header item class may not be the
5156             first item class, as the item classes are ordered by item-class order
5157             number.  So lastEngItemIdIndex could be null.
5158           */
5159           if(lastEngItemIdIndex is null) then
5160             engItemClassItemIdIndexes(i) := 1;
5161             lastEngItemIdIndex := 1;
5162           else
5163             engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5164             lastEngItemIdIndex := lastEngItemIdIndex + 1;
5165           end if;
5166           engItemIds(lastEngItemIdIndex) := engTransactionId;
5167           engItemCounts(i) := 1;
5168         else /* This item class is not the header item class. */
5169           if(engIsTestTransaction) then
5170             open testTransItemIdCursor(itemClassIdIn => engItemClassIds(i));
5171             fetch testTransItemIdCursor bulk collect into itemIds;
5172             close testTransItemIdCursor;
5173             engItemCounts(i) := itemIds.count;
5174             if(itemIds.count > 0) then
5175               if(lastEngItemIdIndex is null) then
5176                 engItemClassItemIdIndexes(i) := 1;
5177                 lastEngItemIdIndex := itemIds.count;
5178               else
5179                 engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5180                 lastEngItemIdIndex := lastEngItemIdIndex + itemIds.count;
5181               end if;
5182               tempIndex := engItemClassItemIdIndexes(i); /* post-increment tempIndex */
5183               for j in 1 .. itemIds.count loop
5184                 engItemIds(tempIndex) := itemIds(j);
5185                 tempIndex := tempIndex + 1;
5186               end loop;
5187             else
5188               engItemClassItemIdIndexes(i) := null;
5189             end if;
5190           else
5191             itemIdQuery := ame_util.removeReturns(stringIn => tempItemIdQueries(i),
5192                                                   replaceWithSpaces => true);
5193             dynamicCursor := dbms_sql.open_cursor;
5194             dbms_sql.parse(dynamicCursor,
5195                            itemIdQuery,
5196                            dbms_sql.native);
5197             if(instrb(itemIdQuery, ame_util.transactionIdPlaceholder, 1, 1) > 0) then
5198               dbms_sql.bind_variable(dynamicCursor,
5199                                      ame_util.transactionIdPlaceholder,
5200                                      engTransactionId,
5201                                      50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
5202             end if;
5203             dbms_sql.define_array(dynamicCursor,
5204                                   1,
5205                                   itemIds,
5206                                   100,
5207                                   1);
5208             rowsFound := dbms_sql.execute(dynamicCursor);
5209             loop
5210               rowsFound := dbms_sql.fetch_rows(dynamicCursor);
5211               dbms_sql.column_value(dynamicCursor,
5212                                     1,
5213                                     itemIds);
5214               exit when rowsFound < 100;
5215             end loop;
5216             dbms_sql.close_cursor(dynamicCursor);
5217             /* Copy the item IDs into engItemIds. */
5218             engItemCounts(i) := itemIds.count;
5219             if(itemIds.count > 0) then
5220               if(lastEngItemIdIndex is null) then
5221                 engItemClassItemIdIndexes(i) := 1;
5222                 lastEngItemIdIndex := itemIds.count;
5223               else
5224                 engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5225                 lastEngItemIdIndex := lastEngItemIdIndex + itemIds.count;
5226               end if;
5227               tempIndex := engItemClassItemIdIndexes(i); /* post-increment tempIndex */
5228               for j in 1 .. itemIds.count loop
5229                 engItemIds(tempIndex) := itemIds(j);
5230                 tempIndex := tempIndex + 1;
5231               end loop;
5232             else
5233               engItemClassItemIdIndexes(i) := null;
5234             end if;
5235           end if;
5236         end if;
5237       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5238         fnd_log.string
5239           (fnd_log.level_statement
5240                  ,'ame_engine.fetchItemClassData'
5241                  ,'Item Class ::' || engItemClassNames(i) ||
5242                   ':' || 'has ' || ':' || engItemCounts(i) || ':items'
5243            );
5244       end if;
5245       end loop;
5246       exception
5247         when others then
5248           if(itemClassUsageCursor%isopen) then
5249             close itemClassUsageCursor;
5250           end if;
5251           if(testTransItemIdCursor%isopen) then
5252             close testTransItemIdCursor;
5253           end if;
5254           ame_util.runtimeException(packageNameIn => 'ame_engine',
5255                                     routineNameIn => 'fetchItemClassData',
5256                                     exceptionNumberIn => sqlcode,
5257                                     exceptionStringIn => sqlerrm);
5258           raise;
5259     end fetchItemClassData;
5260   procedure fetchFndApplicationId(applicationIdIn in integer,
5261                                   fndApplicationIdOut out nocopy integer,
5262                                   transactionTypeIdOut out nocopy varchar2) as
5263     begin
5264       select
5265         fnd_application_id,
5266         transaction_type_id
5267         into
5268           fndApplicationIdOut,
5269           transactionTypeIdOut
5270         from ame_calling_apps
5271         where
5272           application_id = applicationIdIn and
5273           /* Don't use engEffectiveRuleDate here. */
5274           sysdate between
5275             start_date and
5276             nvl(end_date - ame_util.oneSecond, sysdate) and
5277           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
5278       exception
5279         when others then
5280           ame_util.runtimeException(packageNameIn => 'ame_engine',
5281                                     routineNameIn => 'fetchFndApplicationId',
5282                                     exceptionNumberIn => sqlcode,
5283                                     exceptionStringIn => sqlerrm);
5284           fndApplicationIdOut := null;
5285           transactionTypeIdOut := null;
5286           raise;
5287     end fetchFndApplicationId;
5288   procedure fetchOldApprovers as
5289     cursor oldApproversCursor(applicationIdIn in integer,
5290                               transactionIdIn in varchar2) is
5291       select
5292         name,
5293         item_class,
5294         item_id,
5295         approver_category,
5296         api_insertion,
5297         authority,
5298         approval_status,
5299         action_type_id,
5300         group_or_chain_id,
5301         occurrence
5302         from ame_temp_old_approver_lists
5303         where
5304           application_id = applicationIdIn and
5305           transaction_id = transactionIdIn
5306           order by order_number;
5307     actionTypeIds ame_util.idList;
5308     approverApiInsertions ame_util.charList;
5309     approverAuthorities ame_util.charList;
5310     approverCategories ame_util.charList;
5311     approverNames ame_util.longStringList;
5312     approverStatuses ame_util.stringList;
5313     groupOrChainIds ame_util.idList;
5314     itemClasses ame_util.stringList;
5315     itemIds ame_util.stringList;
5316     occurrences ame_util.idList;
5317     upperLimit integer;
5318     begin
5319       open oldApproversCursor(applicationIdIn => engAmeApplicationId,
5320                               transactionIdIn => engTransactionId);
5321       fetch oldApproversCursor bulk collect
5322         into
5323           approverNames,
5324           itemClasses,
5325           itemIds,
5326           approverCategories,
5327           approverApiInsertions,
5328           approverAuthorities,
5329           approverStatuses,
5330           actionTypeIds,
5331           groupOrChainIds,
5332           occurrences;
5333       close oldApproversCursor;
5334       upperLimit := approverAuthorities.count;
5335       for i in 1 .. upperLimit loop
5336         engOldApproverList(i).name := approverNames(i);
5337         engOldApproverList(i).item_class := itemClasses(i);
5338         engOldApproverList(i).item_id := itemIds(i);
5339         engOldApproverList(i).approver_category := approverCategories(i);
5340         engOldApproverList(i).api_insertion := approverApiInsertions(i);
5341         engOldApproverList(i).authority := approverAuthorities(i);
5342         engOldApproverList(i).action_type_id := actionTypeIds(i);
5343         engOldApproverList(i).group_or_chain_id := groupOrChainIds(i);
5344         engOldApproverList(i).occurrence := occurrences(i);
5345         engOldApproverList(i).source := null;
5346         /* Force recalculation of suppressed and repeated statuses with each engine cycle. */
5347         if approverStatuses(i) in (ame_util.suppressedStatus, ame_util.repeatedStatus) then
5348           engOldApproverList(i).approval_status := null;
5349         else
5350           engOldApproverList(i).approval_status := approverStatuses(i);
5351         end if;
5352       end loop;
5353       exception
5354         when others then
5355           if(oldApproversCursor%isopen) then
5356             close oldApproversCursor;
5357           end if;
5358           ame_util.runtimeException(packageNameIn => 'ame_engine',
5359                                     routineNameIn => 'fetchOldApprovers',
5360                                     exceptionNumberIn => sqlcode,
5361                                     exceptionStringIn => sqlerrm);
5362           raise;
5363     end fetchOldApprovers;
5364     function isApproved(isDynamic in boolean
5365                         ,groupIdIn in number
5366                         ,origSystemIn in varchar2 default null
5367                         ,origSystemIdIn in number default null
5368                         ,roleNameIn in varchar2 default null) return boolean is
5369       cursor getInvalidDetails is
5370         select name
5371           from wf_local_roles
5372          where orig_system_id = origSystemIdIn
5373            and orig_system = origSystemIn
5374            and rownum <2;
5375       cursor getStatus(c_nameIn in varchar2) is
5376         select 1
5377          from dual
5378          where exists
5379            (select null
5380              from ame_trans_approval_history a
5381              where application_id = engAmeApplicationId
5382                and transaction_id = engTransactionId
5383                and group_or_chain_id = groupIdIn
5384                and name = c_nameIn
5385                and status is not null
5386                and status in (ame_util.approvedStatus
5387                                        ,ame_util.beatByFirstResponderStatus
5388                                        ,ame_util.forwardStatus
5389                                        ,ame_util.rejectStatus
5390                                        ,ame_util.approvedByRepeatedStatus
5391                                        ,ame_util.rejectedByRepeatedStatus
5392                                        ,ame_util.noResponseStatus
5393                                        ,ame_util2.noResponseByRepeatedStatus
5394                                        ,ame_util2.reassignStatus
5395                                        ,ame_util2.forwardByRepeatedStatus)
5396                and name = c_nameIn
5397                and row_timestamp in
5398                (select max(row_timestamp)
5399                  from ame_trans_approval_history
5400                  where application_id = engAmeApplicationId
5401                    and transaction_id = engTransactionId
5402                    and group_or_chain_id = groupIdIn
5403                    and  name = c_nameIn
5404                   group by name
5405                ));
5406      l_name varchar2(500);
5407      l_return_status boolean := false;
5408      l_count number := 0;
5409     begin
5410       if isDynamic then
5411         open getInvalidDetails;
5412         fetch getInvalidDetails into l_name;
5413         close getInvalidDetails;
5414         if l_name is null then
5415           return false;
5416         end if;
5417       else
5418         l_name := roleNameIn;
5419       end if;
5420       open getStatus(l_name);
5421       fetch getStatus into l_count;
5422       close getStatus;
5423 
5424       if l_count > 0 then
5425         return true;
5426       else
5427         return false;
5428       end if;
5429     end isApproved;
5430   procedure fetchRuntimeGroup(groupIdIn in integer) as
5431     cursor groupMemberCursor(groupIdIn in integer) is
5432       select
5433         orig_system,
5434         orig_system_id,
5435         parameter,
5436         upper(parameter_name),
5437         query_string,
5438         order_number
5439         from ame_approval_group_members
5440         where
5441           approval_group_id = groupIdIn
5442         order by order_number;
5443     badDynamicMemberException exception;
5444     dynamicCursor integer;
5445     colonLocation1 integer;
5446     colonLocation2 integer;
5447     displayNames ame_util.longStringList;
5448     errorCode integer;
5449     errorMessage ame_util.longestStringType;
5450     names ame_util.longStringList;
5451     orderNumbers ame_util.idList;
5452     origSystemIds ame_util.idList;
5453     origSystems ame_util.stringList;
5454     outputIndex integer;
5455     parameters ame_util.longStringList;
5456     queryStrings ame_util.longestStringList;
5457     rowsFound integer;
5458     tempGroupMembers dbms_sql.Varchar2_Table;
5459     upperParameterNames ame_util.stringList;
5460     tempApproverType ame_util.stringType;
5461     tempApproverId   ame_util.stringType;
5462     tempname         wf_roles.name%type;
5463     processFndUser boolean;
5464     l_err_code number;
5465     invgrpMemberException exception;
5466     l_isApproved boolean := false;
5467     l_name_out varchar2(400);
5468     l_display_name_out varchar2(500);
5469     l_appr_type varchar2(100);
5470     begin
5471       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5472         fnd_log.string
5473           (fnd_log.level_statement
5474             ,'ame_engine.fetchRuntimeGroup'
5475             ,'evaluating the group::'||ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5476                                                                       ,effectiveDateIn   => engEffectiveRuleDate)
5477            );
5478       end if;
5479       open groupMemberCursor(groupIdIn => groupIdIn);
5480       fetch groupMemberCursor bulk collect
5481         into
5482           origSystems,
5483           origSystemIds,
5484           parameters,
5485           upperParameterNames,
5486           queryStrings,
5487           orderNumbers;
5488       close groupMemberCursor;
5489       if (engGroupUseItemBind.exists(groupIdIn)) then
5490         /* This is not the first time this query is being executed, so find and delete all old approvers in this group. */
5491         for n in 1 .. engGroupMemberGroupIds.count loop
5492           if( engGroupMemberGroupIds(n) = groupIdIn ) then
5493             -- delete all occurrences of this
5494              engGroupMemberGroupIds(n) := null;
5495              engGroupMemberNames(n) := null;
5496              engGroupMemberOrderNumbers(n) := null;
5497              engGroupMemberDisplayNames(n) := null;
5498              engGroupMemberOrigSystems(n) := null;
5499              engGroupMemberOrigSystemIds(n) := null;
5500           end if;
5501         end loop;
5502         -- compact list
5503         outputIndex := engGroupMemberGroupIds.first;
5504         for i in 1 .. engGroupMemberGroupIds.count loop
5505           if(i <> outputIndex) then /* (Don't copy a row onto itself.) */
5506             engGroupMemberGroupIds(i) := engGroupMemberGroupIds(outputIndex);
5507             engGroupMemberNames(i) := engGroupMemberNames(outputIndex);
5508             engGroupMemberOrderNumbers(i) := engGroupMemberOrderNumbers(outputIndex);
5509             engGroupMemberDisplayNames(i) := engGroupMemberDisplayNames(outputIndex);
5510             engGroupMemberOrigSystems(i) := engGroupMemberOrigSystems(outputIndex);
5511             engGroupMemberOrigSystemIds(i) := engGroupMemberOrigSystemIds(outputIndex);
5512           end if;
5513           outputIndex := engGroupMemberGroupIds.next(outputIndex);
5514         end loop;
5515         engGroupMemberGroupIds.delete(outputIndex, engGroupMemberGroupIds.count);
5516       end if;
5517       outputIndex := engGroupMemberGroupIds.count; /* pre-increment */
5518       for i in 1 .. parameters.count loop
5519         tempGroupMembers.delete; -- for bug 4616570
5520         if(upperParameterNames(i) = upper(ame_util.approverOamGroupId)) then
5521           dynamicCursor := dbms_sql.open_cursor;
5522           dbms_sql.parse(dynamicCursor,
5523                          ame_util.removeReturns(stringIn => queryStrings(i),
5524                                                 replaceWithSpaces => true),
5525                          dbms_sql.native);
5526           engGroupUseItemBind(groupIdIn) := ame_util.booleanFalse;
5527           if(instrb(queryStrings(i),
5528                     ame_util.transactionIdPlaceholder) > 0) then
5529             dbms_sql.bind_variable(dynamicCursor,
5530                                    ame_util.transactionIdPlaceholder,
5531                                    engTransactionId,
5532                                    50);
5533           end if;
5534           if(instrb(queryStrings(i),
5535                     ame_util2.itemClassPlaceHolder) > 0) then
5536             dbms_sql.bind_variable(dynamicCursor,
5537                                    ame_util2.itemClassPlaceHolder,
5538                                    getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
5539                                    50);
5540             engGroupUseItemBind(groupIdIn) := ame_util.booleanTrue;
5541           end if;
5542           if(instrb(queryStrings(i),
5543                     ame_util2.itemIdPlaceHolder) > 0) then
5544             dbms_sql.bind_variable(dynamicCursor,
5545                                    ame_util2.itemIdPlaceHolder,
5546                                    engAppAppItemIds(engAppHandlerFirstIndex),
5547                                    50);
5548             engGroupUseItemBind(groupIdIn) := ame_util.booleanTrue;
5549           end if;
5550           dbms_sql.define_array(dynamicCursor,
5551                                 1,
5552                                 tempGroupMembers,
5553                                 100,
5554                                 1);
5555           rowsFound := dbms_sql.execute(dynamicCursor);
5556           loop
5557             rowsFound := dbms_sql.fetch_rows(dynamicCursor);
5558             dbms_sql.column_value(dynamicCursor,
5559                                   1,
5560                                   tempGroupMembers);
5561             exit when rowsFound < 100;
5562           end loop;
5563           dbms_sql.close_cursor(dynamicCursor);
5564           /*
5565             Dynamic groups' query strings may return rows having one of two forms:
5566               (1) approver_type:approver_id
5567               (2) orig_system:orig_system_id
5568           */
5569           for j in 1 .. tempGroupMembers.count loop
5570             tempApproverType := null;
5571             tempApproverId   := null;
5572             colonLocation1 := instrb(tempGroupMembers(j), ':', 1, 1);
5573             if(colonLocation1 = 0) then
5574               raise badDynamicMemberException;
5575             end if;
5576             tempApproverId := substrb(tempGroupMembers(j),instrb(tempGroupMembers(j), ':', 1, 1) + 1);
5577             tempApproverType := substrb(tempGroupMembers(j), 1, (instrb(tempGroupMembers(j), ':', 1, 1) - 1));
5578             begin
5579             if  tempApproverType is not null and upper(tempApproverType) = upper(ame_util.approverPersonId)
5580                 and tempApproverId is not null then
5581               tempName := ame_approver_type_pkg.getWfRolesName(ame_util.perOrigSystem,tempApproverId);
5582             elsif tempApproverType is not null and upper(tempApproverType) = upper(ame_util.approverUserId)
5583                and tempApproverId is not null then
5584               tempName := ame_approver_type_pkg.getWfRolesName(ame_util.fndUserOrigSystem,tempApproverId);
5585             elsif tempApproverType is not null and  tempApproverId is not null then
5586              tempName := ame_approver_type_pkg.getWfRolesName(tempApproverType,tempApproverId);
5587             end if;
5588             /*following changes added for bpo instance fnd user change*/
5589             processFndUser := true;
5590             if ame_multi_tenancy_pkg.is_multi_tenant_system = ame_util.booleanTrue then
5591               if upper(tempApproverType) = upper(ame_util.approverUserId)
5592                  or upper(tempApproverType) = upper(ame_util.fndUserOrigSystem) then
5593                 processFndUser := false;
5594               end if;
5595             end if;
5596             if tempApproverId is not null and lengthb(trim(tempApproverId)) > 0
5597                and tempApproverType is not null and lengthb(trim(tempApproverType)) > 0
5598                and processFndUser then
5599               outputIndex := outputIndex + 1;
5600               engGroupMemberGroupIds(outputIndex) := groupIdIn;
5601               engGroupMemberOrderNumbers(outputIndex) := j;
5602               if upper(tempApproverType) = upper(ame_util.approverPersonId) then /* old style */
5603                 engGroupMemberOrigSystems(outputIndex)   := ame_util.perOrigSystem;
5604                 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5605               elsif upper(tempApproverType) = upper(ame_util.approverUserId) then /* old style */
5606                 engGroupMemberOrigSystems(outputIndex)   := ame_util.fndUserOrigSystem;
5607                 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5608               else /* 11i10 style */
5609                 engGroupMemberOrigSystems(outputIndex)   := tempApproverType;
5610                 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5611               end if;
5612               begin
5613                 ame_approver_type_pkg.getWfRolesNameAndDisplayName(
5614                   origSystemIn => engGroupMemberOrigSystems(outputIndex),
5615                   origSystemIdIn => engGroupMemberOrigSystemIds(outputIndex),
5616                   nameOut => engGroupMemberNames(outputIndex),
5617                   displayNameOut => engGroupMemberDisplayNames(outputIndex));
5618               exception
5619                when others then
5620                  l_err_code := sqlcode;
5621                  if l_err_code = -20213 then
5622                     errorCode := -20215;
5623                     errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5624                                             messageNameIn => 'AME_400838_INV_APR_FOUND',
5625                                             tokenNameOneIn  => 'PROCESS_NAME',
5626                                             tokenValueOneIn => 'ame_engine.fetchRuntimeGroup:'||ame_approval_group_pkg.getName
5627                                                (approvalGroupIdIn => groupIdIn,effectiveDateIn => engEffectiveRuleDate),
5628                                             tokenNameTwoIn => 'ORIG_SYSTEM',
5629                                             tokenValueTwoIn => tempApproverType,
5630                                             tokenNameThreeIn => 'ORIG_SYSEM_ID',
5631                                             tokenValueThreeIn => tempApproverId
5632                                             );
5633                     raise_application_error(errorCode,errorMessage);
5634                   end if;
5635                   raise;
5636               end;
5637             end if;
5638             exception
5639               when others then
5640                 l_err_code := sqlcode;
5641                 if l_err_code = -20213 then
5642                   if upper(tempApproverType) = upper(ame_util.approverPersonId) then
5643                     l_appr_type := ame_util.perOrigSystem;
5644                   elsif upper(tempApproverType) = upper(ame_util.approverUserId) then
5645                     l_appr_type := ame_util.fndUserOrigSystem;
5646                   else
5647                     l_appr_type := tempApproverType;
5648                   end if;
5649                   l_isApproved := isApproved(isDynamic=>true,groupIdIn => groupIdIn
5650                     ,origSystemIn => l_appr_type,origSystemIdIn => tempApproverId,roleNameIn => null);
5651                   if not l_isApproved then
5652                     errorCode := -20215;
5653                     errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5654                                           messageNameIn => 'AME_400838_INV_APR_FOUND',
5655                                           tokenNameOneIn  => 'PROCESS_NAME',
5656                                           tokenValueOneIn => 'ame_engine.fetchRuntimeGroup:'||ame_approval_group_pkg.getName
5657                                             (approvalGroupIdIn => groupIdIn,effectiveDateIn   => engEffectiveRuleDate),
5658                                           tokenNameTwoIn => 'ORIG_SYSTEM',
5659                                           tokenValueTwoIn => tempApproverType,
5660                                           tokenNameThreeIn => 'ORIG_SYSEM_ID',
5661                                           tokenValueThreeIn => tempApproverId
5662                                           );
5663                     raise_application_error(errorCode,errorMessage);
5664                   end if;
5665                 else
5666                  raise;
5667                 end if;
5668             end;
5669           end loop;
5670         else /* Copy the static group into the engGroup caches. */
5671           begin
5672              ame_approver_type_pkg.getWfRolesNameAndDisplayName(
5673                  origSystemIn => origSystems(i),
5674                  origSystemIdIn => origSystemIds(i),
5675                  nameOut => l_name_out,
5676                  displayNameOut => l_display_name_out);
5677              outputIndex := outputIndex + 1;
5678              engGroupMemberNames(outputIndex) := l_name_out;
5679              engGroupMemberDisplayNames(outputIndex) := l_display_name_out;
5680              engGroupUseItemBind(groupIdIn) := ame_util.booleanFalse;
5681              engGroupMemberGroupIds(outputIndex) := groupIdIn;
5682              engGroupMemberOrderNumbers(outputIndex) := orderNumbers(i);
5683              engGroupMemberOrigSystems(outputIndex) := origSystems(i);
5684              engGroupMemberOrigSystemIds(outputIndex) := origSystemIds(i);
5685           exception
5686             when others then
5687               l_err_code := sqlcode;
5688               if l_err_code = -20213 then
5689                 l_isApproved := isApproved(isDynamic=> false,groupIdIn => groupIdIn
5690                     ,roleNameIn =>parameters(i));
5691                 if l_err_code = -20213 then
5692                   if not l_isApproved then
5693                     errorCode := -20215;
5694                     errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5695                                          messageNameIn => 'AME_400838_INV_APR_FOUND',
5696                                          tokenNameOneIn  => 'PROCESS_NAME',
5697                                          tokenValueOneIn => 'ame_engine.fetchRuntimeGroup:'||ame_approval_group_pkg.getName
5698                                              (approvalGroupIdIn => groupIdIn,effectiveDateIn  => engEffectiveRuleDate),
5699                                          tokenNameTwoIn => 'ORIG_SYSTEM',
5700                                          tokenValueTwoIn => origSystems(i),
5701                                          tokenNameThreeIn => 'ORIG_SYSEM_ID',
5702                                          tokenValueThreeIn => origSystemIds(i)
5703                                          );
5704                     raise_application_error(errorCode,errorMessage);
5705                   end if;
5706                 end if;
5707               else
5708                raise;
5709               end if;
5710           end;
5711         end if;
5712       end loop;
5713       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5714         fnd_log.string
5715           (fnd_log.level_statement
5716             ,'ame_engine.fetchRuntimeGroup'
5717             ,'Completed the group evaluation::'||ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5718                                                                       ,effectiveDateIn   => engEffectiveRuleDate)
5719            );
5720       end if;
5721       exception
5722         when badDynamicMemberException then
5723           errorCode := -20109;
5724           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5725                                               messageNameIn => 'AME_400771_ENG_INVALID_DYN_GRP',
5726                                               tokenNameOneIn  => 'GROUP_NAME',
5727                                               tokenValueOneIn => ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5728                                                                                                ,effectiveDateIn   => engEffectiveRuleDate));
5729           ame_util.runtimeException(packageNameIn => 'ame_engine',
5730                                     routineNameIn => 'fetchRuntimeGroup',
5731                                     exceptionNumberIn => errorCode,
5732                                     exceptionStringIn => errorMessage);
5733           raise_application_error(errorCode,
5734                                   errorMessage);
5735         when others then
5736           if(groupMemberCursor%isopen) then
5737             close groupMemberCursor;
5738           end if;
5739           ame_util.runtimeException(packageNameIn => 'ame_engine',
5740                                     routineNameIn => 'fetchRuntimeGroup',
5741                                     exceptionNumberIn => sqlcode,
5742                                     exceptionStringIn => sqlerrm);
5743           raise;
5744     end fetchRuntimeGroup;
5745   /* This procedure is used to assign calculate min_order and max_order */
5746   /* of each node in the approver tree                                  */
5747   /* It also populates the approver_order_number of the engStApprovers  */
5748   procedure finalizeTree
5749     (parentIndexIn        in            integer default 1
5750     ,maximumOrderOut         out nocopy integer
5751     ,approvalStatusOut       out nocopy integer
5752     ,rejectedItemsExistOut   out nocopy boolean) is
5753     currentTreeNodeIndex           integer;
5754     maximumOrderOfChildren         integer;
5755     approvalStatusOfChildren       integer;
5756     previousTreeNodeIndex          integer;
5757     currentApproverApprovalStatus  varchar2(50);
5758     currentApproverCategory        varchar2(1);
5759     currentApproverIndex           integer;
5760     nextSuspendedItemIndex         integer;
5761     hasRejectedChildren            boolean;
5762     currentTreeNodeRejectionStatus boolean;
5763   begin
5764     if engStApproversTree.count > 0 then
5765       approvalStatusOfChildren := ame_util.unknownStatus;
5766       currentTreeNodeIndex := engStApproversTree(parentIndexIn).child_index;
5767       if currentTreeNodeIndex = ame_util.noChildIndex then
5768         /* This is an approver node                                     */
5769         /* 1. For a approver node the maximum order number is same      */
5770         /*    as parents minimum order number                           */
5771         /* 2. The approvalStatus of the node is set based on            */
5772         /*    approvers approval status                                 */
5773         /* 3. If the approvers approval status is ame_util.rejectStatus */
5774         /*    then the approvers item class and item id are populated   */
5775         /*    into the global list of rejected items                    */
5776         maximumOrderOut := engStApproversTree(parentIndexIn).min_order;
5777         currentApproverApprovalStatus :=
5778           engStApprovers(engStApproversTree(parentIndexIn).approver_index).approval_status;
5779         currentApproverCategory :=
5780           engStApprovers(engStApproversTree(parentIndexIn).approver_index).approver_category;
5781         if currentApproverApprovalStatus is null or
5782            currentApproverApprovalStatus in (ame_util.repeatedStatus) then
5783           approvalStatusOut := ame_util.notStartedStatus;
5784         elsif currentApproverApprovalStatus in (ame_util.approvedStatus
5785                                                ,ame_util.rejectStatus
5786                                                ,ame_util.beatByFirstResponderStatus
5787                                                ,ame_util.approvedByRepeatedStatus
5788                                                ,ame_util.rejectedByRepeatedStatus
5789                                                ,ame_util.suppressedStatus
5790                                                ,ame_util.noResponseStatus
5791                                                ,ame_util.forwardStatus
5792                                                ,ame_util.approveAndForwardStatus
5793                                                ,ame_util2.reassignStatus
5794                                                ,ame_util2.noResponseByRepeatedStatus
5795                                                ,ame_util2.forwardByRepeatedStatus) or
5796              (currentApproverCategory = ame_util.fyiApproverCategory and
5797               (currentApproverApprovalStatus in (ame_util.notifiedStatus,
5798                                                  ame_util.notifiedByRepeatedStatus))) then
5799           approvalStatusOut := ame_util.completedStatus;
5800         elsif currentApproverApprovalStatus not in (ame_util.approvedStatus
5801                                                    ,ame_util.rejectStatus
5802                                                    ,ame_util.beatByFirstResponderStatus
5803                                                    ,ame_util.approvedByRepeatedStatus
5804                                                    ,ame_util.rejectedByRepeatedStatus
5805                                                    ,ame_util.suppressedStatus) then
5806           approvalStatusOut := ame_util.startedStatus;
5807         end if;
5808         if currentApproverApprovalStatus = ame_util.rejectStatus
5809            or currentApproverApprovalStatus = ame_util.rejectedByRepeatedStatus then
5810           rejectedItemsExistOut := true;
5811           /* Populate the list of rejected items and item classes */
5812           nextSuspendedItemIndex := engStSuspendedItems.count + 1;
5813           engStSuspendedItems(nextSuspendedItemIndex)
5814             := engStApprovers(engStApproversTree(parentIndexIn).approver_index).item_id;
5815           engStSuspendedItemClasses(nextSuspendedItemIndex)
5816             := engStApprovers(engStApproversTree(parentIndexIn).approver_index).item_class;
5817         else
5818           rejectedItemsExistOut := false;
5819         end if;
5820       else
5821         /* This is a non approver node                               */
5822         /* 1.For a non approver node find the maximum order number   */
5823         /*   among its children and assign it as the maximum order   */
5824         /*   number of the parent node                               */
5825         /* 2.The approvalStatus of the node is determined by finding */
5826         /*   the aggregate status of all its child nodes             */
5827         /* 3.The current node is flagged as rejected if any of its   */
5828         /*   children have a rejectedStatus                          */
5829         previousTreeNodeIndex := ame_util.invalidTreeIndex;
5830         currentTreeNodeRejectionStatus := false;
5831         maximumOrderOfChildren := engStApproversTree(parentIndexIn).min_order;
5832         loop
5833           if previousTreeNodeIndex = ame_util.invalidTreeIndex then
5834             engStApproversTree(currentTreeNodeIndex).min_order
5835                             := engStApproversTree(parentIndexIn).min_order;
5836           elsif engStApproversTree(currentTreeNodeIndex).order_number
5837                    = engStApproversTree(previousTreeNodeIndex).order_number then
5838             engStApproversTree(currentTreeNodeIndex).min_order
5839                             := engStApproversTree(previousTreeNodeIndex).min_order;
5840           else
5841             engStApproversTree(currentTreeNodeIndex).min_order
5842                             := maximumOrderOfChildren + 1;
5843           end if;
5844           ame_engine.finalizeTree
5845             (parentIndexIn          => currentTreeNodeIndex
5846             ,maximumOrderOut        => engStApproversTree(currentTreeNodeIndex).max_order
5847             ,approvalStatusOut      => engStApproversTree(currentTreeNodeIndex).status
5848             ,rejectedItemsExistOut  => hasRejectedChildren);
5849           if hasRejectedChildren then
5850             currentTreeNodeRejectionStatus := true;
5851           end if;
5852           if engStApproversTree(currentTreeNodeIndex).max_order
5853                                                        > maximumOrderOfChildren then
5854             maximumOrderOfChildren := engStApproversTree(currentTreeNodeIndex).max_order;
5855           end if;
5856           if engStApproversTree(currentTreeNodeIndex).approver_index
5857                                                        <> ame_util.noApproverIndex then
5858             currentApproverIndex := engStApproversTree(currentTreeNodeIndex).approver_index;
5859             engStApprovers(currentApproverIndex).approver_order_number
5860                          := engStApproversTree(currentTreeNodeIndex).max_order;
5861           end if;
5862           if (engStApproversTree(currentTreeNodeIndex).status = ame_util.notStartedStatus
5863                and approvalStatusOfChildren = ame_util.completedStatus)
5864             or (engStApproversTree(currentTreeNodeIndex).status = ame_util.completedStatus
5865                and approvalStatusOfChildren = ame_util.notStartedStatus) then
5866             approvalStatusOfChildren := ame_util.startedStatus;
5867           elsif engStApproversTree(currentTreeNodeIndex).status
5868                            > approvalStatusOfChildren then
5869             approvalStatusOfChildren := engStApproversTree(currentTreeNodeIndex).status;
5870           end if;
5871           previousTreeNodeIndex := currentTreeNodeIndex;
5872           currentTreeNodeIndex := engStApproversTree(currentTreeNodeIndex).sibling_index;
5873           exit when currentTreeNodeIndex = ame_util.noSiblingIndex;
5874         end loop;
5875         maximumOrderOut := maximumOrderOfChildren;
5876         /* If the node has supended children and the node is below the item level then */
5877         /* its status is set to completed as no more approvers are to be fetched from  */
5878         /* below this node                                                             */
5879         if currentTreeNodeRejectionStatus and
5880            engStApproversTree(parentIndexIn).tree_level > 1 then
5881           approvalStatusOut := ame_util.completedStatus;
5882         elsif approvalStatusOfChildren = ame_util.unknownStatus then
5883           approvalStatusOut := ame_util.notStartedStatus;
5884         else
5885           approvalStatusOut := approvalStatusOfChildren;
5886         end if;
5887         rejectedItemsExistOut := currentTreeNodeRejectionStatus;
5888       end if;
5889     end if;
5890   exception
5891     when others then
5892       ame_util.runtimeException(packageNameIn => 'ame_engine',
5893                                 routineNameIn => 'finalizeTree',
5894                                 exceptionNumberIn => sqlcode,
5895                                 exceptionStringIn => sqlerrm);
5896       raise;
5897   end finalizeTree;
5898   /* getAllApprovers is for amem0013.sql backwards compatibility only.  Do not use it elsewhere. */
5899   procedure getAllApprovers(approversOut out nocopy ame_util.approversTable) as
5900     begin
5901       ame_api.getAllApprovers(applicationIdIn => engAmeApplicationId,
5902                               transactionIdIn => engTransactionId,
5903                               transactionTypeIn => engTransactionTypeId,
5904                               approversOut => approversOut);
5905       exception
5906         when others then
5907           ame_util.runtimeException(packageNameIn => 'ame_engine',
5908                                     routineNameIn => 'getAllApprovers',
5909                                     exceptionNumberIn => sqlcode,
5910                                     exceptionStringIn => sqlerrm);
5911           raise;
5912     end getAllApprovers;
5913   procedure getApplicableRules
5914     (ruleIdsOut             out nocopy ame_util.idList
5915     ,ruleDescriptionsOut    out nocopy ame_util.stringList) as
5916     nextRuleIndex  integer;
5917     ruleFound      boolean;
5918     begin
5919       nextRuleIndex := 1;
5920       for i in 1 .. engAppRuleIds.count loop
5921         if engRuleAppliedYN(i) = ame_util.booleanTrue then
5922           if nextRuleIndex = 1 then
5923             ruleFound := false;
5924           else
5925             ruleFound := false;
5926             for j in 1 .. (nextRuleIndex - 1) loop
5927               if ruleIdsOut(j) = engAppRuleIds(i) then
5928                 ruleFound := true;
5929                 exit;
5930               end if;
5931             end loop;
5932           end if;
5933           if not ruleFound then
5934             ruleIdsOut(nextRuleIndex) := engAppRuleIds(i);
5935             ruleDescriptionsOut(nextRuleIndex) := ame_rule_pkg.getDescription(ruleIdIn => engAppRuleIds(i),
5936                                                                               processingDateIn => engEffectiveRuleDate);
5937             nextRuleIndex := nextRuleIndex + 1;
5938           end if;
5939         end if;
5940       end loop;
5941       exception
5942         when others then
5943           ame_util.runtimeException(packageNameIn => 'ame_engine',
5944                                     routineNameIn => 'getApplicableRules',
5945                                     exceptionNumberIn => sqlcode,
5946                                     exceptionStringIn => sqlerrm);
5947           raise;
5948     end getApplicableRules;
5949   /* BUG: 4491715 sort approver categories and sources along with group ids */
5950   procedure getApprovalGroupConfigs(groupIdsInOut in out nocopy ame_util.idList,
5951                                     sourcesInOut in out nocopy ame_util.longStringList,
5952                                     approverCategoriesInOut in out nocopy ame_util.charList,
5953                                     orderNumbersOut out nocopy ame_util.idList,
5954                                     votingRegimesOut out nocopy ame_util.charList) as
5955     cursor approvalGroupConfigCursor(groupIdIn in integer) is
5956       select
5957         order_number,
5958         voting_regime
5959         from ame_approval_group_config
5960         where
5961           application_id = engAmeApplicationId and
5962           approval_group_id = groupIdIn and
5963         engEffectiveRuleDate between
5964           start_date and
5965           nvl(end_date - ame_util.oneSecond, engEffectiveRuleDate);
5966     tempGroupId integer;
5967     tempOrderNumber integer;
5968     tempVotingRegime ame_util.charType;
5969     tempSource ame_util.longStringType;
5970     tempApproverCategory ame_util.charType;
5971     upperLimit integer;
5972     begin
5973       /*
5974         Evidently it's more efficient to fetch this way, than to do a single bulk fetch
5975         with a comma-delimited list of group IDs.
5976       */
5977       for i in 1 .. groupIdsInOut.count loop
5978         open approvalGroupConfigCursor(groupIdIn => groupIdsInOut(i));
5979         fetch approvalGroupConfigCursor
5980           into
5981             orderNumbersOut(i),
5982             votingRegimesOut(i);
5983         close approvalGroupConfigCursor;
5984       end loop;
5985       /* Sort in place, first by group order number, then by group ID. */
5986       for i in 2 .. groupIdsInOut.count loop
5987         upperLimit := i - 1;
5988         for j in 1 .. upperLimit loop
5989           if(orderNumbersOut(i) < orderNumbersOut(j) or
5990              (orderNumbersOut(i) = orderNumbersOut(j) and
5991               groupIdsInOut(i) < groupIdsInOut(j))) then
5992             /* j into temps */
5993             tempGroupId := groupIdsInOut(j);
5994             tempOrderNumber := orderNumbersOut(j);
5995             tempVotingRegime := votingRegimesOut(j);
5996             tempSource := sourcesInOut(j);
5997             tempApproverCategory := approverCategoriesInOut(j);
5998             /* i into j */
5999             groupIdsInOut(j) := groupIdsInOut(i);
6000             orderNumbersOut(j) := orderNumbersOut(i);
6001             votingRegimesOut(j) := votingRegimesOut(i);
6002             sourcesInOut(j) := sourcesInOut(i);
6003             approverCategoriesInOut(j) := approverCategoriesInOut(i);
6004             /* temps into i */
6005             groupIdsInOut(i) := tempGroupId;
6006             orderNumbersOut(i) := tempOrderNumber;
6007             votingRegimesOut(i) := tempVotingRegime;
6008             sourcesInOut(i) := tempSource;
6009             approverCategoriesInOut(i) := tempApproverCategory;
6010           end if;
6011         end loop;
6012       end loop;
6013       exception
6014         when others then
6015           if(approvalGroupConfigCursor%isopen) then
6016             close approvalGroupConfigCursor;
6017           end if;
6018           ame_util.runtimeException(packageNameIn => 'ame_engine',
6019                                     routineNameIn => 'getApprovalGroupConfigs',
6020                                     exceptionNumberIn => sqlcode,
6021                                     exceptionStringIn => sqlerrm);
6022           raise;
6023     end getApprovalGroupConfigs;
6024   procedure getApprovers(approversOut out nocopy ame_util.approversTable2) as
6025     begin
6026       if (not engItemDataPrepared) and engPrepareItemData then
6027         prepareItemData(itemIndexesOut     => engStItemIndexes
6028                        ,itemItemClassesOut => engStItemClasses
6029                        ,itemIdsOut         => engStItemIds
6030                        ,itemSourcesOut     => engStItemSources);
6031         engItemDataPrepared := true;
6032       end if;
6033       prepareRuleData;
6034       preparePerApproverProductions
6035            (prodIndexesOut      => engStProductionIndexes
6036            ,productionNamesOut  => engStVariableNames
6037            ,productionValuesOut => engStVariableValues);
6038       for i in 1 .. engStApprovers.count loop
6039         approversOut(i).name := engStApprovers(i).name;
6040         approversOut(i).orig_system := engStApprovers(i).orig_system;
6041         approversOut(i).orig_system_id := engStApprovers(i).orig_system_id;
6042         approversOut(i).display_name := engStApprovers(i).display_name;
6043         approversOut(i).approver_category := engStApprovers(i).approver_category;
6044         approversOut(i).api_insertion := engStApprovers(i).api_insertion;
6045         approversOut(i).authority := engStApprovers(i).authority;
6046         approversOut(i).approval_status := engStApprovers(i).approval_status;
6047         approversOut(i).action_type_id := engStApprovers(i).action_type_id;
6048         approversOut(i).group_or_chain_id := engStApprovers(i).group_or_chain_id;
6049         approversOut(i).occurrence := engStApprovers(i).occurrence;
6050         approversOut(i).source := engStApprovers(i).source;
6051         approversOut(i).item_class := engStApprovers(i).item_class;
6052         approversOut(i).item_id := engStApprovers(i).item_id;
6053         approversOut(i).item_class_order_number := engStApprovers(i).item_class_order_number;
6054         approversOut(i).item_order_number := engStApprovers(i).item_order_number;
6055         approversOut(i).sub_list_order_number := engStApprovers(i).sub_list_order_number;
6056         approversOut(i).action_type_order_number := engStApprovers(i).action_type_order_number;
6057         approversOut(i).group_or_chain_order_number := engStApprovers(i).group_or_chain_order_number;
6058         approversOut(i).member_order_number := engStApprovers(i).member_order_number;
6059         approversOut(i).approver_order_number := engStApprovers(i).approver_order_number;
6060       end loop;
6061       exception
6062         when others then
6063           ame_util.runtimeException(packageNameIn => 'ame_engine',
6064                                     routineNameIn => 'getApprovers',
6065                                     exceptionNumberIn => sqlcode,
6066                                     exceptionStringIn => sqlerrm);
6067           raise;
6068     end getApprovers;
6069   /* This procedure returns the approvers as well as approvers tree to the calling APIs */
6070   procedure getApprovers2(approversOut out nocopy ame_util.approversTable2
6071                          ,approversTreeOut out nocopy ame_util.approversTreeTable) as
6072     loopIndex integer;
6073     begin
6074       for i in 1 .. engStApprovers.count loop
6075         approversOut(i).name := engStApprovers(i).name;
6076         approversOut(i).orig_system := engStApprovers(i).orig_system;
6077         approversOut(i).orig_system_id := engStApprovers(i).orig_system_id;
6078         approversOut(i).display_name := engStApprovers(i).display_name;
6079         approversOut(i).approver_category := engStApprovers(i).approver_category;
6080         approversOut(i).api_insertion := engStApprovers(i).api_insertion;
6081         approversOut(i).authority := engStApprovers(i).authority;
6082         approversOut(i).approval_status := engStApprovers(i).approval_status;
6083         approversOut(i).action_type_id := engStApprovers(i).action_type_id;
6084         approversOut(i).group_or_chain_id := engStApprovers(i).group_or_chain_id;
6085         approversOut(i).occurrence := engStApprovers(i).occurrence;
6086         approversOut(i).source := engStApprovers(i).source;
6087         approversOut(i).item_class := engStApprovers(i).item_class;
6088         approversOut(i).item_id := engStApprovers(i).item_id;
6089         approversOut(i).item_class_order_number := engStApprovers(i).item_class_order_number;
6090         approversOut(i).item_order_number := engStApprovers(i).item_order_number;
6091         approversOut(i).sub_list_order_number := engStApprovers(i).sub_list_order_number;
6092         approversOut(i).action_type_order_number := engStApprovers(i).action_type_order_number;
6093         approversOut(i).group_or_chain_order_number := engStApprovers(i).group_or_chain_order_number;
6094         approversOut(i).member_order_number := engStApprovers(i).member_order_number;
6095         approversOut(i).approver_order_number := engStApprovers(i).approver_order_number;
6096       end loop;
6097       if engStApproversTree.count > 0 then
6098         /* Approvers Tree is sparse */
6099         loopIndex := engStApproversTree.first;
6100         loop
6101           approversTreeOut(loopIndex).parent_index   := engStApproversTree(loopIndex).parent_index;
6102           approversTreeOut(loopIndex).child_index    := engStApproversTree(loopIndex).child_index;
6103           approversTreeOut(loopIndex).sibling_index  := engStApproversTree(loopIndex).sibling_index;
6104           approversTreeOut(loopIndex).approver_index := engStApproversTree(loopIndex).approver_index;
6105           approversTreeOut(loopIndex).tree_level     := engStApproversTree(loopIndex).tree_level;
6106           approversTreeOut(loopIndex).tree_level_id  := engStApproversTree(loopIndex).tree_level_id;
6107           approversTreeOut(loopIndex).order_number   := engStApproversTree(loopIndex).order_number;
6108           approversTreeOut(loopIndex).min_order      := engStApproversTree(loopIndex).min_order;
6109           approversTreeOut(loopIndex).max_order      := engStApproversTree(loopIndex).max_order;
6110           approversTreeOut(loopIndex).status         := engStApproversTree(loopIndex).status;
6111           approversTreeOut(loopIndex).is_suspended   := engStApproversTree(loopIndex).is_suspended;
6112           exit when loopIndex = engStApproversTree.last;
6113           loopIndex := engStApproversTree.next(loopIndex);
6114         end loop;
6115       end if;
6116       exception
6117         when others then
6118           ame_util.runtimeException(packageNameIn => 'ame_engine',
6119                                     routineNameIn => 'getApprovers2',
6120                                     exceptionNumberIn => sqlcode,
6121                                     exceptionStringIn => sqlerrm);
6122           raise;
6123     end getApprovers2;
6124   procedure getHandlerCOAFirstApprover(itemClassIn in varchar2,
6125                                        itemIdIn in varchar2,
6126                                        actionTypeIdIn in integer,
6127                                        groupOrChainIdIn in integer,
6128                                        nameOut out nocopy varchar2,
6129                                        origSystemOut out nocopy varchar2,
6130                                        origSystemIdOut out nocopy integer,
6131                                        displayNameOut out nocopy varchar2,
6132                                        sourceOut out nocopy varchar2) as
6133     parameter ame_temp_insertions.parameter%type;
6134     l_error_code number;
6135     l_action_type_name varchar2(100);
6136     errorCode integer;
6137     errorMessage ame_util.longestStringType;
6138     begin
6139       parameter := ame_util.firstAuthorityParameter ||
6140                    ame_util.fieldDelimiter ||
6141                    itemClassIn ||
6142                    ame_util.fieldDelimiter ||
6143                    itemIdIn ||
6144                    ame_util.fieldDelimiter ||
6145                    actionTypeIdIn ||
6146                    ame_util.fieldDelimiter ||
6147                    groupOrChainIdIn;
6148       for i in 1 .. engInsertedApproverList.count loop
6149         if(engInsertionParameterList(i) = parameter) then
6150           nameOut := engInsertedApproverList(i).name;
6151           begin
6152             ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
6153                                                               origSystemOut => origSystemOut,
6154                                                               origSystemIdOut => origSystemIdOut,
6155                                                               displayNameOut => displayNameOut);
6156           exception
6157             when others then
6158               l_error_code := sqlcode;
6159               if l_error_code = -20213 then
6160                 l_action_type_name := getActionTypeName(actionTypeIdIn);
6161                 errorCode := -20216;
6162                 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
6163                                               messageNameIn => 'AME_400833_INV_HANDLR_APR',
6164                                               tokenNameOneIn  => 'ACTION_TYPE_NAME',
6165                                               tokenValueOneIn => l_action_type_name,
6166                                               tokenNameTwoIn => 'NAME',
6167                                               tokenValueTwoIn => engInsertedApproverList(i).name
6168                                               );
6169                 raise_application_error(errorCode,errorMessage);
6170               end if;
6171               raise;
6172           end;
6173           sourceOut := ame_util.otherInsertion;
6174           setDeviationReasonDate(engInsertionReasonList(i),engInsertionDateList(i));
6175           return;
6176         end if;
6177       end loop;
6178       exception
6179         when others then
6180           ame_util.runtimeException(packageNameIn => 'ame_engine',
6181                                     routineNameIn => 'getHandlerCOAFirstApprover',
6182                                     exceptionNumberIn => sqlcode,
6183                                     exceptionStringIn => sqlerrm);
6184           raise;
6185     end getHandlerCOAFirstApprover;
6186   procedure getHandlerCOAInsertion(nameIn in varchar2,
6187                                    itemClassIn in varchar2,
6188                                    itemIdIn in varchar2,
6189                                    actionTypeIdIn in integer,
6190                                    groupOrChainIdIn in integer,
6191                                    occurrenceIn in integer,
6192                                    approvalStatusIn in varchar2,
6193                                    nameOut out nocopy varchar2,
6194                                    origSystemOut out nocopy varchar2,
6195                                    origSystemIdOut out nocopy integer,
6196                                    displayNameOut out nocopy varchar2,
6197                                    sourceOut out nocopy varchar2) as
6198     parameter ame_temp_insertions.parameter%type;
6199     l_error_code number;
6200     errorCode integer;
6201     errorMessage ame_util.longestStringType;
6202     l_action_type_name varchar2(200);
6203     begin
6204       parameter := nameIn ||
6205                    ame_util.fieldDelimiter ||
6206                    itemClassIn ||
6207                    ame_util.fieldDelimiter ||
6208                    itemIdIn ||
6209                    ame_util.fieldDelimiter ||
6210                    actionTypeIdIn ||
6211                    ame_util.fieldDelimiter ||
6212                    groupOrChainIdIn ||
6213                    ame_util.fieldDelimiter ||
6214                    occurrenceIn;
6215       for i in 1 .. engInsertedApproverList.count loop
6216         if(engInsertedApproverList(i).api_insertion = ame_util.apiAuthorityInsertion and
6217            engInsertionOrderTypeList(i) = ame_util.afterApprover and
6218            engInsertionParameterList(i) = parameter) then
6219            nameOut := engInsertedApproverList(i).name;
6220            begin
6221             ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
6222                                                               origSystemOut => origSystemOut,
6223                                                               origSystemIdOut => origSystemIdOut,
6224                                                               displayNameOut => displayNameOut);
6225            exception
6226             when others then
6227               l_error_code := sqlcode;
6228               if l_error_code = -20213 then
6229                 l_action_type_name := getActionTypeName(actionTypeIdIn);
6230                 errorCode := -20217;
6231                 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
6232                                               messageNameIn => 'AME_400837_INV_APR_FOUND',
6233                                               tokenNameOneIn  => 'ACTION_TYPE_NAME',
6234                                               tokenValueOneIn => l_action_type_name,
6235                                               tokenNameTwoIn => 'NAME',
6236                                               tokenValueTwoIn => engInsertedApproverList(i).name
6237                                               );
6238                 raise_application_error(errorCode,errorMessage);
6239               end if;
6240               raise;
6241            end;
6242           if(engInsertionIsSpecialForwardee(i) = ame_util.booleanTrue) then
6243             sourceOut := ame_util.specialForwardInsertion;
6244           elsif(approvalStatusIn = ame_util.forwardStatus) then
6245             sourceOut := ame_util.forwardInsertion;
6246           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
6247             sourceOut := ame_util.approveAndForwardInsertion;
6248           else
6249             sourceOut := ame_util.otherInsertion;
6250           end if;
6251           setDeviationReasonDate(engInsertionReasonList(i),engInsertionDateList(i));
6252           return;
6253         end if;
6254       end loop;
6255       exception
6256         when others then
6257           ame_util.runtimeException(packageNameIn => 'ame_engine',
6258                                     routineNameIn => 'getHandlerCOAInsertion',
6259                                     exceptionNumberIn => sqlcode,
6260                                     exceptionStringIn => sqlerrm);
6261           raise;
6262     end getHandlerCOAInsertion;
6263   procedure getHandlerRules(ruleIdsOut out nocopy ame_util.idList,
6264                             approverCategoriesOut out nocopy ame_util.charList,
6265                             parametersOut out nocopy ame_util.stringList,
6266                             parameterTwosOut out nocopy ame_util.stringList) as
6267     outputIndex integer;
6268     begin
6269       outputIndex := 0;
6270       for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6271         outputIndex := outputIndex + 1;
6272         ruleIdsOut(outputIndex) := engAppRuleIds(i);
6273         approverCategoriesOut(outputIndex) := engAppApproverCategories(i);
6274         parametersOut(outputIndex) := engAppParameters(i);
6275         parameterTwosOut(outputIndex) := engAppParameterTwos(i);
6276       end loop;
6277       exception
6278         when others then
6279           ame_util.runtimeException(packageNameIn => 'ame_engine',
6280                                     routineNameIn => 'getHandlerRules',
6281                                     exceptionNumberIn => sqlcode,
6282                                     exceptionStringIn => sqlerrm);
6283           raise;
6284     end getHandlerRules;
6285   procedure getHandlerRules2(ruleIdsOut out nocopy ame_util.idList,
6286                              approverCategoriesOut out nocopy ame_util.charList,
6287                              parametersOut out nocopy ame_util.stringList) as
6288     outputIndex integer;
6289     begin
6290       outputIndex := 0;
6291       for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6292         outputIndex := outputIndex + 1;
6293         ruleIdsOut(outputIndex) := engAppRuleIds(i);
6294         approverCategoriesOut(outputIndex) := engAppApproverCategories(i);
6295         parametersOut(outputIndex) := engAppParameters(i);
6296       end loop;
6297       exception
6298         when others then
6299           ame_util.runtimeException(packageNameIn => 'ame_engine',
6300                                     routineNameIn => 'getHandlerRules2',
6301                                     exceptionNumberIn => sqlcode,
6302                                     exceptionStringIn => sqlerrm);
6303           raise;
6304     end getHandlerRules2;
6305   procedure getHandlerRules3(ruleIdsOut out nocopy ame_util.idList,
6306                              ruleIndexesOut out nocopy ame_util.idList,
6307                              parametersOut out nocopy ame_util.stringList,
6308                              listModParameterOnesOut out nocopy ame_util.stringList,
6309                              listModParameterTwosOut out nocopy ame_util.longStringList) as
6310     outputIndex integer;
6311     begin
6312       outputIndex := 0;
6313       for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6314         outputIndex := outputIndex + 1;
6315         ruleIdsOut(outputIndex) := engAppRuleIds(i);
6316         ruleIndexesOut(outputIndex) := i;
6317         parametersOut(outputIndex) := engAppParameters(i);
6318         getLMCondition(ruleIdIn => engAppRuleIds(i),
6319                        parameterOneOut => listModParameterOnesOut(outputIndex),
6320                        parameterTwoOut => listModParameterTwosOut(outputIndex));
6321       end loop;
6322       exception
6323         when others then
6324           ame_util.runtimeException(packageNameIn => 'ame_engine',
6325                                     routineNameIn => 'getHandlerRules3',
6326                                     exceptionNumberIn => sqlcode,
6327                                     exceptionStringIn => sqlerrm);
6328           raise;
6329     end getHandlerRules3;
6330   procedure getHandlerLMApprovers(listModParameterOneIn in varchar2,
6331                                   listModParameterTwoIn in varchar2,
6332                                   includeFyiApproversIn in boolean,
6333                                   includeApprovalGroupsIn in boolean,
6334                                   returnForwardeesIn in boolean,
6335                                   approverIndexesOut out nocopy ame_util.idList,
6336                                   lastForwardeeIndexesOut out nocopy ame_util.idList) as
6337     currentActionTypeId integer;
6338     currentGroupOrChainId integer;
6339     currentIndex integer;
6340     currentTargetIndex integer;
6341     engStApproversCount integer;
6342     outputIndex integer;
6343     begin
6344       engStApproversCount := engStApprovers.count;
6345       if(engStApproversCount = 0) then
6346         return;
6347       end if;
6348       outputIndex := 0; /* pre-increment */
6349       currentIndex := 1; /* post-increment */
6350       loop
6351         if((engStApprovers(currentIndex).approver_category = ame_util.approvalApproverCategory or
6352             includeFyiApproversIn) and
6353            (engStApprovers(currentIndex).authority = ame_util.authorityApprover or
6354             includeApprovalGroupsIn) and
6355            listModParameterTwoIn = engStApprovers(currentIndex).name) then
6356           /* This approver matches the input approver, and satisfies the input boolean arguments. */
6357           currentTargetIndex := currentIndex;
6358           currentGroupOrChainId := engStApprovers(currentTargetIndex).group_or_chain_id;
6359           currentActionTypeId := engStApprovers(currentTargetIndex).action_type_id;
6360           if(returnForwardeesIn) then
6361             /*
6362               Set currentIndex to the index of the last of any subsequent forwardees.  Start the loop
6363               at the target to check whether the target forwards.  (Note that we necessarily stay
6364               in the same approval group or chain of authority as long as we're forwarding.)
6365             */
6366             for i in currentTargetIndex .. engStApproversCount loop
6367               if(engStApprovers(currentIndex).approval_status in (ame_util.forwardStatus,
6368                                                                   ame_util.approveAndForwardStatus)) then
6369                 currentIndex := i;
6370               else
6371                 exit;
6372               end if;
6373             end loop;
6374           end if;
6375           /*
6376             Now increment currentIndex to point to the approver after the target, or after the target's
6377             forwarding chain if necessary.  (This may point past the end of the list; check for that.)
6378             This also serves to increment currentIndex for the outer loop.
6379           */
6380           currentIndex := currentIndex + 1;
6381           /*
6382             If the target approver satisfies listModParameterOneIn, output the target approver and
6383             optionally the last forwardee.
6384           */
6385           /*
6386             All but the first of the conditions in the following if statement
6387             are for the ame_util.finalApprover case.
6388           */
6389           if(listModParameterOneIn = ame_util.anyApprover or
6390              currentIndex > engStApproversCount or
6391              engStApprovers(currentIndex).group_or_chain_id <> currentGroupOrChainId or
6392              engStApprovers(currentIndex).action_type_id <> currentActionTypeId or
6393              engStApprovers(currentIndex).item_id <> engStApprovers(currentTargetIndex).item_id or
6394              engStApprovers(currentIndex).item_class <> engStApprovers(currentTargetIndex).item_class) then
6395             /* Output the approver(s). */
6396             outputIndex := outputIndex + 1;
6397             approverIndexesOut(outputIndex) := currentTargetIndex;
6398             if(returnForwardeesIn) then
6399               lastForwardeeIndexesOut(outputIndex) := currentIndex - 1;
6400             end if;
6401           end if;
6402         else /* Just iterate. */
6403           currentIndex := currentIndex + 1;
6404         end if;
6405         /* Exit the loop upon reaching the end of engStApprovers. */
6406         if(currentIndex > engStApproversCount) then
6407           exit;
6408         end if;
6409       end loop;
6410       exception
6411         when others then
6412           ame_util.runtimeException(packageNameIn => 'ame_engine',
6413                                     routineNameIn => 'getHandlerLMApprovers',
6414                                     exceptionNumberIn => sqlcode,
6415                                     exceptionStringIn => sqlerrm);
6416           raise;
6417     end getHandlerLMApprovers;
6418   procedure getHeaderAttValues1(attributeIdIn in integer,
6419                                 attributeValue1Out out nocopy varchar2,
6420                                 attributeValue2Out out nocopy varchar2,
6421                                 attributeValue3Out out nocopy varchar2) as
6422     attributeValueIndex integer;
6423     begin
6424       attributeValueIndex := engAttributeValueIndexes(attributeIdIn);
6425       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6426       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6427       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6428       exception
6429         when others then
6430           ame_util.runtimeException(packageNameIn => 'ame_engine',
6431                                     routineNameIn => 'getHeaderAttValues1',
6432                                     exceptionNumberIn => sqlcode,
6433                                     exceptionStringIn => sqlerrm);
6434           raise;
6435     end getHeaderAttValues1;
6436   procedure getHeaderAttValues2(attributeNameIn in varchar2,
6437                                 attributeValue1Out out nocopy varchar2,
6438                                 attributeValue2Out out nocopy varchar2,
6439                                 attributeValue3Out out nocopy varchar2) as
6440     attributeValueIndex integer;
6441     begin
6442       if (engAttributeVariant.exists(getAttributeIdByName(attributeNameIn => attributeNameIn))) then
6443         /* fetch the new attribute value */
6444         attributeValue1Out := getVariantAttributeValue(attributeIdIn => getAttributeIdByName(attributeNameIn => attributeNameIn),
6445                                     itemClassIn => getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
6446                                     itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex) );
6447         attributeValue2Out := null;
6448         attributeValue3Out := null;
6449       else
6450         attributeValueIndex := engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn));
6451         attributeValue1Out := engAttributeValues1(attributeValueIndex);
6452         attributeValue2Out := engAttributeValues2(attributeValueIndex);
6453         attributeValue3Out := engAttributeValues3(attributeValueIndex);
6454       end if;
6455       exception
6456         when others then
6457           ame_util.runtimeException(packageNameIn => 'ame_engine',
6458                                     routineNameIn => 'getHeaderAttValues2',
6459                                     exceptionNumberIn => sqlcode,
6460                                     exceptionStringIn => sqlerrm);
6461           raise;
6462     end getHeaderAttValues2;
6463   procedure getItemAppProcessCompleteYN(itemAppProcessCompleteYNOut out nocopy ame_util.charList) as
6464     begin
6465       for i in 1 .. engStItemAppProcessCompleteYN.count loop
6466         itemAppProcessCompleteYNOut(i) := engStItemAppProcessCompleteYN(i);
6467       end loop;
6468       exception
6469         when others then
6470           ame_util.runtimeException(packageNameIn => 'ame_engine',
6471                                     routineNameIn => 'getItemAppProcessCompleteYN',
6472                                     exceptionNumberIn => sqlcode,
6473                                     exceptionStringIn => sqlerrm);
6474           raise;
6475     end getItemAppProcessCompleteYN;
6476   procedure getItemAttValues1(attributeIdIn in integer,
6477                               itemIdIn in varchar2,
6478                               attributeValue1Out out nocopy varchar2,
6479                               attributeValue2Out out nocopy varchar2,
6480                               attributeValue3Out out nocopy varchar2) as
6481     attributeValueIndex integer;
6482     begin
6483       attributeValueIndex :=
6484         engAttributeValueIndexes(attributeIdIn) +
6485         getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeIdIn),
6486                       itemIdIn => itemIdIn);
6487       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6488       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6489       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6490       exception
6491         when others then
6492           ame_util.runtimeException(packageNameIn => 'ame_engine',
6493                                     routineNameIn => 'getItemAttValues1',
6494                                     exceptionNumberIn => sqlcode,
6495                                     exceptionStringIn => sqlerrm);
6496           raise;
6497     end getItemAttValues1;
6498   procedure getItemAttValues2(attributeNameIn in varchar2,
6499                               itemIdIn in varchar2,
6500                               attributeValue1Out out nocopy varchar2,
6501                               attributeValue2Out out nocopy varchar2,
6502                               attributeValue3Out out nocopy varchar2) as
6503     attributeId integer;
6504     attributeValueIndex integer;
6505     begin
6506       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6507       attributeValueIndex :=
6508         engAttributeValueIndexes(attributeId) +
6509         getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeId),
6510                       itemIdIn => itemIdIn);
6511       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6512       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6513       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6514       exception
6515         when others then
6516           ame_util.runtimeException(packageNameIn => 'ame_engine',
6517                                     routineNameIn => 'getItemAttValues2',
6518                                     exceptionNumberIn => sqlcode,
6519                                     exceptionStringIn => sqlerrm);
6520           raise;
6521     end getItemAttValues2;
6522   procedure getItemAttValues3(attributeIdIn in integer,
6523                               itemIndexIn in varchar2,
6524                               attributeValue1Out out nocopy varchar2,
6525                               attributeValue2Out out nocopy varchar2,
6526                               attributeValue3Out out nocopy varchar2) as
6527     attributeValueIndex integer;
6528     begin
6529       attributeValueIndex :=
6530         engAttributeValueIndexes(attributeIdIn) +
6531         itemIndexIn -
6532         engItemClassItemIdIndexes(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn)));
6533       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6534       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6535       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6536       exception
6537         when others then
6538           ame_util.runtimeException(packageNameIn => 'ame_engine',
6539                                     routineNameIn => 'getItemAttValues3',
6540                                     exceptionNumberIn => sqlcode,
6541                                     exceptionStringIn => sqlerrm);
6542           raise;
6543     end getItemAttValues3;
6544   procedure getItemClassAttValues1(attributeIdIn in integer,
6545                                    attributeValuesOut out nocopy ame_util.attributeValueList) as
6546     outputIndex integer;
6547     begin
6548       outputIndex := 0; /* pre-increment */
6549       for i in
6550         engAttributeValueIndexes(attributeIdIn) ..
6551         (engAttributeValueIndexes(attributeIdIn) +
6552          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn))) -
6553          1) loop
6554         outputIndex := outputIndex + 1;
6555         attributeValuesOut(outputIndex) := engAttributeValues1(i);
6556       end loop;
6557       exception
6558         when others then
6559           ame_util.runtimeException(packageNameIn => 'ame_engine',
6560                                     routineNameIn => 'getItemClassAttValues1',
6561                                     exceptionNumberIn => sqlcode,
6562                                     exceptionStringIn => sqlerrm);
6563           raise;
6564     end getItemClassAttValues1;
6565   procedure getItemClassAttValues2(attributeNameIn in varchar2,
6566                                    attributeValuesOut out nocopy ame_util.attributeValueList) as
6567     attributeId integer;
6568     outputIndex integer;
6569     begin
6570       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6571       outputIndex := 0; /* pre-increment */
6572       for i in
6573         engAttributeValueIndexes(attributeId) ..
6574         (engAttributeValueIndexes(attributeId) +
6575          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeId))) -
6576          1) loop
6577         outputIndex := outputIndex + 1;
6578         attributeValuesOut(outputIndex) := engAttributeValues1(i);
6579       end loop;
6580       exception
6581         when others then
6582           ame_util.runtimeException(packageNameIn => 'ame_engine',
6583                                     routineNameIn => 'getItemClassAttValues2',
6584                                     exceptionNumberIn => sqlcode,
6585                                     exceptionStringIn => sqlerrm);
6586           raise;
6587     end getItemClassAttValues2;
6588   procedure getItemClassAttValues3(attributeIdIn in integer,
6589                                    attributeValues1Out out nocopy ame_util.attributeValueList,
6590                                    attributeValues2Out out nocopy ame_util.attributeValueList,
6591                                    attributeValues3Out out nocopy ame_util.attributeValueList) as
6592     outputIndex integer;
6593     begin
6594       outputIndex := 0; /* pre-increment */
6595       for i in
6596         engAttributeValueIndexes(attributeIdIn) ..
6597         (engAttributeValueIndexes(attributeIdIn) +
6598          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn))) -
6599          1) loop
6600         outputIndex := outputIndex + 1;
6601         attributeValues1Out(outputIndex) := engAttributeValues1(i);
6602         attributeValues2Out(outputIndex) := engAttributeValues2(i);
6603         attributeValues3Out(outputIndex) := engAttributeValues3(i);
6604       end loop;
6605       exception
6606         when others then
6607           ame_util.runtimeException(packageNameIn => 'ame_engine',
6608                                     routineNameIn => 'getItemClassAttValues3',
6609                                     exceptionNumberIn => sqlcode,
6610                                     exceptionStringIn => sqlerrm);
6611           raise;
6612     end getItemClassAttValues3;
6613   procedure getItemClassAttValues4(attributeNameIn in varchar2,
6614                                    attributeValues1Out out nocopy ame_util.attributeValueList,
6615                                    attributeValues2Out out nocopy ame_util.attributeValueList,
6616                                    attributeValues3Out out nocopy ame_util.attributeValueList) as
6617     attributeId integer;
6618     outputIndex integer;
6619     begin
6620       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6621       outputIndex := 0; /* pre-increment */
6622       for i in
6623         engAttributeValueIndexes(attributeId) ..
6624         (engAttributeValueIndexes(attributeId) +
6625          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeId))) -
6626          1) loop
6627         outputIndex := outputIndex + 1;
6628         attributeValues1Out(outputIndex) := engAttributeValues1(i);
6629         attributeValues2Out(outputIndex) := engAttributeValues2(i);
6630         attributeValues3Out(outputIndex) := engAttributeValues3(i);
6631       end loop;
6632       exception
6633         when others then
6634           ame_util.runtimeException(packageNameIn => 'ame_engine',
6635                                     routineNameIn => 'getItemClassAttValues4',
6636                                     exceptionNumberIn => sqlcode,
6637                                     exceptionStringIn => sqlerrm);
6638           raise;
6639     end getItemClassAttValues4;
6640   procedure getItemClassItemIds(itemClassIdIn in integer,
6641                                 itemIdsOut out nocopy ame_util.stringList) as
6642     firstItemIndex integer;
6643     itemClassIndex integer;
6644     tempIndex integer;
6645     begin
6646       itemClassIndex := engItemClassIndexes(itemClassIdIn);
6647       firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
6648       if(firstItemIndex is not null) then
6649         tempIndex := 0; /* pre-increment */
6650         for itemIndex in
6651           firstItemIndex ..
6652           (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
6653           tempIndex := tempIndex + 1;
6654           itemIdsOut(tempIndex) := engItemIds(itemIndex);
6655         end loop;
6656       end if;
6657       exception
6658         when others then
6659           itemIdsOut.delete;
6660           ame_util.runtimeException(packageNameIn => 'ame_engine',
6661                                     routineNameIn => 'getItemClassItemIds',
6662                                     exceptionNumberIn => sqlcode,
6663                                     exceptionStringIn => sqlerrm);
6664           raise;
6665     end getItemClassItemIds;
6666   procedure getItemClasses(itemClassesOut out nocopy ame_util.stringList) as
6667     begin
6668       for i in 1 .. engStItemClasses.count loop
6669         itemClassesOut(i) := engStItemClasses(i);
6670       end loop;
6671       exception
6672         when others then
6673           ame_util.runtimeException(packageNameIn => 'ame_engine',
6674                                     routineNameIn => 'getItemClasses',
6675                                     exceptionNumberIn => sqlcode,
6676                                     exceptionStringIn => sqlerrm);
6677           raise;
6678     end getItemClasses;
6679   procedure getItemIds(itemIdsOut out nocopy ame_util.stringList) as
6680     begin
6681       for i in 1 .. engStItemIds.count loop
6682         itemIdsOut(i) := engStItemIds(i);
6683       end loop;
6684       exception
6685         when others then
6686           ame_util.runtimeException(packageNameIn => 'ame_engine',
6687                                     routineNameIn => 'getItemIds',
6688                                     exceptionNumberIn => sqlcode,
6689                                     exceptionStringIn => sqlerrm);
6690           raise;
6691     end getItemIds;
6692   procedure getItemIndexes(itemIndexesOut out nocopy ame_util.idList) as
6693     begin
6694       for i in 1 .. engStItemIndexes.count loop
6695         itemIndexesOut(i) := engStItemIndexes(i);
6696       end loop;
6697       exception
6698         when others then
6699           ame_util.runtimeException(packageNameIn => 'ame_engine',
6700                                     routineNameIn => 'getItemIndexes',
6701                                     exceptionNumberIn => sqlcode,
6702                                     exceptionStringIn => sqlerrm);
6703           raise;
6704     end getItemIndexes;
6705   procedure getItemSources(itemSourcesOut out nocopy ame_util.longStringList) as
6706     begin
6707       for i in 1 .. engStItemSources.count loop
6708         itemSourcesOut(i) := engStItemSources(i);
6709       end loop;
6710       exception
6711         when others then
6712           ame_util.runtimeException(packageNameIn => 'ame_engine',
6713                                     routineNameIn => 'getItemSources',
6714                                     exceptionNumberIn => sqlcode,
6715                                     exceptionStringIn => sqlerrm);
6716           raise;
6717     end getItemSources;
6718   procedure getAllItemClasses(itemClassNamesOut out nocopy ame_util.stringList) as
6719     tempIndex integer;
6720     tempCount integer;
6721     begin
6722       tempIndex := 0;
6723       tempCount := 0;
6724       for i in 1 .. engItemClassIds.count loop
6725         tempCount := engItemCounts(engItemClassIndexes(engItemClassIds(i)));
6726         tempIndex := itemClassNamesOut.count;
6727         for x in 1 .. tempCount loop
6728           itemClassNamesOut(tempIndex + x) := engItemClassNames(i);
6729         end loop;
6730       end loop;
6731       exception
6732         when others then
6733           ame_util.runtimeException(packageNameIn => 'ame_engine',
6734                                     routineNameIn => 'getAllItemClasses',
6735                                     exceptionNumberIn => sqlcode,
6736                                     exceptionStringIn => sqlerrm);
6737           raise;
6738     end getAllItemClasses;
6739   procedure getAllItemIds(itemIdsOut out nocopy ame_util.stringList) as
6740     begin
6741       for i in 1 .. engItemIds.count loop
6742         itemIdsOut(i) := engItemIds(i);
6743       end loop;
6744       exception
6745         when others then
6746           ame_util.runtimeException(packageNameIn => 'ame_engine',
6747                                     routineNameIn => 'getAllItemIds',
6748                                     exceptionNumberIn => sqlcode,
6749                                     exceptionStringIn => sqlerrm);
6750           raise;
6751     end getAllItemIds;
6752   procedure getInsertions
6753     (positionIn             in            number
6754     ,orderTypeIn            in            varchar2 default null
6755     ,coaInsertionsYNIn      in            varchar2 default ame_util.booleanTrue
6756     ,availableInsertionsOut    out nocopy ame_util.insertionsTable2
6757     ) as
6758 
6759     engStApproversCount         integer;
6760     availableInsertionsIndex    integer; /* pre-increment */
6761     errorCode                   integer;
6762     errorMessage                ame_util.longestStringType;
6763     invalidPositionException    exception;
6764     nextApproverDescription     ame_temp_insertions.description%type;
6765     prevApproverDescription     ame_temp_insertions.description%type;
6766     ruleIdList                  ame_util.idList;
6767     sourceDescription           ame_util.stringType;
6768     tempBoolean                 boolean;
6769     tempInsertionDoesNotExist   boolean;
6770     tempParameter               ame_temp_insertions.parameter%type;
6771     l_error_code                number;
6772   begin
6773 
6774     engStApproversCount := engStApprovers.count;
6775 
6776     if(positionIn < 1 or
6777        positionIn > engStApproversCount + 1 or
6778        not ame_util.isANonNegativeInteger(stringIn => positionIn)) then
6779       raise invalidPositionException;
6780     end if;
6781 
6782     availableInsertionsIndex := 0;
6783 
6784     if (orderTypeIn is null or
6785         orderTypeIn = ame_util.absoluteOrder) then
6786 
6787       tempParameter := positionIn;
6788       if (engStApproversCount = 0) then
6789 
6790         /* pre-approver */
6791         if (not ame_engine.insertionExists
6792                   (orderTypeIn   => ame_util.absoluteOrder
6793                   ,parameterIn   => tempParameter
6794                   )) then
6795           availableInsertionsIndex := availableInsertionsIndex + 1;
6796           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6797           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6798           availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6799           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6800           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6801           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6802           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6803           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
6804           availableInsertionsOut(availableInsertionsIndex).description :=
6805                                         ame_util.absoluteOrderDescription || positionIn || '.  ';
6806         end if;
6807 
6808         /* authority approver */
6809         if (not ame_engine.insertionExists
6810                   (orderTypeIn   => ame_util.absoluteOrder
6811                   ,parameterIn   => tempParameter
6812                   )) then
6813           availableInsertionsIndex := availableInsertionsIndex + 1;
6814           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6815           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6816           availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6817           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6818           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6819           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6820           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6821           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.authorityApprover;
6822           availableInsertionsOut(availableInsertionsIndex).description :=
6823                                          ame_util.absoluteOrderDescription || positionIn || '.  ';
6824         end if;
6825 
6826         /* post approver */
6827         if (not ame_engine.insertionExists
6828                   (orderTypeIn   => ame_util.absoluteOrder
6829                   ,parameterIn   => tempParameter
6830                   )) then
6831           availableInsertionsIndex := availableInsertionsIndex + 1;
6832           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6833           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6834           availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6835           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6836           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6837           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6838           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6839           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
6840           availableInsertionsOut(availableInsertionsIndex).description :=
6841                                          ame_util.absoluteOrderDescription || positionIn || '.  ';
6842         end if;
6843 
6844       else /* If approver count is more than zero */
6845 
6846         if (positionIn < engStApproversCount + 1) then
6847 
6848           /* Attribute to the insertee the relevant properties of the approver at positionIn. */
6849           if (not ame_engine.insertionExists
6850                     (orderTypeIn   => ame_util.absoluteOrder
6851                     ,parameterIn   => tempParameter
6852                     )) then
6853             availableInsertionsIndex := availableInsertionsIndex + 1;
6854             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
6855             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
6856             availableInsertionsOut(availableInsertionsIndex).action_type_id := engStApprovers(positionIn).action_type_id;
6857             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6858                                                                        engStApprovers(positionIn).group_or_chain_id;
6859             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6860             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6861             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6862             availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn).authority;
6863             availableInsertionsOut(availableInsertionsIndex).description :=
6864                                          ame_util.absoluteOrderDescription || positionIn || '.  ';
6865           end if;
6866 
6867         end if;
6868 
6869         /*
6870           If there is an approver at positionIn - 1, and the approver's relevant properties differ from
6871           those of the approver at positionIn (if any), add a second available insertion, attributing
6872           to the insertee the relevant properties of engStApprovers(positionIn - 1).
6873         */
6874         if (positionIn = engStApproversCount + 1 or
6875             (positionIn > 1 and
6876              (engStApprovers(positionIn).group_or_chain_id <> engStApprovers(positionIn - 1).group_or_chain_id or
6877               engStApprovers(positionIn).action_type_id <> engStApprovers(positionIn - 1).action_type_id or
6878               engStApprovers(positionIn).item_id <> engStApprovers(positionIn - 1).item_id or
6879               engStApprovers(positionIn).item_class <> engStApprovers(positionIn - 1).item_class
6880              ))) then
6881 
6882           /* Attribute to the insertee the relevant properties of the approver at positionIn - 1. */
6883           if (not ame_engine.insertionExists
6884                     (orderTypeIn   => ame_util.absoluteOrder
6885                     ,parameterIn   => tempParameter
6886                     )) then
6887             availableInsertionsIndex := availableInsertionsIndex + 1;
6888             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6889             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6890             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6891                                                                    engStApprovers(positionIn - 1).action_type_id;
6892             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6893                                                                  engStApprovers(positionIn - 1).group_or_chain_id;
6894             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6895             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6896             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6897             availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6898             availableInsertionsOut(availableInsertionsIndex).description :=
6899                                                     ame_util.absoluteOrderDescription || positionIn || '.  ';
6900           end if;
6901         end if;
6902       end if; /* End if approver count > 0 */
6903 
6904     end if; /* End if order type is absolute Order */
6905 
6906     /*
6907       ORDER TYPE:  afterApprover
6908       Ad-hoc afterApprover is available if positionIn > 1.  COA afterApprover is available if also
6909       the approver at positionIn - 1 is a COA approvalApproverCategory approver.
6910     */
6911     if (orderTypeIn is null or
6912         orderTypeIn = ame_util.afterApprover) then
6913 
6914       if (positionIn = 1 or
6915           engStApproversCount = 0) then
6916         prevApproverDescription := null;
6917       else
6918         begin
6919           prevApproverDescription :=
6920              ame_approver_type_pkg.getApproverDisplayName(nameIn => engStApprovers(positionIn - 1).name);
6921 
6922         exception
6923           when others then
6924             l_error_code := sqlcode;
6925             if l_error_code = 20213 then
6926               errorCode := -20218;
6927               errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
6928                                               messageNameIn => 'AME_400837_INV_APR_FOUND',
6929                                               tokenNameOneIn  => 'PROCESS_NAME',
6930                                               tokenValueOneIn => 'ame_engine.getInsertions',
6931                                               tokenNameTwoIn => 'NAME',
6932                                               tokenValueTwoIn => engStApprovers(positionIn - 1).name);
6933               raise_application_error(errorCode,errorMessage);
6934             end if;
6935             raise;
6936         end;
6937       end if;
6938 
6939       if(positionIn > 1) then /* ad-hoc */
6940 
6941         tempParameter := engStApprovers(positionIn - 1).name ||
6942                          ame_util.fieldDelimiter ||
6943                          engStApprovers(positionIn - 1).item_class ||
6944                          ame_util.fieldDelimiter ||
6945                          engStApprovers(positionIn - 1).item_id ||
6946                          ame_util.fieldDelimiter ||
6947                          engStApprovers(positionIn - 1).action_type_id ||
6948                          ame_util.fieldDelimiter ||
6949                          engStApprovers(positionIn - 1).group_or_chain_id ||
6950                          ame_util.fieldDelimiter ||
6951                          engStApprovers(positionIn - 1).occurrence;
6952 
6953         if (not ame_engine.insertionExists
6954                   (orderTypeIn   => ame_util.afterApprover
6955                   ,parameterIn   => tempParameter
6956                   )) then
6957           availableInsertionsIndex := availableInsertionsIndex + 1;
6958           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6959           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6960           availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6961                                                                 engStApprovers(positionIn - 1).action_type_id;
6962           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6963                                                              engStApprovers(positionIn - 1).group_or_chain_id;
6964           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.afterApprover;
6965           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6966           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6967           availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6968           availableInsertionsOut(availableInsertionsIndex).description :=
6969                                            ame_util.afterApproverDescription || prevApproverDescription;
6970         end if;
6971 
6972         if positionIn <= engStApproversCount then
6973 
6974           if (engStApprovers(positionIn).authority = ame_util.authorityApprover and
6975               engStApprovers(positionIn).api_insertion <> ame_util.apiInsertion and
6976               engStApprovers(positionIn).approver_category = ame_util.approvalApproverCategory and
6977               coaInsertionsYNIn = ame_util.booleanTrue and
6978               (not ame_engine.insertionExists
6979                    (orderTypeIn   => ame_util.afterApprover
6980                    ,parameterIn   => tempParameter
6981                    ))) then /* COA */
6982             availableInsertionsIndex := availableInsertionsIndex + 1;
6983             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6984             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6985             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6986                                                              engStApprovers(positionIn - 1).action_type_id;
6987             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6988                                                                  engStApprovers(positionIn - 1).group_or_chain_id;
6989             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.afterApprover;
6990               /* We've already build the parameter field above, let's not repeat the work here. */
6991             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6992             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiAuthorityInsertion;
6993             availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6994             availableInsertionsOut(availableInsertionsIndex).description :=
6995                                          ame_util.afterApproverDescription || prevApproverDescription;
6996           end if;
6997         end if;
6998       end if;
6999     end if;
7000 
7001     /*
7002       ORDER TYPE:  beforeApprover
7003       beforeApprover is available if engStApproversCount > 0 and positionIn < engStApproversCount + 1.
7004     */
7005     if (orderTypeIn is null or
7006          orderTypeIn = ame_util.beforeApprover
7007        ) then
7008 
7009       if (positionIn = engStApproversCount + 1 or
7010           engStApproversCount = 0) then
7011         nextApproverDescription := null;
7012       else
7013         begin
7014           nextApproverDescription :=
7015                  ame_approver_type_pkg.getApproverDisplayName(nameIn => engStApprovers(positionIn).name);
7016         exception
7017           when others then
7018            l_error_code := sqlcode;
7019            if l_error_code = -20213 then
7020              errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
7021                                               messageNameIn => 'AME_400837_INV_APR_FOUND',
7022                                               tokenNameOneIn  => 'PROCESS_NAME',
7023                                               tokenValueOneIn => 'ame_engine.getInsertions',
7024                                               tokenNameTwoIn => 'NAME',
7025                                               tokenValueTwoIn =>  engStApprovers(positionIn).name);
7026              raise_application_error(errorCode,errorMessage);
7027            end if;
7028            raise;
7029         end;
7030       end if;
7031 
7032       if (engStApproversCount > 0 and
7033           positionIn < engStApproversCount + 1) then
7034 
7035         tempParameter := engStApprovers(positionIn).name ||
7036                          ame_util.fieldDelimiter ||
7037                          engStApprovers(positionIn).item_class ||
7038                          ame_util.fieldDelimiter ||
7039                          engStApprovers(positionIn).item_id ||
7040                          ame_util.fieldDelimiter ||
7041                          engStApprovers(positionIn).action_type_id ||
7042                          ame_util.fieldDelimiter ||
7043                          engStApprovers(positionIn).group_or_chain_id ||
7044                          ame_util.fieldDelimiter ||
7045                          engStApprovers(positionIn).occurrence;
7046 
7047         if (not ame_engine.insertionExists
7048                   (orderTypeIn   => ame_util.beforeApprover
7049                   ,parameterIn   => tempParameter
7050                   )) then
7051           availableInsertionsIndex := availableInsertionsIndex + 1;
7052           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7053           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7054           availableInsertionsOut(availableInsertionsIndex).action_type_id := engStApprovers(positionIn).action_type_id;
7055           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7056                                                                     engStApprovers(positionIn).group_or_chain_id;
7057           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.beforeApprover;
7058           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7059           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7060           availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn).authority;
7061           availableInsertionsOut(availableInsertionsIndex).description :=
7062                                              ame_util.beforeApproverDescription || nextApproverDescription;
7063         end if;
7064       end if;
7065     end if;
7066 
7067     /*
7068       ORDER TYPE:  firstAuthority
7069       firstAuthority is available if the approver you're at is the first COA approver in a chain.
7070     */
7071     if (coaInsertionsYNIn = ame_util.booleanTrue and
7072         (orderTypeIn is null or
7073         orderTypeIn = ame_util.firstAuthority)) then
7074 
7075       if (positionIn < engStApproversCount + 1 and
7076           engStApprovers(positionIn).authority = ame_util.authorityApprover and
7077           engStApprovers(positionIn).api_insertion <> ame_util.apiInsertion) then
7078         tempBoolean := true; /* tempBoolean remains true if no previous authority is found. */
7079         for i in reverse 1..positionIn - 1 loop
7080           if (engStApprovers(i).group_or_chain_id <> engStApprovers(positionIn).group_or_chain_id or
7081               engStApprovers(i).action_type_id <> engStApprovers(positionIn).action_type_id or
7082               engStApprovers(i).item_id <> engStApprovers(positionIn).item_id or
7083               engStApprovers(i).item_class <> engStApprovers(positionIn).item_class) then
7084             exit;
7085           end if;
7086 
7087           if (engStApprovers(i).authority = ame_util.authorityApprover and
7088               engStApprovers(i).api_insertion <> ame_util.apiInsertion) then
7089             tempBoolean := false;
7090             exit;
7091           end if;
7092         end loop;
7093 
7094         if (tempBoolean) then
7095           tempParameter := ame_util.firstAuthorityParameter ||
7096                            ame_util.fieldDelimiter ||
7097                            engStApprovers(positionIn).item_class ||
7098                            ame_util.fieldDelimiter ||
7099                            engStApprovers(positionIn).item_id ||
7100                            ame_util.fieldDelimiter ||
7101                            engStApprovers(positionIn).action_type_id ||
7102                            ame_util.fieldDelimiter ||
7103                            engStApprovers(positionIn).group_or_chain_id;
7104 
7105           if (not ame_engine.insertionExists
7106                     (orderTypeIn   => ame_util.firstAuthority
7107                     ,parameterIn   => tempParameter
7108                     )) then
7109             availableInsertionsIndex := availableInsertionsIndex + 1;
7110             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7111             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7112             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
7113                                                                    engStApprovers(positionIn).action_type_id;
7114             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7115                                                                  engStApprovers(positionIn).group_or_chain_id;
7116             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstAuthority;
7117             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7118             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiAuthorityInsertion;
7119             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.authorityApprover;
7120             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstAuthorityDescription;
7121           end if;
7122         end if;
7123       end if;
7124     end if;
7125 
7126     /*
7127       ORDER TYPE:  firstPostApprover
7128       Assume that in the case of an entirely empty approver list, we allow insertion of a first
7129       post-approver into the header item's list only.  Otherwise, we only allow insertion of a
7130       first post-approver into a non-empty item list.  Here is the case analysis:
7131           if(the approver list is empty) then
7132             allow a first-post-approver insertion for the header
7133           elsif(positionIn is after the end of the approver list) then
7134             if(the last approver in the list is not a post-approver) then
7135               allow a first-post-approver insertion for the last approver's item
7136             end if
7137           elsif(positionIn = 1) then
7138             if(the first approver in the list is a post-approver_ then
7139               allow a first-post-approver insertion for the first approver's item
7140             end if
7141           else
7142             if(the engStApprovers at positionIn - 1 and positionIn are for the same item) then
7143               if(the first approver is not a post-approver and
7144                  the second approver is a post-approver) then
7145                 allow a first-post-approver insertion for the engStApprovers' item
7146               end if
7147             else
7148               if(the second approver is a post-approver) then
7149                 allow a first-post-approver insertion for the second approver's item
7150               end if
7151               if(the first approver is not a post-approver) then
7152                 allow a first-post-approver insertion for the first approver's item
7153               end if
7154             end if
7155           end if
7156     */
7157     if (orderTypeIn is null or
7158         orderTypeIn = ame_util.firstPostApprover) then
7159 
7160       if (engStApproversCount = 0) then
7161         tempParameter := ame_util.firstPostParameter ||
7162                          ame_util.fieldDelimiter ||
7163                          ame_util.headerItemClassName ||
7164                          ame_util.fieldDelimiter ||
7165                          engTransactionId;
7166 
7167         if (not ame_engine.insertionExists
7168                   (orderTypeIn => ame_util.firstPostApprover
7169                   ,parameterIn => tempParameter
7170                   )) then
7171           availableInsertionsIndex := availableInsertionsIndex + 1;
7172           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7173           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7174           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7175           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7176           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7177           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7178           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7179           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7180           availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7181         end if;
7182       elsif (positionIn = engStApproversCount + 1) then
7183         if (engStApprovers(engStApproversCount).authority <> ame_util.postApprover) then
7184           tempParameter := ame_util.firstPostParameter ||
7185                            ame_util.fieldDelimiter ||
7186                            engStApprovers(engStApproversCount).item_class ||
7187                            ame_util.fieldDelimiter ||
7188                            engStApprovers(engStApproversCount).item_id;
7189           if (not ame_engine.insertionExists
7190                     (orderTypeIn   => ame_util.firstPostApprover
7191                     ,parameterIn   => tempParameter
7192                     )) then
7193             availableInsertionsIndex := availableInsertionsIndex + 1;
7194             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(engStApproversCount).item_class;
7195             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(engStApproversCount).item_id;
7196             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
7197                                                                         ame_util.nullInsertionActionTypeId;
7198             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7199                                                                       ame_util.nullInsertionGroupOrChainId;
7200             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7201             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7202             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7203             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7204             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7205           end if;
7206         end if;
7207       elsif (positionIn = 1) then
7208         if (engStApprovers(1).authority = ame_util.postApprover) then
7209           tempParameter := ame_util.firstPostParameter ||
7210                            ame_util.fieldDelimiter ||
7211                            engStApprovers(1).item_class ||
7212                            ame_util.fieldDelimiter ||
7213                            engStApprovers(1).item_id;
7214           if (not ame_engine.insertionExists
7215                     (orderTypeIn   => ame_util.firstPostApprover
7216                     ,parameterIn   => tempParameter
7217                     )) then
7218             availableInsertionsIndex := availableInsertionsIndex + 1;
7219             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7220             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7221             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7222             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7223             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7224             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7225             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7226             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7227             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7228           end if;
7229         end if;
7230       else
7231         if (engStApprovers(positionIn - 1).item_id = engStApprovers(positionIn).item_id and
7232             engStApprovers(positionIn - 1).item_class = engStApprovers(positionIn).item_class) then
7233           if (engStApprovers(positionIn - 1).authority <> ame_util.postApprover and
7234               engStApprovers(positionIn).authority = ame_util.postApprover) then
7235             tempParameter := ame_util.firstPostParameter ||
7236                              ame_util.fieldDelimiter ||
7237                              engStApprovers(positionIn).item_class ||
7238                              ame_util.fieldDelimiter ||
7239                              engStApprovers(positionIn).item_id;
7240             if (not ame_engine.insertionExists
7241                       (orderTypeIn => ame_util.firstPostApprover
7242                       ,parameterIn => tempParameter
7243                       )) then
7244               availableInsertionsIndex := availableInsertionsIndex + 1;
7245               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7246               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7247               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7248               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7249               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7250                                                             engStApprovers(positionIn).group_or_chain_id;
7251               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7252               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7253               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7254               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7255               availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7256             end if;
7257           end if;
7258         else
7259           if (engStApprovers(positionIn).authority = ame_util.postApprover) then
7260             tempParameter := ame_util.firstPostParameter ||
7261                              ame_util.fieldDelimiter ||
7262                              engStApprovers(positionIn).item_class ||
7263                              ame_util.fieldDelimiter ||
7264                              engStApprovers(positionIn).item_id;
7265             if (not ame_engine.insertionExists
7266                       (orderTypeIn   => ame_util.firstPostApprover
7267                       ,parameterIn   => tempParameter
7268                       )) then
7269               availableInsertionsIndex := availableInsertionsIndex + 1;
7270               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7271               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7272               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7273               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7274               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7275               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7276               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7277               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7278               availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7279             end if;
7280           end if;
7281 
7282           if (engStApprovers(positionIn - 1).authority <> ame_util.postApprover) then
7283             tempParameter := ame_util.firstPostParameter ||
7284                              ame_util.fieldDelimiter ||
7285                              engStApprovers(positionIn - 1).item_class ||
7286                              ame_util.fieldDelimiter ||
7287                              engStApprovers(positionIn - 1).item_id;
7288             if (not ame_engine.insertionExists
7289                       (orderTypeIn   => ame_util.firstPostApprover
7290                       ,parameterIn   => tempParameter
7291                       )) then
7292               availableInsertionsIndex := availableInsertionsIndex + 1;
7293               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
7294               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
7295               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7296               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7297               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7298               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7299               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7300               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7301               availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7302             end if;
7303           end if;
7304         end if;
7305       end if;
7306     end if;
7307 
7308     /*
7309       ORDER TYPE:  firstPreApprover
7310       Assume that in the case of an entirely empty approver list, we allow insertion of a first
7311       pre-approver into the header item's list only.  Otherwise, we only allow insertion of a
7312       first pre-approver into a non-empty item list.  Here is the case analysis:
7313         if(the approver list is empty) then
7314           allow a first-pre-approver insertion for the header item
7315         elsif(positionIn = 1) then
7316           allow a first-pre-approver insertion for the first approver's item
7317         elsif(positionIn < engStApproversCount + 1) then
7318           if(the engStApprovers at positionIn - 1 and positionIn are for different items) then
7319             allow a first-pre-approver insertion for the second approver's item
7320           end if
7321         end if
7322     */
7323     if (orderTypeIn is null or
7324         orderTypeIn = ame_util.firstPreApprover) then
7325 
7326       if (engStApproversCount = 0) then
7327         tempParameter := ame_util.firstPreApprover ||
7328                          ame_util.fieldDelimiter ||
7329                          ame_util.headerItemClassName ||
7330                          ame_util.fieldDelimiter ||
7331                          engTransactionId;
7332         if (not ame_engine.insertionExists
7333                   (orderTypeIn => ame_util.firstPreApprover
7334                   ,parameterIn => tempParameter
7335                   )) then
7336           availableInsertionsIndex := availableInsertionsIndex + 1;
7337           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7338           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7339           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7340           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7341           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7342           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7343           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7344           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7345           availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7346         end if;
7347       elsif (positionIn = 1) then
7348         tempParameter := ame_util.firstPreApprover ||
7349                          ame_util.fieldDelimiter ||
7350                          engStApprovers(1).item_class ||
7351                          ame_util.fieldDelimiter ||
7352                          engStApprovers(1).item_id;
7353         if (not ame_engine.insertionExists
7354                   (orderTypeIn   => ame_util.firstPreApprover
7355                   ,parameterIn   => tempParameter
7356                   )) then
7357           availableInsertionsIndex := availableInsertionsIndex + 1;
7358           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7359           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7360           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7361           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7362           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7363           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7364           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7365           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7366           availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7367         end if;
7368       elsif (positionIn < engStApproversCount + 1) then
7369         if (engStApprovers(positionIn - 1).item_id <> engStApprovers(positionIn).item_id or
7370             engStApprovers(positionIn - 1).item_class <> engStApprovers(positionIn).item_class) then
7371           tempParameter := ame_util.firstPreApprover ||
7372                            ame_util.fieldDelimiter ||
7373                            engStApprovers(positionIn).item_class ||
7374                            ame_util.fieldDelimiter ||
7375                            engStApprovers(positionIn).item_id;
7376           if (not ame_engine.insertionExists
7377                     (orderTypeIn   => ame_util.firstPreApprover
7378                     ,parameterIn   => tempParameter
7379                     )) then
7380             availableInsertionsIndex := availableInsertionsIndex + 1;
7381             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7382             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7383             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7384             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7385             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7386             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7387             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7388             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7389             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7390           end if;
7391         end if;
7392       end if;
7393     end if;
7394 
7395     /*
7396       ORDER TYPE:  lastPostApprover
7397       Assume that in the case of an entirely empty approver list, we allow insertion of a last
7398       post-approver into the header item's list only.  Otherwise, we only allow insertion of a
7399       last post-approver into a non-empty item list.  Here is the case analysis:
7400         if(the approver list is empty) then
7401           allow last-post-approver insertion for the header item
7402         elsif(positionIn = engStApproversCount + 1) then
7403           allow last-post-approver insertion for the last approver's item
7404         elsif(positionIn > 1) then
7405           if(the engStApprovers at positionIn - 1 and positionIn are for different items) then
7406             allow last-post-approver insertion for the former approver's item
7407           end if
7408         end if
7409     */
7410     if (orderTypeIn is null or
7411         orderTypeIn = ame_util.lastPostApprover) then
7412       if (engStApproversCount = 0) then
7413         tempParameter := ame_util.lastPostApprover ||
7414                          ame_util.fieldDelimiter ||
7415                          ame_util.headerItemClassName ||
7416                          ame_util.fieldDelimiter ||
7417                          engTransactionId;
7418         if (not ame_engine.insertionExists
7419                   (orderTypeIn   => ame_util.lastPostApprover
7420                   ,parameterIn   => tempParameter
7421                   )) then
7422           availableInsertionsIndex := availableInsertionsIndex + 1;
7423           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7424           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7425           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7426           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7427           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7428           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7429           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7430           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7431           availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7432         end if;
7433       elsif (positionIn = engStApproversCount + 1) then
7434         tempParameter := ame_util.lastPostApprover ||
7435                          ame_util.fieldDelimiter ||
7436                          engStApprovers(engStApproversCount).item_class ||
7437                          ame_util.fieldDelimiter ||
7438                          engStApprovers(engStApproversCount).item_id;
7439         if (not ame_engine.insertionExists
7440                   (orderTypeIn => ame_util.lastPostApprover
7441                   ,parameterIn => tempParameter
7442                   )) then
7443           availableInsertionsIndex := availableInsertionsIndex + 1;
7444           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(engStApproversCount).item_class;
7445           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(engStApproversCount).item_id;
7446           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7447           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7448           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7449           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7450           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7451           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7452           availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7453         end if;
7454       elsif (positionIn > 1) then
7455         if (engStApprovers(positionIn - 1).item_id <> engStApprovers(positionIn).item_id or
7456             engStApprovers(positionIn - 1).item_class <> engStApprovers(positionIn).item_class) then
7457           tempParameter := ame_util.lastPostApprover ||
7458                            ame_util.fieldDelimiter ||
7459                            engStApprovers(positionIn - 1).item_class ||
7460                            ame_util.fieldDelimiter ||
7461                            engStApprovers(positionIn - 1).item_id;
7462           if (not ame_engine.insertionExists
7463                     (orderTypeIn   => ame_util.lastPostApprover
7464                     ,parameterIn   => tempParameter
7465                     )) then
7466             availableInsertionsIndex := availableInsertionsIndex + 1;
7467             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
7468             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
7469             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7470             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7471             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7472             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7473             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7474             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7475             availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7476           end if;
7477         end if;
7478       end if;
7479     end if;
7480 
7481     /*
7482       ORDER TYPE:  lastPreApprover
7483       Assume that in the case of an entirely empty approver list, we allow insertion of a last
7484       pre-approver into the header item's list only.  Otherwise, we only allow insertion of a
7485       last pre-approver into a non-empty item list.  Here is the case analysis:
7486         if(the approver list is empty) then
7487           allow last-pre-approver insertion for the header item
7488         elsif(positionIn = 1) then
7489           if(the approver at position 1 is not a pre-approver) then
7490             allow last-pre-approver insertion for the item of the first approver
7491           end if
7492         elsif(positionIn <= engStApproversCount) then
7493           if(the engStApprovers at positionIn - 1 and positionIn are for the same item) then
7494             if(the approver at positionIn - 1 is a pre-approver and
7495                the approver at positionIn is not a pre-approver) then
7496               allow last-pre-approver insertion for the engStApprovers' item
7497             end if
7498           else
7499             if(the approver at positionIn is not a pre-approver) then
7500               allow last-pre-approver insertion for the item of the approver at positionIn
7501             end if
7502           end if
7503         end if
7504     */
7505     if (orderTypeIn is null or
7506         orderTypeIn = ame_util.lastPreApprover) then
7507       if (engStApproversCount = 0) then
7508         tempParameter := ame_util.lastPreApprover ||
7509                          ame_util.fieldDelimiter ||
7510                          ame_util.headerItemClassName ||
7511                          ame_util.fieldDelimiter ||
7512                          engTransactionId;
7513         if (not ame_engine.insertionExists
7514                   (orderTypeIn => ame_util.lastPreApprover
7515                   ,parameterIn => tempParameter)) then
7516           availableInsertionsIndex := availableInsertionsIndex + 1;
7517           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7518           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7519           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7520           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7521           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7522           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7523           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7524           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7525           availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7526         end if;
7527       elsif (positionIn = 1) then
7528         if (engStApprovers(1).authority <> ame_util.preApprover) then
7529           tempParameter := ame_util.lastPreApprover ||
7530                            ame_util.fieldDelimiter ||
7531                            engStApprovers(1).item_class ||
7532                            ame_util.fieldDelimiter ||
7533                            engStApprovers(1).item_id;
7534           if (not ame_engine.insertionExists
7535                     (orderTypeIn   => ame_util.lastPreApprover
7536                     ,parameterIn   => tempParameter
7537                     )) then
7538             availableInsertionsIndex := availableInsertionsIndex + 1;
7539             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7540             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7541             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7542             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7543             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7544             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7545             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7546             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7547             availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7548           end if;
7549         end if;
7550       elsif (positionIn <= engStApproversCount) then
7551         if (engStApprovers(positionIn - 1).item_id = engStApprovers(positionIn).item_id and
7552             engStApprovers(positionIn - 1).item_class = engStApprovers(positionIn).item_class) then
7553           if (engStApprovers(positionIn - 1).authority = ame_util.preApprover and
7554               engStApprovers(positionIn).authority <> ame_util.preApprover) then
7555             tempParameter := ame_util.lastPreApprover ||
7556                              ame_util.fieldDelimiter ||
7557                              engStApprovers(positionIn).item_class ||
7558                              ame_util.fieldDelimiter ||
7559                              engStApprovers(positionIn).item_id;
7560             if (not ame_engine.insertionExists
7561                       (orderTypeIn  => ame_util.lastPreApprover
7562                       ,parameterIn  => tempParameter
7563                       )) then
7564               availableInsertionsIndex := availableInsertionsIndex + 1;
7565               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7566               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7567               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7568               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7569               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7570               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7571               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7572               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7573               availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7574             end if;
7575           end if;
7576         else
7577           if (engStApprovers(positionIn).authority <> ame_util.preApprover) then
7578             tempParameter := ame_util.lastPreApprover ||
7579                              ame_util.fieldDelimiter ||
7580                              engStApprovers(positionIn).item_class ||
7581                              ame_util.fieldDelimiter ||
7582                              engStApprovers(positionIn).item_id;
7583             if (not ame_engine.insertionExists
7584                       (orderTypeIn   => ame_util.lastPreApprover
7585                       ,parameterIn   => tempParameter
7586                       )) then
7587               availableInsertionsIndex := availableInsertionsIndex + 1;
7588               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7589               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7590               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7591               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7592               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7593               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7594               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7595               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7596               availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7597             end if;
7598           end if;
7599         end if;
7600       end if;
7601     end if;
7602 
7603   exception
7604     when invalidPositionException then
7605       errorCode := -20211;
7606       errorMessage := ame_util.getMessage
7607         (applicationShortNameIn   =>'PER'
7608         ,messageNameIn            => 'AME_400418_INVALID_INSERTION'
7609         );
7610       ame_util.runtimeException
7611         (packageNameIn     => 'ame_engine'
7612         ,routineNameIn     => 'getInsertions'
7613         ,exceptionNumberIn => errorCode
7614         ,exceptionStringIn => errorMessage
7615         );
7616       raise_application_error(errorCode,errorMessage);
7617 
7618     when others then
7619       ame_util.runtimeException
7620         (packageNameIn     => 'ame_engine'
7621         ,routineNameIn     => 'getInsertions'
7622         ,exceptionNumberIn => sqlcode
7623         ,exceptionStringIn => sqlerrm
7624         );
7625       raise;
7626   end getInsertions;
7627   procedure getLMCondition(ruleIdIn in integer,
7628                            parameterOneOut out nocopy varchar2,
7629                            parameterTwoOut out nocopy varchar2) as
7630     errorCode integer;
7631     errorMessage ame_util.longestStringType;
7632     invalidNameException exception;
7633     tempRuleKey ame_rules.rule_key%type;
7634     parameterOne ame_conditions.parameter_one%type;
7635     parameterTwo ame_conditions.parameter_two%type;
7636     begin
7637       /* Checked for cached values. */
7638       if(not engLMParameterOnes.exists(ruleIdIn)) then
7639         /* Select the values, as they were not cached. */
7640         select
7641           ame_conditions.parameter_one,
7642           ame_conditions.parameter_two
7643           into
7644             parameterOne,
7645             parameterTwo
7646           from
7647             ame_conditions,
7648             ame_condition_usages
7649           where
7650             ame_condition_usages.rule_id = ruleIdIn and
7651             ame_condition_usages.condition_id = ame_conditions.condition_id and
7652             ame_conditions.condition_type = ame_util.listModConditionType and
7653             engEffectiveRuleDate between
7654               ame_conditions.start_date and
7655               nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
7656             engEffectiveRuleDate between
7657               ame_condition_usages.start_date and
7658               nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
7659             rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
7660         /* Check for an invalid wf_roles.name value in parameter_two. */
7661         if(parameterTwo = ame_util.invalidApproverWfRolesName) then
7662           raise invalidNameException;
7663         end if;
7664         /* Cache the values. */
7665         engLMParameterOnes(ruleIdIn) := parameterOne;
7666         engLMParameterTwos(ruleIdIn) := parameterTwo;
7667       end if;
7668       /* Return the values. */
7669       parameterOneOut := engLMParameterOnes(ruleIdIn);
7670       parameterTwoOut := engLMParameterTwos(ruleIdIn);
7671       exception
7672         when invalidNameException then
7673           tempRuleKey := ame_rule_pkg.getRuleKey(ruleIdIn => ruleIdIn);
7674           errorCode := -20001;
7675           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
7676                                               messageNameIn => 'AME_400685_INV_LM_RULE',
7677                                               tokenNameOneIn  => 'RULE_KEY',
7678                                               tokenValueOneIn => tempRuleKey);
7679           ame_util.runtimeException(packageNameIn => 'ame_engine',
7680                                     routineNameIn => 'getLMCondition',
7681                                     exceptionNumberIn => errorCode,
7682                                     exceptionStringIn => errorMessage);
7683           raise_application_error(errorCode,
7684                                   errorMessage);
7685         when others then
7686           ame_util.runtimeException(packageNameIn => 'ame_engine',
7687                                     routineNameIn => 'getLMCondition',
7688                                     exceptionNumberIn => sqlcode,
7689                                     exceptionStringIn => sqlerrm);
7690           raise;
7691     end getLMCondition;
7692   procedure getNextApprovers(
7693             applicationIdIn   in number
7694            ,transactionTypeIn in varchar2
7695            ,transactionIdIn   in varchar2
7696            ,nextApproversType in number
7697            ,flagApproversAsNotifiedIn in varchar2 default ame_util.booleanTrue
7698            ,approvalProcessCompleteYNOut out nocopy varchar2
7699            ,nextApproversOut             out nocopy ame_util.approversTable2
7700            ,itemIndexesOut               out nocopy ame_util.idList
7701            ,itemClassesOut               out nocopy ame_util.stringList
7702            ,itemIdsOut                   out nocopy ame_util.stringList
7703            ,itemSourcesOut               out nocopy ame_util.longStringList
7704            ,productionIndexesOut         out nocopy ame_util.idList
7705            ,variableNamesOut             out nocopy ame_util.stringList
7706            ,variableValuesOut            out nocopy ame_util.stringList
7707            ,transVariableNamesOut        out nocopy ame_util.stringList
7708            ,transVariableValuesOut       out nocopy ame_util.stringList) as
7709       allItemsNotSuspended boolean;
7710       ameApplicationId integer;
7711       copyAncillaryData  boolean;
7712       nextApproverCount integer;
7713       nextTreeNodeIndex integer;
7714       tempTreeNodeIndex integer;
7715       approverItemCount integer;
7716       approverProdCount integer;
7717       currentTreeNode ame_util.approverTreeRecord;
7718       evaluateNextNode boolean;
7719       currentOrderNumber integer;
7720       nextApproverTreeIndexList ame_util.idList;
7721       currentApproverIndex integer;
7722       tempApproverIndexes ame_util.idList;
7723 --      tempItemClass ame_util.stringType;
7724 --      tempItemId    ame_util.stringType;
7725       processSibling boolean;
7726       tempTreeNode ame_util.approverTreeRecord;
7727       -- following two variables added - to use incase of item_class is null
7728       tempItemClass ame_util.stringType;
7729       tempItemId    ame_util.stringType;
7730       -- repeated
7731       tempRepeatedCount integer;
7732       tempRepeatedCount2 integer;
7733       tempPrepareItemData boolean := true;
7734       tempProcessProductionActions boolean := false;
7735       tempProcessProductionRules   boolean := false;
7736       tempTreeLevelId integer;
7737       --+
7738       previousNodeOrderNumber integer;
7739       previousTreeLevelId     varchar2(320);
7740       previousNodeStatus      integer;
7741       --+
7742       prevApproverOrderNumber integer;
7743       prevApproverName        varchar2(320);
7744       prevApproverStatus      integer;
7745       --+
7746     begin
7747       if nextApproversType = 4 then
7748         tempPrepareItemData := false;
7749       end if;
7750       if nextApproversType = 2 or nextApproversType = 3 then
7751         tempProcessProductionActions := true;
7752       end if;
7753       if nextApproversType = 3 then
7754         tempProcessProductionRules := true;
7755       end if;
7756       ame_engine.lockTransaction(fndApplicationIdIn => applicationIdIn,
7757                                  transactionIdIn => transactionIdIn,
7758                                  transactionTypeIdIn => transactionTypeIn);
7759       ame_engine.updateTransactionState(isTestTransactionIn  => false
7760                                        ,isLocalTransactionIn => false
7761                                        ,fetchConfigVarsIn    => true
7762                                        ,fetchOldApproversIn  => true
7763                                        ,fetchInsertionsIn    => true
7764                                        ,fetchDeletionsIn     => true
7765                                        ,fetchAttributeValuesIn      => true
7766                                        ,fetchInactiveAttValuesIn    => false
7767                                        ,processProductionActionsIn  => tempProcessProductionActions
7768                                        ,processProductionRulesIn    => tempProcessProductionRules
7769                                        ,updateCurrentApproverListIn => true
7770                                        ,updateOldApproverListIn     => true
7771                                        ,processPrioritiesIn   => true
7772                                        ,prepareItemDataIn     => tempPrepareItemData
7773                                        ,prepareRuleIdsIn      => false
7774                                        ,prepareRuleDescsIn    => false
7775                                        ,prepareApproverTreeIn => true
7776                                        ,transactionIdIn       => transactionIdIn
7777                                        ,ameApplicationIdIn    => null
7778                                        ,fndApplicationIdIn    => applicationIdIn
7779                                        ,transactionTypeIdIn   => transactionTypeIn);
7780       approvalProcessCompleteYNOut := ame_engine.getApprovalProcessCompleteYN;
7781       ameApplicationId := ame_engine.getAmeApplicationId;
7782       /* If approvalProcessCompleteYNOut is 'Y', there should be no nextApprovers. Hence
7783          return with an empty nextApproversOut table */
7784       if approvalProcessCompleteYNOut = ame_util2.completeFullyApproved or
7785          approvalProcessCompleteYNOut = ame_util2.completeFullyRejected or
7786          approvalProcessCompleteYNOut = ame_util2.completePartiallyApproved or
7787          approvalProcessCompleteYNOut = ame_util2.completeNoApprovers then
7788          ame_engine.unlockTransaction(fndApplicationIdIn  => applicationIdIn,
7789                                      transactionIdIn     => transactionIdIn,
7790                                      transactionTypeIdIn => transactionTypeIn);
7791         return;
7792       end if;
7793       copyAncillaryData := false;
7794       nextApproverCount := 0; /* Pre increment */
7795       approverItemCount := 0;
7796       approverProdCount := 0;
7797       nextTreeNodeIndex := 1;
7798       evaluateNextNode := true;
7799       currentOrderNumber := null;
7800       processSibling := true;
7801       loop
7802         currentTreeNode := engStApproversTree(nextTreeNodeIndex);
7803         if currentTreeNode.is_suspended is null or
7804            currentTreeNode.is_suspended = ame_util.booleanFalse then
7805           if currentTreeNode.tree_level = 6 and
7806              (currentTreeNode.status = ame_util.startedStatus
7807                and engStApprovers(currentTreeNode.approver_index).approval_status
7808                     <> ame_util.notifiedByRepeatedStatus)and
7809              (currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7810                and currentTreeNode.min_order <> engStApproversTree(currentTreeNode.sibling_index).min_order ) then
7811             evaluateNextNode := false;
7812           end if;
7813           if evaluateNextNode then
7814             if currentTreeNode.status <> ame_util.completedStatus then
7815               if currentTreeNode.approver_index = ame_util.noApproverIndex and
7816                  evaluateNextNode then
7817                 currentOrderNumber := currentTreeNode.min_order;
7818               end if;
7819             else
7820               currentOrderNumber := null;
7821             end if;
7822             if currentTreeNode.approver_index <> ame_util.noApproverIndex
7823                 and currentOrderNumber is not null
7824                 and currentTreeNode.status = ame_util.notStartedStatus
7825                 and currentTreeNode.min_order = currentOrderNumber
7826                 and (engStApprovers(currentTreeNode.approver_index).approval_status is null
7827                        or engStApprovers(currentTreeNode.approver_index).approval_status
7828                             <> ame_util.notifiedByRepeatedStatus)
7829                   then
7830               nextApproverCount := nextApproverCount + 1;
7831               ame_util.copyApproverRecord2
7832                 (approverRecord2In => engStApprovers(currentTreeNode.approver_index)
7833                 ,approverRecord2Out => nextApproversOut(nextApproverCount));
7834               if flagApproversAsNotifiedIn  = ame_util.booleanTrue then
7835                 setInsertedApprovalStatus(currentApproverIndexIn => currentTreeNode.approver_index
7836                                            ,approvalStatusIn => ame_util.notifiedStatus );
7837               end if;
7838                 currentApproverIndex := currentTreeNode.approver_index;
7839               copyAncillaryData := true;
7840               nextApproverTreeIndexList(nextApproverCount) := nextTreeNodeIndex;
7841               tempApproverIndexes(nextApproverCount) := currentTreeNode.approver_index;
7842               if currentTreeNode.sibling_index <> -1
7843                 and currentTreeNode.max_order <> engStApproversTree(currentTreeNode.sibling_index).max_order then
7844                 processSibling := false;
7845               else
7846                 processSibling := true;
7847               end if;
7848               for x in 1 .. engStRepeatedIndexes.count loop
7849                 if engStRepeatedIndexes(x) = currentTreeNode.approver_index
7850                    and engStRepeatedAppIndexes(x) <> currentTreeNode.approver_index then
7851                       --+
7852                   update ame_temp_old_approver_lists
7853                      set approval_status = ame_util.notifiedByRepeatedStatus
7854                    where application_id = ameApplicationId
7855                      and transaction_id = transactionIdIn
7856                      and name           = engStApprovers(engStRepeatedAppIndexes(x)).name --nextApproversOut(i).name
7857                      and item_class        = engStApprovers(engStRepeatedAppIndexes(x)).item_class
7858                      and item_id           = engStApprovers(engStRepeatedAppIndexes(x)).item_id
7859                      and action_type_id    = engStApprovers(engStRepeatedAppIndexes(x)).action_type_id
7860                      and group_or_chain_id = engStApprovers(engStRepeatedAppIndexes(x)).group_or_chain_id
7861                      and occurrence        = engStApprovers(engStRepeatedAppIndexes(x)).occurrence
7862                      and (approval_status is null or approval_status = ame_util.repeatedStatus);
7863                      engStApprovers(engStRepeatedAppIndexes(x)).approval_status := ame_util.notifiedByRepeatedStatus;
7864                      setInsertedApprovalStatus(currentApproverIndexIn => engStRepeatedAppIndexes(x)
7865                                     ,approvalStatusIn => ame_util.notifiedByRepeatedStatus);
7866                       --+
7867                 end if;
7868               end loop;
7869             end if;
7870             if currentOrderNumber is null and currentTreeNode.tree_level = 6 then
7871               if currentTreeNode.approver_index <> ame_util.noApproverIndex and
7872                  (currentTreeNode.status = ame_util.completedStatus or
7873                   (
7874                     currentTreeNode.status = ame_util.startedStatus
7875                     and engStApprovers(currentTreeNode.approver_index).approval_status <> ame_util.notifiedByRepeatedStatus
7876                     and processSibling
7877                   )or
7878                   (
7879                   currentTreeNode.status = ame_util.notStartedStatus and
7880                   currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7881                   and currentTreeNode.min_order = engStApproversTree(currentTreeNode.sibling_index).min_order
7882                   )
7883                  )and
7884                  processSibling and --evaluateNextNode and
7885                  (currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7886                   and engStApproversTree(currentTreeNode.sibling_index).status = ame_util.notStartedStatus
7887                 and ( engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index).approval_status is null
7888                   or engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index).approval_status
7889                       <> ame_util.notifiedByRepeatedStatus)
7890                   ) then
7891                 --+
7892                 if prevApproverOrderNumber is null or
7893                  (prevApproverOrderNumber < engStApproversTree(currentTreeNode.sibling_index).min_order
7894                  and prevApproverStatus = ame_util.completedStatus) or
7895                  (prevApproverOrderNumber = engStApproversTree(currentTreeNode.sibling_index).min_order )
7896                  then
7897 
7898                 nextApproverCount := nextApproverCount + 1;
7899                 ame_util.copyApproverRecord2
7900                   (approverRecord2In => engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index)
7901                   ,approverRecord2Out => nextApproversOut(nextApproverCount));
7902                 if flagApproversAsNotifiedIn  = ame_util.booleanTrue then
7903                   setInsertedApprovalStatus(currentApproverIndexIn => engStApproversTree(currentTreeNode.sibling_index).approver_index
7904                                            ,approvalStatusIn =>ame_util.notifiedStatus );
7905                 end if;
7906                 nextApproverTreeIndexList(nextApproverCount) := currentTreeNode.sibling_index;
7907                 tempApproverIndexes(nextApproverCount) := engStApproversTree(currentTreeNode.sibling_index).approver_index;
7908                 currentApproverIndex := engStApproversTree(currentTreeNode.sibling_index).approver_index;
7909                 copyAncillaryData := true;
7910                 tempTreeNode := engStApproversTree(currentTreeNode.sibling_index);
7911                 if tempTreeNode.sibling_index <> -1
7912                     and tempTreeNode.max_order <> engStApproversTree(tempTreeNode.sibling_index).max_order then
7913                   processSibling := false;
7914                 else
7915                   processSibling := true;
7916                 end if;
7917                 for x in 1 .. engStRepeatedIndexes.count loop
7918                   if engStRepeatedIndexes(x) = engStApproversTree(currentTreeNode.sibling_index).approver_index
7919                      and engStRepeatedAppIndexes(x) <> engStApproversTree(currentTreeNode.sibling_index).approver_index then
7920                         --+
7921                     update ame_temp_old_approver_lists
7922                        set approval_status = ame_util.notifiedByRepeatedStatus
7923                      where application_id = ameApplicationId
7924                        and transaction_id = transactionIdIn
7925                        and name           = engStApprovers(engStRepeatedAppIndexes(x)).name --nextApproversOut(i).name
7926                        and item_class        = engStApprovers(engStRepeatedAppIndexes(x)).item_class
7927                        and item_id           = engStApprovers(engStRepeatedAppIndexes(x)).item_id
7928                        and action_type_id    = engStApprovers(engStRepeatedAppIndexes(x)).action_type_id
7929                        and group_or_chain_id = engStApprovers(engStRepeatedAppIndexes(x)).group_or_chain_id
7930                        and occurrence        = engStApprovers(engStRepeatedAppIndexes(x)).occurrence
7931                        and (approval_status is null or approval_status = ame_util.repeatedStatus);
7932                        engStApprovers(engStRepeatedAppIndexes(x)).approval_status := ame_util.notifiedByRepeatedStatus;
7933                        setInsertedApprovalStatus(currentApproverIndexIn => engStRepeatedAppIndexes(x)
7934                                                 ,approvalStatusIn => ame_util.notifiedByRepeatedStatus);
7935 
7936                         --+
7937                   end if;
7938                 end loop;
7939               end if;
7940               end if;
7941             end if;
7942           end if;
7943           --+
7944           --prevApproverOrderNumber := currentTreeNode.min_order;
7945           --prevApproverName        := currentTreeNode.tree_level_id;
7946           --prevApproverStatus      := currentTreeNode.status;
7947           --+
7948           if currentTreeNode.tree_level = 6 and (prevApproverOrderNumber is null or
7949              prevApproverOrderNumber = currentTreeNode.min_order)
7950             then
7951             if currentTreeNode.status <> ame_util.completedStatus then
7952               prevApproverStatus := currentTreeNode.status;
7953               prevApproverOrderNumber := currentTreeNode.min_order;
7954               prevApproverName := currentTreeNode.tree_level_id;
7955             end if;
7956           end if;
7957           --+
7958           if currentTreeNode.child_index <> ame_util.noChildIndex and evaluateNextNode then
7959             nextTreeNodeIndex := currentTreeNode.child_index;
7960           else
7961             if evaluateNextNode then
7962               nextTreeNodeIndex := currentTreeNode.sibling_index;
7963               if nextTreeNodeIndex <> ame_util.invalidTreeIndex
7964                  and (currentTreeNode.min_order = engStApproversTree(nextTreeNodeIndex).min_order
7965                  or currentTreeNode.status = ame_util.completedStatus) then
7966                  evaluateNextNode := true;
7967               else
7968                  evaluateNextNode := false;
7969               end if;
7970             else
7971               nextTreeNodeIndex := ame_util.noSiblingIndex;
7972             end if;
7973           end if;
7974         else
7975           nextTreeNodeIndex := currentTreeNode.sibling_index;
7976           prevApproverOrderNumber := null;
7977         end if;
7978         if nextTreeNodeIndex = ame_util.invalidTreeIndex then
7979           /* There are no more siblings or child nodes for the current node */
7980           /* So try moving to the parent's sibling node                     */
7981           /* If the parent's sibling is not found then move to its parent   */
7982           /* and so on ...                                                  */
7983           prevApproverOrderNumber := null;
7984           previousNodeOrderNumber := null;
7985           if currentTreeNode.tree_level = 0 then
7986             tempTreeNodeIndex := ame_util.invalidTreeIndex;
7987           else
7988             tempTreeNodeIndex := currentTreeNode.parent_index;
7989           end if;
7990           if tempTreeNodeIndex <> ame_util.invalidTreeIndex then
7991             processSibling := true;
7992             evaluateNextNode := false;
7993             loop
7994               if engStApproversTree(tempTreeNodeIndex).sibling_index
7995                                                           = ame_util.noSiblingIndex then
7996                 tempTreeNodeIndex := engStApproversTree(tempTreeNodeIndex).parent_index;
7997               else
7998                 nextTreeNodeIndex := engStApproversTree(tempTreeNodeIndex).sibling_index;
7999                 evaluateNextNode := false;
8000                 if (engStApproversTree(tempTreeNodeIndex).min_order
8001                      = engStApproversTree(nextTreeNodeIndex).min_order
8002                    ) or
8003                    (engStApproversTree(tempTreeNodeIndex).status
8004                      = ame_util.completedStatus )
8005                      and
8006                   (previousNodeOrderNumber is null or engStApproversTree(tempTreeNodeIndex).min_order = previousNodeOrderNumber
8007                     and previousNodeStatus = ame_util.completedStatus
8008                   ) then
8009                   evaluateNextNode := true;
8010                 else
8011                   evaluateNextNode := false;
8012                 end if;
8013                 --+
8014                 --previousNodeOrderNumber := engStApproversTree(tempTreeNodeIndex).min_order;
8015                 previousTreeLevelId     := engStApproversTree(tempTreeNodeIndex).tree_level_id;
8016                 --previousNodeStatus      := engStApproversTree(tempTreeNodeIndex).status;
8017                 if previousNodeOrderNumber is null or previousNodeOrderNumber = engStApproversTree(tempTreeNodeIndex).min_order
8018                   then
8019                   if engStApproversTree(tempTreeNodeIndex).status <> ame_util.completedStatus then
8020                     previousNodeStatus := engStApproversTree(tempTreeNodeIndex).status;
8021                     previousNodeOrderNumber := engStApproversTree(tempTreeNodeIndex).min_order;
8022                   end if;
8023                 end if;
8024                 --+
8025                 exit;
8026               end if;
8027               if tempTreeNodeIndex = 1 or tempTreeNodeIndex = ame_util.invalidTreeIndex then
8028                 nextTreeNodeIndex := ame_util.invalidTreeIndex;
8029                 exit;
8030               end if;
8031             end loop;
8032           end if;
8033         end if;
8034         /* When ever we reach this point we come with a valid node which needs     */
8035         /* be processed by the next pass of the loop. If no valid node is present  */
8036         /* this indicates that the entire tree is traversed and there are no more  */
8037         /* approvers to find                                                       */
8038         exit when nextTreeNodeIndex = ame_util.invalidTreeIndex;
8039       end loop;
8040       if copyAncillaryData and nextApproversType < 4 then
8041         ame_engine.prepareItemData(approverIndexesIn  => tempApproverIndexes
8042                                   ,itemIndexesOut     => itemIndexesOut
8043                                   ,itemItemClassesOut => itemClassesOut
8044                                   ,itemIdsOut         => itemIdsOut
8045                                   ,itemSourcesOut     => itemSourcesOut);
8046         if nextApproversType = 2 or nextApproversType = 3 then
8047           preparePerApproverProductions
8048                   (approverIndexesIn   => tempApproverIndexes
8049                   ,itemIndexesIn       => itemIndexesOut
8050                   ,itemSourcesIn       => itemSourcesOut
8051                   ,prodIndexesOut      => productionIndexesOut
8052                   ,productionNamesOut  => variableNamesOut
8053                   ,productionValuesOut => variableValuesOut);
8054         end if;
8055       end if;
8056       if nextApproversType = 3 then
8057         getTransVariableNames(transVariableNamesOut => transVariableNamesOut);
8058         getTransVariableValues(transVariableValuesOut => transVariableValuesOut);
8059       end if;
8060       if flagApproversAsNotifiedIn  = ame_util.booleanTrue then
8061         ameApplicationId := ame_engine.getAmeApplicationId;
8062         for i in 1 .. nextApproversOut.count loop
8063             update ame_temp_old_approver_lists
8064                set approval_status = ame_util.notifiedStatus
8065              where item_class = nextApproversOut(i).item_class
8066                and item_id = nextApproversOut(i).item_id
8067                and name = nextApproversOut(i).name
8068                and action_type_id = nextApproversOut(i).action_type_id
8069                and group_or_chain_id = nextApproversOut(i).group_or_chain_id
8070                and occurrence = nextApproversOut(i).occurrence
8071                and transaction_id = transactionIdIn
8072                and application_id = ameApplicationId;
8073            /* Insert into Approval Notification History Table */
8074           insertIntoTransApprovalHistory
8075             (transactionIdIn         => transactionIdIn
8076             ,applicationIdIn         => ameApplicationId
8077             ,orderNumberIn           => nextApproversOut(i).approver_order_number
8078             ,nameIn                  => nextApproversOut(i).name
8079             ,appCategoryIn           => nextApproversOut(i).approver_category
8080             ,itemClassIn             => nextApproversOut(i).item_class
8081             ,itemIdIn                => nextApproversOut(i).item_id
8082             ,actionTypeIdIn          => nextApproversOut(i).action_type_id
8083             ,authorityIn             => nextApproversOut(i).authority
8084             ,statusIn                => ame_util.notifiedStatus
8085             ,grpOrChainIdIn          => nextApproversOut(i).group_or_chain_id
8086             ,occurrenceIn            => nextApproversOut(i).occurrence
8087             ,apiInsertionIn          => nextApproversOut(i).api_insertion
8088             ,memberOrderNumberIn     => nextApproversOut(i).member_order_number
8089             ,notificationIdIn        => null
8090             ,userCommentsIn          => null
8091             ,dateClearedIn           => null
8092             ,historyTypeIn           => 'APPROVERPRESENT');
8093         end loop;
8094       end if;
8095       if tempPrepareItemData then
8096         for x in 1 .. nextApproversOut.count loop
8097           if engStApprovers(tempApproverIndexes(x)).item_class is null then
8098             nextApproversOut(x).item_class := null;
8099             nextApproversOut(x).item_id    := null;
8100             nextApproversOut(x).source     := null;
8101           end if;
8102         end loop;
8103       end if;
8104       for x in 1 .. nextApproversOut.count loop
8105         if nextApproversOut(x).approval_status = ame_util.repeatedStatus then
8106           nextApproversOut(x).approval_status := null;
8107         end if;
8108       end loop;
8109       ame_engine.unlockTransaction(fndApplicationIdIn  => applicationIdIn,
8110                                    transactionIdIn     => transactionIdIn,
8111                                    transactionTypeIdIn => transactionTypeIn);
8112     exception
8113       when others then
8114         ame_engine.unlockTransaction(fndApplicationIdIn  => applicationIdIn,
8115                                      transactionIdIn     => transactionIdIn,
8116                                      transactionTypeIdIn => transactionTypeIn);
8117         ame_util.runtimeException(packageNameIn => 'ame_engine',
8118                                   routineNameIn => 'getNextApprovers',
8119                                   exceptionNumberIn => sqlcode,
8120                                   exceptionStringIn => sqlerrm);
8121         approvalProcessCompleteYNOut:= null;
8122         nextApproversOut.delete;
8123         raise;
8124   end getNextApprovers;
8125   procedure prepareItemData(approverIndexesIn  in ame_util.idList default ame_util.emptyIdList
8126                            ,itemIndexesOut     out nocopy ame_util.idList
8127                            ,itemItemClassesOut out nocopy ame_util.stringList
8128                            ,itemIdsOut         out nocopy ame_util.stringList
8129                            ,itemSourcesOut     out nocopy ame_util.longStringList) as
8130     tempItemCount integer;
8131     tempItemClass ame_util.stringType;
8132     tempItemId    ame_util.stringType;
8133     tempRuleIdList ame_util.idList;
8134     prevIndex       integer;
8135     currentIndex    integer;
8136     currentApproverIndex integer;
8137     tempIndex       integer;
8138     tempSourceDescription ame_util.longStringType;
8139     tempLength      integer;
8140     tempFlag        boolean;
8141     tempCount       integer;
8142     tempFlag2       boolean;
8143     tempProcessApprover  boolean;
8144     tempProcessApprover2 boolean;
8145     begin
8146       tempItemCount := 0;
8147       prevIndex := null;
8148       tempCount := approverIndexesIn.count;
8149       tempFlag2 := false;
8150       if tempCount = 0 then
8151         tempFlag2  := true;
8152         tempCount := engStApprovers.count;
8153       end if;
8154       /* here tempFlag2 = false indicates the procedure invoked from getNextApprovers*/
8155       for i in 1 .. tempCount loop
8156         if tempFlag2 then
8157           currentApproverIndex := i;
8158         else
8159           currentApproverIndex := approverIndexesIn(i);
8160         end if;
8161         tempProcessApprover := false;
8162         tempProcessApprover2 := false;
8163         if not tempFlag2 then
8164           tempProcessApprover := true;
8165         else
8166           if ( engStApprovers(currentApproverIndex).approval_status is null
8167                 or engStApprovers(currentApproverIndex).approval_status
8168                           not in (ame_util.notifiedByRepeatedStatus
8169                                  ,ame_util.approvedByRepeatedStatus
8170                                  ,ame_util.rejectedByRepeatedStatus
8171                                  ,ame_util.suppressedStatus
8172                                  ,ame_util.repeatedStatus) ) then
8173           tempProcessApprover := true;
8174           end if;
8175         end if;
8176         if tempProcessApprover then
8177           for j in 1 .. engStRepeatedIndexes.count loop
8178             if engStRepeatedIndexes(j) = currentApproverIndex
8179                 and engStRepeatedAppIndexes(j) = currentApproverIndex then
8180               tempItemClass := engStApprovers(currentApproverIndex).item_class;
8181               tempItemId    := engStApprovers(currentApproverIndex).item_id;
8182             end if;
8183           end loop;
8184           for j in 1 .. engStRepeatedIndexes.count loop
8185             if engStRepeatedIndexes(j) = currentApproverIndex
8186                 and engStRepeatedAppIndexes(j) <> currentApproverIndex then
8187               if tempItemClass <> engStApprovers(engStRepeatedAppIndexes(j)).item_class
8188                   or tempItemId <> engStApprovers(engStRepeatedAppIndexes(j)).item_id then
8189                 tempProcessApprover2 := true;
8190               end if;
8191             end if;
8192           end loop;
8193         end if;
8194         if tempProcessApprover2 then
8195           prevIndex := null;
8196           for j in 1 .. engStRepeatedIndexes.count loop
8197             if engStRepeatedIndexes(j) = currentApproverIndex then
8198               currentIndex := engStRepeatedAppIndexes(j);
8199             if (currentApproverIndex = currentIndex)
8200                 or
8201                (engStApprovers(currentIndex).item_id <> tempItemId
8202                  or engStApprovers(currentIndex).item_class <> tempItemClass) then
8203               tempItemCount := tempItemCount + 1;
8204               itemIndexesOut(tempItemCount) := i;
8205               tempFlag := true;
8206               itemItemClassesOut(tempItemCount) := engStApprovers(currentIndex).item_class;
8207               itemIdsOut(tempItemCount) := engStApprovers(currentIndex).item_id;
8208               prevIndex := tempItemCount;
8209             end if;
8210             tempSourceDescription := null;
8211             tempRuleIdList.delete;
8212             ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source
8213                                      ,sourceDescriptionOut => tempSourceDescription
8214                                      ,ruleIdListOut => tempRuleIdList);
8215             for z in 1 .. tempRuleIdList.count loop
8216               if itemSourcesOut.count >= tempItemCount then
8217                 tempIndex := instrb(itemSourcesOut(tempItemCount),tempRuleIdList(z));
8218               else
8219                 itemSourcesOut(tempItemCount) := null;
8220                 tempIndex := -1;
8221               end if;
8222               if tempIndex = -1 then
8223                 ame_util.appendRuleIdToSource(ruleIdIn => tempRuleIdList(z)
8224                                              ,sourceInOut => itemSourcesOut(tempItemCount));
8225               end if;
8226             end loop;
8227             end if;
8228           end loop;
8229         end if;
8230         if tempFlag and (not engIsLocalTransaction)then
8231           tempFlag := false;
8232           engStApprovers(currentApproverIndex).item_class := null;
8233           engStApprovers(currentApproverIndex).item_id    := null;
8234           engStApprovers(currentApproverIndex).source     := null;
8235         end if;
8236       end loop;
8237     exception
8238       when others then
8239         ame_util.runtimeException(packageNameIn => 'ame_engine',
8240                                   routineNameIn => 'prepareItemData',
8241                                   exceptionNumberIn => sqlcode,
8242                                   exceptionStringIn => sqlerrm);
8243         itemIndexesOut.delete;
8244         itemItemClassesOut.delete;
8245         itemIdsOut.delete;
8246         itemSourcesOut.delete;
8247         raise;
8248   end prepareItemData;
8249   procedure preparePerApproverProductions
8250            (approverIndexesIn    in ame_util.idList default ame_util.emptyIdList
8251            ,itemIndexesIn        in ame_util.idList default ame_util.emptyIdList
8252            ,itemSourcesIn        in ame_util.longStringList default ame_util.emptyLongStringList
8253            ,prodIndexesOut      out nocopy ame_util.idList
8254            ,productionNamesOut  out nocopy ame_util.stringList
8255            ,productionValuesOut out nocopy ame_util.stringList) as
8256     tempRuleIdList ame_util.idList;
8257     tempSourceDescription ame_util.stringType;
8258     hasRepeatedOccurrences boolean;
8259     currentRepeatedFirstIndex integer;
8260     currentIndex integer;
8261     tempCount integer;
8262     tempPerAppProdIndex integer;
8263     tempProdIndex  integer;
8264     tempFlag2 boolean;
8265     tempCount2 integer;
8266     currentApproverIndex integer;
8267     begin
8268       if not engProcessProductionActions then
8269         return;
8270       end if;
8271       tempProdIndex  := 0;
8272       tempPerAppProdIndex := 0;
8273       tempCount := 1;
8274       tempCount2 := approverIndexesIn.count;
8275       tempFlag2 := false;
8276       if tempCount2 = 0 then
8277         tempFlag2  := true;
8278         tempCount2 := engStApprovers.count;
8279       end if;
8280       /* here tempFlag2 = false indicates the procedure invoked from getNextApprovers */
8281       for i in 1 .. tempCount2 loop
8282         hasRepeatedOccurrences := false;
8283         currentRepeatedFirstIndex := -1;
8284         tempRuleIdList.delete;
8285         tempSourceDescription := null;
8286         tempCount := 1;
8287         if tempFlag2 then
8288           currentApproverIndex := i;
8289         else
8290           currentApproverIndex := approverIndexesIn(i);
8291         end if;
8292         if tempFlag2 then
8293           if engStApprovers(currentApproverIndex).item_class is null then
8294             tempCount := 0;
8295             for x in 1 .. engStItemIndexes.count loop
8296               if engStItemIndexes(x) = currentApproverIndex then
8297                 tempCount := tempCount + 1;
8298                 if currentRepeatedFirstIndex = -1 then
8299                   currentRepeatedFirstIndex := x;
8300                 end if;
8301               end if;
8302             end loop;
8303             hasRepeatedOccurrences := true;
8304           end if;
8305         else
8306           tempCount := 0;
8307           for x in 1 .. itemIndexesIn.count loop
8308             if itemIndexesIn(x) = i then
8309                 tempCount := tempCount + 1;
8310                 if currentRepeatedFirstIndex = -1 then
8311                   currentRepeatedFirstIndex := x;
8312                 end if;
8313             end if;
8314           end loop;
8315           if currentRepeatedFirstIndex <> -1 then
8316             hasRepeatedOccurrences := true;
8317           else
8318             hasRepeatedOccurrences := false;
8319             tempCount := 1;
8320           end if;
8321         end if;
8322         currentIndex := 0;
8323         for j in 1 .. tempCount loop
8324           if hasRepeatedOccurrences then
8325             currentIndex := (currentRepeatedFirstIndex+j)-1;
8326           else
8327             currentIndex := currentApproverIndex;
8328           end if;
8329           tempSourceDescription := null;
8330           tempRuleIdList.delete;
8331           if hasRepeatedOccurrences then
8332             if tempFlag2 then
8333               ame_util.parseSourceValue(sourceValueIn => engStItemSources(currentIndex),
8334                                         sourceDescriptionOut => tempSourceDescription,
8335                                         ruleIdListOut => tempRuleIdList);
8336             else
8337               ame_util.parseSourceValue(sourceValueIn => itemSourcesIn(currentIndex),
8338                                         sourceDescriptionOut => tempSourceDescription,
8339                                         ruleIdListOut => tempRuleIdList);
8340             end if;
8341           else
8342             ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source,
8343                                       sourceDescriptionOut => tempSourceDescription,
8344                                       ruleIdListOut => tempRuleIdList);
8345           end if;
8346             for k in 1 .. tempRuleIdList.count loop
8347               if(engAppPerAppProdFirstIndexes.exists(tempRuleIdList(k))) then
8348                 tempPerAppProdIndex := engAppPerAppProdFirstIndexes(tempRuleIdList(k));
8349                 loop
8350                   tempProdIndex := tempProdIndex + 1;
8351                   prodIndexesOut(tempProdIndex) := i;
8352                   productionNamesOut(tempProdIndex) := engAppPerAppProdVariableNames(tempPerAppProdIndex);
8353                   productionValuesOut(tempProdIndex) := engAppPerAppProdVariableValues(tempPerAppProdIndex);
8354                   tempPerAppProdIndex := tempPerAppProdIndex + 1;
8355                   if(not engAppPerAppProdRuleIds.exists(tempPerAppProdIndex) or
8356                    engAppPerAppProdRuleIds(tempPerAppProdIndex) <> tempRuleIdList(k)) then
8357                     exit;
8358                   end if;
8359                 end loop;
8360               end if;
8361             end loop;
8362         end loop;
8363       end loop;
8364     exception
8365       when others then
8366         ame_util.runtimeException(packageNameIn => 'ame_engine',
8367                                   routineNameIn => 'preparePerApproverProductions',
8368                                   exceptionNumberIn => sqlcode,
8369                                   exceptionStringIn => sqlerrm);
8370         prodIndexesOut.delete;
8371         productionNamesOut.delete;
8372         productionValuesOut.delete;
8373         raise;
8374   end preparePerApproverProductions;
8375   procedure prepareRuleData as
8376     tempRuleIdList ame_util.idList;
8377     tempEngStRuleIndex integer;
8378     tempSourceDescription ame_util.stringType;
8379     hasRepeatedOccurrences boolean;
8380     currentRepeatedFirstIndex integer;
8381     currentIndex integer;
8382     tempCount integer;
8383     tempEngStProdIndex  integer;
8384     begin
8385       if not (engPrepareRuleIds
8386                or engPrepareRuleDescs ) then
8387         return;
8388       end if;
8389       tempEngStRuleIndex  := 0;
8390       tempCount := 1;
8391       for i in 1 .. engStApprovers.count loop
8392         hasRepeatedOccurrences := false;
8393         currentRepeatedFirstIndex := -1;
8394         tempRuleIdList.delete;
8395         tempSourceDescription := null;
8396         tempCount := 1;
8397         if engStApprovers(i).item_class is null then
8398           tempCount := 0;
8399           for x in 1 .. engStItemIndexes.count loop
8400             if engStItemIndexes(x) = i then
8401               tempCount := tempCount + 1;
8402               if currentRepeatedFirstIndex = -1 then
8403                 currentRepeatedFirstIndex := x;
8404               end if;
8405             end if;
8406           end loop;
8407           hasRepeatedOccurrences := true;
8408         end if;
8409         currentIndex := 0;
8410         for j in 1 .. tempCount loop
8411           if hasRepeatedOccurrences then
8412             currentIndex := (currentRepeatedFirstIndex+j)-1;
8413           else
8414             currentIndex := i;
8415           end if;
8416           tempSourceDescription := null;
8417           tempRuleIdList.delete;
8418           if hasRepeatedOccurrences then
8419             ame_util.parseSourceValue(sourceValueIn => engStItemSources(currentIndex),
8420                                       sourceDescriptionOut => tempSourceDescription,
8421                                       ruleIdListOut => tempRuleIdList);
8422           else
8423             ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source,
8424                                       sourceDescriptionOut => tempSourceDescription,
8425                                       ruleIdListOut => tempRuleIdList);
8426           end if;
8427           if(tempRuleIdList.count = 0) then
8428             tempEngStRuleIndex := tempEngStRuleIndex + 1;
8429             engStRuleIndexes(tempEngStRuleIndex) := i;
8430             engStSourceTypes(tempEngStRuleIndex) := tempSourceDescription;
8431             if(engPrepareRuleIds) then
8432               engStRuleIds(tempEngStRuleIndex) := null;
8433             end if;
8434             if(engPrepareRuleDescs) then
8435               engStRuleDescriptions(tempEngStRuleIndex) := null;
8436             end if;
8437           else
8438             for k in 1 .. tempRuleIdList.count loop
8439               tempEngStRuleIndex := tempEngStRuleIndex + 1;
8440               engStRuleIndexes(tempEngStRuleIndex) := i;
8441               engStSourceTypes(tempEngStRuleIndex) := tempSourceDescription;
8442               if(engPrepareRuleIds) then
8443                 engStRuleIds(tempEngStRuleIndex) := tempRuleIdList(k);
8444               end if;
8445               if(engPrepareRuleDescs) then
8446                 engStRuleDescriptions(tempEngStRuleIndex) :=
8447                   ame_rule_pkg.getDescription(ruleIdIn => tempRuleIdList(k),
8448                                               processingDateIn => engEffectiveRuleDate);
8449               end if;
8450             end loop;
8451           end if;
8452         end loop;
8453       end loop;
8454     exception
8455       when others then
8456         ame_util.runtimeException(packageNameIn => 'ame_engine',
8457                                   routineNameIn => 'prepareRuleData',
8458                                   exceptionNumberIn => sqlcode,
8459                                   exceptionStringIn => sqlerrm);
8460         engStRuleDescriptions.delete;
8461         engStRuleIds.delete;
8462         engStRuleIndexes.delete;
8463         raise;
8464   end prepareRuleData;
8465   procedure getProductionIndexes(productionIndexesOut out nocopy ame_util.idList) as
8466     begin
8467       for i in 1 .. engStProductionIndexes.count loop
8468         productionIndexesOut(i) := engStProductionIndexes(i);
8469       end loop;
8470       exception
8471         when others then
8472           ame_util.runtimeException(packageNameIn => 'ame_engine',
8473                                     routineNameIn => 'getProductionIndexes',
8474                                     exceptionNumberIn => sqlcode,
8475                                     exceptionStringIn => sqlerrm);
8476           raise;
8477     end getProductionIndexes;
8478   procedure getRepeatedIndexes(repeatedIndexesOut out nocopy ame_util.idList
8479                               ,repeatedAppIndexesOut out nocopy ame_util.idList) as
8480     begin
8481       for i in 1 .. engStRepeatedIndexes.count loop
8482         repeatedIndexesOut(i) := engStRepeatedIndexes(i);
8483       end loop;
8484       for i in 1 .. engStRepeatedAppIndexes.count loop
8485         repeatedAppIndexesOut(i) := engStRepeatedAppIndexes(i);
8486       end loop;
8487       exception
8488         when others then
8489           ame_util.runtimeException(packageNameIn => 'ame_engine',
8490                                     routineNameIn => 'getRepeatedIndexes',
8491                                     exceptionNumberIn => sqlcode,
8492                                     exceptionStringIn => sqlerrm);
8493           raise;
8494     end getRepeatedIndexes;
8495   procedure getRuleDescriptions(ruleDescriptionsOut out nocopy ame_util.stringList) as
8496     begin
8497       for i in 1 .. engStRuleDescriptions.count loop
8498         ruleDescriptionsOut(i) := engStRuleDescriptions(i);
8499       end loop;
8500       exception
8501         when others then
8502           ame_util.runtimeException(packageNameIn => 'ame_engine',
8503                                     routineNameIn => 'getRuleDescriptions',
8504                                     exceptionNumberIn => sqlcode,
8505                                     exceptionStringIn => sqlerrm);
8506           raise;
8507     end getRuleDescriptions;
8508   procedure getRuleIds(ruleIdsOut out nocopy ame_util.idList) as
8509     begin
8510       for i in 1 .. engStRuleIds.count loop
8511         ruleIdsOut(i) := engStRuleIds(i);
8512       end loop;
8513       exception
8514         when others then
8515           ame_util.runtimeException(packageNameIn => 'ame_engine',
8516                                     routineNameIn => 'getRuleIds',
8517                                     exceptionNumberIn => sqlcode,
8518                                     exceptionStringIn => sqlerrm);
8519           raise;
8520     end getRuleIds;
8521   procedure getRuleIndexes(ruleIndexesOut out nocopy ame_util.idList) as
8522     begin
8523       for i in 1 .. engStRuleIndexes.count loop
8524         ruleIndexesOut(i) := engStRuleIndexes(i);
8525       end loop;
8526       exception
8527         when others then
8528           ame_util.runtimeException(packageNameIn => 'ame_engine',
8529                                     routineNameIn => 'getRuleIndexes',
8530                                     exceptionNumberIn => sqlcode,
8531                                     exceptionStringIn => sqlerrm);
8532           raise;
8533     end getRuleIndexes;
8534   procedure getRuntimeGroupMembers(groupIdIn in integer,
8535                                    approverNamesOut out nocopy ame_util.longStringList,
8536                                    approverOrderNumbersOut out nocopy ame_util.idList,
8537                                    approverDisplayNamesOut out nocopy ame_util.longStringList,
8538                                    origSystemIdsOut out nocopy ame_util.idList,
8539                                    origSystemsOut out nocopy ame_util.stringList) as
8540     firstNewIndex integer;
8541     tempIndex integer;
8542     begin
8543       tempIndex := 0; /* pre-increment */
8544       -- Check if group is defined or has to be re run for every item class/item ID
8545       if(not engGroupUseItemBind.exists(groupIdIn)) then
8546         fetchRuntimeGroup(groupIdIn => groupIdIn);
8547       elsif (engGroupUseItemBind(groupIdIn) = ame_util.booleanTrue) then
8548         fetchRuntimeGroup(groupIdIn => groupIdIn);
8549       end if;
8550       for i in 1 .. engGroupMemberGroupIds.count loop
8551         if(engGroupMemberGroupIds(i) = groupIdIn) then
8552           tempIndex := tempIndex + 1;
8553           approverNamesOut(tempIndex) := engGroupMemberNames(i);
8554           approverOrderNumbersOut(tempIndex) := engGroupMemberOrderNumbers(i);
8555           approverDisplayNamesOut(tempIndex) := engGroupMemberDisplayNames(i);
8556           origSystemsOut(tempIndex) := engGroupMemberOrigSystems(i);
8557           origSystemIdsOut(tempIndex) := engGroupMemberOrigSystemIds(i);
8558         elsif(tempIndex > 0) then /* We found and have passed the group. */
8559           exit;
8560         end if;
8561       end loop;
8562       /*
8563         If the group is the last one in the engGroup package variables, the above loop
8564         will never arrive at its exit statement, so we need to check for a found group
8565         outside the loop.
8566       */
8567       if(tempIndex > 0) then
8568         return;
8569       end if;
8570       exception
8571         when others then
8572           ame_util.runtimeException(packageNameIn => 'ame_engine',
8573                                     routineNameIn => 'getRuntimeGroupMembers',
8574                                     exceptionNumberIn => sqlcode,
8575                                     exceptionStringIn => sqlerrm);
8576           raise;
8577     end getRuntimeGroupMembers;
8578   procedure getSourceTypes(sourceTypesOut out nocopy ame_util.stringList) as
8579     begin
8580       for i in 1 .. engStSourceTypes.count loop
8581         sourceTypesOut(i) := engStSourceTypes(i);
8582       end loop;
8583       exception
8584         when others then
8585           ame_util.runtimeException(packageNameIn => 'ame_engine',
8586                                     routineNameIn => 'getSourceTypes',
8587                                     exceptionNumberIn => sqlcode,
8588                                     exceptionStringIn => sqlerrm);
8589           raise;
8590     end getSourceTypes;
8591   procedure getTestTransApplicableRules(ruleItemClassIdsOut out nocopy ame_util.idList,
8592                                         itemClassIdsOut out nocopy ame_util.idList,
8593                                         itemIdsOut out nocopy ame_util.stringList,
8594                                         ruleIdsOut out nocopy ame_util.idList,
8595                                         ruleTypesOut out nocopy ame_util.idList,
8596                                         ruleDescriptionsOut out nocopy ame_util.stringList) as
8597     headerItemClassId integer;
8598     switchRows boolean;
8599     tempIndex integer;
8600     tempItemClassId integer;
8601     tempItemId ame_util.stringType;
8602     tempRuleDescription ame_util.stringType;
8603     tempRuleId integer;
8604     tempRuleItemClassId integer;
8605     tempRuleNotFound boolean;
8606     tempRuleType integer;
8607     begin
8608       headerItemClassId := ame_admin_pkg.getItemClassIdByName(itemClassNameIn => ame_util.headerItemClassName);
8609       /* First populate the output lists, eliminating duplicate rules. */
8610       tempIndex := 0; /* pre-increment */
8611       for i in 1 .. engAppRuleIds.count loop
8612         tempRuleNotFound := true;
8613         for j in 1 .. (i - 1) loop
8614           if(engAppRuleIds(j) = engAppRuleIds(i) and
8615              engAppItemClassIds(i) = engAppItemClassIds(j) and
8616              engAppItemIds(i) = engAppItemIds(j)) then
8617             tempRuleNotFound := false;
8618             exit;
8619           end if;
8620         end loop;
8621         if(tempRuleNotFound) then
8622           tempIndex := tempIndex + 1;
8623           ruleIdsOut(tempIndex) := engAppRuleIds(i);
8624           itemClassIdsOut(tempIndex) := engAppItemClassIds(i);
8625           itemIdsOut(tempIndex) := engAppItemIds(i);
8626           ruleTypesOut(tempIndex) := ame_rule_pkg.getRuleType(ruleIdIn => engAppRuleIds(i),
8627                                                               processingDateIn => engEffectiveRuleDate);
8628           ruleItemClassIdsOut(tempIndex) := ame_rule_pkg.getItemClassId(ruleIdIn => engAppRuleIds(i),
8629                                                                         processingDateIn => engEffectiveRuleDate);
8630           ruleDescriptionsOut(tempIndex) := ame_rule_pkg.getDescription(ruleIdIn => engAppRuleIds(i),
8631                                                                         processingDateIn => engEffectiveRuleDate);
8632         end if;
8633       end loop;
8634       /*
8635         Now sort the output lists.  The header-level rules come first, then all other rules.  Among
8636         the header-level rules, sort first by ruleTypesOut, then by itemClassIdsOut, then by itemIdsOut.
8637         (The sort by item class and item ID is only relevant under per-item evaluation, but it's harmless
8638         otherwise, and efficiency is not a concern here.)  Among the non-header-level rules, sort first
8639         by ruleItemClassIdsOut, then by itemClassIdsOut, then by itemIdsOut, then by ruleTypesOut.
8640       */
8641       for i in 2 .. ruleItemClassIdsOut.count loop
8642         for j in 1 .. (i - 1) loop
8643           if(ruleItemClassIdsOut(j) = headerItemClassId and
8644              ruleItemClassIdsOut(i) = headerItemClassId) then
8645             if(ruleTypesOut(i) > ruleTypesOut(j)) then
8646               switchRows := false;
8647             elsif(ruleTypesOut(i) < ruleTypesOut(j)) then
8648               switchRows := true;
8649             else /* ruleTypesOut(i) = ruleTypesOut(j) */
8650               if(itemClassIdsOut(i) > itemClassIdsOut(j)) then
8651                 switchRows := false;
8652               elsif(itemClassIdsOut(i) < itemClassIdsOut(j)) then
8653                 switchRows := true;
8654               else /* itemClassIdsOut(i) = itemClassIdsOut(j) */
8655                 if(itemIdsOut(i) > itemIdsOut(j)) then
8656                   switchRows := false;
8657                 elsif(itemIdsOut(i) < itemIdsOut(j)) then
8658                   switchRows := true;
8659                 else /* itemIdsOut(i) = itemIdsOut(j) */
8660                   switchRows := false;
8661                 end if;
8662               end if;
8663             end if;
8664           elsif(ruleItemClassIdsOut(j) = headerItemClassId and
8665                 (ruleItemClassIdsOut(i) is null or
8666                  ruleItemClassIdsOut(i) <> headerItemClassId)) then
8667             switchRows := false;
8668           elsif((ruleItemClassIdsOut(j) is null or
8669                  ruleItemClassIdsOut(j) <> headerItemClassId) and
8670                 ruleItemClassIdsOut(i) = headerItemClassId) then
8671             switchRows := true;
8672           else /* ruleItemClassIdsOut(j) <> headerItemClassId and ruleItemClassIdsOut(i) <> headerItemClassId */
8673             if(ruleItemClassIdsOut(i) > ruleItemClassIdsOut(j) or
8674                (ruleItemClassIdsOut(i) is null and ruleItemClassIdsOut(j) is not null)) then
8675               switchRows := false;
8676             elsif(ruleItemClassIdsOut(i) < ruleItemClassIdsOut(j) or
8677                   (ruleItemClassIdsOut(i) is not null and ruleItemClassIdsOut(j) is null)) then
8678               switchRows := true;
8679             else /* ruleItemClassIdsOut(i) = ruleItemClassIdsOut(j) or both are null */
8680               if(itemClassIdsOut(i) > itemClassIdsOut(j)) then
8681                 switchRows := false;
8682               elsif(itemClassIdsOut(i) < itemClassIdsOut(j)) then
8683                 switchRows := true;
8684               else /* itemClassIdsOut(i) = itemClassIdsOut(j) */
8685                 if(itemIdsOut(i) > itemIdsOut(j)) then
8686                   switchRows := false;
8687                 elsif(itemIdsOut(i) < itemIdsOut(j)) then
8688                   switchRows := true;
8689                 else /* itemIdsOut(i) = itemIdsOut(j) */
8690                   switchRows := false;
8691                 end if;
8692               end if;
8693             end if;
8694           end if;
8695           if(switchRows) then
8696             /* Assign i values to temp buffers. */
8697             tempRuleItemClassId := ruleItemClassIdsOut(i);
8698             tempItemClassId := itemClassIdsOut(i);
8699             tempItemId := itemIdsOut(i);
8700             tempRuleId := ruleIdsOut(i);
8701             tempRuleType := ruleTypesOut(i);
8702             tempRuleDescription := ruleDescriptionsOut(i);
8703             /* Assign j values to i values. */
8704             ruleItemClassIdsOut(i) := ruleItemClassIdsOut(j);
8705             itemClassIdsOut(i) := itemClassIdsOut(j);
8706             itemIdsOut(i) := itemIdsOut(j);
8707             ruleIdsOut(i) := ruleIdsOut(j);
8708             ruleTypesOut(i) := ruleTypesOut(j);
8709             ruleDescriptionsOut(i) := ruleDescriptionsOut(j);
8710             /* Assign temp buffers to j values. */
8711             ruleItemClassIdsOut(j) := tempRuleItemClassId;
8712             itemClassIdsOut(j) := tempItemClassId;
8713             itemIdsOut(j) := tempItemId;
8714             ruleIdsOut(j) := tempRuleId;
8715             ruleTypesOut(j) := tempRuleType;
8716             ruleDescriptionsOut(j) := tempRuleDescription;
8717           end if;
8718         end loop;
8719       end loop;
8720       exception
8721         when others then
8722           ame_util.runtimeException(packageNameIn => 'ame_engine',
8723                                     routineNameIn => 'getTestTransApplicableRules',
8724                                     exceptionNumberIn => sqlcode,
8725                                     exceptionStringIn => sqlerrm);
8726           raise;
8727     end getTestTransApplicableRules;
8728   procedure getTestTransApprovers(isTestTransactionIn in boolean,
8729                                   transactionIdIn in varchar2,
8730                                   ameApplicationIdIn in integer,
8731                                   approverListStageIn in integer,
8732                                   approversOut out nocopy ame_util.approversTable2,
8733                                   productionIndexesOut out nocopy ame_util.idList,
8734                                   variableNamesOut out nocopy ame_util.stringList,
8735                                   variableValuesOut out nocopy ame_util.stringList) as
8736     tempCount integer;
8737     begin
8738       if(not isTestTransactionIn) then
8739         /*
8740           Make sure a real transaction gets logged and its state initialized.  (This is usually
8741           only necessary for "real" transactions created for debugging purposes.)
8742         */
8743         select count(*)
8744           into tempCount
8745           from ame_temp_transactions
8746           where
8747             application_id = ameApplicationIdIn and
8748             transaction_id = transactionIdIn and
8749             rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
8750         if(tempCount = 0) then
8751           insert into ame_temp_transactions(
8752             application_id,
8753             transaction_id,
8754             temp_transactions_id,
8755             row_timestamp) values(
8756               ameApplicationIdIn,
8757               transactionIdIn,
8758               -1,
8759               sysdate); /* Don't use engEffectiveRuleDate here. */
8760           updateTransactionState(isTestTransactionIn => false,
8761                                  isLocalTransactionIn => true,
8762                                  fetchConfigVarsIn => true,
8763                                  fetchOldApproversIn => true,
8764                                  fetchInsertionsIn => true,
8765                                  fetchDeletionsIn => true,
8766                                  fetchAttributeValuesIn => true,
8767                                  fetchInactiveAttValuesIn => false,
8768                                  processProductionActionsIn => false,
8769                                  processProductionRulesIn => false,
8770                                  updateCurrentApproverListIn => true,
8771                                  updateOldApproverListIn => true,
8772                                  processPrioritiesIn => true,
8773                                  prepareItemDataIn => true,
8774                                  prepareRuleIdsIn => true,
8775                                  prepareRuleDescsIn => false,
8776                                  prepareApproverTreeIn => true,
8777                                  transactionIdIn => transactionIdIn,
8778                                  ameApplicationIdIn => ameApplicationIdIn);
8779         end if;
8780       end if;
8781       setContext(isTestTransactionIn => isTestTransactionIn,
8782                  isLocalTransactionIn => true,
8783                  fetchConfigVarsIn => true,
8784                  fetchOldApproversIn => true,
8785                  fetchInsertionsIn => approverListStageIn > 1,
8786                  fetchDeletionsIn => approverListStageIn > 2,
8787                  fetchAttributeValuesIn => true,
8788                  fetchInactiveAttValuesIn => false,
8789                  processProductionActionsIn => true,
8790                  processProductionRulesIn => true,
8791                  updateCurrentApproverListIn => true,
8792                  updateOldApproverListIn => true,
8793                  processPrioritiesIn => true,
8794                  prepareItemDataIn => true,
8795                  prepareRuleIdsIn => true,
8796                  prepareRuleDescsIn => false,
8797                  prepareApproverTreeIn => true,
8798                  transactionIdIn => transactionIdIn,
8799                  ameApplicationIdIn => ameApplicationIdIn);
8800       evaluateRules;
8801       fetchApplicableActions;
8802       processExceptions;
8803       processRules;
8804       if(approverListStageIn > 1 and not isTestTransactionIn) then
8805         processAdHocInsertions;
8806         processUnresponsiveApprovers;
8807       end if;
8808       if(approverListStageIn > 2 and not isTestTransactionIn) then
8809         if engRepeatSubstitutions  then
8810           repeatSubstitutions;
8811         end if;
8812       end if;
8813       if(approverListStageIn > 3 and not isTestTransactionIn) then
8814         processSuppressions;
8815       end if;
8816       if(approverListStageIn > 4) then
8817         processRepeatedApprovers;
8818       end if;
8819       if(approverListStageIn > 5) then
8820         calculateApproverOrderNumbers;
8821       end if;
8822       populateEngStVariables;
8823       getApprovers(approversOut => approversOut);
8824       getProductionIndexes(productionIndexesOut => productionIndexesOut);
8825       getVariableNames(variableNamesOut=> variableNamesOut);
8826       getVariableValues(variableValuesOut => variableValuesOut);
8827       exception
8828         when others then
8829           rollback;
8830           ame_util.runtimeException(packageNameIn => 'ame_engine',
8831                                     routineNameIn => 'getTestTransApprovers',
8832                                     exceptionNumberIn => sqlcode,
8833                                     exceptionStringIn => sqlerrm);
8834           raise;
8835     end getTestTransApprovers;
8836   procedure getTransVariableNames(transVariableNamesOut out nocopy ame_util.stringList) as
8837     tempIndex integer;
8838     begin
8839       tempIndex := 1;
8840       for i in 1 .. engStProductionsTable.count loop
8841         if engStProductionsTable(i).item_class = ame_util.headerItemClassName and
8842          engStProductionsTable(i).item_id = engTransactionId then
8843           transVariableNamesOut(tempIndex) := engStProductionsTable(i).variable_name;
8844           tempIndex := tempIndex + 1;
8845         end if;
8846       end loop;
8847       exception
8848         when others then
8849           ame_util.runtimeException(packageNameIn => 'ame_engine',
8850                                     routineNameIn => 'getTransVariableNames',
8851                                     exceptionNumberIn => sqlcode,
8852                                     exceptionStringIn => sqlerrm);
8853           raise;
8854     end getTransVariableNames;
8855   procedure getTransVariableValues(transVariableValuesOut out nocopy ame_util.stringList) as
8856     tempIndex integer;
8857     begin
8858       tempIndex := 1;
8859       for i in 1 .. engStProductionsTable.count loop
8860         if engStProductionsTable(i).item_class = ame_util.headerItemClassName and
8861          engStProductionsTable(i).item_id = engTransactionId then
8862           transVariableValuesOut(tempIndex) := engStProductionsTable(i).variable_value;
8863           tempIndex := tempIndex + 1;
8864         end if;
8865       end loop;
8866       exception
8867         when others then
8868           ame_util.runtimeException(packageNameIn => 'ame_engine',
8869                                     routineNameIn => 'getTransVariableValues',
8870                                     exceptionNumberIn => sqlcode,
8871                                     exceptionStringIn => sqlerrm);
8872           raise;
8873     end getTransVariableValues;
8874   procedure getVariableNames(variableNamesOut out nocopy ame_util.stringList) as
8875     begin
8876       for i in 1 .. engStVariableNames.count loop
8877         variableNamesOut(i) := engStVariableNames(i);
8878       end loop;
8879       exception
8880         when others then
8881           ame_util.runtimeException(packageNameIn => 'ame_engine',
8882                                     routineNameIn => 'getVariableNames',
8883                                     exceptionNumberIn => sqlcode,
8884                                     exceptionStringIn => sqlerrm);
8885           raise;
8886     end getVariableNames;
8887   procedure getVariableValues(variableValuesOut out nocopy ame_util.stringList) as
8888     begin
8889       for i in 1 .. engStVariableValues.count loop
8890         variableValuesOut(i) := engStVariableValues(i);
8891       end loop;
8892       exception
8893         when others then
8894           ame_util.runtimeException(packageNameIn => 'ame_engine',
8895                                     routineNameIn => 'getVariableValues',
8896                                     exceptionNumberIn => sqlcode,
8897                                     exceptionStringIn => sqlerrm);
8898           raise;
8899     end getVariableValues;
8900   /* initializePlsqlContext is for amem0013.sql backwards compatibility only.  Do not use it elsewhere. */
8901   procedure initializePlsqlContext(ameApplicationIdIn in integer default null,
8902                                    fndApplicationIdIn in integer default null,
8903                                    transactionIdIn in varchar2 default null,
8904                                    transactionTypeIdIn in varchar2 default null,
8905                                    fetchConfigVarsIn in boolean default true,
8906                                    fetchOldApproversIn in boolean default true,
8907                                    fetchInsertionsIn in boolean default true,
8908                                    fetchDeletionsIn in boolean default true,
8909                                    fetchAttributeValuesIn in boolean default true,
8910                                    fetchInactiveAttValuesIn in boolean default false) as
8911     begin
8912       setContext(isTestTransactionIn => false,
8913                  isLocalTransactionIn => true,
8914                  fetchConfigVarsIn => true,
8915                  fetchOldApproversIn => true,
8916                  fetchInsertionsIn => true,
8917                  fetchDeletionsIn => true,
8918                  fetchAttributeValuesIn => true,
8919                  fetchInactiveAttValuesIn => false,
8920                  processProductionActionsIn => false,
8921                  processProductionRulesIn => false,
8922                  updateCurrentApproverListIn => true,
8923                  updateOldApproverListIn => true,
8924                  processPrioritiesIn => true,
8925                  prepareItemDataIn => false,
8926                  prepareRuleIdsIn => false,
8927                  prepareRuleDescsIn => false,
8928                  prepareApproverTreeIn => false,
8929                  transactionIdIn => transactionIdIn,
8930                  ameApplicationIdIn => ameApplicationIdIn,
8931                  fndApplicationIdIn => null,
8932                  transactionTypeIdIn => transactionTypeIdIn);
8933       exception
8934         when others then
8935           ame_util.runtimeException(packageNameIn => 'ame_engine',
8936                                     routineNameIn => 'initializePlsqlContext',
8937                                     exceptionNumberIn => sqlcode,
8938                                     exceptionStringIn => sqlerrm);
8939           raise;
8940     end initializePlsqlContext;
8941   procedure updateDeviationList( sourceIndexIn in number
8942                               ,targetIndexIn in number) as
8943   begin
8944    if engDeviationResultList.exists(sourceIndexIn) then
8945      engDeviationResultList(targetIndexIn) := engDeviationResultList(sourceIndexIn);
8946      engDeviationResultList.delete(sourceIndexIn);
8947    else
8948      return;
8949    end if;
8950   exception
8951     when others then
8952       ame_util.runtimeException(packageNameIn => 'ame_engine',
8953                                 routineNameIn => 'updateDeviationList',
8954                                 exceptionNumberIn => sqlcode,
8955                                 exceptionStringIn => sqlerrm);
8956   end updateDeviationList;
8957   procedure insertApprover(indexIn in integer,
8958                            approverIn in ame_util.approverRecord2,
8959                            adjustMemberOrderNumbersIn in boolean default false,
8960                            approverLocationIn in boolean default ame_util.lastAmongEquals,
8961                            inserteeIndexIn in number default null,
8962                            currentInsIndex in integer default null) as
8963     engStApproversCount integer;
8964     errorCode integer;
8965     errorMessage ame_util.longestStringType;
8966     indexException exception;
8967     lastIndex integer;
8968     nextIndex integer;
8969     nextIndexInChain boolean;
8970     previousIndex integer;
8971     previousIndexInChain boolean;
8972     tempVotingRegime     varchar2(1);
8973     approverTreeIndex    integer;
8974     l_insIndex number;
8975     l_action_type_id number;
8976     l_votingRegime  varchar2(100);
8977     l_action_type_name varchar2(100);
8978     begin
8979       checkApprover(approverIn => approverIn);
8980       engStApproversCount := engStApprovers.count;
8981       if(indexIn < 1 or
8982          indexIn > engStApproversCount + 1) then
8983         raise indexException;
8984       end if;
8985       nextIndex := indexIn + 1;
8986       previousIndex := indexIn - 1;
8987       if(engStApproversCount < nextIndex) then
8988         lastIndex := engStApproversCount;
8989       else
8990         lastIndex := nextIndex;
8991       end if;
8992       /* Move any existing approvers at and above the target index. */
8993       /*
8994         It's necessary to initialize a new record at the end of engStApprovers,
8995         for ame_util.copyApproverRecord2 to work in the loop below.
8996       */
8997       engStApprovers(engStApproversCount + 1) := ame_util.emptyApproverRecord2;
8998       for i in reverse indexIn .. engStApproversCount loop
8999         ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i),
9000                                      approverRecord2Out => engStApprovers(i + 1));
9001 
9002         l_insIndex := engInsApproverIndex.first;
9003         if l_insIndex is not null then
9004           loop
9005             if engInsApproverIndex(l_insIndex) = i then
9006               engInsApproverIndex(l_insIndex) := null;
9007               engInsApproverIndex(l_insIndex) := i+1;
9008             end if;
9009             exit when l_insIndex = engInsApproverIndex.last;
9010             l_insIndex := engInsApproverIndex.next(l_insIndex);
9011           end loop;
9012         end if;
9013       end loop;
9014       /* Copy the input approver to the target index. */
9015       ame_util.copyApproverRecord2(approverRecord2In => approverIn,
9016                                    approverRecord2Out => engStApprovers(indexIn));
9017       /*
9018        If the status is not available in ame_temp_insertions get it from
9019        ame_temp_old_approver_lists
9020       */
9021       if engStApprovers(indexIn).approval_status is null then
9022          engStApprovers(indexIn).approval_status :=  getHandlerApprovalStatus(approverIn => engStApprovers(indexIn)
9023                                                      ,isInsertionapprover => true);
9024       end if;
9025       engStApproversCount := engStApproversCount + 1;
9026       /* Optionally adjust member_order_number values in the target group or chain. */
9027       if(adjustMemberOrderNumbersIn) then
9028         if(indexIn = 1 or
9029            engStApprovers(previousIndex).group_or_chain_id <> approverIn.group_or_chain_id or
9030            engStApprovers(previousIndex).action_type_id <> approverIn.action_type_id or
9031            engStApprovers(previousIndex).item_id <> approverIn.item_id or
9032            engStApprovers(previousIndex).item_class <> approverIn.item_class) then
9033           previousIndexInChain := false;
9034         else
9035           previousIndexInChain := true;
9036         end if;
9037         if(indexIn = engStApprovers.count or
9038            engStApprovers(nextIndex).group_or_chain_id <> approverIn.group_or_chain_id or
9039            engStApprovers(nextIndex).action_type_id <> approverIn.action_type_id or
9040            engStApprovers(nextIndex).item_id <> approverIn.item_id or
9041            engStApprovers(nextIndex).item_class <> approverIn.item_class) then
9042           nextIndexInChain := false;
9043         else
9044           nextIndexInChain := true;
9045         end if;
9046         if(previousIndexInChain) then
9047           if(nextIndexInChain) then
9048             if(engStApprovers(previousIndex).member_order_number =
9049                engStApprovers(nextIndex).member_order_number) then
9050               engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number;
9051             else
9052               engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9053               for i in nextIndex .. engStApproversCount loop
9054                 if(engStApprovers(i).item_class <> engStApprovers(indexIn).item_class or
9055                    engStApprovers(i).item_id <> engStApprovers(indexIn).item_id or
9056                    engStApprovers(i).action_type_id <> engStApprovers(indexIn).action_type_id or
9057                    engStApprovers(i).group_or_chain_id <> engStApprovers(indexIn).group_or_chain_id) then
9058                   exit;
9059                 end if;
9060                 engStApprovers(i).member_order_number := engStApprovers(i).member_order_number + 1;
9061               end loop;
9062             end if;
9063           else
9064             if(engStApprovers(previousIndex).approval_status in
9065              (ame_util.approveAndForwardStatus, ame_util.forwardStatus)) then
9066               if(engActionTypeNames(engStApprovers(previousIndex).action_type_id) in
9067                       (ame_util.groupChainApprovalTypeName
9068                       ,ame_util.preApprovalTypeName
9069                       ,ame_util.postApprovalTypeName )) then
9070                 select voting_regime
9071                   into tempVotingRegime
9072                   from ame_approval_group_config
9073                  where approval_group_id = engStApprovers(previousIndex).group_or_chain_id
9074                    and application_id = engAmeApplicationId
9075                    and sysdate between start_date and nvl(end_Date - (1/86400), sysdate);
9076                 if(tempVotingRegime not in (ame_util.serializedVoting
9077                                            ,ame_util.orderNumberVoting)) then
9078                   engStApprovers(indexIn).member_order_number := 1;
9079                 else
9080                   engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9081                 end if;
9082               else
9083                 if(engActionTypeVotingRegimes(engStApprovers(previousIndex).action_type_id) <>
9084                          ame_util.serializedVoting) then
9085                   engStApprovers(indexIn).member_order_number := 1;
9086                 else
9087                   engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9088                 end if;
9089               end if;
9090             else
9091               engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9092             end if;
9093           end if;
9094         else
9095           if(nextIndexInChain) then
9096             engStApprovers(indexIn).member_order_number := engStApprovers(nextIndex).member_order_number - 1;
9097           else
9098             engStApprovers(indexIn).member_order_number := 1;
9099           end if;
9100         end if;
9101       end if;
9102       l_action_type_id := engStApprovers(indexIn).action_type_id;
9103       l_action_type_name := getActionTypeName(l_action_type_id);
9104       if l_action_type_name in (ame_util.postApprovalTypeName,ame_util.preApprovalTypeName ) then
9105           l_votingRegime := ame_approval_group_pkg.getVotingRegime(
9106                            approvalGroupIdIn => engStApprovers(indexIn).group_or_chain_id ,
9107                            applicationIdIn => engAmeApplicationId);
9108         else
9109           l_votingRegime := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => approverIn.action_type_id);
9110       end if;
9111       if engStApprovers(indexIn).approval_status in (ame_util.approvedStatus
9112                                                       ,ame_util.approvedByRepeatedStatus
9113                                                       ,ame_util.rejectStatus
9114                                                       ,ame_util.rejectedByRepeatedStatus ) and l_votingRegime = ame_util.firstApproverVoting then
9115           for i in 1..engStApprovers.count loop
9116             if engStApprovers(indexIn).name <> engStApprovers(i).name and
9117                 engStApprovers(indexIn).action_type_id = engStApprovers(i).action_type_id and
9118                 engStApprovers(indexIn).group_or_chain_id = engStApprovers(i).group_or_chain_id and
9119                 engStApprovers(indexIn).item_class = engStApprovers(i).item_class and
9120                 engStApprovers(indexIn).item_id = engStApprovers(i).item_id and
9121                 engStApprovers(indexIn).member_order_number = engStApprovers(i).member_order_number and
9122                 engStApprovers(i).approval_status is null then
9123              engStApprovers(i).approval_status := ame_util.beatByFirstResponderStatus;
9124             end if;
9125           end loop;
9126       end if;
9127       if engStApprovers(indexIn).approval_status is null and l_votingRegime = ame_util.firstApproverVoting then
9128         if(indexIn <> 1 and indexIn <> engStApprovers.count) then
9129           if(engStApprovers(previousIndex).group_or_chain_id = engStApprovers(indexIn).group_or_chain_id and
9130              engStApprovers(previousIndex).action_type_id = engStApprovers(indexIn).action_type_id and
9131              engStApprovers(previousIndex).item_id = engStApprovers(indexIn).item_id and
9132              engStApprovers(previousIndex).item_class = engStApprovers(indexIn).item_class and
9133              engStApprovers(previousIndex).member_order_number = engStApprovers(indexIn).member_order_number) and
9134             (engStApprovers(nextIndex).group_or_chain_id = engStApprovers(indexIn).group_or_chain_id and
9135              engStApprovers(nextIndex).action_type_id = engStApprovers(indexIn).action_type_id and
9136              engStApprovers(nextIndex).item_id = engStApprovers(indexIn).item_id and
9137              engStApprovers(nextIndex).item_class = engStApprovers(indexIn).item_class and
9138              engStApprovers(nextIndex).member_order_number = engStApprovers(indexIn).member_order_number) then
9139            for i in 1..engStApprovers.count loop
9140             if engStApprovers(indexIn).name <> engStApprovers(i).name and
9141                 engStApprovers(indexIn).action_type_id = engStApprovers(i).action_type_id and
9142                 engStApprovers(indexIn).group_or_chain_id = engStApprovers(i).group_or_chain_id and
9143                 engStApprovers(indexIn).item_class = engStApprovers(i).item_class and
9144                 engStApprovers(indexIn).item_id = engStApprovers(i).item_id and
9145                 engStApprovers(i).approval_status in (ame_util.approvedStatus
9146                                                       ,ame_util.approvedByRepeatedStatus
9147                                                       ,ame_util.beatByFirstResponderStatus
9148                                                       ,ame_util.rejectStatus
9149                                                       ,ame_util.rejectedByRepeatedStatus ) then
9150                  engStApprovers(indexIn).approval_status := ame_util.beatByFirstResponderStatus;
9151             end if;
9152            end loop;
9153           end if;
9154         end if;
9155       end if;
9156       if engPrepareApproverTree and approverIn.orig_system <> 'AME_INS_ORIG_SYSTEM' then
9157         if engStApproversTree.count = 0 then
9158         /* If there are no approvers in tree just add the approver                  */
9159           if inserteeIndexIn is not null then
9160             engTempReason := engInsertionReasonList(inserteeIndexIn);
9161             engTempDate := engInsertionDateList(inserteeIndexIn);
9162           end if;
9163           addApproverToTree
9164             (approverRecordIn    => engStApprovers(indexIn)
9165             ,approverIndexIn     => indexIn
9166             ,approverLocationIn  => ame_util.lastAmongEquals);
9167           if currentInsIndex is not null then
9168             engInsApproverIndex(currentInsIndex) := indexIn;
9169           end if;
9170         else
9171         /* If there exists approvers in the tree then if adjustMemberOrderNumbersIn */
9172         /* is true update the member order number in the tree                       */
9173         /* Add the approver to tree                                                 */
9174           if adjustMemberOrderNumbersIn then
9175             approverTreeIndex := engStApproversTree.first;
9176             loop
9177               if engStApproversTree(approverTreeIndex).approver_index >= indexIn then
9178                 engStApproversTree(approverTreeIndex).order_number
9179                      := engStApprovers(engStApproversTree(approverTreeIndex).approver_index + 1).member_order_number;
9180               end if;
9181               exit when approverTreeIndex = engStApproversTree.last;
9182               approverTreeIndex := engStApproversTree.next(approverTreeIndex);
9183             end loop;
9184           end if;
9185           approverTreeIndex := engStApproversTree.first;
9186           loop
9187             if engStApproversTree(approverTreeIndex).approver_index >= indexIn then
9188               engStApproversTree(approverTreeIndex).approver_index := engStApproversTree(approverTreeIndex).approver_index + 1;
9189             end if;
9190             exit when approverTreeIndex = engStApproversTree.last;
9191             approverTreeIndex := engStApproversTree.next(approverTreeIndex);
9192           end loop;
9193           if inserteeIndexIn is not null then
9194             engTempReason := engInsertionReasonList(inserteeIndexIn);
9195             engTempDate := engInsertionDateList(inserteeIndexIn);
9196           end if;
9197           addApproverToTree
9198             (approverRecordIn    => engStApprovers(indexIn)
9199             ,approverIndexIn     => indexIn
9200             ,approverLocationIn  => approverLocationIn);
9201           if currentInsIndex is not null then
9202             engInsApproverIndex(currentInsIndex) := indexIn;
9203           end if;
9204         end if;
9205       end if;
9206       exception
9207         when indexException then
9208           errorCode := -20001;
9209           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
9210                                               messageNameIn => 'AME_400686_ENG_IDX_OUT_OF_BOU');
9211           ame_util.runtimeException(packageNameIn => 'ame_engine',
9212                                     routineNameIn => 'insertApprover',
9213                                     exceptionNumberIn => errorCode,
9214                                     exceptionStringIn => errorMessage);
9215           raise_application_error(errorCode,
9216                                   errorMessage);
9217         when others then
9218           ame_util.runtimeException(packageNameIn => 'ame_engine',
9219                                     routineNameIn => 'insertApprover',
9220                                     exceptionNumberIn => sqlcode,
9221                                     exceptionStringIn => sqlerrm);
9222           raise;
9223     end insertApprover;
9224   procedure insertApprovers(firstIndexIn in integer,
9225                             approversIn in ame_util.approversTable2) as
9226     approversInCount integer;
9227     engStApproversCount integer;
9228     errorCode integer;
9229     errorMessage ame_util.longestStringType;
9230     indexException exception;
9231     lastIndex integer;
9232     newTreeNode ame_util.approverTreeRecord;
9233     newTreeNodeIndex integer;
9234     siblingTreeNodeIndex integer;
9235     tempIndex integer;
9236     loopIndex integer;
9237     begin
9238       if(firstIndexIn < 1 or
9239          firstIndexIn > engStApprovers.count + 1) then
9240         raise indexException;
9241       end if;
9242       approversInCount := approversIn.count;
9243       engStApproversCount := engStApprovers.count;
9244       /* This code was modified to fix the BUG:(4093937) */
9245       /* Issue 1 in the list of bugs found during the implementation of the */
9246       /* asynchronous parallel approver functionality */
9247       lastIndex := engStApproversCount;
9248       /* Move any existing approvers at and above firstIndexIn. */
9249       for i in reverse firstIndexIn .. lastIndex loop
9250         ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i),
9251                                      approverRecord2Out => engStApprovers(i + approversInCount));
9252       end loop;
9253       /* Copy the input approvers to the target indexes. */
9254       tempIndex := firstIndexIn; /* post-increment */
9255       for i in 1 .. approversInCount loop
9256         ame_util.copyApproverRecord2(approverRecord2In => approversIn(i),
9257                                      approverRecord2Out => engStApprovers(tempIndex));
9258         tempIndex := tempIndex + 1;
9259       end loop;
9260       /* Insert the new approvers to the tree */
9261       if engPrepareApproverTree then
9262         /* Approvers Tree is sparse */
9263         loopIndex := engStApproversTree.last;
9264         loop
9265           if engStApproversTree(loopIndex).approver_index >= firstIndexIn then
9266             engStApproversTree(loopIndex).approver_index
9267                                  := engStApproversTree(loopIndex).approver_index + approversIn.count;
9268           elsif engStApproversTree(loopIndex).approver_index = firstIndexIn - 1 then
9269             siblingTreeNodeIndex := engStApproversTree(loopIndex).sibling_index;
9270             for j in reverse 1 .. approversIn.count loop
9271               newTreeNode.parent_index := engStApproversTree(loopIndex).parent_index;
9272               newTreeNode.sibling_index := siblingTreeNodeIndex;
9273               newTreeNode.child_index := ame_util.noChildIndex;
9274               newTreeNode.order_number := approversIn(j).member_order_number;
9275               newTreeNode.approver_index := engStApproversTree(loopIndex).approver_index + j ;
9276               newTreeNode.tree_level_id := approversIn(j).name;
9277               newTreeNode.is_suspended := ame_util.booleanFalse;
9278               newTreeNode.tree_level := 6;
9279               newTreeNodeIndex := engStApproversTree.last + 1;
9280               engStApproversTree(newTreeNodeIndex) := newTreeNode;
9281               siblingTreeNodeIndex := newTreeNodeIndex;
9282             end loop;
9283             engStApproversTree(loopIndex).sibling_index := siblingTreeNodeIndex;
9284           end if;
9285           exit when engStApproversTree.first = loopIndex;
9286           loopIndex := engStApproversTree.prior(loopIndex);
9287         end loop;
9288       end if;
9289       exception
9290         when indexException then
9291           errorCode := -20001;
9292           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
9293                                               messageNameIn => 'AME_400687_ENG_FIDX_OUT_OF_BOU');
9294           ame_util.runtimeException(packageNameIn => 'ame_engine',
9295                                     routineNameIn => 'insertApprovers',
9296                                     exceptionNumberIn => errorCode,
9297                                     exceptionStringIn => errorMessage);
9298           raise_application_error(errorCode,
9299                                   errorMessage);
9300         when others then
9301           ame_util.runtimeException(packageNameIn => 'ame_engine',
9302                                     routineNameIn => 'insertApprovers',
9303                                     exceptionNumberIn => sqlcode,
9304                                     exceptionStringIn => sqlerrm);
9305           raise;
9306     end insertApprovers;
9307   procedure insertIntoTransApprovalHistory
9308               (transactionIdIn  ame_trans_approval_history.transaction_id%type
9309               ,applicationIdIn  ame_trans_approval_history.application_id%type
9310               ,orderNumberIn    ame_trans_approval_history.order_number%type
9311               ,nameIn           ame_trans_approval_history.name%type
9312               ,appCategoryIn    ame_trans_approval_history.approver_category%type
9313               ,itemClassIn      ame_trans_approval_history.item_class%type
9314               ,itemIdIn         ame_trans_approval_history.item_id%type
9315               ,actionTypeIdIn   ame_trans_approval_history.action_type_id%type
9316               ,authorityIn      ame_trans_approval_history.authority%type
9317               ,statusIn         ame_trans_approval_history.status%type
9318               ,grpOrChainIdIn   ame_trans_approval_history.group_or_chain_id%type
9319               ,occurrenceIn     ame_trans_approval_history.occurrence%type
9320               ,apiInsertionIn   ame_trans_approval_history.api_insertion%type
9321               ,memberorderNumberIn ame_trans_approval_history.member_order_number%type
9322               ,notificationIdIn ame_trans_approval_history.notification_id%type
9323               ,userCommentsIn   ame_trans_approval_history.user_comments%type
9324               ,dateClearedIn    ame_trans_approval_history.date_cleared%type
9325               ,historyTypeIn    varchar2) as
9326     tempTransHistoryId ame_trans_approval_history.trans_history_id%type;
9327     tempItemClass      ame_trans_approval_history.item_class%type;
9328     tempItemId         ame_trans_approval_history.item_id%type;
9329     tempOrderNumber    ame_trans_approval_history.order_number%type;
9330     tempAuthority      ame_trans_approval_history.authority%type;
9331     tempActionTypeId   ame_trans_approval_history.action_type_id%type;
9332     tempGroupOrChainId ame_trans_approval_history.group_or_chain_id%type;
9333     tempOccurrence     ame_trans_approval_history.occurrence%type;
9334     tempApiInsertion   ame_trans_approval_history.api_insertion%type;
9335     tempMemberOrderNumber ame_trans_approval_history.member_order_number%type;
9336     tempName           ame_trans_approval_history.name%type;
9337     approvers          ame_util.approversTable2;
9338     begin
9339       tempName := nameIn;
9340       if historyTypeIn = 'BEATBYFIRSTRESPONDER' then
9341         ame_engine.getApprovers(approversOut => approvers);
9342         for i in 1 .. approvers.count loop
9343           if (approvers(i).name <> nameIn or approvers(i).occurrence <> occurrenceIn)
9344             and approvers(i).item_class = itemClassIn
9345             and approvers(i).item_id = itemIdIn
9346             and approvers(i).action_type_id = actionTypeIdIn
9347             and approvers(i).group_or_chain_id = grpOrChainIdIn
9348             and approvers(i).approver_category = ame_util.approvalApproverCategory
9349             and approvers(i).approval_status = ame_util.notifiedStatus
9350           then
9351             select ame_trans_approval_history_s.nextval
9352               into tempTransHistoryId
9353               from dual;
9354             insert into AME_TRANS_APPROVAL_HISTORY
9355                 (TRANS_HISTORY_ID
9356                 ,TRANSACTION_ID
9357                 ,APPLICATION_ID
9358                 ,ROW_TIMESTAMP
9359                 ,ORDER_NUMBER
9360                 ,NAME
9361                 ,APPROVER_CATEGORY
9362                 ,ITEM_CLASS
9363                 ,ITEM_ID
9364                 ,ACTION_TYPE_ID
9365                 ,AUTHORITY
9366                 ,STATUS
9367                 ,GROUP_OR_CHAIN_ID
9368                 ,OCCURRENCE
9369                 ,API_INSERTION
9370                 ,MEMBER_ORDER_NUMBER
9371                 ,NOTIFICATION_ID
9372                 ,USER_COMMENTS
9373                 ,DATE_CLEARED
9374                 )select tempTransHistoryId
9375                        ,transactionIdIn
9376                        ,applicationIdIn
9377                        ,sysdate
9378                        ,approvers(i).approver_order_number
9379                        ,approvers(i).name
9380                        ,approvers(i).approver_category
9381                        ,approvers(i).item_class
9382                        ,approvers(i).item_id
9383                        ,approvers(i).action_type_id
9384                        ,approvers(i).authority
9385                        ,ame_util.beatByFirstResponderStatus
9386                        ,approvers(i).group_or_chain_id
9387                        ,approvers(i).occurrence
9388                        ,approvers(i).api_insertion
9389                        ,approvers(i).member_order_number
9390                        ,notificationIdIn
9391                        ,null
9392                        ,null
9393                    from dual;
9394           end if;
9395         end loop;
9396         return;
9397       end if;
9398       if historyTypeIn = 'CLEARFRWGRP' then
9399         ame_engine.getApprovers(approversOut => approvers);
9400         for i in 1 .. approvers.count loop
9401           if (approvers(i).name <> nameIn or approvers(i).occurrence <> occurrenceIn)
9402             and approvers(i).item_class = itemClassIn
9403             and approvers(i).item_id = itemIdIn
9404             and approvers(i).action_type_id = actionTypeIdIn
9405             and approvers(i).group_or_chain_id = grpOrChainIdIn
9406             and approvers(i).approver_category = ame_util.approvalApproverCategory
9407             -- and approvers(i).approval_status = ame_util.notifiedStatus
9408           then
9409             select ame_trans_approval_history_s.nextval
9410               into tempTransHistoryId
9411               from dual;
9412             insert into AME_TRANS_APPROVAL_HISTORY
9413                 (TRANS_HISTORY_ID
9414                 ,TRANSACTION_ID
9415                 ,APPLICATION_ID
9416                 ,ROW_TIMESTAMP
9417                 ,ORDER_NUMBER
9418                 ,NAME
9419                 ,APPROVER_CATEGORY
9420                 ,ITEM_CLASS
9421                 ,ITEM_ID
9422                 ,ACTION_TYPE_ID
9423                 ,AUTHORITY
9424                 ,STATUS
9425                 ,GROUP_OR_CHAIN_ID
9426                 ,OCCURRENCE
9427                 ,API_INSERTION
9428                 ,MEMBER_ORDER_NUMBER
9429                 ,NOTIFICATION_ID
9430                 ,USER_COMMENTS
9431                 ,DATE_CLEARED
9432                 )select tempTransHistoryId
9433                        ,transactionIdIn
9434                        ,applicationIdIn
9435                        ,sysdate
9436                        ,approvers(i).approver_order_number
9437                        ,approvers(i).name
9438                        ,approvers(i).approver_category
9439                        ,approvers(i).item_class
9440                        ,approvers(i).item_id
9441                        ,approvers(i).action_type_id
9442                        ,approvers(i).authority
9443                        ,ame_util.beatByFirstResponderStatus
9444                        ,approvers(i).group_or_chain_id
9445                        ,approvers(i).occurrence
9446                        ,approvers(i).api_insertion
9447                        ,approvers(i).member_order_number
9448                        ,notificationIdIn
9449                        ,null
9450                        ,null
9451                    from dual;
9452           end if;
9453         end loop;
9454         return;
9455       end if;
9456       select ame_trans_approval_history_s.nextval
9457         into tempTransHistoryId
9458         from dual;
9459       if historyTypeIn = 'APPROVERPRESENT' then
9460         insert into AME_TRANS_APPROVAL_HISTORY
9461                 (TRANS_HISTORY_ID
9462                 ,TRANSACTION_ID
9463                 ,APPLICATION_ID
9464                 ,ROW_TIMESTAMP
9465                 ,ORDER_NUMBER
9466                 ,NAME
9467                 ,APPROVER_CATEGORY
9468                 ,ITEM_CLASS
9469                 ,ITEM_ID
9470                 ,ACTION_TYPE_ID
9471                 ,AUTHORITY
9472                 ,STATUS
9473                 ,GROUP_OR_CHAIN_ID
9474                 ,OCCURRENCE
9475                 ,API_INSERTION
9476                 ,MEMBER_ORDER_NUMBER
9477                 ,NOTIFICATION_ID
9478                 ,USER_COMMENTS
9479                 ,DATE_CLEARED
9480                 )values
9481                 (tempTransHistoryId
9482                 ,transactionIdIn
9483                 ,applicationIdIn
9484                 ,sysdate
9485                 ,orderNumberIn
9486                 ,nameIn
9487                 ,appCategoryIn
9488                 ,itemClassIn
9489                 ,itemIdIn
9490                 ,actionTypeIdIn
9491                 ,authorityIn
9492                 ,statusIn
9493                 ,grpOrChainIdIn
9494                 ,occurrenceIn
9495                 ,apiInsertionIn
9496                 ,memberorderNumberIn
9497                 ,notificationIdIn
9498                 ,userCommentsIn
9499                 ,dateClearedIn);
9500       else
9501         begin
9502           select atah.item_class item_class
9503                 ,atah.item_id item_id
9504                 ,atah.order_number order_number
9505                 ,atah.authority authority
9506                 ,atah.action_type_id action_type_id
9507                 ,atah.group_or_chain_id group_or_chain_id
9508                 ,atah.occurrence occurrence
9509                 ,atah.api_insertion api_insertion
9510                 ,atah.member_order_number member_order_number
9511             into tempItemClass
9512                 ,tempItemId
9513                 ,tempOrderNumber
9514                 ,tempAuthority
9515                 ,tempActionTypeId
9516                 ,tempGroupOrChainId
9517                 ,tempOccurrence
9518                 ,tempApiInsertion
9519                 ,tempMemberOrderNumber
9520             from ame_trans_approval_history atah
9521                 ,fnd_lookups lookup
9522                 ,fnd_lookups lookup2
9523                 ,ame_approval_groups apg
9524            where atah.date_cleared is null
9525              and atah.transaction_id = transactionIdIn
9526              and atah.application_id = applicationIdIn
9527              and atah.name = tempName
9528              and atah.trans_history_id =
9529                    (select max(b.trans_history_id)
9530                       from ame_trans_approval_history b
9531                      where atah.transaction_id = b.transaction_id
9532                        and atah.application_id = b.application_id
9533                        and atah.name = b.name
9534                        and atah.approver_category = b.approver_category
9535                        and atah.item_class = b.item_class
9536                        and atah.item_id = b.item_id
9537                        and atah.action_type_id = b.action_type_id
9538                        and atah.authority = b.authority
9539                        and atah.group_or_chain_id = b.group_or_chain_id
9540                        and atah.occurrence = b.occurrence
9541                        and b.date_cleared is null )
9542              and lookup.lookup_type = 'AME_SUBLIST_TYPES'
9543              and lookup.lookup_code = atah.authority
9544              and lookup2.lookup_type = 'AME_APPROVAL_STATUS'
9545              and lookup2.lookup_code = atah.status
9546              and apg.approval_group_id(+) = atah.group_or_chain_id
9547              and sysdate between nvl(apg.start_date,sysdate) and nvl(apg.end_date,sysdate);
9548         exception
9549           when no_data_found then
9550             tempItemClass      := '$AME_INVALID_ITEM_CLASS$';
9551             tempItemId         := '$AME_INVALID_ITEM$';
9552             tempOrderNumber    := 0;
9553             tempAuthority      := 'Y';
9554             tempActionTypeId   := ame_util.nullHistoryActionTypeId;
9555             tempGroupOrChainId := ame_util.nullHistoryGroupOrChainId;
9556             tempOccurrence     := ame_util.nullHistoryOccurrence;
9557             tempApiInsertion   := null;
9558             tempMemberOrderNumber := null;
9559         end;
9560         if orderNumberIn is not null then
9561           tempOrderNumber := orderNumberIn;
9562         end if;
9563         if itemClassIn is not null then
9564           tempItemClass := itemClassIn;
9565         end if;
9566         if itemIdIn is not null then
9567           tempItemId := itemIdIn;
9568         end if;
9569         if grpOrChainIdIn is not null then
9570           tempGroupOrChainId := grpOrChainIdIn;
9571         end if;
9572         if authorityIn is not null then
9573           tempAuthority := authorityIn;
9574         end if;
9575         if actionTypeIdIn is not null then
9576           tempActionTypeId := actionTypeIdIn;
9577         end if;
9578         if occurrenceIn is not null then
9579           tempOccurrence := occurrenceIn;
9580         end if;
9581         if apiInsertionIn is not null then
9582           tempApiInsertion := apiInsertionIn;
9583         end if;
9584         if memberorderNumberIn is not null then
9585           tempMemberOrderNumber := memberorderNumberIn;
9586         end if;
9587         insert into AME_TRANS_APPROVAL_HISTORY
9588                 (TRANS_HISTORY_ID
9589                 ,TRANSACTION_ID
9590                 ,APPLICATION_ID
9591                 ,ROW_TIMESTAMP
9592                 ,ORDER_NUMBER
9593                 ,NAME
9594                 ,APPROVER_CATEGORY
9595                 ,ITEM_CLASS
9596                 ,ITEM_ID
9597                 ,ACTION_TYPE_ID
9598                 ,AUTHORITY
9599                 ,STATUS
9600                 ,GROUP_OR_CHAIN_ID
9601                 ,OCCURRENCE
9602                 ,API_INSERTION
9603                 ,MEMBER_ORDER_NUMBER
9604                 ,NOTIFICATION_ID
9605                 ,USER_COMMENTS
9606                 ,DATE_CLEARED
9607                ) values
9608                (tempTransHistoryId
9609                ,transactionIdIn
9610                ,applicationIdIn
9611                ,sysdate
9612                ,tempOrderNumber
9613                ,nameIn
9614                ,appCategoryIn
9615                ,tempItemClass
9616                ,tempItemId
9617                ,tempActionTypeId
9618                ,tempAuthority
9619                ,statusIn
9620                ,tempGroupOrChainId
9621                ,tempOccurrence
9622                ,tempApiInsertion
9623                ,tempMemberOrderNumber
9624                ,notificationIdIn
9625                ,userCommentsIn
9626                ,dateClearedIn
9627                );
9628       end if;
9629       exception
9630         when others then
9631           ame_util.runtimeException(packageNameIn => 'ame_engine',
9632                                     routineNameIn => 'insertIntoTransApprovalHistory',
9633                                     exceptionNumberIn => sqlcode,
9634                                     exceptionStringIn => sqlerrm);
9635 
9636     end insertIntoTransApprovalHistory;
9637   procedure lockTransaction(fndApplicationIdIn in integer,
9638                             transactionIdIn in varchar2,
9639                             transactionTypeIdIn in varchar2 default null) as
9640     tempTransIsLocked varchar2(2);
9641     cursor IsEngLocked is
9642       select 'Y'
9643         from ame_temp_trans_locks
9644        where fnd_application_id = fndApplicationIdIn
9645          and transaction_id = transactionIdIn
9646          and transaction_type_id = transactionTypeIdIn;
9647     begin
9648       /*
9649         The ame_temp_trans_locks_pk unique index will prevent the following insert from occurring
9650         if another row has already been inserted into ame_temp_trans_locks with the same
9651         fnd_application_id, transaction_type_id, and transaction_id values (even though the other
9652         insert is not committed).
9653       */
9654       tempTransIsLocked := null;
9655       if(engTransactionIsLocked) then
9656         return;
9657       end if;
9658       open IsEngLocked;
9659       fetch IsEngLocked into tempTransIsLocked;
9660       close IsEngLocked;
9661       if tempTransIsLocked = 'Y' then
9662         return;
9663       end if;
9664       insert into ame_temp_trans_locks(fnd_application_id,
9665                                        transaction_type_id,
9666                                        transaction_id,
9667                                        row_timestamp) values(
9668                                        fndApplicationIdIn,
9669                                        transactionTypeIdIn,
9670                                        transactionIdIn,
9671                                        sysdate);
9672       engTransactionIsLocked := true;
9673       exception
9674         when others then
9675           ame_util.runtimeException(packageNameIn => 'ame_engine',
9676                                     routineNameIn => 'lockTransaction',
9677                                     exceptionNumberIn => sqlcode,
9678                                     exceptionStringIn => sqlerrm);
9679           raise;
9680     end lockTransaction;
9681   procedure logTransaction as
9682     tempCount integer:= null;
9683     tempTransSeqId number;
9684     begin
9685       /* Log the transaction for eventual purging from the temp tables. */
9686       select count(*)
9687         into tempCount
9688         from ame_temp_transactions
9689         where
9690           application_id = engAmeApplicationId and
9691           transaction_id = engTransactionId and
9692           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
9693       if(tempCount = 0) then
9694         select ame_temp_transactions_s.nextval into tempTransSeqId from dual;
9695         insert into ame_temp_transactions(
9696           application_id,
9697           transaction_id,
9698           row_timestamp,
9699           temp_transactions_id
9700           ) values(
9701             engAmeApplicationId,
9702             engTransactionId,
9703             sysdate,
9704             tempTransSeqId); /* Don't use engEffectiveRuleDate here. */
9705       end if;
9706       exception
9707         when others then
9708           ame_util.runtimeException(packageNameIn => 'ame_engine',
9709                                     routineNameIn => 'logTransaction',
9710                                     exceptionNumberIn => sqlcode,
9711                                     exceptionStringIn => sqlerrm);
9712           raise;
9713     end logTransaction;
9714   procedure parseFields(stringIn in varchar2,
9715                         fieldsOut out nocopy ame_util.longStringList) as
9716     fieldEnd integer;
9717     fieldIndex integer;
9718     fieldStart integer;
9719     stringLength integer;
9720     begin
9721       stringLength := lengthb(stringIn);
9722       fieldStart := 1;
9723       fieldIndex := 1; /* post-increment */
9724       loop
9725         fieldEnd := instrb(stringIn, ame_util.fieldDelimiter, fieldStart, 1);
9726         if(fieldEnd = 0) then
9727           fieldsOut(fieldIndex) := substrb(stringIn, fieldStart);
9728           exit;
9729         end if;
9730         fieldsOut(fieldIndex) := substrb(stringIn, fieldStart, fieldEnd - fieldStart);
9731         fieldIndex := fieldIndex + 1;
9732         fieldStart := fieldEnd + 1;
9733       end loop;
9734       exception
9735         when others then
9736           ame_util.runtimeException(packageNameIn => 'ame_engine',
9737                                     routineNameIn => 'parseFields',
9738                                     exceptionNumberIn => sqlcode,
9739                                     exceptionStringIn => sqlerrm);
9740           raise;
9741     end parseFields;
9742   procedure parseForwardingBehaviors(forwardingBehaviorsIn in varchar2) as
9743     startPosition integer;
9744     valueLength integer;
9745     begin
9746       startPosition := 1;
9747       for i in 1 .. 8 loop
9748         if(i = 8) then
9749           valueLength := lengthb(substrb(forwardingBehaviorsIn, startPosition));
9750         else
9751           valueLength := instrb(forwardingBehaviorsIn, ':', startPosition + 1, 1) - startPosition;
9752         end if;
9753         engForwardingBehaviors(i) := substrb(forwardingBehaviorsIn, startPosition, valueLength);
9754         startPosition := startPosition + valueLength + 1;
9755       end loop;
9756       exception
9757         when others then
9758           ame_util.runtimeException(packageNameIn => 'ame_engine',
9759                                     routineNameIn => 'parseForwardingBehaviors',
9760                                     exceptionNumberIn => sqlcode,
9761                                     exceptionStringIn => sqlerrm);
9762           raise;
9763     end parseForwardingBehaviors;
9764   procedure parsePriorityModes(priorityModesIn in varchar2) as
9765     currentValue ame_util.stringType;
9766     endPosition integer;
9767     startPosition integer;
9768     underscorePosition integer;
9769     begin
9770       /*
9771         The i - 1 indexes on the left side of the assignments account
9772         for the rule-type constants starting at zero.
9773       */
9774       startPosition := 1;
9775       for i in 1 .. 8 loop
9776         if(i < 8) then
9777           endPosition := instrb(priorityModesIn, ':', startPosition, 1) - 1;
9778         else
9779           endPosition := lengthb(priorityModesIn);
9780         end if;
9781         currentValue := substrb(priorityModesIn, startPosition, endPosition - startPosition + 1);
9782         underscorePosition := instrb(currentValue, '_', 1, 1);
9783         if(underscorePosition = 0) then
9784           engPriorityModes(i - 1) := ame_util.disabledRulePriority;
9785           engPriorityThresholds(i - 1) := null;
9786         else
9787           engPriorityThresholds(i - 1) := to_number(substrb(currentValue, underscorePosition + 1));
9788           if(instrb(currentValue, ame_util.absoluteRulePriority, 1, 1) > 0) then
9789             engPriorityModes(i - 1) := ame_util.absoluteRulePriority;
9790           else
9791             engPriorityModes(i - 1) := ame_util.relativeRulePriority;
9792           end if;
9793         end if;
9794         startPosition := endPosition + 2;
9795       end loop;
9796       exception
9797         when others then
9798           ame_util.runtimeException(packageNameIn => 'ame_engine',
9799                                     routineNameIn => 'parsePriorityModes',
9800                                     exceptionNumberIn => sqlcode,
9801                                     exceptionStringIn => sqlerrm);
9802           raise;
9803     end parsePriorityModes;
9804   procedure populateEngStVariables as
9805     headerItemRejected boolean;
9806     itemIds            ame_util.stringList;
9807     itemClasses        ame_util.stringList;
9808     tempItemClass      ame_util.stringType;
9809     tempItemId         ame_util.stringType;
9810     tempItemIndex      integer;
9811     tempPseudoBoolean  ame_util.charType;
9812     stoppingRule       ame_util.stringType;
9813     itemRejected       boolean;
9814     tempCount          integer;
9815     begin
9816       /*
9817         The procedure processRepeatedApprovers populates most of the engSt variables, to synchronize
9818         that work with the repeatedApprovers functionality, for efficiency.  This procedure just
9819         populates engStApprovalProcessCompleteYN, engStItemAppProcessCompleteYN, engStProductionIndexes,
9820         engStVariableNames, and engStVariableValues.  Note that this procedure should execute after
9821         processRepeatedApprovers, so it can treat repeated approvers as having approved in the
9822         calculation of the approval-process-complete values.
9823       */
9824       /* Initialize various values. */
9825       itemRejected := false;
9826       engStApprovalProcessCompleteYN := ame_util2.completeNoApprovers;
9827       for i in 1 .. engItemIds.count loop
9828         engStItemAppProcessCompleteYN(i) := ame_util2.completeNoApprovers;
9829       end loop;
9830       /* Handle the empty-approver-list case first. */
9831       if(engStApprovers.count = 0) then
9832         return;
9833       end if;
9834       /* get all itemclasses and itemids of current transaction */
9835       getAllItemClasses(itemClassNamesOut => itemClasses);
9836       getAllItemIds(itemIdsOut            => itemIds);
9837       /*
9838         The approver list is non-empty.  Set the process-complete values per the statuses in
9839         engStApprovers;
9840       */
9841       /* modified the values of approvalProcessCompleteYN as per bug 4411016 */
9842       /* Initialize the temp variables. */
9843       tempItemId := engStApprovers(1).item_id;
9844       tempItemClass := engStApprovers(1).item_class;
9845       for i in 1 .. itemIds.count loop
9846         if(itemIds(i) = tempItemId and itemClasses(i) = tempItemClass) then
9847           tempItemIndex := i;
9848           engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyApproved;
9849           if engStApprovalProcessCompleteYN = ame_util2.completeNoApprovers then
9850             engStApprovalProcessCompleteYN := ame_util2.completeFullyApproved;
9851           end if;
9852           exit;
9853         end if;
9854       end loop;
9855       tempPseudoBoolean := ame_util.booleanTrue;
9856       /* Loop through the approvers. */
9857       for i in 1 .. engStApprovers.count loop
9858         /* Update the temp variables when the item changes. */
9859         if(engStApprovers(i).item_id <> tempItemId or
9860            engStApprovers(i).item_class <> tempItemClass) then
9861           tempItemId := engStApprovers(i).item_id;
9862           tempItemClass := engStApprovers(i).item_class;
9863           tempPseudoBoolean := ame_util.booleanTrue;
9864           for j in (tempItemIndex + 1) .. itemIds.count loop
9865             if(itemIds(j) = tempItemId and itemClasses(j) = tempItemClass) then
9866               tempItemIndex := j;
9867               engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyApproved;
9868               if engStApprovalProcessCompleteYN = ame_util2.completeNoApprovers then
9869                 engStApprovalProcessCompleteYN := ame_util2.completeFullyApproved;
9870               end if;
9871               exit;
9872             end if;
9873           end loop;
9874         end if;
9875         /* Update the process-complete engSt variables as appropriate. */
9876         -- check for pending/yet to be notified approvers
9877         if(engStItemAppProcessCompleteYN(tempItemIndex) <> ame_util2.completeFullyRejected and
9878            ((engStApprovers(i).approver_category = ame_util.approvalApproverCategory and
9879              (engStApprovers(i).approval_status is null or
9880               engStApprovers(i).approval_status in (ame_util.nullStatus
9881                                                    ,ame_util.notifiedStatus
9882                                                    ,ame_util.repeatedStatus
9883                                                    ,ame_util.notifiedByRepeatedStatus))) or
9884             (engStApprovers(i).approver_category = ame_util.fyiApproverCategory and
9885              (engStApprovers(i).approval_status is null or
9886              engStApprovers(i).approval_status = ame_util.nullStatus)))) then
9887           if engStItemAppProcessCompleteYN(tempItemIndex) in (ame_util2.completeNoApprovers
9888                                                              ,ame_util2.completeFullyApproved) then
9889             engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.notCompleted;
9890             if engStApprovalProcessCompleteYN in (ame_util2.completeNoApprovers
9891                                                  ,ame_util2.completeFullyApproved) then
9892               engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9893             end if;
9894           end if;
9895         end if;
9896         -- check for rejections
9897         if(engStApprovers(i).approver_category = ame_util.approvalApproverCategory and
9898            engStApprovers(i).approval_status in (ame_util.rejectStatus,ame_util.rejectedByRepeatedStatus)) then
9899           itemRejected := true;
9900           if tempItemClass = ame_util.headerItemClassName then
9901             headerItemRejected := true;
9902           end if;
9903           engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyRejected;
9904         end if;
9905       end loop;
9906 
9907       if itemRejected then
9908         stoppingRule := ame_engine.getHeaderAttValue2
9909                           (attributeNameIn => ame_util.rejectionResponseAttribute);
9910         if stoppingRule is null or stoppingRule not in (ame_util.stopAllItems,ame_util.continueOtherSubItems,
9911                                                         ame_util.continueAllOtherItems) then
9912            stoppingRule := ame_util.stopAllItems;
9913         end if;
9914         -- When the stoppingRule is STOP_ALL_ITEMS or a header item got rejected then
9915         -- 1. The transaction as a whole is rejected.
9916         -- 2. Make all pending items approval status rejected.
9917         if stoppingRule = ame_util.stopAllItems or headerItemRejected then
9918           engStApprovalProcessCompleteYN := ame_util2.completeFullyRejected;
9919           --+
9920           for x in 1 .. itemIds.count loop
9921             if engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9922               engStItemAppProcessCompleteYN(x) := ame_util2.completeFullyRejected;
9923             end if;
9924           end loop;
9925           --+
9926         end if;
9927         -- When the stoppingRule is CONTINUE_OTHER_SUBORDINATE_ITEMS or
9928         -- CONTINUE_ALL_OTHER_ITEMS then
9929         -- 1. Reject header item if stoppingRule is CONTINUE_OTHER_SUBORDINATE_ITEMS
9930         --    and header item is pending.
9931         -- 2. Set the transaction level status to partially rejected by default.
9932         -- 3. If any other item is still pending set the approval status of
9933         --    transaction to pending status.
9934         -- 4. If the transaction level status is still partially rejected then
9935         --    check for complete rejection. Complete rejection will happen if all items
9936         --    are rejected or have no approvers.
9937         if stoppingRule = ame_util.continueOtherSubItems or
9938            stoppingRule = ame_util.continueAllOtherItems then
9939           if stoppingRule = ame_util.continueOtherSubItems then
9940             for x in 1 .. itemIds.count loop
9941               if itemClasses(x) = ame_util.headerItemClassName and
9942                  engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9943                 engStItemAppProcessCompleteYN(x) := ame_util2.completeFullyRejected;
9944                 exit;
9945               end if;
9946             end loop;
9947           end if;
9948           engStApprovalProcessCompleteYN := ame_util2.completePartiallyApproved;
9949           for x in 1 .. itemIds.count loop
9950             if engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9951               engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9952               exit;
9953             end if;
9954           end loop;
9955           tempCount := 0;
9956           if engStApprovalProcessCompleteYN = ame_util2.completePartiallyApproved then
9957             for x in 1 .. itemIds.count loop
9958               if engStItemAppProcessCompleteYN(x) <> ame_util2.completeFullyRejected and
9959                  engStItemAppProcessCompleteYN(x) <> ame_util2.completeNoApprovers then
9960                 exit;
9961               end if;
9962               tempCount := tempCount + 1;
9963             end loop;
9964             if tempCount = itemIds.count then
9965               engStApprovalProcessCompleteYN := ame_util2.completeFullyRejected;
9966             end if;
9967           end if;
9968         end if;
9969       end if;
9970       if(engSATOFlag = 'Y') then
9971         engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9972       end if;
9973       exception
9974         when others then
9975           ame_util.runtimeException(packageNameIn => 'ame_engine',
9976                                     routineNameIn => 'populateEngStVariables',
9977                                     exceptionNumberIn => sqlcode,
9978                                     exceptionStringIn => sqlerrm);
9979           raise;
9980     end populateEngStVariables;
9981   procedure processAdHocInsertions as
9982     displacedInserteeIndexes ame_util.idList;
9983     engStApproversCount integer;
9984     parameterFields ame_util.longStringList;
9985     tempAnchorIndex integer;
9986     tempBoolean boolean;
9987     tempIndex integer;
9988     tempIndex2 integer;
9989     tempItemClass ame_temp_insertions.item_class%type;
9990     tempItemId ame_temp_insertions.item_id%type;
9991     tempOrderType ame_temp_insertions.order_type%type;
9992     l_error_code number;
9993     errorCode integer;
9994     errorMessage ame_util.longestStringType;
9995     begin
9996       /*
9997         This procedure generally must populate the following ame_util.approverRecord2 fields,
9998         for each inserted approver:
9999           orig_system
10000           orig_system_id
10001           display_name
10002           action_type_id
10003           group_or_chain_id
10004           occurrence
10005           source
10006           approval_status
10007           item_class_order_number
10008           item_order_number
10009           sub_list_order_number
10010           action_type_order_number
10011           group_or_chain_order_number
10012           member_order_number
10013         The first three of these fields get populated at the beginning of the outermost loop below.
10014         The other fields get populated just before the actual insertion occurs.  This procedure must
10015         therefore decide how to set the order-number fields.  The procedure attempts to set the
10016         order numbers consistent with the order relation of the insertion, where the order relation
10017         anchors the insertion to the approver preceeding or following the insertion in engStApprovers.
10018         See the comments near specific insertApprover calls below.
10019       */
10020       engStApproversCount := engStApprovers.count;
10021       for i in 1 .. engInsertedApproverList.count loop
10022         if(engInsertedApproverList(i).authority <> ame_util.authorityApprover or
10023            engInsertedApproverList(i).api_insertion = ame_util.apiInsertion) then
10024           begin
10025            ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
10026                                                               origSystemOut => engInsertedApproverList(i).orig_system,
10027                                                               origSystemIdOut => engInsertedApproverList(i).orig_system_id,
10028                                                               displayNameOut => engInsertedApproverList(i).display_name);
10029           exception
10030             when others then
10031               l_error_code := sqlcode;
10032               if l_error_code = -20213 then
10033                 if engInsertedApproverList(i).approval_status is null then
10034                   errorCode := -20219;
10035                   errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
10036                                               messageNameIn => 'AME_400837_INV_APR_FOUND',
10037                                               tokenNameOneIn  => 'PROCESS_NAME',
10038                                               tokenValueOneIn => 'ame_engine.processAdHocInsertions',
10039                                               tokenNameTwoIn => 'NAME',
10040                                               tokenValueTwoIn => engInsertedApproverList(i).name);
10041                   raise_application_error(errorCode,errorMessage);
10042                   raise;
10043                 end if;
10044                 engInsertedApproverList(i).orig_system := 'AME_INS_ORIG_SYSTEM';
10045               end if;
10046           end;
10047           parameterFields.delete;
10048           parseFields(stringIn => engInsertionParameterList(i),
10049                       fieldsOut => parameterFields);
10050           /* absoluteOrder */
10051           if(engInsertionOrderTypeList(i) = ame_util.absoluteOrder) then
10052             tempIndex := engInsertionParameterList(i);
10053             if(tempIndex > engStApprovers.count + 1) then
10054               tempIndex := engStApprovers.count + 1;
10055             end if;
10056             engInsertedApproverList(i).source := ame_util.otherInsertion;
10057             if(engStApprovers.exists(tempIndex - 1)  and
10058                engStApprovers(tempIndex - 1).authority = engInsertedApproverList(i).authority and
10059                engStApprovers(tempIndex - 1).item_class = engInsertedApproverList(i).item_class and
10060                engStApprovers(tempIndex - 1).item_id = engInsertedApproverList(i).item_id
10061                ) then
10062               /* Group the insertion with the preceeding approver in engStApprovers. */
10063               engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex - 1).action_type_id;
10064               engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex - 1).group_or_chain_id;
10065               engInsertedApproverList(i).occurrence :=
10066                 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10067                                      itemClassIn => engInsertedApproverList(i).item_class,
10068                                      itemIdIn => engInsertedApproverList(i).item_id,
10069                                      actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10070                                      groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10071               engInsertedApproverList(i).item_class_order_number :=
10072                 engStApprovers(tempIndex - 1).item_class_order_number;
10073               engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex - 1).item_order_number;
10074               engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex - 1).sub_list_order_number;
10075               engInsertedApproverList(i).action_type_order_number :=
10076                 engStApprovers(tempIndex - 1).action_type_order_number;
10077               engInsertedApproverList(i).group_or_chain_order_number :=
10078                 engStApprovers(tempIndex - 1).group_or_chain_order_number;
10079             elsif(engStApprovers.exists(tempIndex)) then
10080               /* Group the insertion with the following approver in engStApprovers. */
10081               engInsertedApproverList(i).authority := engStApprovers(tempIndex).authority;
10082               engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex).action_type_id;
10083               engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
10084               engInsertedApproverList(i).occurrence :=
10085                 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10086                                      itemClassIn => engInsertedApproverList(i).item_class,
10087                                      itemIdIn => engInsertedApproverList(i).item_id,
10088                                      actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10089                                      groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10090               engInsertedApproverList(i).item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
10091               engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex).item_order_number;
10092               engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
10093               engInsertedApproverList(i).action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
10094               engInsertedApproverList(i).group_or_chain_order_number :=
10095                 engStApprovers(tempIndex).group_or_chain_order_number;
10096             else
10097               /* engStApprovers must be empty. */
10098               engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId;
10099               engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10100               engInsertedApproverList(i).occurrence := 1;
10101               engInsertedApproverList(i).item_class_order_number :=
10102                 getItemClassOrderNumber(itemClassIdIn =>
10103                   getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
10104               engInsertedApproverList(i).item_order_number :=
10105                 getItemOrderNumber(itemClassNameIn => engInsertedApproverList(i).item_class,
10106                                    itemIdIn => engInsertedApproverList(i).item_id);
10107               engInsertedApproverList(i).sub_list_order_number :=
10108                 getSublistOrderNum(itemClassNameIn => ame_util.headerItemClassName,
10109                                    authorityIn => ame_util.postApprover);
10110               engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
10111               engInsertedApproverList(i).group_or_chain_order_number := 1;
10112             end if;
10113             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10114               fnd_log.string
10115                 (fnd_log.level_statement
10116                 ,'ame_engine.processAdhocInsertions'
10117                 ,'Adhoc Insertion approver(absolute order) ::: ' || engInsertedApproverList(i).name
10118                 );
10119             end if;
10120             insertApprover(indexIn => tempIndex,
10121                            approverIn => engInsertedApproverList(i),
10122                            adjustMemberOrderNumbersIn => true,
10123                            inserteeIndexIn => i,
10124                            currentInsIndex => i);
10125             populateInsertionIndexes(indexIn => tempIndex
10126                                     ,insertionOrderIn => engInsertionOrderList(i));
10127             engStApproversCount := engStApproversCount + 1;
10128           /* afterApprover, beforeApprover */
10129           elsif(engInsertionOrderTypeList(i) in (ame_util.afterApprover,
10130                                                  ame_util.beforeApprover)) then
10131             tempIndex := 1; /* post-increment */
10132             loop
10133               tempBoolean := false;
10134               /*
10135                 In this loop, tempBoolean indicates whether engStApprovers(tempIndex) matches
10136                 the insertion parameter.
10137               */
10138               if(engStApprovers(tempIndex).name = parameterFields(1) and
10139                  engStApprovers(tempIndex).occurrence = parameterFields(6) and
10140                  engStApprovers(tempIndex).group_or_chain_id = parameterFields(5) and
10141                  engStApprovers(tempIndex).action_type_id = parameterFields(4) and
10142                  engStApprovers(tempIndex).item_id = parameterFields(3) and
10143                  engStApprovers(tempIndex).item_class = parameterFields(2)) then
10144                 tempBoolean := true;
10145                 if(engInsertionOrderTypeList(i) = ame_util.afterApprover) then
10146                   tempIndex2 := tempIndex + 1;
10147                 else
10148                   tempIndex2 := tempIndex;
10149                 end if;
10150                 engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex).action_type_id;
10151                 engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
10152                 engInsertedApproverList(i).occurrence :=
10153                   getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10154                                        itemClassIn => engInsertedApproverList(i).item_class,
10155                                        itemIdIn => engInsertedApproverList(i).item_id,
10156                                        actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10157                                        groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10158                 if(engInsertionIsSpecialForwardee(i) = ame_util.booleanTrue) then
10159                   engInsertedApproverList(i).source := ame_util.specialForwardInsertion;
10160                 else
10161                   if(engInsertionOrderTypeList(i) = ame_util.afterApprover and
10162                      engStApprovers(tempIndex).approval_status = ame_util.forwardStatus) then
10163                     engInsertedApproverList(i).source := ame_util.forwardInsertion;
10164                   elsif(engInsertionOrderTypeList(i) = ame_util.afterApprover and
10165                         engStApprovers(tempIndex).approval_status = ame_util.approveAndForwardStatus) then
10166                     engInsertedApproverList(i).source := ame_util.approveAndForwardInsertion;
10167                   else
10168                     engInsertedApproverList(i).source := ame_util.otherInsertion;
10169                   end if;
10170                 end if;
10171                 engInsertedApproverList(i).item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
10172                 engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex).item_order_number;
10173                 engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
10174                 engInsertedApproverList(i).action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
10175                 engInsertedApproverList(i).group_or_chain_order_number :=
10176                   engStApprovers(tempIndex).group_or_chain_order_number;
10177                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10178                   fnd_log.string
10179                     (fnd_log.level_statement
10180                     ,'ame_engine.processAdhocInsertions'
10181                     ,'Adhoc Insertion approver(after/before approver) ::: ' || engInsertedApproverList(i).name
10182                     );
10183                 end if;
10184                 insertApprover(indexIn => tempIndex2,
10185                                approverIn => engInsertedApproverList(i),
10186                                adjustMemberOrderNumbersIn => true,
10187                                inserteeIndexIn => i,
10188                                currentInsIndex => i);
10189                 populateInsertionIndexes(indexIn => tempIndex2
10190                                         ,insertionOrderIn => engInsertionOrderList(i));
10191                 engStApproversCount := engStApproversCount + 1;
10192               end if;
10193               if(tempBoolean or
10194                  tempIndex = engStApproversCount) then
10195                 exit;
10196               end if;
10197               tempIndex := tempIndex + 1;
10198             end loop;
10199           else /* first/last pre/post approver */
10200             /*
10201               The source, action_type_id, and group_or_chain_id fields are set in
10202               ame_api3.getAvailableInsertions for these order types.
10203             */
10204             if(engStApproversCount = 0) then
10205               /*
10206                 The four first/last pre/post order types can only occur in an empty list if the insertion
10207                 is for the header item.  Treat any other case of these order types as displaced, here.
10208                 In the code blocks below for these four order types, require that engStApproversCount > 0.
10209               */
10210               if(parameterFields(3) = ame_util.headerItemClassName and
10211                  parameterFields(2) = engTransactionId) then
10212                 engInsertedApproverList(i).occurrence := 1;
10213                 engInsertedApproverList(i).item_class_order_number :=
10214                   getItemClassOrderNumber(itemClassIdIn =>
10215                     getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
10216                 engInsertedApproverList(i).item_order_number := 1;
10217                 engInsertedApproverList(i).sub_list_order_number :=
10218                   getSublistOrderNum(itemClassNameIn => ame_util.headerItemClassName,
10219                                      authorityIn => engInsertedApproverList(i).authority);
10220                 engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
10221                 engInsertedApproverList(i).group_or_chain_order_number := 1;
10222                 engInsertedApproverList(i).member_order_number := 1;
10223                 insertApprover(indexIn => 1,
10224                                approverIn => engInsertedApproverList(i),
10225                                adjustMemberOrderNumbersIn => false,
10226                                inserteeIndexIn => i,
10227                                currentInsIndex => i);
10228                 populateInsertionIndexes(indexIn => 1
10229                                         ,insertionOrderIn => engInsertionOrderList(i));
10230                 engStApproversCount := 1;
10231               else /* displaced */
10232                 engInsertedApproverList(i).occurrence := 1;
10233                 engInsertedApproverList(i).item_class_order_number :=
10234                   getItemClassOrderNumber(itemClassIdIn =>
10235                     getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
10236                 engInsertedApproverList(i).item_order_number := 1;
10237                 engInsertedApproverList(i).sub_list_order_number :=
10238                   getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10239                                      authorityIn => engInsertedApproverList(i).authority);
10240                 engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
10241                 engInsertedApproverList(i).group_or_chain_order_number := 1;
10242                 engInsertedApproverList(i).member_order_number := 1;
10243                 displacedInserteeIndexes(displacedInserteeIndexes.count + 1) := i;
10244               end if;
10245             else
10246               tempIndex := null;
10247               tempAnchorIndex := null;
10248               /* firstPostApprover */
10249               if(engInsertionOrderTypeList(i) = ame_util.firstPostApprover) then
10250                 /*
10251                   Insert at tempIndex if it's non-null, after checking the possible cases.
10252                   Recall that the case where engStApproversCount = 0 is handled at the
10253                   start of the procedure, that the item id is in parameterFields(3), and
10254                   that the item-class ID is in parameterFields(2).  Here are the cases
10255                   requiring insertion (always at j + 1).
10256                   1.  j = 0,
10257                       post-approver for the right item at j + 1 = 1
10258                   2.  j > 0,
10259                       j < engStApproversCount,
10260                       non-post-approver for the right item at j,
10261                       post-approver for the right item at j + 1
10262                   3.  j > 0,
10263                       j < engStApproversCount,
10264                       non-post-approver for the right item at j,
10265                       any approver for the wrong item at j + 1
10266                   4.  j > 0,
10267                       j = engStApproversCount,
10268                       non-post-approver for the right item at j
10269                   5.  j > 0,
10270                       j < engStApproversCount,
10271                       any approver for the wrong item at j,
10272                       post-approver for the right item at j + 1
10273                   Finally, note that the way the code is written, case 4 must be checked
10274                   before cases 2, 3, and 5, to ensure that for these cases,
10275                   j + 1 <= engStApproversCount.
10276                 */
10277                 /* The zero lower limit is intentional. */
10278                 for j in 0 .. engStApproversCount loop
10279                   tempIndex2 := j + 1;
10280                   if(j = 0) then /* case 1 */
10281                     if(engStApprovers(tempIndex2).authority = ame_util.postApprover and
10282                        engStApprovers(tempIndex2).item_id = parameterFields(3) and
10283                        engStApprovers(tempIndex2).item_class = parameterFields(2)) then
10284                       tempIndex := tempIndex2;
10285                       tempAnchorIndex := tempIndex2;
10286                       exit;
10287                     end if;
10288                   else /* j > 0:  cases 2-5 */
10289                     /*
10290                       non-post-approver for the right item at j:  cases 2-4
10291                       Case 4 comes before the others to prevent indexing into a non-existent
10292                       engStApprovers(tempIndex2) when j = engStApproversCount.
10293                     */
10294                     if(engStApprovers(j).authority <> ame_util.postApprover and
10295                        engStApprovers(j).item_id = parameterFields(3) and
10296                        engStApprovers(j).item_class = parameterFields(2)) then
10297                       if(j = engStApproversCount) then /* case 4 */
10298                         tempIndex := tempIndex2;
10299                         exit;
10300                       end if;
10301                       if(engStApprovers(tempIndex2).authority = ame_util.postApprover and
10302                          engStApprovers(tempIndex2).item_id = parameterFields(3) and
10303                          engStApprovers(tempIndex2).item_class = parameterFields(2)) then /* case 2 */
10304                         tempIndex := tempIndex2;
10305                         tempAnchorIndex := tempIndex2;
10306                         exit;
10307                       end if;
10308                       if(engStApprovers(tempIndex2).item_id <> parameterFields(3) or
10309                          engStApprovers(tempIndex2).item_class <> parameterFields(2)) then /* case 3 */
10310                         tempIndex := tempIndex2;
10311                         exit;
10312                       end if;
10313                       if((engStApprovers(j).item_id <> parameterFields(3) or
10314                           engStApprovers(j).item_class <> parameterFields(2)) and
10315                          engStApprovers(tempIndex2).authority = ame_util.postApprover and
10316                          engStApprovers(tempIndex2).item_id = parameterFields(3) and
10317                          engStApprovers(tempIndex2).item_class = parameterFields(2)) then /* case 5 */
10318                         tempIndex := tempIndex2;
10319                         tempAnchorIndex := tempIndex2;
10320                         exit;
10321                       end if;
10322                     end if;
10323                   end if;
10324                 end loop;
10325               /* firstPreApprover */
10326               elsif(engInsertionOrderTypeList(i) = ame_util.firstPreApprover) then
10327                 /*
10328                   Insert at tempIndex if it's non-null, after checking the possible cases.
10329                   Recall that the case where engStApproversCount = 0 is handled at the
10330                   start of the procedure.  Here are the cases requiring insertion (always
10331                   at j).
10332                   1.  j = 1,
10333                       any approver for the right item at j = 1
10334                   2.  j > 1,
10335                       any approver for the wrong item at j - 1,
10336                       any approver for the right item at j
10337                 */
10338                 for j in 1 .. engStApproversCount loop
10339                   if(j = 1) then
10340                     if(engStApprovers(1).item_id = parameterFields(3) and
10341                        engStApprovers(1).item_class = parameterFields(2)) then /* case 1 */
10342                       tempIndex := 1;
10343                       if(engStApprovers(1).authority = ame_util.preApprover) then
10344                         tempAnchorIndex := 1;
10345                       end if;
10346                       exit;
10347                     end if;
10348                   elsif((engStApprovers(j - 1).item_id <> parameterFields(3) or
10349                          engStApprovers(j - 1).item_class <> parameterFields(2)) and
10350                         engStApprovers(j).item_id = parameterFields(3) and
10351                         engStApprovers(j).item_class = parameterFields(2)) then /* case 2 */
10352                     tempIndex := j;
10353                     if(engStApprovers(j).authority = ame_util.preApprover) then
10354                       tempAnchorIndex := j;
10355                     end if;
10356                     exit;
10357                   end if;
10358                 end loop;
10359               /* lastPostApprover */
10360               elsif(engInsertionOrderTypeList(i) = ame_util.lastPostApprover) then
10361                 /*
10362                   Insert at tempIndex if it's non-null, after checking the possible cases.
10363                   Recall that the case where engStApproversCount = 0 is handled at the
10364                   start of the procedure.  Here are the cases requiring insertion (always
10365                   at j + 1).
10366                   1.  j = engStApproversCount,
10367                       any approver for the right item at j
10368                   2.  j < engStApproversCount,
10369                       any approver for right item at j,
10370                       any approver for wrong item at j + 1
10371                 */
10372                 for j in 1 .. engStApproversCount loop
10373                   if(j = engStApproversCount) then
10374                     if(engStApprovers(j).item_id = parameterFields(3) and
10375                        engStApprovers(j).item_class = parameterFields(2)) then
10376                       tempIndex := engStApproversCount + 1;
10377                       if(engStApprovers(j).authority = ame_util.postApprover) then
10378                         tempAnchorIndex := j;
10379                       end if;
10380                       exit;
10381                     end if;
10382                   else
10383                     if(engStApprovers(j).item_id = parameterFields(3) and
10384                        engStApprovers(j).item_class = parameterFields(2) and
10385                        (engStApprovers(j + 1).item_id <> parameterFields(3) or
10386                        engStApprovers(j + 1).item_class <> parameterFields(2))) then
10387                       tempIndex := j + 1;
10388                       if(engStApprovers(j).authority = ame_util.postApprover) then
10389                         tempAnchorIndex := j;
10390                       end if;
10391                       exit;
10392                     end if;
10393                   end if;
10394                 end loop;
10395               /* lastPreApprover */
10396               else /* engInsertionOrderTypeList(i) = ame_util.lastPreApprover */
10397                 /*
10398                   Insert at tempIndex if it's non-null, after checking the possible cases.
10399                   Recall that the case where engStApproversCount = 0 is handled at the
10400                   start of the procedure.  Here are the cases (always inserting at j):
10401                   1.  j = 1,
10402                       non-pre-approver for the right item at 1
10403                   2.  j > 1,
10404                       j <= engStApproversCount,
10405                       the approver at j - 1 is for the right item,
10406                       the approver at j is for the right item,
10407                       the approver at j - 1 is a pre-approver,
10408                       the approver at j is not a pre-approver
10409                   3.  j > 1,
10410                       j <= engStApproversCount,
10411                       any approver at j - 1 for the wrong item,
10412                       the approver at j is for the right item,
10413                       the approver at j is not a pre-approver
10414                 */
10415                 for j in 1 .. engStApproversCount loop
10416                   if(j = 1) then
10417                     if(engStApprovers(1).item_id = parameterFields(3) and
10418                        engStApprovers(1).item_class = parameterFields(2) and
10419                        engStApprovers(1).authority <> ame_util.preApprover) then /* case 1 */
10420                       tempIndex := 1;
10421                       exit;
10422                     end if;
10423                   else
10424                     if(engStApprovers(j).item_id = parameterFields(3) and
10425                        engStApprovers(j).item_class = parameterFields(2) and
10426                        engStApprovers(j).authority <> ame_util.preApprover) then
10427                       if(engStApprovers(j - 1).item_id = parameterFields(3) and
10428                          engStApprovers(j - 1).item_class = parameterFields(2)) then
10429                         if(engStApprovers(j - 1).authority = ame_util.preApprover) then /* case 2 */
10430                           tempIndex := j;
10431                           tempAnchorIndex := j - 1;
10432                           exit;
10433                         end if;
10434                       else /* case 3 */
10435                         tempIndex := j;
10436                         exit;
10437                       end if;
10438                     end if;
10439                   end if;
10440                 end loop;
10441               end if;
10442               /* Set the remaining fields in the insertee's approverRecord2. */
10443               engInsertedApproverList(i).source := ame_util.otherInsertion;
10444               if(tempAnchorIndex is null) then
10445                 engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10446                 /* This code was commented out to fix BUG (4095846)                                 */
10447                 /* Issue 9 in the list of bugs identified during implementation of                  */
10448                 /* asynchronous parallel approver functionality                                     */
10449                 /* engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId; */
10450                 engInsertedApproverList(i).occurrence :=
10451                   getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10452                                        itemClassIn => engInsertedApproverList(i).item_class,
10453                                        itemIdIn => engInsertedApproverList(i).item_id,
10454                                        actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10455                                        groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10456                 engInsertedApproverList(i).item_class_order_number :=
10457                   getItemClassOrderNumber(itemClassIdIn =>
10458                     getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
10459                 engInsertedApproverList(i).item_order_number :=
10460                   getItemOrderNumber(itemClassNameIn => engInsertedApproverList(i).item_class,
10461                                                  itemIdIn => engInsertedApproverList(i).item_id);
10462                 /* Code Modified to fix BUG (4095825)                              */
10463                 /* Issue 2 in the list of bugs identified during implementation of */
10464                 /* asynchronous parallel approver functionality                    */
10465                 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10466                         engInsertionOrderTypeList(i) = ame_util.lastPreApprover then
10467                   engInsertedApproverList(i).sub_list_order_number :=
10468                     getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10469                                        authorityIn => ame_util.preApprover);
10470                 elsif engInsertionOrderTypeList(i) = ame_util.firstPostApprover or
10471                         engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10472                   engInsertedApproverList(i).sub_list_order_number :=
10473                     getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10474                                        authorityIn => ame_util.postApprover);
10475                 end if;
10476                 /* Code Modified to fix BUG (4095846)                                                   */
10477                 /* Issue 9 in the list of bugs identified during implementation of                      */
10478                 /* asynchronous parallel approver functionality                                         */
10479                 /* engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber; */
10480                 engInsertedApproverList(i).action_type_order_number := 1;
10481                 engInsertedApproverList(i).group_or_chain_order_number := 1;
10482               else
10483                 engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10484                 /* Code Modified to fix BUG (4095846)                                              */
10485                 /* Issue 9 in the list of bugs identified during implementation of                 */
10486                 /* asynchronous parallel approver functionality                                    */
10487                 /* engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId;*/
10488                 engInsertedApproverList(i).occurrence :=
10489                   getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10490                                        itemClassIn => engInsertedApproverList(i).item_class,
10491                                        itemIdIn => engInsertedApproverList(i).item_id,
10492                                        actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10493                                        groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10494                 engInsertedApproverList(i).item_class_order_number :=
10495                   engStApprovers(tempAnchorIndex).item_class_order_number;
10496                 engInsertedApproverList(i).item_order_number :=
10497                   engStApprovers(tempAnchorIndex).item_order_number;
10498                 engInsertedApproverList(i).sub_list_order_number :=
10499                   engStApprovers(tempAnchorIndex).sub_list_order_number;
10500                 /* Code Modified to fix BUG (4095846)                                   */
10501                 /* Issue 9 in the list of bugs identified during implementation of      */
10502                 /* asynchronous parallel approver functionality                         */
10503                 /*engInsertedApproverList(i).action_type_order_number :=                */
10504                 /*  engStApprovers(tempAnchorIndex).action_type_order_number;           */
10505                 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10506                      engInsertionOrderTypeList(i) = ame_util.firstPostApprover then
10507                   engInsertedApproverList(i).action_type_order_number :=
10508                     engStApprovers(tempAnchorIndex).action_type_order_number - 1;
10509                 elsif engInsertionOrderTypeList(i) = ame_util.lastPreApprover or
10510                      engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10511                   engInsertedApproverList(i).action_type_order_number :=
10512                     engStApprovers(tempAnchorIndex).action_type_order_number + 1;
10513                 end if;
10514                 engInsertedApproverList(i).group_or_chain_order_number :=
10515                   engStApprovers(tempAnchorIndex).group_or_chain_order_number;
10516               end if;
10517               /* Perform the insertion if the proper position has been located. */
10518               if(tempIndex is null) then
10519                 displacedInserteeIndexes(displacedInserteeIndexes.count + 1) := i;
10520               else
10521                 /* Code Modified to fix BUG (4095846)                                   */
10522                 /* Issue 9 in the list of bugs identified during implementation of      */
10523                 /* asynchronous parallel approver functionality                         */
10524                 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10525                         engInsertionOrderTypeList(i) = ame_util.firstPostApprover then
10526                   engInsertedApproverList(i).action_type_id := -1;
10527                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10528                     fnd_log.string
10529                       (fnd_log.level_statement
10530                       ,'ame_engine.processAdhocInsertions'
10531                       ,'Adhoc Insertion approver(first pre/first post approver) ::: ' || engInsertedApproverList(i).name
10532                       );
10533                   end if;
10534                   insertApprover(indexIn => tempIndex,
10535                                  approverIn => engInsertedApproverList(i),
10536                                  adjustMemberOrderNumbersIn => true,
10537                                  approverLocationIn => ame_util.firstAmongEquals,
10538                                  inserteeIndexIn => i,
10539                                  currentInsIndex => i);
10540                   populateInsertionIndexes(indexIn => tempIndex
10541                                           ,insertionOrderIn => engInsertionOrderList(i));
10542                 elsif engInsertionOrderTypeList(i) = ame_util.lastPreApprover or
10543                         engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10544                   engInsertedApproverList(i).action_type_id := -2;
10545                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10546                     fnd_log.string
10547                       (fnd_log.level_statement
10548                       ,'ame_engine.processAdhocInsertions'
10549                       ,'Adhoc Insertion approver(last pre/last post approver) ::: ' || engInsertedApproverList(i).name
10550                       );
10551                   end if;
10552                   insertApprover(indexIn => tempIndex,
10553                                  approverIn => engInsertedApproverList(i),
10554                                  adjustMemberOrderNumbersIn => true,
10555                                  approverLocationIn => ame_util.lastAmongEquals,
10556                                  inserteeIndexIn => i,
10557                                  currentInsIndex => i);
10558                   populateInsertionIndexes(indexIn => tempIndex
10559                                           ,insertionOrderIn => engInsertionOrderList(i));
10560                 end if;
10561                 engStApproversCount := engStApproversCount + 1;
10562               end if;
10563             end if;
10564           end if;
10565         end if;
10566       end loop;
10567       /*
10568         Insert any displaced approvers at the end of their items' lists, if possible; and
10569         otherwise at the end of the transaction's list.
10570       */
10571       for i in 1 .. displacedInserteeIndexes.count loop
10572         parameterFields.delete;
10573         parseFields(stringIn => engInsertionParameterList(displacedInserteeIndexes(i)),
10574                     fieldsOut => parameterFields);
10575         /* Set tempBoolean false if displaced approver i is inserted at the end of its item's list. */
10576         tempBoolean := true;
10577         engStApproversCount := engStApprovers.count;
10578         for j in 1 .. engStApproversCount loop
10579           if(engStApprovers(j).item_id = parameterFields(2) and
10580              engStApprovers(j).item_class = parameterFields(3) and
10581              (j = engStApproversCount or
10582               engStApprovers(j + 1).item_id <> parameterFields(2) or
10583               engStApprovers(j + 1).item_class <> parameterFields(3))) then
10584             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10585               fnd_log.string
10586                 (fnd_log.level_statement
10587                 ,'ame_engine.processAdhocInsertions'
10588                 ,'Adhoc Insertion approver(displaced) ::: ' || engInsertedApproverList(displacedInserteeIndexes(i)).name
10589                 );
10590             end if;
10591             insertApprover(indexIn => j + 1,
10592                            approverIn => engInsertedApproverList(displacedInserteeIndexes(i)),
10593                            adjustMemberOrderNumbersIn => true,
10594                            inserteeIndexIn => i,
10595                            currentInsIndex => i);
10596             populateInsertionIndexes(indexIn => j + 1
10597                                     ,insertionOrderIn => engInsertionOrderList(displacedInserteeIndexes(i)));
10598             tempBoolean := false;
10599             exit;
10600           end if;
10601         end loop;
10602         if(tempBoolean) then
10603           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10604             fnd_log.string
10605               (fnd_log.level_statement
10606               ,'ame_engine.processAdhocInsertions'
10607               ,'Adhoc Insertion approver(displaced) ::: ' || engInsertedApproverList(displacedInserteeIndexes(i)).name
10608               );
10609           end if;
10610           insertApprover(indexIn => engStApproversCount + 1,
10611                          approverIn => engInsertedApproverList(displacedInserteeIndexes(i)),
10612                          adjustMemberOrderNumbersIn => false,
10613                          inserteeIndexIn => i,
10614                          currentInsIndex => i);
10615           populateInsertionIndexes(indexIn => engStApproversCount + 1
10616                                   ,insertionOrderIn => engInsertionOrderList(displacedInserteeIndexes(i)));
10617         end if;
10618         engStApproversCount := engStApproversCount + 1;
10619       end loop;
10620       for i in reverse 1..engStApprovers.count loop
10621         if engStApprovers(i).orig_system = 'AME_INS_ORIG_SYSTEM' then
10622           for j in i+1..engStApprovers.count loop
10623             engStApprovers(j-1) := engStApprovers(j);
10624           end loop;
10625           engStApprovers.delete(engStApprovers.count);
10626         end if;
10627       end loop;
10628       exception
10629         when others then
10630           ame_util.runtimeException(packageNameIn => 'ame_engine',
10631                                     routineNameIn => 'processAdHocInsertions',
10632                                     exceptionNumberIn => sqlcode,
10633                                     exceptionStringIn => sqlerrm);
10634           raise;
10635     end processAdHocInsertions;
10636   --+
10637   --
10638   --+
10639   procedure getAllProductions(productionsOut out nocopy ame_util2.productionsTable) is
10640     begin
10641       for i in 1 .. engStProductionsTable.count loop
10642         productionsOut(i).variable_name := engStProductionsTable(i).variable_name;
10643         productionsOut(i).variable_value := engStProductionsTable(i).variable_value;
10644         productionsOut(i).item_class := engStProductionsTable(i).item_class;
10645         productionsOut(i).item_id := engStProductionsTable(i).item_id;
10646       end loop;
10647     end getAllProductions;
10648   procedure getProductions(itemClassIn    in  varchar2
10649                           ,itemIdIn       in  varchar2
10650                           ,productionsOut out nocopy ame_util2.productionsTable) is
10651     tempIndex integer;
10652     begin
10653       tempIndex := 1;
10654       for i in 1 .. engStProductionsTable.count loop
10655         if itemClassIn = engStProductionsTable(i).item_class and
10656          itemIdIn    = engStProductionsTable(i).item_id then
10657           productionsOut(tempIndex).variable_name := engStProductionsTable(i).variable_name;
10658           productionsOut(tempIndex).variable_value := engStProductionsTable(i).variable_value;
10659           productionsOut(tempIndex).item_class := engStProductionsTable(i).item_class;
10660           productionsOut(tempIndex).item_id := engStProductionsTable(i).item_id;
10661           tempIndex := tempIndex+1;
10662         end if;
10663       end loop;
10664     end getProductions;
10665   procedure processActionType as
10666     tempIndex integer;
10667     begin
10668       if(engAppRuleTypes(engAppHandlerFirstIndex) = ame_util.productionRuleType) then
10669         /*
10670           Copy item-level productions to the appropriate engStProductionsTable.  Note that we
10671           have to initialize tempIndex as below to account for the possibility of multiple
10672           production action types.
10673         */
10674         tempIndex := engStProductionsTable.count;
10675         for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
10676           tempIndex := tempIndex + 1;
10677           engStProductionsTable(tempIndex).variable_name  := engAppParameters(i);
10678           engStProductionsTable(tempIndex).variable_value := engAppParameterTwos(i);
10679           engStProductionsTable(tempIndex).item_class     := getHandlerItemClassName;
10680           engStProductionsTable(tempIndex).item_id        := getHandlerItemId;
10681           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10682             fnd_log.string
10683               (fnd_log.level_statement
10684               ,'ame_engine.processActionType'
10685               ,'Transaction Production ::: ' || engStProductionsTable(tempIndex).variable_name || '/' || engStProductionsTable(tempIndex).variable_value
10686               );
10687           end if;
10688         end loop;
10689       /*
10690         This elsif is necessary to avoid processing production actions of approver-generating rules.
10691         (The engine processes these after constructing the approver list.)
10692       */
10693       elsif(engActionTypeUsages(engAppActionTypeIds(engAppHandlerFirstIndex)) <>
10694             ame_util.productionRuleType) then
10695         /*
10696           Call the handler for action types other than the production-rule action type.
10697           (Per-approver productions get handled later.)
10698         */
10699         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10700           fnd_log.string
10701             (fnd_log.level_statement
10702             ,'ame_engine.processActionType'
10703             ,'Processing Action Type ::: ' || engAppActionTypeIds(engAppHandlerFirstIndex)
10704             );
10705         end if;
10706         execute immediate
10707           'begin ' ||
10708           getActionTypePackageName(actionTypeIdIn => engAppActionTypeIds(engAppHandlerFirstIndex)) ||
10709           '.handler; end;';
10710       end if;
10711       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10712           fnd_log.string
10713             (fnd_log.level_statement
10714             ,'ame_engine.processActionType'
10715             ,'Completed processing the action Type ::: ' || engAppActionTypeIds(engAppHandlerFirstIndex)
10716             );
10717       end if;
10718       exception
10719         when others then
10720           ame_util.runtimeException(packageNameIn => 'ame_engine',
10721                                     routineNameIn => 'processActionType',
10722                                     exceptionNumberIn => sqlcode,
10723                                     exceptionStringIn => sqlerrm);
10724           raise;
10725     end processActionType;
10726   procedure populateInsertionIndexes(indexIn in integer
10727                                     ,insertionOrderIn in integer) as
10728     firstIndex integer;
10729     lastIndex integer;
10730     tempValue integer;
10731     begin
10732       firstIndex := engStInsertionIndexes.first;
10733       if(engStInsertionIndexes.exists(firstIndex)) then
10734         lastIndex := engStInsertionIndexes.last;
10735         while engStInsertionIndexes.exists(lastIndex) and lastIndex >= indexIn loop
10736           tempValue := engStInsertionIndexes(lastIndex);
10737           engStInsertionIndexes(lastIndex + 1) := tempValue;
10738           engStInsertionIndexes.delete(lastIndex);
10739           lastIndex := engStInsertionIndexes.prior(lastIndex + 1);
10740         end loop;
10741         engStInsertionIndexes(indexIn) := insertionOrderIn;
10742       else
10743         engStInsertionIndexes(indexIn) := insertionOrderIn;
10744       end if;
10745     end populateInsertionIndexes;
10746   procedure processSuppressDeviation(approverIndexIn in number,suppressApproverIndex in number) as
10747    tempcount number;
10748   begin
10749    engDeviationResultList(approverIndexIn).effectiveDate := engSuppressionDateList(suppressApproverIndex);
10750    engDeviationResultList(approverIndexIn).reason := engSupperssionReasonList(suppressApproverIndex);
10751    exception
10752      when others then
10753        ame_util.runtimeException(packageNameIn => 'ame_engine',
10754                                  routineNameIn => 'processSuppressDeviation',
10755                                  exceptionNumberIn => sqlcode,
10756                                  exceptionStringIn => sqlerrm);
10757   end processSuppressDeviation;
10758   procedure processSuppressions as
10759     begin
10760       for i in 1 .. engDeletedApproverList.count loop
10761         for j in 1 .. engStApprovers.count loop
10762           if(engStApprovers(j).name = engDeletedApproverList(i).name and
10763              engStApprovers(j).occurrence = engDeletedApproverList(i).occurrence and
10764              engStApprovers(j).group_or_chain_id = engDeletedApproverList(i).group_or_chain_id and
10765              engStApprovers(j).action_type_id = engDeletedApproverList(i).action_type_id and
10766              engStApprovers(j).item_id = engDeletedApproverList(i).item_id and
10767              engStApprovers(j).item_class = engDeletedApproverList(i).item_class) then
10768             engStApprovers(j).approval_status := ame_util.suppressedStatus;
10769             engStApprovers(j).source := ame_util.apiSuppression;
10770             processSuppressDeviation(j,i);
10771             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10772               fnd_log.string
10773                 (fnd_log.level_statement
10774                 ,'ame_engine.processSuppressions'
10775                 ,'Suppressed approver ::: ' || engStApprovers(j).name
10776                 );
10777             end if;
10778           end if;
10779         end loop;
10780       end loop;
10781       exception
10782         when others then
10783           ame_util.runtimeException(packageNameIn => 'ame_engine',
10784                                     routineNameIn => 'processSuppressions',
10785                                     exceptionNumberIn => sqlcode,
10786                                     exceptionStringIn => sqlerrm);
10787           raise;
10788    end processSuppressions;
10789   procedure processExceptions as
10790     authorityRuleSuppressed boolean;
10791     currentFirstAuthorityIndex integer;
10792     currentFirstExceptionIndex integer;
10793     currentFirstItemIndex integer;
10794     currentLastAuthorityIndex integer;
10795     currentLastExceptionIndex integer;
10796     currentLastItemIndex integer;
10797     currentItemClassId integer;
10798     currentItemId ame_util.stringType;
10799     ruleCount integer;
10800     tempAttributeId integer;
10801     tempAttributeIdsToMatch ame_util.idList;
10802     tempExcOrdCondAttributeIds ame_util.idList;
10803     tempBoolean boolean;
10804     tempBoolean2 boolean;
10805     begin
10806       /* Handle the empty-rule-list case first. */
10807       if(engAppRuleIds.count = 0) then
10808         return;
10809       end if;
10810       authorityRuleSuppressed := false;
10811       /* Check for exception rules. */
10812       ruleCount := engAppRuleIds.count; /* This value gets used later in the code too. */
10813       tempBoolean := true;
10814       for i in 1 .. ruleCount loop
10815         if(engAppRuleTypes(i) = ame_util.exceptionRuleType) then
10816           tempBoolean := false;
10817           exit;
10818         end if;
10819       end loop;
10820       if(tempBoolean) then /* No exception rules. */
10821         return;
10822       end if;
10823       /* Now handle the case of a nonempty rule list containing at least one exception rule. */
10824       currentLastItemIndex := 0; /* This will set currentFirstItemIndex to one below. */
10825       loop /* Loop through the sublists of rules applying to an item. */
10826         /* Initialize the current[whatever]Index values. */
10827         currentFirstItemIndex := currentLastItemIndex + 1;
10828         currentLastItemIndex := null;
10829         currentFirstAuthorityIndex := null;
10830         currentLastAuthorityIndex := null;
10831         currentFirstExceptionIndex := null;
10832         currentLastExceptionIndex := null;
10833         currentItemClassId := engAppRuleItemClassIds(currentFirstItemIndex);
10834         currentItemId := engAppAppItemIds(currentFirstItemIndex);
10835         /* Set the current[whatever]Index values. */
10836         for i in currentFirstItemIndex .. ruleCount loop
10837           if(currentItemClassId <> engAppRuleItemClassIds(i) or
10838              currentItemId <> engAppAppItemIds(i)) then
10839             currentLastItemIndex := i - 1;
10840             exit;
10841           elsif(i = ruleCount) then
10842             currentLastItemIndex := i;
10843           end if;
10844           if(engAppRuleTypes(i) = ame_util.authorityRuleType) then
10845             if(currentFirstAuthorityIndex is null) then
10846               currentFirstAuthorityIndex := i;
10847             end if;
10848             currentLastAuthorityIndex := i;
10849           elsif(engAppRuleTypes(i) = ame_util.exceptionRuleType) then
10850             if(currentFirstExceptionIndex is null) then
10851               currentFirstExceptionIndex := i;
10852             end if;
10853             currentLastExceptionIndex := i;
10854           end if;
10855         end loop;
10856         /* Process the current item's exception rules (if any). */
10857         if(currentFirstExceptionIndex is not null) then
10858           for i in currentFirstExceptionIndex .. currentLastExceptionIndex loop
10859             /*
10860               Build the list of attribute IDs for the ordinary conditions used by this exception
10861               (in the local variable tempExcOrdCondAttributeIds) by looping through the engACU variables
10862               until the current exception's rule ID is matched.  Index the list of attribute IDs by
10863               attribute ID (the value doesn't matter, so we set it to a constant--one--for efficiency).
10864               Here tempBoolean indicates whether the exception rule has been found in the engACU
10865               variables, so we can exit the inner loop once we find all of the exception's attributes.
10866             */
10867             tempBoolean := false;
10868             tempExcOrdCondAttributeIds.delete;
10869             for j in 1 .. engACUsageRuleIds.count loop
10870               if(engACUsageRuleIds(j) = engAppRuleIds(i)) then
10871                 tempBoolean := true;
10872                 if(engACConditionTypes(engACUsageConditionIds(j)) = ame_util.ordinaryConditionType) then
10873                   tempExcOrdCondAttributeIds(engACAttributeIds(engACUsageConditionIds(j))) := 1;
10874                 end if;
10875               elsif(tempBoolean) then
10876                 exit;
10877               end if;
10878             end loop;
10879             /* Suppress authority rules as necessary. */
10880             if(currentFirstAuthorityIndex is not null) then
10881               for j in currentFirstAuthorityIndex .. currentLastAuthorityIndex loop
10882                 /* A previous iteration of the i loop could have suppressed the rule at j; check for this. */
10883                 if(engAppRuleIds.exists(j)) then
10884                   /*
10885                     Rather than rebuild tempExcOrdCondAttributeIds at each iteration,
10886                     copy it at each iteration, so we can freely delete entries in the
10887                     copy.
10888                   */
10889                   tempAttributeIdsToMatch.delete;
10890                   ame_util.copyIdList(idListIn => tempExcOrdCondAttributeIds,
10891                                       idListOut => tempAttributeIdsToMatch);
10892                   /*
10893                     For an applicable exception to override an otherwise applicable authority rule,
10894                     both rules' ordinary conditions must be defined on the same attributes.  (If
10895                     neither rule has any ordinary conditions, the exception overrides the authority
10896                     rule.)  Here tempBoolean indicates whether each of the authority rule's
10897                     attributes were matched, and tempBoolean2 indicates whether the target authority
10898                     rule has been found in the engACU variables.
10899                   */
10900                   tempBoolean := true;
10901                   tempBoolean2 := false;
10902                   for k in 1 .. engACUsageRuleIds.count loop
10903                     if(engACUsageRuleIds(k) = engAppRuleIds(j)) then
10904                       tempBoolean2 := true;
10905                       /*
10906                         (An authority rule only has ordinary conditions, so we don't have to check
10907                         the condition type here.)
10908                       */
10909                       tempAttributeId := engACAttributeIds(engACUsageConditionIds(k));
10910                       if(tempAttributeIdsToMatch.exists(tempAttributeId)) then
10911                         tempAttributeIdsToMatch.delete(tempAttributeId);
10912                       else
10913                         tempBoolean := false;
10914                         exit;
10915                       end if;
10916                     elsif(tempBoolean2) then
10917                       exit;
10918                     end if;
10919                   end loop;
10920                   if(tempBoolean and
10921                      tempAttributeIdsToMatch.count = 0) then
10922                     /*
10923                       All of the authority rule's conditions' attributes were matched, and all of the
10924                       exception's ordinary conditions' attributes were matched; so, delete the authority
10925                       rule from the list of applicable rules.
10926                     */
10927                     authorityRuleSuppressed := true;
10928                     engAppItemClassIds.delete(j);
10929                     engAppItemIds.delete(j);
10930                     engAppRuleIds.delete(j);
10931                     engRuleAppliedYN.delete(j);
10932                     engAppRuleTypes.delete(j);
10933                     engAppActionTypeIds.delete(j);
10934                     engAppParameters.delete(j);
10935                     engAppParameterTwos.delete(j);
10936                     engAppRuleItemClassIds.delete(j);
10937                     engAppAppItemIds.delete(j);
10938                   end if;
10939                 end if;
10940               end loop; /* j */
10941             end if;
10942             /*
10943               Convert the exception rule to an authority rule, so it gets processed with
10944               the remaining authority rules.
10945             */
10946             engAppRuleTypes(i) := ame_util.authorityRuleType;
10947           end loop;
10948         end if;
10949         /* Exit the outer loop if no more item rule lists exist. */
10950         if(currentLastItemIndex = ruleCount) then
10951           exit;
10952         end if;
10953       end loop;
10954       /* Re-compact the engApp lists if any authority rules got deleted. */
10955       if(authorityRuleSuppressed) then
10956         compactEngAppLists(compactPrioritiesIn => false,
10957                            compactActionTypeIdsIn => true,
10958                            compactParametersIn => true);
10959       end if;
10960       exception
10961         when others then
10962           ame_util.runtimeException(packageNameIn => 'ame_engine',
10963                                     routineNameIn => 'processExceptions',
10964                                     exceptionNumberIn => sqlcode,
10965                                     exceptionStringIn => sqlerrm);
10966           raise;
10967     end processExceptions;
10968   procedure processRepeatedApprovers as
10969     engAppRuleIdsCount integer;
10970     engStApproversCount integer;
10971     productionActionTypeId integer;
10972     repeatedApproversMode ame_util.attributeValueType;
10973     repeatedByApproverIndex integer;
10974     repeatedIndexesList ame_util.idList;
10975     tempAuthority ame_util.charType;
10976     tempActionTypeId integer;
10977     tempCount integer;
10978     tempEngStItemIndex integer;
10979     tempEngStProductionIndex integer;
10980     tempEngStRuleIndex integer;
10981     tempFirstIndexOfLastItem integer;
10982     tempFirstOccurrenceCurGrouping integer;
10983     tempGroupOrChainId integer;
10984     tempItemClass ame_util.stringType;
10985     tempItemId ame_util.stringType;
10986     tempApproverCategory ame_util.charType;
10987     tempProcessApprover boolean;
10988     tempRuleNotFound boolean;
10989     tempRuleIdList ame_util.idList;
10990     tempRuleIdList2 ame_util.idList;
10991     tempSourceDescription ame_util.longStringType;
10992     treeLevel integer;
10993     tempRepeatedAprCount number;
10994     tempChangeStatus boolean;
10995     begin
10996       /*
10997         This procedure does two things:  (1) suppress repeated approvers, and (2) aggregate various
10998         approver-related data in appropriate engSt package variables.  The aggregation has to occur
10999         for all occurrences of a wf_roles.name value in engStApprovers, at once; so this procedure's
11000         outer loop iterates through engStApprovers, doing the aggregation.  The inner loop suppresses
11001         repeated approvers.
11002       */
11003       tempEngStItemIndex := 0; /* pre-increment */
11004       tempEngStProductionIndex := 0; /* pre-increment */
11005       tempEngStRuleIndex := 0; /* pre-increment */
11006       repeatedApproversMode := getConfigVarValue(configVarNameIn => ame_util.repeatedApproverConfigVar);
11007       /* Set treeLevel for efficiency in the inner loop. */
11008       if(repeatedApproversMode = ame_util.oncePerTransaction) then
11009         treeLevel := 0;
11010       elsif(repeatedApproversMode = ame_util.oncePerItemClass) then
11011         treeLevel := 1;
11012       elsif(repeatedApproversMode = ame_util.oncePerItem) then
11013         treeLevel := 2;
11014       elsif(repeatedApproversMode = ame_util.oncePerSublist) then
11015         treeLevel := 3;
11016       elsif(repeatedApproversMode = ame_util.oncePerActionType) then
11017         treeLevel := 4;
11018       elsif(repeatedApproversMode = ame_util.oncePerGroupOrChain) then
11019         treeLevel := 5;
11020       else /* repeatedApproversMode = ame_util.eachOccurrence */
11021         treeLevel := 6;
11022       end if;
11023       engStApproversCount := engStApprovers.count;
11024       for i in 1 .. engStApproversCount loop
11025         /*
11026           We only want to process an approver if the approver has not been previously processed and
11027           has not been suppressed.  If an approver was suppressed, they can't aggregate the approvals
11028           requirements of subsequent occurrences of the same wf_roles.name in engStApprovers.  If an
11029           approver was previously processed, we don't want to duplicate their data in the engStItem
11030           variables.
11031         */
11032         tempProcessApprover := true;
11033         if(engStApprovers(i).approval_status in (ame_util.suppressedStatus
11034                                                 ,ame_util.repeatedStatus)) then
11035           tempProcessApprover := false;
11036         else
11037           for j in 1 .. (i - 1) loop
11038             if(engStApprovers(j).name = engStApprovers(i).name and
11039                engStApprovers(j).approver_category = engStApprovers(i).approver_category) then
11040               tempProcessApprover := false;
11041               exit;
11042             end if;
11043           end loop;
11044         end if;
11045         if(tempProcessApprover) then
11046           /*
11047             Iterate through the rest of the approver list, looking for engStApprovers(i).name, and outputting
11048             each occurrence's data as required to various engSt variables.  If engStApprovers(i).name has
11049             already occurred in the current grouping, set engStApprovers(i).approval_status to
11050             ame_util.repeatedStatus and output its data for the index tempFirstOccurrenceCurGrouping.
11051             Otherwise output its data for index j.  (Set tempFirstOccurrenceCurGrouping to j when we find a
11052             new repeated-approvers grouping.)
11053           */
11054           for j in i .. engStApproversCount loop
11055             if(engStApprovers(j).name = engStApprovers(i).name and
11056                engStApprovers(j).approver_category = engStApprovers(i).approver_category) then
11057               /*
11058                  If repeatedApproversMode is ame_util.oncePerTransaction (that is, treeLevel = 6),
11059                  all occurrences of the approver with j > i are repeated.
11060               */
11061               if(j = i or
11062                  treeLevel = 6 or
11063                  (treelevel = 5 and tempGroupOrChainId <> engStApprovers(j).group_or_chain_id) or
11064                  (treeLevel > 3 and tempActionTypeId <> engStApprovers(j).action_type_id) or
11065                  (treeLevel > 2 and tempAuthority <> engStApprovers(j).authority) or
11066                  (treeLevel > 1 and tempItemId <> engStApprovers(j).item_id) or
11067                  (treeLevel > 0 and tempItemClass <> engStApprovers(j).item_class)) then
11068                 /* We're in a new repeatedApprovers grouping. */
11069                 tempFirstOccurrenceCurGrouping := j;
11070                 tempGroupOrChainId := engStApprovers(j).group_or_chain_id;
11071                 tempActionTypeId := engStApprovers(j).action_type_id;
11072                 tempAuthority := engStApprovers(j).authority;
11073                 tempItemId := engStApprovers(j).item_id;
11074                 tempItemClass := engStApprovers(j).item_class;
11075                 repeatedIndexesList(1) := j;
11076               else /* This is a repeated approver. */
11077                 /*
11078                   Don't overwrite non-null statuses with ame_util.repeatedStatus.  These can reflect
11079                   per-item approver responses.  See the ame_api2.updateApprovalStatus code for details.
11080                   Also, don't suppress special forwardees.  See bug 3401298 for details.
11081                 */
11082                 if(engStApprovers(j).approval_status is null and
11083                    engStApprovers(j).source not like ame_util.specialForwardInsertion || '%') then
11084                   engStApprovers(j).approval_status := ame_util.repeatedStatus;
11085                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11086                     fnd_log.string
11087                       (fnd_log.level_statement
11088                       ,'ame_engine.processRepeatedApprovers'
11089                       ,'Repeated Approver ::: ' || engStApprovers(j).name
11090                       );
11091                   end if;
11092                 end if;
11093                 if engStApprovers(j).approval_status in (ame_util.repeatedStatus
11094                                                         ,ame_util.notifiedByRepeatedStatus
11095                                                         ,ame_util.approvedByRepeatedStatus
11096                                                         ,ame_util.rejectedByRepeatedStatus
11097                                                         ,ame_util.rejectStatus
11098                                                         ,ame_util.approvedStatus
11099                                                         ,ame_util.notifiedStatus
11100                                                         ,ame_util.beatByFirstResponderStatus) then
11101                   /* Get the repeated by approver's tree node index */
11102                   repeatedIndexesList(repeatedIndexesList.count + 1) := j;
11103                 end if;
11104               end if;
11105             end if;
11106           end loop;
11107           tempCount := engStRepeatedIndexes.count;
11108           if repeatedIndexesList.count > 1 then
11109             for x in 1 .. repeatedIndexesList.count loop
11110               for y in 1 .. repeatedIndexesList.count loop
11111                 tempCount := tempCount + 1;
11112                 engStRepeatedIndexes(tempCount) := repeatedIndexesList(x);
11113                 engStRepeatedAppIndexes(tempCount) := repeatedIndexesList(y);
11114               end loop;
11115             end loop;
11116           end if;
11117           repeatedIndexesList.delete;
11118         end if;
11119       end loop;
11120       -- Handle the case of migration from pre ASP to ASP.
11121       for i in 1 .. engStApprovers.count loop
11122         for j in 1 .. engStRepeatedIndexes.count loop
11123           if engStRepeatedIndexes(j) = i and engStRepeatedAppIndexes(j) <> i then
11124             if engStApprovers(i).approval_status = ame_util.repeatedStatus or
11125                engStApprovers(i).approval_status is null then
11126               if engStApprovers(engStRepeatedAppIndexes(j)).approval_status = ame_util.approvedStatus then
11127                 engStApprovers(i).approval_status := ame_util.approvedByRepeatedStatus;
11128               elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
11129                                               = ame_util.noResponseStatus then
11130                 engStApprovers(i).approval_status := ame_util2.noResponseByRepeatedStatus;
11131               elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
11132                                               = ame_util.notifiedStatus then
11133                 engStApprovers(i).approval_status := ame_util.notifiedByRepeatedStatus;
11134               elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
11135                                               = ame_util.forwardStatus then
11136                 engStApprovers(i).approval_status := ame_util2.forwardByRepeatedStatus;
11137               end if;
11138             end if;
11139           end if;
11140         end loop;
11141       end loop;
11142       -- handle the repetaed status case
11143       tempRepeatedAprCount := engStRepeatedIndexes.count;
11144       for i in 1..engStApprovers.count loop
11145         if engStApprovers(i).approval_status in (ame_util.notifiedByRepeatedStatus
11146                                                 ) then
11147           if tempRepeatedAprCount = 0 then
11148             if engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus then
11149               engStApprovers(i).approval_status := ame_util.notifiedStatus ;
11150             end if;
11151           end if;
11152           tempChangeStatus := true;
11153           for j in 1..tempRepeatedAprCount loop
11154             if engStRepeatedIndexes(j) = i and engStRepeatedAppIndexes(j) <> i then
11155               if engStApprovers(engStRepeatedAppIndexes(j)).approval_status is null or
11156                  (engStApprovers(engStRepeatedAppIndexes(j)).approval_status = ame_util.notifiedStatus
11157                    and engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus ) then
11158                  tempChangeStatus := false;
11159                 exit;
11160               end if;
11161             end if;
11162           end loop;
11163           if tempChangeStatus then
11164             if engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus then
11165               engStApprovers(i).approval_status := null ;
11166             end if;
11167           end if;
11168         end if;
11169       end loop;
11170       exception
11171         when others then
11172           ame_util.runtimeException(packageNameIn => 'ame_engine',
11173                                     routineNameIn => 'processRepeatedApprovers',
11174                                     exceptionNumberIn => sqlcode,
11175                                     exceptionStringIn => sqlerrm);
11176           raise;
11177     end processRepeatedApprovers;
11178   procedure processRules(processOnlyProductionsIn in boolean default false) as
11179     currentActionTypeId integer;
11180     currentFirstItemIndex integer;
11181     currentFirstRuleIndexes ame_util.idList; /* indexed by rule type */
11182     currentIndex integer;
11183     currentItemClassId integer;
11184     currentItemId ame_util.stringType;
11185     currentLastItemIndex integer;
11186     currentLastRuleIndexes ame_util.idList; /* indexed by rule type */
11187     currentRuleType integer;
11188     ruleCount integer;
11189     ruleTypes ame_util.idList;
11190     tempIndex integer;
11191     tempLastRuleIndex integer;
11192     tempRuleType integer;
11193     ruleTypeUpperLimit integer;
11194     begin
11195       /* Handle the empty-rule-list case first. */
11196       if(engAppRuleIds.count = 0) then
11197         return;
11198       end if;
11199       /* Now handle the nonempty-rule-list case. . . . */
11200       /*
11201         Set the order in which rule types are processed, for a given item.
11202         Combination rules have already been split into their single-action
11203         components, and exceptions have been converted into authority rules,
11204         so ignore these rule types.
11205       */
11206       ruleTypes(1) := ame_util.productionRuleType;
11207       ruleTypes(2) := ame_util.preListGroupRuleType;
11208       ruleTypes(3) := ame_util.authorityRuleType;
11209       ruleTypes(4) := ame_util.postListGroupRuleType;
11210       ruleTypes(5) := ame_util.listModRuleType;
11211       ruleTypes(6) := ame_util.substitutionRuleType;
11212       /* Initialize the engine substitution variables. */
11213       engAppSubHandlerFirstIndex  := null;
11214       engAppSubHandlerLastIndex  := null;
11215       /* Initialize the state variables. */
11216       ruleCount := engAppRuleIds.count;
11217       currentItemClassId := engAppRuleItemClassIds(1);
11218       currentItemId := engAppAppItemIds(1);
11219       currentRuleType := engAppRuleTypes(1);
11220       currentFirstItemIndex := 1;
11221       currentFirstRuleIndexes(currentRuleType) := 1;
11222       currentIndex := 2;
11223       /* Iterate through the items. */
11224       loop
11225         if(currentIndex > ruleCount or
11226            currentItemClassId <> engAppRuleItemClassIds(currentIndex) or
11227            currentItemId <> engAppAppItemIds(currentIndex)) then
11228           currentLastItemIndex := currentIndex - 1;
11229           currentLastRuleIndexes(currentRuleType) := currentLastItemIndex;
11230         elsif(currentRuleType <> engAppRuleTypes(currentIndex)) then
11231           currentLastRuleIndexes(currentRuleType) := currentIndex - 1;
11232           currentRuleType := engAppRuleTypes(currentIndex);
11233           currentFirstRuleIndexes(currentRuleType) := currentIndex;
11234         end if;
11235         if(currentLastItemIndex is not null) then
11236           /* Process the current item's rules. */
11237           if processOnlyProductionsIn then
11238             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11239               fnd_log.string
11240                 (fnd_log.level_statement
11241                 ,'ame_engine.processRules'
11242                 ,'Processing only production rules'
11243                 );
11244             end if;
11245             ruleTypeUpperLimit := 1;
11246           else
11247             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11248               fnd_log.string
11249                 (fnd_log.level_statement
11250                 ,'ame_engine.processRules'
11251                 ,'Processing all rules'
11252                 );
11253             end if;
11254             ruleTypeUpperLimit := 6;
11255           end if;
11256           for i in 1 .. ruleTypeUpperLimit loop
11257             /* Process the action types within rule type ruleTypes(i). */
11258             tempRuleType := ruleTypes(i);
11259             if(currentFirstRuleIndexes.exists(tempRuleType)) then
11260               /* Initialize the action-type state variables. */
11261               engAppHandlerFirstIndex := currentFirstRuleIndexes(tempRuleType);
11262               currentActionTypeId := engAppActionTypeIds(engAppHandlerFirstIndex);
11263               tempIndex := engAppHandlerFirstIndex + 1;
11264               tempLastRuleIndex := currentLastRuleIndexes(tempRuleType);
11265               loop
11266                 if(tempIndex > tempLastRuleIndex or
11267                    currentActionTypeId <> engAppActionTypeIds(tempIndex)) then
11268                   /* Process the current action type for the current item. */
11269                   engAppHandlerLastIndex := tempIndex - 1;
11270                   processActionType;
11271                   if (currentRuleType = ame_util.substitutionRuleType) then
11272                     /* Set variables so subsequent call to the substitution handler is
11273                     possible without iterating through the applicable rule list again */
11274                     engAppSubHandlerFirstIndex :=currentFirstRuleIndexes(tempRuleType);
11275                     engAppSubHandlerLastIndex := currentLastRuleIndexes(tempRuleType);
11276                   end if;
11277                   if(tempIndex <= tempLastRuleIndex) then
11278                     /* Update the current action-type state variables. */
11279                     engAppHandlerFirstIndex := tempIndex;
11280                     currentActionTypeId := engAppActionTypeIds(tempIndex);
11281                   end if;
11282                 end if;
11283                 /* Iterate or exit. */
11284                 if(tempIndex > tempLastRuleIndex) then
11285                   exit;
11286                 end if;
11287                 tempIndex := tempIndex + 1;
11288               end loop;
11289             end if;
11290           end loop;
11291           if(currentIndex <= ruleCount) then
11292             /* Update the current state variables. */
11293             currentFirstRuleIndexes.delete;
11294             currentLastRuleIndexes.delete;
11295             currentItemClassId := engAppRuleItemClassIds(currentIndex);
11296             currentItemId := engAppAppItemIds(currentIndex);
11297             currentRuleType := engAppRuleTypes(currentIndex);
11298             currentFirstItemIndex := currentIndex;
11299             currentFirstRuleIndexes(currentRuleType) := currentIndex;
11300             currentLastItemIndex := null;
11301           end if;
11302         end if;
11303         /* Iterate or exit. */
11304         if(currentIndex > ruleCount) then
11305           exit;
11306         end if;
11307         currentIndex := currentIndex + 1;
11308       end loop;
11309       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11310         if engStApprovers.count = 0 then
11311           fnd_log.string
11312             (fnd_log.level_statement
11313             ,'ame_engine.processRules'
11314             ,'**************** No Approvers ******************'
11315             );
11316         else
11317           for i in 1 .. engStApprovers.count loop
11318             fnd_log.string
11319               (fnd_log.level_statement
11320               ,'ame_engine.processRules'
11321               ,'Approver ::: ' || engStApprovers(i).name
11322               );
11323           end loop;
11324         end if;
11325       end if;
11326       exception
11327         when others then
11328           ame_util.runtimeException(packageNameIn => 'ame_engine',
11329                                     routineNameIn => 'processRules',
11330                                     exceptionNumberIn => sqlcode,
11331                                     exceptionStringIn => sqlerrm);
11332           raise;
11333     end processRules;
11334   procedure processRelativePriorities as
11335     currentItemClassId integer;
11336     currentItemId ame_util.stringType;
11337     currentRuleType integer;
11338     currentThreshold integer;
11339     engAppRuleIdsCount integer;
11340     ruleDeleted boolean;
11341     tempAbsoluteThreshold integer;
11342     tempDoRelativePriorities boolean;
11343     tempFirstIndex integer;
11344     tempLastIndex integer;
11345     tempThresholdCounter integer;
11346     tempThresholds ame_util.idList;
11347     ruleExists boolean;
11348     tempIndex integer;
11349     oldTempIndex integer;
11350     begin
11351       /* Handle the trivial case here, so we can assume a non-empty applicable-rules list. */
11352       if(engAppRuleIds.count = 0) then
11353         return;
11354       end if;
11355       /* Now for the non-empty-list case. */
11356       ruleDeleted := false;
11357       /* Now for the non-empty-list case. */
11358       if engEvalPrioritiesPerItem then
11359         /* Evaluate priorites per item */
11360         tempFirstIndex := 1;
11361         engAppRuleIdsCount := engAppRuleIds.count;
11362         loop
11363           currentItemClassId := engAppRuleItemClassIds(tempFirstIndex);
11364           currentItemId := engAppAppItemIds(tempFirstIndex);
11365           currentRuleType := engAppRuleTypes(tempFirstIndex);
11366           tempThresholds.delete;
11367           tempLastIndex := null;
11368           tempDoRelativePriorities := engPriorityModes(currentRuleType) = ame_util.relativeRulePriority;
11369           /* Find tempLastIndex and optionally set the values in tempThresholds. */
11370           for i in tempFirstIndex .. engAppRuleIdsCount loop
11371             /* The following if does its comparisons in descending order of probability of success, for efficiency. */
11372             if(currentRuleType <> engAppRuleTypes(i) or
11373                currentItemId <> engAppAppItemIds(i) or
11374                currentItemClassId <> engAppRuleItemClassIds(i)) then
11375               tempLastIndex := i - 1;
11376               exit;
11377             else
11378               if(tempDoRelativePriorities) then
11379                 /* The tempThresholds index and value are the same for convenience. */
11380                 if engAppPriorities(i) is null then
11381                   tempThresholds(99999) := engAppPriorities(i);
11382                 else
11383                   tempThresholds(engAppPriorities(i)) := engAppPriorities(i);
11384                 end if;
11385               end if;
11386             end if;
11387           end loop;
11388           if(tempLastIndex is null) then
11389             tempLastIndex := engAppRuleIdsCount;
11390           end if;
11391           if(tempDoRelativePriorities) then
11392             /* Find the absolute threshold equivalent to the relative. */
11393             tempAbsoluteThreshold := tempThresholds.first;
11394             tempThresholdCounter := 1;
11395             currentThreshold := engPriorityThresholds(currentRuleType);
11396             while (tempThresholdCounter < currentThreshold) loop
11397               tempAbsoluteThreshold := tempThresholds.next(tempAbsoluteThreshold);
11398               tempThresholdCounter := tempThresholdCounter + 1;
11399             end loop;
11400             /* Do priority processing between tempFirstIndex and tempLastIndex. */
11401             for i in tempFirstIndex .. tempLastIndex loop
11402               if(engAppPriorities(i) is null or
11403                  engAppPriorities(i) > tempAbsoluteThreshold) then
11404                 engAppRuleIds.delete(i);
11405                 engRuleAppliedYN.delete(i);
11406                 engAppItemClassIds.delete(i);
11407                 engAppItemIds.delete(i);
11408                 engAppPriorities.delete(i);
11409                 engAppApproverCategories.delete(i);
11410                 engAppRuleTypes.delete(i);
11411                 engAppRuleItemClassIds.delete(i);
11412                 engAppAppItemIds.delete(i);
11413                 ruleDeleted := true;
11414               end if;
11415             end loop;
11416           end if;
11417           /* If there are no more applicable rules to process, stop. */
11418           if(tempLastIndex = engAppRuleIdsCount) then
11419             exit;
11420           end if;
11421           tempFirstIndex := tempLastIndex + 1;
11422         end loop;
11423       else
11424         /* Evaluate priorities at transaction level */
11425         /* BUG Fixes : 4472308 and 4065967 */
11426         for i in 0 .. 7 loop
11427           tempDoRelativePriorities := engPriorityModes(i) = ame_util.relativeRulePriority;
11428           if tempDoRelativePriorities then
11429             ruleExists := false;
11430             tempIndex := engAppRuleIds.first;
11431             loop
11432               if engAppRuleTypes(tempIndex) = i then
11433                 if engAppPriorities(tempIndex) is null then
11434                   tempThresholds(99999) := engAppPriorities(tempIndex);
11435                 else
11436                   tempThresholds(engAppPriorities(tempIndex)) := engAppPriorities(tempIndex);
11437                 end if;
11438                 ruleExists := true;
11439               end if;
11440               tempIndex := engAppRuleIds.next(tempIndex);
11441               exit when tempIndex is null;
11442             end loop;
11443             if ruleExists then
11444               tempAbsoluteThreshold := tempThresholds.first;
11445               tempThresholdCounter := 1;
11446               currentThreshold := engPriorityThresholds(i);
11447               while (tempThresholdCounter < currentThreshold) loop
11448                 tempAbsoluteThreshold := tempThresholds.next(tempAbsoluteThreshold);
11449                 tempThresholdCounter := tempThresholdCounter + 1;
11450               end loop;
11451               tempIndex := engAppRuleIds.first;
11452               loop
11453                 if(engAppRuleTypes(tempIndex) = i and
11454                    (engAppPriorities(tempIndex) is null or
11455                     engAppPriorities(tempIndex) > tempAbsoluteThreshold)) then
11456                   oldTempIndex := tempIndex;
11457                   tempIndex := engAppRuleIds.next(oldTempIndex);
11458                   engAppRuleIds.delete(oldTempIndex);
11459                   engRuleAppliedYN.delete(oldTempIndex);
11460                   engAppItemClassIds.delete(oldTempIndex);
11461                   engAppItemIds.delete(oldTempIndex);
11462                   engAppPriorities.delete(oldTempIndex);
11463                   engAppApproverCategories.delete(oldTempIndex);
11464                   engAppRuleTypes.delete(oldTempIndex);
11465                   engAppRuleItemClassIds.delete(oldTempIndex);
11466                   engAppAppItemIds.delete(oldTempIndex);
11467                   ruleDeleted := true;
11468                 else
11469                   tempIndex := engAppRuleIds.next(tempIndex);
11470                 end if;
11471                 exit when tempIndex is null;
11472               end loop;
11473             end if;
11474           end if;
11475         end loop;
11476       end if;
11477       /* If relative-priority processing deleted one or more rules from the engApp lists, compact them. */
11478       if(ruleDeleted) then
11479         compactEngAppLists(compactPrioritiesIn => true,
11480                            compactActionTypeIdsIn => false,
11481                            compactParametersIn => false);
11482       end if;
11483       exception
11484         when others then
11485           ame_util.runtimeException(packageNameIn => 'ame_engine',
11486                                     routineNameIn => 'processRelativePriorities',
11487                                     exceptionNumberIn => sqlcode,
11488                                     exceptionStringIn => sqlerrm);
11489           raise;
11490     end processRelativePriorities;
11491   procedure processUnresponsiveApprovers as
11492     engStApproversCount integer;
11493     tempIndex integer;
11494     tempSurrogateApprover ame_util.approverRecord2;
11495     begin
11496       /* First handle the empty-list case. */
11497       engStApproversCount := engStApprovers.count;
11498       if(engStApproversCount = 0) then
11499         return;
11500       end if;
11501       /* Now handle the non-empty case. */
11502       tempIndex := 1; /* post-increment */
11503       loop
11504         if(engStApprovers(tempIndex).approval_status = ame_util.noResponseStatus) then
11505           /* Fetch surrogate's wf_roles-specific data. */
11506           ame_approver_type_pkg.getSurrogate(origSystemIn => engStApprovers(tempIndex).orig_system,
11507                                              origSystemIdIn => engStApprovers(tempIndex).orig_system_id,
11508                                              origSystemIdOut => tempSurrogateApprover.orig_system_id,
11509                                              wfRolesNameOut => tempSurrogateApprover.name,
11510                                              displayNameOut => tempSurrogateApprover.display_name);
11511           tempSurrogateApprover.orig_system := engStApprovers(tempIndex).orig_system;
11512           /* Set fields constant for all surrogates. */
11513           tempSurrogateApprover.api_insertion := ame_util.apiInsertion;
11514           tempSurrogateApprover.source := ame_util.surrogateInsertion;
11515           /* Set common-valued fields. */
11516           tempSurrogateApprover.approver_category := engStApprovers(tempIndex).approver_category;
11517           tempSurrogateApprover.authority := engStApprovers(tempIndex).authority;
11518           tempSurrogateApprover.action_type_id := engStApprovers(tempIndex).action_type_id;
11519           tempSurrogateApprover.group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
11520           tempSurrogateApprover.item_class := engStApprovers(tempIndex).item_class;
11521           tempSurrogateApprover.item_id := engStApprovers(tempIndex).item_id;
11522           tempSurrogateApprover.item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
11523           tempSurrogateApprover.item_order_number := engStApprovers(tempIndex).item_order_number;
11524           tempSurrogateApprover.sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
11525           tempSurrogateApprover.action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
11526           tempSurrogateApprover.group_or_chain_order_number := engStApprovers(tempIndex).group_or_chain_order_number;
11527           /* Set remaining fields. */
11528           tempSurrogateApprover.occurrence :=
11529             getHandlerOccurrence(nameIn => tempSurrogateApprover.name,
11530                                  itemClassIn => tempSurrogateApprover.item_class,
11531                                  itemIdIn => tempSurrogateApprover.item_id,
11532                                  actionTypeIdIn => tempSurrogateApprover.action_type_id,
11533                                  groupOrChainIdIn => tempSurrogateApprover.group_or_chain_id);
11534           tempSurrogateApprover.approval_status := getHandlerApprovalStatus(approverIn => tempSurrogateApprover);
11535           /* The member order number and the approver order number are set here
11536              instead of in insertApprover. This will ensure that the surrogate has the same
11537              order as the unresponsive approver. Also changed call to insertApprover so that
11538              adjustMemberOrderNumbers is false */
11539           tempSurrogateApprover.member_order_number := engStApprovers(tempIndex).member_order_number;
11540           tempSurrogateApprover.approver_order_number := engStApprovers(tempIndex).approver_order_number;
11541           /* tempSurrogateApprover.approver_order_number also gets set later. */
11542           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11543             fnd_log.string
11544               (fnd_log.level_statement
11545               ,'ame_engine.processUnresponsiveApprovers'
11546               ,'Unresponsive approver ::: ' || engStApprovers(tempIndex).name || ' Surrogate ::: ' || tempSurrogateApprover.name
11547               );
11548           end if;
11549           engTempReason := ame_approver_deviation_pkg.timeoutReason;
11550           engTempDate := sysdate;
11551           insertApprover(indexIn => tempIndex + 1,
11552                          approverIn => tempSurrogateApprover,
11553                          adjustMemberOrderNumbersIn => false);
11554           engStApproversCount := engStApproversCount + 1;
11555         end if;
11556         if(tempIndex = engStApproversCount) then
11557           exit;
11558         end if;
11559         tempIndex := tempIndex + 1;
11560       end loop;
11561       exception
11562         when others then
11563           ame_util.runtimeException(packageNameIn => 'ame_engine',
11564                                     routineNameIn => 'processUnresponsiveApprovers',
11565                                     exceptionNumberIn => sqlcode,
11566                                     exceptionStringIn => sqlerrm);
11567           raise;
11568     end processUnresponsiveApprovers;
11569   procedure repeatSubstitutions as
11570     currentActionTypeId integer;
11571     begin
11572       /* Check if any substitution rule exists. This can be done by checking if
11573          engAppSubHandlerFirstIndex  is null or not */
11574       engRepSubFlag := 'Y';
11575       if not(engAppSubHandlerFirstIndex  is null or
11576              engAppSubHandlerLastIndex is null) then
11577         /* Initialize the action-type state variables. */
11578         engAppHandlerFirstIndex := engAppSubHandlerFirstIndex;
11579         engAppHandlerLastIndex := engAppSubHandlerLastIndex;
11580         processActionType;
11581       end if;
11582       engRepSubFlag := 'N';
11583     end repeatSubstitutions;
11584   procedure setContext(isTestTransactionIn in boolean,
11585                        isLocalTransactionIn in boolean,
11586                        fetchConfigVarsIn in boolean,
11587                        fetchOldApproversIn in boolean,
11588                        fetchInsertionsIn in boolean,
11589                        fetchDeletionsIn in boolean,
11590                        fetchAttributeValuesIn in boolean,
11591                        fetchInactiveAttValuesIn in boolean,
11592                        processProductionActionsIn in boolean,
11593                        processProductionRulesIn in boolean,
11594                        updateCurrentApproverListIn in boolean,
11595                        updateOldApproverListIn in boolean,
11596                        processPrioritiesIn in boolean,
11597                        prepareItemDataIn in boolean,
11598                        prepareRuleIdsIn in boolean,
11599                        prepareRuleDescsIn in boolean,
11600                        prepareApproverTreeIn in boolean default false,
11601                        transactionIdIn in varchar2,
11602                        ameApplicationIdIn in integer default null,
11603                        fndApplicationIdIn in integer default null,
11604                        transactionTypeIdIn in varchar2 default null) as
11605     badLocalTransException exception;
11606     errorCode integer;
11607     errorMessage ame_util.longestStringType;
11608     nullValuesException exception;
11609     tempConfigVarValue ame_config_vars.variable_value%type;
11610     begin
11611       /*
11612         Clear all of the package variables, to be conservative.  (The application server does not initialize
11613         package variables.  See http://www-apps.us.oracle.com/atg/plans/r1153/plsqlglobals.txt for details.)
11614       */
11615       engLMParameterOnes.delete;
11616       engLMParameterTwos.delete;
11617       engGroupMemberGroupIds.delete;
11618       engGroupMemberNames.delete;
11619       engGroupMemberOrderNumbers.delete;
11620       engGroupMemberDisplayNames.delete;
11621       engGroupMemberOrigSystems.delete;
11622       engGroupMemberOrigSystemIds.delete;
11623       engGroupUseItemBind.delete;
11624       engAppActionTypeIds.delete;
11625       engAppApproverCategories.delete;
11626       engAppItemClassIds.delete;
11627       engAppItemIds.delete;
11628       engAppLMSubItemClassIds.delete;
11629       engAppLMSubItemIds.delete;
11630       engAppParameters.delete;
11631       engAppParameterTwos.delete;
11632       engAppPriorities.delete;
11633       engAppRuleIds.delete;
11634       engRuleAppliedYN.delete;
11635       engAppRuleTypes.delete;
11636       engAppRuleItemClassIds.delete;
11637       engAppAppItemIds.delete;
11638       engAppPerAppProdFirstIndexes.delete;
11639       engAppPerAppProdRuleIds.delete;
11640       engAppPerAppProdVariableNames.delete;
11641       engAppPerAppProdVariableValues.delete;
11642       engStApprovers.delete;
11643       /* Clear the engine approver tree */
11644       engStApproversTree.delete;
11645       engStItemClasses.delete;
11646       engStItemIds.delete;
11647       engStItemIndexes.delete;
11648       engStItemSources.delete;
11649       engStProductionIndexes.delete;
11650       /* Clear repeated indexes list */
11651       engStRepeatedIndexes.delete;
11652       engStRepeatedAppIndexes.delete;
11653       engStRuleDescriptions.delete;
11654       engStRuleIds.delete;
11655       engStRuleIndexes.delete;
11656       engStSourceTypes.delete;
11657       /* Clear suspended items list */
11658       engStSuspendedItems.delete;
11659       engStSuspendedItemClasses.delete;
11660       engStProductionsTable.delete;
11661       engStVariableNames.delete;
11662       engStVariableValues.delete;
11663       engStItemAppProcessCompleteYN.delete;
11664       engConfigVarNames.delete;
11665       engConfigVarValues.delete;
11666       engForwardingBehaviors.delete;
11667       engPriorityModes.delete;
11668       engPriorityThresholds.delete;
11669       engActionTypeChainOrderModes.delete;
11670       engActionTypeOrderNumbers.delete;
11671       engActionTypeVotingRegimes.delete;
11672       engActionTypeNames.delete;
11673       engActionTypeUsages.delete;
11674       engActionTypePackageNames.delete;
11675       engItemClassIds.delete;
11676       engItemClassIndexes.delete;
11677       engItemClassItemIdIndexes.delete;
11678       engItemClassNames.delete;
11679       engItemClassOrderNumbers.delete;
11680       engItemClassParModes.delete;
11681       engItemClassSublistModes.delete;
11682       engItemCounts.delete;
11683       engItemIds.delete;
11684       engAttributeIsStatics.delete;
11685       engAttributeItemClassIds.delete;
11686       engAttributeNames.delete;
11687       engAttributeTypes.delete;
11688       engAttributeValueIndexes.delete;
11689       engAttributeValues1.delete;
11690       engAttributeValues2.delete;
11691       engAttributeValues3.delete;
11692       engAttributeQueries.delete;
11693       engAttributeVariant.delete;
11694       engHeaderConditionValues.delete;
11695       engACUsageConditionIds.delete;
11696       engACUsageFirstIndexes.delete;
11697       engACUsageItemClassCounts.delete;
11698       engACUsageRuleIds.delete;
11699       engACUsageRulePriorities.delete;
11700       engACUsageRuleTypes.delete;
11701       engACUsageRuleApprCategories.delete;
11702       engACAttributeIds.delete;
11703       engACConditionTypes.delete;
11704       engACIncludeLowerLimits.delete;
11705       engACIncludeUpperLimits.delete;
11706       engACParameterOnes.delete;
11707       engACParameterThrees.delete;
11708       engACParameterTwos.delete;
11709       engACStringValueCounts.delete;
11710       engACStringValueFirstIndexes.delete;
11711       engACStringValues.delete;
11712       engOldApproverList.delete;
11713       engInsertedApproverList.delete;
11714       engInsertionOrderTypeList.delete;
11715       engInsertionParameterList.delete;
11716       engInsertionIsSpecialForwardee.delete;
11717       engDeletedApproverList.delete;
11718       engStInsertionIndexes.delete;
11719       /*delete deviation related info*/
11720       engDeviationResultList.delete;
11721       engInsertionReasonList.delete;
11722       engInsertionDateList.delete;
11723       engSuppressionDateList.delete;
11724       engSupperssionReasonList.delete;
11725       engInsApproverIndex.delete;
11726       engTempReason := null;
11727       engTempDate := null;
11728       engRepSubFlag := 'N';
11729       engSATOFlag := 'N';
11730       /* Fetch the transaction identifiers. */
11731       if(ameApplicationIdIn is null) then
11732         if(fndApplicationIdIn is null) then
11733           raise nullValuesException;
11734         end if;
11735         engFndApplicationId := fndApplicationIdIn;
11736         engTransactionTypeId := transactionTypeIdIn;
11737         engAmeApplicationId := fetchAmeApplicationId(fndApplicationIdIn => fndApplicationIdIn,
11738                                                      transactionTypeIdIn => transactionTypeIdIn);
11739       else
11740         engAmeApplicationId := ameApplicationIdIn;
11741         fetchFndApplicationId(applicationIdIn => ameApplicationIdIn,
11742                               fndApplicationIdOut => engFndApplicationId,
11743                               transactionTypeIdOut => engTransactionTypeId);
11744       end if;
11745       engTransactionId := transactionIdIn;
11746       engIsTestTransaction := isTestTransactionIn;
11747       engIsLocalTransaction := isLocalTransactionIn;
11748       if(engIsTestTransaction and not engIsLocalTransaction) then
11749         raise badLocalTransException;
11750       end if;
11751       /* Initialize engEffectiveRuleDate to sysdate, in case the attribute values aren't fetched. */
11752       engEffectiveRuleDate := sysdate;
11753       /* Initialize misc. boolean globals to the corresponding input values. */
11754       engPrepareItemData := prepareItemDataIn;
11755       engPrepareRuleIds := prepareRuleIdsIn;
11756       engPrepareRuleDescs := prepareRuleDescsIn;
11757       engPrepareApproverTree := prepareApproverTreeIn;
11758       engItemDataPrepared := false;
11759       engProcessProductionActions := processProductionActionsIn;
11760       engProcessProductionRules := processProductionRulesIn;
11761       engProcessPriorities := processPrioritiesIn;
11762       engUpdateCurrentApproverList := updateCurrentApproverListIn;
11763       engUpdateOldApproverList := updateOldApproverListIn;
11764       /* Optionally fetch the global configuration-variable lists. */
11765       if(fetchConfigVarsIn) then
11766         /* Fetch. */
11767         fetchConfigVars;
11768         /* Reconcile the engProcessProduction values with the productionFunctionality config var. */
11769         tempConfigVarValue := getConfigVarValue(configVarNameIn => ame_util.productionConfigVar);
11770         if(engProcessProductionActions and
11771            tempConfigVarValue in (ame_util.noProductions, ame_util.perTransactionProductions)) then
11772           engProcessProductionActions := false;
11773         end if;
11774         if(engProcessProductionRules and
11775            tempConfigVarValue in (ame_util.noProductions, ame_util.perApproverProductions)) then
11776           engProcessProductionRules := false;
11777         end if;
11778       end if;
11779       /* Optionally fetch the transaction's attribute values.  */
11780       if(fetchAttributeValuesIn) then
11781         /* Go fetch. */
11782         fetchItemClassData;
11783         fetchAttributeValues(fetchInactivesIn => fetchInactiveAttValuesIn);
11784         /* Set misc. frequently-used attribute-value caches. */
11785         engEvalPrioritiesPerItem :=
11786           getHeaderAttValue2(attributeNameIn => ame_util.evalPrioritiesPerItemAttribute) =
11787             ame_util.booleanAttributeTrue;
11788         engRepeatSubstitutions  :=
11789           getHeaderAttValue2(attributeNameIn => ame_util.repeatSubstitutionsAttribute) =
11790             ame_util.booleanAttributeTrue;
11791         /* A null effective rule date should be interpreted as sysdate. */
11792         engEffectiveRuleDate := ame_util.versionStringToDate(stringDateIn =>
11793           getHeaderAttValue2(attributeNameIn => ame_util.effectiveRuleDateAttribute));
11794         if(engEffectiveRuleDate is null) then
11795           engEffectiveRuleDate := sysdate;
11796         else
11797           -- evaluate the attributes with use count 0 if they are used in rules
11798           -- which were active as of effective_rule_date.
11799           if not fetchInactiveAttValuesIn then
11800             fetchOtherAttributeValues;
11801           end if;
11802         end if;
11803         if(processProductionActionsIn or
11804            processProductionRulesIn or
11805            updateCurrentApproverListIn or
11806            updateOldApproverListIn or
11807            processPrioritiesIn or
11808            prepareItemDataIn or
11809            prepareRuleIdsIn or
11810            prepareRuleDescsIn) then
11811           /* Fetch the active condition usages. */
11812           fetchActiveConditionUsages;
11813         end if;
11814       end if;
11815       /* Optionally fetch the old approver list. */
11816       if(fetchOldApproversIn) then
11817         fetchOldApprovers;
11818       end if;
11819       /* Optionally fetch the inserted-approvers list. */
11820       if(fetchInsertionsIn) then
11821         fetchInsertedApprovers;
11822       end if;
11823       /* Optionally fetch the approver-deletions list. */
11824       if(fetchDeletionsIn) then
11825         fetchDeletedApprovers;
11826       end if;
11827       exception
11828         when badLocalTransException then
11829           errorCode := -20001;
11830           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11831                                               messageNameIn => 'AME_400688_ENG_TESTTX_NONLOCAL');
11832           ame_util.runtimeException(packageNameIn => 'ame_engine',
11833                                     routineNameIn => 'setContext',
11834                                     exceptionNumberIn => errorCode,
11835                                     exceptionStringIn => errorMessage);
11836           raise_application_error(errorCode,
11837                                   errorMessage);
11838         when nullValuesException then
11839           errorCode := -20001;
11840           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11841                                               messageNameIn => 'AME_400129_ENG_APPLID_NULL');
11842           ame_util.runtimeException(packageNameIn => 'ame_engine',
11843                                     routineNameIn => 'setContext',
11844                                     exceptionNumberIn => errorCode,
11845                                     exceptionStringIn => errorMessage);
11846           raise_application_error(errorCode,
11847                                   errorMessage);
11848         when others then
11849           ame_util.runtimeException(packageNameIn => 'ame_engine',
11850                                     routineNameIn => 'setContext',
11851                                     exceptionNumberIn => sqlcode,
11852                                     exceptionStringIn => sqlerrm);
11853           raise;
11854     end setContext;
11855   procedure setHandlerState(handlerNameIn in varchar2,
11856                             parameterIn in varchar2 default null,
11857                             stateIn in varchar2 default null) as
11858     argumentLengthException exception;
11859     errorCode integer;
11860     errorMessage ame_util.longestStringType;
11861     handlerName ame_temp_handler_states.handler_name%type;
11862     begin
11863       if(lengthb(stateIn) > 100 or
11864          lengthb(parameterIn) > 100) then
11865         raise argumentLengthException;
11866       end if;
11867       handlerName := upper(handlerNameIn);
11868       delete
11869         from ame_temp_handler_states
11870         where
11871           handler_name = handlerName and
11872           application_id = engAmeApplicationId and
11873           ((parameter is null and parameterIn is null) or
11874            (parameter = parameterIn));
11875       insert into ame_temp_handler_states(
11876         handler_name,
11877         row_timestamp,
11878         application_id,
11879         parameter,
11880         state)
11881         values(
11882           handlerName,
11883           sysdate, /* Don't use engEffectiveRuleDate here. */
11884           engAmeApplicationId,
11885           parameterIn,
11886           stateIn);
11887       exception
11888         when argumentLengthException then
11889           errorCode := -20001;
11890           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11891                                               messageNameIn => 'AME_400130_ENG_HDLR_PAR_LNG');
11892           ame_util.runtimeException(packageNameIn => 'ame_engine',
11893                                     routineNameIn => 'setHandlerState',
11894                                     exceptionNumberIn => errorCode,
11895                                     exceptionStringIn => errorMessage);
11896           raise_application_error(errorCode,
11897                                   errorMessage);
11898         when others then
11899           ame_util.runtimeException(packageNameIn => 'ame_engine',
11900                                     routineNameIn => 'setHandlerState',
11901                                     exceptionNumberIn => sqlcode,
11902                                     exceptionStringIn => sqlerrm);
11903           raise;
11904     end setHandlerState;
11905   procedure setInsertedApprovalStatus(currentApproverIndexIn in integer
11906                                       ,approvalStatusIn in varchar2) as
11907       insIndex Number;
11908     begin
11909       insIndex := engInsApproverIndex.first;
11910       if insIndex is not null then
11911         loop
11912           if engInsApproverIndex(insIndex) = currentApproverIndexIn then
11913             engInsertedApproverList(insIndex).approval_status := approvalStatusIn;
11914             update ame_temp_insertions
11915              set approval_status = approvalStatusIn
11916             where application_id = engAmeApplicationId
11917               and transaction_id = engTransactionId
11918               and insertion_order = engInsertionOrderList(insIndex)
11919               and order_type = engInsertionOrderTypeList(insIndex)
11920               and parameter = engInsertionParameterList(insIndex)
11921               and api_insertion = engInsertedApproverList(insIndex).api_insertion
11922               and authority = engInsertedApproverList(insIndex).authority;
11923             return;
11924           end if;
11925           exit when insIndex = engInsApproverIndex.last;
11926           insIndex := engInsApproverIndex.next(insIndex);
11927         end loop;
11928       end if;
11929     exception
11930       when others then
11931         ame_util.runtimeException(packageNameIn => 'ame_engine',
11932                                   routineNameIn => 'setInsertedApprovalStatus',
11933                                   exceptionNumberIn => sqlcode,
11934                                   exceptionStringIn => sqlerrm);
11935           raise;
11936   end setInsertedApprovalStatus;
11937   procedure setRuleApplied(ruleIndexIn in integer) as
11938     begin
11939       engRuleAppliedYN(ruleIndexIn) := ame_util.booleanTrue;
11940     end setRuleApplied;
11941   procedure sortApplicableRules(sortByActionTypeIn in boolean) as
11942     exchangeActionTypeId integer;
11943     exchangeAppItemId ame_util.stringType;
11944     exchangeApproverCategory ame_util.charType;
11945     exchangeItemClassId integer;
11946     exchangeItemId ame_util.stringType;
11947     exchangeParameter ame_actions.parameter%type;
11948     exchangeParameterTwo ame_actions.parameter_two%type;
11949     exchangePriority integer;
11950     exchangeRuleId integer;
11951     exchangeRuleItemClassId integer;
11952     exchangeRuleType ame_util.stringType;
11953     exchangeRuleAppliedYN ame_util.charType;
11954     begin
11955       /*
11956         This is a simple sort algorithm, but it is efficient for small input counts.
11957         The inputs are generally nearly sorted, which makes at least a nonrandomized
11958         quicksort a poor choice (quicksort's worst-case performance arises in the
11959         case of inputs that are already sorted or nearly sorted).  A randomized
11960         quicksort would avoid this problem, but our judgment is that the random-number
11961         generation overhead makes this approach undesirable for inputs of the sizes
11962         we expect.
11963       */
11964       for i in 2 .. engAppRuleIds.count loop
11965         for j in 1 .. i - 1 loop
11966           if(compareApplicableRules(index1In => i,
11967                                     index2In => j,
11968                                     compareActionTypesIn => sortbyActionTypeIn)) then
11969             /* Set exchange buffers' values. */
11970             exchangeItemClassId := engAppItemClassIds(i);
11971             exchangeItemId := engAppItemIds(i);
11972             exchangeRuleItemClassId := engAppRuleItemClassIds(i);
11973             exchangeAppItemId := engAppAppItemIds(i);
11974             exchangeRuleId := engAppRuleIds(i);
11975             exchangeRuleAppliedYN := engRuleAppliedYN(i);
11976             exchangeRuleType := engAppRuleTypes(i);
11977             exchangeApproverCategory := engAppApproverCategories(i);
11978             if(sortByActionTypeIn) then
11979               exchangeActionTypeId := engAppActionTypeIds(i);
11980               exchangeParameter := engAppParameters(i);
11981               exchangeParameterTwo := engAppParameterTwos(i);
11982             elsif(engProcessPriorities) then
11983               exchangePriority := engAppPriorities(i);
11984             end if;
11985             /* Move jth values to index i. */
11986             engAppRuleItemClassIds(i) := engAppRuleItemClassIds(j);
11987             engAppAppItemIds(i) := engAppAppItemIds(j);
11988             engAppItemClassIds(i) := engAppItemClassIds(j);
11989             engAppItemIds(i) := engAppItemIds(j);
11990             engAppRuleIds(i) := engAppRuleIds(j);
11991             engRuleAppliedYN(i) := engRuleAppliedYN(j);
11992             engAppRuleTypes(i) := engAppRuleTypes(j);
11993             engAppApproverCategories(i) := engAppApproverCategories(j);
11994             if(sortByActionTypeIn) then
11995               engAppActionTypeIds(i) := engAppActionTypeIds(j);
11996               engAppParameters(i) := engAppParameters(j);
11997               engAppParameterTwos(i) := engAppParameterTwos(j);
11998             elsif(engProcessPriorities) then
11999               engAppPriorities(i) := engAppPriorities(j);
12000             end if;
12001             /* Move buffered ith values to index j. */
12002             engAppRuleItemClassIds(j) := exchangeRuleItemClassId;
12003             engAppAppItemIds(j) := exchangeAppItemId;
12004             engAppItemClassIds(j) := exchangeItemClassId;
12005             engAppItemIds(j) := exchangeItemId;
12006             engAppRuleIds(j) := exchangeRuleId;
12007             engRuleAppliedYN(j) := exchangeRuleAppliedYN;
12008             engAppRuleTypes(j) := exchangeRuleType;
12009             engAppApproverCategories(j) := exchangeApproverCategory;
12010             if(sortByActionTypeIn) then
12011               engAppActionTypeIds(j) := exchangeActionTypeId;
12012               engAppParameters(j) := exchangeParameter;
12013               engAppParameterTwos(j) := exchangeParameterTwo;
12014             elsif(engProcessPriorities) then
12015               engAppPriorities(j) := exchangePriority;
12016             end if;
12017           end if;
12018         end loop;
12019       end loop;
12020       exception
12021         when others then
12022           ame_util.runtimeException(packageNameIn => 'ame_engine',
12023                                     routineNameIn => 'sortApplicableRules',
12024                                     exceptionNumberIn => sqlcode,
12025                                     exceptionStringIn => sqlerrm);
12026           raise;
12027     end sortApplicableRules;
12028   procedure substituteApprover(approverIndexIn in integer,
12029                                nameIn in varchar2,
12030                                actionTypeIdIn in varchar2,
12031                                ruleIdIn in integer) as
12032     currentActionTypeId integer;
12033     currentGroupOrChainId integer;
12034     occurrence integer;
12035     l_error_code number;
12036     errorCode integer;
12037     errorMessage ame_util.longestStringType;
12038     begin
12039       /* Look up the orig_system, orig_system_id, and display_name values corresponding to nameIn. */
12040         begin
12041          ame_approver_type_pkg.getOrigSystemIdAndDisplayName(
12042             nameIn => nameIn,
12043             origSystemOut => engStApprovers(approverIndexIn).orig_system,
12044             origSystemIdOut => engStApprovers(approverIndexIn).orig_system_id,
12045             displayNameOut => engStApprovers(approverIndexIn).display_name);
12046         exception
12047           when others then
12048             l_error_code := sqlcode;
12049             if l_error_code = -20213 then
12050               errorCode := -20220;
12051               errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
12052                                                 messageNameIn => 'AME_400837_INV_APR_FOUND',
12053                                                 tokenNameOneIn  => 'PROCESS_NAME',
12054                                                 tokenValueOneIn => 'ame_engine.substituteApprover',
12055                                                 tokenNameTwoIn => 'NAME',
12056                                                 tokenValueTwoIn => nameIn);
12057               raise_application_error(errorCode,errorMessage);
12058             end if;
12059             raise;
12060         end;
12061 
12062       /* Calculate the occurrence value for the substitution. */
12063       currentGroupOrChainId := engStApprovers(approverIndexIn).group_or_chain_id;
12064       occurrence := 1;
12065       for i in reverse 1 .. (approverIndexIn - 1) loop
12066         if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
12067            engStApprovers(approverIndexIn).action_type_id <> engStApprovers(i).action_type_id or
12068            engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
12069            engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
12070           exit;
12071         end if;
12072         if(nameIn = engStApprovers(i).name) then
12073           occurrence := occurrence + 1;
12074         end if;
12075       end loop;
12076       engStApprovers(approverIndexIn).name := nameIn;
12077       engStApprovers(approverIndexIn).occurrence := occurrence;
12078       /* Get and set the approval status. */
12079       engStApprovers(approverIndexIn).approval_status :=
12080         getHandlerApprovalStatus(approverIn => engStApprovers(approverIndexIn));
12081       if(engStApprovers(approverIndexIn).approval_status = ame_util.noResponseStatus
12082          and engRepSubFlag = 'Y' ) then
12083         engSATOFlag := 'Y';
12084       end if;
12085       /* Append ruleIdIn to source value. */
12086       ame_util.appendRuleIdToSource(ruleIdIn => ruleIdIn,
12087                                     sourceInOut => engStApprovers(approverIndexIn).source);
12088       /* Update the occurrence values of the same approver wherever the approver occurs later in the same chain. */
12089       for i in approverIndexIn + 1 .. engStApprovers.count loop
12090         if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
12091            engStApprovers(approverIndexIn).action_type_id <> engStApprovers(i).action_type_id or
12092            engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
12093            engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
12094           exit;
12095         end if;
12096         if(nameIn = engStApprovers(i).name) then
12097           occurrence := occurrence + 1;
12098           engStApprovers(i).occurrence := occurrence;
12099           /* Get and set the approval status for this approver's approval status. */
12100           engStApprovers(i).approval_status :=
12101             getHandlerApprovalStatus(approverIn => engStApprovers(i));
12102         end if;
12103       end loop;
12104       exception
12105         when others then
12106           ame_util.runtimeException(packageNameIn => 'ame_engine',
12107                                     routineNameIn => 'substituteApprover',
12108                                     exceptionNumberIn => sqlcode,
12109                                     exceptionStringIn => sqlerrm);
12110           raise;
12111     end substituteApprover;
12112   procedure truncateChain(approverIndexIn in integer,
12113                           ruleIdIn in integer) as
12114     currentActionTypeId integer;
12115     currentGroupOrChainId integer;
12116     engStApproversCount integer;
12117     firstIndexToTruncate integer;
12118     lastIndexToTruncate integer;
12119     siblingTreeNodeIndex integer;
12120     tempIndex integer;
12121     truncateCount integer;
12122     loopIndex integer;
12123     nextIndex integer;
12124     begin
12125       /*
12126         This procedure copies the current action-type ID and group-or-chain ID into local
12127         variables for efficiency, but does not copy the item ID or item class because these
12128         copy operations are likely to take much longer, and to require substantially more
12129         memory-allocation overhead.
12130       */
12131       currentActionTypeId := engStApprovers(approverIndexIn).action_type_id;
12132       currentGroupOrChainId := engStApprovers(approverIndexIn).group_or_chain_id;
12133       engStApproversCount := engStApprovers.count;
12134       /* First handle the case where no truncation is required. */
12135       tempIndex := approverIndexIn + 1;
12136       if(approverIndexIn = engStApproversCount or
12137          currentGroupOrChainId <> engStApprovers(tempIndex).group_or_chain_id or
12138          currentActionTypeId <> engStApprovers(tempIndex).action_type_id or
12139          engStApprovers(approverIndexIn).item_id <> engStApprovers(tempIndex).item_id or
12140          engStApprovers(approverIndexIn).item_class <> engStApprovers(tempIndex).item_class) then
12141         return;
12142       end if;
12143       /* Evidently the approver at tempIndex is in the same chain.  Find the last approver in that chain. */
12144       firstIndexToTruncate := tempIndex;
12145       lastIndexToTruncate := firstIndexToTruncate;
12146       for i in firstIndexToTruncate + 1 .. engStApproversCount loop
12147         /* Stop at the end of the chain. */
12148         if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
12149            currentActionTypeId <> engStApprovers(i).action_type_id or
12150            engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
12151            engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
12152           lastIndexToTruncate := i - 1;
12153           exit;
12154         end if;
12155         if(i = engStApproversCount) then
12156           lastIndexToTruncate := engStApproversCount;
12157         end if;
12158       end loop;
12159       /*
12160         Truncate from the first index to the last index, inclusive.
12161          delete the rest of the chain.
12162       */
12163       truncateCount := lastIndexToTruncate - firstIndexToTruncate + 1;
12164       /* Copy the end of the list down truncateCount places. */
12165       for i in firstIndexToTruncate .. (engStApproversCount - truncateCount) loop
12166         ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i + truncateCount),
12167                                      approverRecord2Out => engStApprovers(i));
12168       end loop;
12169       /* Code to delete the approvers from the tree whenever there are approver suppressions */
12170       if engPrepareApproverTree then
12171         siblingTreeNodeIndex := ame_util.noSiblingIndex;
12172         /* Approvers Tree is sparse */
12173         loopIndex := engStApproversTree.last;
12174         loop
12175           if engStApproversTree(loopIndex).tree_level = 6 then
12176             if engStApproversTree(loopIndex).approver_index >= firstIndexToTruncate + truncateCount then
12177               engStApproversTree(loopIndex).approver_index := engStApproversTree(loopIndex).approver_index - truncateCount;
12178               nextIndex := engStApproversTree.prior(loopIndex);
12179             elsif engStApproversTree(loopIndex).approver_index >= firstIndexToTruncate
12180                   and engStApproversTree(loopIndex).approver_index < lastIndexToTruncate then
12181               nextIndex := engStApproversTree.prior(loopIndex);
12182               engStApproversTree.delete(loopIndex);
12183             elsif engStApproversTree(loopIndex).approver_index = lastIndexToTruncate then
12184               siblingTreeNodeIndex := engStApproversTree(loopIndex).sibling_index;
12185               nextIndex := engStApproversTree.prior(loopIndex);
12186               engStApproversTree.delete(loopIndex);
12187             elsif engStApproversTree(loopIndex).approver_index = firstIndexToTruncate - 1 then
12188               engStApproversTree(loopIndex).sibling_index := siblingTreeNodeIndex;
12189               nextIndex := engStApproversTree.prior(loopIndex);
12190             else
12191               nextIndex := engStApproversTree.prior(loopIndex);
12192             end if;
12193           else
12194             nextIndex := engStApproversTree.prior(loopIndex);
12195           end if;
12196           exit when engStApproversTree.first = nextIndex;
12197           loopIndex := nextIndex;
12198         end loop;
12199       end if;
12200       /* Delete the last truncateCount places. */
12201       engStApprovers.delete(engStApproversCount - truncateCount + 1, engStApproversCount);
12202       exception
12203         when others then
12204           ame_util.runtimeException(packageNameIn => 'ame_engine',
12205                                     routineNameIn => 'truncateChain',
12206                                     exceptionNumberIn => sqlcode,
12207                                     exceptionStringIn => sqlerrm);
12208           raise;
12209     end truncateChain;
12210   procedure unlockTransaction(fndApplicationIdIn in integer,
12211                               transactionIdIn in varchar2,
12212                               transactionTypeIdIn in varchar2 default null) as
12213     begin
12214       if(engTransactionIsLocked) then
12215         delete from ame_temp_trans_locks
12216           where
12217             fnd_application_id = fndApplicationIdIn and
12218             ((transaction_type_id is null and transactionTypeIdIn is null) or
12219              transaction_type_id = transactionTypeIdIn) and
12220             transaction_id = transactionIdIn;
12221       end if;
12222       engTransactionIsLocked := false;
12223       exception
12224          when others then
12225           ame_util.runtimeException(packageNameIn => 'ame_engine',
12226                                     routineNameIn => 'unlockTransaction',
12227                                     exceptionNumberIn => sqlcode,
12228                                     exceptionStringIn => sqlerrm);
12229           raise;
12230     end unlockTransaction;
12231   procedure updateTransactionState(isTestTransactionIn in boolean,
12232                                    isLocalTransactionIn in boolean,
12233                                    fetchConfigVarsIn in boolean,
12234                                    fetchOldApproversIn in boolean,
12235                                    fetchInsertionsIn in boolean,
12236                                    fetchDeletionsIn in boolean,
12237                                    fetchAttributeValuesIn in boolean,
12238                                    fetchInactiveAttValuesIn in boolean,
12239                                    processProductionActionsIn in boolean,
12240                                    processProductionRulesIn in boolean,
12241                                    updateCurrentApproverListIn in boolean,
12242                                    updateOldApproverListIn in boolean,
12243                                    processPrioritiesIn in boolean,
12244                                    prepareItemDataIn in boolean,
12245                                    prepareRuleIdsIn in boolean,
12246                                    prepareRuleDescsIn in boolean,
12247                                    prepareApproverTreeIn in boolean default false,
12248                                    transactionIdIn in varchar2,
12249                                    ameApplicationIdIn in integer default null,
12250                                    fndApplicationIdIn in integer default null,
12251                                    transactionTypeIdIn in varchar2 default null) as
12252     configVarException exception;
12253     errorCode integer;
12254     errorMessage ame_util.longestStringType;
12255     begin
12256       setContext(isTestTransactionIn => isTestTransactionIn,
12257                  isLocalTransactionIn => isLocalTransactionIn,
12258                  fetchConfigVarsIn => fetchConfigVarsIn,
12259                  fetchOldApproversIn => fetchOldApproversIn,
12260                  fetchInsertionsIn => fetchInsertionsIn,
12261                  fetchDeletionsIn => fetchDeletionsIn,
12262                  fetchAttributeValuesIn => fetchAttributeValuesIn,
12263                  fetchInactiveAttValuesIn => fetchInactiveAttValuesIn,
12264                  processProductionActionsIn => processProductionActionsIn,
12265                  processProductionRulesIn => processProductionRulesIn,
12266                  updateCurrentApproverListIn => updateCurrentApproverListIn,
12267                  updateOldApproverListIn => updateOldApproverListIn,
12268                  processPrioritiesIn => processPrioritiesIn,
12269                  prepareItemDataIn => prepareItemDataIn,
12270                  prepareRuleIdsIn => prepareRuleIdsIn,
12271                  prepareRuleDescsIn => prepareRuleDescsIn,
12272                  prepareApproverTreeIn => prepareApproverTreeIn,
12273                  transactionIdIn => transactionIdIn,
12274                  ameApplicationIdIn => ameApplicationIdIn,
12275                  fndApplicationIdIn => fndApplicationIdIn,
12276                  transactionTypeIdIn => transactionTypeIdIn);
12277       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12278         fnd_log.string
12279           (fnd_log.level_statement
12280           ,'ame_engine.updateTransactionState'
12281           ,'AME Application Id ::: ' || engAmeApplicationId
12282           );
12283         fnd_log.string
12284           (fnd_log.level_statement
12285           ,'ame_engine.updateTransactionState'
12286           ,'AME Transaction Id ::: ' || engTransactionId
12287           );
12288       end if;
12289       /* Added from version 115.217 to log a transaction (backward compatiblity)*/
12290       if updateOldApproverListIn then
12291         logTransaction;
12292       end if;
12293       if(processProductionActionsIn or
12294          processProductionRulesIn or
12295          updateCurrentApproverListIn or
12296          updateOldApproverListIn or
12297          processPrioritiesIn or
12298          prepareItemDataIn or
12299          prepareRuleIdsIn or
12300          prepareRuleDescsIn) then
12301         if(not fetchConfigVarsIn) then
12302           raise configVarException;
12303         end if;
12304         evaluateRules;
12305         fetchApplicableActions;
12306         processExceptions;
12307       end if;
12308       if(updateCurrentApproverListIn or
12309          updateOldApproverListIn) then
12310         processRules(processOnlyProductionsIn => false);
12311       elsif(processProductionRulesIn) then
12312         processRules(processOnlyProductionsIn => true);
12313       end if;
12314       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12315         fnd_log.string
12316           (fnd_log.level_statement
12317           ,'ame_engine.updateTransactionState'
12318           ,'Approver count after processRules ::: ' || engStApprovers.count
12319           );
12320       end if;
12321       if(updateCurrentApproverListIn or
12322          updateOldApproverListIn) then
12323         processAdHocInsertions;
12324         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12325           fnd_log.string
12326             (fnd_log.level_statement
12327             ,'ame_engine.updateTransactionState'
12328             ,'Approver count after processAdHocInsertions ::: ' || engStApprovers.count
12329             );
12330         end if;
12331         processUnresponsiveApprovers;
12332         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12333           fnd_log.string
12334             (fnd_log.level_statement
12335             ,'ame_engine.updateTransactionState'
12336             ,'Approver count after processUnresponsiveApprovers ::: ' || engStApprovers.count
12337             );
12338         end if;
12339         if engRepeatSubstitutions  then
12340           repeatSubstitutions;
12341           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12342             fnd_log.string
12343               (fnd_log.level_statement
12344               ,'ame_engine.updateTransactionState'
12345               ,'Approver count after repeatSubstitutions ::: ' || engStApprovers.count
12346               );
12347           end if;
12348         end if;
12349 
12350         /*
12351           processSuppressions must precede processRepeatedApprovers, because the latter procedure needs to see
12352           any approver deletions, to aggregate approvers correctly.
12353         */
12354         processSuppressions;
12355         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12356           fnd_log.string
12357             (fnd_log.level_statement
12358             ,'ame_engine.updateTransactionState'
12359             ,'Approver count after processSuppressions ::: ' || engStApprovers.count
12360             );
12361         end if;
12362         /*
12363           processSuppressions must precede processRepeatedApprovers so every approver in engStApprovers still
12364           has non-null item_class and item_id fields.
12365         */
12366         processRepeatedApprovers;
12367         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12368           fnd_log.string
12369             (fnd_log.level_statement
12370             ,'ame_engine.updateTransactionState'
12371             ,'Approver count after processRepeatedApprovers ::: ' || engStApprovers.count
12372             );
12373         end if;
12374         /*
12375           processRepeatedApprovers must precede populateEngStVariables so the latter can treat repeated
12376           approvers as equivalent to approving approvers, for purposes of determining whether an item or
12377           transaction's approval process is complete.
12378         */
12379         populateEngStVariables;
12380         if engPrepareApproverTree then
12381           calculateApproverOrderNumbers;
12382           if updateOldApproverListIn then
12383             ame_approver_deviation_pkg.updateDeviationState(
12384                                          engAmeApplicationId
12385                                         ,engTransactionId
12386                                         ,engDeviationResultList
12387                                         ,engStApprovalProcessCompleteYN
12388                                         ,engStApprovers);
12389           end if;
12390         end if;
12391         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12392           if engStApprovers.count = 0 then
12393             fnd_log.string
12394               (fnd_log.level_statement
12395               ,'ame_engine.updateTransactionState'
12396               ,'**************** No Approvers ******************'
12397               );
12398           else
12399             for i in 1 .. engStApprovers.count loop
12400               fnd_log.string
12401                 (fnd_log.level_statement
12402                 ,'ame_engine.updateTransactionState'
12403                 ,'Approver ::: ' || engStApprovers(i).name || ' Order Number ::: ' || engStApprovers(i).approver_order_number
12404                 );
12405             end loop;
12406           end if;
12407         end if;
12408         if(updateOldApproverListIn) then
12409           updateOldApproverList;
12410         end if;
12411       end if;
12412       exception
12413         when configVarException then
12414           errorCode := -20001;
12415           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
12416                                               messageNameIn => 'AME_400691_INV_PARAM_ENG_UPDTX');
12417           ame_util.runtimeException(packageNameIn => 'ame_engine',
12418                                     routineNameIn => 'updateTransactionState',
12419                                     exceptionNumberIn => errorCode,
12420                                     exceptionStringIn => errorMessage);
12421           raise_application_error(errorCode,
12422                                   errorMessage);
12423         when others then
12424           ame_util.runtimeException(packageNameIn => 'ame_engine',
12425                                     routineNameIn => 'updateTransactionState',
12426                                     exceptionNumberIn => sqlcode,
12427                                     exceptionStringIn => sqlerrm);
12428           raise;
12429     end updateTransactionState;
12430   procedure updateOldApproverList as
12431     tempActionTypeIds ame_util.idList;
12432     tempApiValues ame_util.charList;
12433     tempAuthorityValues ame_util.charList;
12434     tempCategories ame_util.charList;
12435     tempCount integer;
12436     tempGroupOrChainIds ame_util.idList;
12437     tempItemClasses ame_util.stringList;
12438     tempItemIds ame_util.stringList;
12439     tempNames ame_util.longStringList;
12440     tempOccurrences ame_util.idList;
12441     tempOrderNumbers ame_util.idList;
12442     tempStatuses ame_util.stringList;
12443     begin
12444       delete from ame_temp_old_approver_lists
12445         where
12446           application_id = engAmeApplicationId and
12447           transaction_id = engTransactionId;
12448       /*
12449         Bulk insert the transaction's current state into ame_temp_old_approver_lists.
12450         Take the state from engStApprovers, to account for all operations on the approver list.
12451       */
12452       ame_util.convertApproversTable2ToValues(approversTableIn => engStApprovers,
12453                                               namesOut => tempNames,
12454                                               itemClassesOut => tempItemClasses,
12455                                               itemIdsOut => tempItemIds,
12456                                               apiInsertionsOut => tempApiValues,
12457                                               authoritiesOut => tempAuthorityValues,
12458                                               actionTypeIdsOut => tempActionTypeIds,
12459                                               groupOrChainIdsOut => tempGroupOrChainIds,
12460                                               occurrencesOut => tempOccurrences,
12461                                               approverCategoriesOut => tempCategories,
12462                                               statusesOut => tempStatuses);
12463       tempCount := tempNames.count;
12464       for i in 1 .. tempCount loop
12465         if engStApprovers.exists(i) and engStApprovers(i).approver_order_number is not null then
12466            tempOrderNumbers(i) := engStApprovers(i).approver_order_number;
12467         else
12468            tempOrderNumbers(i) := i;
12469         end if;
12470       end loop;
12471       for i in 1..engStApprovers.count loop
12472         setInsertedApprovalStatus(currentApproverIndexIn => i
12473                                  ,approvalStatusIn => engStApprovers(i).approval_status);
12474       end loop;
12475       forall i in 1 .. tempCount
12476         insert into ame_temp_old_approver_lists(
12477           transaction_id,
12478           application_id,
12479           order_number,
12480           name,
12481           item_class,
12482           item_id,
12483           api_insertion,
12484           authority,
12485           action_type_id,
12486           group_or_chain_id,
12487           occurrence,
12488           approver_category,
12489           approval_status) values(
12490             engTransactionId,
12491             engAmeApplicationId,
12492             tempOrderNumbers(i),
12493             tempNames(i),
12494             tempItemClasses(i),
12495             tempItemIds(i),
12496             tempApiValues(i),
12497             tempAuthorityValues(i),
12498             tempActionTypeIds(i),
12499             tempGroupOrChainIds(i),
12500             tempOccurrences(i),
12501             tempCategories(i),
12502             tempStatuses(i));
12503       exception
12504         when others then
12505           ame_util.runtimeException(packageNameIn => 'ame_engine',
12506                                     routineNameIn => 'updateOldApproverList',
12507                                     exceptionNumberIn => sqlcode,
12508                                     exceptionStringIn => sqlerrm);
12509           raise;
12510     end updateOldApproverList;
12511   /* test procedure */
12512   procedure testEngine(printContextYNIn in varchar2 default 'N',
12513                        printAppRulesYNIn in varchar2 default 'N',
12514                        printApproversYNIn in varchar2 default 'N') as
12515     begin
12516 null;
12517       exception
12518         when others then
12519           ame_util.runtimeException(packageNameIn => 'ame_engine',
12520                                     routineNameIn => 'testEngine',
12521                                     exceptionNumberIn => sqlcode,
12522                                     exceptionStringIn => sqlerrm);
12523           raise;
12524     end testEngine;
12525   procedure updateApprovalStatus(applicationIdIn in number,
12526                                  transactionTypeIn in varchar2,
12527                                  transactionIdIn in varchar2,
12528                                  approverIn in ame_util.approverRecord2,
12529                                  notificationIn in ame_util2.notificationRecord
12530                                          default ame_util2.emptyNotificationRecord,
12531                                  forwardeeIn in ame_util.approverRecord2 default
12532                                              ame_util.emptyApproverRecord2,
12533                                  updateItemIn in boolean default false) as
12534     ameApplicationId integer;
12535     apiInsertionException exception;
12536     approver ame_util.approverRecord2;
12537     approverInIndex integer;
12538     approverInIsSpecialForwardee boolean;
12539     badApproverException exception;
12540     badForwardeeException exception;
12541     badStatusException exception;
12542     currentApprovers ame_util.approversTable2;
12543     errorCode integer;
12544     errorMessage ame_util.longStringType;
12545     l_error_code number;
12546     firstIndexInChain integer;
12547     forwardee ame_util.approverRecord2;
12548     forwardeeIndex integer;
12549     forwardeeType ame_util.stringType;
12550     forwarderFound boolean;
12551     forwarderType ame_util.stringType;
12552     forwardingBehavior ame_util.stringType;
12553     insertedApprover ame_util.approverRecord2;
12554     prevApproverIndex integer;
12555     prevApproverOccurrence integer;
12556     repeatedIndexes ame_util.idList;
12557     repeatedAppIndexes ame_util.idList;
12558     superiorApprover ame_util.approverRecord2;
12559     tempInsertionOrder integer;
12560     tempParameter ame_temp_insertions.parameter%type;
12561     tempCOAGroupActionTypeId integer;
12562     tempPreGroupActionTypeId integer;
12563     tempPostGroupActionTypeId integer;
12564     votingRegime ame_util.charType;
12565     approverOldApprovalStatus varchar2(50);
12566     tempReason varchar2(50);
12567     tempStatus varchar2(50);
12568     tempfrwCount number;
12569     l_actiontypeName varchar2(50);
12570     l_votingRegime varchar2(20);
12571     l_actionTypeId Number;
12572     l_frw_index number;
12573     begin
12574       /* Lock the transaction. */
12575       ame_engine.lockTransaction(fndApplicationIdIn => applicationIdIn,
12576                                  transactionIdIn => transactionIdIn,
12577                                  transactionTypeIdIn => transactionTypeIn);
12578       /* Clear the exception log when required. */
12579       if(approverIn.approval_status = ame_util.clearExceptionsStatus) then
12580         delete from ame_exceptions_log
12581           where
12582             transaction_id = transactionIdIn and
12583             application_id = ameApplicationId;
12584         ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
12585                                      transactionIdIn => transactionIdIn,
12586                                      transactionTypeIdIn => transactionTypeIn);
12587         return;
12588       end if;
12589       /* Locate approverIn in the current approver list, if possible. */
12590       ame_engine.updateTransactionState(isTestTransactionIn => false,
12591                                         isLocalTransactionIn => false,
12592                                         fetchConfigVarsIn => true,
12593                                         fetchOldApproversIn => true,
12594                                         fetchInsertionsIn => true,
12595                                         fetchDeletionsIn => true,
12596                                         fetchAttributeValuesIn => true,
12597                                         fetchInactiveAttValuesIn => false,
12598                                         processProductionActionsIn => false,
12599                                         processProductionRulesIn => false,
12600                                         updateCurrentApproverListIn => true,
12601                                         updateOldApproverListIn => false,
12602                                         processPrioritiesIn => true,
12603                                         prepareItemDataIn => false,
12604                                         prepareRuleIdsIn => false,
12605                                         prepareRuleDescsIn => false,
12606                                         prepareApproverTreeIn => true,
12607                                         transactionIdIn => transactionIdIn,
12608                                         ameApplicationIdIn => null,
12609                                         fndApplicationIdIn => applicationIdIn,
12610                                         transactionTypeIdIn => transactionTypeIn);
12611       ame_engine.getApprovers(approversOut => currentApprovers);
12612       ame_engine.getRepeatedIndexes(repeatedIndexesOut    => repeatedIndexes
12613                                    ,repeatedAppIndexesOut => repeatedAppIndexes);
12614       ameApplicationId := ame_engine.getAmeApplicationId;
12615       approverInIndex := null;
12616       if(approverIn.occurrence is null or
12617          approverIn.group_or_chain_id is null or
12618          approverIn.action_type_id is null or
12619          approverIn.item_id is null or
12620          approverIn.item_class is null) then /* partial match */
12621         /* We need to split the search below to take in to account that the user
12622            could be trying to clear an approvers status */
12623         if(approverIn.approval_status is null) then /* Clear Approver status */
12624           for i in 1 .. currentApprovers.count loop
12625             if(approverIn.name = currentApprovers(i).name and
12626                (currentApprovers(i).approval_status = ame_util.approvedStatus or
12627                 currentApprovers(i).approval_status = ame_util.approveAndForwardStatus or
12628                 currentApprovers(i).approval_status = ame_util.forwardStatus or
12629                 currentApprovers(i).approval_status = ame_util2.reassignStatus or
12630                 currentApprovers(i).approval_status = ame_util.rejectStatus or
12631                 currentApprovers(i).approval_status = ame_util.notifiedStatus or
12632                 currentApprovers(i).approval_status = ame_util.exceptionStatus or
12633                 currentApprovers(i).approval_status = ame_util.noResponseStatus ) and
12634                (approverIn.occurrence is null or
12635                 approverIn.occurrence = currentApprovers(i).occurrence) and
12636                (approverIn.group_or_chain_id is null or
12637                 approverIn.group_or_chain_id = currentApprovers(i).group_or_chain_id) and
12638                (approverIn.action_type_id is null or
12639                 approverIn.action_type_id = currentApprovers(i).action_type_id) and
12640                (approverIn.item_id is null or
12641                 approverIn.item_id = currentApprovers(i).item_id) and
12642                (approverIn.item_class is null or
12643                 approverIn.item_class = currentApprovers(i).item_class)) then
12644               approverInIndex := i;
12645               exit;
12646             end if;
12647           end loop;
12648         else
12649           for i in 1 .. currentApprovers.count loop
12650             if(approverIn.name = currentApprovers(i).name and
12651                (currentApprovers(i).approval_status is null or
12652                 currentApprovers(i).approval_status = ame_util.nullStatus or
12653                 (currentApprovers(i).approver_category = ame_util.approvalApproverCategory and
12654                  currentApprovers(i).approval_status = ame_util.notifiedStatus)) and
12655                (approverIn.occurrence is null or
12656                 approverIn.occurrence = currentApprovers(i).occurrence) and
12657                (approverIn.group_or_chain_id is null or
12658                 approverIn.group_or_chain_id = currentApprovers(i).group_or_chain_id) and
12659                (approverIn.action_type_id is null or
12660                 approverIn.action_type_id = currentApprovers(i).action_type_id) and
12661                (approverIn.item_id is null or
12662                 approverIn.item_id = currentApprovers(i).item_id) and
12663                (approverIn.item_class is null or
12664                 approverIn.item_class = currentApprovers(i).item_class)) then
12665               approverInIndex := i;
12666               exit;
12667             end if;
12668           end loop;
12669         end if;
12670       else /* complete match */
12671         for i in 1 .. currentApprovers.count loop
12672           if(ame_engine.approversMatch(approverRecord1In => currentApprovers(i),
12673                                        approverRecord2In => approverIn)) then
12674             approverInIndex := i;
12675             exit;
12676           end if;
12677         end loop;
12678       end if;
12679       /* Initialize the local variable approver. */
12680       if(approverInIndex is null) then
12681         ame_util.copyApproverRecord2(approverRecord2In => approverIn,
12682                                      approverRecord2Out => approver);
12683       else
12684         ame_util.copyApproverRecord2(approverRecord2In => currentApprovers(approverInIndex),
12685                                      approverRecord2Out => approver);
12686         approverOldApprovalStatus := approver.approval_status;
12687         approver.approval_status := approverIn.approval_status;
12688       end if;
12689       /*
12690         Most of the remaining code should reference approver rather than approverIn or
12691         currentApprovers(approverInIndex).  Any code below this comment that cannot reference
12692         approver should have a comment explaining why.
12693       */
12694       /* Make sure the input approval statuses are valid. */
12695       if((approver.approver_category = ame_util.approvalApproverCategory and
12696           approver.approval_status not in (ame_util.approvedStatus,
12697                                            ame_util.approveAndForwardStatus,
12698                                            ame_util.forwardStatus,
12699                                            ame_util.rejectStatus,
12700                                            ame_util.noResponseStatus,
12701                                            ame_util.nullStatus,
12702                                            ame_util.notifiedStatus,
12703                                            ame_util2.reassignStatus) and
12704           approver.approval_status is not null) or
12705          (approver.approver_category = ame_util.fyiApproverCategory and
12706           approver.approval_status is not null and
12707           approver.approval_status <> ame_util.notifiedStatus)) then
12708         raise badStatusException;
12709       end if;
12710       /* Prepare forwardee (if any), if the forwarder is in the current list. */
12711       if(approver.approval_status in (ame_util.approveAndForwardStatus, ame_util.forwardStatus) and
12712          approverInIndex is not null) then
12713         /* Make sure a valid forwardee exists for forwardings. */
12714         if(forwardeeIn.name is null or
12715            forwardeeIn.name = approver.name) then
12716           raise badForwardeeException;
12717         end if;
12718         if(approver.source like (ame_util.specialForwardInsertion || '%')) then
12719           approverInIsSpecialForwardee := true;
12720         else
12721           approverInIsSpecialForwardee := false;
12722         end if;
12723         /* Copy forwardeeIn to forwardee. */
12724         ame_util.copyApproverRecord2(approverRecord2In => forwardeeIn,
12725                                      approverRecord2Out => forwardee);
12726         /* If approverInIsSpecialForwardee, silently convert api_insertion to
12727            ame_util.apiInsertion for forwardee */
12728         if approverInIsSpecialForwardee then
12729           forwardee.api_insertion := ame_util.apiInsertion;
12730         end if;
12731         /* Make sure the forwardee has the correct api_insertion value for COA forwarders. */
12732         if(/* Special forwardees can only do ad-hoc forwardings. */
12733            (approverInIsSpecialForwardee and
12734             forwardee.api_insertion <> ame_util.apiInsertion) or
12735            /* Ad-hoc approvers can only do ad-hoc forwardings. */
12736            ((not approverInIsSpecialForwardee and
12737              approver.authority <> ame_util.authorityApprover or
12738              approver.api_insertion = ame_util.apiInsertion) and
12739             forwardee.api_insertion <> ame_util.apiInsertion) or
12740            /* COA approvers other than special forwardees can only do COA forwardings. */
12741            (not approverInIsSpecialForwardee and
12742             approver.authority = ame_util.authorityApprover and
12743             approver.api_insertion <> ame_util.apiInsertion and
12744             forwardee.api_insertion <> ame_util.apiAuthorityInsertion)) then
12745           raise apiInsertionException;
12746         end if;
12747         /* Make sure forwardee has complete approver-matching data. */
12748         if(forwardee.orig_system is null or
12749            forwardee.orig_system_id is null or
12750            forwardee.display_name is null) then
12751            begin
12752             ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn =>forwardee.name,
12753                                                               origSystemOut => forwardee.orig_system,
12754                                                               origSystemIdOut => forwardee.orig_system_id,
12755                                                               displayNameOut => forwardee.display_name);
12756            exception
12757              when others then
12758                l_error_code := sqlcode;
12759                if l_error_code = -20213 then
12760                  errorCode := -20221;
12761                  errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
12762                                                    messageNameIn => 'AME_400837_INV_APR_FOUND',
12763                                                    tokenNameOneIn  => 'PROCESS_NAME',
12764                                                    tokenValueOneIn => 'ame_engine.updateApprovalStatus',
12765                                                    tokenNameTwoIn => 'NAME',
12766                                                    tokenValueTwoIn => forwardee.name);
12767                raise_application_error(errorCode,errorMessage);
12768                end if;
12769                raise;
12770            end;
12771 
12772         end if;
12773         /*
12774           If the forwardee is from a different originating system than the forwarder,
12775           make sure the forwardee is an ad-hoc insertion.  Make this change silently,
12776           so calling applications don't have to be originating-system aware.
12777         */
12778         if(approver.orig_system <> forwardee.orig_system) then
12779           forwardee.api_insertion := ame_util.apiInsertion;
12780         end if;
12781         forwardee.item_class := approver.item_class;
12782         forwardee.item_id := approver.item_id;
12783         forwardee.authority := approver.authority;
12784         forwardee.action_type_id := approver.action_type_id;
12785         forwardee.group_or_chain_id := approver.group_or_chain_id;
12786       end if;
12787       /* Log the status update to the history table. */
12788       if(approverInIndex is null) then
12789         insert into ame_approvals_history(transaction_id,
12790                                           application_id,
12791                                           approval_status,
12792                                           row_timestamp,
12793                                           item_class,
12794                                           item_id,
12795                                           name,
12796                                           approver_category,
12797                                           action_type_id,
12798                                           group_or_chain_id,
12799                                           occurrence)
12800           values(transactionIdIn,
12801                  ameApplicationId,
12802                  decode(approver.approval_status,
12803                         ame_util.nullStatus, ame_util.nullHistoryStatus,
12804                         null, ame_util.nullHistoryStatus,
12805                         approver.approval_status),
12806                  sysdate,
12807                  approver.item_class,
12808                  approver.item_id,
12809                  approver.name,
12810                  approver.approver_category,
12811                  ame_util.nullHistoryActionTypeId,
12812                  ame_util.nullHistoryGroupOrChainId,
12813                  ame_util.nullHistoryOccurrence);
12814         /*  As approver is no longer in the approval list, log the message in the
12815             history table with a cleared date equal to sysdate. Also, first set
12816             date_cleared for  other possible rows for this approver in the history
12817             table so  that rows do not appear in the history table. */
12818         update AME_TRANS_APPROVAL_HISTORY
12819            set date_cleared = sysdate
12820           where transaction_id = transactionIdIn
12821             and application_id = ameApplicationId
12822             and name = approver.name
12823             and (approver.item_class is null or
12824                  item_class = approver.item_class)
12825             and (approver.item_id is null or
12826                  item_id = approver.item_id)
12827             and (approver.action_type_id is null or
12828                  action_type_id = approver.action_type_id)
12829             and (approver.group_or_chain_id is null or
12830                  group_or_chain_id = approver.group_or_chain_id)
12831             and (approver.occurrence is null or
12832                  occurrence = approver.occurrence)
12833             and date_cleared is null;
12834       /* Log the approvers response in the Notification Approval History table before
12835          doing any further processing */
12836         insertIntoTransApprovalHistory
12837           (transactionIdIn         => transactionIdIn
12838           ,applicationIdIn         => ameApplicationId
12839           ,orderNumberIn           => approver.approver_order_number
12840           ,nameIn                  => approver.name
12841           ,appCategoryIn           => approver.approver_category
12842           ,itemClassIn             => approver.item_class
12843           ,itemIdIn                => approver.item_id
12844           ,actionTypeIdIn          => ame_util.nullHistoryActionTypeId
12845           ,authorityIn             => approver.authority
12846           ,statusIn                => approver.approval_status
12847           ,grpOrChainIdIn          => ame_util.nullHistoryGroupOrChainId
12848           ,occurrenceIn            => ame_util.nullHistoryOccurrence
12849           ,apiInsertionIn          => approver.api_insertion
12850           ,memberOrderNumberIn     => approver.member_order_number
12851           ,notificationIdIn        => notificationIn.notification_id
12852           ,userCommentsIn          => notificationIn.user_comments
12853           ,dateClearedIn           => sysdate
12854           ,historyTypeIn           => 'APPROVERNOTPRESENT');
12855         /* Insert a warning into AME's exception log and return. */
12856         errorCode := -20001;
12857         errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
12858                                             messageNameIn => 'AME_400065_API_NO_MATCH_APPR2');
12859         /*
12860           Pass localErrorIn => true in this case, because we're just logging a warning
12861           to the AME exception log, and we don't want the warning to appear in the
12862           Workflow context stack.
12863         */
12864         ame_util.runtimeException(packageNameIn => 'ame_engine',
12865                                   routineNameIn => 'updateApprovalStatus',
12866                                   exceptionNumberIn => errorCode,
12867                                   exceptionStringIn => errorMessage);
12868         return;
12869       end if;
12870       insert into ame_approvals_history(transaction_id,
12871                                         application_id,
12872                                         approval_status,
12873                                         row_timestamp,
12874                                         item_class,
12875                                         item_id,
12876                                         name,
12877                                         approver_category,
12878                                         action_type_id,
12879                                         group_or_chain_id,
12880                                         occurrence)
12881         values(transactionIdIn,
12882                ameApplicationId,
12883                decode(approver.approval_status,
12884                       ame_util.nullStatus, ame_util.nullHistoryStatus,
12885                       null, ame_util.nullHistoryStatus,
12886                       approver.approval_status),
12887                sysdate,
12888                approver.item_class,
12889                approver.item_id,
12890                approver.name,
12891                approver.approver_category,
12892                approver.action_type_id,
12893                approver.group_or_chain_id,
12894                approver.occurrence);
12895       /*
12896         If the approver has been suppressed or is a repeated approver, disregard their response,
12897         even if they're trying to forward.
12898       */
12899       if(approverOldApprovalStatus in (ame_util.suppressedStatus, ame_util.beatByFirstResponderStatus, ame_util.repeatedStatus)) then
12900         /* The response though disregarded must be logged in the history table. This should not be shown in
12901            the history region. Hence set the date_cleared to sysdate. */
12902         insertIntoTransApprovalHistory
12903           (transactionIdIn         => transactionIdIn
12904           ,applicationIdIn         => ameApplicationId
12905           ,orderNumberIn           => approver.approver_order_number
12906           ,nameIn                  => approver.name
12907           ,appCategoryIn           => approver.approver_category
12908           ,itemClassIn             => approver.item_class
12909           ,itemIdIn                => approver.item_id
12910           ,actionTypeIdIn          => approver.action_type_id
12911           ,authorityIn             => approver.authority
12912           ,statusIn                => approver.approval_status
12913           ,grpOrChainIdIn          => approver.group_or_chain_id
12914           ,occurrenceIn            => approver.occurrence
12915           ,apiInsertionIn          => approver.api_insertion
12916           ,memberOrderNumberIn     => approver.member_order_number
12917           ,notificationIdIn        => notificationIn.notification_id
12918           ,userCommentsIn          => notificationIn.user_comments
12919           ,dateClearedIn           => sysdate
12920           ,historyTypeIn           => 'APPROVERPRESENT');
12921         return;
12922       end if;
12923       /* Log the approvers response in the Notification Approval History table before
12924          doing any further processing */
12925         insertIntoTransApprovalHistory
12926           (transactionIdIn         => transactionIdIn
12927           ,applicationIdIn         => ameApplicationId
12928           ,orderNumberIn           => approver.approver_order_number
12929           ,nameIn                  => approver.name
12930           ,appCategoryIn           => approver.approver_category
12931           ,itemClassIn             => approver.item_class
12932           ,itemIdIn                => approver.item_id
12933           ,actionTypeIdIn          => approver.action_type_id
12934           ,authorityIn             => approver.authority
12935           ,statusIn                => approver.approval_status
12936           ,grpOrChainIdIn          => approver.group_or_chain_id
12937           ,occurrenceIn            => approver.occurrence
12938           ,apiInsertionIn          => approver.api_insertion
12939           ,memberOrderNumberIn     => approver.member_order_number
12940           ,notificationIdIn        => notificationIn.notification_id
12941           ,userCommentsIn          => notificationIn.user_comments
12942           ,dateClearedIn           => null
12943           ,historyTypeIn           => 'APPROVERPRESENT');
12944       /*
12945         Update the status of approverIn in ame_temp_old_approver_lists.  If updateItemIn
12946         is true, update also any other occurrences of the same approver for the same item
12947         class and item ID.
12948       */
12949       if(updateItemIn) then
12950         if(approver.approval_status in (ame_util.forwardStatus, ame_util.approveAndForwardStatus)) then
12951           /* Update the forwarder proper. */
12952           update ame_temp_old_approver_lists
12953             set approval_status = approver.approval_status
12954             where
12955               application_id = ameApplicationId and
12956               transaction_id = transactionIdIn and
12957               name = approver.name and
12958               item_class = approver.item_class and
12959               item_id = approver.item_id and
12960               action_type_id = approver.action_type_id and
12961               group_or_chain_id = approver.group_or_chain_id and
12962               occurrence = approver.occurrence;
12963           /* Suppress other occurrences of the approver, for the same item. */
12964           update ame_temp_old_approver_lists
12965             set approval_status = ame_util.suppressedStatus
12966             where
12967               application_id = ameApplicationId and
12968               transaction_id = transactionIdIn and
12969               name = approver.name and
12970               item_class = approver.item_class and
12971               item_id = approver.item_id and
12972               (action_type_id <> approver.action_type_id or
12973                group_or_chain_id <> approver.group_or_chain_id or
12974                occurrence <> approver.occurrence);
12975         else
12976           update ame_temp_old_approver_lists
12977             set approval_status = approver.approval_status
12978             where
12979               application_id = ameApplicationId and
12980               transaction_id = transactionIdIn and
12981               name = approver.name and
12982               item_class = approver.item_class and
12983               item_id = approver.item_id;
12984         end if;
12985       else
12986         update ame_temp_old_approver_lists
12987           set approval_status = approver.approval_status
12988           where
12989             application_id = ameApplicationId and
12990             transaction_id = transactionIdIn and
12991             name = approver.name and
12992             item_class = approver.item_class and
12993             item_id = approver.item_id and
12994             action_type_id = approver.action_type_id and
12995             group_or_chain_id = approver.group_or_chain_id and
12996             occurrence = approver.occurrence;
12997       end if;
12998       --+
12999       if approverInIndex is not null then
13000         setInsertedApprovalStatus(currentApproverIndexIn => approverInIndex
13001                                   ,approvalStatusIn => approver.approval_status);
13002       end if;
13003       if approver.approval_status in (ame_util.approvedStatus
13004                                      ,ame_util.rejectStatus
13005                                      ,ame_util.approveAndForwardStatus
13006                                      ,ame_util.forwardStatus
13007                                      ,ame_util.noResponseStatus) then
13008         for z in 1 .. repeatedIndexes.count loop
13009           if repeatedIndexes(z) = approverInIndex and repeatedAppIndexes(z) <> approverInIndex then
13010             update ame_temp_old_approver_lists
13011                set approval_status = decode(approver.approval_status
13012                                            ,ame_util.approvedStatus
13013                                            ,ame_util.approvedByRepeatedStatus
13014                                            ,ame_util.approveAndForwardStatus
13015                                            ,ame_util.approvedByRepeatedStatus
13016                                            ,ame_util.rejectStatus
13017                                            ,ame_util.rejectedByRepeatedStatus
13018                                            ,ame_util.forwardStatus
13019                                            ,ame_util2.forwardByRepeatedStatus
13020                                            ,ame_util2.reassignStatus
13021                                            ,ame_util.nullStatus
13022                                            ,ame_util.noResponseStatus
13023                                            ,ame_util2.noResponseByRepeatedStatus
13024                                            ,ame_util.repeatedStatus)
13025              where application_id = ameApplicationId
13026                and transaction_id = transactionIdIn
13027                and name           = approver.name
13028                and item_class        = currentApprovers(repeatedAppIndexes(z)).item_class
13029                and item_id           = currentApprovers(repeatedAppIndexes(z)).item_id
13030                and action_type_id    = currentApprovers(repeatedAppIndexes(z)).action_type_id
13031                and group_or_chain_id = currentApprovers(repeatedAppIndexes(z)).group_or_chain_id
13032                and occurrence        = currentApprovers(repeatedAppIndexes(z)).occurrence
13033                and approval_status in ( ame_util.notifiedByRepeatedStatus
13034                                        ,ame_util.repeatedStatus);
13035             select decode(approver.approval_status
13036                                            ,ame_util.approvedStatus
13037                                            ,ame_util.approvedByRepeatedStatus
13038                                            ,ame_util.approveAndForwardStatus
13039                                            ,ame_util.approvedByRepeatedStatus
13040                                            ,ame_util.rejectStatus
13041                                            ,ame_util.rejectedByRepeatedStatus
13042                                            ,ame_util.forwardStatus
13043                                            ,ame_util2.forwardByRepeatedStatus
13044                                            ,ame_util2.reassignStatus
13045                                            ,ame_util.nullStatus
13046                                            ,ame_util.noResponseStatus
13047                                            ,ame_util2.noResponseByRepeatedStatus
13048                                            ,ame_util.repeatedStatus) into tempStatus from dual;
13049             setInsertedApprovalStatus(currentApproverIndexIn => repeatedAppIndexes(z)
13050                                      ,approvalStatusIn => tempStatus);
13051             l_frw_index := repeatedAppIndexes(z);
13052             l_actionTypeId := currentApprovers(l_frw_index).action_type_id;
13053             l_votingRegime := null;
13054             l_votingRegime := ame_engine.getActionTypeVotingRegime(l_actionTypeId);
13055             if l_votingRegime is null then
13056               l_votingRegime := ame_approval_group_pkg.getVotingRegime(
13057                              approvalGroupIdIn => currentApprovers(l_frw_index).group_or_chain_id ,
13058                              applicationIdIn => ameApplicationId);
13059             end if;
13060             if l_votingRegime = ame_util.firstApproverVoting then
13061               tempfrwCount := 0;
13062               select count(*)
13063                  into tempfrwCount
13064                  from ame_temp_old_approver_lists
13065                 where
13066                   application_id = ameApplicationId and
13067                   transaction_id = transactionIdIn and
13068                   item_class = currentApprovers(l_frw_index).item_class and
13069                   item_id = currentApprovers(l_frw_index).item_id and
13070                   action_type_id = currentApprovers(l_frw_index).action_type_id and
13071                   group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13072                   approver_category = ame_util.approvalApproverCategory and
13073                   approval_status  in (ame_util.notifiedStatus
13074                                        ,ame_util.notifiedByRepeatedStatus) and
13075                  exists ( select null
13076                           from ame_temp_old_approver_lists
13077                           where  application_id = ameApplicationId and
13078                                  transaction_id = transactionIdIn and
13079                                  item_class = currentApprovers(l_frw_index).item_class and
13080                                  item_id = currentApprovers(l_frw_index).item_id and
13081                                  action_type_id = currentApprovers(l_frw_index).action_type_id and
13082                                  group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13083                                  approver_category = ame_util.approvalApproverCategory and
13084                                  approval_status in (ame_util.approvedStatus
13085                                                     ,ame_util.approvedByRepeatedStatus
13086                                                     ,ame_util.rejectStatus
13087                                                     ,ame_util.rejectedByRepeatedStatus)
13088                            ) and
13089                 not exists ( select null
13090                           from ame_temp_old_approver_lists
13091                           where  application_id = ameApplicationId and
13092                                  transaction_id = transactionIdIn and
13093                                  item_class = currentApprovers(l_frw_index).item_class and
13094                                  item_id = currentApprovers(l_frw_index).item_id and
13095                                  action_type_id = currentApprovers(l_frw_index).action_type_id and
13096                                  group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13097                                  approver_category = ame_util.approvalApproverCategory and
13098                                  (approval_status  is null or approval_status in (
13099                                                      ame_util.nullStatus
13100                                                     ,ame_util.repeatedStatus)));
13101                if tempfrwCount > 0 then
13102                  update ame_temp_old_approver_lists
13103                  set approval_status = ame_util.beatByFirstResponderStatus
13104                  where
13105                   application_id = ameApplicationId and
13106                   transaction_id = transactionIdIn and
13107                   item_class = currentApprovers(l_frw_index).item_class and
13108                   item_id = currentApprovers(l_frw_index).item_id and
13109                   action_type_id = currentApprovers(l_frw_index).action_type_id and
13110                   group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13111                   approver_category = ame_util.approvalApproverCategory and
13112                   approval_status in (ame_util.notifiedStatus,ame_util.notifiedByRepeatedStatus );
13113                  insertIntoTransApprovalHistory
13114                    (transactionIdIn         => transactionIdIn
13115                    ,applicationIdIn         => ameApplicationId
13116                    ,orderNumberIn           => currentApprovers(l_frw_index).approver_order_number
13117                    ,nameIn                  => currentApprovers(l_frw_index).name
13118                    ,appCategoryIn           => null
13119                    ,itemClassIn             => currentApprovers(l_frw_index).item_class
13120                    ,itemIdIn                => currentApprovers(l_frw_index).item_id
13121                    ,actionTypeIdIn          => currentApprovers(l_frw_index).action_type_id
13122                    ,authorityIn             => null
13123                    ,statusIn                => null
13124                    ,grpOrChainIdIn          => currentApprovers(l_frw_index).group_or_chain_id
13125                    ,occurrenceIn            => currentApprovers(l_frw_index).occurrence
13126                    ,apiInsertionIn          => currentApprovers(l_frw_index).api_insertion
13127                    ,memberOrderNumberIn     => currentApprovers(l_frw_index).member_order_number
13128                    ,notificationIdIn        => notificationIn.notification_id
13129                    ,userCommentsIn          => null
13130                    ,dateClearedIn           => null
13131                    ,historyTypeIn           => 'BEATBYFIRSTRESPONDER');
13132                end if;
13133             end if;
13134           end if;
13135         end loop;
13136       end if;
13137       if(approver.approval_status is null or approver.approval_status in (ame_util.approvedStatus, ame_util.rejectStatus )) then
13138         /* Account for approval-group and chain-of-authority voting. */
13139         /* get action type id's  for  ame_util.groupChainApprovalTypeName,
13140            ame_util.postApprovalTypeName and ame_util.preApprovalTypeName */
13141         tempCOAGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
13142                                          ame_util.groupChainApprovalTypeName);
13143         tempPreGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
13144                                          ame_util.preApprovalTypeName);
13145         tempPostGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
13146                                          ame_util.postApprovalTypeName);
13147         if approver.action_type_id in (tempPreGroupActionTypeId
13148                                       ,tempPostGroupActionTypeId) then
13149                  -- removed tempCOAGroupActionTypeId from above list for the
13150                  -- bug 4095605
13151           votingRegime := ame_approval_group_pkg.getVotingRegime(
13152                            approvalGroupIdIn => approver.group_or_chain_id ,
13153                            applicationIdIn => ameApplicationId);
13154                                -- in approver.group_or_chain_id
13155         else
13156           votingRegime := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => approver.action_type_id);
13157         end if;
13158         if(votingRegime = ame_util.firstApproverVoting) then
13159           if approver.approval_status in (ame_util.approvedStatus, ame_util.rejectStatus ) then
13160             /*
13161             approverIn must be the first responder (otherwise, they would be suppressed,
13162             and we would have returned above).  Suppress the other approval approvers in the
13163             group or chain (including other occurrences of the input approver).
13164             */
13165             update ame_temp_old_approver_lists
13166               set approval_status = ame_util.beatByFirstResponderStatus
13167               where
13168                 application_id = ameApplicationId and
13169                 transaction_id = transactionIdIn and
13170                 (name <> approver.name or
13171                  occurrence <> approver.occurrence) and
13172                 item_class = approver.item_class and
13173                 item_id = approver.item_id and
13174                 action_type_id = approver.action_type_id and
13175                 group_or_chain_id = approver.group_or_chain_id and
13176                   approver_category = ame_util.approvalApproverCategory and
13177                   approval_status in (ame_util.notifiedStatus,ame_util.notifiedByRepeatedStatus);
13178              for i in 1..currentApprovers.count loop
13179               if currentApprovers(i).item_class = approver.item_class and
13180               currentApprovers(i).item_id = approver.item_id and
13181               currentApprovers(i).action_type_id = approver.action_type_id and
13182               currentApprovers(i).group_or_chain_id = approver.group_or_chain_id and
13183               currentApprovers(i).approver_category = approver.approver_category and
13184               currentApprovers(i).approval_status = ame_util.notifiedStatus and
13185               (currentApprovers(i).name <> approver.name or
13186               currentApprovers(i).occurrence <>  approver.occurrence) then
13187               setInsertedApprovalStatus(currentApproverIndexIn => i
13188                                        ,approvalStatusIn => ame_util.beatByFirstResponderStatus);
13189               end if;
13190              end loop;
13191             /* Insert rows in the notification approval history region for approvers
13192                with beat by first responder */
13193             insertIntoTransApprovalHistory
13194               (transactionIdIn         => transactionIdIn
13195               ,applicationIdIn         => ameApplicationId
13196               ,orderNumberIn           => approver.approver_order_number
13197               ,nameIn                  => approver.name
13198               ,appCategoryIn           => null
13199               ,itemClassIn             => approver.item_class
13200               ,itemIdIn                => approver.item_id
13201               ,actionTypeIdIn          => approver.action_type_id
13202               ,authorityIn             => null
13203               ,statusIn                => null
13204               ,grpOrChainIdIn          => approver.group_or_chain_id
13205               ,occurrenceIn            => approver.occurrence
13206               ,apiInsertionIn          => approver.api_insertion
13207               ,memberOrderNumberIn     => approver.member_order_number
13208               ,notificationIdIn        => notificationIn.notification_id
13209               ,userCommentsIn          => null
13210               ,dateClearedIn           => null
13211               ,historyTypeIn           => 'BEATBYFIRSTRESPONDER');
13212           elsif approver.approval_status is null then
13213             /*
13214               the approval status is null. This is the request to clear the approval status.
13215               As this approver is from a FRW approver group, need to clear the status of all the group members.
13216             */
13217             update ame_temp_old_approver_lists
13218                set approval_status = null
13219              where
13220               application_id = ameApplicationId and
13221               transaction_id = transactionIdIn and
13222               (name <> approver.name or
13223                occurrence <> approver.occurrence) and
13224               item_class = approver.item_class and
13225               item_id = approver.item_id and
13226               action_type_id = approver.action_type_id and
13227               group_or_chain_id = approver.group_or_chain_id and
13228               approver_category = ame_util.approvalApproverCategory;
13229               -- and approval_status in (ame_util.notifiedStatus,ame_util.notifiedByRepeatedStatus);
13230             insertIntoTransApprovalHistory
13231               (transactionIdIn         => transactionIdIn
13232               ,applicationIdIn         => ameApplicationId
13233               ,orderNumberIn           => approver.approver_order_number
13234               ,nameIn                  => approver.name
13235               ,appCategoryIn           => approver.approver_category
13236               ,itemClassIn             => approver.item_class
13237               ,itemIdIn                => approver.item_id
13238               ,actionTypeIdIn          => approver.action_type_id
13239               ,authorityIn             => approver.authority
13240               ,statusIn                => approver.approval_status
13241               ,grpOrChainIdIn          => approver.group_or_chain_id
13242               ,occurrenceIn            => approver.occurrence
13243               ,apiInsertionIn          => approver.api_insertion
13244               ,memberOrderNumberIn     => approver.member_order_number
13245               ,notificationIdIn        => notificationIn.notification_id
13246               ,userCommentsIn          => notificationIn.user_comments
13247               ,dateClearedIn           => null
13248               ,historyTypeIn           => 'CLEARFRWGRP');
13249           end if;
13250         end if;
13251       end if;
13252       --+
13253       --+ process reassignStatus
13254       --+
13255       if(approver.approval_status = ame_util2.reassignStatus) then
13256         ame_util.copyApproverRecord2(approverRecord2In => forwardeeIn,
13257                                      approverRecord2Out => forwardee);
13258         -- fetch forwardee details
13259         if(forwardee.orig_system is null or
13260            forwardee.orig_system_id is null or
13261            forwardee.display_name is null) then
13262 
13263           begin
13264            ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn =>forwardee.name,
13265                                                               origSystemOut => forwardee.orig_system,
13266                                                               origSystemIdOut => forwardee.orig_system_id,
13267                                                               displayNameOut => forwardee.display_name);
13268           exception
13269             when others then
13270               l_error_code := sqlcode;
13271               if l_error_code = -20213 then
13272                 errorCode := -20221;
13273                 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
13274                                                   messageNameIn => 'AME_400837_INV_APR_FOUND',
13275                                                   tokenNameOneIn  => 'PROCESS_NAME',
13276                                                   tokenValueOneIn => 'ame_engine.updateApprovalStatus',
13277                                                   tokenNameTwoIn => 'NAME',
13278                                                   tokenValueTwoIn => forwardee.name);
13279               raise_application_error(errorCode,errorMessage);
13280               end if;
13281               raise;
13282           end;
13283         end if;
13284           tempInsertionOrder := ame_engine.getNextInsertionOrder;
13285           tempParameter := approver.name ||
13286                            ame_util.fieldDelimiter ||
13287                            approver.item_class ||
13288                            ame_util.fieldDelimiter ||
13289                            approver.item_id ||
13290                            ame_util.fieldDelimiter ||
13291                            approver.action_type_id ||
13292                            ame_util.fieldDelimiter ||
13293                            approver.group_or_chain_id ||
13294                            ame_util.fieldDelimiter ||
13295                            approver.occurrence;
13296           insert into ame_temp_insertions(
13297               transaction_id,
13298               application_id,
13299               insertion_order,
13300               order_type,
13301               parameter,
13302               description,
13303               name,
13304               item_class,
13305               item_id,
13306               approver_category,
13307               api_insertion,
13308               authority,
13309               effective_date,
13310               reason) values(
13311                 transactionIdIn,
13312                 ameApplicationId,
13313                 tempInsertionOrder,
13314                 ame_util.afterApprover,
13315                 tempParameter,
13316                 ame_util.afterApproverDescription || approver.display_name,
13317                 forwardee.name,
13318                 forwardee.item_class,
13319                 forwardee.item_id,
13320                 forwardee.approver_category,
13321                 decode(forwarderType,
13322                        ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13323                        ame_util.apiInsertion),
13324                 approver.authority,
13325                 sysdate,
13326                 ame_approver_deviation_pkg.reassignStatus );
13327       end if;
13328       --+
13329       /* Process the forwardee, checking for special forwarding cases. */
13330       if(approver.approval_status in (ame_util.forwardStatus,
13331                                         ame_util.approveAndForwardStatus)) then
13332         forwardeeType := null;
13333         if(approverInIsSpecialForwardee or
13334            approver.authority <> ame_util.authorityApprover or
13335            approver.api_insertion = ame_util.apiInsertion) then
13336           forwarderType := ame_util.adHocForwarder;
13337         else
13338           forwarderType := ame_util.chainOfAuthorityForwarder;
13339         end if;
13340         /* Use the reverse keyword to find the match nearest to approver. */
13341         for i in reverse 1 .. approverInIndex loop
13342           if(currentApprovers(i).name = forwardee.name and currentApprovers(i).item_id=approver.item_id) then
13343             forwardeeIndex := i;
13344             if(forwarderType = ame_util.chainOfAuthorityForwarder and
13345                currentApprovers(i).action_type_id = forwardee.action_type_id and
13346                currentApprovers(i).group_or_chain_id = forwardee.group_or_chain_id) then
13347               forwardeeType := ame_util.previousSameChainForwardee;
13348             else
13349               forwardeeType := ame_util.alreadyInListForwardee;
13350             end if;
13351             exit;
13352           end if;
13353         end loop;
13354         if(forwarderType = ame_util.chainOfAuthorityForwarder and
13355            (forwardeeType is null or
13356             forwardeeType = ame_util.alreadyInListForwardee) and
13357            ame_approver_type_pkg.isASubordinate(approverIn => approver,
13358                                                 possibleSubordApproverIn => forwardee)) then
13359           forwardeeType := ame_util.subordSameHierarchyForwardee;
13360         end if;
13361         if(forwardeeType = ame_util.previousSameChainForwardee) then
13362           forwardee.occurrence := currentApprovers(forwardeeIndex).occurrence + 1;
13363         else
13364           forwardee.occurrence := 1;
13365         end if;
13366         if(forwardeeType is null) then /* Handle normal forwarding cases. */
13367           if(approver.orig_system <> forwardee.orig_system) then
13368             forwarderType := ame_util.adHocForwarder;
13369           end if;
13370           tempInsertionOrder := ame_engine.getNextInsertionOrder;
13371           tempParameter := approver.name ||
13372                            ame_util.fieldDelimiter ||
13373                            approver.item_class ||
13374                            ame_util.fieldDelimiter ||
13375                            approver.item_id ||
13376                            ame_util.fieldDelimiter ||
13377                            approver.action_type_id ||
13378                            ame_util.fieldDelimiter ||
13379                            approver.group_or_chain_id ||
13380                            ame_util.fieldDelimiter ||
13381                            approver.occurrence;
13382           insert into ame_temp_insertions(
13383               transaction_id,
13384               application_id,
13385               insertion_order,
13386               order_type,
13387               parameter,
13388               description,
13389               name,
13390               item_class,
13391               item_id,
13392               approver_category,
13393               api_insertion,
13394               authority,
13395               effective_date,
13396               reason) values(
13397                 transactionIdIn,
13398                 ameApplicationId,
13399                 tempInsertionOrder,
13400                 ame_util.afterApprover,
13401                 tempParameter,
13402                 ame_util.afterApproverDescription || approver.display_name,
13403                 forwardee.name,
13404                 forwardee.item_class,
13405                 forwardee.item_id,
13406                 forwardee.approver_category,
13407                 decode(forwarderType,
13408                        ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13409                        ame_util.apiInsertion),
13410                 approver.authority,
13411                 sysdate
13412                 ,ame_approver_deviation_pkg.forwardReason );
13413         else /* Handle special forwarding cases. */
13414           /*
13415             All of the insertees generated within this if statement should have the same
13416             action_type_id and group_or_chain_id as approver.  The insertees' source
13417             should always be ame_util.specialForwardInsertion.  The insertions' order
13418             types should always be ame_util.afterApprover.
13419           */
13420           forwardingBehavior := ame_engine.getForwardingBehavior(forwarderTypeIn => forwarderType,
13421                                                                  forwardeeTypeIn => forwardeeType,
13422                                                                  approvalStatusIn => approver.approval_status);
13423           if(forwardingBehavior in (ame_util.repeatForwarder,
13424                                     ame_util.skipForwarder,
13425                                     ame_util.remand)) then
13426             /*
13427               Locate the start of the chain, so we can calculate each insertee's occurrence
13428               value, for use in the following insertee's insertion parameter.
13429             */
13430             for i in reverse 1 .. (approverInIndex - 1) loop
13431               if(currentApprovers(i).group_or_chain_id <> approver.group_or_chain_id or
13432                  currentApprovers(i).action_type_id <> approver.action_type_id or
13433                  currentApprovers(i).item_id <> approver.item_id or
13434                  currentApprovers(i).item_class <> approver.item_class) then
13435                 firstIndexInChain := i + 1;
13436                 exit;
13437               end if;
13438             end loop;
13439             if(firstIndexInChain is null) then
13440               firstIndexInChain := 1;
13441             end if;
13442           end if;
13443           /* Handle the special forwarding cases. */
13444           if(forwardingBehavior in (ame_util.forwardeeOnly,
13445                                     ame_util.forwarderAndForwardee)) then
13446             /* Insert forwardee as ad-hoc or COA, according to whether approverIn is ad-hoc or COA. */
13447             tempInsertionOrder := ame_engine.getNextInsertionOrder;
13448             tempParameter := approver.name ||
13449                              ame_util.fieldDelimiter ||
13450                              approver.item_class ||
13451                              ame_util.fieldDelimiter ||
13452                              approver.item_id ||
13453                              ame_util.fieldDelimiter ||
13454                              approver.action_type_id ||
13455                              ame_util.fieldDelimiter ||
13456                              approver.group_or_chain_id ||
13457                              ame_util.fieldDelimiter ||
13458                              approver.occurrence;
13459             insert into ame_temp_insertions(
13460               transaction_id,
13461               application_id,
13462               insertion_order,
13463               order_type,
13464               parameter,
13465               description,
13466               name,
13467               item_class,
13468               item_id,
13469               approver_category,
13470               api_insertion,
13471               authority,
13472               special_forwardee,
13473               effective_date,
13474               reason) values(
13475                 transactionIdIn,
13476                 ameApplicationId,
13477                 tempInsertionOrder,
13478                 ame_util.afterApprover,
13479                 tempParameter,
13480                 ame_util.afterApproverDescription || approver.display_name,
13481                 forwardee.name,
13482                 forwardee.item_class,
13483                 forwardee.item_id,
13484                 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13485                 decode(forwarderType,
13486                        ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13487                        ame_util.apiInsertion),
13488                 approver.authority,
13489                 ame_util.booleanTrue,
13490                 sysdate,
13491                 ame_approver_deviation_pkg.forwardReason);
13492             if(forwardingBehavior = ame_util.forwarderAndForwardee) then /* Insert the forwarder. */
13493               tempInsertionOrder := ame_engine.getNextInsertionOrder;
13494               tempParameter := forwardee.name ||
13495                                ame_util.fieldDelimiter ||
13496                                forwardee.item_class ||
13497                                ame_util.fieldDelimiter ||
13498                                forwardee.item_id ||
13499                                ame_util.fieldDelimiter ||
13500                                forwardee.action_type_id ||
13501                                ame_util.fieldDelimiter ||
13502                                forwardee.group_or_chain_id ||
13503                                ame_util.fieldDelimiter ||
13504                                forwardee.occurrence;
13505               insert into ame_temp_insertions(
13506                 transaction_id,
13507                 application_id,
13508                 insertion_order,
13509                 order_type,
13510                 parameter,
13511                 description,
13512                 name,
13513                 item_class,
13514                 item_id,
13515                 approver_category,
13516                 api_insertion,
13517                 authority,
13518                 special_forwardee,
13519                 effective_date,
13520                 reason) values(
13521                   transactionIdIn,
13522                   ameApplicationId,
13523                   tempInsertionOrder,
13524                   ame_util.afterApprover,
13525                   tempParameter,
13526                   ame_util.afterApproverDescription || forwardee.display_name,
13527                   approver.name,
13528                   approver.item_class,
13529                   approver.item_id,
13530                   ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13531                   decode(forwarderType,
13532                          ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13533                          ame_util.apiInsertion),
13534                   approver.authority,
13535                   ame_util.booleanTrue,
13536                   sysdate,
13537                   ame_approver_deviation_pkg.forwardForwardeeReason);
13538             end if;
13539           elsif(forwardingBehavior in (ame_util.repeatForwarder, ame_util.skipForwarder)) then
13540             /*
13541               These cases are for a forwardee who is a subordinate of approverIn (who must be
13542               a COA approver), but who does not already precede approverIn in the list.  In this
13543               case we insert starting at the insertee, and ascending the hierarchy up to but not
13544               including approver.  In the case of ame_util.repeatForwarder, we then add
13545               approverIn and stop.  In the case of ame_util.skipForwarder, we then add
13546               approverIn's superior and stop.  The insertees are all COA approvers.
13547             */
13548             /* Insert the forwardee. */
13549             tempInsertionOrder := ame_engine.getNextInsertionOrder;
13550             tempParameter := approver.name ||
13551                              ame_util.fieldDelimiter ||
13552                              approver.item_class ||
13553                              ame_util.fieldDelimiter ||
13554                              approver.item_id ||
13555                              ame_util.fieldDelimiter ||
13556                              approver.action_type_id ||
13557                              ame_util.fieldDelimiter ||
13558                              approver.group_or_chain_id ||
13559                              ame_util.fieldDelimiter ||
13560                              approver.occurrence;
13561             insert into ame_temp_insertions(
13562               transaction_id,
13563               application_id,
13564               insertion_order,
13565               order_type,
13566               parameter,
13567               description,
13568               name,
13569               item_class,
13570               item_id,
13571               approver_category,
13572               api_insertion,
13573               authority,
13574               special_forwardee,
13575               effective_date,
13576               reason) values(
13577                 transactionIdIn,
13578                 ameApplicationId,
13579                 tempInsertionOrder,
13580                 ame_util.afterApprover,
13581                 tempParameter,
13582                 ame_util.afterApproverDescription || approver.display_name,
13583                 forwardee.name,
13584                 forwardee.item_class,
13585                 forwardee.item_id,
13586                 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13587                 ame_util.apiAuthorityInsertion,
13588                 ame_util.authorityApprover,
13589                 ame_util.booleanTrue,
13590                 sysdate,
13591                 ame_approver_deviation_pkg.forwardReason);
13592             insertedApprover.name := forwardee.name;
13593             insertedApprover.orig_system := forwardee.orig_system;
13594             insertedApprover.orig_system_id := forwardee.orig_system_id;
13595             insertedApprover.item_class := forwardee.item_class;
13596             insertedApprover.item_id := forwardee.item_id;
13597             insertedApprover.action_type_id := forwardee.action_type_id;
13598             insertedApprover.group_or_chain_id :=forwardee.group_or_chain_id;
13599             insertedApprover.occurrence := forwardee.occurrence;
13600             forwarderFound := false;
13601             /* Iterate through the forwardee's chain of authority. */
13602             loop
13603               /* Get the next superior to insert. */
13604               tempReason := ame_approver_deviation_pkg.forwardEngInsReason;
13605               ame_approver_type_pkg.getSuperior(approverIn => insertedApprover,
13606                                                 superiorOut => superiorApprover);
13607               if(superiorApprover.name = approver.name) then
13608                 forwarderFound := true;
13609                 tempReason := ame_approver_deviation_pkg.forwardForwardeeReason;
13610                 if(forwardingBehavior = ame_util.skipForwarder) then
13611                   tempReason := ame_approver_deviation_pkg.forwardEngInsReason;
13612                   --insertedApprover.name := approver.name;
13613                   --insertedApprover.orig_system_id := approver.orig_system_id;
13614                   ame_approver_type_pkg.getSuperior(approverIn => approver,
13615                                                     superiorOut => superiorApprover);
13616                 end if;
13617               end if;
13618               /* Calculate insertedApprover.occurrence. */
13619               insertedApprover.occurrence := 1;
13620               for i in reverse firstIndexInChain .. approverInIndex loop
13621                 if(currentApprovers(i).name = insertedApprover.name) then
13622                   insertedApprover.occurrence := currentApprovers(i).occurrence + 1;
13623                   exit;
13624                 end if;
13625               end loop;
13626               /* Prepare and do the insertion. */
13627               tempInsertionOrder := ame_engine.getNextInsertionOrder;
13628               tempParameter := insertedApprover.name ||
13629                                ame_util.fieldDelimiter ||
13630                                insertedApprover.item_class ||
13631                                ame_util.fieldDelimiter ||
13632                                insertedApprover.item_id ||
13633                                ame_util.fieldDelimiter ||
13634                                insertedApprover.action_type_id ||
13635                                ame_util.fieldDelimiter ||
13636                                insertedApprover.group_or_chain_id ||
13637                                ame_util.fieldDelimiter ||
13638                                insertedApprover.occurrence;
13639               insert into ame_temp_insertions(
13640                 transaction_id,
13641                 application_id,
13642                 insertion_order,
13643                 order_type,
13644                 parameter,
13645                 description,
13646                 name,
13647                 item_class,
13648                 item_id,
13649                 approver_category,
13650                 api_insertion,
13651                 authority,
13652                 special_forwardee,
13653                 effective_date,
13654                 reason) values(
13655                   transactionIdIn,
13656                   ameApplicationId,
13657                   tempInsertionOrder,
13658                   ame_util.afterApprover,
13659                   tempParameter,
13660                   ame_util.afterApproverDescription || insertedApprover.display_name,
13661                   superiorApprover.name,
13662                   approver.item_class,
13663                   approver.item_id,
13664                   ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13665                   ame_util.apiAuthorityInsertion,
13666                   ame_util.authorityApprover,
13667                   ame_util.booleanTrue,
13668                   sysdate,
13669                   tempReason);
13670               if(forwarderFound) then
13671                 exit;
13672               end if;
13673               insertedApprover.name := superiorApprover.name;
13674               insertedApprover.orig_system_id := superiorApprover.orig_system_id;
13675             end loop;
13676           elsif(forwardingBehavior = ame_util.remand) then
13677             /*
13678               Remanding is possible only when forwardeeIn already precedes approverIn in
13679               the list (not necessarily in the same chain), and approverIn is a COA approver.  In
13680               such cases, we insert starting with forwardeeIn and continuing up to and including
13681               approver.  The insertees are always ad-hoc, and pertain to the same item, sublist,
13682               action type, and group or chain as the forwarder.
13683             */
13684             for i in forwardeeIndex .. approverInIndex loop
13685               if(i = forwardeeIndex) then
13686                 prevApproverIndex := approverInIndex;
13687                 prevApproverOccurrence := approver.occurrence;
13688               else
13689                 prevApproverIndex := i - 1;
13690                 prevApproverOccurrence := 1;
13691                 for i in reverse firstIndexInChain .. approverInIndex loop
13692                   if(currentApprovers(i).name = currentApprovers(prevApproverIndex).name) then
13693                     prevApproverOccurrence := currentApprovers(prevApproverIndex).occurrence + 1;
13694                     exit;
13695                   end if;
13696                 end loop;
13697               end if;
13698               tempInsertionOrder := ame_engine.getNextInsertionOrder;
13699               tempParameter := currentApprovers(prevApproverIndex).name ||
13700                                ame_util.fieldDelimiter ||
13701                                approver.item_class ||
13702                                ame_util.fieldDelimiter ||
13703                                approver.item_id ||
13704                                ame_util.fieldDelimiter ||
13705                                approver.action_type_id ||
13706                                ame_util.fieldDelimiter ||
13707                                approver.group_or_chain_id ||
13708                                ame_util.fieldDelimiter ||
13709                                prevApproverOccurrence;
13710               insert into ame_temp_insertions(
13711                 transaction_id,
13712                 application_id,
13713                 insertion_order,
13714                 order_type,
13715                 parameter,
13716                 description,
13717                 name,
13718                 item_class,
13719                 item_id,
13720                 approver_category,
13721                 api_insertion,
13722                 authority,
13723                 special_forwardee,
13724                 effective_date,
13725                 reason) values(
13726                   transactionIdIn,
13727                   ameApplicationId,
13728                   tempInsertionOrder,
13729                   ame_util.afterApprover,
13730                   tempParameter,
13731                   ame_util.afterApproverDescription || insertedApprover.display_name,
13732                   currentApprovers(i).name,
13733                   approver.item_class,
13734                   approver.item_id,
13735                   ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13736                   ame_util.apiInsertion,
13737                   approver.authority,
13738                   ame_util.booleanTrue,
13739                   sysdate,
13740                   ame_approver_deviation_pkg.forwardRemandReason);
13741               prevApproverIndex := prevApproverIndex + 1;
13742             end loop;
13743           /* else forwardingBehavior = ame_util.ignoreForwarding */
13744         end if;
13745       end if;
13746       /* Cycle the engine to write the forwardees out to the old-approvers table. */
13747       ame_engine.updateTransactionState(isTestTransactionIn => false,
13748                                           isLocalTransactionIn => false,
13749                                           fetchConfigVarsIn => true,
13750                                           fetchOldApproversIn => true,
13751                                           fetchInsertionsIn => true,
13752                                           fetchDeletionsIn => true,
13753                                           fetchAttributeValuesIn => true,
13754                                           fetchInactiveAttValuesIn => false,
13755                                           processProductionActionsIn => false,
13756                                           processProductionRulesIn => false,
13757                                           updateCurrentApproverListIn => true,
13758                                           updateOldApproverListIn => true,
13759                                           processPrioritiesIn => true,
13760                                           prepareItemDataIn => false,
13761                                           prepareRuleIdsIn => false,
13762                                           prepareRuleDescsIn => false,
13763                                           transactionIdIn => transactionIdIn,
13764                                           ameApplicationIdIn => null,
13765                                           fndApplicationIdIn => applicationIdIn,
13766                                           transactionTypeIdIn => transactionTypeIn);
13767       end if;
13768       ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13769                                    transactionIdIn => transactionIdIn,
13770                                    transactionTypeIdIn => transactionTypeIn);
13771       exception
13772         when badForwardeeException then
13773           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13774                                        transactionIdIn => transactionIdIn,
13775                                        transactionTypeIdIn => transactionTypeIn);
13776           errorCode := -20101;
13777           if transactionTypeIn is not null then
13778             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13779                                                 messageNameIn => 'AME_400298_API_FOR_NOT_VALID',
13780                                                 tokenNameOneIn => 'TRANSACTION_ID',
13781                                                 tokenValueOneIn => transactionIdIn,
13782                                                 tokenNameTwoIn => 'TRANSACTION_TYPE',
13783                                                 tokenValueTwoIn => transactionTypeIn);
13784           else
13785             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13786                                                 messageNameIn => 'AME_400066_API_FOR_NOT_VALID2',
13787                                                 tokenNameOneIn => 'TRANSACTION_ID',
13788                                                 tokenValueOneIn => transactionIdIn);
13789           end if;
13790           ame_util.runtimeException(packageNameIn => 'ame_engine',
13791                                     routineNameIn => 'updateApprovalStatus',
13792                                     exceptionNumberIn => errorCode,
13793                                     exceptionStringIn => errorMessage);
13794           raise_application_error(errorCode,
13795                                   errorMessage);
13796         when apiInsertionException then
13797           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13798                                        transactionIdIn => transactionIdIn,
13799                                        transactionTypeIdIn => transactionTypeIn);
13800           errorCode := -20308;
13801           errorMessage :=
13802           ame_util.getMessage(applicationShortNameIn => 'PER',
13803                               messageNameIn => 'AME_400246_API_FWD_SAME_VALUE');
13804           ame_util.runtimeException(packageNameIn => 'ame_engine',
13805                                     routineNameIn => 'updateApprovalStatus',
13806                                     exceptionNumberIn => errorCode,
13807                                     exceptionStringIn => errorMessage);
13808           raise_application_error(errorCode,
13809                                   errorMessage);
13810         when badStatusException then
13811           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13812                                        transactionIdIn => transactionIdIn,
13813                                        transactionTypeIdIn => transactionTypeIn);
13814           errorCode := -20001;
13815           if transactionTypeIn is not null then
13816             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13817                                                 messageNameIn => 'AME_400247_API_APPR_STAT_VALUE',
13818                                                 tokenNameOneIn => 'TRANSACTION_ID',
13819                                                 tokenValueOneIn => transactionIdIn,
13820                                                 tokenNameTwoIn => 'TRANSACTION_TYPE',
13821                                                 tokenValueTwoIn => transactionTypeIn,
13822                                                 tokenNameThreeIn => 'APPROVED_STATUS',
13823                                                 tokenValueThreeIn => ame_util.approvedStatus,
13824                                                 tokenNameFourIn => 'APPROVED_FORWARD_STATUS',
13825                                                 tokenValueFourIn => ame_util.approveAndForwardStatus,
13826                                                 tokenNameFiveIn => 'EXCEPTION_STATUS',
13827                                                 tokenValueFiveIn => ame_util.exceptionStatus ,
13828                                                 tokenNameSixIn => 'FORWARD_STATUS',
13829                                                 tokenValueSixIn => ame_util.forwardStatus,
13830                                                 tokenNameSevenIn => 'REJECT_STATUS',
13831                                                 tokenValueSevenIn => ame_util.rejectStatus);
13832           else
13833             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13834                                                 messageNameIn => 'AME_400064_API_APPR_STAT_VAL2',
13835                                                 tokenNameOneIn => 'TRANSACTION_ID',
13836                                                 tokenValueOneIn => transactionIdIn,
13837                                                 tokenNameTwoIn => 'APPROVED_STATUS',
13838                                                 tokenValueTwoIn => ame_util.approvedStatus,
13839                                                 tokenNameThreeIn => 'APPROVED_FORWARD_STATUS',
13840                                                 tokenValueThreeIn => ame_util.approveAndForwardStatus,
13841                                                 tokenNameFourIn => 'EXCEPTION_STATUS',
13842                                                 tokenValueFourIn => ame_util.exceptionStatus ,
13843                                                 tokenNameFiveIn => 'FORWARD_STATUS',
13844                                                 tokenValueFiveIn => ame_util.forwardStatus,
13845                                                 tokenNameSixIn => 'REJECT_STATUS',
13846                                                 tokenValueSixIn => ame_util.rejectStatus);
13847           end if;
13848           ame_util.runtimeException(packageNameIn => 'ame_engine',
13849                                     routineNameIn => 'updateApprovalStatus',
13850                                     exceptionNumberIn => errorCode,
13851                                     exceptionStringIn => errorMessage);
13852           raise_application_error(errorCode,
13853                                   errorMessage);
13854         when others then
13855           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13856                                        transactionIdIn => transactionIdIn,
13857                                        transactionTypeIdIn => transactionTypeIn);
13858           ame_util.runtimeException(packageNameIn => 'ame_engine',
13859                                     routineNameIn => 'updateApprovalStatus',
13860                                     exceptionNumberIn => sqlcode,
13861                                     exceptionStringIn => sqlerrm);
13862           raise;
13863     end updateApprovalStatus;
13864   procedure updateInsertions(indexIn in integer) as
13865     tempIndex integer;
13866     approverInsertionOrder integer;
13867     deletionInsertionOrder integer;
13868     begin
13869       if engStInsertionIndexes.exists(indexIn) then
13870         deletionInsertionOrder := engStInsertionIndexes(indexIn);
13871         tempIndex := engStInsertionIndexes.next(indexIn);
13872         while engStInsertionIndexes.exists(tempIndex) loop
13873           approverInsertionOrder := engStInsertionIndexes(tempIndex);
13874           if approverInsertionOrder > deletionInsertionOrder then
13875             update ame_temp_insertions
13876                set parameter = parameter - 1
13877              where insertion_order = approverInsertionOrder
13878                and application_id = engAmeApplicationId
13879                and transaction_id = engTransactionId
13880                and order_type = ame_util.absoluteOrder;
13881           end if;
13882           tempIndex := engStInsertionIndexes.next(tempIndex);
13883         end loop;
13884       end if;
13885     end updateInsertions;
13886   procedure setDeviationReasonDate(reasonIn in varchar2,dateIn in date) as
13887   begin
13888     engTempReason := reasonIn;
13889     engTempDate := dateIn;
13890   end setDeviationReasonDate;
13891 end ame_engine;